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.