diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp | 1240 |
1 files changed, 854 insertions, 386 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp index e326a20..982e7a5 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp @@ -16,14 +16,17 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" +#include "clang/AST/Mangle.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" #include "llvm/ADT/StringExtras.h" using namespace clang; using namespace sema; @@ -37,6 +40,7 @@ enum AttributeDeclKind { ExpectedFunctionOrMethod, ExpectedParameter, ExpectedFunctionMethodOrBlock, + ExpectedFunctionMethodOrClass, ExpectedFunctionMethodOrParameter, ExpectedClass, ExpectedVariable, @@ -44,7 +48,11 @@ enum AttributeDeclKind { ExpectedVariableFunctionOrLabel, ExpectedFieldOrGlobalVar, ExpectedStruct, - ExpectedTLSVar + ExpectedVariableFunctionOrTag, + ExpectedTLSVar, + ExpectedVariableOrField, + ExpectedVariableFieldOrTag, + ExpectedTypeOrNamespace }; //===----------------------------------------------------------------------===// @@ -293,12 +301,12 @@ static bool isIntOrBool(Expr *Exp) { static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) { DeclContextLookupConstResult Res1 = RT->getDecl()->lookup( S.Context.DeclarationNames.getCXXOperatorName(OO_Star)); - if (Res1.first == Res1.second) + if (Res1.empty()) return false; DeclContextLookupConstResult Res2 = RT->getDecl()->lookup( S.Context.DeclarationNames.getCXXOperatorName(OO_Arrow)); - if (Res2.first == Res2.second) + if (Res2.empty()) return false; return true; @@ -503,18 +511,22 @@ static void handleGuardedVarAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkGuardedVarAttrCommon(S, D, Attr)) return; - D->addAttr(::new (S.Context) GuardedVarAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + GuardedVarAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handlePtGuardedVarAttr(Sema &S, Decl *D, - const AttributeList &Attr) { + const AttributeList &Attr) { if (!checkGuardedVarAttrCommon(S, D, Attr)) return; if (!threadSafetyCheckIsPointer(S, D, Attr)) return; - D->addAttr(::new (S.Context) PtGuardedVarAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + PtGuardedVarAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static bool checkGuardedByAttrCommon(Sema &S, Decl *D, @@ -594,11 +606,13 @@ static void handleScopedLockableAttr(Sema &S, Decl *D, if (!checkLockableAttrCommon(S, D, Attr)) return; - D->addAttr(::new (S.Context) ScopedLockableAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ScopedLockableAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } -static void handleNoThreadSafetyAttr(Sema &S, Decl *D, - const AttributeList &Attr) { +static void handleNoThreadSafetyAnalysis(Sema &S, Decl *D, + const AttributeList &Attr) { assert(!Attr.isInvalid()); if (!checkAttributeNumArgs(S, Attr, 0)) @@ -614,7 +628,7 @@ static void handleNoThreadSafetyAttr(Sema &S, Decl *D, S.Context)); } -static void handleNoAddressSafetyAttr(Sema &S, Decl *D, +static void handleNoSanitizeAddressAttr(Sema &S, Decl *D, const AttributeList &Attr) { assert(!Attr.isInvalid()); @@ -622,13 +636,48 @@ static void handleNoAddressSafetyAttr(Sema &S, Decl *D, return; if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + D->addAttr(::new (S.Context) + NoSanitizeAddressAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); +} + +static void handleNoSanitizeMemory(Sema &S, Decl *D, + const AttributeList &Attr) { + assert(!Attr.isInvalid()); + + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + D->addAttr(::new (S.Context) NoSanitizeMemoryAttr(Attr.getRange(), + S.Context)); +} + +static void handleNoSanitizeThread(Sema &S, Decl *D, + const AttributeList &Attr) { + assert(!Attr.isInvalid()); + + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunctionOrMethod; return; } - D->addAttr(::new (S.Context) NoAddressSafetyAnalysisAttr(Attr.getRange(), - S.Context)); + D->addAttr(::new (S.Context) NoSanitizeThreadAttr(Attr.getRange(), + S.Context)); } static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, @@ -673,8 +722,10 @@ static void handleAcquiredAfterAttr(Sema &S, Decl *D, return; Expr **StartArg = &Args[0]; - D->addAttr(::new (S.Context) AcquiredAfterAttr(Attr.getRange(), S.Context, - StartArg, Args.size())); + D->addAttr(::new (S.Context) + AcquiredAfterAttr(Attr.getRange(), S.Context, + StartArg, Args.size(), + Attr.getAttributeSpellingListIndex())); } static void handleAcquiredBeforeAttr(Sema &S, Decl *D, @@ -684,8 +735,10 @@ static void handleAcquiredBeforeAttr(Sema &S, Decl *D, return; Expr **StartArg = &Args[0]; - D->addAttr(::new (S.Context) AcquiredBeforeAttr(Attr.getRange(), S.Context, - StartArg, Args.size())); + D->addAttr(::new (S.Context) + AcquiredBeforeAttr(Attr.getRange(), S.Context, + StartArg, Args.size(), + Attr.getAttributeSpellingListIndex())); } static bool checkLockFunAttrCommon(Sema &S, Decl *D, @@ -716,9 +769,9 @@ static void handleSharedLockFunctionAttr(Sema &S, Decl *D, unsigned Size = Args.size(); Expr **StartArg = Size == 0 ? 0 : &Args[0]; - D->addAttr(::new (S.Context) SharedLockFunctionAttr(Attr.getRange(), - S.Context, - StartArg, Size)); + D->addAttr(::new (S.Context) + SharedLockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size, + Attr.getAttributeSpellingListIndex())); } static void handleExclusiveLockFunctionAttr(Sema &S, Decl *D, @@ -729,9 +782,10 @@ static void handleExclusiveLockFunctionAttr(Sema &S, Decl *D, unsigned Size = Args.size(); Expr **StartArg = Size == 0 ? 0 : &Args[0]; - D->addAttr(::new (S.Context) ExclusiveLockFunctionAttr(Attr.getRange(), - S.Context, - StartArg, Size)); + D->addAttr(::new (S.Context) + ExclusiveLockFunctionAttr(Attr.getRange(), S.Context, + StartArg, Size, + Attr.getAttributeSpellingListIndex())); } static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, @@ -768,10 +822,10 @@ static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D, unsigned Size = Args.size(); Expr **StartArg = Size == 0 ? 0 : &Args[0]; - D->addAttr(::new (S.Context) SharedTrylockFunctionAttr(Attr.getRange(), - S.Context, - Attr.getArg(0), - StartArg, Size)); + D->addAttr(::new (S.Context) + SharedTrylockFunctionAttr(Attr.getRange(), S.Context, + Attr.getArg(0), StartArg, Size, + Attr.getAttributeSpellingListIndex())); } static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D, @@ -782,10 +836,10 @@ static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D, unsigned Size = Args.size(); Expr **StartArg = Size == 0 ? 0 : &Args[0]; - D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(Attr.getRange(), - S.Context, - Attr.getArg(0), - StartArg, Size)); + D->addAttr(::new (S.Context) + ExclusiveTrylockFunctionAttr(Attr.getRange(), S.Context, + Attr.getArg(0), StartArg, Size, + Attr.getAttributeSpellingListIndex())); } static bool checkLocksRequiredCommon(Sema &S, Decl *D, @@ -817,10 +871,10 @@ static void handleExclusiveLocksRequiredAttr(Sema &S, Decl *D, return; Expr **StartArg = &Args[0]; - D->addAttr(::new (S.Context) ExclusiveLocksRequiredAttr(Attr.getRange(), - S.Context, - StartArg, - Args.size())); + D->addAttr(::new (S.Context) + ExclusiveLocksRequiredAttr(Attr.getRange(), S.Context, + StartArg, Args.size(), + Attr.getAttributeSpellingListIndex())); } static void handleSharedLocksRequiredAttr(Sema &S, Decl *D, @@ -830,10 +884,10 @@ static void handleSharedLocksRequiredAttr(Sema &S, Decl *D, return; Expr **StartArg = &Args[0]; - D->addAttr(::new (S.Context) SharedLocksRequiredAttr(Attr.getRange(), - S.Context, - StartArg, - Args.size())); + D->addAttr(::new (S.Context) + SharedLocksRequiredAttr(Attr.getRange(), S.Context, + StartArg, Args.size(), + Attr.getAttributeSpellingListIndex())); } static void handleUnlockFunAttr(Sema &S, Decl *D, @@ -854,8 +908,9 @@ static void handleUnlockFunAttr(Sema &S, Decl *D, unsigned Size = Args.size(); Expr **StartArg = Size == 0 ? 0 : &Args[0]; - D->addAttr(::new (S.Context) UnlockFunctionAttr(Attr.getRange(), S.Context, - StartArg, Size)); + D->addAttr(::new (S.Context) + UnlockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size, + Attr.getAttributeSpellingListIndex())); } static void handleLockReturnedAttr(Sema &S, Decl *D, @@ -878,8 +933,9 @@ static void handleLockReturnedAttr(Sema &S, Decl *D, if (Size == 0) return; - D->addAttr(::new (S.Context) LockReturnedAttr(Attr.getRange(), S.Context, - Args[0])); + D->addAttr(::new (S.Context) + LockReturnedAttr(Attr.getRange(), S.Context, Args[0], + Attr.getAttributeSpellingListIndex())); } static void handleLocksExcludedAttr(Sema &S, Decl *D, @@ -903,54 +959,24 @@ static void handleLocksExcludedAttr(Sema &S, Decl *D, return; Expr **StartArg = &Args[0]; - D->addAttr(::new (S.Context) LocksExcludedAttr(Attr.getRange(), S.Context, - StartArg, Size)); + D->addAttr(::new (S.Context) + LocksExcludedAttr(Attr.getRange(), S.Context, StartArg, Size, + Attr.getAttributeSpellingListIndex())); } static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D, const AttributeList &Attr) { - TypedefNameDecl *tDecl = dyn_cast<TypedefNameDecl>(D); - if (tDecl == 0) { + TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D); + if (TD == 0) { + // __attribute__((ext_vector_type(N))) can only be applied to typedefs + // and type-ids. S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef); return; } - QualType curType = tDecl->getUnderlyingType(); - - Expr *sizeExpr; - - // Special case where the argument is a template id. - if (Attr.getParameterName()) { - CXXScopeSpec SS; - SourceLocation TemplateKWLoc; - UnqualifiedId id; - id.setIdentifier(Attr.getParameterName(), Attr.getLoc()); - - ExprResult Size = S.ActOnIdExpression(scope, SS, TemplateKWLoc, id, - false, false); - if (Size.isInvalid()) - return; - - sizeExpr = Size.get(); - } else { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 1)) - return; - - sizeExpr = Attr.getArg(0); - } - - // Instantiate/Install the vector type, and let Sema build the type for us. - // This will run the reguired checks. - QualType T = S.BuildExtVectorType(curType, sizeExpr, Attr.getLoc()); - if (!T.isNull()) { - // FIXME: preserve the old source info. - tDecl->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(T)); - - // Remember this typedef decl, we will need it later for diagnostics. - S.ExtVectorDecls.push_back(tDecl); - } + // Remember this typedef decl, we will need it later for diagnostics. + S.ExtVectorDecls.push_back(TD); } static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -969,14 +995,18 @@ static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type) << Attr.getName() << FD->getType(); else - FD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context)); + FD->addAttr(::new (S.Context) + PackedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } static void handleMsStructAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) - RD->addAttr(::new (S.Context) MsStructAttr(Attr.getRange(), S.Context)); + RD->addAttr(::new (S.Context) + MsStructAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } @@ -989,7 +1019,9 @@ static void handleIBAction(Sema &S, Decl *D, const AttributeList &Attr) { // The IBAction attributes only apply to instance methods. if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) if (MD->isInstanceMethod()) { - D->addAttr(::new (S.Context) IBActionAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + IBActionAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; } @@ -1030,7 +1062,9 @@ static void handleIBOutlet(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkIBOutletCommon(S, D, Attr)) return; - D->addAttr(::new (S.Context) IBOutletAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + IBOutletAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleIBOutletCollection(Sema &S, Decl *D, @@ -1064,8 +1098,10 @@ static void handleIBOutletCollection(Sema &S, Decl *D, S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II; return; } - D->addAttr(::new (S.Context) IBOutletCollectionAttr(Attr.getRange(),S.Context, - QT, Attr.getParameterLoc())); + D->addAttr(::new (S.Context) + IBOutletCollectionAttr(Attr.getRange(),S.Context, + QT, Attr.getParameterLoc(), + Attr.getAttributeSpellingListIndex())); } static void possibleTransparentUnionPointerType(QualType &T) { @@ -1096,7 +1132,11 @@ static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { // In C++ the implicit 'this' function parameter also counts, and they are // counted from one. bool HasImplicitThisParam = isInstanceMethod(D); - unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; + unsigned NumArgs; + if (hasFunctionProto(D)) + NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; + else + NumArgs = 0; SmallVector<unsigned, 8> SizeArgs; @@ -1148,8 +1188,10 @@ static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { << "alloc_size" << 0 /*function*/<< 1 /*pointer*/ << D->getSourceRange(); } - D->addAttr(::new (S.Context) AllocSizeAttr(Attr.getRange(), S.Context, - SizeArgs.data(), SizeArgs.size())); + D->addAttr(::new (S.Context) + AllocSizeAttr(Attr.getRange(), S.Context, + SizeArgs.data(), SizeArgs.size(), + Attr.getAttributeSpellingListIndex())); } static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1164,15 +1206,13 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { // In C++ the implicit 'this' function parameter also counts, and they are // counted from one. bool HasImplicitThisParam = isInstanceMethod(D); - unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; + unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; // The nonnull attribute only applies to pointers. SmallVector<unsigned, 10> NonNullArgs; - for (AttributeList::arg_iterator I=Attr.arg_begin(), - E=Attr.arg_end(); I!=E; ++I) { - - + for (AttributeList::arg_iterator I = Attr.arg_begin(), + E = Attr.arg_end(); I != E; ++I) { // The argument must be an integer constant expression. Expr *Ex = *I; llvm::APSInt ArgNum(32); @@ -1219,11 +1259,11 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { // If no arguments were specified to __attribute__((nonnull)) then all pointer // arguments have a nonnull attribute. if (NonNullArgs.empty()) { - for (unsigned I = 0, E = getFunctionOrMethodNumArgs(D); I != E; ++I) { - QualType T = getFunctionOrMethodArgType(D, I).getNonReferenceType(); + for (unsigned i = 0, e = getFunctionOrMethodNumArgs(D); i != e; ++i) { + QualType T = getFunctionOrMethodArgType(D, i).getNonReferenceType(); possibleTransparentUnionPointerType(T); if (T->isAnyPointerType() || T->isBlockPointerType()) - NonNullArgs.push_back(I); + NonNullArgs.push_back(i); } // No pointer arguments? @@ -1236,11 +1276,12 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { } } - unsigned* start = &NonNullArgs[0]; + unsigned *start = &NonNullArgs[0]; unsigned size = NonNullArgs.size(); llvm::array_pod_sort(start, start + size); - D->addAttr(::new (S.Context) NonNullAttr(Attr.getRange(), S.Context, start, - size)); + D->addAttr(::new (S.Context) + NonNullAttr(Attr.getRange(), S.Context, start, size, + Attr.getAttributeSpellingListIndex())); } static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { @@ -1395,27 +1436,9 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { return; } - D->addAttr(::new (S.Context) OwnershipAttr(AL.getLoc(), S.Context, K, Module, - start, size)); -} - -/// Whether this declaration has internal linkage for the purposes of -/// things that want to complain about things not have internal linkage. -static bool hasEffectivelyInternalLinkage(NamedDecl *D) { - switch (D->getLinkage()) { - case NoLinkage: - case InternalLinkage: - return true; - - // Template instantiations that go from external to unique-external - // shouldn't get diagnosed. - case UniqueExternalLinkage: - return true; - - case ExternalLinkage: - return false; - } - llvm_unreachable("unknown linkage kind!"); + D->addAttr(::new (S.Context) + OwnershipAttr(AL.getLoc(), S.Context, K, Module, start, size, + AL.getAttributeSpellingListIndex())); } static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1468,11 +1491,6 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) { // This looks like a bug in gcc. We reject that for now. We should revisit // it if this behaviour is actually used. - if (!hasEffectivelyInternalLinkage(nd)) { - S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_static); - return; - } - // GCC rejects // static ((alias ("y"), weakref)). // Should we? How to check that weakref is before or after alias? @@ -1493,7 +1511,9 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) { Str->getString())); } - D->addAttr(::new (S.Context) WeakRefAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + WeakRefAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1521,7 +1541,8 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { // FIXME: check if target symbol exists in current file D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, - Str->getString())); + Str->getString(), + Attr.getAttributeSpellingListIndex())); } static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1535,7 +1556,9 @@ static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) MinSizeAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + MinSizeAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1555,7 +1578,8 @@ static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) ColdAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) ColdAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1575,7 +1599,8 @@ static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) HotAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) HotAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1589,7 +1614,9 @@ static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) NakedAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + NakedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleAlwaysInlineAttr(Sema &S, Decl *D, @@ -1606,7 +1633,9 @@ static void handleAlwaysInlineAttr(Sema &S, Decl *D, return; } - D->addAttr(::new (S.Context) AlwaysInlineAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + AlwaysInlineAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleTLSModelAttr(Sema &S, Decl *D, @@ -1641,8 +1670,9 @@ static void handleTLSModelAttr(Sema &S, Decl *D, return; } - D->addAttr(::new (S.Context) TLSModelAttr(Attr.getRange(), S.Context, - Model)); + D->addAttr(::new (S.Context) + TLSModelAttr(Attr.getRange(), S.Context, Model, + Attr.getAttributeSpellingListIndex())); } static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1655,7 +1685,9 @@ static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { QualType RetTy = FD->getResultType(); if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) { - D->addAttr(::new (S.Context) MallocAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + MallocAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; } } @@ -1668,13 +1700,17 @@ static void handleMayAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkAttributeNumArgs(S, Attr, 0)) return; - D->addAttr(::new (S.Context) MayAliasAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + MayAliasAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { assert(!Attr.isInvalid()); if (isa<VarDecl>(D)) - D->addAttr(::new (S.Context) NoCommonAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + NoCommonAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedVariable; @@ -1683,7 +1719,9 @@ static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { assert(!Attr.isInvalid()); if (isa<VarDecl>(D)) - D->addAttr(::new (S.Context) CommonAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + CommonAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedVariable; @@ -1700,7 +1738,9 @@ static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) { return; } - D->addAttr(::new (S.Context) NoReturnAttr(attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + NoReturnAttr(attr.getRange(), S.Context, + attr.getAttributeSpellingListIndex())); } bool Sema::CheckNoReturnAttr(const AttributeList &attr) { @@ -1727,14 +1767,33 @@ static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, if (VD == 0 || (!VD->getType()->isBlockPointerType() && !VD->getType()->isFunctionPointerType())) { S.Diag(Attr.getLoc(), - Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type + Attr.isCXX11Attribute() ? diag::err_attribute_wrong_decl_type : diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunctionMethodOrBlock; return; } } - D->addAttr(::new (S.Context) AnalyzerNoReturnAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + AnalyzerNoReturnAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); +} + +static void handleCXX11NoReturnAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + // C++11 [dcl.attr.noreturn]p1: + // The attribute may be applied to the declarator-id in a function + // declaration. + FunctionDecl *FD = dyn_cast<FunctionDecl>(D); + if (!FD) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + D->addAttr(::new (S.Context) + CXX11NoReturnAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } // PS3 PPU-specific. @@ -1795,16 +1854,30 @@ static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) { count++; } - D->addAttr(::new (S.Context) VecReturnAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + VecReturnAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } -static void handleDependencyAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (!isFunctionOrMethod(D) && !isa<ParmVarDecl>(D)) { +static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D, + const AttributeList &Attr) { + if (isa<ParmVarDecl>(D)) { + // [[carries_dependency]] can only be applied to a parameter if it is a + // parameter of a function declaration or lambda. + if (!(Scope->getFlags() & clang::Scope::FunctionDeclarationScope)) { + S.Diag(Attr.getLoc(), + diag::err_carries_dependency_param_not_function_decl); + return; + } + } else if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunctionMethodOrParameter; return; } - // FIXME: Actually store the attribute on the declaration + + D->addAttr(::new (S.Context) CarriesDependencyAttr( + Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1821,7 +1894,9 @@ static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) UnusedAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + UnusedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleReturnsTwiceAttr(Sema &S, Decl *D, @@ -1838,7 +1913,9 @@ static void handleReturnsTwiceAttr(Sema &S, Decl *D, return; } - D->addAttr(::new (S.Context) ReturnsTwiceAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ReturnsTwiceAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1859,7 +1936,9 @@ static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) UsedAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + UsedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1888,8 +1967,9 @@ static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) ConstructorAttr(Attr.getRange(), S.Context, - priority)); + D->addAttr(::new (S.Context) + ConstructorAttr(Attr.getRange(), S.Context, priority, + Attr.getAttributeSpellingListIndex())); } static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1918,8 +1998,9 @@ static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) DestructorAttr(Attr.getRange(), S.Context, - priority)); + D->addAttr(::new (S.Context) + DestructorAttr(Attr.getRange(), S.Context, priority, + Attr.getAttributeSpellingListIndex())); } template <typename AttrTy> @@ -1943,7 +2024,8 @@ static void handleAttrWithMessage(Sema &S, Decl *D, const AttributeList &Attr, Str = SE->getString(); } - D->addAttr(::new (S.Context) AttrTy(Attr.getRange(), S.Context, Str)); + D->addAttr(::new (S.Context) AttrTy(Attr.getRange(), S.Context, Str, + Attr.getAttributeSpellingListIndex())); } static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D, @@ -1954,8 +2036,9 @@ static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D, return; } - D->addAttr(::new (S.Context) ArcWeakrefUnavailableAttr( - Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ArcWeakrefUnavailableAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleObjCRootClassAttr(Sema &S, Decl *D, @@ -1971,11 +2054,13 @@ static void handleObjCRootClassAttr(Sema &S, Decl *D, return; } - D->addAttr(::new (S.Context) ObjCRootClassAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ObjCRootClassAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } -static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D, - const AttributeList &Attr) { +static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D, + const AttributeList &Attr) { if (!isa<ObjCInterfaceDecl>(D)) { S.Diag(Attr.getLoc(), diag::err_suppress_autosynthesis); return; @@ -1987,8 +2072,9 @@ static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D, return; } - D->addAttr(::new (S.Context) ObjCRequiresPropertyDefsAttr( - Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ObjCRequiresPropertyDefsAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static bool checkAvailabilityAttr(Sema &S, SourceRange Range, @@ -2030,13 +2116,33 @@ static bool checkAvailabilityAttr(Sema &S, SourceRange Range, return false; } -AvailabilityAttr *Sema::mergeAvailabilityAttr(Decl *D, SourceRange Range, +/// \brief Check whether the two versions match. +/// +/// If either version tuple is empty, then they are assumed to match. If +/// \p BeforeIsOkay is true, then \p X can be less than or equal to \p Y. +static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y, + bool BeforeIsOkay) { + if (X.empty() || Y.empty()) + return true; + + if (X == Y) + return true; + + if (BeforeIsOkay && X < Y) + return true; + + return false; +} + +AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, IdentifierInfo *Platform, VersionTuple Introduced, VersionTuple Deprecated, VersionTuple Obsoleted, bool IsUnavailable, - StringRef Message) { + StringRef Message, + bool Override, + unsigned AttrSpellingListIndex) { VersionTuple MergedIntroduced = Introduced; VersionTuple MergedDeprecated = Deprecated; VersionTuple MergedObsoleted = Obsoleted; @@ -2062,18 +2168,47 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(Decl *D, SourceRange Range, VersionTuple OldDeprecated = OldAA->getDeprecated(); VersionTuple OldObsoleted = OldAA->getObsoleted(); bool OldIsUnavailable = OldAA->getUnavailable(); - StringRef OldMessage = OldAA->getMessage(); - - if ((!OldIntroduced.empty() && !Introduced.empty() && - OldIntroduced != Introduced) || - (!OldDeprecated.empty() && !Deprecated.empty() && - OldDeprecated != Deprecated) || - (!OldObsoleted.empty() && !Obsoleted.empty() && - OldObsoleted != Obsoleted) || - (OldIsUnavailable != IsUnavailable) || - (OldMessage != Message)) { - Diag(OldAA->getLocation(), diag::warn_mismatched_availability); - Diag(Range.getBegin(), diag::note_previous_attribute); + + if (!versionsMatch(OldIntroduced, Introduced, Override) || + !versionsMatch(Deprecated, OldDeprecated, Override) || + !versionsMatch(Obsoleted, OldObsoleted, Override) || + !(OldIsUnavailable == IsUnavailable || + (Override && !OldIsUnavailable && IsUnavailable))) { + if (Override) { + int Which = -1; + VersionTuple FirstVersion; + VersionTuple SecondVersion; + if (!versionsMatch(OldIntroduced, Introduced, Override)) { + Which = 0; + FirstVersion = OldIntroduced; + SecondVersion = Introduced; + } else if (!versionsMatch(Deprecated, OldDeprecated, Override)) { + Which = 1; + FirstVersion = Deprecated; + SecondVersion = OldDeprecated; + } else if (!versionsMatch(Obsoleted, OldObsoleted, Override)) { + Which = 2; + FirstVersion = Obsoleted; + SecondVersion = OldObsoleted; + } + + if (Which == -1) { + Diag(OldAA->getLocation(), + diag::warn_mismatched_availability_override_unavail) + << AvailabilityAttr::getPrettyPlatformName(Platform->getName()); + } else { + Diag(OldAA->getLocation(), + diag::warn_mismatched_availability_override) + << Which + << AvailabilityAttr::getPrettyPlatformName(Platform->getName()) + << FirstVersion.getAsString() << SecondVersion.getAsString(); + } + Diag(Range.getBegin(), diag::note_overridden_method); + } else { + Diag(OldAA->getLocation(), diag::warn_mismatched_availability); + Diag(Range.getBegin(), diag::note_previous_attribute); + } + Attrs.erase(Attrs.begin() + i); --e; continue; @@ -2115,7 +2250,8 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(Decl *D, SourceRange Range, MergedDeprecated, MergedObsoleted)) { return ::new (Context) AvailabilityAttr(Range, Context, Platform, Introduced, Deprecated, - Obsoleted, IsUnavailable, Message); + Obsoleted, IsUnavailable, Message, + AttrSpellingListIndex); } return NULL; } @@ -2124,11 +2260,18 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { IdentifierInfo *Platform = Attr.getParameterName(); SourceLocation PlatformLoc = Attr.getParameterLoc(); - + unsigned Index = Attr.getAttributeSpellingListIndex(); + if (AvailabilityAttr::getPrettyPlatformName(Platform->getName()).empty()) S.Diag(PlatformLoc, diag::warn_availability_unknown_platform) << Platform; + NamedDecl *ND = dyn_cast<NamedDecl>(D); + if (!ND) { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); + return; + } + AvailabilityChange Introduced = Attr.getAvailabilityIntroduced(); AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated(); AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted(); @@ -2139,37 +2282,69 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, if (SE) Str = SE->getString(); - AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(D, Attr.getRange(), + AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, Attr.getRange(), Platform, Introduced.Version, Deprecated.Version, Obsoleted.Version, - IsUnavailable, Str); + IsUnavailable, Str, + /*Override=*/false, + Index); if (NewAttr) D->addAttr(NewAttr); } +template <class T> +static T *mergeVisibilityAttr(Sema &S, Decl *D, SourceRange range, + typename T::VisibilityType value, + unsigned attrSpellingListIndex) { + T *existingAttr = D->getAttr<T>(); + if (existingAttr) { + typename T::VisibilityType existingValue = existingAttr->getVisibility(); + if (existingValue == value) + return NULL; + S.Diag(existingAttr->getLocation(), diag::err_mismatched_visibility); + S.Diag(range.getBegin(), diag::note_previous_attribute); + D->dropAttr<T>(); + } + return ::new (S.Context) T(range, S.Context, value, attrSpellingListIndex); +} + VisibilityAttr *Sema::mergeVisibilityAttr(Decl *D, SourceRange Range, - VisibilityAttr::VisibilityType Vis) { + VisibilityAttr::VisibilityType Vis, + unsigned AttrSpellingListIndex) { + return ::mergeVisibilityAttr<VisibilityAttr>(*this, D, Range, Vis, + AttrSpellingListIndex); +} + +TypeVisibilityAttr *Sema::mergeTypeVisibilityAttr(Decl *D, SourceRange Range, + TypeVisibilityAttr::VisibilityType Vis, + unsigned AttrSpellingListIndex) { + return ::mergeVisibilityAttr<TypeVisibilityAttr>(*this, D, Range, Vis, + AttrSpellingListIndex); +} + +static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr, + bool isTypeVisibility) { + // Visibility attributes don't mean anything on a typedef. if (isa<TypedefNameDecl>(D)) { - Diag(Range.getBegin(), diag::warn_attribute_ignored) << "visibility"; - return NULL; + S.Diag(Attr.getRange().getBegin(), diag::warn_attribute_ignored) + << Attr.getName(); + return; } - VisibilityAttr *ExistingAttr = D->getAttr<VisibilityAttr>(); - if (ExistingAttr) { - VisibilityAttr::VisibilityType ExistingVis = ExistingAttr->getVisibility(); - if (ExistingVis == Vis) - return NULL; - Diag(ExistingAttr->getLocation(), diag::err_mismatched_visibility); - Diag(Range.getBegin(), diag::note_previous_attribute); - D->dropAttr<VisibilityAttr>(); + + // 'type_visibility' can only go on a type or namespace. + if (isTypeVisibility && + !(isa<TagDecl>(D) || + isa<ObjCInterfaceDecl>(D) || + isa<NamespaceDecl>(D))) { + S.Diag(Attr.getRange().getBegin(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << ExpectedTypeOrNamespace; + return; } - return ::new (Context) VisibilityAttr(Range, Context, Vis); -} -static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. - if(!checkAttributeNumArgs(S, Attr, 1)) + if (!checkAttributeNumArgs(S, Attr, 1)) return; Expr *Arg = Attr.getArg(0); @@ -2178,13 +2353,13 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!Str || !Str->isAscii()) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) - << "visibility" << 1; + << (isTypeVisibility ? "type_visibility" : "visibility") << 1; return; } StringRef TypeStr = Str->getString(); VisibilityAttr::VisibilityType type; - + if (TypeStr == "default") type = VisibilityAttr::Default; else if (TypeStr == "hidden") @@ -2205,9 +2380,17 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - VisibilityAttr *NewAttr = S.mergeVisibilityAttr(D, Attr.getRange(), type); - if (NewAttr) - D->addAttr(NewAttr); + unsigned Index = Attr.getAttributeSpellingListIndex(); + clang::Attr *newAttr; + if (isTypeVisibility) { + newAttr = S.mergeTypeVisibilityAttr(D, Attr.getRange(), + (TypeVisibilityAttr::VisibilityType) type, + Index); + } else { + newAttr = S.mergeVisibilityAttr(D, Attr.getRange(), type, Index); + } + if (newAttr) + D->addAttr(newAttr); } static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl, @@ -2274,7 +2457,9 @@ static void handleObjCExceptionAttr(Sema &S, Decl *D, return; } - D->addAttr(::new (S.Context) ObjCExceptionAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ObjCExceptionAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) { @@ -2305,7 +2490,9 @@ static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) { // case. S.Diag(D->getLocation(), diag::warn_nsobject_attribute); } - D->addAttr(::new (S.Context) ObjCNSObjectAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ObjCNSObjectAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void @@ -2320,7 +2507,9 @@ handleOverloadableAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) OverloadableAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + OverloadableAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -2344,7 +2533,9 @@ static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) BlocksAttr(Attr.getRange(), S.Context, type)); + D->addAttr(::new (S.Context) + BlocksAttr(Attr.getRange(), S.Context, type, + Attr.getAttributeSpellingListIndex())); } static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -2436,8 +2627,9 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) { << Attr.getName() << ExpectedFunctionMethodOrBlock; return; } - D->addAttr(::new (S.Context) SentinelAttr(Attr.getRange(), S.Context, sentinel, - nullPos)); + D->addAttr(::new (S.Context) + SentinelAttr(Attr.getRange(), S.Context, sentinel, nullPos, + Attr.getAttributeSpellingListIndex())); } static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) { @@ -2445,9 +2637,9 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) if (!checkAttributeNumArgs(S, Attr, 0)) return; - if (!isFunction(D) && !isa<ObjCMethodDecl>(D)) { + if (!isFunction(D) && !isa<ObjCMethodDecl>(D) && !isa<CXXRecordDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << ExpectedFunctionOrMethod; + << Attr.getName() << ExpectedFunctionMethodOrClass; return; } @@ -2463,7 +2655,9 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) return; } - D->addAttr(::new (S.Context) WarnUnusedResultAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + WarnUnusedResultAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -2485,13 +2679,9 @@ static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) { NamedDecl *nd = cast<NamedDecl>(D); - // 'weak' only applies to declarations with external linkage. - if (hasEffectivelyInternalLinkage(nd)) { - S.Diag(Attr.getLoc(), diag::err_attribute_weak_static); - return; - } - - nd->addAttr(::new (S.Context) WeakAttr(Attr.getRange(), S.Context)); + nd->addAttr(::new (S.Context) + WeakAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -2518,7 +2708,9 @@ static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) WeakImportAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + WeakImportAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } // Handles reqd_work_group_size and work_group_size_hint. @@ -2568,15 +2760,57 @@ static void handleWorkGroupSize(Sema &S, Decl *D, if (Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize) D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(Attr.getRange(), S.Context, - WGSize[0], WGSize[1], WGSize[2])); + WGSize[0], WGSize[1], WGSize[2], + Attr.getAttributeSpellingListIndex())); else D->addAttr(::new (S.Context) WorkGroupSizeHintAttr(Attr.getRange(), S.Context, - WGSize[0], WGSize[1], WGSize[2])); + WGSize[0], WGSize[1], WGSize[2], + Attr.getAttributeSpellingListIndex())); +} + +static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) { + assert(Attr.getKind() == AttributeList::AT_VecTypeHint); + + // Attribute has 1 argument. + if (!checkAttributeNumArgs(S, Attr, 1)) + return; + + QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg()); + + if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() && + (ParmType->isBooleanType() || + !ParmType->isIntegralType(S.getASTContext()))) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_vec_type_hint) + << ParmType; + return; + } + + if (Attr.getKind() == AttributeList::AT_VecTypeHint && + D->hasAttr<VecTypeHintAttr>()) { + VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>(); + if (A->getTypeHint() != ParmType) { + S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName(); + return; + } + } + + D->addAttr(::new (S.Context) VecTypeHintAttr(Attr.getLoc(), S.Context, + ParmType, Attr.getLoc())); +} + +static void handleEndianAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!dyn_cast<VarDecl>(D)) + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << "endian" + << 9; + StringRef EndianType = Attr.getParameterName()->getName(); + if (EndianType != "host" && EndianType != "device") + S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_endian) << EndianType; } SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range, - StringRef Name) { + StringRef Name, + unsigned AttrSpellingListIndex) { if (SectionAttr *ExistingAttr = D->getAttr<SectionAttr>()) { if (ExistingAttr->getName() == Name) return NULL; @@ -2584,7 +2818,8 @@ SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range, Diag(Range.getBegin(), diag::note_previous_attribute); return NULL; } - return ::new (Context) SectionAttr(Range, Context, Name); + return ::new (Context) SectionAttr(Range, Context, Name, + AttrSpellingListIndex); } static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -2614,8 +2849,10 @@ static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) { S.Diag(SE->getLocStart(), diag::err_attribute_section_local_variable); return; } + + unsigned Index = Attr.getAttributeSpellingListIndex(); SectionAttr *NewAttr = S.mergeSectionAttr(D, Attr.getRange(), - SE->getString()); + SE->getString(), Index); if (NewAttr) D->addAttr(NewAttr); } @@ -2632,7 +2869,9 @@ static void handleNothrowAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (Existing->getLocation().isInvalid()) Existing->setRange(Attr.getRange()); } else { - D->addAttr(::new (S.Context) NoThrowAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + NoThrowAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } } @@ -2647,7 +2886,9 @@ static void handleConstAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (Existing->getLocation().isInvalid()) Existing->setRange(Attr.getRange()); } else { - D->addAttr(::new (S.Context) ConstAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ConstAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex() )); } } @@ -2656,7 +2897,9 @@ static void handlePureAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkAttributeNumArgs(S, Attr, 0)) return; - D->addAttr(::new (S.Context) PureAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + PureAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -2715,8 +2958,11 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) CleanupAttr(Attr.getRange(), S.Context, FD)); + D->addAttr(::new (S.Context) + CleanupAttr(Attr.getRange(), S.Context, FD, + Attr.getAttributeSpellingListIndex())); S.MarkFunctionReferenced(Attr.getParameterLoc(), FD); + S.DiagnoseUseOfDecl(FD, Attr.getParameterLoc()); } /// Handle __attribute__((format_arg((idx)))) attribute based on @@ -2790,8 +3036,9 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) FormatArgAttr(Attr.getRange(), S.Context, - Idx.getZExtValue())); + D->addAttr(::new (S.Context) + FormatArgAttr(Attr.getRange(), S.Context, Idx.getZExtValue(), + Attr.getAttributeSpellingListIndex())); } enum FormatAttrKind { @@ -2866,12 +3113,14 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, Attr.setInvalid(); return; } - D->addAttr(::new (S.Context) InitPriorityAttr(Attr.getRange(), S.Context, - prioritynum)); + D->addAttr(::new (S.Context) + InitPriorityAttr(Attr.getRange(), S.Context, prioritynum, + Attr.getAttributeSpellingListIndex())); } FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format, - int FormatIdx, int FirstArg) { + int FormatIdx, int FirstArg, + unsigned AttrSpellingListIndex) { // Check whether we already have an equivalent format attribute. for (specific_attr_iterator<FormatAttr> i = D->specific_attr_begin<FormatAttr>(), @@ -2889,8 +3138,8 @@ FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format, } } - return ::new (Context) FormatAttr(Range, Context, Format, FormatIdx, - FirstArg); + return ::new (Context) FormatAttr(Range, Context, Format, FormatIdx, FirstArg, + AttrSpellingListIndex); } /// Handle __attribute__((format(type,idx,firstarg))) attributes based on @@ -3030,7 +3279,8 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { FormatAttr *NewAttr = S.mergeFormatAttr(D, Attr.getRange(), Format, Idx.getZExtValue(), - FirstArg.getZExtValue()); + FirstArg.getZExtValue(), + Attr.getAttributeSpellingListIndex()); if (NewAttr) D->addAttr(NewAttr); } @@ -3099,7 +3349,9 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, } } - RD->addAttr(::new (S.Context) TransparentUnionAttr(Attr.getRange(), S.Context)); + RD->addAttr(::new (S.Context) + TransparentUnionAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -3124,8 +3376,10 @@ static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) { if ((*i)->getAnnotation() == SE->getString()) return; } - D->addAttr(::new (S.Context) AnnotateAttr(Attr.getRange(), S.Context, - SE->getString())); + + D->addAttr(::new (S.Context) + AnnotateAttr(Attr.getRange(), S.Context, SE->getString(), + Attr.getAttributeSpellingListIndex())); } static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -3135,34 +3389,77 @@ static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - //FIXME: The C++0x version of this attribute has more limited applicabilty - // than GNU's, and should error out when it is used to specify a - // weaker alignment, rather than being silently ignored. - if (Attr.getNumArgs() == 0) { - D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context, - true, 0, Attr.isDeclspecAttribute())); + D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context, + true, 0, Attr.getAttributeSpellingListIndex())); return; } - S.AddAlignedAttr(Attr.getRange(), D, Attr.getArg(0), - Attr.isDeclspecAttribute()); -} + Expr *E = Attr.getArg(0); + if (Attr.isPackExpansion() && !E->containsUnexpandedParameterPack()) { + S.Diag(Attr.getEllipsisLoc(), + diag::err_pack_expansion_without_parameter_packs); + return; + } -void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, - bool isDeclSpec) { - // FIXME: Handle pack-expansions here. - if (DiagnoseUnexpandedParameterPack(E)) + if (!Attr.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E)) return; + S.AddAlignedAttr(Attr.getRange(), D, E, Attr.getAttributeSpellingListIndex(), + Attr.isPackExpansion()); +} + +void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, + unsigned SpellingListIndex, bool IsPackExpansion) { + AlignedAttr TmpAttr(AttrRange, Context, true, E, SpellingListIndex); + SourceLocation AttrLoc = AttrRange.getBegin(); + + // C++11 alignas(...) and C11 _Alignas(...) have additional requirements. + if (TmpAttr.isAlignas()) { + // C++11 [dcl.align]p1: + // An alignment-specifier may be applied to a variable or to a class + // data member, but it shall not be applied to a bit-field, a function + // parameter, the formal parameter of a catch clause, or a variable + // declared with the register storage class specifier. An + // alignment-specifier may also be applied to the declaration of a class + // or enumeration type. + // C11 6.7.5/2: + // An alignment attribute shall not be specified in a declaration of + // a typedef, or a bit-field, or a function, or a parameter, or an + // object declared with the register storage-class specifier. + int DiagKind = -1; + if (isa<ParmVarDecl>(D)) { + DiagKind = 0; + } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (VD->getStorageClass() == SC_Register) + DiagKind = 1; + if (VD->isExceptionVariable()) + DiagKind = 2; + } else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { + if (FD->isBitField()) + DiagKind = 3; + } else if (!isa<TagDecl>(D)) { + Diag(AttrLoc, diag::err_attribute_wrong_decl_type) + << (TmpAttr.isC11() ? "'_Alignas'" : "'alignas'") + << (TmpAttr.isC11() ? ExpectedVariableOrField + : ExpectedVariableFieldOrTag); + return; + } + if (DiagKind != -1) { + Diag(AttrLoc, diag::err_alignas_attribute_wrong_decl_type) + << TmpAttr.isC11() << DiagKind; + return; + } + } + if (E->isTypeDependent() || E->isValueDependent()) { // Save dependent expressions in the AST to be instantiated. - D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, E, - isDeclSpec)); + AlignedAttr *AA = ::new (Context) AlignedAttr(TmpAttr); + AA->setPackExpansion(IsPackExpansion); + D->addAttr(AA); return; } - - SourceLocation AttrLoc = AttrRange.getBegin(); + // FIXME: Cache the number on the Attr object? llvm::APSInt Alignment(32); ExprResult ICE @@ -3171,32 +3468,79 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, /*AllowFold*/ false); if (ICE.isInvalid()) return; - if (!llvm::isPowerOf2_64(Alignment.getZExtValue())) { + + // C++11 [dcl.align]p2: + // -- if the constant expression evaluates to zero, the alignment + // specifier shall have no effect + // C11 6.7.5p6: + // An alignment specification of zero has no effect. + if (!(TmpAttr.isAlignas() && !Alignment) && + !llvm::isPowerOf2_64(Alignment.getZExtValue())) { Diag(AttrLoc, diag::err_attribute_aligned_not_power_of_two) << E->getSourceRange(); return; } - if (isDeclSpec) { + + if (TmpAttr.isDeclspec()) { // We've already verified it's a power of 2, now let's make sure it's // 8192 or less. if (Alignment.getZExtValue() > 8192) { - Diag(AttrLoc, diag::err_attribute_aligned_greater_than_8192) + Diag(AttrLoc, diag::err_attribute_aligned_greater_than_8192) << E->getSourceRange(); return; } } - D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, ICE.take(), - isDeclSpec)); + AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, true, + ICE.take(), SpellingListIndex); + AA->setPackExpansion(IsPackExpansion); + D->addAttr(AA); } -void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS, - bool isDeclSpec) { +void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS, + unsigned SpellingListIndex, bool IsPackExpansion) { // FIXME: Cache the number on the Attr object if non-dependent? // FIXME: Perform checking of type validity - D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, false, TS, - isDeclSpec)); - return; + AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, false, TS, + SpellingListIndex); + AA->setPackExpansion(IsPackExpansion); + D->addAttr(AA); +} + +void Sema::CheckAlignasUnderalignment(Decl *D) { + assert(D->hasAttrs() && "no attributes on decl"); + + QualType Ty; + if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) + Ty = VD->getType(); + else + Ty = Context.getTagDeclType(cast<TagDecl>(D)); + if (Ty->isDependentType() || Ty->isIncompleteType()) + return; + + // C++11 [dcl.align]p5, C11 6.7.5/4: + // The combined effect of all alignment attributes in a declaration shall + // not specify an alignment that is less strict than the alignment that + // would otherwise be required for the entity being declared. + AlignedAttr *AlignasAttr = 0; + unsigned Align = 0; + for (specific_attr_iterator<AlignedAttr> + I = D->specific_attr_begin<AlignedAttr>(), + E = D->specific_attr_end<AlignedAttr>(); I != E; ++I) { + if (I->isAlignmentDependent()) + return; + if (I->isAlignas()) + AlignasAttr = *I; + Align = std::max(Align, I->getAlignment(Context)); + } + + if (AlignasAttr && Align) { + CharUnits RequestedAlign = Context.toCharUnitsFromBits(Align); + CharUnits NaturalAlign = Context.getTypeAlignInChars(Ty); + if (NaturalAlign > RequestedAlign) + Diag(AlignasAttr->getLocation(), diag::err_alignas_underaligned) + << Ty << (unsigned)NaturalAlign.getQuantity(); + } } /// handleModeAttr - This attribute modifies the width of a decl with primitive @@ -3260,6 +3604,10 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (Str == "pointer") DestWidth = S.Context.getTargetInfo().getPointerWidth(0); break; + case 11: + if (Str == "unwind_word") + DestWidth = S.Context.getTargetInfo().getUnwindWordWidth(); + break; } QualType OldTy; @@ -3386,7 +3734,9 @@ static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) NoDebugAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + NoDebugAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -3401,7 +3751,9 @@ static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) NoInlineAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + NoInlineAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D, @@ -3417,8 +3769,9 @@ static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D, return; } - D->addAttr(::new (S.Context) NoInstrumentFunctionAttr(Attr.getRange(), - S.Context)); + D->addAttr(::new (S.Context) + NoInstrumentFunctionAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -3435,7 +3788,9 @@ static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) CUDAConstantAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + CUDAConstantAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } else { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "constant"; } @@ -3455,7 +3810,9 @@ static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) CUDADeviceAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + CUDADeviceAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } else { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "device"; } @@ -3476,10 +3833,10 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) { FunctionDecl *FD = cast<FunctionDecl>(D); if (!FD->getResultType()->isVoidType()) { TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens(); - if (FunctionTypeLoc* FTL = dyn_cast<FunctionTypeLoc>(&TL)) { + if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return) << FD->getType() - << FixItHint::CreateReplacement(FTL->getResultLoc().getSourceRange(), + << FixItHint::CreateReplacement(FTL.getResultLoc().getSourceRange(), "void"); } else { S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return) @@ -3488,7 +3845,9 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) CUDAGlobalAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + CUDAGlobalAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } else { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "global"; } @@ -3507,7 +3866,9 @@ static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) CUDAHostAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + CUDAHostAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } else { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "host"; } @@ -3519,14 +3880,15 @@ static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkAttributeNumArgs(S, Attr, 0)) return; - if (!isa<VarDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedVariable; return; } - D->addAttr(::new (S.Context) CUDASharedAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + CUDASharedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } else { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "shared"; } @@ -3549,16 +3911,19 @@ static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) GNUInlineAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + GNUInlineAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (hasDeclarator(D)) return; + const FunctionDecl *FD = dyn_cast<FunctionDecl>(D); // Diagnostic is emitted elsewhere: here we store the (valid) Attr // in the Decl node for syntactic reasoning, e.g., pretty-printing. CallingConv CC; - if (S.CheckCallingConvAttr(Attr, CC)) + if (S.CheckCallingConvAttr(Attr, CC, FD)) return; if (!isa<ObjCMethodDecl>(D)) { @@ -3569,19 +3934,29 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { switch (Attr.getKind()) { case AttributeList::AT_FastCall: - D->addAttr(::new (S.Context) FastCallAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + FastCallAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; case AttributeList::AT_StdCall: - D->addAttr(::new (S.Context) StdCallAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + StdCallAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; case AttributeList::AT_ThisCall: - D->addAttr(::new (S.Context) ThisCallAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ThisCallAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; case AttributeList::AT_CDecl: - D->addAttr(::new (S.Context) CDeclAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + CDeclAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; case AttributeList::AT_Pascal: - D->addAttr(::new (S.Context) PascalAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + PascalAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; case AttributeList::AT_Pcs: { PcsAttr::PCSType PCS; @@ -3596,11 +3971,20 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { llvm_unreachable("unexpected calling convention in pcs attribute"); } - D->addAttr(::new (S.Context) PcsAttr(Attr.getRange(), S.Context, PCS)); + D->addAttr(::new (S.Context) + PcsAttr(Attr.getRange(), S.Context, PCS, + Attr.getAttributeSpellingListIndex())); return; } case AttributeList::AT_PnaclCall: - D->addAttr(::new (S.Context) PnaclCallAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + PnaclCallAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); + return; + case AttributeList::AT_IntelOclBicc: + D->addAttr(::new (S.Context) + IntelOclBiccAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; default: @@ -3613,7 +3997,24 @@ static void handleOpenCLKernelAttr(Sema &S, Decl *D, const AttributeList &Attr){ D->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getRange(), S.Context)); } -bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) { +static void handleOpenCLImageAccessAttr(Sema &S, Decl *D, const AttributeList &Attr){ + assert(!Attr.isInvalid()); + + Expr *E = Attr.getArg(0); + llvm::APSInt ArgNum(32); + if (E->isTypeDependent() || E->isValueDependent() || + !E->isIntegerConstantExpr(ArgNum, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << Attr.getName()->getName() << E->getSourceRange(); + return; + } + + D->addAttr(::new (S.Context) OpenCLImageAccessAttr( + Attr.getRange(), S.Context, ArgNum.getZExtValue())); +} + +bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, + const FunctionDecl *FD) { if (attr.isInvalid()) return true; @@ -3656,6 +4057,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) { return true; } case AttributeList::AT_PnaclCall: CC = CC_PnaclCall; break; + case AttributeList::AT_IntelOclBicc: CC = CC_IntelOclBicc; break; default: llvm_unreachable("unexpected attribute kind"); } @@ -3663,7 +4065,12 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) { TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC); if (A == TargetInfo::CCCR_Warning) { Diag(attr.getLoc(), diag::warn_cconv_ignored) << attr.getName(); - CC = TI.getDefaultCallingConv(); + + TargetInfo::CallingConvMethodType MT = TargetInfo::CCMT_Unknown; + if (FD) + MT = FD->isCXXInstanceMember() ? TargetInfo::CCMT_Member : + TargetInfo::CCMT_NonMember; + CC = TI.getDefaultCallingConv(MT); } return false; @@ -3682,7 +4089,9 @@ static void handleRegparmAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) RegparmAttr(Attr.getRange(), S.Context, numParams)); + D->addAttr(::new (S.Context) + RegparmAttr(Attr.getRange(), S.Context, numParams, + Attr.getAttributeSpellingListIndex())); } /// Checks a regparm attribute, returning true if it is ill-formed and @@ -3762,9 +4171,11 @@ static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){ } } - D->addAttr(::new (S.Context) CUDALaunchBoundsAttr(Attr.getRange(), S.Context, - MaxThreads.getZExtValue(), - MinBlocks.getZExtValue())); + D->addAttr(::new (S.Context) + CUDALaunchBoundsAttr(Attr.getRange(), S.Context, + MaxThreads.getZExtValue(), + MinBlocks.getZExtValue(), + Attr.getAttributeSpellingListIndex())); } else { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "launch_bounds"; } @@ -3815,12 +4226,10 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, } } - D->addAttr(::new (S.Context) ArgumentWithTypeTagAttr(Attr.getRange(), - S.Context, - ArgumentKind, - ArgumentIdx, - TypeTagIdx, - IsPointer)); + D->addAttr(::new (S.Context) + ArgumentWithTypeTagAttr(Attr.getRange(), S.Context, ArgumentKind, + ArgumentIdx, TypeTagIdx, IsPointer, + Attr.getAttributeSpellingListIndex())); } static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, @@ -3834,13 +4243,12 @@ static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, QualType MatchingCType = S.GetTypeFromParser(Attr.getMatchingCType(), NULL); - D->addAttr(::new (S.Context) TypeTagForDatatypeAttr( - Attr.getRange(), - S.Context, - PointerKind, - MatchingCType, - Attr.getLayoutCompatible(), - Attr.getMustBeNull())); + D->addAttr(::new (S.Context) + TypeTagForDatatypeAttr(Attr.getRange(), S.Context, PointerKind, + MatchingCType, + Attr.getLayoutCompatible(), + Attr.getMustBeNull(), + Attr.getAttributeSpellingListIndex())); } //===----------------------------------------------------------------------===// @@ -3882,9 +4290,13 @@ static void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) { } if (cf) - param->addAttr(::new (S.Context) CFConsumedAttr(Attr.getRange(), S.Context)); + param->addAttr(::new (S.Context) + CFConsumedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else - param->addAttr(::new (S.Context) NSConsumedAttr(Attr.getRange(), S.Context)); + param->addAttr(::new (S.Context) + NSConsumedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleNSConsumesSelfAttr(Sema &S, Decl *D, @@ -3895,7 +4307,9 @@ static void handleNSConsumesSelfAttr(Sema &S, Decl *D, return; } - D->addAttr(::new (S.Context) NSConsumesSelfAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + NSConsumesSelfAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, @@ -3947,24 +4361,29 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, default: llvm_unreachable("invalid ownership attribute"); case AttributeList::AT_NSReturnsAutoreleased: - D->addAttr(::new (S.Context) NSReturnsAutoreleasedAttr(Attr.getRange(), - S.Context)); + D->addAttr(::new (S.Context) + NSReturnsAutoreleasedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; case AttributeList::AT_CFReturnsNotRetained: - D->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(Attr.getRange(), - S.Context)); + D->addAttr(::new (S.Context) + CFReturnsNotRetainedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; case AttributeList::AT_NSReturnsNotRetained: - D->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(Attr.getRange(), - S.Context)); + D->addAttr(::new (S.Context) + NSReturnsNotRetainedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; case AttributeList::AT_CFReturnsRetained: - D->addAttr(::new (S.Context) CFReturnsRetainedAttr(Attr.getRange(), - S.Context)); + D->addAttr(::new (S.Context) + CFReturnsRetainedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; case AttributeList::AT_NSReturnsRetained: - D->addAttr(::new (S.Context) NSReturnsRetainedAttr(Attr.getRange(), - S.Context)); + D->addAttr(::new (S.Context) + NSReturnsRetainedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; }; } @@ -3994,8 +4413,9 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D, return; } - method->addAttr( - ::new (S.Context) ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context)); + method->addAttr(::new (S.Context) + ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context, + attr.getAttributeSpellingListIndex())); } static void handleObjCRequiresSuperAttr(Sema &S, Decl *D, @@ -4021,8 +4441,9 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl *D, return; } - method->addAttr( - ::new (S.Context) ObjCRequiresSuperAttr(attr.getRange(), S.Context)); + method->addAttr(::new (S.Context) + ObjCRequiresSuperAttr(attr.getRange(), S.Context, + attr.getAttributeSpellingListIndex())); } /// Handle cf_audited_transfer and cf_unknown_transfer. @@ -4052,11 +4473,13 @@ static void handleCFTransferAttr(Sema &S, Decl *D, const AttributeList &A) { // All clear; add the attribute. if (IsAudited) { - D->addAttr( - ::new (S.Context) CFAuditedTransferAttr(A.getRange(), S.Context)); + D->addAttr(::new (S.Context) + CFAuditedTransferAttr(A.getRange(), S.Context, + A.getAttributeSpellingListIndex())); } else { - D->addAttr( - ::new (S.Context) CFUnknownTransferAttr(A.getRange(), S.Context)); + D->addAttr(::new (S.Context) + CFUnknownTransferAttr(A.getRange(), S.Context, + A.getAttributeSpellingListIndex())); } } @@ -4086,8 +4509,9 @@ static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D, } } - D->addAttr(::new (S.Context) NSBridgedAttr(Attr.getRange(), S.Context, - ParmName)); + D->addAttr(::new (S.Context) + NSBridgedAttr(Attr.getRange(), S.Context, ParmName, + Attr.getAttributeSpellingListIndex())); } static void handleObjCOwnershipAttr(Sema &S, Decl *D, @@ -4141,7 +4565,8 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D, } D->addAttr(::new (S.Context) - ObjCPreciseLifetimeAttr(Attr.getRange(), S.Context)); + ObjCPreciseLifetimeAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } //===----------------------------------------------------------------------===// @@ -4189,15 +4614,16 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); return; } - } else if (!isxdigit(*I)) { + } else if (!isHexDigit(*I)) { S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); return; } I++; } - D->addAttr(::new (S.Context) UuidAttr(Attr.getRange(), S.Context, - Str->getString())); + D->addAttr(::new (S.Context) + UuidAttr(Attr.getRange(), S.Context, Str->getString(), + Attr.getAttributeSpellingListIndex())); } else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "uuid"; } @@ -4211,13 +4637,19 @@ static void handleInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) { AttributeList::Kind Kind = Attr.getKind(); if (Kind == AttributeList::AT_SingleInheritance) D->addAttr( - ::new (S.Context) SingleInheritanceAttr(Attr.getRange(), S.Context)); + ::new (S.Context) + SingleInheritanceAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else if (Kind == AttributeList::AT_MultipleInheritance) D->addAttr( - ::new (S.Context) MultipleInheritanceAttr(Attr.getRange(), S.Context)); + ::new (S.Context) + MultipleInheritanceAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else if (Kind == AttributeList::AT_VirtualInheritance) D->addAttr( - ::new (S.Context) VirtualInheritanceAttr(Attr.getRange(), S.Context)); + ::new (S.Context) + VirtualInheritanceAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handlePortabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -4225,20 +4657,25 @@ static void handlePortabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { AttributeList::Kind Kind = Attr.getKind(); if (Kind == AttributeList::AT_Ptr32) D->addAttr( - ::new (S.Context) Ptr32Attr(Attr.getRange(), S.Context)); + ::new (S.Context) Ptr32Attr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else if (Kind == AttributeList::AT_Ptr64) D->addAttr( - ::new (S.Context) Ptr64Attr(Attr.getRange(), S.Context)); + ::new (S.Context) Ptr64Attr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else if (Kind == AttributeList::AT_Win64) D->addAttr( - ::new (S.Context) Win64Attr(Attr.getRange(), S.Context)); + ::new (S.Context) Win64Attr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } static void handleForceInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.LangOpts.MicrosoftExt) - D->addAttr(::new (S.Context) ForceInlineAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ForceInlineAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } @@ -4261,12 +4698,11 @@ static void ProcessNonInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, const AttributeList &Attr) { switch (Attr.getKind()) { - case AttributeList::AT_IBAction: handleIBAction(S, D, Attr); break; - case AttributeList::AT_IBOutlet: handleIBOutlet(S, D, Attr); break; - case AttributeList::AT_IBOutletCollection: - handleIBOutletCollection(S, D, Attr); break; + case AttributeList::AT_IBAction: handleIBAction(S, D, Attr); break; + case AttributeList::AT_IBOutlet: handleIBOutlet(S, D, Attr); break; + case AttributeList::AT_IBOutletCollection: + handleIBOutletCollection(S, D, Attr); break; case AttributeList::AT_AddressSpace: - case AttributeList::AT_OpenCLImageAccess: case AttributeList::AT_ObjCGC: case AttributeList::AT_VectorSize: case AttributeList::AT_NeonVectorType: @@ -4291,10 +4727,14 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_Annotate: handleAnnotateAttr (S, D, Attr); break; case AttributeList::AT_Availability:handleAvailabilityAttr(S, D, Attr); break; case AttributeList::AT_CarriesDependency: - handleDependencyAttr (S, D, Attr); break; + handleDependencyAttr(S, scope, D, Attr); + break; case AttributeList::AT_Common: handleCommonAttr (S, D, Attr); break; case AttributeList::AT_CUDAConstant:handleConstantAttr (S, D, Attr); break; case AttributeList::AT_Constructor: handleConstructorAttr (S, D, Attr); break; + case AttributeList::AT_CXX11NoReturn: + handleCXX11NoReturnAttr(S, D, Attr); + break; case AttributeList::AT_Deprecated: handleAttrWithMessage<DeprecatedAttr>(S, D, Attr, "deprecated"); break; @@ -4364,6 +4804,13 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_ReqdWorkGroupSize: handleWorkGroupSize(S, D, Attr); break; + case AttributeList::AT_VecTypeHint: + handleVecTypeHint(S, D, Attr); break; + + case AttributeList::AT_Endian: + handleEndianAttr(S, D, Attr); + break; + case AttributeList::AT_InitPriority: handleInitPriorityAttr(S, D, Attr); break; @@ -4386,7 +4833,12 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, handleReturnsTwiceAttr(S, D, Attr); break; case AttributeList::AT_Used: handleUsedAttr (S, D, Attr); break; - case AttributeList::AT_Visibility: handleVisibilityAttr (S, D, Attr); break; + case AttributeList::AT_Visibility: + handleVisibilityAttr(S, D, Attr, false); + break; + case AttributeList::AT_TypeVisibility: + handleVisibilityAttr(S, D, Attr, true); + break; case AttributeList::AT_WarnUnusedResult: handleWarnUnusedResult(S, D, Attr); break; case AttributeList::AT_Weak: handleWeakAttr (S, D, Attr); break; @@ -4423,11 +4875,15 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_Pascal: case AttributeList::AT_Pcs: case AttributeList::AT_PnaclCall: + case AttributeList::AT_IntelOclBicc: handleCallConvAttr(S, D, Attr); break; case AttributeList::AT_OpenCLKernel: handleOpenCLKernelAttr(S, D, Attr); break; + case AttributeList::AT_OpenCLImageAccess: + handleOpenCLImageAccessAttr(S, D, Attr); + break; // Microsoft attributes: case AttributeList::AT_MsStruct: @@ -4460,11 +4916,17 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_ScopedLockable: handleScopedLockableAttr(S, D, Attr); break; - case AttributeList::AT_NoAddressSafetyAnalysis: - handleNoAddressSafetyAttr(S, D, Attr); + case AttributeList::AT_NoSanitizeAddress: + handleNoSanitizeAddressAttr(S, D, Attr); break; case AttributeList::AT_NoThreadSafetyAnalysis: - handleNoThreadSafetyAttr(S, D, Attr); + handleNoThreadSafetyAnalysis(S, D, Attr); + break; + case AttributeList::AT_NoSanitizeThread: + handleNoSanitizeThread(S, D, Attr); + break; + case AttributeList::AT_NoSanitizeMemory: + handleNoSanitizeMemory(S, D, Attr); break; case AttributeList::AT_Lockable: handleLockableAttr(S, D, Attr); @@ -4530,19 +4992,17 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, /// ProcessDeclAttribute - Apply the specific attribute to the specified decl if /// the attribute applies to decls. If the attribute is a type attribute, just -/// silently ignore it if a GNU attribute. FIXME: Applying a C++0x attribute to -/// the wrong thing is illegal (C++0x [dcl.attr.grammar]/4). +/// silently ignore it if a GNU attribute. static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const AttributeList &Attr, - bool NonInheritable, bool Inheritable) { + bool NonInheritable, bool Inheritable, + bool IncludeCXX11Attributes) { if (Attr.isInvalid()) return; - // Type attributes are still treated as declaration attributes by - // ParseMicrosoftTypeAttributes and ParseBorlandTypeAttributes. We don't - // want to process them, however, because we will simply warn about ignoring - // them. So instead, we will bail out early. - if (Attr.isMSTypespecAttribute()) + // Ignore C++11 attributes on declarator chunks: they appertain to the type + // instead. + if (Attr.isCXX11Attribute() && !IncludeCXX11Attributes) return; if (NonInheritable) @@ -4556,17 +5016,19 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, /// attribute list to the specified decl, ignoring any type attributes. void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList, - bool NonInheritable, bool Inheritable) { - for (const AttributeList* l = AttrList; l; l = l->getNext()) { - ProcessDeclAttribute(*this, S, D, *l, NonInheritable, Inheritable); - } + bool NonInheritable, bool Inheritable, + bool IncludeCXX11Attributes) { + for (const AttributeList* l = AttrList; l; l = l->getNext()) + ProcessDeclAttribute(*this, S, D, *l, NonInheritable, Inheritable, + IncludeCXX11Attributes); // GCC accepts // static int a9 __attribute__((weakref)); // but that looks really pointless. We reject it. if (Inheritable && D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) { Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) << - dyn_cast<NamedDecl>(D)->getNameAsString(); + cast<NamedDecl>(D)->getNameAsString(); + D->dropAttr<WeakRefAttr>(); return; } } @@ -4592,7 +5054,7 @@ bool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) { for ( ; A; A = A->getNext()) { // Only warn if the attribute is an unignored, non-type attribute. - if (A->isUsedAsTypeAttr()) continue; + if (A->isUsedAsTypeAttr() || A->isInvalid()) continue; if (A->getKind() == AttributeList::IgnoredAttribute) continue; if (A->getKind() == AttributeList::UnknownAttribute) { @@ -4630,8 +5092,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II, NewFD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(), Loc, Loc, DeclarationName(II), FD->getType(), FD->getTypeSourceInfo(), - SC_None, SC_None, - false/*isInlineSpecified*/, + SC_None, false/*isInlineSpecified*/, FD->hasPrototype(), false/*isConstexprSpecified*/); NewD = NewFD; @@ -4656,8 +5117,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II, NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(), VD->getInnerLocStart(), VD->getLocation(), II, VD->getType(), VD->getTypeSourceInfo(), - VD->getStorageClass(), - VD->getStorageClassAsWritten()); + VD->getStorageClass()); if (VD->getQualifier()) { VarDecl *NewVD = cast<VarDecl>(NewD); NewVD->setQualifierInfo(VD->getQualifierLoc()); @@ -4689,30 +5149,37 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) { } } -/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in -/// it, apply them to D. This is a bit tricky because PD can have attributes -/// specified in many different places, and we need to find and apply them all. -void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD, - bool NonInheritable, bool Inheritable) { +void Sema::ProcessPragmaWeak(Scope *S, Decl *D) { // It's valid to "forward-declare" #pragma weak, in which case we // have to do this. - if (Inheritable) { - LoadExternalWeakUndeclaredIdentifiers(); - if (!WeakUndeclaredIdentifiers.empty()) { - if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) { - if (IdentifierInfo *Id = ND->getIdentifier()) { - llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator I - = WeakUndeclaredIdentifiers.find(Id); - if (I != WeakUndeclaredIdentifiers.end() && ND->hasLinkage()) { - WeakInfo W = I->second; - DeclApplyPragmaWeak(S, ND, W); - WeakUndeclaredIdentifiers[Id] = W; - } + LoadExternalWeakUndeclaredIdentifiers(); + if (!WeakUndeclaredIdentifiers.empty()) { + NamedDecl *ND = NULL; + if (VarDecl *VD = dyn_cast<VarDecl>(D)) + if (VD->isExternC()) + ND = VD; + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + if (FD->isExternC()) + ND = FD; + if (ND) { + if (IdentifierInfo *Id = ND->getIdentifier()) { + llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator I + = WeakUndeclaredIdentifiers.find(Id); + if (I != WeakUndeclaredIdentifiers.end()) { + WeakInfo W = I->second; + DeclApplyPragmaWeak(S, ND, W); + WeakUndeclaredIdentifiers[Id] = W; } } } } +} +/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in +/// it, apply them to D. This is a bit tricky because PD can have attributes +/// specified in many different places, and we need to find and apply them all. +void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD, + bool NonInheritable, bool Inheritable) { // Apply decl attributes from the DeclSpec if present. if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList()) ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable); @@ -4723,7 +5190,8 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD, // when X is a decl attribute. for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs()) - ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable); + ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable, + /*IncludeCXX11Attributes=*/false); // Finally, apply any attributes on the decl itself. if (const AttributeList *Attrs = PD.getAttributes()) |