//===--------------------------------------------------------------------===//
// C99 6.9: External Definitions.
- DeclGroupPtrTy ParseExternalDeclaration(CXX0XAttributeList Attr,
+ struct ParsedAttributesWithRange : ParsedAttributes {
+ SourceRange Range;
+ };
+
+ DeclGroupPtrTy ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
ParsingDeclSpec *DS = 0);
bool isDeclarationAfterDeclarator() const;
bool isStartOfFunctionDefinition(const ParsingDeclarator &Declarator);
- DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
- AccessSpecifier AS = AS_none);
+ DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs,
+ AccessSpecifier AS = AS_none);
DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS,
- AttributeList *Attr,
AccessSpecifier AS = AS_none);
Decl *ParseFunctionDefinition(ParsingDeclarator &D,
Decl *ParseObjCAtDirectives();
Decl *ParseObjCAtClassDeclaration(SourceLocation atLoc);
Decl *ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
- AttributeList *prefixAttrs = 0);
+ ParsedAttributes &prefixAttrs);
void ParseObjCClassInstanceVariables(Decl *interfaceDecl,
tok::ObjCKeywordKind visibility,
SourceLocation atLoc);
void ParseObjCInterfaceDeclList(Decl *interfaceDecl,
tok::ObjCKeywordKind contextKey);
Decl *ParseObjCAtProtocolDeclaration(SourceLocation atLoc,
- AttributeList *prefixAttrs = 0);
+ ParsedAttributes &prefixAttrs);
Decl *ObjCImpDecl;
llvm::SmallVector<Decl *, 4> PendingObjCImpDecl;
}
StmtResult ParseStatementOrDeclaration(StmtVector& Stmts,
bool OnlyStatement = false);
- StmtResult ParseLabeledStatement(AttributeList *Attr);
- StmtResult ParseCaseStatement(AttributeList *Attr);
- StmtResult ParseDefaultStatement(AttributeList *Attr);
- StmtResult ParseCompoundStatement(AttributeList *Attr,
+ StmtResult ParseLabeledStatement(ParsedAttributes &Attr);
+ StmtResult ParseCaseStatement(ParsedAttributes &Attr);
+ StmtResult ParseDefaultStatement(ParsedAttributes &Attr);
+ StmtResult ParseCompoundStatement(ParsedAttributes &Attr,
bool isStmtExpr = false);
StmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
bool ParseParenExprOrCondition(ExprResult &ExprResult,
Decl *&DeclResult,
SourceLocation Loc,
bool ConvertToBoolean);
- StmtResult ParseIfStatement(AttributeList *Attr);
- StmtResult ParseSwitchStatement(AttributeList *Attr);
- StmtResult ParseWhileStatement(AttributeList *Attr);
- StmtResult ParseDoStatement(AttributeList *Attr);
- StmtResult ParseForStatement(AttributeList *Attr);
- StmtResult ParseGotoStatement(AttributeList *Attr);
- StmtResult ParseContinueStatement(AttributeList *Attr);
- StmtResult ParseBreakStatement(AttributeList *Attr);
- StmtResult ParseReturnStatement(AttributeList *Attr);
+ StmtResult ParseIfStatement(ParsedAttributes &Attr);
+ StmtResult ParseSwitchStatement(ParsedAttributes &Attr);
+ StmtResult ParseWhileStatement(ParsedAttributes &Attr);
+ StmtResult ParseDoStatement(ParsedAttributes &Attr);
+ StmtResult ParseForStatement(ParsedAttributes &Attr);
+ StmtResult ParseGotoStatement(ParsedAttributes &Attr);
+ StmtResult ParseContinueStatement(ParsedAttributes &Attr);
+ StmtResult ParseBreakStatement(ParsedAttributes &Attr);
+ StmtResult ParseReturnStatement(ParsedAttributes &Attr);
StmtResult ParseAsmStatement(bool &msAsm);
StmtResult FuzzyParseMicrosoftAsmStatement(SourceLocation AsmLoc);
bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
//===--------------------------------------------------------------------===//
// C++ 6: Statements and Blocks
- StmtResult ParseCXXTryBlock(AttributeList *Attr);
+ StmtResult ParseCXXTryBlock(ParsedAttributes &Attr);
StmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc);
StmtResult ParseCXXCatchBlock();
DeclGroupPtrTy ParseDeclaration(StmtVector &Stmts,
unsigned Context, SourceLocation &DeclEnd,
- CXX0XAttributeList Attr);
+ ParsedAttributesWithRange &attrs);
DeclGroupPtrTy ParseSimpleDeclaration(StmtVector &Stmts,
unsigned Context,
SourceLocation &DeclEnd,
- AttributeList *Attr,
+ ParsedAttributes &attrs,
bool RequireSemi);
DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context,
bool AllowFunctionDefinitions,
TypeResult ParseTypeName(SourceRange *Range = 0);
void ParseBlockId();
- // EndLoc, if non-NULL, is filled with the location of the last token of
- // the attribute list.
- CXX0XAttributeList ParseCXX0XAttributes(SourceLocation *EndLoc = 0);
- void ParseMicrosoftAttributes();
- AttributeList *ParseGNUAttributes(SourceLocation *EndLoc = 0);
- AttributeList *ParseMicrosoftDeclSpec(AttributeList* CurrAttr = 0);
- AttributeList *ParseMicrosoftTypeAttributes(AttributeList* CurrAttr = 0);
- AttributeList *ParseBorlandTypeAttributes(AttributeList* CurrAttr = 0);
+
+ void ProhibitAttributes(ParsedAttributesWithRange &attrs) {
+ if (!attrs.Range.isValid()) return;
+ DiagnoseProhibitedAttributes(attrs);
+ }
+ void DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs);
+
+ void MaybeParseGNUAttributes(Declarator &D) {
+ if (Tok.is(tok::kw___attribute)) {
+ ParsedAttributes attrs;
+ SourceLocation endLoc;
+ ParseGNUAttributes(attrs, &endLoc);
+ D.addAttributes(attrs.getList(), endLoc);
+ }
+ }
+ void MaybeParseGNUAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = 0) {
+ if (Tok.is(tok::kw___attribute))
+ ParseGNUAttributes(attrs, endLoc);
+ }
+ void ParseGNUAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = 0);
+
+ void MaybeParseCXX0XAttributes(Declarator &D) {
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+ ParsedAttributesWithRange attrs;
+ SourceLocation endLoc;
+ ParseCXX0XAttributes(attrs, &endLoc);
+ D.addAttributes(attrs.getList(), endLoc);
+ }
+ }
+ void MaybeParseCXX0XAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = 0) {
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+ ParsedAttributesWithRange attrsWithRange;
+ ParseCXX0XAttributes(attrsWithRange, endLoc);
+ attrs.append(attrsWithRange.getList());
+ }
+ }
+ void MaybeParseCXX0XAttributes(ParsedAttributesWithRange &attrs,
+ SourceLocation *endLoc = 0) {
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+ ParseCXX0XAttributes(attrs, endLoc);
+ }
+ void ParseCXX0XAttributes(ParsedAttributesWithRange &attrs,
+ SourceLocation *EndLoc = 0);
+
+ void MaybeParseMicrosoftAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = 0) {
+ if (getLang().Microsoft && Tok.is(tok::l_square))
+ ParseMicrosoftAttributes(attrs, endLoc);
+ }
+ void ParseMicrosoftAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = 0);
+ void ParseMicrosoftDeclSpec(ParsedAttributes &attrs);
+ void ParseMicrosoftTypeAttributes(ParsedAttributes &attrs);
+ void ParseBorlandTypeAttributes(ParsedAttributes &attrs);
+
void ParseTypeofSpecifier(DeclSpec &DS);
void ParseDecltypeSpecifier(DeclSpec &DS);
typedef void (Parser::*DirectDeclParseFunction)(Declarator&);
void ParseDeclaratorInternal(Declarator &D,
DirectDeclParseFunction DirectDeclParser);
+
void ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed = true,
bool CXX0XAttributesAllowed = true);
void ParseDirectDeclarator(Declarator &D);
void ParseParenDeclarator(Declarator &D);
void ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
- AttributeList *AttrList = 0,
+ ParsedAttributes &attrs,
bool RequiresArg = false);
void ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
IdentifierInfo *FirstIdent,
Decl *ParseUsingDirectiveOrDeclaration(unsigned Context,
const ParsedTemplateInfo &TemplateInfo,
SourceLocation &DeclEnd,
- CXX0XAttributeList Attrs);
+ ParsedAttributesWithRange &attrs);
Decl *ParseUsingDirective(unsigned Context,
SourceLocation UsingLoc,
- SourceLocation &DeclEnd, AttributeList *Attr);
+ SourceLocation &DeclEnd,
+ ParsedAttributes &attrs);
Decl *ParseUsingDeclaration(unsigned Context,
const ParsedTemplateInfo &TemplateInfo,
SourceLocation UsingLoc,
IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
IdentifierInfo *ParmName, SourceLocation ParmLoc,
Expr **args, unsigned numargs,
- AttributeList *Next, bool declspec, bool cxx0x);
+ bool declspec, bool cxx0x);
public:
class Factory {
llvm::BumpPtrAllocator Alloc;
AttributeList *Create(IdentifierInfo *AttrName, SourceLocation AttrLoc,
IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
IdentifierInfo *ParmName, SourceLocation ParmLoc,
- Expr **args, unsigned numargs,
- AttributeList *Next, bool declspec = false, bool cxx0x = false) {
+ Expr **args, unsigned numargs, bool declspec = false, bool cxx0x = false) {
AttributeList *Mem = Alloc.Allocate<AttributeList>();
new (Mem) AttributeList(Alloc, AttrName, AttrLoc, ScopeName, ScopeLoc,
ParmName, ParmLoc, args, numargs,
- Next, declspec, cxx0x);
+ declspec, cxx0x);
return Mem;
}
};
}
};
+/// ParsedAttributes - A collection of parsed attributes. Currently
+/// we don't differentiate between the various attribute syntaxes,
+/// which is basically silly.
+///
+/// Right now this is a very lightweight container, but the expectation
+/// is that this will become significantly more serious.
+class ParsedAttributes {
+public:
+ ParsedAttributes() : list(0) {}
+
+ bool empty() const { return list == 0; }
+
+ void add(AttributeList *newAttr) {
+ assert(newAttr);
+ assert(newAttr->getNext() == 0);
+ newAttr->setNext(list);
+ list = newAttr;
+ }
+
+ void append(AttributeList *newList) {
+ if (!newList) return;
+
+ AttributeList *lastInNewList = newList;
+ while (AttributeList *next = lastInNewList->getNext())
+ lastInNewList = next;
+
+ lastInNewList->setNext(list);
+ list = newList;
+ }
+
+ void set(AttributeList *newList) {
+ list = newList;
+ }
+
+ void clear() { list = 0; }
+ AttributeList *getList() const { return list; }
+
+private:
+ AttributeList *list;
+};
+
} // end namespace clang
#endif
// storage-class-specifier
/*SCS*/unsigned StorageClassSpec : 3;
- bool SCS_thread_specified : 1;
- bool SCS_extern_in_linkage_spec : 1;
+ unsigned SCS_thread_specified : 1;
+ unsigned SCS_extern_in_linkage_spec : 1;
// type-specifier
/*TSW*/unsigned TypeSpecWidth : 2;
/*TSC*/unsigned TypeSpecComplex : 2;
/*TSS*/unsigned TypeSpecSign : 2;
/*TST*/unsigned TypeSpecType : 5;
- bool TypeAltiVecVector : 1;
- bool TypeAltiVecPixel : 1;
- bool TypeAltiVecBool : 1;
- bool TypeSpecOwned : 1;
+ unsigned TypeAltiVecVector : 1;
+ unsigned TypeAltiVecPixel : 1;
+ unsigned TypeAltiVecBool : 1;
+ unsigned TypeSpecOwned : 1;
// type-qualifiers
unsigned TypeQualifiers : 3; // Bitwise OR of TQ.
// function-specifier
- bool FS_inline_specified : 1;
- bool FS_virtual_specified : 1;
- bool FS_explicit_specified : 1;
+ unsigned FS_inline_specified : 1;
+ unsigned FS_virtual_specified : 1;
+ unsigned FS_explicit_specified : 1;
// friend-specifier
- bool Friend_specified : 1;
+ unsigned Friend_specified : 1;
// constexpr-specifier
- bool Constexpr_specified : 1;
+ unsigned Constexpr_specified : 1;
/*SCS*/unsigned StorageClassSpecAsWritten : 3;
};
// attributes.
- AttributeList *AttrList;
+ ParsedAttributes Attrs;
// Scope specifier for the type spec, if applicable.
CXXScopeSpec TypeScope;
Friend_specified(false),
Constexpr_specified(false),
StorageClassSpecAsWritten(SCS_unspecified),
- AttrList(0),
ProtocolQualifiers(0),
NumProtocolQualifiers(0),
ProtocolLocs(0),
/// short __attribute__((unused)) __attribute__((deprecated))
/// int __attribute__((may_alias)) __attribute__((aligned(16))) var;
///
- void AddAttributes(AttributeList *alist) {
- AttrList = addAttributeLists(AttrList, alist);
+ void addAttributes(AttributeList *AL) {
+ Attrs.append(AL);
}
- void SetAttributes(AttributeList *AL) { AttrList = AL; }
- const AttributeList *getAttributes() const { return AttrList; }
- AttributeList *getAttributes() { return AttrList; }
+ void aetAttributes(AttributeList *AL) {
+ Attrs.set(AL);
+ }
+
+ bool hasAttributes() const { return !Attrs.empty(); }
+
+ ParsedAttributes &getAttributes() { return Attrs; }
+ const ParsedAttributes &getAttributes() const { return Attrs; }
/// TakeAttributes - Return the current attribute list and remove them from
/// the DeclSpec so that it doesn't own them.
- AttributeList *TakeAttributes() {
- AttributeList *AL = AttrList;
- AttrList = 0;
- return AL;
+ ParsedAttributes takeAttributes() {
+ ParsedAttributes saved = Attrs;
+ Attrs.clear();
+ return saved;
+ }
+
+ void takeAttributesFrom(ParsedAttributes &attrs) {
+ Attrs.append(attrs.getList());
+ attrs.clear();
}
typedef Decl * const *ProtocolQualifierListTy;
/// EndLoc - If valid, the place where this chunck ends.
SourceLocation EndLoc;
- struct PointerTypeInfo {
+ struct TypeInfoCommon {
+ AttributeList *AttrList;
+ };
+
+ struct PointerTypeInfo : TypeInfoCommon {
/// The type qualifiers: const/volatile/restrict.
unsigned TypeQuals : 3;
- AttributeList *AttrList;
void destroy() {
}
};
- struct ReferenceTypeInfo {
+ struct ReferenceTypeInfo : TypeInfoCommon {
/// The type qualifier: restrict. [GNU] C++ extension
bool HasRestrict : 1;
/// True if this is an lvalue reference, false if it's an rvalue reference.
bool LValueRef : 1;
- AttributeList *AttrList;
void destroy() {
}
};
- struct ArrayTypeInfo {
+ struct ArrayTypeInfo : TypeInfoCommon {
/// The type qualifiers for the array: const/volatile/restrict.
unsigned TypeQuals : 3;
/// Since the parser is multi-purpose, and we don't want to impose a root
/// expression class on all clients, NumElts is untyped.
Expr *NumElts;
+
void destroy() {}
};
SourceRange Range;
};
- struct FunctionTypeInfo {
+ struct FunctionTypeInfo : TypeInfoCommon {
/// hasPrototype - This is true if the function had at least one typed
/// argument. If the function is () or (a,b,c), then it has no prototype,
/// and is treated as a K&R-style function.
- bool hasPrototype : 1;
+ unsigned hasPrototype : 1;
/// isVariadic - If this function has a prototype, and if that
/// proto ends with ',...)', this is true. When true, EllipsisLoc
/// contains the location of the ellipsis.
- bool isVariadic : 1;
+ unsigned isVariadic : 1;
/// The type qualifiers: const/volatile/restrict.
/// The qualifier bitmask values are the same as in QualType.
unsigned TypeQuals : 3;
/// hasExceptionSpec - True if the function has an exception specification.
- bool hasExceptionSpec : 1;
+ unsigned hasExceptionSpec : 1;
/// hasAnyExceptionSpec - True if the function has a throw(...) specifier.
- bool hasAnyExceptionSpec : 1;
+ unsigned hasAnyExceptionSpec : 1;
/// DeleteArgInfo - If this is true, we need to delete[] ArgInfo.
- bool DeleteArgInfo : 1;
+ unsigned DeleteArgInfo : 1;
/// When isVariadic is true, the location of the ellipsis in the source.
unsigned EllipsisLoc;
}
};
- struct BlockPointerTypeInfo {
+ struct BlockPointerTypeInfo : TypeInfoCommon {
/// For now, sema will catch these as invalid.
/// The type qualifiers: const/volatile/restrict.
unsigned TypeQuals : 3;
- AttributeList *AttrList;
+
void destroy() {
}
};
- struct MemberPointerTypeInfo {
+ struct MemberPointerTypeInfo : TypeInfoCommon {
/// The type qualifiers: const/volatile/restrict.
unsigned TypeQuals : 3;
- AttributeList *AttrList;
// CXXScopeSpec has a constructor, so it can't be a direct member.
// So we need some pointer-aligned storage and a bit of trickery.
union {
case Pointer: return Ptr.AttrList;
case Reference: return Ref.AttrList;
case MemberPointer: return Mem.AttrList;
- case Array: return 0;
- case Function: return 0;
+ case Array: return Arr.AttrList;
+ case Function: return Fun.AttrList;
case BlockPointer: return Cls.AttrList;
case Paren: return 0;
}
/// getPointer - Return a DeclaratorChunk for a pointer.
///
static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc,
- AttributeList *AL) {
+ const ParsedAttributes &attrs) {
DeclaratorChunk I;
I.Kind = Pointer;
I.Loc = Loc;
I.Ptr.TypeQuals = TypeQuals;
- I.Ptr.AttrList = AL;
+ I.Ptr.AttrList = attrs.getList();
return I;
}
/// getReference - Return a DeclaratorChunk for a reference.
///
static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc,
- AttributeList *AL, bool lvalue) {
+ const ParsedAttributes &attrs,
+ bool lvalue) {
DeclaratorChunk I;
I.Kind = Reference;
I.Loc = Loc;
I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0;
I.Ref.LValueRef = lvalue;
- I.Ref.AttrList = AL;
+ I.Ref.AttrList = attrs.getList();
return I;
}
/// getArray - Return a DeclaratorChunk for an array.
///
- static DeclaratorChunk getArray(unsigned TypeQuals, bool isStatic,
- bool isStar, Expr *NumElts,
+ static DeclaratorChunk getArray(unsigned TypeQuals,
+ const ParsedAttributes &attrs,
+ bool isStatic, bool isStar, Expr *NumElts,
SourceLocation LBLoc, SourceLocation RBLoc) {
DeclaratorChunk I;
I.Kind = Array;
I.Loc = LBLoc;
I.EndLoc = RBLoc;
+ I.Arr.AttrList = attrs.getList();
I.Arr.TypeQuals = TypeQuals;
I.Arr.hasStatic = isStatic;
I.Arr.isStar = isStar;
/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
/// "TheDeclarator" is the declarator that this will be added to.
- static DeclaratorChunk getFunction(bool hasProto, bool isVariadic,
+ static DeclaratorChunk getFunction(const ParsedAttributes &attrs,
+ bool hasProto, bool isVariadic,
SourceLocation EllipsisLoc,
ParamInfo *ArgInfo, unsigned NumArgs,
unsigned TypeQuals, bool hasExceptionSpec,
/// getBlockPointer - Return a DeclaratorChunk for a block.
///
static DeclaratorChunk getBlockPointer(unsigned TypeQuals, SourceLocation Loc,
- AttributeList *AL) {
+ const ParsedAttributes &attrs) {
DeclaratorChunk I;
I.Kind = BlockPointer;
I.Loc = Loc;
I.Cls.TypeQuals = TypeQuals;
- I.Cls.AttrList = AL;
+ I.Cls.AttrList = attrs.getList();
return I;
}
static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS,
unsigned TypeQuals,
SourceLocation Loc,
- AttributeList *AL) {
+ const ParsedAttributes &attrs) {
DeclaratorChunk I;
I.Kind = MemberPointer;
I.Loc = Loc;
I.Mem.TypeQuals = TypeQuals;
- I.Mem.AttrList = AL;
+ I.Mem.AttrList = attrs.getList();
new (I.Mem.ScopeMem.Mem) CXXScopeSpec(SS);
return I;
}
/// __attribute__((common,deprecated));
///
/// Also extends the range of the declarator.
- void AddAttributes(AttributeList *alist, SourceLocation LastLoc) {
+ void addAttributes(AttributeList *alist, SourceLocation LastLoc) {
AttrList = addAttributeLists(AttrList, alist);
if (!LastLoc.isInvalid())
SetRangeEnd(LastLoc);
}
+ void addAttributes(const ParsedAttributes &attrs) {
+ addAttributes(attrs.getList(), SourceLocation());
+ }
+
const AttributeList *getAttributes() const { return AttrList; }
AttributeList *getAttributes() { return AttrList; }
/// hasAttributes - do we contain any attributes?
bool hasAttributes() const {
- if (getAttributes() || getDeclSpec().getAttributes()) return true;
+ if (getAttributes() || getDeclSpec().hasAttributes()) return true;
for (unsigned i = 0, e = getNumTypeObjects(); i != e; ++i)
if (getTypeObject(i).getAttrs())
return true;
if (CanT.getObjCGCAttr() == GCAttr)
return T;
- if (T->isPointerType()) {
- QualType Pointee = T->getAs<PointerType>()->getPointeeType();
+ if (const PointerType *ptr = T->getAs<PointerType>()) {
+ QualType Pointee = ptr->getPointeeType();
if (Pointee->isAnyPointerType()) {
QualType ResultType = getObjCGCQualType(Pointee, GCAttr);
return getPointerType(ResultType);
/// attributes are very simple in practice. Until we find a bug, I don't see
/// a pressing need to implement the 2 token lookahead.
-AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) {
+void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc) {
assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!");
- AttributeList *CurrAttr = 0;
-
while (Tok.is(tok::kw___attribute)) {
ConsumeToken();
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
"attribute")) {
SkipUntil(tok::r_paren, true); // skip until ) or ;
- return CurrAttr;
+ return;
}
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "(")) {
SkipUntil(tok::r_paren, true); // skip until ) or ;
- return CurrAttr;
+ return;
}
// Parse the attribute-list. e.g. __attribute__(( weak, alias("__f") ))
while (Tok.is(tok::identifier) || isDeclarationSpecifier() ||
if (Tok.is(tok::r_paren)) {
// __attribute__(( mode(byte) ))
ConsumeParen(); // ignore the right paren loc for now
- CurrAttr = AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
- ParmName, ParmLoc, 0, 0, CurrAttr);
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
+ ParmName, ParmLoc, 0, 0));
} else if (Tok.is(tok::comma)) {
ConsumeToken();
// __attribute__(( format(printf, 1, 2) ))
}
if (ArgExprsOk && Tok.is(tok::r_paren)) {
ConsumeParen(); // ignore the right paren loc for now
- CurrAttr = AttrFactory.Create(AttrName, AttrNameLoc, 0,
- AttrNameLoc, ParmName, ParmLoc,
- ArgExprs.take(), ArgExprs.size(),
- CurrAttr);
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0,
+ AttrNameLoc, ParmName, ParmLoc,
+ ArgExprs.take(), ArgExprs.size()));
}
}
} else { // not an identifier
// parse a possibly empty comma separated list of expressions
// __attribute__(( nonnull() ))
ConsumeParen(); // ignore the right paren loc for now
- CurrAttr = AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
- 0, SourceLocation(), 0, 0, CurrAttr);
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
+ 0, SourceLocation(), 0, 0));
break;
case tok::kw_char:
case tok::kw_wchar_t:
case tok::kw_float:
case tok::kw_double:
case tok::kw_void:
- case tok::kw_typeof:
- CurrAttr = AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
- 0, SourceLocation(), 0, 0, CurrAttr);
- if (CurrAttr->getKind() == AttributeList::AT_IBOutletCollection)
+ case tok::kw_typeof: {
+ AttributeList *attr
+ = AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
+ 0, SourceLocation(), 0, 0);
+ attrs.add(attr);
+ if (attr->getKind() == AttributeList::AT_IBOutletCollection)
Diag(Tok, diag::err_iboutletcollection_builtintype);
// If it's a builtin type name, eat it and expect a rparen
// __attribute__(( vec_type_hint(char) ))
if (Tok.is(tok::r_paren))
ConsumeParen();
break;
+ }
default:
// __attribute__(( aligned(16) ))
ExprVector ArgExprs(Actions);
// Match the ')'.
if (ArgExprsOk && Tok.is(tok::r_paren)) {
ConsumeParen(); // ignore the right paren loc for now
- CurrAttr = AttrFactory.Create(AttrName, AttrNameLoc, 0,
- AttrNameLoc, 0, SourceLocation(), ArgExprs.take(),
- ArgExprs.size(),
- CurrAttr);
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0,
+ AttrNameLoc, 0, SourceLocation(),
+ ArgExprs.take(), ArgExprs.size()));
}
break;
}
}
} else {
- CurrAttr = AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
- 0, SourceLocation(), 0, 0, CurrAttr);
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
+ 0, SourceLocation(), 0, 0));
}
}
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) {
SkipUntil(tok::r_paren, false);
}
- if (EndLoc)
- *EndLoc = Loc;
+ if (endLoc)
+ *endLoc = Loc;
}
- return CurrAttr;
}
/// ParseMicrosoftDeclSpec - Parse an __declspec construct
/// extended-decl-modifier[opt]
/// extended-decl-modifier extended-decl-modifier-seq
-AttributeList* Parser::ParseMicrosoftDeclSpec(AttributeList *CurrAttr) {
+void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &attrs) {
assert(Tok.is(tok::kw___declspec) && "Not a declspec!");
ConsumeToken();
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
"declspec")) {
SkipUntil(tok::r_paren, true); // skip until ) or ;
- return CurrAttr;
+ return;
}
while (Tok.getIdentifierInfo()) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
ExprResult ArgExpr(ParseAssignmentExpression());
if (!ArgExpr.isInvalid()) {
Expr *ExprList = ArgExpr.take();
- CurrAttr = AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
- SourceLocation(), &ExprList, 1,
- CurrAttr, true);
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
+ SourceLocation(), &ExprList, 1, true));
}
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
SkipUntil(tok::r_paren, false);
} else {
- CurrAttr = AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
- 0, SourceLocation(), 0, 0, CurrAttr, true);
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
+ 0, SourceLocation(), 0, 0, true));
}
}
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
SkipUntil(tok::r_paren, false);
- return CurrAttr;
+ return;
}
-AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) {
+void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) {
// Treat these like attributes
// FIXME: Allow Sema to distinguish between these and real attributes!
while (Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___stdcall) ||
if (Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64))
// FIXME: Support these properly!
continue;
- CurrAttr = AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
- SourceLocation(), 0, 0, CurrAttr, true);
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
+ SourceLocation(), 0, 0, true));
}
- return CurrAttr;
}
-AttributeList* Parser::ParseBorlandTypeAttributes(AttributeList *CurrAttr) {
+void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) {
// Treat these like attributes
while (Tok.is(tok::kw___pascal)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
- CurrAttr = AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
- SourceLocation(), 0, 0, CurrAttr, true);
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
+ SourceLocation(), 0, 0, true));
}
- return CurrAttr;
+}
+
+void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) {
+ Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed)
+ << attrs.Range;
}
/// ParseDeclaration - Parse a full 'declaration', which consists of
Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts,
unsigned Context,
SourceLocation &DeclEnd,
- CXX0XAttributeList Attr) {
+ ParsedAttributesWithRange &attrs) {
ParenBraceBracketBalancer BalancerRAIIObj(*this);
Decl *SingleDecl = 0;
switch (Tok.getKind()) {
case tok::kw_template:
case tok::kw_export:
- if (Attr.HasAttr)
- Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
- << Attr.Range;
+ ProhibitAttributes(attrs);
SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd);
break;
case tok::kw_inline:
// Could be the start of an inline namespace. Allowed as an ext in C++03.
if (getLang().CPlusPlus && NextToken().is(tok::kw_namespace)) {
- if (Attr.HasAttr)
- Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
- << Attr.Range;
+ ProhibitAttributes(attrs);
SourceLocation InlineLoc = ConsumeToken();
SingleDecl = ParseNamespace(Context, DeclEnd, InlineLoc);
break;
}
- return ParseSimpleDeclaration(Stmts, Context, DeclEnd, Attr.AttrList,
+ return ParseSimpleDeclaration(Stmts, Context, DeclEnd, attrs,
true);
case tok::kw_namespace:
- if (Attr.HasAttr)
- Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
- << Attr.Range;
+ ProhibitAttributes(attrs);
SingleDecl = ParseNamespace(Context, DeclEnd);
break;
case tok::kw_using:
SingleDecl = ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(),
- DeclEnd, Attr);
+ DeclEnd, attrs);
break;
case tok::kw_static_assert:
- if (Attr.HasAttr)
- Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
- << Attr.Range;
+ ProhibitAttributes(attrs);
SingleDecl = ParseStaticAssertDeclaration(DeclEnd);
break;
default:
- return ParseSimpleDeclaration(Stmts, Context, DeclEnd, Attr.AttrList,
- true);
+ return ParseSimpleDeclaration(Stmts, Context, DeclEnd, attrs, true);
}
// This routine returns a DeclGroup, if the thing we parsed only contains a
Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(StmtVector &Stmts,
unsigned Context,
SourceLocation &DeclEnd,
- AttributeList *Attr,
+ ParsedAttributes &attrs,
bool RequireSemi) {
// Parse the common declaration-specifiers piece.
ParsingDeclSpec DS(*this);
- if (Attr)
- DS.AddAttributes(Attr);
+ DS.takeAttributesFrom(attrs);
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none,
getDeclSpecContextFromDeclaratorContext(Context));
StmtResult R = Actions.ActOnVlaStmt(DS);
// short __attribute__((common)) var; -> declspec
// short var __attribute__((common)); -> declarator
// short x, __attribute__((common)) var; -> declarator
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- D.AddAttributes(AttrList, Loc);
- }
+ MaybeParseGNUAttributes(D);
ParseDeclarator(D);
D.SetRangeEnd(Loc);
}
- // If attributes are present, parse them.
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- D.AddAttributes(AttrList, Loc);
- }
+ MaybeParseGNUAttributes(D);
// Inform the current actions module that we just parsed this declarator.
Decl *ThisDecl = 0;
// Validate declspec for type-name.
unsigned Specs = DS.getParsedSpecifiers();
if (Specs == DeclSpec::PQ_None && !DS.getNumProtocolQualifiers() &&
- !DS.getAttributes())
+ !DS.hasAttributes())
Diag(Tok, diag::err_typename_requires_specqual);
// Issue diagnostic and remove storage class if present.
// GNU attributes support.
case tok::kw___attribute:
- DS.AddAttributes(ParseGNUAttributes());
+ ParseGNUAttributes(DS.getAttributes());
continue;
// Microsoft declspec support.
case tok::kw___declspec:
- DS.AddAttributes(ParseMicrosoftDeclSpec());
+ ParseMicrosoftDeclSpec(DS.getAttributes());
continue;
// Microsoft single token adornments.
case tok::kw___stdcall:
case tok::kw___fastcall:
case tok::kw___thiscall:
- DS.AddAttributes(ParseMicrosoftTypeAttributes());
+ ParseMicrosoftTypeAttributes(DS.getAttributes());
continue;
// Borland single token adornments.
case tok::kw___pascal:
- DS.AddAttributes(ParseBorlandTypeAttributes());
+ ParseBorlandTypeAttributes(DS.getAttributes());
continue;
// storage-class-specifier
case tok::kw___stdcall:
case tok::kw___fastcall:
case tok::kw___thiscall:
- DS.AddAttributes(ParseMicrosoftTypeAttributes());
+ ParseMicrosoftTypeAttributes(DS.getAttributes());
return true;
case tok::kw___pascal:
- DS.AddAttributes(ParseBorlandTypeAttributes());
+ ParseBorlandTypeAttributes(DS.getAttributes());
return true;
default:
FieldDeclarator DeclaratorInfo(DS);
// Attributes are only allowed here on successive declarators.
- if (!FirstDeclarator && Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- DeclaratorInfo.D.AddAttributes(AttrList, Loc);
- }
+ if (!FirstDeclarator)
+ MaybeParseGNUAttributes(DeclaratorInfo.D);
/// struct-declarator: declarator
/// struct-declarator: declarator[opt] ':' constant-expression
}
// If attributes exist after the declarator, parse them.
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- DeclaratorInfo.D.AddAttributes(AttrList, Loc);
- }
+ MaybeParseGNUAttributes(DeclaratorInfo.D);
// We're done with this declarator; invoke the callback.
Decl *D = Fields.invoke(DeclaratorInfo);
SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
- AttributeList *AttrList = 0;
+ ParsedAttributes attrs;
// If attributes exist after struct contents, parse them.
- if (Tok.is(tok::kw___attribute))
- AttrList = ParseGNUAttributes();
+ MaybeParseGNUAttributes(attrs);
Actions.ActOnFields(getCurScope(),
RecordLoc, TagDecl, FieldDecls.data(), FieldDecls.size(),
LBraceLoc, RBraceLoc,
- AttrList);
+ attrs.getList());
StructScope.Exit();
Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, RBraceLoc);
}
ConsumeCodeCompletionToken();
}
- AttributeList *Attr = 0;
// If attributes exist after tag, parse them.
- if (Tok.is(tok::kw___attribute))
- Attr = ParseGNUAttributes();
+ ParsedAttributes attrs;
+ MaybeParseGNUAttributes(attrs);
CXXScopeSpec &SS = DS.getTypeSpecScope();
if (getLang().CPlusPlus) {
const char *PrevSpec = 0;
unsigned DiagID;
Decl *TagDecl = Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK,
- StartLoc, SS, Name, NameLoc, Attr,
+ StartLoc, SS, Name, NameLoc, attrs.getList(),
AS,
MultiTemplateParamsArg(Actions),
Owned, IsDependent, IsScopedEnum,
SourceLocation IdentLoc = ConsumeToken();
// If attributes exist after the enumerator, parse them.
- AttributeList *Attr = 0;
- if (Tok.is(tok::kw___attribute))
- Attr = ParseGNUAttributes();
+ ParsedAttributes attrs;
+ MaybeParseGNUAttributes(attrs);
SourceLocation EqualLoc;
ExprResult AssignedVal;
Decl *EnumConstDecl = Actions.ActOnEnumConstant(getCurScope(), EnumDecl,
LastEnumConstDecl,
IdentLoc, Ident,
- Attr, EqualLoc,
+ attrs.getList(), EqualLoc,
AssignedVal.release());
EnumConstantDecls.push_back(EnumConstDecl);
LastEnumConstDecl = EnumConstDecl;
// Eat the }.
SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
- AttributeList *Attr = 0;
// If attributes exist after the identifier list, parse them.
- if (Tok.is(tok::kw___attribute))
- Attr = ParseGNUAttributes(); // FIXME: where do they do?
+ ParsedAttributes attrs;
+ MaybeParseGNUAttributes(attrs);
Actions.ActOnEnumBody(StartLoc, LBraceLoc, RBraceLoc, EnumDecl,
EnumConstantDecls.data(), EnumConstantDecls.size(),
- getCurScope(), Attr);
+ getCurScope(), attrs.getList());
EnumScope.Exit();
Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl, RBraceLoc);
bool CXX0XAttributesAllowed) {
if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
SourceLocation Loc = Tok.getLocation();
- CXX0XAttributeList Attr = ParseCXX0XAttributes();
+ ParsedAttributesWithRange attrs;
+ ParseCXX0XAttributes(attrs);
if (CXX0XAttributesAllowed)
- DS.AddAttributes(Attr.AttrList);
+ DS.takeAttributesFrom(attrs);
else
Diag(Loc, diag::err_attributes_not_allowed);
}
case tok::kw___fastcall:
case tok::kw___thiscall:
if (VendorAttributesAllowed) {
- DS.AddAttributes(ParseMicrosoftTypeAttributes());
+ ParseMicrosoftTypeAttributes(DS.getAttributes());
continue;
}
goto DoneWithTypeQuals;
case tok::kw___pascal:
if (VendorAttributesAllowed) {
- DS.AddAttributes(ParseBorlandTypeAttributes());
+ ParseBorlandTypeAttributes(DS.getAttributes());
continue;
}
goto DoneWithTypeQuals;
case tok::kw___attribute:
if (VendorAttributesAllowed) {
- DS.AddAttributes(ParseGNUAttributes());
+ ParseGNUAttributes(DS.getAttributes());
continue; // do *not* consume the next token!
}
// otherwise, FALL THROUGH!
// Sema will have to catch (syntactically invalid) pointers into global
// scope. It has to catch pointers into namespace scope anyway.
D.AddTypeInfo(DeclaratorChunk::getMemberPointer(SS,DS.getTypeQualifiers(),
- Loc, DS.TakeAttributes()),
+ Loc, DS.takeAttributes()),
/* Don't replace range end. */SourceLocation());
return;
}
if (Kind == tok::star)
// Remember that we parsed a pointer type, and remember the type-quals.
D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc,
- DS.TakeAttributes()),
+ DS.takeAttributes()),
SourceLocation());
else
// Remember that we parsed a Block type, and remember the type-quals.
D.AddTypeInfo(DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(),
- Loc, DS.TakeAttributes()),
+ Loc, DS.takeAttributes()),
SourceLocation());
} else {
// Is a reference
// Remember that we parsed a reference type. It doesn't have type-quals.
D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc,
- DS.TakeAttributes(),
+ DS.takeAttributes(),
Kind == tok::amp),
SourceLocation());
}
"Haven't past the location of the identifier yet?");
// Don't parse attributes unless we have an identifier.
- if (D.getIdentifier() && getLang().CPlusPlus0x
- && isCXX0XAttributeSpecifier(true)) {
- SourceLocation AttrEndLoc;
- CXX0XAttributeList Attr = ParseCXX0XAttributes();
- D.AddAttributes(Attr.AttrList, AttrEndLoc);
- }
+ if (D.getIdentifier())
+ MaybeParseCXX0XAttributes(D);
while (1) {
if (Tok.is(tok::l_paren)) {
if (!isCXXFunctionDeclarator(warnIfAmbiguous))
break;
}
- ParseFunctionDeclarator(ConsumeParen(), D);
+ ParsedAttributes attrs;
+ ParseFunctionDeclarator(ConsumeParen(), D, attrs);
} else if (Tok.is(tok::l_square)) {
ParseBracketDeclarator(D);
} else {
// In either case, we need to eat any attributes to be able to determine what
// sort of paren this is.
//
- AttributeList *AttrList = 0;
+ ParsedAttributes attrs;
bool RequiresArg = false;
if (Tok.is(tok::kw___attribute)) {
- AttrList = ParseGNUAttributes();
+ ParseGNUAttributes(attrs);
// We require that the argument list (if this is a non-grouping paren) be
// present even if the attribute list was empty.
if (Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___stdcall) ||
Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___fastcall) ||
Tok.is(tok::kw___w64) || Tok.is(tok::kw___ptr64)) {
- AttrList = ParseMicrosoftTypeAttributes(AttrList);
+ ParseMicrosoftTypeAttributes(attrs);
}
// Eat any Borland extensions.
if (Tok.is(tok::kw___pascal))
- AttrList = ParseBorlandTypeAttributes(AttrList);
+ ParseBorlandTypeAttributes(attrs);
// If we haven't past the identifier yet (or where the identifier would be
// stored, if this is an abstract declarator), then this is probably just
if (isGrouping) {
bool hadGroupingParens = D.hasGroupingParens();
D.setGroupingParens(true);
- if (AttrList)
- D.AddAttributes(AttrList, SourceLocation());
+ if (!attrs.empty())
+ D.addAttributes(attrs.getList(), SourceLocation());
ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
// Match the ')'.
// ParseFunctionDeclarator to handle of argument list.
D.SetIdentifier(0, Tok.getLocation());
- ParseFunctionDeclarator(StartLoc, D, AttrList, RequiresArg);
+ ParseFunctionDeclarator(StartLoc, D, attrs, RequiresArg);
}
/// ParseFunctionDeclarator - We are after the identifier and have parsed the
/// and "exception-specification[opt]".
///
void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
- AttributeList *AttrList,
+ ParsedAttributes &attrs,
bool RequiresArg) {
// lparen is already consumed!
assert(D.isPastIdentifier() && "Should not call before identifier!");
llvm::SmallVector<ParsedType, 2> Exceptions;
llvm::SmallVector<SourceRange, 2> ExceptionRanges;
if (getLang().CPlusPlus) {
+ MaybeParseCXX0XAttributes(attrs);
+
ParseTypeQualifierListOpt(DS, false /*no attributes*/);
if (!DS.getSourceRange().getEnd().isInvalid())
EndLoc = DS.getSourceRange().getEnd();
// Remember that we parsed a function type, and remember the attributes.
// int() -> no prototype, no '...'.
- D.AddTypeInfo(DeclaratorChunk::getFunction(/*prototype*/getLang().CPlusPlus,
+ D.AddTypeInfo(DeclaratorChunk::getFunction(attrs,
+ /*prototype*/getLang().CPlusPlus,
/*variadic*/ false,
SourceLocation(),
/*arglist*/ 0, 0,
EllipsisLoc = ConsumeToken(); // Consume the ellipsis.
break;
}
+
+ // Parse the declaration-specifiers.
+ // Just use the ParsingDeclaration "scope" of the declarator.
+ DeclSpec DS;
// Skip any Microsoft attributes before a param.
if (getLang().Microsoft && Tok.is(tok::l_square))
- ParseMicrosoftAttributes();
+ ParseMicrosoftAttributes(DS.getAttributes());
SourceLocation DSStart = Tok.getLocation();
- // Parse the declaration-specifiers.
- // Just use the ParsingDeclaration "scope" of the declarator.
- DeclSpec DS;
-
// If the caller parsed attributes for the first argument, add them now.
- if (AttrList) {
- DS.AddAttributes(AttrList);
- AttrList = 0; // Only apply the attributes to the first parameter.
- }
+ // Take them so that we only apply the attributes to the first parameter.
+ DS.takeAttributesFrom(attrs);
+
ParseDeclarationSpecifiers(DS);
// Parse the declarator. This is "PrototypeContext", because we must
ParseDeclarator(ParmDecl);
// Parse GNU attributes, if present.
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- ParmDecl.AddAttributes(AttrList, Loc);
- }
+ MaybeParseGNUAttributes(ParmDecl);
// Remember this parsed parameter in ParamInfo.
IdentifierInfo *ParmII = ParmDecl.getIdentifier();
llvm::SmallVector<SourceRange, 2> ExceptionRanges;
if (getLang().CPlusPlus) {
+ MaybeParseCXX0XAttributes(attrs);
+
// Parse cv-qualifier-seq[opt].
ParseTypeQualifierListOpt(DS, false /*no attributes*/);
if (!DS.getSourceRange().getEnd().isInvalid())
PrototypeScope.Exit();
// Remember that we parsed a function type, and remember the attributes.
- D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic,
+ D.AddTypeInfo(DeclaratorChunk::getFunction(attrs,
+ /*proto*/true, IsVariadic,
EllipsisLoc,
ParamInfo.data(), ParamInfo.size(),
DS.getTypeQualifiers(),
// Remember that we parsed a function type, and remember the attributes. This
// function type is always a K&R style function type, which is not varargs and
// has no prototype.
- D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/false, /*varargs*/false,
+ D.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(),
+ /*proto*/false, /*varargs*/false,
SourceLocation(),
&ParamInfo[0], ParamInfo.size(),
/*TypeQuals*/0,
// This code does a fast path to handle some of the most obvious cases.
if (Tok.getKind() == tok::r_square) {
SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
- //FIXME: Use these
- CXX0XAttributeList Attr;
- if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier(true)) {
- Attr = ParseCXX0XAttributes();
- }
+ ParsedAttributes attrs;
+ MaybeParseCXX0XAttributes(attrs);
// Remember that we parsed the empty array type.
ExprResult NumElements;
- D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0,
+ D.AddTypeInfo(DeclaratorChunk::getArray(0, attrs, false, false, 0,
StartLoc, EndLoc),
EndLoc);
return;
ConsumeToken();
SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
- //FIXME: Use these
- CXX0XAttributeList Attr;
- if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
- Attr = ParseCXX0XAttributes();
- }
-
- // If there was an error parsing the assignment-expression, recover.
- if (ExprRes.isInvalid())
- ExprRes.release(); // Deallocate expr, just use [].
+ ParsedAttributes attrs;
+ MaybeParseCXX0XAttributes(attrs);
// Remember that we parsed a array type, and remember its features.
- D.AddTypeInfo(DeclaratorChunk::getArray(0, false, 0, ExprRes.release(),
+ D.AddTypeInfo(DeclaratorChunk::getArray(0, attrs, false, 0,
+ ExprRes.release(),
StartLoc, EndLoc),
EndLoc);
return;
SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
- //FIXME: Use these
- CXX0XAttributeList Attr;
- if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
- Attr = ParseCXX0XAttributes();
- }
+ ParsedAttributes attrs;
+ MaybeParseCXX0XAttributes(attrs);
// Remember that we parsed a array type, and remember its features.
- D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(),
+ D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(), attrs,
StaticLoc.isValid(), isStar,
NumElements.release(),
StartLoc, EndLoc),
}
// Read label attributes, if present.
- AttributeList *AttrList = 0;
+ ParsedAttributes attrs;
if (Tok.is(tok::kw___attribute)) {
attrTok = Tok;
// FIXME: save these somewhere.
- AttrList = ParseGNUAttributes();
+ ParseGNUAttributes(attrs);
}
if (Tok.is(tok::equal)) {
- if (AttrList)
+ if (!attrs.empty())
Diag(attrTok, diag::err_unexpected_namespace_attributes_alias);
if (InlineLoc.isValid())
Diag(InlineLoc, diag::err_inline_namespace_alias)
Decl *NamespcDecl =
Actions.ActOnStartNamespaceDef(getCurScope(), InlineLoc, IdentLoc, Ident,
- LBrace, AttrList);
+ LBrace, attrs.getList());
PrettyDeclStackTraceEntry CrashInfo(Actions, NamespcDecl, NamespaceLoc,
"parsing namespace");
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
- CXX0XAttributeList Attr;
- if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
- Attr = ParseCXX0XAttributes();
- if (getLang().Microsoft && Tok.is(tok::l_square))
- ParseMicrosoftAttributes();
- ParseExternalDeclaration(Attr);
+ ParsedAttributesWithRange attrs;
+ MaybeParseCXX0XAttributes(attrs);
+ MaybeParseMicrosoftAttributes(attrs);
+ ParseExternalDeclaration(attrs);
}
// Leave the namespace scope.
Tok.is(tok::l_brace)? Tok.getLocation()
: SourceLocation());
- CXX0XAttributeList Attr;
- if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
- Attr = ParseCXX0XAttributes();
-
- if (getLang().Microsoft && Tok.is(tok::l_square))
- ParseMicrosoftAttributes();
+ ParsedAttributesWithRange attrs;
+ MaybeParseCXX0XAttributes(attrs);
+ MaybeParseMicrosoftAttributes(attrs);
if (Tok.isNot(tok::l_brace)) {
DS.setExternInLinkageSpec(true);
- ParseExternalDeclaration(Attr, &DS);
+ ParseExternalDeclaration(attrs, &DS);
return Actions.ActOnFinishLinkageSpecification(getCurScope(), LinkageSpec,
SourceLocation());
}
DS.abort();
- if (Attr.HasAttr)
- Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
- << Attr.Range;
+ ProhibitAttributes(attrs);
SourceLocation LBrace = ConsumeBrace();
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
- CXX0XAttributeList Attr;
- if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
- Attr = ParseCXX0XAttributes();
- if (getLang().Microsoft && Tok.is(tok::l_square))
- ParseMicrosoftAttributes();
- ParseExternalDeclaration(Attr);
+ ParsedAttributesWithRange attrs;
+ MaybeParseCXX0XAttributes(attrs);
+ MaybeParseMicrosoftAttributes(attrs);
+ ParseExternalDeclaration(attrs);
}
SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
const ParsedTemplateInfo &TemplateInfo,
SourceLocation &DeclEnd,
- CXX0XAttributeList Attr) {
+ ParsedAttributesWithRange &attrs) {
assert(Tok.is(tok::kw_using) && "Not using token");
// Eat 'using'.
<< R << FixItHint::CreateRemoval(R);
}
- return ParseUsingDirective(Context, UsingLoc, DeclEnd, Attr.AttrList);
+ return ParseUsingDirective(Context, UsingLoc, DeclEnd, attrs);
}
// Otherwise, it must be a using-declaration.
// Using declarations can't have attributes.
- if (Attr.HasAttr)
- Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
- << Attr.Range;
+ ProhibitAttributes(attrs);
return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd);
}
Decl *Parser::ParseUsingDirective(unsigned Context,
SourceLocation UsingLoc,
SourceLocation &DeclEnd,
- AttributeList *Attr) {
+ ParsedAttributes &attrs) {
assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token");
// Eat 'namespace'.
bool GNUAttr = false;
if (Tok.is(tok::kw___attribute)) {
GNUAttr = true;
- Attr = addAttributeLists(Attr, ParseGNUAttributes());
+ ParseGNUAttributes(attrs);
}
// Eat ';'.
"", tok::semi);
return Actions.ActOnUsingDirective(getCurScope(), UsingLoc, NamespcLoc, SS,
- IdentLoc, NamespcName, Attr);
+ IdentLoc, NamespcName, attrs.getList());
}
/// ParseUsingDeclaration - Parse C++ using-declaration. Assumes that
}
// Parse (optional) attributes (most likely GNU strong-using extension).
- AttributeList *AttrList = 0;
- if (Tok.is(tok::kw___attribute))
- AttrList = ParseGNUAttributes();
+ ParsedAttributes attrs;
+ MaybeParseGNUAttributes(attrs);
// Eat ';'.
DeclEnd = Tok.getLocation();
ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
- AttrList ? "attributes list" : "using declaration",
+ !attrs.empty() ? "attributes list" : "using declaration",
tok::semi);
// Diagnose an attempt to declare a templated using-declaration.
}
return Actions.ActOnUsingDeclaration(getCurScope(), AS, true, UsingLoc, SS,
- Name, AttrList, IsTypeName, TypenameLoc);
+ Name, attrs.getList(),
+ IsTypeName, TypenameLoc);
}
/// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion.
SuppressingAccessChecks = true;
}
- AttributeList *AttrList = 0;
+ ParsedAttributes attrs;
// If attributes exist after tag, parse them.
if (Tok.is(tok::kw___attribute))
- AttrList = ParseGNUAttributes();
+ ParseGNUAttributes(attrs);
// If declspecs exist after tag, parse them.
while (Tok.is(tok::kw___declspec))
- AttrList = ParseMicrosoftDeclSpec(AttrList);
+ ParseMicrosoftDeclSpec(attrs);
// If C++0x attributes exist here, parse them.
// FIXME: Are we consistent with the ordering of parsing of different
// styles of attributes?
- if (isCXX0XAttributeSpecifier())
- AttrList = addAttributeLists(AttrList, ParseCXX0XAttributes().AttrList);
+ MaybeParseCXX0XAttributes(attrs);
if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_pod)) {
// GNU libstdc++ 4.2 uses __is_pod as the name of a struct template, but
TemplateId->LAngleLoc,
TemplateArgsPtr,
TemplateId->RAngleLoc,
- AttrList);
+ attrs.getList());
// Friend template-ids are treated as references unless
// they have template headers, in which case they're ill-formed
TemplateId->LAngleLoc,
TemplateArgsPtr,
TemplateId->RAngleLoc,
- AttrList,
+ attrs.getList(),
MultiTemplateParamsArg(Actions,
TemplateParams? &(*TemplateParams)[0] : 0,
TemplateParams? TemplateParams->size() : 0));
TemplateInfo.ExternLoc,
TemplateInfo.TemplateLoc,
TagType, StartLoc, SS, Name,
- NameLoc, AttrList);
+ NameLoc, attrs.getList());
} else if (TUK == Sema::TUK_Friend &&
TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) {
TagOrTempResult =
Actions.ActOnTemplatedFriendTag(getCurScope(), DS.getFriendSpecLoc(),
TagType, StartLoc, SS,
- Name, NameLoc, AttrList,
+ Name, NameLoc, attrs.getList(),
MultiTemplateParamsArg(Actions,
TemplateParams? &(*TemplateParams)[0] : 0,
TemplateParams? TemplateParams->size() : 0));
// Declaration or definition of a class type
TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc,
- SS, Name, NameLoc, AttrList, AS,
+ SS, Name, NameLoc, attrs.getList(), AS,
TParams, Owned, IsDependent, false,
false, clang::TypeResult());
// is a bitfield.
ColonProtectionRAIIObject X(*this);
- CXX0XAttributeList AttrList;
+ ParsedAttributesWithRange attrs;
// Optional C++0x attribute-specifier
- if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
- AttrList = ParseCXX0XAttributes();
- if (getLang().Microsoft && Tok.is(tok::l_square))
- ParseMicrosoftAttributes();
+ MaybeParseCXX0XAttributes(attrs);
+ MaybeParseMicrosoftAttributes(attrs);
if (Tok.is(tok::kw_using)) {
// FIXME: Check for template aliases
- if (AttrList.HasAttr)
- Diag(AttrList.Range.getBegin(), diag::err_attributes_not_allowed)
- << AttrList.Range;
+ ProhibitAttributes(attrs);
// Eat 'using'.
SourceLocation UsingLoc = ConsumeToken();
// decl-specifier-seq:
// Parse the common declaration-specifiers piece.
ParsingDeclSpec DS(*this, TemplateDiags);
- DS.AddAttributes(AttrList.AttrList);
+ DS.takeAttributesFrom(attrs);
ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class);
MultiTemplateParamsArg TemplateParams(Actions,
}
// If attributes exist after the declarator, but before an '{', parse them.
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- DeclaratorInfo.AddAttributes(AttrList, Loc);
- }
+ MaybeParseGNUAttributes(DeclaratorInfo);
// function-definition:
if (Tok.is(tok::l_brace)
}
// If attributes exist after the declarator, parse them.
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- DeclaratorInfo.AddAttributes(AttrList, Loc);
- }
+ MaybeParseGNUAttributes(DeclaratorInfo);
// NOTE: If Sema is the Action module and declarator is an instance field,
// this call will *not* return the created decl; It will return null.
Deleted = false;
// Attributes are only allowed on the second declarator.
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- DeclaratorInfo.AddAttributes(AttrList, Loc);
- }
+ MaybeParseGNUAttributes(DeclaratorInfo);
if (Tok.isNot(tok::colon))
ParseDeclarator(DeclaratorInfo);
}
// If attributes exist after class contents, parse them.
- AttributeList *AttrList = 0;
- if (Tok.is(tok::kw___attribute))
- AttrList = ParseGNUAttributes();
+ ParsedAttributes attrs;
+ MaybeParseGNUAttributes(attrs);
if (TagDecl)
Actions.ActOnFinishCXXMemberSpecification(getCurScope(), RecordLoc, TagDecl,
LBraceLoc, RBraceLoc,
- AttrList);
+ attrs.getList());
// C++ 9.2p2: Within the class member-specification, the class is regarded as
// complete within function bodies, default arguments,
/// '[' balanced-token-seq ']'
/// '{' balanced-token-seq '}'
/// any token but '(', ')', '[', ']', '{', or '}'
-CXX0XAttributeList Parser::ParseCXX0XAttributes(SourceLocation *EndLoc) {
+void Parser::ParseCXX0XAttributes(ParsedAttributesWithRange &attrs,
+ SourceLocation *endLoc) {
assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square)
&& "Not a C++0x attribute list");
SourceLocation StartLoc = Tok.getLocation(), Loc;
- AttributeList *CurrAttr = 0;
ConsumeBracket();
ConsumeBracket();
break;
}
- CurrAttr = AttrFactory.Create(AttrName, AttrLoc, 0, AttrLoc, 0,
- SourceLocation(), 0, 0, CurrAttr, false,
- true);
+ attrs.add(AttrFactory.Create(AttrName, AttrLoc, 0, AttrLoc, 0,
+ SourceLocation(), 0, 0, false, true));
AttrParsed = true;
break;
}
ExprVector ArgExprs(Actions);
ArgExprs.push_back(ArgExpr.release());
- CurrAttr = AttrFactory.Create(AttrName, AttrLoc, 0, AttrLoc,
- 0, ParamLoc, ArgExprs.take(), 1, CurrAttr,
- false, true);
+ attrs.add(AttrFactory.Create(AttrName, AttrLoc, 0, AttrLoc,
+ 0, ParamLoc, ArgExprs.take(), 1,
+ false, true));
AttrParsed = true;
break;
if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
SkipUntil(tok::r_square, false);
- CXX0XAttributeList Attr (CurrAttr, SourceRange(StartLoc, Loc), true);
- return Attr;
+ attrs.Range = SourceRange(StartLoc, Loc);
}
/// ParseCXX0XAlignArgument - Parse the argument to C++0x's [[align]]
/// [MS] ms-attribute-seq:
/// ms-attribute[opt]
/// ms-attribute ms-attribute-seq
-void Parser::ParseMicrosoftAttributes() {
+void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc) {
assert(Tok.is(tok::l_square) && "Not a Microsoft attribute list");
while (Tok.is(tok::l_square)) {
ConsumeBracket();
SkipUntil(tok::r_square, true, true);
+ if (endLoc) *endLoc = Tok.getLocation();
ExpectAndConsume(tok::r_square, diag::err_expected_rsquare);
}
}
if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
Diag(Tok, diag::ext_gnu_statement_expr);
- StmtResult Stmt(ParseCompoundStatement(0, true));
+ ParsedAttributes attrs;
+ StmtResult Stmt(ParseCompoundStatement(attrs, true));
ExprType = CompoundStmt;
// If the substmt parsed correctly, build the AST node.
ParseDeclarator(DeclaratorInfo);
// We do this for: ^ __attribute__((noreturn)) {, as DS has the attributes.
- DeclaratorInfo.AddAttributes(DS.TakeAttributes(),
- SourceLocation());
+ DeclaratorInfo.addAttributes(DS.takeAttributes());
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- DeclaratorInfo.AddAttributes(AttrList, Loc);
- }
+ MaybeParseGNUAttributes(DeclaratorInfo);
// Inform sema that we are starting a block.
Actions.ActOnBlockArguments(DeclaratorInfo, getCurScope());
return ExprError();
}
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- ParamInfo.AddAttributes(AttrList, Loc);
- }
+ MaybeParseGNUAttributes(ParamInfo);
// Inform sema that we are starting a block.
Actions.ActOnBlockArguments(ParamInfo, getCurScope());
ParseBlockId();
} else {
// Otherwise, pretend we saw (void).
- ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false,
+ ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(),
+ true, false,
SourceLocation(),
0, 0, 0,
false, SourceLocation(),
ParamInfo),
CaretLoc);
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- ParamInfo.AddAttributes(AttrList, Loc);
- }
+ MaybeParseGNUAttributes(ParamInfo);
// Inform sema that we are starting a block.
Actions.ActOnBlockArguments(ParamInfo, getCurScope());
}
// If attributes are present, parse them.
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- DeclaratorInfo.AddAttributes(AttrList, Loc);
- }
+ MaybeParseGNUAttributes(DeclaratorInfo);
// Type-check the declaration itself.
DeclResult Dcl = Actions.ActOnCXXConditionDeclaration(getCurScope(),
- DeclaratorInfo);
+ DeclaratorInfo);
DeclOut = Dcl.get();
ExprOut = ExprError();
first = false;
SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc);
- D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
+ D.AddTypeInfo(DeclaratorChunk::getArray(0, ParsedAttributes(),
+ /*static=*/false, /*star=*/false,
Size.release(), LLoc, RLoc),
RLoc);
switch (Tok.getObjCKeywordID()) {
case tok::objc_class:
return ParseObjCAtClassDeclaration(AtLoc);
- case tok::objc_interface:
- return ParseObjCAtInterfaceDeclaration(AtLoc);
- case tok::objc_protocol:
- return ParseObjCAtProtocolDeclaration(AtLoc);
+ case tok::objc_interface: {
+ ParsedAttributes attrs;
+ return ParseObjCAtInterfaceDeclaration(AtLoc, attrs);
+ }
+ case tok::objc_protocol: {
+ ParsedAttributes attrs;
+ return ParseObjCAtProtocolDeclaration(AtLoc, attrs);
+ }
case tok::objc_implementation:
return ParseObjCAtImplementationDeclaration(AtLoc);
case tok::objc_end:
/// __attribute__((unavailable))
/// __attribute__((objc_exception)) - used by NSException on 64-bit
///
-Decl *Parser::ParseObjCAtInterfaceDeclaration(
- SourceLocation atLoc, AttributeList *attrList) {
+Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
+ ParsedAttributes &attrs) {
assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
"ParseObjCAtInterfaceDeclaration(): Expected @interface");
ConsumeToken(); // the "interface" identifier
LAngleLoc, EndProtoLoc))
return 0;
- if (attrList) // categories don't support attributes.
+ if (!attrs.empty()) // categories don't support attributes.
Diag(Tok, diag::err_objc_no_attributes_on_category);
Decl *CategoryType =
superClassId, superClassLoc,
ProtocolRefs.data(), ProtocolRefs.size(),
ProtocolLocs.data(),
- EndProtoLoc, attrList);
+ EndProtoLoc, attrs.getList());
if (Tok.is(tok::l_brace))
ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, atLoc);
// FIXME: as the name implies, this rule allows function definitions.
// We could pass a flag or check for functions during semantic analysis.
- allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(0));
+ ParsedAttributes attrs;
+ allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(attrs));
continue;
}
ReturnType = ParseObjCTypeName(DSRet, false);
// If attributes exist before the method, parse them.
- AttributeList *MethodAttrs = 0;
- if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
- MethodAttrs = ParseGNUAttributes();
+ ParsedAttributes attrs;
+ if (getLang().ObjC2)
+ MaybeParseGNUAttributes(attrs);
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
llvm::SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo;
if (Tok.isNot(tok::colon)) {
// If attributes exist after the method, parse them.
- if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
- MethodAttrs = addAttributeLists(MethodAttrs, ParseGNUAttributes());
+ if (getLang().ObjC2)
+ MaybeParseGNUAttributes(attrs);
Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
Decl *Result
mType, IDecl, DSRet, ReturnType, Sel,
0,
CParamInfo.data(), CParamInfo.size(),
- MethodAttrs, MethodImplKind);
+ attrs.getList(), MethodImplKind);
PD.complete(Result);
return Result;
}
// If attributes exist before the argument name, parse them.
ArgInfo.ArgAttrs = 0;
- if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
- ArgInfo.ArgAttrs = ParseGNUAttributes();
+ if (getLang().ObjC2) {
+ ParsedAttributes attrs;
+ MaybeParseGNUAttributes(attrs);
+ ArgInfo.ArgAttrs = attrs.getList();
+ }
// Code completion for the next piece of the selector.
if (Tok.is(tok::code_completion)) {
// FIXME: Add support for optional parameter list...
// If attributes exist after the method, parse them.
- if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
- MethodAttrs = addAttributeLists(MethodAttrs, ParseGNUAttributes());
+ if (getLang().ObjC2)
+ MaybeParseGNUAttributes(attrs);
if (KeyIdents.size() == 0)
return 0;
mType, IDecl, DSRet, ReturnType, Sel,
&ArgInfos[0],
CParamInfo.data(), CParamInfo.size(),
- MethodAttrs,
+ attrs.getList(),
MethodImplKind, isVariadic);
PD.complete(Result);
return Result;
/// identifier-list ;": objc-interface-decl-list may not start with a
/// semicolon in the first alternative if objc-protocol-refs are omitted.
Decl *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
- AttributeList *attrList) {
+ ParsedAttributes &attrs) {
assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
"ParseObjCAtProtocolDeclaration(): Expected @protocol");
ConsumeToken(); // the "protocol" identifier
IdentifierLocPair ProtoInfo(protocolName, nameLoc);
ConsumeToken();
return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1,
- attrList);
+ attrs.getList());
}
if (Tok.is(tok::comma)) { // list of forward declarations.
return Actions.ActOnForwardProtocolDeclaration(AtLoc,
&ProtocolRefs[0],
ProtocolRefs.size(),
- attrList);
+ attrs.getList());
}
// Last, and definitely not least, parse a protocol declaration.
ProtocolRefs.data(),
ProtocolRefs.size(),
ProtocolLocs.data(),
- EndProtoLoc, attrList);
+ EndProtoLoc, attrs.getList());
ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol);
return ProtoType;
}
ParenBraceBracketBalancer BalancerRAIIObj(*this);
- CXX0XAttributeList Attr;
- if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
- Attr = ParseCXX0XAttributes();
- AttributeList *AttrList = Attr.AttrList;
+ ParsedAttributesWithRange attrs;
+ MaybeParseCXX0XAttributes(attrs);
// Cases in this switch statement should fall through if the parser expects
// the token to end in a semicolon (in which case SemiError should be set),
case tok::identifier:
if (NextToken().is(tok::colon)) { // C99 6.8.1: labeled-statement
// identifier ':' statement
- return ParseLabeledStatement(AttrList);
+ return ParseLabeledStatement(attrs);
}
// PASS THROUGH.
if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
DeclGroupPtrTy Decl = ParseDeclaration(Stmts, Declarator::BlockContext,
- DeclEnd, Attr);
+ DeclEnd, attrs);
return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
}
}
case tok::kw_case: // C99 6.8.1: labeled-statement
- return ParseCaseStatement(AttrList);
+ return ParseCaseStatement(attrs);
case tok::kw_default: // C99 6.8.1: labeled-statement
- return ParseDefaultStatement(AttrList);
+ return ParseDefaultStatement(attrs);
case tok::l_brace: // C99 6.8.2: compound-statement
- return ParseCompoundStatement(AttrList);
+ return ParseCompoundStatement(attrs);
case tok::semi: { // C99 6.8.3p3: expression[opt] ';'
bool LeadingEmptyMacro = Tok.hasLeadingEmptyMacro();
return Actions.ActOnNullStmt(ConsumeToken(), LeadingEmptyMacro);
}
case tok::kw_if: // C99 6.8.4.1: if-statement
- return ParseIfStatement(AttrList);
+ return ParseIfStatement(attrs);
case tok::kw_switch: // C99 6.8.4.2: switch-statement
- return ParseSwitchStatement(AttrList);
+ return ParseSwitchStatement(attrs);
case tok::kw_while: // C99 6.8.5.1: while-statement
- return ParseWhileStatement(AttrList);
+ return ParseWhileStatement(attrs);
case tok::kw_do: // C99 6.8.5.2: do-statement
- Res = ParseDoStatement(AttrList);
+ Res = ParseDoStatement(attrs);
SemiError = "do/while";
break;
case tok::kw_for: // C99 6.8.5.3: for-statement
- return ParseForStatement(AttrList);
+ return ParseForStatement(attrs);
case tok::kw_goto: // C99 6.8.6.1: goto-statement
- Res = ParseGotoStatement(AttrList);
+ Res = ParseGotoStatement(attrs);
SemiError = "goto";
break;
case tok::kw_continue: // C99 6.8.6.2: continue-statement
- Res = ParseContinueStatement(AttrList);
+ Res = ParseContinueStatement(attrs);
SemiError = "continue";
break;
case tok::kw_break: // C99 6.8.6.3: break-statement
- Res = ParseBreakStatement(AttrList);
+ Res = ParseBreakStatement(attrs);
SemiError = "break";
break;
case tok::kw_return: // C99 6.8.6.4: return-statement
- Res = ParseReturnStatement(AttrList);
+ Res = ParseReturnStatement(attrs);
SemiError = "return";
break;
case tok::kw_asm: {
- if (Attr.HasAttr)
- Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
- << Attr.Range;
+ ProhibitAttributes(attrs);
bool msAsm = false;
Res = ParseAsmStatement(msAsm);
Res = Actions.ActOnFinishFullStmt(Res.get());
}
case tok::kw_try: // C++ 15: try-block
- return ParseCXXTryBlock(AttrList);
+ return ParseCXXTryBlock(attrs);
}
// If we reached this code, the statement must end in a semicolon.
/// identifier ':' statement
/// [GNU] identifier ':' attributes[opt] statement
///
-StmtResult Parser::ParseLabeledStatement(AttributeList *Attr) {
+StmtResult Parser::ParseLabeledStatement(ParsedAttributes &attrs) {
assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
"Not an identifier!");
SourceLocation ColonLoc = ConsumeToken();
// Read label attributes, if present.
- if (Tok.is(tok::kw___attribute))
- Attr = addAttributeLists(Attr, ParseGNUAttributes());
+ MaybeParseGNUAttributes(attrs);
StmtResult SubStmt(ParseStatement());
return Actions.ActOnLabelStmt(IdentTok.getLocation(),
IdentTok.getIdentifierInfo(),
- ColonLoc, SubStmt.get(), Attr);
+ ColonLoc, SubStmt.get(), attrs.getList());
}
/// ParseCaseStatement
/// 'case' constant-expression ':' statement
/// [GNU] 'case' constant-expression '...' constant-expression ':' statement
///
-StmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
+StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs) {
assert(Tok.is(tok::kw_case) && "Not a case stmt!");
// FIXME: Use attributes?
/// 'default' ':' statement
/// Note that this does not parse the 'statement' at the end.
///
-StmtResult Parser::ParseDefaultStatement(AttributeList *Attr) {
+StmtResult Parser::ParseDefaultStatement(ParsedAttributes &attrs) {
//FIXME: Use attributes?
assert(Tok.is(tok::kw_default) && "Not a default stmt!");
/// [OMP] barrier-directive
/// [OMP] flush-directive
///
-StmtResult Parser::ParseCompoundStatement(AttributeList *Attr,
+StmtResult Parser::ParseCompoundStatement(ParsedAttributes &attrs,
bool isStmtExpr) {
//FIXME: Use attributes?
while (Tok.is(tok::kw___extension__))
ConsumeToken();
- CXX0XAttributeList Attr;
- if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
- Attr = ParseCXX0XAttributes();
+ ParsedAttributesWithRange attrs;
+ MaybeParseCXX0XAttributes(attrs);
// If this is the start of a declaration, parse it as such.
if (isDeclarationStatement()) {
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
DeclGroupPtrTy Res = ParseDeclaration(Stmts,
Declarator::BlockContext, DeclEnd,
- Attr);
+ attrs);
R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
} else {
// Otherwise this was a unary __extension__ marker.
/// [C++] 'if' '(' condition ')' statement
/// [C++] 'if' '(' condition ')' statement 'else' statement
///
-StmtResult Parser::ParseIfStatement(AttributeList *Attr) {
+StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs) {
// FIXME: Use attributes?
assert(Tok.is(tok::kw_if) && "Not an if stmt!");
/// switch-statement:
/// 'switch' '(' expression ')' statement
/// [C++] 'switch' '(' condition ')' statement
-StmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
+StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs) {
// FIXME: Use attributes?
assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
/// while-statement: [C99 6.8.5.1]
/// 'while' '(' expression ')' statement
/// [C++] 'while' '(' condition ')' statement
-StmtResult Parser::ParseWhileStatement(AttributeList *Attr) {
+StmtResult Parser::ParseWhileStatement(ParsedAttributes &attrs) {
// FIXME: Use attributes?
assert(Tok.is(tok::kw_while) && "Not a while stmt!");
/// do-statement: [C99 6.8.5.2]
/// 'do' statement 'while' '(' expression ')' ';'
/// Note: this lets the caller parse the end ';'.
-StmtResult Parser::ParseDoStatement(AttributeList *Attr) {
+StmtResult Parser::ParseDoStatement(ParsedAttributes &attrs) {
// FIXME: Use attributes?
assert(Tok.is(tok::kw_do) && "Not a do stmt!");
/// [C++] expression-statement
/// [C++] simple-declaration
///
-StmtResult Parser::ParseForStatement(AttributeList *Attr) {
+StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) {
// FIXME: Use attributes?
assert(Tok.is(tok::kw_for) && "Not a for stmt!");
if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode?
Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
- AttributeList *AttrList = 0;
- if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
- AttrList = ParseCXX0XAttributes().AttrList;
+ ParsedAttributesWithRange attrs;
+ MaybeParseCXX0XAttributes(attrs);
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
StmtVector Stmts(Actions);
DeclGroupPtrTy DG = ParseSimpleDeclaration(Stmts, Declarator::ForContext,
- DeclEnd, AttrList, false);
+ DeclEnd, attrs, false);
FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
if (Tok.is(tok::semi)) { // for (int x = 4;
///
/// Note: this lets the caller parse the end ';'.
///
-StmtResult Parser::ParseGotoStatement(AttributeList *Attr) {
+StmtResult Parser::ParseGotoStatement(ParsedAttributes &attrs) {
// FIXME: Use attributes?
assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
///
/// Note: this lets the caller parse the end ';'.
///
-StmtResult Parser::ParseContinueStatement(AttributeList *Attr) {
+StmtResult Parser::ParseContinueStatement(ParsedAttributes &attrs) {
// FIXME: Use attributes?
SourceLocation ContinueLoc = ConsumeToken(); // eat the 'continue'.
///
/// Note: this lets the caller parse the end ';'.
///
-StmtResult Parser::ParseBreakStatement(AttributeList *Attr) {
+StmtResult Parser::ParseBreakStatement(ParsedAttributes &attrs) {
// FIXME: Use attributes?
SourceLocation BreakLoc = ConsumeToken(); // eat the 'break'.
/// ParseReturnStatement
/// jump-statement:
/// 'return' expression[opt] ';'
-StmtResult Parser::ParseReturnStatement(AttributeList *Attr) {
+StmtResult Parser::ParseReturnStatement(ParsedAttributes &attrs) {
// FIXME: Use attributes?
assert(Tok.is(tok::kw_return) && "Not a return stmt!");
/// try-block:
/// 'try' compound-statement handler-seq
///
-StmtResult Parser::ParseCXXTryBlock(AttributeList* Attr) {
+StmtResult Parser::ParseCXXTryBlock(ParsedAttributes &attrs) {
// FIXME: Add attributes?
assert(Tok.is(tok::kw_try) && "Expected 'try'");
if (Tok.isNot(tok::l_brace))
return StmtError(Diag(Tok, diag::err_expected_lbrace));
// FIXME: Possible draft standard bug: attribute-specifier should be allowed?
- StmtResult TryBlock(ParseCompoundStatement(0));
+ ParsedAttributesWithRange attrs;
+ StmtResult TryBlock(ParseCompoundStatement(attrs));
if (TryBlock.isInvalid())
return move(TryBlock);
StmtVector Handlers(Actions);
- if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
- CXX0XAttributeList Attr = ParseCXX0XAttributes();
- Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
- << Attr.Range;
- }
+ MaybeParseCXX0XAttributes(attrs);
+ ProhibitAttributes(attrs);
+
if (Tok.isNot(tok::kw_catch))
return StmtError(Diag(Tok, diag::err_expected_catch));
while (Tok.is(tok::kw_catch)) {
return StmtError(Diag(Tok, diag::err_expected_lbrace));
// FIXME: Possible draft standard bug: attribute-specifier should be allowed?
- StmtResult Block(ParseCompoundStatement(0));
+ ParsedAttributes attrs;
+ StmtResult Block(ParseCompoundStatement(attrs));
if (Block.isInvalid())
return move(Block);
return 0;
}
- CXX0XAttributeList PrefixAttrs;
- if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
- PrefixAttrs = ParseCXX0XAttributes();
+ ParsedAttributesWithRange prefixAttrs;
+ MaybeParseCXX0XAttributes(prefixAttrs);
if (Tok.is(tok::kw_using))
return ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,
- PrefixAttrs);
+ prefixAttrs);
// Parse the declaration specifiers, stealing the accumulated
// diagnostics from the template parameters.
ParsingDeclSpec DS(DiagsFromTParams);
- if (PrefixAttrs.HasAttr)
- DS.AddAttributes(PrefixAttrs.AttrList);
+ DS.takeAttributesFrom(prefixAttrs);
ParseDeclarationSpecifiers(DS, TemplateInfo, AS,
getDeclSpecContextFromDeclaratorContext(Context));
return TPResult::True(); // '...' is a sign of a function declarator.
}
- if (getLang().Microsoft && Tok.is(tok::l_square))
- ParseMicrosoftAttributes();
+ ParsedAttributes attrs;
+ MaybeParseMicrosoftAttributes(attrs);
// decl-specifier-seq
TPResult TPR = TryParseDeclarationSpecifier();
return true;
}
- CXX0XAttributeList Attr;
- if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
- Attr = ParseCXX0XAttributes();
- if (getLang().Microsoft && Tok.is(tok::l_square))
- ParseMicrosoftAttributes();
+ ParsedAttributesWithRange attrs;
+ MaybeParseCXX0XAttributes(attrs);
+ MaybeParseMicrosoftAttributes(attrs);
- Result = ParseExternalDeclaration(Attr);
+ Result = ParseExternalDeclaration(attrs);
return false;
}
/// ';'
///
/// [C++0x/GNU] 'extern' 'template' declaration
-Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr,
- ParsingDeclSpec *DS) {
+Parser::DeclGroupPtrTy
+Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
+ ParsingDeclSpec *DS) {
ParenBraceBracketBalancer BalancerRAIIObj(*this);
Decl *SingleDecl = 0;
// __extension__ silences extension warnings in the subexpression.
ExtensionRAIIObject O(Diags); // Use RAII to do this.
ConsumeToken();
- return ParseExternalDeclaration(Attr);
+ return ParseExternalDeclaration(attrs);
}
case tok::kw_asm: {
- if (Attr.HasAttr)
- Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
- << Attr.Range;
+ ProhibitAttributes(attrs);
ExprResult Result(ParseSimpleAsm());
ObjCImpDecl? Sema::PCC_ObjCImplementation
: Sema::PCC_Namespace);
ConsumeCodeCompletionToken();
- return ParseExternalDeclaration(Attr);
+ return ParseExternalDeclaration(attrs);
case tok::kw_using:
case tok::kw_namespace:
case tok::kw_typedef:
{
SourceLocation DeclEnd;
StmtVector Stmts(Actions);
- return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, Attr);
+ return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs);
}
case tok::kw_static:
<< 0;
SourceLocation DeclEnd;
StmtVector Stmts(Actions);
- return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, Attr);
+ return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs);
}
goto dont_know;
if (NextKind == tok::kw_namespace) {
SourceLocation DeclEnd;
StmtVector Stmts(Actions);
- return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, Attr);
+ return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs);
}
// Parse (then ignore) 'inline' prior to a template instantiation. This is
<< 1;
SourceLocation DeclEnd;
StmtVector Stmts(Actions);
- return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, Attr);
+ return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs);
}
}
goto dont_know;
default:
dont_know:
// We can't tell whether this is a function-definition or declaration yet.
- if (DS)
- return ParseDeclarationOrFunctionDefinition(*DS, Attr.AttrList);
- else
- return ParseDeclarationOrFunctionDefinition(Attr.AttrList);
+ if (DS) {
+ DS->takeAttributesFrom(attrs);
+ return ParseDeclarationOrFunctionDefinition(*DS);
+ } else {
+ return ParseDeclarationOrFunctionDefinition(attrs);
+ }
}
// This routine returns a DeclGroup, if the thing we parsed only contains a
///
Parser::DeclGroupPtrTy
Parser::ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS,
- AttributeList *Attr,
AccessSpecifier AS) {
// Parse the common declaration-specifiers piece.
- if (Attr)
- DS.AddAttributes(Attr);
-
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_top_level);
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
}
Parser::DeclGroupPtrTy
-Parser::ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
+Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs,
AccessSpecifier AS) {
ParsingDeclSpec DS(*this);
- return ParseDeclarationOrFunctionDefinition(DS, Attr, AS);
+ DS.takeAttributesFrom(attrs);
+ return ParseDeclarationOrFunctionDefinition(DS, AS);
}
/// ParseFunctionDefinition - We parsed and verified that the specified
// Handle the full declarator list.
while (1) {
// If attributes are present, parse them.
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- ParmDeclarator.AddAttributes(AttrList, Loc);
- }
+ MaybeParseGNUAttributes(ParmDeclarator);
// Ask the actions module to compute the type for this declarator.
Decl *Param =
IdentifierInfo *sName, SourceLocation sLoc,
IdentifierInfo *pName, SourceLocation pLoc,
Expr **ExprList, unsigned numArgs,
- AttributeList *n, bool declspec, bool cxx0x)
+ bool declspec, bool cxx0x)
: AttrName(aName), AttrLoc(aLoc), ScopeName(sName),
ScopeLoc(sLoc),
- ParmName(pName), ParmLoc(pLoc), NumArgs(numArgs), Next(n),
+ ParmName(pName), ParmLoc(pLoc), NumArgs(numArgs), Next(0),
DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false) {
if (numArgs == 0)
/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
/// "TheDeclarator" is the declarator that this will be added to.
-DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
+DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs,
+ bool hasProto, bool isVariadic,
SourceLocation EllipsisLoc,
ParamInfo *ArgInfo,
unsigned NumArgs,
I.Kind = Function;
I.Loc = LPLoc;
I.EndLoc = RPLoc;
+ I.Fun.AttrList = attrs.getList();
I.Fun.hasPrototype = hasProto;
I.Fun.isVariadic = isVariadic;
I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding();
writtenBS.Type = getTypeSpecType();
// Search the list of attributes for the presence of a mode attribute.
writtenBS.ModeAttr = false;
- AttributeList* attrs = getAttributes();
+ AttributeList* attrs = getAttributes().getList();
while (attrs) {
if (attrs->getKind() == AttributeList::AT_mode) {
writtenBS.ModeAttr = true;
}
if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
- ProcessDeclAttributeList(S, Record, DS.getAttributes());
+ ProcessDeclAttributeList(S, Record, DS.getAttributes().getList());
if (!Record->getDeclName() && Record->isDefinition() &&
DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
(void)Error; // Silence warning.
assert(!Error && "Error setting up implicit decl!");
Declarator D(DS, Declarator::BlockContext);
- D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, SourceLocation(), 0,
+ D.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(),
+ false, false, SourceLocation(), 0,
0, 0, false, SourceLocation(),
false, 0,0,0, Loc, Loc, D),
SourceLocation());
}
// Apply decl attributes from the DeclSpec if present.
- if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes())
+ if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList())
ProcessDeclAttributeList(S, D, Attrs);
// Walk the declarator structure, applying decl attributes that were in a type
// See if there are any attributes on the declspec that apply to the type (as
// opposed to the decl).
- if (const AttributeList *AL = DS.getAttributes())
+ if (const AttributeList *AL = DS.getAttributes().getList())
ProcessTypeAttributeList(TheSema, Result, true, AL, Delayed);
// Apply const/volatile/restrict qualifiers to T.