Consolidating the notion of a GNU attribute parameter with the attribute argument list.

llvm-svn: 189711
This commit is contained in:
Aaron Ballman 2013-08-31 01:11:41 +00:00
parent fb4b433bbb
commit 00e99966c4
12 changed files with 397 additions and 387 deletions

View File

@ -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 <cassert>
@ -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<Expr*, IdentifierLoc*> ArgsUnion;
typedef llvm::SmallVector<ArgsUnion, 12U> 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<Expr**>(this+1);
/// Arguments, if any, are stored immediately following the object.
ArgsUnion *getArgsBuffer() {
return reinterpret_cast<ArgsUnion*>(this+1);
}
Expr * const *getArgsBuffer() const {
return reinterpret_cast<Expr* const *>(this+1);
ArgsUnion const *getArgsBuffer() const {
return reinterpret_cast<ArgsUnion const *>(this+1);
}
enum AvailabilitySlot {
IntroducedSlot, DeprecatedSlot, ObsoletedSlot
};
AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) {
return reinterpret_cast<AvailabilityChange*>(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<AvailabilityChange*>(getArgsBuffer()
+ NumArgs)[index];
}
const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const {
return reinterpret_cast<const AvailabilityChange*>(this+1)[index];
return reinterpret_cast<const AvailabilityChange*>(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<TypeTagForDatatypeData *>(this + 1);
return *reinterpret_cast<TypeTagForDatatypeData*>(getArgsBuffer()+NumArgs);
}
const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
return *reinterpret_cast<const TypeTagForDatatypeData *>(this + 1);
return *reinterpret_cast<const TypeTagForDatatypeData*>(getArgsBuffer()
+ NumArgs);
}
/// The type buffer immediately follows the object and are mutually exclusive
/// with arguments.
ParsedType &getTypeBuffer() {
return *reinterpret_cast<ParsedType *>(this + 1);
}
@ -161,6 +187,8 @@ private:
return *reinterpret_cast<const ParsedType *>(this + 1);
}
/// The property data immediately follows the object is is mutually exclusive
/// with arguments.
PropertyData &getPropertyDataBuffer() {
assert(IsProperty);
return *reinterpret_cast<PropertyData*>(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*>();
}
Expr *getArgAsExpr(unsigned Arg) const {
return getArg(Arg).get<Expr*>();
}
bool isArgIdent(unsigned Arg) const {
return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>();
}
IdentifierLoc *getArgAsIdent(unsigned Arg) const {
return getArg(Arg).get<IdentifierLoc*>();
}
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;
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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"

View File

@ -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<unsigned, 8> 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<unsigned, 8> 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<unsigned, 8> 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<StringLiteral>(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<StringLiteral>(Arg);
StringLiteral *Str = 0;
if (Attr.isArgExpr(0))
Str = dyn_cast<StringLiteral>(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<FunctionDecl>(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<StringLiteral>(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<FunctionDecl>(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<VarDecl>(D) && !isa<ObjCIvarDecl>(D) && !isFunctionOrMethod(D) &&
!isa<TypeDecl>(D) && !isa<LabelDecl>(D) && !isa<FieldDecl>(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<FunctionDecl>(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<VarDecl>(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<StringLiteral>(Attr.getArg(0));
if (Attr.isArgExpr(0)) {
StringLiteral *SE = dyn_cast<StringLiteral>(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<NamedDecl>(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<StringLiteral>(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;
StringRef param = Attr.getParameterName()->getName();
IdentifierLoc *IL = Attr.getArgAsIdent(0);
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<VarDecl>(D) && !isa<FunctionDecl>(D)) {
if (isa<CXXRecordDecl>(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,10 +2789,15 @@ 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());
if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() &&
@ -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<VarDecl>(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<StringLiteral>(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<NoThrowAttr>()) {
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<ConstAttr>()) {
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<VarDecl>(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<FunctionDecl>(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<StringLiteral>(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<VarDecl>(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<StringLiteral>(Arg);
StringLiteral *Str = 0;
if (attr.isArgExpr(0))
Str = dyn_cast<StringLiteral>(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<StringLiteral>(Arg);
if (!Str || !Str->isAscii()) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)

View File

@ -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<Expr *>(Attr.getArg(0));
Expr *ASArgExpr = static_cast<Expr *>(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<StringLiteral>(Attr.getArg(0));
StringLiteral *Str = cast<StringLiteral>(Attr.getArgAsExpr(0));
return llvm::StringSwitch<AttributedType::Kind>(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<Expr *>(Attr.getArg(0));
Expr *sizeExpr = static_cast<Expr *>(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<Expr *>(Attr.getArg(0));
Expr *sizeExpr = static_cast<Expr *>(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<Expr *>(Attr.getArg(0));
Expr *numEltsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
llvm::APSInt numEltsInt(32);
if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() ||
!numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) {

View File

@ -37,7 +37,7 @@ static void HandleMSP430InterruptAttr(Decl *d,
// FIXME: Check for decl - it should be void ()(void).
Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0));
Expr *NumParamsExpr = static_cast<Expr *>(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;

View File

@ -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}}

View File

@ -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}}

View File

@ -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}}

View File

@ -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() {

View File

@ -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}}