diff options
26 files changed, 802 insertions, 164 deletions
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index b36ff12293..35f9b330dd 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -59,6 +59,7 @@ public: Deprecated, Destructor, FastCall, + Final, Format, FormatArg, GNUInline, @@ -184,12 +185,24 @@ public: class AlignedAttr : public Attr { unsigned Alignment; public: - AlignedAttr(unsigned alignment) : Attr(Aligned), Alignment(alignment) {} + AlignedAttr(unsigned alignment) + : Attr(Aligned), Alignment(alignment) {} /// getAlignment - The specified alignment in bits. unsigned getAlignment() const { return Alignment; } + + /// getMaxAlignment - Get the maximum alignment of attributes on this list. + unsigned getMaxAlignment() const { + const AlignedAttr *Next = getNext<AlignedAttr>(); + if (Next) + return std::max(Next->getMaxAlignment(), Alignment); + else + return Alignment; + } - virtual Attr* clone(ASTContext &C) const { return ::new (C) AlignedAttr(Alignment); } + virtual Attr* clone(ASTContext &C) const { + return ::new (C) AlignedAttr(Alignment); + } // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { @@ -304,6 +317,7 @@ DEF_SIMPLE_ATTR(Malloc); DEF_SIMPLE_ATTR(NoReturn); DEF_SIMPLE_ATTR(AnalyzerNoReturn); DEF_SIMPLE_ATTR(Deprecated); +DEF_SIMPLE_ATTR(Final); class SectionAttr : public Attr { std::string Name; diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 3a8c5bf8f1..890c639431 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -75,6 +75,7 @@ def err_expected_ident_lbrace : Error<"expected identifier or '{'">; def err_expected_lbrace : Error<"expected '{'">; def err_expected_lparen : Error<"expected '('">; def err_expected_rparen : Error<"expected ')'">; +def err_expected_lsquare : Error<"expected '['">; def err_expected_rsquare : Error<"expected ']'">; def err_expected_rbrace : Error<"expected '}'">; def err_expected_greater : Error<"expected '>'">; @@ -245,6 +246,11 @@ def err_operator_missing_type_specifier : Error< def err_anon_type_definition : Error< "declaration of anonymous %0 must be a definition">; +def err_cxx0x_attribute_forbids_arguments : Error< + "C++0x attribute '%0' cannot have an argument list">; +def err_cxx0x_attribute_requires_arguments : Error< + "C++0x attribute '%0' must have an argument list">; +def err_attributes_not_allowed : Error<"an attribute list cannot appear here">; /// C++ Templates def err_expected_template : Error<"expected template">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a864d8ab9e..7ca011986b 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -551,6 +551,12 @@ def err_auto_not_allowed : Error< "|class member|exception declaration|template parameter|block literal}0">; def err_auto_var_requires_init : Error< "declaration of variable %0 with type %1 requires an initializer">; + +// C++0x [[final]] +def err_final_function_overridden : Error< + "declaration of %0 overrides a 'final' function">; +def err_final_base : Error< + "derivation from 'final' %0">; // Objective-C++ def err_objc_decls_may_only_appear_in_global_scope : Error< @@ -638,8 +644,14 @@ def warn_attribute_weak_import_invalid_on_definition : Warning< "'weak_import' attribute cannot be specified on a definition">; def warn_attribute_wrong_decl_type : Warning< "%0 attribute only applies to %select{function|union|" - "variable and function|function or method|parameter|parameter or Objective-C method |" - "function, method or block}1 types">; + "variable and function|function or method|parameter|" + "parameter or Objective-C method |function, method or block|" + "virtual method or class|function, method, or parameter}1 types">; +def err_attribute_wrong_decl_type : Error< + "%0 attribute only applies to %select{function|union|" + "variable and function|function or method|parameter|" + "parameter or Objective-C method |function, method or block|" + "virtual method or class|function, method, or parameter}1 types">; def warn_gnu_inline_attribute_requires_inline : Warning< "'gnu_inline' attribute requires function to be marked 'inline'," " attribute ignored">; diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h index 81bb3007ba..e273cadff1 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Parse/AttributeList.h @@ -33,19 +33,22 @@ namespace clang { class AttributeList { IdentifierInfo *AttrName; SourceLocation AttrLoc; + IdentifierInfo *ScopeName; + SourceLocation ScopeLoc; IdentifierInfo *ParmName; SourceLocation ParmLoc; ActionBase::ExprTy **Args; unsigned NumArgs; AttributeList *Next; - bool DeclspecAttribute; + bool DeclspecAttribute, CXX0XAttribute; AttributeList(const AttributeList &); // DO NOT IMPLEMENT void operator=(const AttributeList &); // DO NOT IMPLEMENT public: AttributeList(IdentifierInfo *AttrName, SourceLocation AttrLoc, + IdentifierInfo *ScopeName, SourceLocation ScopeLoc, IdentifierInfo *ParmName, SourceLocation ParmLoc, ActionBase::ExprTy **args, unsigned numargs, - AttributeList *Next, bool declspec = false); + AttributeList *Next, bool declspec = false, bool cxx0x = false); ~AttributeList(); enum Kind { // Please keep this list alphabetized. @@ -57,6 +60,7 @@ public: AT_analyzer_noreturn, AT_annotate, AT_blocks, + AT_carries_dependency, AT_cdecl, AT_cleanup, AT_const, @@ -67,6 +71,7 @@ public: AT_dllimport, AT_ext_vector_type, AT_fastcall, + AT_final, AT_format, AT_format_arg, AT_gnu_inline, @@ -106,8 +111,15 @@ public: IdentifierInfo *getName() const { return AttrName; } SourceLocation getLoc() const { return AttrLoc; } + + bool hasScope() const { return ScopeName; } + IdentifierInfo *getScopeName() const { return ScopeName; } + SourceLocation getScopeLoc() const { return ScopeLoc; } + IdentifierInfo *getParameterName() const { return ParmName; } + bool isDeclspecAttribute() const { return DeclspecAttribute; } + bool isCXX0XAttribute() const { return CXX0XAttribute; } Kind getKind() const { return getKind(getName()); } static Kind getKind(const IdentifierInfo *Name); @@ -181,6 +193,22 @@ inline AttributeList* addAttributeLists (AttributeList *Left, return Left; } +/// CXX0XAttributeList - A wrapper around a C++0x attribute list. +/// Stores, in addition to the list proper, whether or not an actual list was +/// (as opposed to an empty list, which may be ill-formed in some places) and +/// the source range of the list. +struct CXX0XAttributeList { + AttributeList *AttrList; + SourceRange Range; + bool HasAttr; + CXX0XAttributeList (AttributeList *attrList, SourceRange range, bool hasAttr) + : AttrList(attrList), Range(range), HasAttr (hasAttr) { + } + CXX0XAttributeList () + : AttrList(0), Range(), HasAttr(false) { + } +}; + } // end namespace clang #endif diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 814064a79e..b1375d7d65 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -24,6 +24,7 @@ namespace clang { class AttributeList; + struct CXX0XAttributeList; class PragmaHandler; class Scope; class DiagnosticBuilder; @@ -753,10 +754,10 @@ private: //===--------------------------------------------------------------------===// // C99 6.9: External Definitions. - DeclGroupPtrTy ParseExternalDeclaration(); + DeclGroupPtrTy ParseExternalDeclaration(CXX0XAttributeList Attr); bool isDeclarationAfterDeclarator(); bool isStartOfFunctionDefinition(); - DeclGroupPtrTy ParseDeclarationOrFunctionDefinition( + DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(AttributeList *Attr, AccessSpecifier AS = AS_none); DeclPtrTy ParseFunctionDefinition(ParsingDeclarator &D, @@ -994,24 +995,25 @@ private: return ParseStatementOrDeclaration(true); } OwningStmtResult ParseStatementOrDeclaration(bool OnlyStatement = false); - OwningStmtResult ParseLabeledStatement(); - OwningStmtResult ParseCaseStatement(); - OwningStmtResult ParseDefaultStatement(); - OwningStmtResult ParseCompoundStatement(bool isStmtExpr = false); + OwningStmtResult ParseLabeledStatement(AttributeList *Attr); + OwningStmtResult ParseCaseStatement(AttributeList *Attr); + OwningStmtResult ParseDefaultStatement(AttributeList *Attr); + OwningStmtResult ParseCompoundStatement(AttributeList *Attr, + bool isStmtExpr = false); OwningStmtResult ParseCompoundStatementBody(bool isStmtExpr = false); bool ParseParenExprOrCondition(OwningExprResult &CondExp, bool OnlyAllowCondition = false, SourceLocation *LParenLoc = 0, SourceLocation *RParenLoc = 0); - OwningStmtResult ParseIfStatement(); - OwningStmtResult ParseSwitchStatement(); - OwningStmtResult ParseWhileStatement(); - OwningStmtResult ParseDoStatement(); - OwningStmtResult ParseForStatement(); - OwningStmtResult ParseGotoStatement(); - OwningStmtResult ParseContinueStatement(); - OwningStmtResult ParseBreakStatement(); - OwningStmtResult ParseReturnStatement(); + OwningStmtResult ParseIfStatement(AttributeList *Attr); + OwningStmtResult ParseSwitchStatement(AttributeList *Attr); + OwningStmtResult ParseWhileStatement(AttributeList *Attr); + OwningStmtResult ParseDoStatement(AttributeList *Attr); + OwningStmtResult ParseForStatement(AttributeList *Attr); + OwningStmtResult ParseGotoStatement(AttributeList *Attr); + OwningStmtResult ParseContinueStatement(AttributeList *Attr); + OwningStmtResult ParseBreakStatement(AttributeList *Attr); + OwningStmtResult ParseReturnStatement(AttributeList *Attr); OwningStmtResult ParseAsmStatement(bool &msAsm); OwningStmtResult FuzzyParseMicrosoftAsmStatement(); bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names, @@ -1021,7 +1023,7 @@ private: //===--------------------------------------------------------------------===// // C++ 6: Statements and Blocks - OwningStmtResult ParseCXXTryBlock(); + OwningStmtResult ParseCXXTryBlock(AttributeList *Attr); OwningStmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc); OwningStmtResult ParseCXXCatchBlock(); @@ -1045,9 +1047,11 @@ private: DSC_class // class context, enables 'friend' }; - DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd); + DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd, + CXX0XAttributeList Attr); DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context, - SourceLocation &DeclEnd); + SourceLocation &DeclEnd, + AttributeList *Attr); DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context, bool AllowFunctionDefinitions, SourceLocation *DeclEnd = 0); @@ -1217,11 +1221,14 @@ private: void ParseBlockId(); // EndLoc, if non-NULL, is filled with the location of the last token of // the attribute list. - AttributeList *ParseAttributes(SourceLocation *EndLoc = 0); + CXX0XAttributeList ParseCXX0XAttributes(SourceLocation *EndLoc = 0); + AttributeList *ParseGNUAttributes(SourceLocation *EndLoc = 0); AttributeList *ParseMicrosoftDeclSpec(AttributeList* CurrAttr = 0); AttributeList *ParseMicrosoftTypeAttributes(AttributeList* CurrAttr = 0); void ParseTypeofSpecifier(DeclSpec &DS); void ParseDecltypeSpecifier(DeclSpec &DS); + + OwningExprResult ParseCXX0XAlignArgument(SourceLocation Start); /// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to /// enter a new C++ declarator scope and exit it when the function is @@ -1265,7 +1272,8 @@ private: typedef void (Parser::*DirectDeclParseFunction)(Declarator&); void ParseDeclaratorInternal(Declarator &D, DirectDeclParseFunction DirectDeclParser); - void ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed = true); + void ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed = true, + bool CXX0XAttributesAllowed = true); void ParseDirectDeclarator(Declarator &D); void ParseParenDeclarator(Declarator &D); void ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, @@ -1278,12 +1286,17 @@ private: //===--------------------------------------------------------------------===// // C++ 7: Declarations [dcl.dcl] + bool isCXX0XAttributeSpecifier(bool FullLookahead = false, + tok::TokenKind *After = 0); + DeclPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd); DeclPtrTy ParseLinkage(unsigned Context); DeclPtrTy ParseUsingDirectiveOrDeclaration(unsigned Context, - SourceLocation &DeclEnd); + SourceLocation &DeclEnd, + CXX0XAttributeList Attrs); DeclPtrTy ParseUsingDirective(unsigned Context, SourceLocation UsingLoc, - SourceLocation &DeclEnd); + SourceLocation &DeclEnd, + AttributeList *Attr); DeclPtrTy ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc, SourceLocation &DeclEnd, AccessSpecifier AS = AS_none); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index aced8c7623..6121580bab 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -521,7 +521,7 @@ unsigned ASTContext::getDeclAlignInBytes(const Decl *D) { unsigned Align = Target.getCharWidth(); if (const AlignedAttr* AA = D->getAttr<AlignedAttr>()) - Align = std::max(Align, AA->getAlignment()); + Align = std::max(Align, AA->getMaxAlignment()); if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) { QualType T = VD->getType(); @@ -761,7 +761,8 @@ ASTContext::getTypeInfo(const Type *T) { case Type::Typedef: { const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl(); if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) { - Align = Aligned->getAlignment(); + Align = std::max(Aligned->getMaxAlignment(), + getTypeAlign(Typedef->getUnderlyingType().getTypePtr())); Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr()); } else return getTypeInfo(Typedef->getUnderlyingType().getTypePtr()); diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index b9cfcfec74..c084ba6f51 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -448,7 +448,7 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) { MaxFieldAlignment = PPA->getAlignment(); if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) - UpdateAlignment(AA->getAlignment()); + UpdateAlignment(AA->getMaxAlignment()); // If this is a C++ class, lay out the vtable and the non-virtual bases. const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D); @@ -498,7 +498,7 @@ void ASTRecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D, MaxFieldAlignment = PPA->getAlignment(); if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) - UpdateAlignment(AA->getAlignment()); + UpdateAlignment(AA->getMaxAlignment()); // Layout each ivar sequentially. llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; @@ -539,8 +539,9 @@ void ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) { if (FieldPacked) FieldAlign = 1; - if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) - FieldAlign = std::max(FieldAlign, AA->getAlignment()); + if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) { + FieldAlign = std::max(FieldAlign, AA->getMaxAlignment()); + } // The maximum field alignment overrides the aligned attribute. if (MaxFieldAlignment) FieldAlign = std::min(FieldAlign, MaxFieldAlignment); @@ -574,8 +575,9 @@ void ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) { if (FieldPacked) FieldAlign = 8; - if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) - FieldAlign = std::max(FieldAlign, AA->getAlignment()); + if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) { + FieldAlign = std::max(FieldAlign, AA->getMaxAlignment()); + } // The maximum field alignment overrides the aligned attribute. if (MaxFieldAlignment) FieldAlign = std::min(FieldAlign, MaxFieldAlignment); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 1fbd3b9273..b8027d8314 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -353,8 +353,12 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, else if (Features.getStackProtectorMode() == LangOptions::SSPReq) F->addFnAttr(llvm::Attribute::StackProtectReq); - if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) - F->setAlignment(AA->getAlignment()/8); + if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) { + unsigned width = Context.Target.getCharWidth(); + F->setAlignment(AA->getAlignment() / width); + while ((AA = AA->getNext<AlignedAttr>())) + F->setAlignment(std::max(F->getAlignment(), AA->getAlignment() / width)); + } // C++ ABI requires 2-byte alignment for member functions. if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D)) F->setAlignment(2); diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 6a92a2db51..328bb611ba 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -461,6 +461,7 @@ Attr *PCHReader::ReadAttributes() { SIMPLE_ATTR(Deprecated); UNSIGNED_ATTR(Destructor); SIMPLE_ATTR(FastCall); + SIMPLE_ATTR(Final); case Attr::Format: { std::string Type = ReadString(Record, Idx); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 8a45ebce1b..e3f6c62c2d 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1792,6 +1792,7 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) { break; case Attr::FastCall: + case Attr::Final: break; case Attr::Format: { diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index dde4bc866a..7e2935c2e0 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -17,11 +17,13 @@ using namespace clang; AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc, + IdentifierInfo *sName, SourceLocation sLoc, IdentifierInfo *pName, SourceLocation pLoc, ActionBase::ExprTy **ExprList, unsigned numArgs, - AttributeList *n, bool declspec) - : AttrName(aName), AttrLoc(aLoc), ParmName(pName), ParmLoc(pLoc), - NumArgs(numArgs), Next(n), DeclspecAttribute(declspec) { + AttributeList *n, bool declspec, bool cxx0x) + : AttrName(aName), AttrLoc(aLoc), ScopeName(sName), ScopeLoc(sLoc), + ParmName(pName), ParmLoc(pLoc), NumArgs(numArgs), Next(n), + DeclspecAttribute(declspec), CXX0XAttribute(cxx0x) { if (numArgs == 0) Args = 0; @@ -59,6 +61,8 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { .Case("mode", AT_mode) .Case("used", AT_used) .Case("alias", AT_alias) + .Case("align", AT_aligned) + .Case("final", AT_final) .Case("cdecl", AT_cdecl) .Case("const", AT_const) .Case("packed", AT_packed) @@ -103,6 +107,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { .Case("transparent_union", AT_transparent_union) .Case("analyzer_noreturn", AT_analyzer_noreturn) .Case("warn_unused_result", AT_warn_unused_result) + .Case("carries_dependency", AT_carries_dependency) .Case("ns_returns_retained", AT_ns_returns_retained) .Case("cf_returns_retained", AT_cf_returns_retained) .Case("reqd_work_group_size", AT_reqd_wg_size) diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 2bfda30a95..b13dc73356 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1,3 +1,4 @@ + //===--- ParseDecl.cpp - Declaration Parsing ------------------------------===// // // The LLVM Compiler Infrastructure @@ -45,7 +46,7 @@ Action::TypeResult Parser::ParseTypeName(SourceRange *Range) { return Actions.ActOnTypeName(CurScope, DeclaratorInfo); } -/// ParseAttributes - Parse a non-empty attributes list. +/// ParseGNUAttributes - Parse a non-empty attributes list. /// /// [GNU] attributes: /// attribute @@ -81,8 +82,8 @@ Action::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::ParseAttributes(SourceLocation *EndLoc) { - assert(Tok.is(tok::kw___attribute) && "Not an attribute list!"); +AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) { + assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!"); AttributeList *CurrAttr = 0; @@ -121,7 +122,7 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) { if (Tok.is(tok::r_paren)) { // __attribute__(( mode(byte) )) ConsumeParen(); // ignore the right paren loc for now - CurrAttr = new AttributeList(AttrName, AttrNameLoc, + CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, ParmName, ParmLoc, 0, 0, CurrAttr); } else if (Tok.is(tok::comma)) { ConsumeToken(); @@ -145,8 +146,10 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) { } if (ArgExprsOk && Tok.is(tok::r_paren)) { ConsumeParen(); // ignore the right paren loc for now - CurrAttr = new AttributeList(AttrName, AttrNameLoc, ParmName, - ParmLoc, ArgExprs.take(), ArgExprs.size(), CurrAttr); + CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, + AttrNameLoc, ParmName, ParmLoc, + ArgExprs.take(), ArgExprs.size(), + CurrAttr); } } } else { // not an identifier @@ -155,7 +158,7 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) { // parse a possibly empty comma separated list of expressions // __attribute__(( nonnull() )) ConsumeParen(); // ignore the right paren loc for now - CurrAttr = new AttributeList(AttrName, AttrNameLoc, + CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(), 0, 0, CurrAttr); break; case tok::kw_char: @@ -175,7 +178,7 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) { // If it's a builtin type name, eat it and expect a rparen // __attribute__(( vec_type_hint(char) )) ConsumeToken(); - CurrAttr = new AttributeList(AttrName, AttrNameLoc, + CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(), 0, 0, CurrAttr); if (Tok.is(tok::r_paren)) ConsumeParen(); @@ -203,20 +206,21 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) { if (ArgExprsOk && Tok.is(tok::r_paren)) { ConsumeParen(); // ignore the right paren loc for now CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, - SourceLocation(), ArgExprs.take(), ArgExprs.size(), + AttrNameLoc, 0, SourceLocation(), ArgExprs.take(), + ArgExprs.size(), CurrAttr); } break; } } } else { - CurrAttr = new AttributeList(AttrName, AttrNameLoc, + CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(), 0, 0, CurrAttr); } } if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) SkipUntil(tok::r_paren, false); - SourceLocation Loc = Tok.getLocation();; + SourceLocation Loc = Tok.getLocation(); if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) { SkipUntil(tok::r_paren, false); } @@ -254,15 +258,15 @@ AttributeList* Parser::ParseMicrosoftDeclSpec(AttributeList *CurrAttr) { OwningExprResult ArgExpr(ParseAssignmentExpression()); if (!ArgExpr.isInvalid()) { ExprTy* ExprList = ArgExpr.take(); - CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, + CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(), &ExprList, 1, CurrAttr, true); } if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) SkipUntil(tok::r_paren, false); } else { - CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, SourceLocation(), - 0, 0, CurrAttr, true); + CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, + 0, SourceLocation(), 0, 0, CurrAttr, true); } } if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) @@ -281,7 +285,7 @@ AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) { if (Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64)) // FIXME: Support these properly! continue; - CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, + CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(), 0, 0, CurrAttr, true); } return CurrAttr; @@ -304,26 +308,36 @@ AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) { /// others... [FIXME] /// Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, - SourceLocation &DeclEnd) { + SourceLocation &DeclEnd, + CXX0XAttributeList Attr) { DeclPtrTy SingleDecl; 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; SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd); break; case tok::kw_namespace: + if (Attr.HasAttr) + Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed) + << Attr.Range; SingleDecl = ParseNamespace(Context, DeclEnd); break; case tok::kw_using: - SingleDecl = ParseUsingDirectiveOrDeclaration(Context, DeclEnd); + SingleDecl = ParseUsingDirectiveOrDeclaration(Context, DeclEnd, Attr); break; case tok::kw_static_assert: + if (Attr.HasAttr) + Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed) + << Attr.Range; SingleDecl = ParseStaticAssertDeclaration(DeclEnd); break; default: - return ParseSimpleDeclaration(Context, DeclEnd); + return ParseSimpleDeclaration(Context, DeclEnd, Attr.AttrList); } - + // This routine returns a DeclGroup, if the thing we parsed only contains a // single decl, convert it now. return Actions.ConvertDeclToDeclGroup(SingleDecl); @@ -337,9 +351,12 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, /// If RequireSemi is false, this does not check for a ';' at the end of the /// declaration. Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context, - SourceLocation &DeclEnd) { + SourceLocation &DeclEnd, + AttributeList *Attr) { // Parse the common declaration-specifiers piece. ParsingDeclSpec DS(*this); + if (Attr) + DS.AddAttributes(Attr); ParseDeclarationSpecifiers(DS); // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" @@ -422,7 +439,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // short x, __attribute__((common)) var; -> declarator if (Tok.is(tok::kw___attribute)) { SourceLocation Loc; - AttributeList *AttrList = ParseAttributes(&Loc); + AttributeList *AttrList = ParseGNUAttributes(&Loc); D.AddAttributes(AttrList, Loc); } @@ -491,7 +508,7 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D, // If attributes are present, parse them. if (Tok.is(tok::kw___attribute)) { SourceLocation Loc; - AttributeList *AttrList = ParseAttributes(&Loc); + AttributeList *AttrList = ParseGNUAttributes(&Loc); D.AddAttributes(AttrList, Loc); } @@ -988,7 +1005,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // GNU attributes support. case tok::kw___attribute: - DS.AddAttributes(ParseAttributes()); + DS.AddAttributes(ParseGNUAttributes()); continue; // Microsoft declspec support. @@ -1522,7 +1539,7 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) { // Attributes are only allowed here on successive declarators. if (!FirstDeclarator && Tok.is(tok::kw___attribute)) { SourceLocation Loc; - AttributeList *AttrList = ParseAttributes(&Loc); + AttributeList *AttrList = ParseGNUAttributes(&Loc); DeclaratorInfo.D.AddAttributes(AttrList, Loc); } @@ -1543,7 +1560,7 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) { // If attributes exist after the declarator, parse them. if (Tok.is(tok::kw___attribute)) { SourceLocation Loc; - AttributeList *AttrList = ParseAttributes(&Loc); + AttributeList *AttrList = ParseGNUAttributes(&Loc); DeclaratorInfo.D.AddAttributes(AttrList, Loc); } @@ -1667,7 +1684,7 @@ void P |