From 624421f98d8fcb8ed8ebc406da41217682159aa8 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Sat, 31 Aug 2013 01:11:41 +0000 Subject: [PATCH] Consolidating the notion of a GNU attribute parameter with the attribute argument list. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189711 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/AttributeList.h | 216 ++++++++++-------- lib/Parse/ParseDecl.cpp | 95 ++++---- lib/Parse/ParseDeclCXX.cpp | 7 +- lib/Sema/AttributeList.cpp | 7 +- lib/Sema/SemaDeclAttr.cpp | 352 +++++++++++++---------------- lib/Sema/SemaType.cpp | 80 ++++--- lib/Sema/TargetAttributesSema.cpp | 6 +- test/Sema/attr-endian.c | 11 + test/Sema/callingconv.c | 2 +- test/Sema/warn-type-safety.c | 4 +- test/SemaObjC/arc.m | 2 + test/SemaOpenCL/endian-attr.cl | 2 +- 12 files changed, 397 insertions(+), 387 deletions(-) create mode 100644 test/Sema/attr-endian.c diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index bba0767ab3..909f4a2e61 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -19,6 +19,7 @@ #include "clang/Basic/VersionTuple.h" #include "clang/Sema/Ownership.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/PointerUnion.h" #include "llvm/Support/Allocator.h" #include @@ -44,6 +45,18 @@ struct AvailabilityChange { bool isValid() const { return !Version.empty(); } }; +/// \brief Wraps an identifier and optional source location for the identifier. +/// It is expected that these will be created from the ASTContext memory pool. +struct IdentifierLoc { + SourceLocation Loc; + IdentifierInfo *Ident; +}; + +/// \brief A union of the various pointer types that can be passed to an +/// AttributeList as an argument. +typedef llvm::PointerUnion ArgsUnion; +typedef llvm::SmallVector ArgsVector; + /// AttributeList - Represents a syntactic attribute. /// /// For a GNU attribute, there are four forms of this construct: @@ -66,13 +79,12 @@ public: /// __ptr16, alignas(...), etc. AS_Keyword }; + private: IdentifierInfo *AttrName; IdentifierInfo *ScopeName; - IdentifierInfo *ParmName; SourceRange AttrRange; SourceLocation ScopeLoc; - SourceLocation ParmLoc; SourceLocation EllipsisLoc; /// The number of expression arguments this attribute has. @@ -100,6 +112,9 @@ private: /// Microsoft __delcspec(property) attribute. unsigned IsProperty : 1; + /// True if this has a ParsedType + unsigned HasParsedType : 1; + unsigned AttrKind : 8; /// \brief The location of the 'unavailable' keyword in an @@ -114,22 +129,27 @@ private: /// The next attribute allocated in the current Pool. AttributeList *NextInPool; - Expr **getArgsBuffer() { - return reinterpret_cast(this+1); + /// Arguments, if any, are stored immediately following the object. + ArgsUnion *getArgsBuffer() { + return reinterpret_cast(this+1); } - Expr * const *getArgsBuffer() const { - return reinterpret_cast(this+1); + ArgsUnion const *getArgsBuffer() const { + return reinterpret_cast(this+1); } enum AvailabilitySlot { IntroducedSlot, DeprecatedSlot, ObsoletedSlot }; - AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) { - return reinterpret_cast(this+1)[index]; + /// Availability information is stored immediately following the arguments, + /// if any, at the end of the object. + AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) { + return reinterpret_cast(getArgsBuffer() + + NumArgs)[index]; } const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const { - return reinterpret_cast(this+1)[index]; + return reinterpret_cast(getArgsBuffer() + + NumArgs)[index]; } public: @@ -145,14 +165,20 @@ public: }; private: + /// Type tag information is stored immediately following the arguments, if + /// any, at the end of the object. They are mutually exlusive with + /// availability slots. TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() { - return *reinterpret_cast(this + 1); + return *reinterpret_cast(getArgsBuffer()+NumArgs); } const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const { - return *reinterpret_cast(this + 1); + return *reinterpret_cast(getArgsBuffer() + + NumArgs); } + /// The type buffer immediately follows the object and are mutually exclusive + /// with arguments. ParsedType &getTypeBuffer() { return *reinterpret_cast(this + 1); } @@ -161,6 +187,8 @@ private: return *reinterpret_cast(this + 1); } + /// The property data immediately follows the object is is mutually exclusive + /// with arguments. PropertyData &getPropertyDataBuffer() { assert(IsProperty); return *reinterpret_cast(this + 1); @@ -181,36 +209,34 @@ private: /// Constructor for attributes with expression arguments. AttributeList(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *parmName, SourceLocation parmLoc, - Expr **args, unsigned numArgs, + ArgsUnion *args, unsigned numArgs, Syntax syntaxUsed, SourceLocation ellipsisLoc) - : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), - AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), - EllipsisLoc(ellipsisLoc), NumArgs(numArgs), SyntaxUsed(syntaxUsed), - Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), - IsTypeTagForDatatype(false), IsProperty(false), NextInPosition(0), - NextInPool(0) { - if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*)); + : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), + ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs), + SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), + IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), + HasParsedType(false), NextInPosition(0), NextInPool(0) { + if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion)); AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } /// Constructor for availability attributes. AttributeList(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *parmName, SourceLocation parmLoc, - const AvailabilityChange &introduced, + IdentifierLoc *Parm, const AvailabilityChange &introduced, const AvailabilityChange &deprecated, const AvailabilityChange &obsoleted, SourceLocation unavailable, const Expr *messageExpr, Syntax syntaxUsed) - : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), - AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), EllipsisLoc(), - NumArgs(0), SyntaxUsed(syntaxUsed), + : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), + ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), - IsTypeTagForDatatype(false), IsProperty(false), + IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), UnavailableLoc(unavailable), MessageExpr(messageExpr), NextInPosition(0), NextInPool(0) { + ArgsUnion PVal(Parm); + memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced); new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated); new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted); @@ -220,16 +246,15 @@ private: /// Constructor for type_tag_for_datatype attribute. AttributeList(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *argumentKindName, - SourceLocation argumentKindLoc, - ParsedType matchingCType, bool layoutCompatible, - bool mustBeNull, Syntax syntaxUsed) - : AttrName(attrName), ScopeName(scopeName), ParmName(argumentKindName), - AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(argumentKindLoc), - EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed), + IdentifierLoc *ArgKind, ParsedType matchingCType, + bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed) + : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), + ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), - IsTypeTagForDatatype(true), IsProperty(false), NextInPosition(NULL), - NextInPool(NULL) { + IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false), + NextInPosition(NULL), NextInPool(NULL) { + ArgsUnion PVal(ArgKind); + memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot(); new (&ExtraData.MatchingCType) ParsedType(matchingCType); ExtraData.LayoutCompatible = layoutCompatible; @@ -240,14 +265,12 @@ private: /// Constructor for attributes with a single type argument. AttributeList(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *parmName, SourceLocation parmLoc, ParsedType typeArg, Syntax syntaxUsed) - : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), - AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), - EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false), - UsedAsTypeAttr(false), IsAvailability(false), - IsTypeTagForDatatype(false), IsProperty(false), NextInPosition(0), - NextInPool(0) { + : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), + ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed), + Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), + IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true), + NextInPosition(0), NextInPool(0) { new (&getTypeBuffer()) ParsedType(typeArg); AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } @@ -255,15 +278,13 @@ private: /// Constructor for microsoft __declspec(property) attribute. AttributeList(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *parmName, SourceLocation parmLoc, IdentifierInfo *getterId, IdentifierInfo *setterId, Syntax syntaxUsed) - : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), - AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), - SyntaxUsed(syntaxUsed), + : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), + ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), - IsTypeTagForDatatype(false), IsProperty(true), NextInPosition(0), - NextInPool(0) { + IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false), + NextInPosition(0), NextInPool(0) { new (&getPropertyDataBuffer()) PropertyData(getterId, setterId); AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } @@ -288,8 +309,7 @@ public: IdentifierInfo *getScopeName() const { return ScopeName; } SourceLocation getScopeLoc() const { return ScopeLoc; } - IdentifierInfo *getParameterName() const { return ParmName; } - SourceLocation getParameterLoc() const { return ParmLoc; } + bool hasParsedType() const { return HasParsedType; } /// Is this the Microsoft __declspec(property) attribute? bool isDeclspecPropertyAttribute() const { @@ -326,21 +346,31 @@ public: /// getNumArgs - Return the number of actual arguments to this attribute. unsigned getNumArgs() const { return NumArgs; } - /// hasParameterOrArguments - Return true if this attribute has a parameter, - /// or has a non empty argument expression list. - bool hasParameterOrArguments() const { return ParmName || NumArgs; } - /// getArg - Return the specified argument. - Expr *getArg(unsigned Arg) const { + ArgsUnion getArg(unsigned Arg) const { assert(Arg < NumArgs && "Arg access out of range!"); return getArgsBuffer()[Arg]; } + bool isArgExpr(unsigned Arg) const { + return Arg < NumArgs && getArg(Arg).is(); + } + Expr *getArgAsExpr(unsigned Arg) const { + return getArg(Arg).get(); + } + + bool isArgIdent(unsigned Arg) const { + return Arg < NumArgs && getArg(Arg).is(); + } + IdentifierLoc *getArgAsIdent(unsigned Arg) const { + return getArg(Arg).get(); + } + class arg_iterator { - Expr * const *X; + ArgsUnion const *X; unsigned Idx; public: - arg_iterator(Expr * const *x, unsigned idx) : X(x), Idx(idx) {} + arg_iterator(ArgsUnion const *x, unsigned idx) : X(x), Idx(idx) {} arg_iterator& operator++() { ++Idx; @@ -357,7 +387,7 @@ public: return !operator==(I); } - Expr* operator*() const { + ArgsUnion operator*() const { return X[Idx]; } @@ -445,11 +475,13 @@ public: /// which we want to ensure is a multiple of sizeof(void*). AvailabilityAllocSize = sizeof(AttributeList) - + ((3 * sizeof(AvailabilityChange) + sizeof(void*) - 1) + + ((3 * sizeof(AvailabilityChange) + sizeof(void*) + + sizeof(ArgsUnion) - 1) / sizeof(void*) * sizeof(void*)), TypeTagForDatatypeAllocSize = sizeof(AttributeList) - + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) - 1) + + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) + + sizeof(ArgsUnion) - 1) / sizeof(void*) * sizeof(void*), PropertyAllocSize = sizeof(AttributeList) @@ -541,22 +573,20 @@ public: AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *parmName, SourceLocation parmLoc, - Expr **args, unsigned numArgs, + ArgsUnion *args, unsigned numArgs, AttributeList::Syntax syntax, SourceLocation ellipsisLoc = SourceLocation()) { void *memory = allocate(sizeof(AttributeList) - + numArgs * sizeof(Expr*)); + + numArgs * sizeof(ArgsUnion)); return add(new (memory) AttributeList(attrName, attrRange, scopeName, scopeLoc, - parmName, parmLoc, args, numArgs, syntax, ellipsisLoc)); } AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *parmName, SourceLocation parmLoc, + IdentifierLoc *Param, const AvailabilityChange &introduced, const AvailabilityChange &deprecated, const AvailabilityChange &obsoleted, @@ -566,9 +596,9 @@ public: void *memory = allocate(AttributeFactory::AvailabilityAllocSize); return add(new (memory) AttributeList(attrName, attrRange, scopeName, scopeLoc, - parmName, parmLoc, - introduced, deprecated, obsoleted, - unavailable, MessageExpr, syntax)); + Param, introduced, deprecated, + obsoleted, unavailable, MessageExpr, + syntax)); } AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name, @@ -577,40 +607,35 @@ public: AttributeList *createTypeTagForDatatype( IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *argumentKindName, - SourceLocation argumentKindLoc, - ParsedType matchingCType, bool layoutCompatible, - bool mustBeNull, AttributeList::Syntax syntax) { + IdentifierLoc *argumentKind, ParsedType matchingCType, + bool layoutCompatible, bool mustBeNull, + AttributeList::Syntax syntax) { void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize); return add(new (memory) AttributeList(attrName, attrRange, scopeName, scopeLoc, - argumentKindName, argumentKindLoc, - matchingCType, layoutCompatible, - mustBeNull, syntax)); + argumentKind, matchingCType, + layoutCompatible, mustBeNull, + syntax)); } AttributeList *createTypeAttribute( IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *parmName, SourceLocation parmLoc, ParsedType typeArg, AttributeList::Syntax syntaxUsed) { void *memory = allocate(sizeof(AttributeList) + sizeof(void *)); return add(new (memory) AttributeList(attrName, attrRange, scopeName, scopeLoc, - parmName, parmLoc, typeArg, syntaxUsed)); } AttributeList *createPropertyAttribute( IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *parmName, SourceLocation parmLoc, IdentifierInfo *getterId, IdentifierInfo *setterId, AttributeList::Syntax syntaxUsed) { void *memory = allocate(AttributeFactory::PropertyAllocSize); return add(new (memory) AttributeList(attrName, attrRange, scopeName, scopeLoc, - parmName, parmLoc, getterId, setterId, syntaxUsed)); } @@ -709,13 +734,12 @@ public: /// Add attribute with expression arguments. AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *parmName, SourceLocation parmLoc, - Expr **args, unsigned numArgs, + ArgsUnion *args, unsigned numArgs, AttributeList::Syntax syntax, SourceLocation ellipsisLoc = SourceLocation()) { AttributeList *attr = - pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc, - args, numArgs, syntax, ellipsisLoc); + pool.create(attrName, attrRange, scopeName, scopeLoc, args, numArgs, + syntax, ellipsisLoc); add(attr); return attr; } @@ -723,7 +747,7 @@ public: /// Add availability attribute. AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *parmName, SourceLocation parmLoc, + IdentifierLoc *Param, const AvailabilityChange &introduced, const AvailabilityChange &deprecated, const AvailabilityChange &obsoleted, @@ -731,9 +755,8 @@ public: const Expr *MessageExpr, AttributeList::Syntax syntax) { AttributeList *attr = - pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc, - introduced, deprecated, obsoleted, unavailable, - MessageExpr, syntax); + pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced, + deprecated, obsoleted, unavailable, MessageExpr, syntax); add(attr); return attr; } @@ -742,16 +765,14 @@ public: AttributeList *addNewTypeTagForDatatype( IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *argumentKindName, - SourceLocation argumentKindLoc, - ParsedType matchingCType, bool layoutCompatible, - bool mustBeNull, AttributeList::Syntax syntax) { + IdentifierLoc *argumentKind, ParsedType matchingCType, + bool layoutCompatible, bool mustBeNull, + AttributeList::Syntax syntax) { AttributeList *attr = pool.createTypeTagForDatatype(attrName, attrRange, scopeName, scopeLoc, - argumentKindName, argumentKindLoc, - matchingCType, layoutCompatible, - mustBeNull, syntax); + argumentKind, matchingCType, + layoutCompatible, mustBeNull, syntax); add(attr); return attr; } @@ -760,11 +781,10 @@ public: AttributeList * addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *parmName, SourceLocation parmLoc, ParsedType typeArg, AttributeList::Syntax syntaxUsed) { AttributeList *attr = pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc, - parmName, parmLoc, typeArg, syntaxUsed); + typeArg, syntaxUsed); add(attr); return attr; } @@ -773,13 +793,11 @@ public: AttributeList * addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *parmName, SourceLocation parmLoc, IdentifierInfo *getterId, IdentifierInfo *setterId, AttributeList::Syntax syntaxUsed) { AttributeList *attr = pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc, - parmName, parmLoc, getterId, setterId, - syntaxUsed); + getterId, setterId, syntaxUsed); add(attr); return attr; } diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 392535acef..5f02c31fc2 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -164,8 +164,8 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, 0, SourceLocation(), AttributeList::AS_GNU); } } else { - attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, - 0, SourceLocation(), 0, 0, AttributeList::AS_GNU); + attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0, + AttributeList::AS_GNU); } } if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) @@ -217,9 +217,8 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, ConsumeParen(); // ignore the left paren loc for now - IdentifierInfo *ParmName = 0; - SourceLocation ParmLoc; bool BuiltinType = false; + ArgsVector ArgExprs; TypeResult T; SourceRange TypeRange; @@ -248,7 +247,7 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, TypeParsed = true; break; - case tok::identifier: + case tok::identifier: { if (AttrName->isStr("vec_type_hint")) { T = ParseTypeName(&TypeRange); TypeParsed = true; @@ -258,22 +257,24 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, // break out to handle it below. if (attributeHasExprArgs(*AttrName)) break; - ParmName = Tok.getIdentifierInfo(); - ParmLoc = ConsumeToken(); - break; + + IdentifierLoc *Param = ::new (Actions.Context) IdentifierLoc; + Param->Ident = Tok.getIdentifierInfo(); + Param->Loc = ConsumeToken(); + ArgExprs.push_back(Param); + } break; default: break; } - ExprVector ArgExprs; bool isInvalid = false; bool isParmType = false; if (!BuiltinType && !AttrName->isStr("vec_type_hint") && - (ParmLoc.isValid() ? Tok.is(tok::comma) : Tok.isNot(tok::r_paren))) { + (!ArgExprs.empty() ? Tok.is(tok::comma) : Tok.isNot(tok::r_paren))) { // Eat the comma. - if (ParmLoc.isValid()) + if (!ArgExprs.empty()) ConsumeToken(); // Parse the non-empty comma-separated list of expressions. @@ -322,11 +323,11 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc; if (isParmType) { Attrs.addNewTypeAttr(AttrName, SourceRange(AttrLoc, RParen), ScopeName, - ScopeLoc, ParmName, ParmLoc, T.get(), Syntax); + ScopeLoc, T.get(), Syntax); } else { AttributeList *attr = Attrs.addNew( - AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc, ParmName, - ParmLoc, ArgExprs.data(), ArgExprs.size(), Syntax); + AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc, + ArgExprs.data(), ArgExprs.size(), Syntax); if (BuiltinType && attr->getKind() == AttributeList::AT_IBOutletCollection) Diag(Tok, diag::err_iboutletcollection_builtintype); @@ -350,9 +351,9 @@ void Parser::ParseMicrosoftDeclSpecWithSingleArg(IdentifierInfo *AttrName, T.skipToEnd(); return; } - Expr *ExprList = ArgExpr.take(); - Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(), - &ExprList, 1, AttributeList::AS_Declspec); + ArgsUnion ExprList = ArgExpr.take(); + Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, &ExprList, 1, + AttributeList::AS_Declspec); T.consumeClose(); } @@ -400,8 +401,7 @@ void Parser::ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident, if (Tok.getKind() == tok::l_paren) ParseMicrosoftDeclSpecWithSingleArg(Ident, Loc, Attrs); else - Attrs.addNew(Ident, Loc, 0, Loc, 0, SourceLocation(), 0, 0, - AttributeList::AS_Declspec); + Attrs.addNew(Ident, Loc, 0, Loc, 0, 0, AttributeList::AS_Declspec); } else if (Ident->getName() == "property") { // The property declspec is more complex in that it can take one or two // assignment expressions as a parameter, but the lhs of the assignment @@ -514,8 +514,7 @@ void Parser::ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident, // Only add the property attribute if it was well-formed. if (!HasInvalidAccessor) { - Attrs.addNewPropertyAttr(Ident, Loc, 0, SourceLocation(), 0, - SourceLocation(), + Attrs.addNewPropertyAttr(Ident, Loc, 0, SourceLocation(), AccessorNames[AK_Get], AccessorNames[AK_Put], AttributeList::AS_Declspec); } @@ -589,8 +588,8 @@ void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &Attrs) { // // Alternatively, if the identifier is a simple one, then it requires no // arguments and can be turned into an attribute directly. - Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(), - 0, 0, AttributeList::AS_Declspec); + Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0, + AttributeList::AS_Declspec); else ParseComplexMicrosoftDeclSpec(AttrName, AttrNameLoc, Attrs); } @@ -606,8 +605,8 @@ void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) { Tok.is(tok::kw___sptr) || Tok.is(tok::kw___uptr)) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); - attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, - SourceLocation(), 0, 0, AttributeList::AS_Keyword); + attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0, + AttributeList::AS_Keyword); } } @@ -616,8 +615,8 @@ void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) { while (Tok.is(tok::kw___pascal)) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); - attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, - SourceLocation(), 0, 0, AttributeList::AS_Keyword); + attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0, + AttributeList::AS_Keyword); } } @@ -626,8 +625,8 @@ void Parser::ParseOpenCLAttributes(ParsedAttributes &attrs) { while (Tok.is(tok::kw___kernel)) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); - attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, - SourceLocation(), 0, 0, AttributeList::AS_Keyword); + attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0, + AttributeList::AS_Keyword); } } @@ -811,9 +810,6 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, SourceLocation AvailabilityLoc, ParsedAttributes &attrs, SourceLocation *endLoc) { - SourceLocation PlatformLoc; - IdentifierInfo *Platform = 0; - enum { Introduced, Deprecated, Obsoleted, Unknown }; AvailabilityChange Changes[Unknown]; ExprResult MessageExpr; @@ -831,8 +827,10 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, SkipUntil(tok::r_paren); return; } - Platform = Tok.getIdentifierInfo(); - PlatformLoc = ConsumeToken(); + + IdentifierLoc *Platform = new (Actions.Context) IdentifierLoc; + Platform->Ident = Tok.getIdentifierInfo(); + Platform->Loc = ConsumeToken(); // Parse the ',' following the platform name. if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::r_paren)) @@ -961,7 +959,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, attrs.addNew(&Availability, SourceRange(AvailabilityLoc, T.getCloseLocation()), 0, AvailabilityLoc, - Platform, PlatformLoc, + Platform, Changes[Introduced], Changes[Deprecated], Changes[Obsoleted], @@ -1162,7 +1160,7 @@ void Parser::ParseThreadSafetyAttribute(IdentifierInfo &AttrName, BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); - ExprVector ArgExprs; + ArgsVector ArgExprs; bool ArgExprsOk = true; // now parse the list of expressions @@ -1182,8 +1180,8 @@ void Parser::ParseThreadSafetyAttribute(IdentifierInfo &AttrName, } // Match the ')'. if (ArgExprsOk && !T.consumeClose()) { - Attrs.addNew(&AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(), - ArgExprs.data(), ArgExprs.size(), AttributeList::AS_GNU); + Attrs.addNew(&AttrName, AttrNameLoc, 0, AttrNameLoc, ArgExprs.data(), + ArgExprs.size(), AttributeList::AS_GNU); } if (EndLoc) *EndLoc = T.getCloseLocation(); @@ -1203,8 +1201,9 @@ void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName, T.skipToEnd(); return; } - IdentifierInfo *ArgumentKind = Tok.getIdentifierInfo(); - SourceLocation ArgumentKindLoc = ConsumeToken(); + IdentifierLoc *ArgumentKind = new (Actions.Context) IdentifierLoc; + ArgumentKind->Ident = Tok.getIdentifierInfo(); + ArgumentKind->Loc = ConsumeToken(); if (Tok.isNot(tok::comma)) { Diag(Tok, diag::err_expected_comma); @@ -1244,9 +1243,9 @@ void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName, if (!T.consumeClose()) { Attrs.addNewTypeTagForDatatype(&AttrName, AttrNameLoc, 0, AttrNameLoc, - ArgumentKind, ArgumentKindLoc, - MatchingCType.release(), LayoutCompatible, - MustBeNull, AttributeList::AS_GNU); + ArgumentKind, MatchingCType.release(), + LayoutCompatible, MustBeNull, + AttributeList::AS_GNU); } if (EndLoc) @@ -2312,10 +2311,10 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs, if (EndLoc) *EndLoc = T.getCloseLocation(); - ExprVector ArgExprs; + ArgsVector ArgExprs; ArgExprs.push_back(ArgExpr.release()); - Attrs.addNew(KWName, KWLoc, 0, KWLoc, 0, T.getOpenLocation(), - ArgExprs.data(), 1, AttributeList::AS_Keyword, EllipsisLoc); + Attrs.addNew(KWName, KWLoc, 0, KWLoc, ArgExprs.data(), 1, + AttributeList::AS_Keyword, EllipsisLoc); } /// ParseDeclarationSpecifiers @@ -2740,8 +2739,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, SourceLocation AttrNameLoc = Tok.getLocation(); // FIXME: This does not work correctly if it is set to be a declspec // attribute, and a GNU attribute is simply incorrect. - DS.getAttributes().addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, - SourceLocation(), 0, 0, AttributeList::AS_GNU); + DS.getAttributes().addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0, + AttributeList::AS_GNU); break; } diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 61b64eb8b3..6594749592 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -987,8 +987,8 @@ void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) { Tok.is(tok::kw___virtual_inheritance)) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); - attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, - SourceLocation(), 0, 0, AttributeList::AS_GNU); + attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0, + AttributeList::AS_GNU); } } @@ -3245,8 +3245,7 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, attrs.addNew(AttrName, SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc, AttrLoc), - ScopeName, ScopeLoc, 0, - SourceLocation(), 0, 0, AttributeList::AS_CXX11); + ScopeName, ScopeLoc, 0, 0, AttributeList::AS_CXX11); if (Tok.is(tok::ellipsis)) { ConsumeToken(); diff --git a/lib/Sema/AttributeList.cpp b/lib/Sema/AttributeList.cpp index 9ac4c63e19..dd01aef73c 100644 --- a/lib/Sema/AttributeList.cpp +++ b/lib/Sema/AttributeList.cpp @@ -25,7 +25,7 @@ size_t AttributeList::allocated_size() const { return AttributeFactory::TypeTagForDatatypeAllocSize; else if (IsProperty) return AttributeFactory::PropertyAllocSize; - return (sizeof(AttributeList) + NumArgs * sizeof(Expr*)); + return (sizeof(AttributeList) + NumArgs * sizeof(ArgsUnion)); } AttributeFactory::AttributeFactory() { @@ -98,10 +98,9 @@ void AttributePool::takePool(AttributeList *pool) { AttributeList * AttributePool::createIntegerAttribute(ASTContext &C, IdentifierInfo *Name, SourceLocation TokLoc, int Arg) { - Expr *IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg), + ArgsUnion IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg), C.IntTy, TokLoc); - return create(Name, TokLoc, 0, TokLoc, 0, TokLoc, &IArg, 1, - AttributeList::AS_GNU); + return create(Name, TokLoc, 0, TokLoc, &IArg, 1, AttributeList::AS_GNU); } #include "clang/Sema/AttrParsedAttrKinds.inc" diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index b9e4ef0633..00f8af9382 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -419,7 +419,7 @@ static void checkAttrArgsAreLockableObjs(Sema &S, Decl *D, int Sidx = 0, bool ParamIdxOk = false) { for(unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) { - Expr *ArgExp = Attr.getArg(Idx); + Expr *ArgExp = Attr.getArgAsExpr(Idx); if (ArgExp->isTypeDependent()) { // FIXME -- need to check this again on template instantiation @@ -815,7 +815,7 @@ static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, return false; } - if (!isIntOrBool(Attr.getArg(0))) { + if (!isIntOrBool(Attr.getArgAsExpr(0))) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) << Attr.getName() << 1 << AANT_ArgumentIntOrBool; return false; @@ -833,11 +833,10 @@ static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D, if (!checkTryLockFunAttrCommon(S, D, Attr, Args)) return; - unsigned Size = Args.size(); - Expr **StartArg = Size == 0 ? 0 : &Args[0]; D->addAttr(::new (S.Context) SharedTrylockFunctionAttr(Attr.getRange(), S.Context, - Attr.getArg(0), StartArg, Size, + Attr.getArgAsExpr(0), + Args.data(), Args.size(), Attr.getAttributeSpellingListIndex())); } @@ -847,11 +846,10 @@ static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D, if (!checkTryLockFunAttrCommon(S, D, Attr, Args)) return; - unsigned Size = Args.size(); - Expr **StartArg = Size == 0 ? 0 : &Args[0]; D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(Attr.getRange(), S.Context, - Attr.getArg(0), StartArg, Size, + Attr.getArgAsExpr(0), + Args.data(), Args.size(), Attr.getAttributeSpellingListIndex())); } @@ -1177,7 +1175,7 @@ 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) { + if (Attr.getNumArgs() > 1) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr.getName() << 1; return; @@ -1186,9 +1184,15 @@ static void handleIBOutletCollection(Sema &S, Decl *D, if (!checkIBOutletCommon(S, D, Attr)) return; - IdentifierInfo *II = Attr.getParameterName(); - if (!II) + IdentifierLoc *IL = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0; + IdentifierInfo *II; + SourceLocation ILS; + if (IL) { + II = IL->Ident; + ILS = IL->Loc; + } else { II = &S.Context.Idents.get("NSObject"); + } ParsedType TypeRep = S.getTypeName(*II, Attr.getLoc(), S.getScopeForContext(D->getDeclContext()->getParent())); @@ -1206,8 +1210,7 @@ static void handleIBOutletCollection(Sema &S, Decl *D, return; } D->addAttr(::new (S.Context) - IBOutletCollectionAttr(Attr.getRange(),S.Context, - QT, Attr.getParameterLoc(), + IBOutletCollectionAttr(Attr.getRange(), S.Context, QT, ILS, Attr.getAttributeSpellingListIndex())); } @@ -1238,7 +1241,7 @@ static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { SmallVector SizeArgs; for (unsigned i = 0; i < Attr.getNumArgs(); ++i) { - Expr *Ex = Attr.getArg(i); + Expr *Ex = Attr.getArgAsExpr(i); uint64_t Idx; if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(), Attr.getLoc(), i + 1, Ex, Idx)) @@ -1278,7 +1281,7 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { SmallVector NonNullArgs; for (unsigned i = 0; i < Attr.getNumArgs(); ++i) { - Expr *Ex = Attr.getArg(i); + Expr *Ex = Attr.getArgAsExpr(i); uint64_t Idx; if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(), Attr.getLoc(), i + 1, Ex, Idx)) @@ -1336,7 +1339,7 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { // after being held. free() should be __attribute((ownership_takes)), whereas // a list append function may well be __attribute((ownership_holds)). - if (!AL.getParameterName()) { + if (!AL.isArgIdent(0)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) << AL.getName()->getName() << 1 << AANT_ArgumentString; return; @@ -1346,7 +1349,7 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { switch (AL.getKind()) { case AttributeList::AT_ownership_takes: K = OwnershipAttr::Takes; - if (AL.getNumArgs() < 1) { + if (AL.getNumArgs() < 2) { S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL.getName() << 2; return; @@ -1354,7 +1357,7 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { break; case AttributeList::AT_ownership_holds: K = OwnershipAttr::Holds; - if (AL.getNumArgs() < 1) { + if (AL.getNumArgs() < 2) { S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL.getName() << 2; return; @@ -1362,9 +1365,9 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { break; case AttributeList::AT_ownership_returns: K = OwnershipAttr::Returns; - if (AL.getNumArgs() > 1) { + if (AL.getNumArgs() > 2) { S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) - << AL.getName() << AL.getNumArgs() + 1; + << AL.getName() << AL.getNumArgs() + 2; return; } break; @@ -1379,7 +1382,7 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { return; } - StringRef Module = AL.getParameterName()->getName(); + StringRef Module = AL.getArgAsIdent(0)->Ident->getName(); // Normalize the argument, __foo__ becomes foo. if (Module.startswith("__") && Module.endswith("__")) @@ -1387,11 +1390,11 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { SmallVector OwnershipArgs; - for (unsigned i = 0; i < AL.getNumArgs(); ++i) { - Expr *Ex = AL.getArg(i); + for (unsigned i = 1; i < AL.getNumArgs(); ++i) { + Expr *Ex = AL.getArgAsExpr(i); uint64_t Idx; if (!checkFunctionOrMethodArgumentIndex(S, D, AL.getName()->getName(), - AL.getLoc(), i + 1, Ex, Idx)) + AL.getLoc(), i, Ex, Idx)) return; switch (K) { @@ -1410,9 +1413,9 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { break; } case OwnershipAttr::Returns: { - if (AL.getNumArgs() > 1) { + if (AL.getNumArgs() > 2) { // Is the function argument an integer type? - Expr *IdxExpr = AL.getArg(0); + Expr *IdxExpr = AL.getArgAsExpr(1); llvm::APSInt ArgNum(32); if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) { @@ -1514,8 +1517,8 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) { // static ((alias ("y"), weakref)). // Should we? How to check that weakref is before or after alias? - if (Attr.getNumArgs() == 1) { - Expr *Arg = Attr.getArg(0); + if (Attr.isArgExpr(0)) { + Expr *Arg = Attr.getArgAsExpr(0); Arg = Arg->IgnoreParenCasts(); StringLiteral *Str = dyn_cast(Arg); @@ -1540,9 +1543,9 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkAttributeNumArgs(S, Attr, 1)) return; - Expr *Arg = Attr.getArg(0); - Arg = Arg->IgnoreParenCasts(); - StringLiteral *Str = dyn_cast(Arg); + StringLiteral *Str = 0; + if (Attr.isArgExpr(0)) + Str = dyn_cast(Attr.getArgAsExpr(0)->IgnoreParenCasts()); if (!Str || !Str->isAscii()) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) @@ -1639,11 +1642,8 @@ static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) { 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) - << Attr.getName() << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } if (!isa(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) @@ -1662,7 +1662,7 @@ static void handleTLSModelAttr(Sema &S, Decl *D, if (!checkAttributeNumArgs(S, Attr, 1)) return; - Expr *Arg = Attr.getArg(0); + Expr *Arg = Attr.getArgAsExpr(0); Arg = Arg->IgnoreParenCasts(); StringLiteral *Str = dyn_cast(Arg); @@ -1694,11 +1694,8 @@ static void handleTLSModelAttr(Sema &S, Decl *D, 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) - << Attr.getName() << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } if (const FunctionDecl *FD = dyn_cast(D)) { QualType RetTy = FD->getResultType(); @@ -1765,9 +1762,7 @@ static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) { } bool Sema::CheckNoReturnAttr(const AttributeList &attr) { - if (attr.hasParameterOrArguments()) { - Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << attr.getName() << 0; + if (!checkAttributeNumArgs(*this, attr, 0)) { attr.setInvalid(); return true; } @@ -1904,11 +1899,8 @@ static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D, 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) - << Attr.getName() << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } if (!isa(D) && !isa(D) && !isFunctionOrMethod(D) && !isa(D) && !isa(D) && !isa(D)) { @@ -1925,11 +1917,8 @@ static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { static void handleReturnsTwiceAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. - if (Attr.hasParameterOrArguments()) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << Attr.getName() << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } if (!isa(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) @@ -1944,11 +1933,8 @@ static void handleReturnsTwiceAttr(Sema &S, Decl *D, 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) - << Attr.getName() << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } if (const VarDecl *VD = dyn_cast(D)) { if (VD->hasLocalStorage()) { @@ -1975,7 +1961,7 @@ static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { int priority = 65535; // FIXME: Do not hardcode such constants. if (Attr.getNumArgs() > 0) { - Expr *E = Attr.getArg(0); + Expr *E = Attr.getArgAsExpr(0); llvm::APSInt Idx(32); if (E->isTypeDependent() || E->isValueDependent() || !E->isIntegerConstantExpr(Idx, S.Context)) { @@ -2007,7 +1993,7 @@ static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { int priority = 65535; // FIXME: Do not hardcode such constants. if (Attr.getNumArgs() > 0) { - Expr *E = Attr.getArg(0); + Expr *E = Attr.getArgAsExpr(0); llvm::APSInt Idx(32); if (E->isTypeDependent() || E->isValueDependent() || !E->isIntegerConstantExpr(Idx, S.Context)) { @@ -2041,11 +2027,12 @@ static void handleAttrWithMessage(Sema &S, Decl *D, // Handle the case where the attribute has a text message. StringRef Str; - if (NumArgs == 1) { - StringLiteral *SE = dyn_cast(Attr.getArg(0)); + if (Attr.isArgExpr(0)) { + StringLiteral *SE = dyn_cast(Attr.getArgAsExpr(0)); if (!SE) { - S.Diag(Attr.getArg(0)->getLocStart(), diag::err_attribute_argument_type) - << Attr.getName() << AANT_ArgumentString; + S.Diag(Attr.getArgAsExpr(0)->getLocStart(), + diag::err_attribute_argument_type) << Attr.getName() + << AANT_ArgumentString; return; } Str = SE->getString(); @@ -2280,13 +2267,15 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, static void handleAvailabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { - IdentifierInfo *Platform = Attr.getParameterName(); - SourceLocation PlatformLoc = Attr.getParameterLoc(); + if (!checkAttributeNumArgs(S, Attr, 1)) + return; + IdentifierLoc *Platform = Attr.getArgAsIdent(0); unsigned Index = Attr.getAttributeSpellingListIndex(); - if (AvailabilityAttr::getPrettyPlatformName(Platform->getName()).empty()) - S.Diag(PlatformLoc, diag::warn_availability_unknown_platform) - << Platform; + IdentifierInfo *II = Platform->Ident; + if (AvailabilityAttr::getPrettyPlatformName(II->getName()).empty()) + S.Diag(Platform->Loc, diag::warn_availability_unknown_platform) + << Platform->Ident; NamedDecl *ND = dyn_cast(D); if (!ND) { @@ -2304,8 +2293,7 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, if (SE) Str = SE->getString(); - AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, Attr.getRange(), - Platform, + AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, Attr.getRange(), II, Introduced.Version, Deprecated.Version, Obsoleted.Version, @@ -2369,7 +2357,7 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr, if (!checkAttributeNumArgs(S, Attr, 1)) return; - Expr *Arg = Attr.getArg(0); + Expr *Arg = Attr.getArgAsExpr(0); Arg = Arg->IgnoreParenCasts(); StringLiteral *Str = dyn_cast(Arg); @@ -2424,19 +2412,18 @@ static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl, return; } - if (Attr.getNumArgs() != 0 || !Attr.getParameterName()) { - if (!Attr.getParameterName() && Attr.getNumArgs() == 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) - << Attr.getName() << 1 << AANT_ArgumentString; - } else { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << Attr.getName() << 0; - } - Attr.setInvalid(); + if (!Attr.isArgIdent(0)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) + << Attr.getName() << 1 << AANT_ArgumentIdentifier; return; } + + if (!checkAttributeNumArgs(S, Attr, 1)) + return; + + IdentifierLoc *IL = Attr.getArgAsIdent(0); - StringRef param = Attr.getParameterName()->getName(); + StringRef param = IL->Ident->getName(); ObjCMethodFamilyAttr::FamilyKind family; if (param == "none") family = ObjCMethodFamilyAttr::OMF_None; @@ -2453,7 +2440,7 @@ static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl, 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(IL->Loc, diag::warn_unknown_method_family); return; } @@ -2533,24 +2520,22 @@ handleOverloadableAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (!Attr.getParameterName()) { + if (!Attr.isArgIdent(0)) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) - << Attr.getName() << 1 << AANT_ArgumentString; + << Attr.getName() << 1 << AANT_ArgumentIdentifier; return; } - - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << Attr.getName() << 1; + + if (!checkAttributeNumArgs(S, Attr, 1)) return; - } + IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident; BlocksAttr::BlockType type; - if (Attr.getParameterName()->isStr("byref")) + if (II->isStr("byref")) type = BlocksAttr::ByRef; else { - S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) - << "blocks" << Attr.getParameterName(); + S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) << "blocks" + << II; return; } @@ -2568,7 +2553,7 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) { unsigned sentinel = 0; if (Attr.getNumArgs() > 0) { - Expr *E = Attr.getArg(0); + Expr *E = Attr.getArgAsExpr(0); llvm::APSInt Idx(32); if (E->isTypeDependent() || E->isValueDependent() || !E->isIntegerConstantExpr(Idx, S.Context)) { @@ -2589,7 +2574,7 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) { unsigned nullPos = 0; if (Attr.getNumArgs() > 1) { - Expr *E = Attr.getArg(1); + Expr *E = Attr.getArgAsExpr(1); llvm::APSInt Idx(32); if (E->isTypeDependent() || E->isValueDependent() || !E->isIntegerConstantExpr(Idx, S.Context)) { @@ -2696,11 +2681,8 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) 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) - << Attr.getName() << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } if (!isa(D) && !isa(D)) { if (isa(D)) { @@ -2758,7 +2740,7 @@ static void handleWorkGroupSize(Sema &S, Decl *D, unsigned WGSize[3]; for (unsigned i = 0; i < 3; ++i) { - Expr *E = Attr.getArg(i); + Expr *E = Attr.getArgAsExpr(i); llvm::APSInt ArgNum(32); if (E->isTypeDependent() || E->isValueDependent() || !E->isIntegerConstantExpr(ArgNum, S.Context)) { @@ -2807,9 +2789,14 @@ static void handleWorkGroupSize(Sema &S, Decl *D, static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) { assert(Attr.getKind() == AttributeList::AT_VecTypeHint); - // Attribute has 1 argument. - if (!checkAttributeNumArgs(S, Attr, 1)) + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + if (!Attr.hasParsedType()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 1; return; + } QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg()); @@ -2835,10 +2822,19 @@ static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleEndianAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!Attr.isArgIdent(0)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) + << Attr.getName() << 1 << AANT_ArgumentIdentifier; + return; + } + + if (!checkAttributeNumArgs(S, Attr, 1)) + return; + if (!dyn_cast(D)) - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << "endian" - << 9; - StringRef EndianType = Attr.getParameterName()->getName(); + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariable; + StringRef EndianType = Attr.getArgAsIdent(0)->Ident->getName(); if (EndianType != "host" && EndianType != "device") S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_endian) << EndianType; } @@ -2864,7 +2860,7 @@ static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) { // Make sure that there is a string literal as the sections's single // argument. - Expr *ArgExpr = Attr.getArg(0); + Expr *ArgExpr = Attr.getArgAsExpr(0); StringLiteral *SE = dyn_cast(ArgExpr); if (!SE) { S.Diag(ArgExpr->getLocStart(), diag::err_attribute_argument_type) @@ -2895,12 +2891,8 @@ static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) { 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) - << Attr.getName() << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } if (NoThrowAttr *Existing = D->getAttr()) { if (Existing->getLocation().isInvalid()) @@ -2913,12 +2905,8 @@ static void handleNothrowAttr(Sema &S, Decl *D, const AttributeList &Attr) { } 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) - << Attr.getName() << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } if (ConstAttr *Existing = D->getAttr()) { if (Existing->getLocation().isInvalid()) @@ -2941,17 +2929,14 @@ static void handlePureAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (!Attr.getParameterName()) { + if (!Attr.isArgIdent(0)) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr.getName() << 1; return; } - - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << Attr.getName() << 1; + + if (!checkAttributeNumArgs(S, Attr, 1)) return; - } VarDecl *VD = dyn_cast(D); @@ -2960,29 +2945,27 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } + IdentifierLoc *IL = Attr.getArgAsIdent(0); + // Look up the function // FIXME: Lookup probably isn't looking in the right place NamedDecl *CleanupDecl - = S.LookupSingleName(S.TUScope, Attr.getParameterName(), - Attr.getParameterLoc(), Sema::LookupOrdinaryName); + = S.LookupSingleName(S.TUScope, IL->Ident, IL->Loc, + Sema::LookupOrdinaryName); if (!CleanupDecl) { - S.Diag(Attr.getParameterLoc(), diag::err_attribute_cleanup_arg_not_found) << - Attr.getParameterName(); + S.Diag(IL->Loc, diag::err_attribute_cleanup_arg_not_found) << IL->Ident; return; } FunctionDecl *FD = dyn_cast(CleanupDecl); if (!FD) { - S.Diag(Attr.getParameterLoc(), - diag::err_attribute_cleanup_arg_not_function) - << Attr.getParameterName(); + S.Diag(IL->Loc, diag::err_attribute_cleanup_arg_not_function) << IL->Ident; return; } if (FD->getNumParams() != 1) { - S.Diag(Attr.getParameterLoc(), - diag::err_attribute_cleanup_func_must_take_one_arg) - << Attr.getParameterName(); + S.Diag(IL->Loc, diag::err_attribute_cleanup_func_must_take_one_arg) + << IL->Ident; return; } @@ -2992,17 +2975,16 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { QualType ParamTy = FD->getParamDecl(0)->getType(); if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(), ParamTy, Ty) != Sema::Compatible) { - S.Diag(Attr.getParameterLoc(), - diag::err_attribute_cleanup_func_arg_incompatible_type) << - Attr.getParameterName() << ParamTy << Ty; + S.Diag(IL->Loc, diag::err_attribute_cleanup_func_arg_incompatible_type) << + IL->Ident << ParamTy << Ty; return; } D->addAttr(::new (S.Context) CleanupAttr(Attr.getRange(), S.Context, FD, Attr.getAttributeSpellingListIndex())); - S.MarkFunctionReferenced(Attr.getParameterLoc(), FD); - S.DiagnoseUseOfDecl(FD, Attr.getParameterLoc()); + S.MarkFunctionReferenced(IL->Loc, FD); + S.DiagnoseUseOfDecl(FD, IL->Loc); } /// Handle __attribute__((format_arg((idx)))) attribute based on @@ -3017,7 +2999,7 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - Expr *IdxExpr = Attr.getArg(0); + Expr *IdxExpr = Attr.getArgAsExpr(0); uint64_t ArgIdx; if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(), Attr.getLoc(), 1, IdxExpr, ArgIdx)) @@ -3114,7 +3096,7 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, Attr.setInvalid(); return; } - Expr *priorityExpr = Attr.getArg(0); + Expr *priorityExpr = Attr.getArgAsExpr(0); llvm::APSInt priority(32); if (priorityExpr->isTypeDependent() || priorityExpr->isValueDependent() || @@ -3164,18 +3146,14 @@ FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format, /// Handle __attribute__((format(type,idx,firstarg))) attributes based on /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { - - if (!Attr.getParameterName()) { + if (!Attr.isArgIdent(0)) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) - << Attr.getName() << 1 << AANT_ArgumentString; + << Attr.getName() << 1 << AANT_ArgumentIdentifier; return; } - - if (Attr.getNumArgs() != 2) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << Attr.getName() << 3; + + if (!checkAttributeNumArgs(S, Attr, 3)) return; - } if (!isFunctionOrMethodOrBlock(D) || !hasFunctionProto(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) @@ -3189,7 +3167,8 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; unsigned FirstIdx = 1; - StringRef Format = Attr.getParameterName()->getName(); + IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident; + StringRef Format = II->getName(); // Normalize the argument, __foo__ becomes foo. if (Format.startswith("__") && Format.endswith("__")) @@ -3203,12 +3182,12 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (Kind == InvalidFormat) { S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) - << "format" << Attr.getParameterName()->getName(); + << "format" << II->getName(); return; } // checks for the 2nd argument - Expr *IdxExpr = Attr.getArg(0); + Expr *IdxExpr = Attr.getArgAsExpr(1); llvm::APSInt Idx(32); if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { @@ -3264,7 +3243,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { } // check the 3rd argument - Expr *FirstArgExpr = Attr.getArg(1); + Expr *FirstArgExpr = Attr.getArgAsExpr(2); llvm::APSInt FirstArg(32); if (FirstArgExpr->isTypeDependent() || FirstArgExpr->isValueDependent() || !FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) { @@ -3381,7 +3360,7 @@ static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkAttributeNumArgs(S, Attr, 1)) return; - Expr *ArgExpr = Attr.getArg(0); + Expr *ArgExpr = Attr.getArgAsExpr(0); StringLiteral *SE = dyn_cast(ArgExpr); // Make sure that there is a string literal as the annotation's single @@ -3419,7 +3398,7 @@ static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - Expr *E = Attr.getArg(0); + Expr *E = Attr.getArgAsExpr(0); if (Attr.isPackExpansion() && !E->containsUnexpandedParameterPack()) { S.Diag(Attr.getEllipsisLoc(), diag::err_pack_expansion_without_parameter_packs); @@ -3576,20 +3555,17 @@ void Sema::CheckAlignasUnderalignment(Decl *D) { 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 (!checkAttributeNumArgs(S, Attr, 0)) - return; - - - IdentifierInfo *Name = Attr.getParameterName(); - if (!Name) { + if (!Attr.isArgIdent(0)) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName() << AANT_ArgumentIdentifier; return; } + + if (!checkAttributeNumArgs(S, Attr, 1)) + return; - StringRef Str = Attr.getParameterName()->getName(); + IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident; + StringRef Str = Name->getName(); // Normalize the attribute name, __foo__ becomes foo. if (Str.startswith("__") && Str.endswith("__")) @@ -3808,12 +3784,8 @@ static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D, static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.LangOpts.CUDA) { - // check the attribute arguments. - if (Attr.hasParameterOrArguments()) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << Attr.getName() << 0; + if (!checkAttributeNumArgs(S, Attr, 0)) return; - } if (!isa(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) @@ -4041,7 +4013,7 @@ static void handleOpenCLKernelAttr(Sema &S, Decl *D, const AttributeList &Attr){ } static void handleOpenCLImageAccessAttr(Sema &S, Decl *D, const AttributeList &Attr){ - Expr *E = Attr.getArg(0); + Expr *E = Attr.getArgAsExpr(0); llvm::APSInt ArgNum(32); if (E->isTypeDependent() || E->isValueDependent() || !E->isIntegerConstantExpr(ArgNum, S.Context)) { @@ -4061,9 +4033,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, return true; unsigned ReqArgs = attr.getKind() == AttributeList::AT_Pcs ? 1 : 0; - if (attr.getNumArgs() != ReqArgs || attr.getParameterName()) { - Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << attr.getName() << ReqArgs; + if (!checkAttributeNumArgs(*this, attr, ReqArgs)) { attr.setInvalid(); return true; } @@ -4085,8 +4055,10 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, CC_C; break; case AttributeList::AT_Pcs: { - Expr *Arg = attr.getArg(0); - StringLiteral *Str = dyn_cast(Arg); + StringLiteral *Str = 0; + if (attr.isArgExpr(0)) + Str = dyn_cast(attr.getArgAsExpr(0)); + if (!Str || !Str->isAscii()) { Diag(attr.getLoc(), diag::err_attribute_argument_type) << attr.getName() << AANT_ArgumentString; @@ -4156,7 +4128,7 @@ bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) { return true; } - Expr *NumParamsExpr = Attr.getArg(0); + Expr *NumParamsExpr = Attr.getArgAsExpr(0); llvm::APSInt NumParams(32); if (NumParamsExpr->isTypeDependent() || NumParamsExpr->isValueDependent() || !NumParamsExpr->isIntegerConstantExpr(NumParams, Context)) { @@ -4200,7 +4172,7 @@ static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){ return; } - Expr *MaxThreadsExpr = Attr.getArg(0); + Expr *MaxThreadsExpr = Attr.getArgAsExpr(0); llvm::APSInt MaxThreads(32); if (MaxThreadsExpr->isTypeDependent() || MaxThreadsExpr->isValueDependent() || @@ -4213,7 +4185,7 @@ static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){ llvm::APSInt MinBlocks(32); if (Attr.getNumArgs() > 1) { - Expr *MinBlocksExpr = Attr.getArg(1); + Expr *MinBlocksExpr = Attr.getArgAsExpr(1); if (MinBlocksExpr->isTypeDependent() || MinBlocksExpr->isValueDependent() || !MinBlocksExpr->isIntegerConstantExpr(MinBlocks, S.Context)) { @@ -4236,20 +4208,17 @@ static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, const AttributeList &Attr) { - StringRef AttrName = Attr.getName()->getName(); - if (!Attr.getParameterName()) { + if (!Attr.isArgIdent(0)) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) << Attr.getName() << /* arg num = */ 1 << AANT_ArgumentIdentifier; return; } - - if (Attr.getNumArgs() != 2) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << Attr.getName() << /* required args = */ 3; + + if (!checkAttributeNumArgs(S, Attr, 3)) return; - } - IdentifierInfo *ArgumentKind = Attr.getParameterName(); + StringRef AttrName = Attr.getName()->getName(); + IdentifierInfo *ArgumentKind = Attr.getArgAsIdent(0)->Ident; if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) @@ -4260,13 +4229,13 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, uint64_t ArgumentIdx; if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName, Attr.getLoc(), 2, - Attr.getArg(0), ArgumentIdx)) + Attr.getArgAsExpr(1), ArgumentIdx)) return; uint64_t TypeTagIdx; if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName, Attr.getLoc(), 3, - Attr.getArg(1), TypeTagIdx)) + Attr.getArgAsExpr(2), TypeTagIdx)) return; bool IsPointer = (AttrName == "pointer_with_type_tag"); @@ -4287,13 +4256,16 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, const AttributeList &Attr) { - IdentifierInfo *PointerKind = Attr.getParameterName(); - if (!PointerKind) { + if (!Attr.isArgIdent(0)) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) << Attr.getName() << 1 << AANT_ArgumentIdentifier; return; } + + if (!checkAttributeNumArgs(S, Attr, 1)) + return; + IdentifierInfo *PointerKind = Attr.getArgAsIdent(0)->Ident; QualType MatchingCType = S.GetTypeFromParser(Attr.getMatchingCType(), NULL); D->addAttr(::new (S.Context) @@ -4544,14 +4516,14 @@ static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D, << Attr.getRange() << Attr.getName() << ExpectedStruct; } - IdentifierInfo *ParmName = Attr.getParameterName(); + IdentifierLoc *Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0; // In Objective-C, verify that the type names an Objective-C type. // We don't want to check this outside of ObjC because people sometimes // do crazy C declarations of Objective-C types. - if (ParmName && S.getLangOpts().ObjC1) { + if (Parm && S.getLangOpts().ObjC1) { // Check for an existing type with this name. - LookupResult R(S, DeclarationName(ParmName), Attr.getParameterLoc(), + LookupResult R(S, DeclarationName(Parm->Ident), Parm->Loc, Sema::LookupOrdinaryName); if (S.LookupName(R, Sc)) { NamedDecl *Target = R.getFoundDecl(); @@ -4563,7 +4535,7 @@ static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D, } D->addAttr(::new (S.Context) - NSBridgedAttr(Attr.getRange(), S.Context, ParmName, + NSBridgedAttr(Attr.getRange(), S.Context, Parm ? Parm->Ident : 0, Attr.getAttributeSpellingListIndex())); } @@ -4644,7 +4616,7 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkAttributeNumArgs(S, Attr, 1)) return; - Expr *Arg = Attr.getArg(0); + Expr *Arg = Attr.getArgAsExpr(0); StringLiteral *Str = dyn_cast(Arg); if (!Str || !Str->isAscii()) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 5834e4f5c7..c8fd32ff2f 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -81,10 +81,11 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, StringRef name = attr.getName()->getName(); // The GC attributes are usually written with macros; special-case them. - if (useExpansionLoc && loc.isMacroID() && attr.getParameterName()) { - if (attr.getParameterName()->isStr("strong")) { + IdentifierInfo *II = attr.isArgIdent(0) ? attr.getArgAsIdent(0)->Ident : 0; + if (useExpansionLoc && loc.isMacroID() && II) { + if (II->isStr("strong")) { if (S.findMacroSpelling(loc, "__strong")) name = "__strong"; - } else if (attr.getParameterName()->isStr("weak")) { + } else if (II->isStr("weak")) { if (S.findMacroSpelling(loc, "__weak")) name = "__weak"; } } @@ -3291,13 +3292,18 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state, case Qualifiers::OCL_Autoreleasing: attrStr = "autoreleasing"; break; } + IdentifierLoc *Arg = new (S.Context) IdentifierLoc; + Arg->Ident = &S.Context.Idents.get(attrStr); + Arg->Loc = SourceLocation(); + + ArgsUnion Args(Arg); + // If there wasn't one, add one (with an invalid source location // so that we don't make an AttributedType for it). AttributeList *attr = D.getAttributePool() .create(&S.Context.Idents.get("objc_ownership"), SourceLocation(), /*scope*/ 0, SourceLocation(), - &S.Context.Idents.get(attrStr), SourceLocation(), - /*args*/ 0, 0, AttributeList::AS_GNU); + /*args*/ &Args, 1, AttributeList::AS_GNU); spliceAttrIntoList(*attr, chunk.getAttrListRef()); // TODO: mark whether we did this inference? @@ -3435,10 +3441,10 @@ static void fillAttributedTypeLoc(AttributedTypeLoc TL, } TL.setAttrNameLoc(attrs->getLoc()); - if (TL.hasAttrExprOperand()) - TL.setAttrExprOperand(attrs->getArg(0)); - else if (TL.hasAttrEnumOperand()) - TL.setAttrEnumOperandLoc(attrs->getParameterLoc()); + if (TL.hasAttrExprOperand() && attrs->isArgExpr(0)) + TL.setAttrExprOperand(attrs->getArgAsExpr(0)); + else if (TL.hasAttrEnumOperand() && attrs->isArgIdent(0)) + TL.setAttrEnumOperandLoc(attrs->getArgAsIdent(0)->Loc); // FIXME: preserve this information to here. if (TL.hasAttrOperand()) @@ -3902,7 +3908,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, Attr.setInvalid(); return; } - Expr *ASArgExpr = static_cast(Attr.getArg(0)); + Expr *ASArgExpr = static_cast(Attr.getArgAsExpr(0)); llvm::APSInt addrSpace(32); if (ASArgExpr->isTypeDependent() || ASArgExpr->isValueDependent() || !ASArgExpr->isIntegerConstantExpr(addrSpace, S.Context)) { @@ -4002,7 +4008,7 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, if (AttrLoc.isMacroID()) AttrLoc = S.getSourceManager().getImmediateExpansionRange(AttrLoc).first; - if (!attr.getParameterName()) { + if (!attr.isArgIdent(0)) { S.Diag(AttrLoc, diag::err_attribute_argument_type) << attr.getName() << AANT_ArgumentString; attr.setInvalid(); @@ -4014,18 +4020,19 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, if (!S.getLangOpts().ObjCAutoRefCount) return true; + IdentifierInfo *II = attr.getArgAsIdent(0)->Ident; Qualifiers::ObjCLifetime lifetime; - if (attr.getParameterName()->isStr("none")) + if (II->isStr("none")) lifetime = Qualifiers::OCL_ExplicitNone; - else if (attr.getParameterName()->isStr("strong")) + else if (II->isStr("strong")) lifetime = Qualifiers::OCL_Strong; - else if (attr.getParameterName()->isStr("weak")) + else if (II->isStr("weak")) lifetime = Qualifiers::OCL_Weak; - else if (attr.getParameterName()->isStr("autoreleasing")) + else if (II->isStr("autoreleasing")) lifetime = Qualifiers::OCL_Autoreleasing; else { S.Diag(AttrLoc, diag::warn_attribute_type_not_supported) - << "objc_ownership" << attr.getParameterName(); + << "objc_ownership" << II; attr.setInvalid(); return true; } @@ -4136,28 +4143,30 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state, attr.setInvalid(); return true; } - + // Check the attribute arguments. - if (!attr.getParameterName()) { + if (!attr.isArgIdent(0)) { S.Diag(attr.getLoc(), diag::err_attribute_argument_type) << attr.getName() << AANT_ArgumentString; attr.setInvalid(); return true; } Qualifiers::GC GCAttr; - if (attr.getNumArgs() != 0) { + if (attr.getNumArgs() > 1) { S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << attr.getName() << 1; attr.setInvalid(); return true; } - if (attr.getParameterName()->isStr("weak")) + + IdentifierInfo *II = attr.getArgAsIdent(0)->Ident; + if (II->isStr("weak")) GCAttr = Qualifiers::Weak; - else if (attr.getParameterName()->isStr("strong")) + else if (II->isStr("strong")) GCAttr = Qualifiers::Strong; else { S.Diag(attr.getLoc(), diag::warn_attribute_type_not_supported) - << "objc_gc" << attr.getParameterName(); + << "objc_gc" << II; attr.setInvalid(); return true; } @@ -4383,7 +4392,7 @@ static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) { return AttributedType::attr_pascal; case AttributeList::AT_Pcs: { // We know attr is valid so it can only have one of two strings args. - StringLiteral *Str = cast(Attr.getArg(0)); + StringLiteral *Str = cast(Attr.getArgAsExpr(0)); return llvm::StringSwitch(Str->getString()) .Case("aapcs", AttributedType::attr_pcs) .Case("aapcs-vfp", AttributedType::attr_pcs_vfp); @@ -4567,7 +4576,7 @@ static void HandleOpenCLImageAccessAttribute(QualType& CurType, Attr.setInvalid(); return; } - Expr *sizeExpr = static_cast(Attr.getArg(0)); + Expr *sizeExpr = static_cast(Attr.getArgAsExpr(0)); llvm::APSInt arg(32); if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() || !sizeExpr->isIntegerConstantExpr(arg, S.Context)) { @@ -4609,7 +4618,7 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, Attr.setInvalid(); return; } - Expr *sizeExpr = static_cast(Attr.getArg(0)); + Expr *sizeExpr = static_cast(Attr.getArgAsExpr(0)); llvm::APSInt vecSize(32); if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() || !sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) { @@ -4661,14 +4670,21 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, static void HandleExtVectorTypeAttr(QualType &CurType, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 1; + return; + } + Expr *sizeExpr; // Special case where the argument is a template id. - if (Attr.getParameterName()) { + if (Attr.isArgIdent(0)) { CXXScopeSpec SS; SourceLocation TemplateKWLoc; UnqualifiedId id; - id.setIdentifier(Attr.getParameterName(), Attr.getLoc()); + id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc()); ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc, id, false, false); @@ -4677,13 +4693,7 @@ static void HandleExtVectorTypeAttr(QualType &CurType, sizeExpr = Size.get(); } else { - // check the attribute arguments. - if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << Attr.getName() << 1; - return; - } - sizeExpr = Attr.getArg(0); + sizeExpr = Attr.getArgAsExpr(0); } // Create the vector type. @@ -4746,7 +4756,7 @@ static void HandleNeonVectorTypeAttr(QualType& CurType, return; } // The number of elements must be an ICE. - Expr *numEltsExpr = static_cast(Attr.getArg(0)); + Expr *numEltsExpr = static_cast(Attr.getArgAsExpr(0)); llvm::APSInt numEltsInt(32); if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() || !numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) { diff --git a/lib/Sema/TargetAttributesSema.cpp b/lib/Sema/TargetAttributesSema.cpp index f84373944b..7db0b241fa 100644 --- a/lib/Sema/TargetAttributesSema.cpp +++ b/lib/Sema/TargetAttributesSema.cpp @@ -37,7 +37,7 @@ static void HandleMSP430InterruptAttr(Decl *d, // FIXME: Check for decl - it should be void ()(void). - Expr *NumParamsExpr = static_cast(Attr.getArg(0)); + Expr *NumParamsExpr = static_cast(Attr.getArgAsExpr(0)); llvm::APSInt NumParams(32); if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) @@ -235,7 +235,7 @@ namespace { static void HandleMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) { // check the attribute arguments. - if (Attr.hasParameterOrArguments()) { + if (Attr.getNumArgs()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr.getName() << 0; return; @@ -252,7 +252,7 @@ static void HandleMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) { static void HandleNoMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) { // check the attribute arguments. - if (Attr.hasParameterOrArguments()) { + if (Attr.getNumArgs()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr.getName() << 0; return; diff --git a/test/Sema/attr-endian.c b/test/Sema/attr-endian.c new file mode 100644 index 0000000000..09442400a5 --- /dev/null +++ b/test/Sema/attr-endian.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only + +int p1 __attribute__((endian(host))); +int p2 __attribute__((endian(device))); + +int p3 __attribute__((endian)); // expected-error {{'endian' attribute requires parameter 1 to be an identifier}} +int p4 __attribute__((endian("host"))); // expected-error {{'endian' attribute requires parameter 1 to be an identifier}} +int p5 __attribute__((endian(host, 15))); // expected-error {{'endian' attribute takes one argument}} +int p6 __attribute__((endian(strange))); // expected-warning {{unknown endian 'strange'}} + +void func(void) __attribute__((endian(host))); // expected-warning {{'endian' attribute only applies to variables}} diff --git a/test/Sema/callingconv.c b/test/Sema/callingconv.c index b9adf791b5..3234609d68 100644 --- a/test/Sema/callingconv.c +++ b/test/Sema/callingconv.c @@ -38,7 +38,7 @@ Handler H = foo; int __attribute__((pcs("aapcs", "aapcs"))) pcs1(void); // expected-error {{'pcs' attribute takes one argument}} int __attribute__((pcs())) pcs2(void); // expected-error {{'pcs' attribute takes one argument}} -int __attribute__((pcs(pcs1))) pcs3(void); // expected-error {{'pcs' attribute takes one argument}} +int __attribute__((pcs(pcs1))) pcs3(void); // expected-error {{'pcs' attribute requires a string}} int __attribute__((pcs(0))) pcs4(void); // expected-error {{'pcs' attribute requires a string}} /* These are ignored because the target is i386 and not ARM */ int __attribute__((pcs("aapcs"))) pcs5(void); // expected-warning {{calling convention 'pcs' ignored for this target}} diff --git a/test/Sema/warn-type-safety.c b/test/Sema/warn-type-safety.c index 4ac453d380..dfab8f8c81 100644 --- a/test/Sema/warn-type-safety.c +++ b/test/Sema/warn-type-safety.c @@ -7,7 +7,7 @@ struct A {}; typedef struct A *MPI_Datatype; int wrong1(void *buf, MPI_Datatype datatype) - __attribute__(( pointer_with_type_tag )); // expected-error {{attribute requires parameter 1 to be an identifier}} + __attribute__(( pointer_with_type_tag )); // expected-error {{'pointer_with_type_tag' attribute requires parameter 1 to be an identifier}} int wrong2(void *buf, MPI_Datatype datatype) __attribute__(( pointer_with_type_tag(mpi,0,7) )); // expected-error {{attribute parameter 2 is out of bounds}} @@ -39,7 +39,7 @@ int wrong10(double buf, MPI_Datatype type) extern struct A datatype_wrong1 - __attribute__(( type_tag_for_datatype )); // expected-error {{attribute requires parameter 1 to be an identifier}} + __attribute__(( type_tag_for_datatype )); // expected-error {{'type_tag_for_datatype' attribute requires parameter 1 to be an identifier}} extern struct A datatype_wrong2 __attribute__(( type_tag_for_datatype(mpi,1,2) )); // expected-error {{expected a type}} diff --git a/test/SemaObjC/arc.m b/test/SemaObjC/arc.m index 76a97f3ab3..063e857c34 100644 --- a/test/SemaObjC/arc.m +++ b/test/SemaObjC/arc.m @@ -87,6 +87,8 @@ void test1(A *a) { + (id)alloc; - (id)initWithInt: (int) i; - (id)myInit __attribute__((objc_method_family(init))); +- (id)myBadInit __attribute__((objc_method_family(12))); // expected-error {{'objc_method_family' attribute requires parameter 1 to be an identifier}} + @end void rdar8861761() { diff --git a/test/SemaOpenCL/endian-attr.cl b/test/SemaOpenCL/endian-attr.cl index e851cdf90b..ba2f0e5c73 100644 --- a/test/SemaOpenCL/endian-attr.cl +++ b/test/SemaOpenCL/endian-attr.cl @@ -6,4 +6,4 @@ constant long b __attribute__((endian(device))) = 100; constant long c __attribute__((endian(none))) = 100; // expected-warning {{unknown endian 'none'}} -void func() __attribute__((endian(host))); // expected-warning {{endian attribute only applies to variables}} +void func() __attribute__((endian(host))); // expected-warning {{'endian' attribute only applies to variables}} -- 2.40.0