diff options
Diffstat (limited to 'lib/Sema/SemaDeclAttr.cpp')
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 1115 |
1 files changed, 620 insertions, 495 deletions
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 7f93ab7..61b7b3e 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -17,6 +17,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" +#include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/DelayedDiagnostic.h" @@ -48,14 +49,14 @@ enum { // Helper functions //===----------------------------------------------------------------------===// -static const FunctionType *getFunctionType(const Decl *d, +static const FunctionType *getFunctionType(const Decl *D, bool blocksToo = true) { QualType Ty; - if (const ValueDecl *decl = dyn_cast<ValueDecl>(d)) + if (const ValueDecl *decl = dyn_cast<ValueDecl>(D)) Ty = decl->getType(); - else if (const FieldDecl *decl = dyn_cast<FieldDecl>(d)) + else if (const FieldDecl *decl = dyn_cast<FieldDecl>(D)) Ty = decl->getType(); - else if (const TypedefNameDecl* decl = dyn_cast<TypedefNameDecl>(d)) + else if (const TypedefNameDecl* decl = dyn_cast<TypedefNameDecl>(D)) Ty = decl->getUnderlyingType(); else return 0; @@ -73,46 +74,47 @@ static const FunctionType *getFunctionType(const Decl *d, /// isFunction - Return true if the given decl has function /// type (function or function-typed variable). -static bool isFunction(const Decl *d) { - return getFunctionType(d, false) != NULL; +static bool isFunction(const Decl *D) { + return getFunctionType(D, false) != NULL; } /// isFunctionOrMethod - Return true if the given decl has function /// type (function or function-typed variable) or an Objective-C /// method. -static bool isFunctionOrMethod(const Decl *d) { - return isFunction(d)|| isa<ObjCMethodDecl>(d); +static bool isFunctionOrMethod(const Decl *D) { + return isFunction(D)|| isa<ObjCMethodDecl>(D); } /// isFunctionOrMethodOrBlock - Return true if the given decl has function /// type (function or function-typed variable) or an Objective-C /// method or a block. -static bool isFunctionOrMethodOrBlock(const Decl *d) { - if (isFunctionOrMethod(d)) +static bool isFunctionOrMethodOrBlock(const Decl *D) { + if (isFunctionOrMethod(D)) return true; // check for block is more involved. - if (const VarDecl *V = dyn_cast<VarDecl>(d)) { + if (const VarDecl *V = dyn_cast<VarDecl>(D)) { QualType Ty = V->getType(); return Ty->isBlockPointerType(); } - return isa<BlockDecl>(d); + return isa<BlockDecl>(D); } /// Return true if the given decl has a declarator that should have /// been processed by Sema::GetTypeForDeclarator. -static bool hasDeclarator(const Decl *d) { - // In some sense, TypedefNameDecl really *ought* to be a DeclaratorDecl. - return isa<DeclaratorDecl>(d) || isa<BlockDecl>(d) || isa<TypedefNameDecl>(d); +static bool hasDeclarator(const Decl *D) { + // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl. + return isa<DeclaratorDecl>(D) || isa<BlockDecl>(D) || isa<TypedefNameDecl>(D) || + isa<ObjCPropertyDecl>(D); } /// hasFunctionProto - Return true if the given decl has a argument /// information. This decl should have already passed /// isFunctionOrMethod or isFunctionOrMethodOrBlock. -static bool hasFunctionProto(const Decl *d) { - if (const FunctionType *FnTy = getFunctionType(d)) +static bool hasFunctionProto(const Decl *D) { + if (const FunctionType *FnTy = getFunctionType(D)) return isa<FunctionProtoType>(FnTy); else { - assert(isa<ObjCMethodDecl>(d) || isa<BlockDecl>(d)); + assert(isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D)); return true; } } @@ -120,42 +122,42 @@ static bool hasFunctionProto(const Decl *d) { /// getFunctionOrMethodNumArgs - Return number of function or method /// arguments. It is an error to call this on a K&R function (use /// hasFunctionProto first). -static unsigned getFunctionOrMethodNumArgs(const Decl *d) { - if (const FunctionType *FnTy = getFunctionType(d)) +static unsigned getFunctionOrMethodNumArgs(const Decl *D) { + if (const FunctionType *FnTy = getFunctionType(D)) return cast<FunctionProtoType>(FnTy)->getNumArgs(); - if (const BlockDecl *BD = dyn_cast<BlockDecl>(d)) + if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) return BD->getNumParams(); - return cast<ObjCMethodDecl>(d)->param_size(); + return cast<ObjCMethodDecl>(D)->param_size(); } -static QualType getFunctionOrMethodArgType(const Decl *d, unsigned Idx) { - if (const FunctionType *FnTy = getFunctionType(d)) +static QualType getFunctionOrMethodArgType(const Decl *D, unsigned Idx) { + if (const FunctionType *FnTy = getFunctionType(D)) return cast<FunctionProtoType>(FnTy)->getArgType(Idx); - if (const BlockDecl *BD = dyn_cast<BlockDecl>(d)) + if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) return BD->getParamDecl(Idx)->getType(); - return cast<ObjCMethodDecl>(d)->param_begin()[Idx]->getType(); + return cast<ObjCMethodDecl>(D)->param_begin()[Idx]->getType(); } -static QualType getFunctionOrMethodResultType(const Decl *d) { - if (const FunctionType *FnTy = getFunctionType(d)) +static QualType getFunctionOrMethodResultType(const Decl *D) { + if (const FunctionType *FnTy = getFunctionType(D)) return cast<FunctionProtoType>(FnTy)->getResultType(); - return cast<ObjCMethodDecl>(d)->getResultType(); + return cast<ObjCMethodDecl>(D)->getResultType(); } -static bool isFunctionOrMethodVariadic(const Decl *d) { - if (const FunctionType *FnTy = getFunctionType(d)) { +static bool isFunctionOrMethodVariadic(const Decl *D) { + if (const FunctionType *FnTy = getFunctionType(D)) { const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy); return proto->isVariadic(); - } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(d)) + } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) return BD->isVariadic(); else { - return cast<ObjCMethodDecl>(d)->isVariadic(); + return cast<ObjCMethodDecl>(D)->isVariadic(); } } -static bool isInstanceMethod(const Decl *d) { - if (const CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(d)) +static bool isInstanceMethod(const Decl *D) { + if (const CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D)) return MethodDecl->isInstance(); return false; } @@ -192,6 +194,16 @@ static inline bool isCFStringType(QualType T, ASTContext &Ctx) { return RD->getIdentifier() == &Ctx.Idents.get("__CFString"); } +static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr, + unsigned int Num) { + if (Attr.getNumArgs() != Num) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Num; + return false; + } + + return true; +} + //===----------------------------------------------------------------------===// // Attribute Implementations //===----------------------------------------------------------------------===// @@ -200,9 +212,9 @@ static inline bool isCFStringType(QualType T, ASTContext &Ctx) { // least add some helper functions to check most argument patterns (# // and types of args). -static void HandleExtVectorTypeAttr(Scope *scope, Decl *d, - const AttributeList &Attr, Sema &S) { - TypedefNameDecl *tDecl = dyn_cast<TypedefNameDecl>(d); +static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D, + const AttributeList &Attr) { + TypedefNameDecl *tDecl = dyn_cast<TypedefNameDecl>(D); if (tDecl == 0) { S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef); return; @@ -217,13 +229,17 @@ static void HandleExtVectorTypeAttr(Scope *scope, Decl *d, CXXScopeSpec SS; UnqualifiedId id; id.setIdentifier(Attr.getParameterName(), Attr.getLoc()); - sizeExpr = S.ActOnIdExpression(scope, SS, id, false, false).takeAs<Expr>(); + + ExprResult Size = S.ActOnIdExpression(scope, SS, id, false, false); + if (Size.isInvalid()) + return; + + sizeExpr = Size.get(); } else { // check the attribute arguments. - if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + if (!checkAttributeNumArgs(S, Attr, 1)) return; - } + sizeExpr = Attr.getArg(0); } @@ -239,16 +255,14 @@ static void HandleExtVectorTypeAttr(Scope *scope, Decl *d, } } -static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. - if (Attr.getNumArgs() > 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } - if (TagDecl *TD = dyn_cast<TagDecl>(d)) + if (TagDecl *TD = dyn_cast<TagDecl>(D)) TD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context)); - else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) { + else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { // If the alignment is less than or equal to 8 bits, the packed attribute // has no effect. if (!FD->getType()->isIncompleteType() && @@ -261,49 +275,45 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } -static void HandleMsStructAttr(Decl *d, const AttributeList &Attr, Sema &S) { - if (TagDecl *TD = dyn_cast<TagDecl>(d)) +static void handleMsStructAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (TagDecl *TD = dyn_cast<TagDecl>(D)) TD->addAttr(::new (S.Context) MsStructAttr(Attr.getLoc(), S.Context)); else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } -static void HandleIBAction(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleIBAction(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. - if (Attr.getNumArgs() > 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } // The IBAction attributes only apply to instance methods. - if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) + if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) if (MD->isInstanceMethod()) { - d->addAttr(::new (S.Context) IBActionAttr(Attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) IBActionAttr(Attr.getLoc(), S.Context)); return; } S.Diag(Attr.getLoc(), diag::warn_attribute_ibaction) << Attr.getName(); } -static void HandleIBOutlet(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleIBOutlet(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. - if (Attr.getNumArgs() > 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } // The IBOutlet attributes only apply to instance variables of // Objective-C classes. - if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d)) { - d->addAttr(::new (S.Context) IBOutletAttr(Attr.getLoc(), S.Context)); + if (isa<ObjCIvarDecl>(D) || isa<ObjCPropertyDecl>(D)) { + D->addAttr(::new (S.Context) IBOutletAttr(Attr.getLoc(), S.Context)); return; } S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName(); } -static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr, - Sema &S) { +static void handleIBOutletCollection(Sema &S, Decl *D, + const AttributeList &Attr) { // The iboutletcollection attribute can have zero or one arguments. if (Attr.getParameterName() && Attr.getNumArgs() > 0) { @@ -313,17 +323,17 @@ static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr, // The IBOutletCollection attributes only apply to instance variables of // Objective-C classes. - if (!(isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d))) { + if (!(isa<ObjCIvarDecl>(D) || isa<ObjCPropertyDecl>(D))) { S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName(); return; } - if (const ValueDecl *VD = dyn_cast<ValueDecl>(d)) + if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) if (!VD->getType()->getAs<ObjCObjectPointerType>()) { S.Diag(Attr.getLoc(), diag::err_iboutletcollection_object_type) << VD->getType() << 0; return; } - if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(d)) + if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) if (!PD->getType()->getAs<ObjCObjectPointerType>()) { S.Diag(Attr.getLoc(), diag::err_iboutletcollection_object_type) << PD->getType() << 1; @@ -335,7 +345,7 @@ static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr, II = &S.Context.Idents.get("id"); ParsedType TypeRep = S.getTypeName(*II, Attr.getLoc(), - S.getScopeForContext(d->getDeclContext()->getParent())); + S.getScopeForContext(D->getDeclContext()->getParent())); if (!TypeRep) { S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II; return; @@ -350,14 +360,29 @@ static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr, S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II; return; } - d->addAttr(::new (S.Context) IBOutletCollectionAttr(Attr.getLoc(), S.Context, + D->addAttr(::new (S.Context) IBOutletCollectionAttr(Attr.getLoc(), S.Context, QT)); } -static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void possibleTransparentUnionPointerType(QualType &T) { + if (const RecordType *UT = T->getAsUnionType()) + if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) { + RecordDecl *UD = UT->getDecl(); + for (RecordDecl::field_iterator it = UD->field_begin(), + itend = UD->field_end(); it != itend; ++it) { + QualType QT = it->getType(); + if (QT->isAnyPointerType() || QT->isBlockPointerType()) { + T = QT; + return; + } + } + } +} + +static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { // GCC ignores the nonnull attribute on K&R style function prototypes, so we // ignore it as well - if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) { + if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; return; @@ -365,8 +390,8 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { // In C++ the implicit 'this' function parameter also counts, and they are // counted from one. - bool HasImplicitThisParam = isInstanceMethod(d); - unsigned NumArgs = getFunctionOrMethodNumArgs(d) + HasImplicitThisParam; + bool HasImplicitThisParam = isInstanceMethod(D); + unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; // The nonnull attribute only applies to pointers. llvm::SmallVector<unsigned, 10> NonNullArgs; @@ -405,7 +430,9 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { } // Is the function argument a pointer type? - QualType T = getFunctionOrMethodArgType(d, x).getNonReferenceType(); + QualType T = getFunctionOrMethodArgType(D, x).getNonReferenceType(); + possibleTransparentUnionPointerType(T); + if (!T->isAnyPointerType() && !T->isBlockPointerType()) { // FIXME: Should also highlight argument in decl. S.Diag(Attr.getLoc(), diag::warn_nonnull_pointers_only) @@ -419,23 +446,11 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { // 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); - else if (const RecordType *UT = T->getAsUnionType()) { - if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) { - RecordDecl *UD = UT->getDecl(); - for (RecordDecl::field_iterator it = UD->field_begin(), - itend = UD->field_end(); it != itend; ++it) { - T = it->getType(); - if (T->isAnyPointerType() || T->isBlockPointerType()) { - NonNullArgs.push_back(I); - break; - } - } - } - } } // No pointer arguments? @@ -451,11 +466,11 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { unsigned* start = &NonNullArgs[0]; unsigned size = NonNullArgs.size(); llvm::array_pod_sort(start, start + size); - d->addAttr(::new (S.Context) NonNullAttr(Attr.getLoc(), S.Context, start, + D->addAttr(::new (S.Context) NonNullAttr(Attr.getLoc(), S.Context, start, size)); } -static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) { +static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { // This attribute must be applied to a function declaration. // The first argument to the attribute must be a string, // the name of the resource, for example "malloc". @@ -500,7 +515,7 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) { llvm_unreachable("Unknown ownership attribute"); } - if (!isFunction(d) || !hasFunctionProto(d)) { + if (!isFunction(D) || !hasFunctionProto(D)) { S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) << AL.getName() << ExpectedFunction; return; @@ -508,8 +523,8 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) { // In C++ the implicit 'this' function parameter also counts, and they are // counted from one. - bool HasImplicitThisParam = isInstanceMethod(d); - unsigned NumArgs = getFunctionOrMethodNumArgs(d) + HasImplicitThisParam; + bool HasImplicitThisParam = isInstanceMethod(D); + unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; llvm::StringRef Module = AL.getParameterName()->getName(); @@ -552,7 +567,7 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) { case OwnershipAttr::Takes: case OwnershipAttr::Holds: { // Is the function argument a pointer type? - QualType T = getFunctionOrMethodArgType(d, x); + QualType T = getFunctionOrMethodArgType(D, x); if (!T->isAnyPointerType() && !T->isBlockPointerType()) { // FIXME: Should also highlight argument in decl. S.Diag(AL.getLoc(), diag::err_ownership_type) @@ -584,8 +599,8 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) { // Check we don't have a conflict with another ownership attribute. for (specific_attr_iterator<OwnershipAttr> - i = d->specific_attr_begin<OwnershipAttr>(), - e = d->specific_attr_end<OwnershipAttr>(); + i = D->specific_attr_begin<OwnershipAttr>(), + e = D->specific_attr_end<OwnershipAttr>(); i != e; ++i) { if ((*i)->getOwnKind() != K) { for (const unsigned *I = (*i)->args_begin(), *E = (*i)->args_end(); @@ -609,7 +624,7 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) { return; } - d->addAttr(::new (S.Context) OwnershipAttr(AL.getLoc(), S.Context, K, Module, + D->addAttr(::new (S.Context) OwnershipAttr(AL.getLoc(), S.Context, K, Module, start, size)); } @@ -633,20 +648,20 @@ static bool hasEffectivelyInternalLinkage(NamedDecl *D) { return false; } -static void HandleWeakRefAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) { // Check the attribute arguments. if (Attr.getNumArgs() > 1) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; return; } - if (!isa<VarDecl>(d) && !isa<FunctionDecl>(d)) { + if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) << Attr.getName() << ExpectedVariableOrFunction; return; } - NamedDecl *nd = cast<NamedDecl>(d); + NamedDecl *nd = cast<NamedDecl>(D); // gcc rejects // class c { @@ -658,7 +673,7 @@ static void HandleWeakRefAttr(Decl *d, const AttributeList &Attr, Sema &S) { // static int a __attribute__((weakref ("v2"))); // } // we reject them - const DeclContext *Ctx = d->getDeclContext()->getRedeclContext(); + const DeclContext *Ctx = D->getDeclContext()->getRedeclContext(); if (!Ctx->isFileContext()) { S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) << nd->getNameAsString(); @@ -704,14 +719,14 @@ static void HandleWeakRefAttr(Decl *d, const AttributeList &Attr, Sema &S) { } // GCC will accept anything as the argument of weakref. Should we // check for an existing decl? - d->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context, + D->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context, Str->getString())); } - d->addAttr(::new (S.Context) WeakRefAttr(Attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) WeakRefAttr(Attr.getLoc(), S.Context)); } -static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. if (Attr.getNumArgs() != 1) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; @@ -735,55 +750,52 @@ static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { // FIXME: check if target symbol exists in current file - d->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context, + D->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context, Str->getString())); } -static void HandleNakedAttr(Decl *d, const AttributeList &Attr, - Sema &S) { +static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) { // Check the attribute arguments. - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } - if (!isa<FunctionDecl>(d)) { + if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; return; } - d->addAttr(::new (S.Context) NakedAttr(Attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) NakedAttr(Attr.getLoc(), S.Context)); } -static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, - Sema &S) { +static void handleAlwaysInlineAttr(Sema &S, Decl *D, + const AttributeList &Attr) { // Check the attribute arguments. if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } - if (!isa<FunctionDecl>(d)) { + if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; return; } - d->addAttr(::new (S.Context) AlwaysInlineAttr(Attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) AlwaysInlineAttr(Attr.getLoc(), S.Context)); } -static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) { // Check the attribute arguments. if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) { + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { QualType RetTy = FD->getResultType(); if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) { - d->addAttr(::new (S.Context) MallocAttr(Attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) MallocAttr(Attr.getLoc(), S.Context)); return; } } @@ -791,46 +803,44 @@ static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only); } -static void HandleMayAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleMayAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } - d->addAttr(::new (S.Context) MayAliasAttr(Attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) MayAliasAttr(Attr.getLoc(), S.Context)); } -static void HandleNoCommonAttr(Decl *d, const AttributeList &Attr, Sema &S) { - assert(Attr.isInvalid() == false); - if (isa<VarDecl>(d)) - d->addAttr(::new (S.Context) NoCommonAttr(Attr.getLoc(), S.Context)); +static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { + assert(!Attr.isInvalid()); + if (isa<VarDecl>(D)) + D->addAttr(::new (S.Context) NoCommonAttr(Attr.getLoc(), S.Context)); else S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedVariable; } -static void HandleCommonAttr(Decl *d, const AttributeList &Attr, Sema &S) { - assert(Attr.isInvalid() == false); - if (isa<VarDecl>(d)) - d->addAttr(::new (S.Context) CommonAttr(Attr.getLoc(), S.Context)); +static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { + assert(!Attr.isInvalid()); + if (isa<VarDecl>(D)) + D->addAttr(::new (S.Context) CommonAttr(Attr.getLoc(), S.Context)); else S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedVariable; } -static void HandleNoReturnAttr(Decl *d, const AttributeList &attr, Sema &S) { - if (hasDeclarator(d)) return; +static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) { + if (hasDeclarator(D)) return; if (S.CheckNoReturnAttr(attr)) return; - if (!isa<ObjCMethodDecl>(d)) { + if (!isa<ObjCMethodDecl>(D)) { S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) << attr.getName() << ExpectedFunctionOrMethod; return; } - d->addAttr(::new (S.Context) NoReturnAttr(attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) NoReturnAttr(attr.getLoc(), S.Context)); } bool Sema::CheckNoReturnAttr(const AttributeList &attr) { @@ -843,19 +853,17 @@ bool Sema::CheckNoReturnAttr(const AttributeList &attr) { return false; } -static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr, - Sema &S) { +static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, + const AttributeList &Attr) { // The checking path for 'noreturn' and 'analyzer_noreturn' are different // because 'analyzer_noreturn' does not impact the type. - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; - return; - } + if(!checkAttributeNumArgs(S, Attr, 0)) + return; - if (!isFunctionOrMethod(d) && !isa<BlockDecl>(d)) { - ValueDecl *VD = dyn_cast<ValueDecl>(d); + if (!isFunctionOrMethod(D) && !isa<BlockDecl>(D)) { + ValueDecl *VD = dyn_cast<ValueDecl>(D); if (VD == 0 || (!VD->getType()->isBlockPointerType() && !VD->getType()->isFunctionPointerType())) { S.Diag(Attr.getLoc(), @@ -866,12 +874,11 @@ static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr, } } - d->addAttr(::new (S.Context) AnalyzerNoReturnAttr(Attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) AnalyzerNoReturnAttr(Attr.getLoc(), S.Context)); } // PS3 PPU-specific. -static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr, - Sema &S) { +static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) { /* Returning a Vector Class in Registers @@ -895,18 +902,18 @@ static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr, return result; // This will be returned in a register } */ - if (!isa<RecordDecl>(d)) { + if (!isa<RecordDecl>(D)) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) << Attr.getName() << ExpectedClass; return; } - if (d->getAttr<VecReturnAttr>()) { + if (D->getAttr<VecReturnAttr>()) { S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "vecreturn"; return; } - RecordDecl *record = cast<RecordDecl>(d); + RecordDecl *record = cast<RecordDecl>(D); int count = 0; if (!isa<CXXRecordDecl>(record)) { @@ -928,11 +935,11 @@ static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr, count++; } - d->addAttr(::new (S.Context) VecReturnAttr(Attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) VecReturnAttr(Attr.getLoc(), S.Context)); } -static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) { - if (!isFunctionOrMethod(d) && !isa<ParmVarDecl>(d)) { +static void handleDependencyAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!isFunctionOrMethod(D) && !isa<ParmVarDecl>(D)) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunctionMethodOrParameter; return; @@ -940,45 +947,45 @@ static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) { // FIXME: Actually store the attribute on the declaration } -static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } - if (!isa<VarDecl>(d) && !isa<ObjCIvarDecl>(d) && !isFunctionOrMethod(d) && - !isa<TypeDecl>(d) && !isa<LabelDecl>(d)) { + if (!isa<VarDecl>(D) && !isa<ObjCIvarDecl>(D) && !isFunctionOrMethod(D) && + !isa<TypeDecl>(D) && !isa<LabelDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedVariableFunctionOrLabel; return; } - d->addAttr(::new (S.Context) UnusedAttr(Attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) UnusedAttr(Attr.getLoc(), S.Context)); } -static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } - if (const VarDecl *VD = dyn_cast<VarDecl>(d)) { + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (VD->hasLocalStorage() || VD->hasExternalStorage()) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "used"; return; } - } else if (!isFunctionOrMethod(d)) { + } else if (!isFunctionOrMethod(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedVariableOrFunction; return; } - d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context)); } -static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. if (Attr.getNumArgs() > 1) { S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; @@ -998,17 +1005,17 @@ static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { priority = Idx.getZExtValue(); } - if (!isa<FunctionDecl>(d)) { + if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; return; } - d->addAttr(::new (S.Context) ConstructorAttr(Attr.getLoc(), S.Context, + D->addAttr(::new (S.Context) ConstructorAttr(Attr.getLoc(), S.Context, priority)); } -static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. if (Attr.getNumArgs() > 1) { S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; @@ -1028,17 +1035,17 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { priority = Idx.getZExtValue(); } - if (!isa<FunctionDecl>(d)) { + if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; return; } - d->addAttr(::new (S.Context) DestructorAttr(Attr.getLoc(), S.Context, + D->addAttr(::new (S.Context) DestructorAttr(Attr.getLoc(), S.Context, priority)); } -static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleDeprecatedAttr(Sema &S, Decl *D, const AttributeList &Attr) { unsigned NumArgs = Attr.getNumArgs(); if (NumArgs > 1) { S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; @@ -1057,10 +1064,10 @@ static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { Str = SE->getString(); } - d->addAttr(::new (S.Context) DeprecatedAttr(Attr.getLoc(), S.Context, Str)); + D->addAttr(::new (S.Context) DeprecatedAttr(Attr.getLoc(), S.Context, Str)); } -static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleUnavailableAttr(Sema &S, Decl *D, const AttributeList &Attr) { unsigned NumArgs = Attr.getNumArgs(); if (NumArgs > 1) { S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; @@ -1078,11 +1085,23 @@ static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) { } Str = SE->getString(); } - d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context, Str)); + D->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context, Str)); +} + +static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + unsigned NumArgs = Attr.getNumArgs(); + if (NumArgs > 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0; + return; + } + + D->addAttr(::new (S.Context) ArcWeakrefUnavailableAttr( + Attr.getLoc(), S.Context)); } -static void HandleAvailabilityAttr(Decl *d, const AttributeList &Attr, - Sema &S) { +static void handleAvailabilityAttr(Sema &S, Decl *D, + const AttributeList &Attr) { IdentifierInfo *Platform = Attr.getParameterName(); SourceLocation PlatformLoc = Attr.getParameterLoc(); @@ -1126,7 +1145,7 @@ static void HandleAvailabilityAttr(Decl *d, const AttributeList &Attr, return; } - d->addAttr(::new (S.Context) AvailabilityAttr(Attr.getLoc(), S.Context, + D->addAttr(::new (S.Context) AvailabilityAttr(Attr.getLoc(), S.Context, Platform, Introduced.Version, Deprecated.Version, @@ -1134,12 +1153,10 @@ static void HandleAvailabilityAttr(Decl *d, const AttributeList &Attr, IsUnavailable)); } -static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. - if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + if(!checkAttributeNumArgs(S, Attr, 1)) return; - } Expr *Arg = Attr.getArg(0); Arg = Arg->IgnoreParenCasts(); @@ -1167,30 +1184,30 @@ static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) VisibilityAttr(Attr.getLoc(), S.Context, type)); + D->addAttr(::new (S.Context) VisibilityAttr(Attr.getLoc(), S.Context, type)); } -static void HandleObjCMethodFamilyAttr(Decl *decl, const AttributeList &attr, - Sema &S) { +static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl, + const AttributeList &Attr) { ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(decl); if (!method) { - S.Diag(attr.getLoc(), diag::err_attribute_wrong_decl_type) + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) << ExpectedMethod; return; } - if (attr.getNumArgs() != 0 || !attr.getParameterName()) { - if (!attr.getParameterName() && attr.getNumArgs() == 1) { - S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) + if (Attr.getNumArgs() != 0 || !Attr.getParameterName()) { + if (!Attr.getParameterName() && Attr.getNumArgs() == 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) << "objc_method_family" << 1; } else { - S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; } - attr.setInvalid(); + Attr.setInvalid(); return; } - llvm::StringRef param = attr.getParameterName()->getName(); + llvm::StringRef param = Attr.getParameterName()->getName(); ObjCMethodFamilyAttr::FamilyKind family; if (param == "none") family = ObjCMethodFamilyAttr::OMF_None; @@ -1207,20 +1224,26 @@ static void HandleObjCMethodFamilyAttr(Decl *decl, const AttributeList &attr, else { // Just warn and ignore it. This is future-proof against new // families being used in system headers. - S.Diag(attr.getParameterLoc(), diag::warn_unknown_method_family); + S.Diag(Attr.getParameterLoc(), diag::warn_unknown_method_family); return; } - decl->addAttr(new (S.Context) ObjCMethodFamilyAttr(attr.getLoc(), - S.Context, family)); + if (family == ObjCMethodFamilyAttr::OMF_init && + !method->getResultType()->isObjCObjectPointerType()) { + S.Diag(method->getLocation(), diag::err_init_method_bad_return_type) + << method->getResultType(); + // Ignore the attribute. + return; + } + + method->addAttr(new (S.Context) ObjCMethodFamilyAttr(Attr.getLoc(), + S.Context, family)); } -static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr, - Sema &S) { - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; +static void handleObjCExceptionAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D); if (OCI == 0) { @@ -1231,7 +1254,7 @@ static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr, D->addAttr(::new (S.Context) ObjCExceptionAttr(Attr.getLoc(), S.Context)); } -static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) { +static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) { if (Attr.getNumArgs() != 0) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; return; @@ -1248,7 +1271,7 @@ static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) { } static void -HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) { +handleOverloadableAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (Attr.getNumArgs() != 0) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; return; @@ -1262,7 +1285,7 @@ HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) { D->addAttr(::new (S.Context) OverloadableAttr(Attr.getLoc(), S.Context)); } -static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!Attr.getParameterName()) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) << "blocks" << 1; @@ -1283,10 +1306,10 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) BlocksAttr(Attr.getLoc(), S.Context, type)); + D->addAttr(::new (S.Context) BlocksAttr(Attr.getLoc(), S.Context, type)); } -static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. if (Attr.getNumArgs() > 2) { S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2; @@ -1333,7 +1356,7 @@ static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { } } - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { const FunctionType *FT = FD->getType()->getAs<FunctionType>(); assert(FT && "FunctionDecl has non-function type?"); @@ -1346,19 +1369,19 @@ static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; return; } - } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) { + } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { if (!MD->isVariadic()) { S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; return; } - } else if (isa<BlockDecl>(d)) { + } else if (isa<BlockDecl>(D)) { // Note! BlockDecl is typeless. Variadic diagnostics will be issued by the // caller. ; - } else if (const VarDecl *V = dyn_cast<VarDecl>(d)) { + } else if (const VarDecl *V = dyn_cast<VarDecl>(D)) { QualType Ty = V->getType(); if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) { - const FunctionType *FT = Ty->isFunctionPointerType() ? getFunctionType(d) + const FunctionType *FT = Ty->isFunctionPointerType() ? getFunctionType(D) : Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>(); if (!cast<FunctionProtoType>(FT)->isVariadic()) { int m = Ty->isFunctionPointerType() ? 0 : 1; @@ -1375,16 +1398,14 @@ static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { << Attr.getName() << ExpectedFunctionMethodOrBlock; return; } - d->addAttr(::new (S.Context) SentinelAttr(Attr.getLoc(), S.Context, sentinel, + D->addAttr(::new (S.Context) SentinelAttr(Attr.getLoc(), S.Context, sentinel, nullPos)); } -static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) { +static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } if (!isFunction(D) && !isa<ObjCMethodDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) @@ -1407,36 +1428,35 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) D->addAttr(::new (S.Context) WarnUnusedResultAttr(Attr.getLoc(), S.Context)); } -static void HandleWeakAttr(Decl *d, const AttributeList &attr, Sema &S) { +static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. - if (attr.hasParameterOrArguments()) { - S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (Attr.hasParameterOrArguments()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } - if (!isa<VarDecl>(d) && !isa<FunctionDecl>(d)) { - S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << attr.getName() << ExpectedVariableOrFunction; + if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariableOrFunction; return; } - NamedDecl *nd = cast<NamedDecl>(d); + 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); + S.Diag(Attr.getLoc(), diag::err_attribute_weak_static); return; } - nd->addAttr(::new (S.Context) WeakAttr(attr.getLoc(), S.Context)); + nd->addAttr(::new (S.Context) WeakAttr(Attr.getLoc(), S.Context)); } -static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { +static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } + // weak_import only applies to variable & function declarations. bool isDef = false; @@ -1459,13 +1479,11 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { D->addAttr(::new (S.Context) WeakImportAttr(Attr.getLoc(), S.Context)); } -static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr, - Sema &S) { +static void handleReqdWorkGroupSize(Sema &S, Decl *D, + const AttributeList &Attr) { // Attribute has 3 arguments. - if (Attr.getNumArgs() != 3) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + if (!checkAttributeNumArgs(S, Attr, 3)) return; - } unsigned WGSize[3]; for (unsigned i = 0; i < 3; ++i) { @@ -1484,12 +1502,10 @@ static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr, WGSize[2])); } -static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) { +static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) { // Attribute has no arguments. - if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + if (!checkAttributeNumArgs(S, Attr, 1)) return; - } // Make sure that there is a string literal as the sections's single // argument. @@ -1519,37 +1535,45 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) { } -static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleNothrowAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } - - d->addAttr(::new (S.Context) NoThrowAttr(Attr.getLoc(), S.Context)); + + if (NoThrowAttr *Existing = D->getAttr<NoThrowAttr>()) { + if (Existing->getLocation().isInvalid()) + Existing->setLocation(Attr.getLoc()); + } else { + D->addAttr(::new (S.Context) NoThrowAttr(Attr.getLoc(), S.Context)); + } } -static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleConstAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } - d->addAttr(::new (S.Context) ConstAttr(Attr.getLoc(), S.Context)); + if (ConstAttr *Existing = D->getAttr<ConstAttr>()) { + if (Existing->getLocation().isInvalid()) + Existing->setLocation(Attr.getLoc()); + } else { + D->addAttr(::new (S.Context) ConstAttr(Attr.getLoc(), S.Context)); + } } -static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handlePureAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } - d->addAttr(::new (S.Context) PureAttr(Attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) PureAttr(Attr.getLoc(), S.Context)); } -static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!Attr.getParameterName()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; return; @@ -1560,7 +1584,7 @@ static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - VarDecl *VD = dyn_cast<VarDecl>(d); + VarDecl *VD = dyn_cast<VarDecl>(D); if (!VD || !VD->hasLocalStorage()) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup"; @@ -1605,18 +1629,17 @@ static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) CleanupAttr(Attr.getLoc(), S.Context, FD)); + D->addAttr(::new (S.Context) CleanupAttr(Attr.getLoc(), S.Context, FD)); S.MarkDeclarationReferenced(Attr.getParameterLoc(), FD); } /// Handle __attribute__((format_arg((idx)))) attribute based on /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html -static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) { - if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; +static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!checkAttributeNumArgs(S, Attr, 1)) return; - } - if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) { + + if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; return; @@ -1624,8 +1647,8 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) { // In C++ the implicit 'this' function parameter also counts, and they are // counted from one. - bool HasImplicitThisParam = isInstanceMethod(d); - unsigned NumArgs = getFunctionOrMethodNumArgs(d) + HasImplicitThisParam; + bool HasImplicitThisParam = isInstanceMethod(D); + unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; unsigned FirstIdx = 1; // checks for the 2nd argument @@ -1656,7 +1679,7 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) { } // make sure the format string is really a string - QualType Ty = getFunctionOrMethodArgType(d, ArgIdx); + QualType Ty = getFunctionOrMethodArgType(D, ArgIdx); bool not_nsstring_type = !isNSStringType(Ty, S.Context); if (not_nsstring_type && @@ -1669,7 +1692,7 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) { << IdxExpr->getSourceRange(); return; } - Ty = getFunctionOrMethodResultType(d); + Ty = getFunctionOrMethodResultType(D); if (!isNSStringType(Ty, S.Context) && !isCFStringType(Ty, S.Context) && (!Ty->isPointerType() || @@ -1681,7 +1704,7 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) FormatArgAttr(Attr.getLoc(), S.Context, + D->addAttr(::new (S.Context) FormatArgAttr(Attr.getLoc(), S.Context, Idx.getZExtValue())); } @@ -1722,19 +1745,19 @@ static FormatAttrKind getFormatAttrKind(llvm::StringRef Format) { /// Handle __attribute__((init_priority(priority))) attributes based on /// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html -static void HandleInitPriorityAttr(Decl *d, const AttributeList &Attr, - Sema &S) { +static void handleInitPriorityAttr(Sema &S, Decl *D, + const AttributeList &Attr) { if (!S.getLangOptions().CPlusPlus) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); return; } - if (!isa<VarDecl>(d) || S.getCurFunctionOrMethodDecl()) { + if (!isa<VarDecl>(D) || S.getCurFunctionOrMethodDecl()) { S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr); Attr.setInvalid(); return; } - QualType T = dyn_cast<VarDecl>(d)->getType(); + QualType T = dyn_cast<VarDecl>(D)->getType(); if (S.Context.getAsArrayType(T)) T = S.Context.getBaseElementType(T); if (!T->getAs<RecordType>()) { @@ -1765,13 +1788,13 @@ static void HandleInitPriorityAttr(Decl *d, const AttributeList &Attr, Attr.setInvalid(); return; } - d->addAttr(::new (S.Context) InitPriorityAttr(Attr.getLoc(), S.Context, + D->addAttr(::new (S.Context) InitPriorityAttr(Attr.getLoc(), S.Context, prioritynum)); } /// Handle __attribute__((format(type,idx,firstarg))) attributes based on /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html -static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!Attr.getParameterName()) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) @@ -1784,7 +1807,7 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - if (!isFunctionOrMethodOrBlock(d) || !hasFunctionProto(d)) { + if (!isFunctionOrMethodOrBlock(D) || !hasFunctionProto(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; return; @@ -1792,8 +1815,8 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { // In C++ the implicit 'this' function parameter also counts, and they are // counted from one. - bool HasImplicitThisParam = isInstanceMethod(d); - unsigned NumArgs = getFunctionOrMethodNumArgs(d) + HasImplicitThisParam; + bool HasImplicitThisParam = isInstanceMethod(D); + unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; unsigned FirstIdx = 1; llvm::StringRef Format = Attr.getParameterName()->getName(); @@ -1844,7 +1867,7 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { } // make sure the format string is really a string - QualType Ty = getFunctionOrMethodArgType(d, ArgIdx); + QualType Ty = getFunctionOrMethodArgType(D, ArgIdx); if (Kind == CFStringFormat) { if (!isCFStringType(Ty, S.Context)) { @@ -1881,10 +1904,10 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check if the function is variadic if the 3rd argument non-zero if (FirstArg != 0) { - if (isFunctionOrMethodVariadic(d)) { + if (isFunctionOrMethodVariadic(D)) { ++NumArgs; // +1 for ... } else { - S.Diag(d->getLocation(), diag::err_format_attribute_requires_variadic); + S.Diag(D->getLocation(), diag::err_format_attribute_requires_variadic); return; } } @@ -1904,26 +1927,42 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) FormatAttr(Attr.getLoc(), S.Context, Format, + // Check whether we already have an equivalent format attribute. + for (specific_attr_iterator<FormatAttr> + i = D->specific_attr_begin<FormatAttr>(), + e = D->specific_attr_end<FormatAttr>(); + i != e ; ++i) { + FormatAttr *f = *i; + if (f->getType() == Format && + f->getFormatIdx() == (int)Idx.getZExtValue() && + f->getFirstArg() == (int)FirstArg.getZExtValue()) { + // If we don't have a valid location for this attribute, adopt the + // location. + if (f->getLocation().isInvalid()) + f->setLocation(Attr.getLoc()); + return; + } + } + + D->addAttr(::new (S.Context) FormatAttr(Attr.getLoc(), S.Context, Format, Idx.getZExtValue(), FirstArg.getZExtValue())); } -static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, - Sema &S) { +static void handleTransparentUnionAttr(Sema &S, Decl *D, + const AttributeList &Attr) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } + // Try to find the underlying union declaration. RecordDecl *RD = 0; - TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(d); + TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D); if (TD && TD->getUnderlyingType()->isUnionType()) RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); else - RD = dyn_cast<RecordDecl>(d); + RD = dyn_cast<RecordDecl>(D); if (!RD || !RD->isUnion()) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) @@ -1977,12 +2016,11 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, RD->addAttr(::new (S.Context) TransparentUnionAttr(Attr.getLoc(), S.Context)); } -static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. - if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + if (!checkAttributeNumArgs(S, Attr, 1)) return; - } + Expr *ArgExpr = Attr.getArg(0); StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr); @@ -1992,11 +2030,11 @@ static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate"; return; } - d->addAttr(::new (S.Context) AnnotateAttr(Attr.getLoc(), S.Context, + D->addAttr(::new (S.Context) AnnotateAttr(Attr.getLoc(), S.Context, SE->getString())); } -static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) { +static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. if (Attr.getNumArgs() > 1) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; @@ -2045,21 +2083,20 @@ void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, TypeSourceInfo *TS) { return; } -/// HandleModeAttr - This attribute modifies the width of a decl with primitive +/// handleModeAttr - This attribute modifies the width of a decl with primitive /// type. /// /// Despite what would be logical, the mode attribute is a decl attribute, not a /// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be /// HImode, not an intermediate pointer. -static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { +static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { // This attribute isn't documented, but glibc uses it. It changes // the width of an int or unsigned int to the specified size. // Check that there aren't any arguments - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } + IdentifierInfo *Name = Attr.getParameterName(); if (!Name) { @@ -2216,57 +2253,53 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { cast<ValueDecl>(D)->setType(NewTy); } -static void HandleNoDebugAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. - if (Attr.getNumArgs() > 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } - if (!isFunctionOrMethod(d)) { + if (!isFunctionOrMethod(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; return; } - d->addAttr(::new (S.Context) NoDebugAttr(Attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) NoDebugAttr(Attr.getLoc(), S.Context)); } -static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } - if (!isa<FunctionDecl>(d)) { + + if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; return; } - d->addAttr(::new (S.Context) NoInlineAttr(Attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) NoInlineAttr(Attr.getLoc(), S.Context)); } -static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr, - Sema &S) { +static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D, + const AttributeList &Attr) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } - if (!isa<FunctionDecl>(d)) { + + if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; return; } - d->addAttr(::new (S.Context) NoInstrumentFunctionAttr(Attr.getLoc(), + D->addAttr(::new (S.Context) NoInstrumentFunctionAttr(Attr.getLoc(), S.Context)); } -static void HandleConstantAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.LangOpts.CUDA) { // check the attribute arguments. if (Attr.hasParameterOrArguments()) { @@ -2274,19 +2307,19 @@ static void HandleConstantAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - if (!isa<VarDecl>(d)) { + if (!isa<VarDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedVariable; return; } - d->addAttr(::new (S.Context) CUDAConstantAttr(Attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) CUDAConstantAttr(Attr.getLoc(), S.Context)); } else { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "constant"; } } -static void HandleDeviceAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.LangOpts.CUDA) { // check the attribute arguments. if (Attr.getNumArgs() != 0) { @@ -2294,33 +2327,31 @@ static void HandleDeviceAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - if (!isa<FunctionDecl>(d) && !isa<VarDecl>(d)) { + if (!isa<FunctionDecl>(D) && !isa<VarDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedVariableOrFunction; return; } - d->addAttr(::new (S.Context) CUDADeviceAttr(Attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) CUDADeviceAttr(Attr.getLoc(), S.Context)); } else { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "device"; } } -static void HandleGlobalAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.LangOpts.CUDA) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } - if (!isa<FunctionDecl>(d)) { + if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; return; } - FunctionDecl *FD = cast<FunctionDecl>(d); + FunctionDecl *FD = cast<FunctionDecl>(D); if (!FD->getResultType()->isVoidType()) { TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens(); if (FunctionTypeLoc* FTL = dyn_cast<FunctionTypeLoc>(&TL)) { @@ -2335,60 +2366,56 @@ static void HandleGlobalAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) CUDAGlobalAttr(Attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) CUDAGlobalAttr(Attr.getLoc(), S.Context)); } else { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "global"; } } -static void HandleHostAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.LangOpts.CUDA) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } - if (!isa<FunctionDecl>(d)) { + + if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; return; } - d->addAttr(::new (S.Context) CUDAHostAttr(Attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) CUDAHostAttr(Attr.getLoc(), S.Context)); } else { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "host"; } } -static void HandleSharedAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.LangOpts.CUDA) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } - if (!isa<VarDecl>(d)) { + + 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.getLoc(), S.Context)); + D->addAttr(::new (S.Context) CUDASharedAttr(Attr.getLoc(), S.Context)); } else { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "shared"; } } -static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } - FunctionDecl *Fn = dyn_cast<FunctionDecl>(d); + FunctionDecl *Fn = dyn_cast<FunctionDecl>(D); if (Fn == 0) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; @@ -2400,47 +2427,47 @@ static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) GNUInlineAttr(Attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) GNUInlineAttr(Attr.getLoc(), S.Context)); } -static void HandleCallConvAttr(Decl *d, const AttributeList &attr, Sema &S) { - if (hasDeclarator(d)) return; +static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (hasDeclarator(D)) return; - // Diagnostic is emitted elsewhere: here we store the (valid) attr + // 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)) return; - if (!isa<ObjCMethodDecl>(d)) { - S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << attr.getName() << ExpectedFunctionOrMethod; + if (!isa<ObjCMethodDecl>(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; return; } - switch (attr.getKind()) { + switch (Attr.getKind()) { case AttributeList::AT_fastcall: - d->addAttr(::new (S.Context) FastCallAttr(attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) FastCallAttr(Attr.getLoc(), S.Context)); return; case AttributeList::AT_stdcall: - d->addAttr(::new (S.Context) StdCallAttr(attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) StdCallAttr(Attr.getLoc(), S.Context)); return; case AttributeList::AT_thiscall: - d->addAttr(::new (S.Context) ThisCallAttr(attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) ThisCallAttr(Attr.getLoc(), S.Context)); return; case AttributeList::AT_cdecl: - d->addAttr(::new (S.Context) CDeclAttr(attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) CDeclAttr(Attr.getLoc(), S.Context)); return; case AttributeList::AT_pascal: - d->addAttr(::new (S.Context) PascalAttr(attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) PascalAttr(Attr.getLoc(), S.Context)); return; case AttributeList::AT_pcs: { - Expr *Arg = attr.getArg(0); + Expr *Arg = Attr.getArg(0); StringLiteral *Str = dyn_cast<StringLiteral>(Arg); if (Str == 0 || Str->isWide()) { - S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) << "pcs" << 1; - attr.setInvalid(); + Attr.setInvalid(); return; } @@ -2451,12 +2478,12 @@ static void HandleCallConvAttr(Decl *d, const AttributeList &attr, Sema &S) { else if (StrRef == "aapcs-vfp") PCS = PcsAttr::AAPCS_VFP; else { - S.Diag(attr.getLoc(), diag::err_invalid_pcs); - attr.setInvalid(); + S.Diag(Attr.getLoc(), diag::err_invalid_pcs); + Attr.setInvalid(); return; } - d->addAttr(::new (S.Context) PcsAttr(attr.getLoc(), S.Context, PCS)); + D->addAttr(::new (S.Context) PcsAttr(Attr.getLoc(), S.Context, PCS)); } default: llvm_unreachable("unexpected attribute kind"); @@ -2464,9 +2491,9 @@ static void HandleCallConvAttr(Decl *d, const AttributeList &attr, Sema &S) { } } -static void HandleOpenCLKernelAttr(Decl *d, const AttributeList &Attr, Sema &S){ - assert(Attr.isInvalid() == false); - d->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getLoc(), S.Context)); +static void handleOpenCLKernelAttr(Sema &S, Decl *D, const AttributeList &Attr){ + assert(!Attr.isInvalid()); + D->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getLoc(), S.Context)); } bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) { @@ -2515,63 +2542,63 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) { return false; } -static void HandleRegparmAttr(Decl *d, const AttributeList &attr, Sema &S) { - if (hasDeclarator(d)) return; +static void handleRegparmAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (hasDeclarator(D)) return; unsigned numParams; - if (S.CheckRegparmAttr(attr, numParams)) + if (S.CheckRegparmAttr(Attr, numParams)) return; - if (!isa<ObjCMethodDecl>(d)) { - S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << attr.getName() << ExpectedFunctionOrMethod; + if (!isa<ObjCMethodDecl>(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; return; } - d->addAttr(::new (S.Context) RegparmAttr(attr.getLoc(), S.Context, numParams)); + D->addAttr(::new (S.Context) RegparmAttr(Attr.getLoc(), S.Context, numParams)); } /// Checks a regparm attribute, returning true if it is ill-formed and /// otherwise setting numParams to the appropriate value. -bool Sema::CheckRegparmAttr(const AttributeList &attr, unsigned &numParams) { - if (attr.isInvalid()) +bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) { + if (Attr.isInvalid()) return true; - if (attr.getNumArgs() != 1) { - Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; - attr.setInvalid(); + if (Attr.getNumArgs() != 1) { + Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + Attr.setInvalid(); return true; } - Expr *NumParamsExpr = attr.getArg(0); + Expr *NumParamsExpr = Attr.getArg(0); llvm::APSInt NumParams(32); if (NumParamsExpr->isTypeDependent() || NumParamsExpr->isValueDependent() || !NumParamsExpr->isIntegerConstantExpr(NumParams, Context)) { - Diag(attr.getLoc(), diag::err_attribute_argument_not_int) + Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) << "regparm" << NumParamsExpr->getSourceRange(); - attr.setInvalid(); + Attr.setInvalid(); return true; } if (Context.Target.getRegParmMax() == 0) { - Diag(attr.getLoc(), diag::err_attribute_regparm_wrong_platform) + Diag(Attr.getLoc(), diag::err_attribute_regparm_wrong_platform) << NumParamsExpr->getSourceRange(); - attr.setInvalid(); + Attr.setInvalid(); return true; } numParams = NumParams.getZExtValue(); if (numParams > Context.Target.getRegParmMax()) { - Diag(attr.getLoc(), diag::err_attribute_regparm_invalid_number) + Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number) << Context.Target.getRegParmMax() << NumParamsExpr->getSourceRange(); - attr.setInvalid(); + Attr.setInvalid(); return true; } return false; } -static void HandleLaunchBoundsAttr(Decl *d, const AttributeList &Attr, Sema &S){ +static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){ if (S.LangOpts.CUDA) { // check the attribute arguments. if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) { @@ -2580,7 +2607,7 @@ static void HandleLaunchBoundsAttr(Decl *d, const AttributeList &Attr, Sema &S){ return; } - if (!isFunctionOrMethod(d)) { + if (!isFunctionOrMethod(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunctionOrMethod; return; @@ -2608,7 +2635,7 @@ static void HandleLaunchBoundsAttr(Decl *d, const AttributeList &Attr, Sema &S){ } } - d->addAttr(::new (S.Context) CUDALaunchBoundsAttr(Attr.getLoc(), S.Context, + D->addAttr(::new (S.Context) CUDALaunchBoundsAttr(Attr.getLoc(), S.Context, MaxThreads.getZExtValue(), MinBlocks.getZExtValue())); } else { @@ -2627,16 +2654,16 @@ static bool isValidSubjectOfCFAttribute(Sema &S, QualType type) { return type->isPointerType() || isValidSubjectOfNSAttribute(S, type); } -static void HandleNSConsumedAttr(Decl *d, const AttributeList &attr, Sema &S) { - ParmVarDecl *param = dyn_cast<ParmVarDecl>(d); +static void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) { + ParmVarDecl *param = dyn_cast<ParmVarDecl>(D); if (!param) { - S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type) - << SourceRange(attr.getLoc()) << attr.getName() << ExpectedParameter; + S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type) + << SourceRange(Attr.getLoc()) << Attr.getName() << ExpectedParameter; return; } bool typeOK, cf; - if (attr.getKind() == AttributeList::AT_ns_consumed) { + if (Attr.getKind() == AttributeList::AT_ns_consumed) { typeOK = isValidSubjectOfNSAttribute(S, param->getType()); cf = false; } else { @@ -2645,47 +2672,52 @@ static void HandleNSConsumedAttr(Decl *d, const AttributeList &attr, Sema &S) { } if (!typeOK) { - S.Diag(d->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type) - << SourceRange(attr.getLoc()) << attr.getName() << cf; + S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type) + << SourceRange(Attr.getLoc()) << Attr.getName() << cf; return; } if (cf) - param->addAttr(::new (S.Context) CFConsumedAttr(attr.getLoc(), S.Context)); + param->addAttr(::new (S.Context) CFConsumedAttr(Attr.getLoc(), S.Context)); else - param->addAttr(::new (S.Context) NSConsumedAttr(attr.getLoc(), S.Context)); + param->addAttr(::new (S.Context) NSConsumedAttr(Attr.getLoc(), S.Context)); } -static void HandleNSConsumesSelfAttr(Decl *d, const AttributeList &attr, - Sema &S) { - if (!isa<ObjCMethodDecl>(d)) { - S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type) - << SourceRange(attr.getLoc()) << attr.getName() << ExpectedMethod; +static void handleNSConsumesSelfAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!isa<ObjCMethodDecl>(D)) { + S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type) + << SourceRange(Attr.getLoc()) << Attr.getName() << ExpectedMethod; return; } - d->addAttr(::new (S.Context) NSConsumesSelfAttr(attr.getLoc(), S.Context)); + D->addAttr(::new (S.Context) NSConsumesSelfAttr(Attr.getLoc(), S.Context)); } -static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &attr, - Sema &S) { +static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, + const AttributeList &Attr) { QualType returnType; - if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) + if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) returnType = MD->getResultType(); - else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) + else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) + returnType = PD->getType(); + else if (S.getLangOptions().ObjCAutoRefCount && hasDeclarator(D) && + (Attr.getKind() == AttributeList::AT_ns_returns_retained)) + return; // ignore: was handled as a type attribute + else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) returnType = FD->getResultType(); else { - S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type) - << SourceRange(attr.getLoc()) << attr.getName() + S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type) + << SourceRange(Attr.getLoc()) << Attr.getName() << ExpectedFunctionOrMethod; return; } bool typeOK; bool cf; - switch (attr.getKind()) { + switch (Attr.getKind()) { default: llvm_unreachable("invalid ownership attribute"); return; case AttributeList::AT_ns_returns_autoreleased: case AttributeList::AT_ns_returns_retained: @@ -2702,39 +2734,95 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &attr, } if (!typeOK) { - S.Diag(d->getLocStart(), diag::warn_ns_attribute_wrong_return_type) - << SourceRange(attr.getLoc()) - << attr.getName() << isa<ObjCMethodDecl>(d) << cf; + S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type) + << SourceRange(Attr.getLoc()) + << Attr.getName() << isa<ObjCMethodDecl>(D) << cf; return; } - switch (attr.getKind()) { + switch (Attr.getKind()) { default: assert(0 && "invalid ownership attribute"); return; case AttributeList::AT_ns_returns_autoreleased: - d->addAttr(::new (S.Context) NSReturnsAutoreleasedAttr(attr.getLoc(), + D->addAttr(::new (S.Context) NSReturnsAutoreleasedAttr(Attr.getLoc(), S.Context)); return; case AttributeList::AT_cf_returns_not_retained: - d->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(attr.getLoc(), + D->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(Attr.getLoc(), S.Context)); return; case AttributeList::AT_ns_returns_not_retained: - d->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(attr.getLoc(), + D->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(Attr.getLoc(), S.Context)); return; case AttributeList::AT_cf_returns_retained: - d->addAttr(::new (S.Context) CFReturnsRetainedAttr(attr.getLoc(), + D->addAttr(::new (S.Context) CFReturnsRetainedAttr(Attr.getLoc(), S.Context)); return; case AttributeList::AT_ns_returns_retained: - d->addAttr(::new (S.Context) NSReturnsRetainedAttr(attr.getLoc(), + D->addAttr(::new (S.Context) NSReturnsRetainedAttr(Attr.getLoc(), S.Context)); return; }; } +static void handleObjCOwnershipAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (hasDeclarator(D)) return; + + SourceLocation L = Attr.getLoc(); + S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) + << SourceRange(L, L) << Attr.getName() << 12 /* variable */; +} + +static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!isa<VarDecl>(D) && !isa<FieldDecl>(D)) { + SourceLocation L = Attr.getLoc(); + S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) + << SourceRange(L, L) << Attr.getName() << 12 /* variable */; + return; + } + + ValueDecl *vd = cast<ValueDecl>(D); + QualType type = vd->getType(); + + if (!type->isDependentType() && + !type->isObjCLifetimeType()) { + S.Diag(Attr.getLoc(), diag::err_objc_precise_lifetime_bad_type) + << type; + return; + } + + Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime(); + + // If we have no lifetime yet, check the lifetime we're presumably + // going to infer. + if (lifetime == Qualifiers::OCL_None && !type->isDependentType()) + lifetime = type->getObjCARCImplicitLifetime(); + + switch (lifetime) { + case Qualifiers::OCL_None: + assert(type->isDependentType() && + "didn't infer lifetime for non-dependent type?"); + break; + + case Qualifiers::OCL_Weak: // meaningful + case Qualifiers::OCL_Strong: // meaningful + break; + + case Qualifiers::OCL_ExplicitNone: + case Qualifiers::OCL_Autoreleasing: + S.Diag(Attr.getLoc(), diag::warn_objc_precise_lifetime_meaningless) + << (lifetime == Qualifiers::OCL_Autoreleasing); + break; + } + + D->addAttr(::new (S.Context) + ObjCPreciseLifetimeAttr(Attr.getLoc(), S.Context)); +} + static bool isKnownDeclSpecAttr(const AttributeList &Attr) { return Attr.getKind() == AttributeList::AT_dllimport || Attr.getKind() == AttributeList::AT_dllexport || @@ -2745,13 +2833,12 @@ static bool isKnownDeclSpecAttr(const AttributeList &Attr) { // Microsoft specific attribute handlers. //===----------------------------------------------------------------------===// -static void HandleUuidAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.LangOpts.Microsoft || S.LangOpts.Borland) { // check the attribute arguments. - if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + if (!checkAttributeNumArgs(S, Attr, 1)) return; - } + Expr *Arg = Attr.getArg(0); StringLiteral *Str = dyn_cast<StringLiteral>(Arg); if (Str == 0 || Str->isWide()) { @@ -2794,7 +2881,7 @@ static void HandleUuidAttr(Decl *d, const AttributeList &Attr, Sema &S) { I++; } - d->addAttr(::new (S.Context) UuidAttr(Attr.getLoc(), S.Context, + D->addAttr(::new (S.Context) UuidAttr(Attr.getLoc(), S.Context, Str->getString())); } else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "uuid"; @@ -2804,24 +2891,24 @@ static void HandleUuidAttr(Decl *d, const AttributeList &Attr, Sema &S) { // Top Level Sema Entry Points //===----------------------------------------------------------------------===// -static void ProcessNonInheritableDeclAttr(Scope *scope, Decl *D, - const AttributeList &Attr, Sema &S) { +static void ProcessNonInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, + const AttributeList &Attr) { switch (Attr.getKind()) { - case AttributeList::AT_device: HandleDeviceAttr (D, Attr, S); break; - case AttributeList::AT_host: HandleHostAttr (D, Attr, S); break; - case AttributeList::AT_overloadable:HandleOverloadableAttr(D, Attr, S); break; + case AttributeList::AT_device: handleDeviceAttr (S, D, Attr); break; + case AttributeList::AT_host: handleHostAttr (S, D, Attr); break; + case AttributeList::AT_overloadable:handleOverloadableAttr(S, D, Attr); break; default: break; } } -static void ProcessInheritableDeclAttr(Scope *scope, Decl *D, - const AttributeList &Attr, Sema &S) { +static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, + const AttributeList &Attr) { switch (Attr.getKind()) { - case AttributeList::AT_IBAction: HandleIBAction(D, Attr, S); break; - case AttributeList::AT_IBOutlet: HandleIBOutlet(D, Attr, S); break; + case AttributeList::AT_IBAction: handleIBAction(S, D, Attr); break; + case AttributeList::AT_IBOutlet: handleIBOutlet(S, D, Attr); break; case AttributeList::AT_IBOutletCollection: - HandleIBOutletCollection(D, Attr, S); break; + handleIBOutletCollection(S, D, Attr); break; case AttributeList::AT_address_space: case AttributeList::AT_opencl_image_access: case AttributeList::AT_objc_gc: @@ -2837,100 +2924,108 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D, // Ignore, this is a non-inheritable attribute, handled // by ProcessNonInheritableDeclAttr. break; - case AttributeList::AT_alias: HandleAliasAttr (D, Attr, S); break; - case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break; + case AttributeList::AT_alias: handleAliasAttr (S, D, Attr); break; + case AttributeList::AT_aligned: handleAlignedAttr (S, D, Attr); break; case AttributeList::AT_always_inline: - HandleAlwaysInlineAttr (D, Attr, S); break; + handleAlwaysInlineAttr (S, D, Attr); break; 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; + handleAnalyzerNoReturnAttr (S, D, Attr); break; + case AttributeList::AT_annotate: handleAnnotateAttr (S, D, Attr); break; + case AttributeList::AT_availability:handleAvailabilityAttr(S, D, Attr); break; case AttributeList::AT_carries_dependency: - HandleDependencyAttr (D, Attr, S); break; - case AttributeList::AT_common: HandleCommonAttr (D, Attr, S); break; - case AttributeList::AT_constant: HandleConstantAttr (D, Attr, S); break; - case AttributeList::AT_constructor: HandleConstructorAttr (D, Attr, S); break; - case AttributeList::AT_deprecated: HandleDeprecatedAttr (D, Attr, S); break; - case AttributeList::AT_destructor: HandleDestructorAttr (D, Attr, S); break; + handleDependencyAttr (S, D, Attr); break; + case AttributeList::AT_common: handleCommonAttr (S, D, Attr); break; + case AttributeList::AT_constant: handleConstantAttr (S, D, Attr); break; + case AttributeList::AT_constructor: handleConstructorAttr (S, D, Attr); break; + case AttributeList::AT_deprecated: handleDeprecatedAttr (S, D, Attr); break; + case AttributeList::AT_destructor: handleDestructorAttr (S, D, Attr); break; case AttributeList::AT_ext_vector_type: - HandleExtVectorTypeAttr(scope, D, Attr, S); + handleExtVectorTypeAttr(S, scope, D, Attr); break; - case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break; - case AttributeList::AT_format_arg: HandleFormatArgAttr (D, Attr, S); break; - case AttributeList::AT_global: HandleGlobalAttr (D, Attr, S); break; - case AttributeList::AT_gnu_inline: HandleGNUInlineAttr (D, Attr, S); break; + case AttributeList::AT_format: handleFormatAttr (S, D, Attr); break; + case AttributeList::AT_format_arg: handleFormatArgAttr (S, D, Attr); break; + case AttributeList::AT_global: handleGlobalAttr (S, D, Attr); break; + case AttributeList::AT_gnu_inline: handleGNUInlineAttr (S, D, Attr); break; case AttributeList::AT_launch_bounds: - HandleLaunchBoundsAttr(D, Attr, S); + handleLaunchBoundsAttr(S, D, Attr); break; - case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break; - case AttributeList::AT_malloc: HandleMallocAttr (D, Attr, S); break; - case AttributeList::AT_may_alias: HandleMayAliasAttr (D, Attr, S); break; - case AttributeList::AT_nocommon: HandleNoCommonAttr (D, Attr, S); break; - case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break; + case AttributeList::AT_mode: handleModeAttr (S, D, Attr); break; + case AttributeList::AT_malloc: handleMallocAttr (S, D, Attr); break; + case AttributeList::AT_may_alias: handleMayAliasAttr (S, D, Attr); break; + case AttributeList::AT_nocommon: handleNoCommonAttr (S, D, Attr); break; + case AttributeList::AT_nonnull: handleNonNullAttr (S, D, Attr); break; case AttributeList::AT_ownership_returns: case AttributeList::AT_ownership_takes: case AttributeList::AT_ownership_holds: - HandleOwnershipAttr (D, Attr, S); break; - case AttributeList::AT_naked: HandleNakedAttr (D, Attr, S); break; - case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break; - case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break; - case AttributeList::AT_shared: HandleSharedAttr (D, Attr, S); break; - case AttributeList::AT_vecreturn: HandleVecReturnAttr (D, Attr, S); break; + handleOwnershipAttr (S, D, Attr); break; + case AttributeList::AT_naked: handleNakedAttr (S, D, Attr); break; + case AttributeList::AT_noreturn: handleNoReturnAttr (S, D, Attr); break; + case AttributeList::AT_nothrow: handleNothrowAttr (S, D, Attr); break; + case AttributeList::AT_shared: handleSharedAttr (S, D, Attr); break; + case AttributeList::AT_vecreturn: handleVecReturnAttr (S, D, Attr); break; + + case AttributeList::AT_objc_ownership: + handleObjCOwnershipAttr(S, D, Attr); break; + case AttributeList::AT_objc_precise_lifetime: + handleObjCPreciseLifetimeAttr(S, D, Attr); break; // Checker-specific. case AttributeList::AT_cf_consumed: - case AttributeList::AT_ns_consumed: HandleNSConsumedAttr (D, Attr, S); break; + case AttributeList::AT_ns_consumed: handleNSConsumedAttr (S, D, Attr); break; case AttributeList::AT_ns_consumes_self: - HandleNSConsumesSelfAttr(D, Attr, S); break; + handleNSConsumesSelfAttr(S, D, Attr); break; case AttributeList::AT_ns_returns_autoreleased: case AttributeList::AT_ns_returns_not_retained: case AttributeList::AT_cf_returns_not_retained: case AttributeList::AT_ns_returns_retained: case AttributeList::AT_cf_returns_retained: - HandleNSReturnsRetainedAttr(D, Attr, S); break; + handleNSReturnsRetainedAttr(S, D, Attr); break; case AttributeList::AT_reqd_wg_size: - HandleReqdWorkGroupSize(D, Attr, S); break; + handleReqdWorkGroupSize(S, D, Attr); break; case AttributeList::AT_init_priority: - HandleInitPriorityAttr(D, Attr, S); break; + handleInitPriorityAttr(S, D, Attr); break; - case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break; - case AttributeList::AT_MsStruct: HandleMsStructAttr (D, Attr, S); break; - case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break; - case AttributeList::AT_unavailable: HandleUnavailableAttr (D, Attr, S); break; - case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break; - case AttributeList::AT_used: HandleUsedAttr (D, Attr, S); break; - case AttributeList::AT_visibility: HandleVisibilityAttr (D, Attr, S); break; - case AttributeList::AT_warn_unused_result: HandleWarnUnusedResult(D,Attr,S); + case AttributeList::AT_packed: handlePackedAttr (S, D, Attr); break; + case AttributeList::AT_MsStruct: handleMsStructAttr (S, D, Attr); break; + case AttributeList::AT_section: handleSectionAttr (S, D, Attr); break; + case AttributeList::AT_unavailable: handleUnavailableAttr (S, D, Attr); break; + case AttributeList::AT_arc_weakref_unavailable: + handleArcWeakrefUnavailableAttr (S, D, Attr); break; - case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break; - case AttributeList::AT_weakref: HandleWeakRefAttr (D, Attr, S); break; - case AttributeList::AT_weak_import: HandleWeakImportAttr (D, Attr, S); break; + case AttributeList::AT_unused: handleUnusedAttr (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_warn_unused_result: handleWarnUnusedResult(S, D, Attr); + break; + case AttributeList::AT_weak: handleWeakAttr (S, D, Attr); break; + case AttributeList::AT_weakref: handleWeakRefAttr (S, D, Attr); break; + case AttributeList::AT_weak_import: handleWeakImportAttr (S, D, Attr); break; case AttributeList::AT_transparent_union: - HandleTransparentUnionAttr(D, Attr, S); + handleTransparentUnionAttr(S, D, Attr); break; case AttributeList::AT_objc_exception: - HandleObjCExceptionAttr(D, Attr, S); + handleObjCExceptionAttr(S, D, Attr); break; case AttributeList::AT_objc_method_family: - HandleObjCMethodFamilyAttr(D, Attr, S); + handleObjCMethodFamilyAttr(S, D, Attr); break; - case AttributeList::AT_nsobject: HandleObjCNSObject (D, Attr, S); break; - case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break; - case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break; - case AttributeList::AT_const: HandleConstAttr (D, Attr, S); break; - case AttributeList::AT_pure: HandlePureAttr (D, Attr, S); break; - case AttributeList::AT_cleanup: HandleCleanupAttr (D, Attr, S); break; - case AttributeList::AT_nodebug: HandleNoDebugAttr (D, Attr, S); break; - case AttributeList::AT_noinline: HandleNoInlineAttr (D, Attr, S); break; - case AttributeList::AT_regparm: HandleRegparmAttr (D, Attr, S); break; + case AttributeList::AT_nsobject: handleObjCNSObject (S, D, Attr); break; + case AttributeList::AT_blocks: handleBlocksAttr (S, D, Attr); break; + case AttributeList::AT_sentinel: handleSentinelAttr (S, D, Attr); break; + case AttributeList::AT_const: handleConstAttr (S, D, Attr); break; + case AttributeList::AT_pure: handlePureAttr (S, D, Attr); break; + case AttributeList::AT_cleanup: handleCleanupAttr (S, D, Attr); break; + case AttributeList::AT_nodebug: handleNoDebugAttr (S, D, Attr); break; + case AttributeList::AT_noinline: handleNoInlineAttr (S, D, Attr); break; + case AttributeList::AT_regparm: handleRegparmAttr (S, D, Attr); break; case AttributeList::IgnoredAttribute: // Just ignore break; case AttributeList::AT_no_instrument_function: // Interacts with -pg. - HandleNoInstrumentFunctionAttr(D, Attr, S); + handleNoInstrumentFunctionAttr(S, D, Attr); break; case AttributeList::AT_stdcall: case AttributeList::AT_cdecl: @@ -2938,13 +3033,13 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D, case AttributeList::AT_thiscall: case AttributeList::AT_pascal: case AttributeList::AT_pcs: - HandleCallConvAttr(D, Attr, S); + handleCallConvAttr(S, D, Attr); break; case AttributeList::AT_opencl_kernel_function: - HandleOpenCLKernelAttr(D, Attr, S); + handleOpenCLKernelAttr(S, D, Attr); break; case AttributeList::AT_uuid: - HandleUuidAttr(D, Attr, S); + handleUuidAttr(S, D, Attr); break; default: // Ask target about the attribute. @@ -2960,8 +3055,8 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D, /// 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). -static void ProcessDeclAttribute(Scope *scope, Decl *D, - const AttributeList &Attr, Sema &S, +static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, + const AttributeList &Attr, bool NonInheritable, bool Inheritable) { if (Attr.isInvalid()) return; @@ -2971,10 +3066,10 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, return; if (NonInheritable) - ProcessNonInheritableDeclAttr(scope, D, Attr, S); + ProcessNonInheritableDeclAttr(S, scope, D, Attr); if (Inheritable) - ProcessInheritableDeclAttr(scope, D, Attr, S); + ProcessInheritableDeclAttr(S, scope, D, Attr); } /// ProcessDeclAttributeList - Apply all the decl attributes in the specified @@ -2983,7 +3078,7 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList, bool NonInheritable, bool Inheritable) { for (const AttributeList* l = AttrList; l; l = l->getNext()) { - ProcessDeclAttribute(S, D, *l, *this, NonInheritable, Inheritable); + ProcessDeclAttribute(*this, S, D, *l, NonInheritable, Inheritable); } // GCC accepts @@ -3085,6 +3180,32 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD, ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable); } +/// Is the given declaration allowed to use a forbidden type? +static bool isForbiddenTypeAllowed(Sema &S, Decl *decl) { + // Private ivars are always okay. Unfortunately, people don't + // always properly make their ivars private, even in system headers. + // Plus we need to make fields okay, too. + if (!isa<FieldDecl>(decl) && !isa<ObjCPropertyDecl>(decl)) + return false; + + // Require it to be declared in a system header. + return S.Context.getSourceManager().isInSystemHeader(decl->getLocation()); +} + +/// Handle a delayed forbidden-type diagnostic. +static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag, + Decl *decl) { + if (decl && isForbiddenTypeAllowed(S, decl)) { + decl->addAttr(new (S.Context) UnavailableAttr(diag.Loc, S.Context, + "this system declaration uses an unsupported type")); + return; + } + + S.Diag(diag.Loc, diag.getForbiddenTypeDiagnostic()) + << diag.getForbiddenTypeOperand() << diag.getForbiddenTypeArgument(); + diag.Triggered = true; +} + // This duplicates a vector push_back but hides the need to know the // size of the type. void Sema::DelayedDiagnostics::add(const DelayedDiagnostic &diag) { @@ -3126,7 +3247,7 @@ void Sema::DelayedDiagnostics::popParsingDecl(Sema &S, ParsingDeclState state, // We only want to actually emit delayed diagnostics when we // successfully parsed a decl. - if (decl) { + if (decl && !decl->isInvalidDecl()) { // We emit all the active diagnostics, not just those starting // from the saved state. The idea is this: we get one push for a // decl spec and another for each declarator; in a decl group like: @@ -3147,6 +3268,10 @@ void Sema::DelayedDiagnostics::popParsingDecl(Sema &S, ParsingDeclState state, case DelayedDiagnostic::Access: S.HandleDelayedAccessCheck(diag, decl); break; + + case DelayedDiagnostic::ForbiddenType: + handleDelayedForbiddenType(S, diag, decl); + break; } } } |