From 53fa71476d0539b031a8f91232607f5ca8f182e5 Mon Sep 17 00:00:00 2001 From: John McCall Date: Fri, 24 Dec 2010 02:08:15 +0000 Subject: [PATCH] Refactor how we collect attributes during parsing, and add slots for attributes on array and function declarators. This is pretty far from complete, and I'll revisit it later if someone doesn't beat me to it. llvm-svn: 122535 --- clang/include/clang/Parse/Parser.h | 121 ++++++--- clang/include/clang/Sema/AttributeList.h | 48 +++- clang/include/clang/Sema/DeclSpec.h | 123 ++++++---- clang/lib/AST/ASTContext.cpp | 4 +- clang/lib/Parse/ParseDecl.cpp | 299 ++++++++++------------- clang/lib/Parse/ParseDeclCXX.cpp | 147 +++++------ clang/lib/Parse/ParseExpr.cpp | 27 +- clang/lib/Parse/ParseExprCXX.cpp | 11 +- clang/lib/Parse/ParseObjc.cpp | 56 +++-- clang/lib/Parse/ParseStmt.cpp | 101 ++++---- clang/lib/Parse/ParseTemplate.cpp | 10 +- clang/lib/Parse/ParseTentative.cpp | 4 +- clang/lib/Parse/Parser.cpp | 56 ++--- clang/lib/Sema/AttributeList.cpp | 4 +- clang/lib/Sema/DeclSpec.cpp | 6 +- clang/lib/Sema/SemaDecl.cpp | 5 +- clang/lib/Sema/SemaDeclAttr.cpp | 2 +- clang/lib/Sema/SemaType.cpp | 2 +- 18 files changed, 525 insertions(+), 501 deletions(-) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 3b6aceb5cd47..db4d1b7a4b77 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -920,14 +920,17 @@ private: //===--------------------------------------------------------------------===// // 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, @@ -942,7 +945,7 @@ private: Decl *ParseObjCAtDirectives(); Decl *ParseObjCAtClassDeclaration(SourceLocation atLoc); Decl *ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, - AttributeList *prefixAttrs = 0); + ParsedAttributes &prefixAttrs); void ParseObjCClassInstanceVariables(Decl *interfaceDecl, tok::ObjCKeywordKind visibility, SourceLocation atLoc); @@ -955,7 +958,7 @@ private: void ParseObjCInterfaceDeclList(Decl *interfaceDecl, tok::ObjCKeywordKind contextKey); Decl *ParseObjCAtProtocolDeclaration(SourceLocation atLoc, - AttributeList *prefixAttrs = 0); + ParsedAttributes &prefixAttrs); Decl *ObjCImpDecl; llvm::SmallVector PendingObjCImpDecl; @@ -1189,25 +1192,25 @@ private: } 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 &Names, @@ -1217,7 +1220,7 @@ private: //===--------------------------------------------------------------------===// // C++ 6: Statements and Blocks - StmtResult ParseCXXTryBlock(AttributeList *Attr); + StmtResult ParseCXXTryBlock(ParsedAttributes &Attr); StmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc); StmtResult ParseCXXCatchBlock(); @@ -1244,11 +1247,11 @@ private: 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, @@ -1447,14 +1450,64 @@ private: 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); @@ -1499,12 +1552,13 @@ private: 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, @@ -1524,10 +1578,11 @@ private: 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, diff --git a/clang/include/clang/Sema/AttributeList.h b/clang/include/clang/Sema/AttributeList.h index 69170fa23ce5..0dab6669798b 100644 --- a/clang/include/clang/Sema/AttributeList.h +++ b/clang/include/clang/Sema/AttributeList.h @@ -56,7 +56,7 @@ private: 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; @@ -66,12 +66,11 @@ public: 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(); new (Mem) AttributeList(Alloc, AttrName, AttrLoc, ScopeName, ScopeLoc, ParmName, ParmLoc, args, numargs, - Next, declspec, cxx0x); + declspec, cxx0x); return Mem; } }; @@ -266,6 +265,47 @@ struct CXX0XAttributeList { } }; +/// 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 diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 3a57657e60db..7cc5b8f7a3aa 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -170,32 +170,32 @@ private: // 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; @@ -206,7 +206,7 @@ private: }; // attributes. - AttributeList *AttrList; + ParsedAttributes Attrs; // Scope specifier for the type spec, if applicable. CXXScopeSpec TypeScope; @@ -268,7 +268,6 @@ public: Friend_specified(false), Constexpr_specified(false), StorageClassSpecAsWritten(SCS_unspecified), - AttrList(0), ProtocolQualifiers(0), NumProtocolQualifiers(0), ProtocolLocs(0), @@ -473,19 +472,29 @@ public: /// 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; @@ -809,25 +818,27 @@ struct DeclaratorChunk { /// 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; @@ -841,6 +852,7 @@ struct DeclaratorChunk { /// 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() {} }; @@ -875,29 +887,29 @@ struct DeclaratorChunk { 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; @@ -960,19 +972,18 @@ struct DeclaratorChunk { } }; - 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 { @@ -1019,8 +1030,8 @@ struct DeclaratorChunk { 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; } @@ -1032,37 +1043,40 @@ struct DeclaratorChunk { /// 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; @@ -1072,7 +1086,8 @@ struct DeclaratorChunk { /// 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, @@ -1088,24 +1103,24 @@ struct DeclaratorChunk { /// 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; } @@ -1399,19 +1414,23 @@ public: /// __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; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index eaf222cafad8..b145683ce5e5 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1119,8 +1119,8 @@ QualType ASTContext::getObjCGCQualType(QualType T, if (CanT.getObjCGCAttr() == GCAttr) return T; - if (T->isPointerType()) { - QualType Pointee = T->getAs()->getPointeeType(); + if (const PointerType *ptr = T->getAs()) { + QualType Pointee = ptr->getPointeeType(); if (Pointee->isAnyPointerType()) { QualType ResultType = getObjCGCQualType(Pointee, GCAttr); return getPointerType(ResultType); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index f627b2c9f42e..ab9173ffab0b 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -82,21 +82,20 @@ TypeResult Parser::ParseTypeName(SourceRange *Range) { /// 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() || @@ -122,8 +121,8 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) { 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) )) @@ -146,10 +145,9 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) { } 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 @@ -158,8 +156,8 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) { // 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: @@ -174,10 +172,12 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) { 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) )) @@ -185,6 +185,7 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) { if (Tok.is(tok::r_paren)) ConsumeParen(); break; + } default: // __attribute__(( aligned(16) )) ExprVector ArgExprs(Actions); @@ -207,17 +208,16 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) { // 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)) @@ -226,10 +226,9 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) { 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 @@ -241,14 +240,14 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) { /// 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(); @@ -260,23 +259,22 @@ AttributeList* Parser::ParseMicrosoftDeclSpec(AttributeList *CurrAttr) { 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) || @@ -287,21 +285,24 @@ AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) { 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 @@ -323,49 +324,40 @@ AttributeList* Parser::ParseBorlandTypeAttributes(AttributeList *CurrAttr) { 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 @@ -383,12 +375,11 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, 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); @@ -482,11 +473,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &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); @@ -555,12 +542,7 @@ Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &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; @@ -688,7 +670,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS) { // 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. @@ -1191,12 +1173,12 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // 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. @@ -1210,12 +1192,12 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, 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 @@ -1692,11 +1674,11 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, 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: @@ -1759,11 +1741,8 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) { 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 @@ -1783,11 +1762,7 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) { } // 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); @@ -1908,15 +1883,14 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, 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); } @@ -1958,10 +1932,9 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, 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) { @@ -2102,7 +2075,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, 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, @@ -2185,9 +2158,8 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { 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; @@ -2202,7 +2174,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { Decl *EnumConstDecl = Actions.ActOnEnumConstant(getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident, - Attr, EqualLoc, + attrs.getList(), EqualLoc, AssignedVal.release()); EnumConstantDecls.push_back(EnumConstDecl); LastEnumConstDecl = EnumConstDecl; @@ -2229,14 +2201,13 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { // 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); @@ -2567,9 +2538,10 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, 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); } @@ -2605,19 +2577,19 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, 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! @@ -2703,7 +2675,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // 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; } @@ -2737,12 +2709,12 @@ void Parser::ParseDeclaratorInternal(Declarator &D, 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 @@ -2794,7 +2766,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // 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()); } @@ -2946,12 +2918,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) { "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)) { @@ -2965,7 +2933,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) { if (!isCXXFunctionDeclarator(warnIfAmbiguous)) break; } - ParseFunctionDeclarator(ConsumeParen(), D); + ParsedAttributes attrs; + ParseFunctionDeclarator(ConsumeParen(), D, attrs); } else if (Tok.is(tok::l_square)) { ParseBracketDeclarator(D); } else { @@ -3001,10 +2970,10 @@ void Parser::ParseParenDeclarator(Declarator &D) { // 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. @@ -3014,11 +2983,11 @@ void Parser::ParseParenDeclarator(Declarator &D) { 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 @@ -3047,8 +3016,8 @@ void Parser::ParseParenDeclarator(Declarator &D) { 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 ')'. @@ -3065,7 +3034,7 @@ void Parser::ParseParenDeclarator(Declarator &D) { // 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 @@ -3101,7 +3070,7 @@ void Parser::ParseParenDeclarator(Declarator &D) { /// 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!"); @@ -3124,6 +3093,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, llvm::SmallVector Exceptions; llvm::SmallVector ExceptionRanges; if (getLang().CPlusPlus) { + MaybeParseCXX0XAttributes(attrs); + ParseTypeQualifierListOpt(DS, false /*no attributes*/); if (!DS.getSourceRange().getEnd().isInvalid()) EndLoc = DS.getSourceRange().getEnd(); @@ -3146,7 +3117,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, // 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, @@ -3219,22 +3191,21 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, EllipsisLoc = ConsumeToken(); // Consume the ellipsis. break; } - - // Skip any Microsoft attributes before a param. - if (getLang().Microsoft && Tok.is(tok::l_square)) - ParseMicrosoftAttributes(); - - SourceLocation DSStart = Tok.getLocation(); // 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(DS.getAttributes()); + + SourceLocation DSStart = Tok.getLocation(); // 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 @@ -3243,11 +3214,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, 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(); @@ -3362,6 +3329,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, llvm::SmallVector ExceptionRanges; if (getLang().CPlusPlus) { + MaybeParseCXX0XAttributes(attrs); + // Parse cv-qualifier-seq[opt]. ParseTypeQualifierListOpt(DS, false /*no attributes*/); if (!DS.getSourceRange().getEnd().isInvalid()) @@ -3390,7 +3359,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, 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(), @@ -3470,7 +3440,8 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, // 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, @@ -3492,15 +3463,12 @@ void Parser::ParseBracketDeclarator(Declarator &D) { // 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; @@ -3511,18 +3479,12 @@ void Parser::ParseBracketDeclarator(Declarator &D) { 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; @@ -3583,14 +3545,11 @@ void Parser::ParseBracketDeclarator(Declarator &D) { 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), diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index e1f7f7bdc589..fe2390f1aa06 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -69,16 +69,16 @@ Decl *Parser::ParseNamespace(unsigned Context, } // 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) @@ -112,18 +112,16 @@ Decl *Parser::ParseNamespace(unsigned Context, 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. @@ -201,34 +199,27 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) { 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); @@ -241,7 +232,7 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) { 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'. @@ -261,15 +252,13 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, << 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); } @@ -287,7 +276,7 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, Decl *Parser::ParseUsingDirective(unsigned Context, SourceLocation UsingLoc, SourceLocation &DeclEnd, - AttributeList *Attr) { + ParsedAttributes &attrs) { assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token"); // Eat 'namespace'. @@ -322,7 +311,7 @@ Decl *Parser::ParseUsingDirective(unsigned Context, bool GNUAttr = false; if (Tok.is(tok::kw___attribute)) { GNUAttr = true; - Attr = addAttributeLists(Attr, ParseGNUAttributes()); + ParseGNUAttributes(attrs); } // Eat ';'. @@ -333,7 +322,7 @@ Decl *Parser::ParseUsingDirective(unsigned Context, "", tok::semi); return Actions.ActOnUsingDirective(getCurScope(), UsingLoc, NamespcLoc, SS, - IdentLoc, NamespcName, Attr); + IdentLoc, NamespcName, attrs.getList()); } /// ParseUsingDeclaration - Parse C++ using-declaration. Assumes that @@ -391,14 +380,13 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, } // 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. @@ -414,7 +402,8 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, } return Actions.ActOnUsingDeclaration(getCurScope(), AS, true, UsingLoc, SS, - Name, AttrList, IsTypeName, TypenameLoc); + Name, attrs.getList(), + IsTypeName, TypenameLoc); } /// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion. @@ -685,20 +674,19 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, 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 @@ -892,7 +880,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, 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 @@ -954,7 +942,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TemplateId->LAngleLoc, TemplateArgsPtr, TemplateId->RAngleLoc, - AttrList, + attrs.getList(), MultiTemplateParamsArg(Actions, TemplateParams? &(*TemplateParams)[0] : 0, TemplateParams? TemplateParams->size() : 0)); @@ -972,13 +960,13 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, 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)); @@ -1000,7 +988,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // 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()); @@ -1364,19 +1352,15 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // 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(); @@ -1397,7 +1381,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // 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, @@ -1430,11 +1414,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, } // 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) @@ -1518,11 +1498,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, } // 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. @@ -1569,11 +1545,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, 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); @@ -1708,14 +1680,13 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, } // 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, @@ -2043,12 +2014,12 @@ void Parser::PopParsingClass() { /// '[' 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(); @@ -2104,9 +2075,8 @@ CXX0XAttributeList Parser::ParseCXX0XAttributes(SourceLocation *EndLoc) { 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; } @@ -2126,9 +2096,9 @@ CXX0XAttributeList Parser::ParseCXX0XAttributes(SourceLocation *EndLoc) { 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; @@ -2153,8 +2123,7 @@ CXX0XAttributeList Parser::ParseCXX0XAttributes(SourceLocation *EndLoc) { 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]] @@ -2185,12 +2154,14 @@ ExprResult Parser::ParseCXX0XAlignArgument(SourceLocation Start) { /// [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); } } diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 47b60b5f477d..92bbbd7bf9ac 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1522,7 +1522,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, 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. @@ -1741,14 +1742,9 @@ void Parser::ParseBlockId() { 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()); @@ -1806,11 +1802,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { 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()); @@ -1818,7 +1810,8 @@ ExprResult Parser::ParseBlockLiteralExpression() { 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(), @@ -1827,11 +1820,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { 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()); diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 8014dbd50e02..bf4b5f4b1661 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -810,15 +810,11 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, } // 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(); @@ -1729,7 +1725,8 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) { 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); diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index cd1321ed8324..c48f6803b01c 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -40,10 +40,14 @@ Decl *Parser::ParseObjCAtDirectives() { 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: @@ -124,8 +128,8 @@ Decl *Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { /// __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 @@ -178,7 +182,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration( 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 = @@ -230,7 +234,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration( 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); @@ -365,7 +369,8 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, // 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; } @@ -830,9 +835,9 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, 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, @@ -856,8 +861,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, llvm::SmallVector 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 @@ -865,7 +870,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, mType, IDecl, DSRet, ReturnType, Sel, 0, CParamInfo.data(), CParamInfo.size(), - MethodAttrs, MethodImplKind); + attrs.getList(), MethodImplKind); PD.complete(Result); return Result; } @@ -889,8 +894,11 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // 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)) { @@ -964,8 +972,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // 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; @@ -976,7 +984,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, mType, IDecl, DSRet, ReturnType, Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), - MethodAttrs, + attrs.getList(), MethodImplKind, isVariadic); PD.complete(Result); return Result; @@ -1184,7 +1192,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, /// 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 @@ -1206,7 +1214,7 @@ Decl *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, IdentifierLocPair ProtoInfo(protocolName, nameLoc); ConsumeToken(); return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1, - attrList); + attrs.getList()); } if (Tok.is(tok::comma)) { // list of forward declarations. @@ -1235,7 +1243,7 @@ Decl *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtocolRefs[0], ProtocolRefs.size(), - attrList); + attrs.getList()); } // Last, and definitely not least, parse a protocol declaration. @@ -1253,7 +1261,7 @@ Decl *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, ProtocolRefs.data(), ProtocolRefs.size(), ProtocolLocs.data(), - EndProtoLoc, attrList); + EndProtoLoc, attrs.getList()); ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol); return ProtoType; } diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 437a950cd94a..dafe37377835 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -81,10 +81,8 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) { 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), @@ -106,7 +104,7 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) { case tok::identifier: if (NextToken().is(tok::colon)) { // C99 6.8.1: labeled-statement // identifier ':' statement - return ParseLabeledStatement(AttrList); + return ParseLabeledStatement(attrs); } // PASS THROUGH. @@ -114,7 +112,7 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) { 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); } @@ -141,52 +139,50 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) { } 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()); @@ -196,7 +192,7 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) { } 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. @@ -220,7 +216,7 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) { /// 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!"); @@ -233,8 +229,7 @@ StmtResult Parser::ParseLabeledStatement(AttributeList *Attr) { SourceLocation ColonLoc = ConsumeToken(); // Read label attributes, if present. - if (Tok.is(tok::kw___attribute)) - Attr = addAttributeLists(Attr, ParseGNUAttributes()); + MaybeParseGNUAttributes(attrs); StmtResult SubStmt(ParseStatement()); @@ -244,7 +239,7 @@ StmtResult Parser::ParseLabeledStatement(AttributeList *Attr) { return Actions.ActOnLabelStmt(IdentTok.getLocation(), IdentTok.getIdentifierInfo(), - ColonLoc, SubStmt.get(), Attr); + ColonLoc, SubStmt.get(), attrs.getList()); } /// ParseCaseStatement @@ -252,7 +247,7 @@ StmtResult Parser::ParseLabeledStatement(AttributeList *Attr) { /// '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? @@ -380,7 +375,7 @@ StmtResult Parser::ParseCaseStatement(AttributeList *Attr) { /// '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!"); @@ -438,7 +433,7 @@ StmtResult Parser::ParseDefaultStatement(AttributeList *Attr) { /// [OMP] barrier-directive /// [OMP] flush-directive /// -StmtResult Parser::ParseCompoundStatement(AttributeList *Attr, +StmtResult Parser::ParseCompoundStatement(ParsedAttributes &attrs, bool isStmtExpr) { //FIXME: Use attributes? @@ -482,9 +477,8 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { 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()) { @@ -495,7 +489,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { 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. @@ -585,7 +579,7 @@ bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult, /// [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!"); @@ -707,7 +701,7 @@ StmtResult Parser::ParseIfStatement(AttributeList *Attr) { /// 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!"); @@ -792,7 +786,7 @@ StmtResult Parser::ParseSwitchStatement(AttributeList *Attr) { /// 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!"); @@ -866,7 +860,7 @@ StmtResult Parser::ParseWhileStatement(AttributeList *Attr) { /// 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!"); @@ -942,7 +936,7 @@ StmtResult Parser::ParseDoStatement(AttributeList *Attr) { /// [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!"); @@ -1007,14 +1001,13 @@ StmtResult Parser::ParseForStatement(AttributeList *Attr) { 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; @@ -1141,7 +1134,7 @@ StmtResult Parser::ParseForStatement(AttributeList *Attr) { /// /// 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!"); @@ -1176,7 +1169,7 @@ StmtResult Parser::ParseGotoStatement(AttributeList *Attr) { /// /// 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'. @@ -1189,7 +1182,7 @@ StmtResult Parser::ParseContinueStatement(AttributeList *Attr) { /// /// 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'. @@ -1199,7 +1192,7 @@ StmtResult Parser::ParseBreakStatement(AttributeList *Attr) { /// 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!"); @@ -1521,7 +1514,7 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl) { /// 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'"); @@ -1546,16 +1539,15 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) { 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)) { @@ -1616,7 +1608,8 @@ StmtResult Parser::ParseCXXCatchBlock() { 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); diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index d38d0599ac25..afa2cc62f9fb 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -196,20 +196,18 @@ Parser::ParseSingleDeclarationAfterTemplate( 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)); diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index fc57b4086b0b..c6e6784f6c20 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -1151,8 +1151,8 @@ Parser::TPResult Parser::TryParseParameterDeclarationClause() { 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(); diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index f79a2f68c727..2a569b58d8c4 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -402,13 +402,11 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { 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; } @@ -449,8 +447,9 @@ void Parser::ParseTranslationUnit() { /// ';' /// /// [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; @@ -474,12 +473,10 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr, // __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()); @@ -511,7 +508,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr, 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: @@ -522,7 +519,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr, { SourceLocation DeclEnd; StmtVector Stmts(Actions); - return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, Attr); + return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); } case tok::kw_static: @@ -533,7 +530,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr, << 0; SourceLocation DeclEnd; StmtVector Stmts(Actions); - return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, Attr); + return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); } goto dont_know; @@ -545,7 +542,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr, 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 @@ -555,7 +552,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr, << 1; SourceLocation DeclEnd; StmtVector Stmts(Actions); - return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, Attr); + return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); } } goto dont_know; @@ -575,10 +572,12 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr, 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 @@ -632,12 +631,8 @@ bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) { /// 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 };" @@ -690,10 +685,11 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS, } 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 @@ -835,11 +831,7 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { // 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 = diff --git a/clang/lib/Sema/AttributeList.cpp b/clang/lib/Sema/AttributeList.cpp index 6aa9690476aa..6e0a3321048a 100644 --- a/clang/lib/Sema/AttributeList.cpp +++ b/clang/lib/Sema/AttributeList.cpp @@ -21,10 +21,10 @@ AttributeList::AttributeList(llvm::BumpPtrAllocator &Alloc, 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) diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 5304193b6646..4afdc24275fb 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -46,7 +46,8 @@ void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) { /// 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, @@ -65,6 +66,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, 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(); @@ -483,7 +485,7 @@ void DeclSpec::SaveWrittenBuiltinSpecs() { 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; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index d59664947901..62262bc60b53 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1642,7 +1642,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, } if (RecordDecl *Record = dyn_cast_or_null(Tag)) { - ProcessDeclAttributeList(S, Record, DS.getAttributes()); + ProcessDeclAttributeList(S, Record, DS.getAttributes().getList()); if (!Record->getDeclName() && Record->isDefinition() && DS.getStorageClassSpec() != DeclSpec::SCS_typedef) { @@ -5553,7 +5553,8 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, (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()); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 06cb42ec0e04..6977a33ac4ae 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2808,7 +2808,7 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { } // 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 diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 46ec0fe10914..c70d5befbbf3 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -402,7 +402,7 @@ static QualType ConvertDeclSpecToType(Sema &TheSema, // 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.