summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/AttributeList.cpp19
-rw-r--r--clang/lib/Sema/CodeCompleteConsumer.cpp17
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp81
-rw-r--r--clang/lib/Sema/SemaDeclObjC.cpp11
-rw-r--r--clang/lib/Sema/SemaExpr.cpp60
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp6
-rw-r--r--clang/lib/Sema/SemaObjCProperty.cpp12
-rw-r--r--clang/lib/Sema/SemaOverload.cpp26
8 files changed, 161 insertions, 71 deletions
diff --git a/clang/lib/Sema/AttributeList.cpp b/clang/lib/Sema/AttributeList.cpp
index a715989c685..ae5ea673eba 100644
--- a/clang/lib/Sema/AttributeList.cpp
+++ b/clang/lib/Sema/AttributeList.cpp
@@ -36,6 +36,24 @@ AttributeList::AttributeList(llvm::BumpPtrAllocator &Alloc,
}
}
+AttributeList::AttributeList(llvm::BumpPtrAllocator &Alloc,
+ IdentifierInfo *AttrName, SourceLocation AttrLoc,
+ IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
+ IdentifierInfo *ParmName, SourceLocation ParmLoc,
+ const AvailabilityChange &Introduced,
+ const AvailabilityChange &Deprecated,
+ const AvailabilityChange &Obsoleted,
+ bool declspec, bool cxx0x)
+ : AttrName(AttrName), AttrLoc(AttrLoc), ScopeName(ScopeName),
+ ScopeLoc(ScopeLoc), ParmName(ParmName), ParmLoc(ParmLoc),
+ Args(0), NumArgs(0), Next(0),
+ DeclspecAttribute(declspec), CXX0XAttribute(cxx0x),
+ AvailabilityIntroduced(Introduced),
+ AvailabilityDeprecated(Deprecated),
+ AvailabilityObsoleted(Obsoleted),
+ Invalid(false) {
+}
+
AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
llvm::StringRef AttrName = Name->getName();
@@ -83,6 +101,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
.Case("may_alias", AT_may_alias)
.Case("base_check", AT_base_check)
.Case("deprecated", AT_deprecated)
+ .Case("availability", AT_availability)
.Case("visibility", AT_visibility)
.Case("destructor", AT_destructor)
.Case("format_arg", AT_format_arg)
diff --git a/clang/lib/Sema/CodeCompleteConsumer.cpp b/clang/lib/Sema/CodeCompleteConsumer.cpp
index b7037ce83e7..2334ab5128a 100644
--- a/clang/lib/Sema/CodeCompleteConsumer.cpp
+++ b/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -375,12 +375,21 @@ void CodeCompletionResult::computeCursorKindAndAvailability() {
switch (Kind) {
case RK_Declaration:
// Set the availability based on attributes.
- Availability = CXAvailability_Available;
- if (Declaration->getAttr<UnavailableAttr>())
- Availability = CXAvailability_NotAvailable;
- else if (Declaration->getAttr<DeprecatedAttr>())
+ switch (Declaration->getAvailability()) {
+ case AR_Available:
+ case AR_NotYetIntroduced:
+ Availability = CXAvailability_Available;
+ break;
+
+ case AR_Deprecated:
Availability = CXAvailability_Deprecated;
+ break;
+ case AR_Unavailable:
+ Availability = CXAvailability_NotAvailable;
+ break;
+ }
+
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration))
if (Function->isDeleted())
Availability = CXAvailability_NotAvailable;
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 3c1127784d4..3f33f144e48 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -1074,6 +1074,57 @@ static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context, Str));
}
+static void HandleAvailabilityAttr(Decl *d, const AttributeList &Attr,
+ Sema &S) {
+ IdentifierInfo *Platform = Attr.getParameterName();
+ SourceLocation PlatformLoc = Attr.getParameterLoc();
+
+ llvm::StringRef PlatformName
+ = AvailabilityAttr::getPrettyPlatformName(Platform->getName());
+ if (PlatformName.empty()) {
+ S.Diag(PlatformLoc, diag::warn_availability_unknown_platform)
+ << Platform;
+
+ PlatformName = Platform->getName();
+ }
+
+ AvailabilityChange Introduced = Attr.getAvailabilityIntroduced();
+ AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated();
+ AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted();
+
+ // Ensure that Introduced < Deprecated < Obsoleted (although not all
+ // of these steps are needed).
+ if (Introduced.isValid() && Deprecated.isValid() &&
+ !(Introduced.Version < Deprecated.Version)) {
+ S.Diag(Introduced.KeywordLoc, diag::warn_availability_version_ordering)
+ << 1 << PlatformName << Deprecated.Version.getAsString()
+ << 0 << Introduced.Version.getAsString();
+ return;
+ }
+
+ if (Introduced.isValid() && Obsoleted.isValid() &&
+ !(Introduced.Version < Obsoleted.Version)) {
+ S.Diag(Introduced.KeywordLoc, diag::warn_availability_version_ordering)
+ << 2 << PlatformName << Obsoleted.Version.getAsString()
+ << 0 << Introduced.Version.getAsString();
+ return;
+ }
+
+ if (Deprecated.isValid() && Obsoleted.isValid() &&
+ !(Deprecated.Version < Obsoleted.Version)) {
+ S.Diag(Deprecated.KeywordLoc, diag::warn_availability_version_ordering)
+ << 2 << PlatformName << Obsoleted.Version.getAsString()
+ << 1 << Deprecated.Version.getAsString();
+ return;
+ }
+
+ d->addAttr(::new (S.Context) AvailabilityAttr(Attr.getLoc(), S.Context,
+ Platform,
+ Introduced.Version,
+ Deprecated.Version,
+ Obsoleted.Version));
+}
+
static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
if (Attr.getNumArgs() != 1) {
@@ -1380,27 +1431,18 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// weak_import only applies to variable & function declarations.
bool isDef = false;
- if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
- isDef = (!VD->hasExternalStorage() || VD->getInit());
- } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- isDef = FD->hasBody();
- } else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D)) {
- // We ignore weak import on properties and methods
- return;
- } else if (!(S.LangOpts.ObjCNonFragileABI && isa<ObjCInterfaceDecl>(D))) {
- // Don't issue the warning for darwin as target; yet, ignore the attribute.
- if (S.Context.Target.getTriple().getOS() != llvm::Triple::Darwin ||
- !isa<ObjCInterfaceDecl>(D))
+ if (!D->canBeWeakImported(isDef)) {
+ if (isDef)
+ S.Diag(Attr.getLoc(),
+ diag::warn_attribute_weak_import_invalid_on_definition)
+ << "weak_import" << 2 /*variable and function*/;
+ else if (S.Context.Target.getTriple().getOS() != llvm::Triple::Darwin ||
+ (!isa<ObjCInterfaceDecl>(D) &&
+ !isa<ObjCPropertyDecl>(D) &&
+ !isa<ObjCMethodDecl>(D)))
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedVariableOrFunction;
- return;
- }
- // Merge should handle any subsequent violations.
- if (isDef) {
- S.Diag(Attr.getLoc(),
- diag::warn_attribute_weak_import_invalid_on_definition)
- << "weak_import" << 2 /*variable and function*/;
return;
}
@@ -2745,6 +2787,7 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D,
case AttributeList::AT_analyzer_noreturn:
HandleAnalyzerNoReturnAttr (D, Attr, S); break;
case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break;
+ case AttributeList::AT_availability:HandleAvailabilityAttr(D, Attr, S); break;
case AttributeList::AT_carries_dependency:
HandleDependencyAttr (D, Attr, S); break;
case AttributeList::AT_common: HandleCommonAttr (D, Attr, S); break;
@@ -3058,7 +3101,7 @@ void Sema::DelayedDiagnostics::popParsingDecl(Sema &S, ParsingDeclState state,
static bool isDeclDeprecated(Decl *D) {
do {
- if (D->hasAttr<DeprecatedAttr>())
+ if (D->isDeprecated())
return true;
} while ((D = cast_or_null<Decl>(D->getDeclContext())));
return false;
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index 8717385b516..101ade72e3c 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -28,7 +28,7 @@ static void DiagnoseObjCImplementedDeprecations(Sema &S,
NamedDecl *ND,
SourceLocation ImplLoc,
int select) {
- if (ND && ND->getAttr<DeprecatedAttr>()) {
+ if (ND && ND->isDeprecated()) {
S.Diag(ImplLoc, diag::warn_deprecated_def) << select;
if (select == 0)
S.Diag(ND->getLocation(), diag::note_method_declared_at);
@@ -1369,15 +1369,14 @@ void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl,
PrevObjCMethod->setDefined(impl);
// If a method is deprecated, push it in the global pool.
// This is used for better diagnostics.
- if (Method->getAttr<DeprecatedAttr>()) {
- if (!PrevObjCMethod->getAttr<DeprecatedAttr>())
+ if (Method->isDeprecated()) {
+ if (!PrevObjCMethod->isDeprecated())
List->Method = Method;
}
// If new method is unavailable, push it into global pool
// unless previous one is deprecated.
- if (Method->getAttr<UnavailableAttr>()) {
- if (!PrevObjCMethod->getAttr<UnavailableAttr>() &&
- !PrevObjCMethod->getAttr<DeprecatedAttr>())
+ if (Method->isUnavailable()) {
+ if (PrevObjCMethod->getAvailability() < AR_Deprecated)
List->Method = Method;
}
return;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index b8f0c729d17..c2f3a434b81 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -68,7 +68,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
Diag(Suppressed[I].first, Suppressed[I].second);
// Clear out the list of suppressed diagnostics, so that we don't emit
- // them again for this specialization. However, we don't remove this
+ // them again for this specialization. However, we don't obsolete this
// entry from the table, because we want to avoid ever emitting these
// diagnostics again.
Suppressed.clear();
@@ -82,13 +82,28 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
return true;
}
- // See if the decl is deprecated.
- if (const DeprecatedAttr *DA = D->getAttr<DeprecatedAttr>())
- EmitDeprecationWarning(D, DA->getMessage(), Loc, UnknownObjCClass);
+ // See if this is a deleted function.
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->isDeleted()) {
+ Diag(Loc, diag::err_deleted_function_use);
+ Diag(D->getLocation(), diag::note_unavailable_here) << true;
+ return true;
+ }
+ }
+
+ // See if this declaration is unavailable or deprecated.
+ std::string Message;
+ switch (D->getAvailability(&Message)) {
+ case AR_Available:
+ case AR_NotYetIntroduced:
+ break;
- // See if the decl is unavailable
- if (const UnavailableAttr *UA = D->getAttr<UnavailableAttr>()) {
- if (UA->getMessage().empty()) {
+ case AR_Deprecated:
+ EmitDeprecationWarning(D, Message, Loc, UnknownObjCClass);
+ break;
+
+ case AR_Unavailable:
+ if (Message.empty()) {
if (!UnknownObjCClass)
Diag(Loc, diag::err_unavailable) << D->getDeclName();
else
@@ -97,17 +112,9 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
}
else
Diag(Loc, diag::err_unavailable_message)
- << D->getDeclName() << UA->getMessage();
- Diag(D->getLocation(), diag::note_unavailable_here) << 0;
- }
-
- // See if this is a deleted function.
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- if (FD->isDeleted()) {
- Diag(Loc, diag::err_deleted_function_use);
- Diag(D->getLocation(), diag::note_unavailable_here) << true;
- return true;
- }
+ << D->getDeclName() << Message;
+ Diag(D->getLocation(), diag::note_unavailable_here) << 0;
+ break;
}
// Warn if this is used but marked unused.
@@ -117,6 +124,23 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
return false;
}
+/// \brief Retrieve the message suffix that should be added to a
+/// diagnostic complaining about the given function being deleted or
+/// unavailable.
+std::string Sema::getDeletedOrUnavailableSuffix(const FunctionDecl *FD) {
+ // FIXME: C++0x implicitly-deleted special member functions could be
+ // detected here so that we could improve diagnostics to say, e.g.,
+ // "base class 'A' had a deleted copy constructor".
+ if (FD->isDeleted())
+ return std::string();
+
+ std::string Message;
+ if (FD->getAvailability(&Message))
+ return ": " + Message;
+
+ return std::string();
+}
+
/// DiagnoseSentinelCalls - This routine checks on method dispatch calls
/// (and other functions in future), which have been declared with sentinel
/// attribute. It warns if call does not have the sentinel argument.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 8fa2a5d2e86..0a8bd8fb526 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -1388,16 +1388,16 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
Candidates.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs);
return true;
- case OR_Deleted:
+ case OR_Deleted: {
Diag(StartLoc, diag::err_ovl_deleted_call)
<< Best->Function->isDeleted()
<< Name
- << Best->Function->getMessageUnavailableAttr(
- !Best->Function->isDeleted())
+ << getDeletedOrUnavailableSuffix(Best->Function)
<< Range;
Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
return true;
}
+ }
assert(false && "Unreachable, bad result from BestViableFunction");
return true;
}
diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp
index 91de095ac7e..f607d658951 100644
--- a/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/clang/lib/Sema/SemaObjCProperty.cpp
@@ -1138,10 +1138,14 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod,
ObjCPropertyDecl *Property) {
// Should we just clone all attributes over?
- if (DeprecatedAttr *A = Property->getAttr<DeprecatedAttr>())
- PropertyMethod->addAttr(A->clone(S.Context));
- if (UnavailableAttr *A = Property->getAttr<UnavailableAttr>())
- PropertyMethod->addAttr(A->clone(S.Context));
+ for (Decl::attr_iterator A = Property->attr_begin(),
+ AEnd = Property->attr_end();
+ A != AEnd; ++A) {
+ if (isa<DeprecatedAttr>(*A) ||
+ isa<UnavailableAttr>(*A) ||
+ isa<AvailabilityAttr>(*A))
+ PropertyMethod->addAttr((*A)->clone(S.Context));
+ }
}
/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 110f8cdc1cb..7a4e68d3cbb 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6282,8 +6282,7 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
// Best is the best viable function.
if (Best->Function &&
- (Best->Function->isDeleted() ||
- Best->Function->getAttr<UnavailableAttr>()))
+ (Best->Function->isDeleted() || Best->Function->isUnavailable()))
return OR_Deleted;
return OR_Success;
@@ -6735,7 +6734,7 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
FunctionDecl *Fn = Cand->Function;
// Note deleted candidates, but only if they're viable.
- if (Cand->Viable && (Fn->isDeleted() || Fn->hasAttr<UnavailableAttr>())) {
+ if (Cand->Viable && (Fn->isDeleted() || Fn->isUnavailable())) {
std::string FnDesc;
OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc);
@@ -7744,8 +7743,7 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call)
<< Best->Function->isDeleted()
<< ULE->getName()
- << Best->Function->getMessageUnavailableAttr(
- !Best->Function->isDeleted())
+ << getDeletedOrUnavailableSuffix(Best->Function)
<< Fn->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
}
@@ -7928,8 +7926,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
Diag(OpLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted()
<< UnaryOperator::getOpcodeStr(Opc)
- << Best->Function->getMessageUnavailableAttr(
- !Best->Function->isDeleted())
+ << getDeletedOrUnavailableSuffix(Best->Function)
<< Input->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
return ExprError();
@@ -8199,8 +8196,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
Diag(OpLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted()
<< BinaryOperator::getOpcodeStr(Opc)
- << Best->Function->getMessageUnavailableAttr(
- !Best->Function->isDeleted())
+ << getDeletedOrUnavailableSuffix(Best->Function)
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2);
return ExprError();
@@ -8349,8 +8345,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
case OR_Deleted:
Diag(LLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted() << "[]"
- << Best->Function->getMessageUnavailableAttr(
- !Best->Function->isDeleted())
+ << getDeletedOrUnavailableSuffix(Best->Function)
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2,
"[]", LLoc);
@@ -8468,8 +8463,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call)
<< Best->Function->isDeleted()
<< DeclName
- << Best->Function->getMessageUnavailableAttr(
- !Best->Function->isDeleted())
+ << getDeletedOrUnavailableSuffix(Best->Function)
<< MemExprE->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
// FIXME: Leaking incoming expressions!
@@ -8643,8 +8637,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
diag::err_ovl_deleted_object_call)
<< Best->Function->isDeleted()
<< Object->getType()
- << Best->Function->getMessageUnavailableAttr(
- !Best->Function->isDeleted())
+ << getDeletedOrUnavailableSuffix(Best->Function)
<< Object->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
break;
@@ -8852,8 +8845,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
Diag(OpLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted()
<< "->"
- << Best->Function->getMessageUnavailableAttr(
- !Best->Function->isDeleted())
+ << getDeletedOrUnavailableSuffix(Best->Function)
<< Base->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &Base, 1);
return ExprError();
OpenPOWER on IntegriCloud