From: Chris Lattner Date: Sun, 29 Mar 2009 16:50:03 +0000 (+0000) Subject: Push DeclGroup much farther throughout the compiler. Now the various X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=682bf92db408a6cbc3d37b5496a99b6ef85041ec;p=clang Push DeclGroup much farther throughout the compiler. Now the various productions (except the already broken ObjC cases like @class X,Y;) in the parser that can produce more than one Decl return a DeclGroup instead of a Decl, etc. This allows elimination of the Decl::NextDeclarator field, and exposes various clients that should look at all decls in a group, but which were only looking at one (such as the dumper, printer, etc). These have been fixed. Still TODO: 1) there are some FIXME's in the code about potentially using DeclGroup for better location info. 2) ParseObjCAtDirectives should return a DeclGroup due to @class etc. 3) I'm not sure what is going on with StmtIterator.cpp, or if it can be radically simplified now. 4) I put a truly horrible hack in ParseTemplate.cpp. I plan to bring up #3/4 on the mailing list, but don't plan to tackle #1/2 in the short term. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68002 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h index 70daebf197..cafeecbae4 100644 --- a/include/clang/AST/ASTConsumer.h +++ b/include/clang/AST/ASTConsumer.h @@ -16,7 +16,7 @@ namespace clang { class ASTContext; - class Decl; + class DeclGroupRef; class TagDecl; class HandleTagDeclDefinition; @@ -25,7 +25,7 @@ namespace clang { /// independent of the AST producer (e.g. parser vs AST dump file reader, etc). class ASTConsumer { public: - virtual ~ASTConsumer(); + virtual ~ASTConsumer() {} /// Initialize - This is called to initialize the consumer, providing the /// ASTContext. @@ -35,7 +35,7 @@ public: /// called by the parser to process every top-level Decl*. Note that D can /// be the head of a chain of Decls (e.g. for `int a, b` the chain will have /// two elements). Use Decl::getNextDeclarator() to walk the chain. - virtual void HandleTopLevelDecl(Decl *D) {} + virtual void HandleTopLevelDecl(DeclGroupRef D); /// HandleTranslationUnit - This method is called when the ASTs for entire /// translation unit have been parsed. diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index aaec16ee44..abdb10dcbc 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -100,16 +100,9 @@ public: }; private: - /// NextDeclarator - If this decl was part of a multi-declarator declaration, - /// such as "int X, Y, *Z;" this indicates Decl for the next declarator. - Decl *NextDeclarator; - /// NextDeclInContext - The next declaration within the same lexical /// DeclContext. These pointers form the linked list that is /// traversed via DeclContext's decls_begin()/decls_end(). - /// FIXME: If NextDeclarator is non-NULL, will it always be the same - /// as NextDeclInContext? If so, we can use a - /// PointerIntPair to make Decl smaller. Decl *NextDeclInContext; friend class DeclContext; @@ -176,8 +169,7 @@ protected: friend class CXXClassMemberWrapper; Decl(Kind DK, DeclContext *DC, SourceLocation L) - : NextDeclarator(0), NextDeclInContext(0), - DeclCtx(DC), + : NextDeclInContext(0), DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(0), HasAttrs(false), Implicit(false), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), Access(AS_none) { @@ -276,13 +268,6 @@ public: void setLexicalDeclContext(DeclContext *DC); - /// getNextDeclarator - If this decl was part of a multi-declarator - /// declaration, such as "int X, Y, *Z;" this returns the decl for the next - /// declarator. Otherwise it returns null. - Decl *getNextDeclarator() { return NextDeclarator; } - const Decl *getNextDeclarator() const { return NextDeclarator; } - void setNextDeclarator(Decl *N) { NextDeclarator = N; } - // isDefinedOutsideFunctionOrMethod - This predicate returns true if this // scoped decl is defined outside the current function or method. This is // roughly global variables and functions, but also handles enums (which could diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h index b1c2575361..1a8546339b 100644 --- a/include/clang/AST/DeclGroup.h +++ b/include/clang/AST/DeclGroup.h @@ -34,7 +34,7 @@ private: DeclGroup(unsigned numdecls, Decl** decls); public: - static DeclGroup* Create(ASTContext& C, unsigned numdecls, Decl** decls); + static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls); void Destroy(ASTContext& C); unsigned size() const { return NumDecls; } @@ -57,6 +57,8 @@ public: }; class DeclGroupRef { + // Note this is not a PointerIntPair because we need the address of the + // non-group case to be valid as a Decl** for iteration. enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 }; Decl* D; @@ -71,6 +73,14 @@ public: explicit DeclGroupRef(DeclGroup* dg) : D((Decl*) (reinterpret_cast(dg) | DeclGroupKind)) {} + static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) { + if (NumDecls == 0) + return DeclGroupRef(); + if (NumDecls == 1) + return DeclGroupRef(Decls[0]); + return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls)); + } + typedef Decl** iterator; typedef Decl* const * const_iterator; diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 84023d6678..a58fc81c83 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -71,6 +71,7 @@ public: typedef ActionBase::ExprTy ExprTy; typedef ActionBase::StmtTy StmtTy; typedef OpaquePtr<0> DeclPtrTy; + typedef OpaquePtr<1> DeclGroupPtrTy; typedef void TypeTy; // FIXME: Change TypeTy to use OpaquePtr<1>. typedef void AttrTy; typedef void BaseTy; @@ -130,6 +131,13 @@ public: // Declaration Tracking Callbacks. //===--------------------------------------------------------------------===// + /// ConvertDeclToDeclGroup - If the parser has one decl in a context where it + /// needs a decl group, it calls this to convert between the two + /// representations. + virtual DeclGroupPtrTy ConvertDeclToDeclGroup(DeclPtrTy Ptr) { + return DeclGroupPtrTy(); + } + /// getTypeName - Return non-null if the specified identifier is a type name /// in the current scope. /// An optional CXXScopeSpec can be passed to indicate the C++ scope (class or @@ -210,11 +218,7 @@ public: /// 'Init' specifies the initializer if any. This is for things like: /// "int X = 4" or "typedef int foo". /// - /// LastInGroup is non-null for cases where one declspec has multiple - /// declarators on it. For example in 'int A, B', ActOnDeclarator will be - /// called with LastInGroup=A when invoked for B. - virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D, - DeclPtrTy LastInGroup) { + virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) { return DeclPtrTy(); } @@ -253,10 +257,12 @@ public: /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed, this /// gives the actions implementation a chance to process the group as a whole. - virtual DeclPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy Group) { - return Group; + virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy *Group, + unsigned NumDecls) { + return DeclGroupPtrTy(); } + /// @brief Indicates that all K&R-style parameter declarations have /// been parsed prior to a function definition. /// @param S The function prototype scope. @@ -270,7 +276,7 @@ public: virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) { // Default to ActOnDeclarator. return ActOnStartOfFunctionDef(FnBodyScope, - ActOnDeclarator(FnBodyScope, D,DeclPtrTy())); + ActOnDeclarator(FnBodyScope, D)); } /// ActOnStartOfFunctionDef - This is called at the start of a function @@ -415,7 +421,8 @@ public: bool isStmtExpr) { return StmtEmpty(); } - virtual OwningStmtResult ActOnDeclStmt(DeclPtrTy Decl,SourceLocation StartLoc, + virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, + SourceLocation StartLoc, SourceLocation EndLoc) { return StmtEmpty(); } @@ -1041,8 +1048,7 @@ public: virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, ExprTy *BitfieldWidth, - ExprTy *Init, - DeclPtrTy LastInGroup) { + ExprTy *Init) { return DeclPtrTy(); } @@ -1408,9 +1414,8 @@ public: unsigned allNum = 0, DeclPtrTy *allProperties = 0, unsigned pNum = 0, - DeclPtrTy *allTUVars = 0, + DeclGroupPtrTy *allTUVars = 0, unsigned tuvNum = 0) { - return; } // ActOnProperty - called to build one property AST virtual DeclPtrTy ActOnProperty(Scope *S, SourceLocation AtLoc, @@ -1570,8 +1575,7 @@ public: /// ActOnDeclarator - If this is a typedef declarator, we modify the /// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is /// popped. - virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D, - DeclPtrTy LastInGroup); + virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D); /// ActOnPopScope - When a scope is popped, if any typedefs are now /// out-of-scope, they are removed from the IdentifierInfo::FETokenInfo field. diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 66058ca225..eb820570b9 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -120,6 +120,7 @@ public: typedef Action::ExprTy ExprTy; typedef Action::StmtTy StmtTy; typedef Action::DeclPtrTy DeclPtrTy; + typedef Action::DeclGroupPtrTy DeclGroupPtrTy; typedef Action::TypeTy TypeTy; typedef Action::BaseTy BaseTy; typedef Action::MemInitTy MemInitTy; @@ -167,7 +168,7 @@ public: /// ParseTopLevelDecl - Parse one top-level declaration. Returns true if /// the EOF was encountered. - bool ParseTopLevelDecl(DeclPtrTy &Result); + bool ParseTopLevelDecl(DeclGroupPtrTy &Result); private: //===--------------------------------------------------------------------===// @@ -547,8 +548,8 @@ private: //===--------------------------------------------------------------------===// // C99 6.9: External Definitions. - DeclPtrTy ParseExternalDeclaration(); - DeclPtrTy ParseDeclarationOrFunctionDefinition( + DeclGroupPtrTy ParseExternalDeclaration(); + DeclGroupPtrTy ParseDeclarationOrFunctionDefinition( TemplateParameterLists *TemplateParams = 0, AccessSpecifier AS = AS_none); @@ -807,9 +808,9 @@ private: //===--------------------------------------------------------------------===// // C99 6.7: Declarations. - DeclPtrTy ParseDeclaration(unsigned Context); - DeclPtrTy ParseSimpleDeclaration(unsigned Context); - DeclPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D); + DeclGroupPtrTy ParseDeclaration(unsigned Context); + DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context); + DeclGroupPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D); DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl); void ParseDeclarationSpecifiers(DeclSpec &DS, TemplateParameterLists *TemplateParams = 0, @@ -1009,7 +1010,7 @@ private: AccessSpecifier AS = AS_none); void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType, DeclPtrTy TagDecl); - DeclPtrTy ParseCXXClassMemberDeclaration(AccessSpecifier AS); + void ParseCXXClassMemberDeclaration(AccessSpecifier AS); void ParseConstructorInitializer(DeclPtrTy ConstructorDecl); MemInitResult ParseMemInitializer(DeclPtrTy ConstructorDecl); diff --git a/lib/AST/ASTConsumer.cpp b/lib/AST/ASTConsumer.cpp index 6c44d1ab7b..f37cbdea54 100644 --- a/lib/AST/ASTConsumer.cpp +++ b/lib/AST/ASTConsumer.cpp @@ -12,7 +12,8 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTConsumer.h" -#include "clang/AST/Decl.h" +#include "clang/AST/DeclGroup.h" using namespace clang; -ASTConsumer::~ASTConsumer() {} +void ASTConsumer::HandleTopLevelDecl(DeclGroupRef D) {} + diff --git a/lib/AST/DeclGroup.cpp b/lib/AST/DeclGroup.cpp index 36a7c2b400..64b0399901 100644 --- a/lib/AST/DeclGroup.cpp +++ b/lib/AST/DeclGroup.cpp @@ -19,13 +19,12 @@ #include "llvm/Bitcode/Deserialize.h" using namespace clang; -DeclGroup* DeclGroup::Create(ASTContext& C, unsigned numdecls, Decl** decls) { - assert (numdecls > 0); - unsigned size = sizeof(DeclGroup) + sizeof(Decl*) * numdecls; - unsigned alignment = llvm::AlignOf::Alignment; - void* mem = C.Allocate(size, alignment); - new (mem) DeclGroup(numdecls, decls); - return static_cast(mem); +DeclGroup* DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) { + assert(NumDecls > 1 && "Invalid DeclGroup"); + unsigned Size = sizeof(DeclGroup) + sizeof(Decl*) * NumDecls; + void* Mem = C.Allocate(Size, llvm::AlignOf::Alignment); + new (Mem) DeclGroup(NumDecls, Decls); + return static_cast(Mem); } /// Emit - Serialize a DeclGroup to Bitcode. @@ -37,9 +36,9 @@ void DeclGroup::Emit(llvm::Serializer& S) const { /// Read - Deserialize a DeclGroup from Bitcode. DeclGroup* DeclGroup::Read(llvm::Deserializer& D, ASTContext& C) { unsigned NumDecls = (unsigned) D.ReadInt(); - unsigned size = sizeof(DeclGroup) + sizeof(Decl*) * NumDecls; + unsigned Size = sizeof(DeclGroup) + sizeof(Decl*) * NumDecls; unsigned alignment = llvm::AlignOf::Alignment; - DeclGroup* DG = (DeclGroup*) C.Allocate(size, alignment); + DeclGroup* DG = (DeclGroup*) C.Allocate(Size, alignment); new (DG) DeclGroup(); DG->NumDecls = NumDecls; D.BatchReadOwnedPtrs(NumDecls, &(*DG)[0], C); diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp index 8e3ef08d2c..acaced2468 100644 --- a/lib/AST/DeclSerialization.cpp +++ b/lib/AST/DeclSerialization.cpp @@ -39,7 +39,6 @@ void Decl::Emit(Serializer& S) const { S.EmitInt(Access); S.EmitPtr(cast_or_null(getDeclContext())); // From Decl. S.EmitPtr(cast_or_null(getLexicalDeclContext())); // From Decl. - S.EmitPtr(NextDeclarator); if (const DeclContext *DC = dyn_cast(this)) DC->EmitOutRec(S); @@ -144,7 +143,6 @@ Decl* Decl::Create(Deserializer& D, ASTContext& C) { D.ReadPtr(MDC->SemanticDC, SemaDCPtrID); D.ReadPtr(MDC->LexicalDC, LexicalDCPtrID); } - D.ReadPtr(Dcl->NextDeclarator); if (DeclContext *DC = dyn_cast(Dcl)) DC->ReadOutRec(D, C); bool OwnsNext = D.ReadBool(); diff --git a/lib/AST/StmtIterator.cpp b/lib/AST/StmtIterator.cpp index 94829c01e3..20024f513f 100644 --- a/lib/AST/StmtIterator.cpp +++ b/lib/AST/StmtIterator.cpp @@ -67,12 +67,11 @@ void StmtIteratorBase::NextDecl(bool ImmediateAdvance) { if (inDecl()) { assert (decl); + // FIXME: SIMPLIFY AWAY. if (ImmediateAdvance) - decl = decl->getNextDeclarator(); - - for ( ; decl ; decl = decl->getNextDeclarator()) - if (HandleDecl(decl)) - return; + decl = 0; + else if (HandleDecl(decl)) + return; } else { assert (inDeclGroup()); diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp index d41f1339b0..896464ed5a 100644 --- a/lib/CodeGen/ModuleBuilder.cpp +++ b/lib/CodeGen/ModuleBuilder.cpp @@ -60,16 +60,16 @@ namespace { *M, *TD, Diags)); } - virtual void HandleTopLevelDecl(Decl *D) { + virtual void HandleTopLevelDecl(DeclGroupRef DG) { // Make sure to emit all elements of a Decl. - for (; D; D = D->getNextDeclarator()) - Builder->EmitTopLevelDecl(D); + for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) + Builder->EmitTopLevelDecl(*I); } /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl - /// (e.g. struct, union, enum, class) is completed. This allows the client to - /// hack on the type, which can occur at any point in the file (because these - /// can be defined in declspecs). + /// to (e.g. struct, union, enum, class) is completed. This allows the + /// client hack on the type, which can occur at any point in the file + /// (because these can be defined in declspecs). virtual void HandleTagDeclDefinition(TagDecl *D) { Builder->UpdateCompletedType(D); } diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp index 049228f56c..f31aef61d3 100644 --- a/lib/Parse/MinimalAction.cpp +++ b/lib/Parse/MinimalAction.cpp @@ -144,7 +144,7 @@ MinimalAction::isTemplateName(IdentifierInfo &II, Scope *S, /// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is /// popped. Action::DeclPtrTy -MinimalAction::ActOnDeclarator(Scope *S, Declarator &D, DeclPtrTy LastInGroup) { +MinimalAction::ActOnDeclarator(Scope *S, Declarator &D) { IdentifierInfo *II = D.getIdentifier(); // If there is no identifier associated with this declarator, bail out. diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index e139cf9c3e..45eaa74681 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -27,8 +27,7 @@ Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) { assert((Tok.is(tok::l_brace) || Tok.is(tok::colon)) && "Current token not a '{' or ':'!"); - DeclPtrTy FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0, - DeclPtrTy()); + DeclPtrTy FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0); // Consume the tokens and store them for later parsing. diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 5a8b2b8569..1f8522f094 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -228,27 +228,36 @@ void Parser::FuzzyParseMicrosoftDeclSpec() { /// [C++0x] static_assert-declaration /// others... [FIXME] /// -Parser::DeclPtrTy Parser::ParseDeclaration(unsigned Context) { +Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context) { + DeclPtrTy SingleDecl; switch (Tok.getKind()) { case tok::kw_export: case tok::kw_template: - return ParseTemplateDeclarationOrSpecialization(Context); + SingleDecl = ParseTemplateDeclarationOrSpecialization(Context); + break; case tok::kw_namespace: - return ParseNamespace(Context); + SingleDecl = ParseNamespace(Context); + break; case tok::kw_using: - return ParseUsingDirectiveOrDeclaration(Context); + SingleDecl = ParseUsingDirectiveOrDeclaration(Context); + break; case tok::kw_static_assert: - return ParseStaticAssertDeclaration(); + SingleDecl = ParseStaticAssertDeclaration(); + break; default: return ParseSimpleDeclaration(Context); } + + // This routine returns a DeclGroup, if the thing we parsed only contains a + // single decl, convert it now. + return Actions.ConvertDeclToDeclGroup(SingleDecl); } /// simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl] /// declaration-specifiers init-declarator-list[opt] ';' ///[C90/C++]init-declarator-list ';' [TODO] /// [OMP] threadprivate-directive [TODO] -Parser::DeclPtrTy Parser::ParseSimpleDeclaration(unsigned Context) { +Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context) { // Parse the common declaration-specifiers piece. DeclSpec DS; ParseDeclarationSpecifiers(DS); @@ -257,7 +266,8 @@ Parser::DeclPtrTy Parser::ParseSimpleDeclaration(unsigned Context) { // declaration-specifiers init-declarator-list[opt] ';' if (Tok.is(tok::semi)) { ConsumeToken(); - return Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + return Actions.ConvertDeclToDeclGroup(TheDecl); } Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context); @@ -291,12 +301,11 @@ Parser::DeclPtrTy Parser::ParseSimpleDeclaration(unsigned Context) { /// According to the standard grammar, =default and =delete are function /// definitions, but that definitely doesn't fit with the parser here. /// -Parser::DeclPtrTy Parser:: +Parser::DeclGroupPtrTy Parser:: ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { - - // Declarators may be grouped together ("int X, *Y, Z();"). Provide info so - // that they can be chained properly if the actions want this. - Parser::DeclPtrTy LastDeclInGroup; + // Declarators may be grouped together ("int X, *Y, Z();"). Remember the decls + // that we parse together here. + llvm::SmallVector DeclsInGroup; // At this point, we know that it is not a function definition. Parse the // rest of the init-declarator-list. @@ -307,7 +316,7 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { OwningExprResult AsmLabel(ParseSimpleAsm(&Loc)); if (AsmLabel.isInvalid()) { SkipUntil(tok::semi); - return DeclPtrTy(); + return DeclGroupPtrTy(); } D.setAsmLabel(AsmLabel.release()); @@ -322,21 +331,22 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { } // Inform the current actions module that we just parsed this declarator. - LastDeclInGroup = Actions.ActOnDeclarator(CurScope, D, LastDeclInGroup); + DeclPtrTy ThisDecl = Actions.ActOnDeclarator(CurScope, D); + DeclsInGroup.push_back(ThisDecl); // Parse declarator '=' initializer. if (Tok.is(tok::equal)) { ConsumeToken(); if (getLang().CPlusPlus0x && Tok.is(tok::kw_delete)) { SourceLocation DelLoc = ConsumeToken(); - Actions.SetDeclDeleted(LastDeclInGroup, DelLoc); + Actions.SetDeclDeleted(ThisDecl, DelLoc); } else { OwningExprResult Init(ParseInitializer()); if (Init.isInvalid()) { SkipUntil(tok::semi); - return DeclPtrTy(); + return DeclGroupPtrTy(); } - Actions.AddInitializerToDecl(LastDeclInGroup, move(Init)); + Actions.AddInitializerToDecl(ThisDecl, move(Init)); } } else if (Tok.is(tok::l_paren)) { // Parse C++ direct initializer: '(' expression-list ')' @@ -355,12 +365,12 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { if (!InvalidExpr) { assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() && "Unexpected number of commas!"); - Actions.AddCXXDirectInitializerToDecl(LastDeclInGroup, LParenLoc, + Actions.AddCXXDirectInitializerToDecl(ThisDecl, LParenLoc, move_arg(Exprs), &CommaLocs[0], RParenLoc); } } else { - Actions.ActOnUninitializedDecl(LastDeclInGroup); + Actions.ActOnUninitializedDecl(ThisDecl); } // If we don't have a comma, it is either the end of the list (a ';') or an @@ -395,23 +405,26 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { // for(is key; in keys) is error. if (D.getContext() == Declarator::ForContext && isTokIdentifier_in()) { Diag(Tok, diag::err_parse_error); - return DeclPtrTy(); + return DeclGroupPtrTy(); } - return Actions.FinalizeDeclaratorGroup(CurScope, LastDeclInGroup); + + return Actions.FinalizeDeclaratorGroup(CurScope, &DeclsInGroup[0], + DeclsInGroup.size()); } // If this is an ObjC2 for-each loop, this is a successful declarator // parse. The syntax for these looks like: // 'for' '(' declaration 'in' expr ')' statement if (D.getContext() == Declarator::ForContext && isTokIdentifier_in()) - return Actions.FinalizeDeclaratorGroup(CurScope, LastDeclInGroup); + return Actions.FinalizeDeclaratorGroup(CurScope, &DeclsInGroup[0], + DeclsInGroup.size()); Diag(Tok, diag::err_parse_error); // Skip to end of block or statement SkipUntil(tok::r_brace, true, true); if (Tok.is(tok::semi)) ConsumeToken(); - return DeclPtrTy(); + return DeclGroupPtrTy(); } /// ParseSpecifierQualifierList diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index c50a033e56..37a460cd41 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -663,14 +663,17 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const /// constant-initializer: /// '=' constant-expression /// -Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { +void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { // static_assert-declaration - if (Tok.is(tok::kw_static_assert)) - return ParseStaticAssertDeclaration(); + if (Tok.is(tok::kw_static_assert)) { + ParseStaticAssertDeclaration(); + return; + } - if (Tok.is(tok::kw_template)) - return ParseTemplateDeclarationOrSpecialization(Declarator::MemberContext, - AS); + if (Tok.is(tok::kw_template)) { + ParseTemplateDeclarationOrSpecialization(Declarator::MemberContext, AS); + return; + } // Handle: member-declaration ::= '__extension__' member-declaration if (Tok.is(tok::kw___extension__)) { @@ -692,14 +695,15 @@ Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { // class-specifier or an enum-specifier or in a friend declaration. // FIXME: Friend declarations. switch (DS.getTypeSpecType()) { - case DeclSpec::TST_struct: - case DeclSpec::TST_union: - case DeclSpec::TST_class: - case DeclSpec::TST_enum: - return Actions.ParsedFreeStandingDeclSpec(CurScope, DS); - default: - Diag(DSStart, diag::err_no_declarators); - return DeclPtrTy(); + case DeclSpec::TST_struct: + case DeclSpec::TST_union: + case DeclSpec::TST_class: + case DeclSpec::TST_enum: + Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + return; + default: + Diag(DSStart, diag::err_no_declarators); + return; } } @@ -714,7 +718,7 @@ Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { SkipUntil(tok::r_brace, true); if (Tok.is(tok::semi)) ConsumeToken(); - return DeclPtrTy(); + return; } // function-definition: @@ -724,7 +728,7 @@ Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { Diag(Tok, diag::err_func_def_no_params); ConsumeBrace(); SkipUntil(tok::r_brace, true); - return DeclPtrTy(); + return; } if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { @@ -734,10 +738,11 @@ Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { // assumes the declarator represents a function, not a typedef. ConsumeBrace(); SkipUntil(tok::r_brace, true); - return DeclPtrTy(); + return; } - return ParseCXXInlineMethodDef(AS, DeclaratorInfo); + ParseCXXInlineMethodDef(AS, DeclaratorInfo); + return; } } @@ -745,7 +750,7 @@ Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { // member-declarator // member-declarator-list ',' member-declarator - DeclPtrTy LastDeclInGroup; + llvm::SmallVector DeclsInGroup; OwningExprResult BitfieldSize(Actions); OwningExprResult Init(Actions); @@ -784,14 +789,14 @@ Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { } // NOTE: If Sema is the Action module and declarator is an instance field, - // this call will *not* return the created decl; LastDeclInGroup will be - // returned instead. + // this call will *not* return the created decl; It will return null. // See Sema::ActOnCXXMemberDeclarator for details. - LastDeclInGroup = Actions.ActOnCXXMemberDeclarator(CurScope, AS, - DeclaratorInfo, - BitfieldSize.release(), - Init.release(), - LastDeclInGroup); + DeclPtrTy ThisDecl = Actions.ActOnCXXMemberDeclarator(CurScope, AS, + DeclaratorInfo, + BitfieldSize.release(), + Init.release()); + if (ThisDecl) + DeclsInGroup.push_back(ThisDecl); if (DeclaratorInfo.isFunctionDeclarator() && DeclaratorInfo.getDeclSpec().getStorageClassSpec() @@ -807,7 +812,7 @@ Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { // Push this method onto the stack of late-parsed method // declarations. getCurTopClassStack().MethodDecls.push_back( - LateParsedMethodDeclaration(LastDeclInGroup)); + LateParsedMethodDeclaration(ThisDecl)); LateMethod = &getCurTopClassStack().MethodDecls.back(); // Add all of the parameters prior to this one (they don't @@ -853,8 +858,9 @@ Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { if (Tok.is(tok::semi)) { ConsumeToken(); - // Reverse the chain list. - return Actions.FinalizeDeclaratorGroup(CurScope, LastDeclInGroup); + Actions.FinalizeDeclaratorGroup(CurScope, &DeclsInGroup[0], + DeclsInGroup.size()); + return; } Diag(Tok, diag::err_expected_semi_decl_list); @@ -862,7 +868,7 @@ Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { SkipUntil(tok::r_brace, true, true); if (Tok.is(tok::semi)) ConsumeToken(); - return DeclPtrTy(); + return; } /// ParseCXXMemberSpecification - Parse the class definition. diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 8ff1944a9d..05c919cbea 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -215,7 +215,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, tok::ObjCKeywordKind contextKey) { llvm::SmallVector allMethods; llvm::SmallVector allProperties; - llvm::SmallVector allTUVariables; + llvm::SmallVector allTUVariables; tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword; SourceLocation AtEndLoc; @@ -253,8 +253,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, // FIXME: as the name implies, this rule allows function definitions. // We could pass a flag or check for functions during semantic analysis. - DeclPtrTy VFDecl = ParseDeclarationOrFunctionDefinition(); - allTUVariables.push_back(VFDecl); + allTUVariables.push_back(ParseDeclarationOrFunctionDefinition()); continue; } @@ -359,13 +358,9 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, // Insert collected methods declarations into the @interface object. // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit. Actions.ActOnAtEnd(AtEndLoc, interfaceDecl, - allMethods.empty() ? 0 : &allMethods[0], - allMethods.size(), - allProperties.empty() ? 0 : &allProperties[0], - allProperties.size(), - allTUVariables.empty() ? 0 : - &allTUVariables[0], - allTUVariables.size()); + &allMethods[0], allMethods.size(), + &allProperties[0], allProperties.size(), + &allTUVariables[0], allTUVariables.size()); } /// Parse property attribute declarations. diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index b996c74fcf..b1a32decff 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -101,7 +101,7 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) { default: { if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) { SourceLocation DeclStart = Tok.getLocation(); - DeclPtrTy Decl = ParseDeclaration(Declarator::BlockContext); + DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext); // FIXME: Pass in the right location for the end of the declstmt. return Actions.ActOnDeclStmt(Decl, DeclStart, DeclStart); } @@ -444,7 +444,7 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { if (isDeclarationStatement()) { // FIXME: Save the __extension__ on the decl as a node somehow. SourceLocation DeclStart = Tok.getLocation(); - DeclPtrTy Res = ParseDeclaration(Declarator::BlockContext); + DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext); // FIXME: Pass in the right location for the end of the declstmt. R = Actions.ActOnDeclStmt(Res, DeclStart, DeclStart); } else { @@ -912,10 +912,9 @@ Parser::OwningStmtResult Parser::ParseForStatement() { Diag(Tok, diag::ext_c99_variable_decl_in_for_loop); SourceLocation DeclStart = Tok.getLocation(); - DeclPtrTy aBlockVarDecl = ParseSimpleDeclaration(Declarator::ForContext); + DeclGroupPtrTy VarDecls = ParseSimpleDeclaration(Declarator::ForContext); // FIXME: Pass in the right location for the end of the declstmt. - FirstPart = Actions.ActOnDeclStmt(aBlockVarDecl, DeclStart, - DeclStart); + FirstPart = Actions.ActOnDeclStmt(VarDecls, DeclStart, DeclStart); if ((ForEach = isTokIdentifier_in())) { ConsumeToken(); // consume 'in' SecondPart = ParseExpression(); @@ -929,12 +928,10 @@ Parser::OwningStmtResult Parser::ParseForStatement() { if (Tok.is(tok::semi)) { ConsumeToken(); - } - else if ((ForEach = isTokIdentifier_in())) { + } else if ((ForEach = isTokIdentifier_in())) { ConsumeToken(); // consume 'in' SecondPart = ParseExpression(); - } - else { + } else { if (!Value.isInvalid()) Diag(Tok, diag::err_expected_semi_for); SkipUntil(tok::semi); } @@ -995,11 +992,11 @@ Parser::OwningStmtResult Parser::ParseForStatement() { return Actions.ActOnForStmt(ForLoc, LParenLoc, move(FirstPart), move(SecondPart), move(ThirdPart), RParenLoc, move(Body)); - else - return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, - move(FirstPart), - move(SecondPart), - RParenLoc, move(Body)); + + return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, + move(FirstPart), + move(SecondPart), + RParenLoc, move(Body)); } /// ParseGotoStatement diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 29b8a147db..b962cbf646 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -94,7 +94,12 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template)); // Parse the actual template declaration. - return ParseDeclarationOrFunctionDefinition(&ParamLists, AS); + + // FIXME: This accepts template int y; + // FIXME: Converting DeclGroupPtr to DeclPtr like this is an insanely gruesome + // hack, will bring up on cfe-dev. + DeclGroupPtrTy DG = ParseDeclarationOrFunctionDefinition(&ParamLists, AS); + return DeclPtrTy::make(DG.get()); } /// ParseTemplateParameters - Parses a template-parameter-list enclosed in diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 00a3349c21..56f922d400 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -324,8 +324,8 @@ void Parser::Initialize() { /// ParseTopLevelDecl - Parse one top-level declaration, return whatever the /// action tells us to. This returns true if the EOF was encountered. -bool Parser::ParseTopLevelDecl(DeclPtrTy &Result) { - Result = DeclPtrTy(); +bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { + Result = DeclGroupPtrTy(); if (Tok.is(tok::eof)) { Actions.ActOnEndOfTranslationUnit(); return true; @@ -342,7 +342,7 @@ bool Parser::ParseTopLevelDecl(DeclPtrTy &Result) { void Parser::ParseTranslationUnit() { Initialize(); - DeclPtrTy Res; + DeclGroupPtrTy Res; while (!ParseTopLevelDecl(Res)) /*parse them all*/; @@ -368,20 +368,21 @@ void Parser::ParseTranslationUnit() { /// [GNU] asm-definition: /// simple-asm-expr ';' /// -Parser::DeclPtrTy Parser::ParseExternalDeclaration() { +Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration() { + DeclPtrTy SingleDecl; switch (Tok.getKind()) { case tok::semi: Diag(Tok, diag::ext_top_level_semi); ConsumeToken(); // TODO: Invoke action for top-level semicolon. - return DeclPtrTy(); + return DeclGroupPtrTy(); case tok::r_brace: Diag(Tok, diag::err_expected_external_declaration); ConsumeBrace(); - return DeclPtrTy(); + return DeclGroupPtrTy(); case tok::eof: Diag(Tok, diag::err_expected_external_declaration); - return DeclPtrTy(); + return DeclGroupPtrTy(); case tok::kw___extension__: { // __extension__ silences extension warnings in the subexpression. ExtensionRAIIObject O(Diags); // Use RAII to do this. @@ -394,20 +395,26 @@ Parser::DeclPtrTy Parser::ParseExternalDeclaration() { ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "top-level asm block"); - if (!Result.isInvalid()) - return Actions.ActOnFileScopeAsmDecl(Tok.getLocation(), move(Result)); - return DeclPtrTy(); + if (Result.isInvalid()) + return DeclGroupPtrTy(); + SingleDecl = Actions.ActOnFileScopeAsmDecl(Tok.getLocation(), move(Result)); + break; } case tok::at: - // @ is not a legal token unless objc is enabled, no need to check. - return ParseObjCAtDirectives(); + // @ is not a legal token unless objc is enabled, no need to check for ObjC. + /// FIXME: ParseObjCAtDirectives should return a DeclGroup for things like + /// @class foo, bar; + SingleDecl = ParseObjCAtDirectives(); + break; case tok::minus: case tok::plus: - if (getLang().ObjC1) - return ParseObjCMethodDefinition(); - Diag(Tok, diag::err_expected_external_declaration); - ConsumeToken(); - return DeclPtrTy(); + if (!getLang().ObjC1) { + Diag(Tok, diag::err_expected_external_declaration); + ConsumeToken(); + return DeclGroupPtrTy(); + } + SingleDecl = ParseObjCMethodDefinition(); + break; case tok::kw_using: case tok::kw_namespace: case tok::kw_typedef: @@ -420,6 +427,10 @@ Parser::DeclPtrTy Parser::ParseExternalDeclaration() { // We can't tell whether this is a function-definition or declaration yet. return ParseDeclarationOrFunctionDefinition(); } + + // This routine returns a DeclGroup, if the thing we parsed only contains a + // single decl, convert it now. + return Actions.ConvertDeclToDeclGroup(SingleDecl); } /// ParseDeclarationOrFunctionDefinition - Parse either a function-definition or @@ -438,7 +449,7 @@ Parser::DeclPtrTy Parser::ParseExternalDeclaration() { /// [!C99] init-declarator-list ';' [TODO: warn in c99 mode] /// [OMP] threadprivate-directive [TODO] /// -Parser::DeclPtrTy +Parser::DeclGroupPtrTy Parser::ParseDeclarationOrFunctionDefinition( TemplateParameterLists *TemplateParams, AccessSpecifier AS) { @@ -450,7 +461,8 @@ Parser::ParseDeclarationOrFunctionDefinition( // declaration-specifiers init-declarator-list[opt] ';' if (Tok.is(tok::semi)) { ConsumeToken(); - return Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + return Actions.ConvertDeclToDeclGroup(TheDecl); } // ObjC2 allows prefix attributes on class interfaces and protocols. @@ -462,14 +474,18 @@ Parser::ParseDeclarationOrFunctionDefinition( !Tok.isObjCAtKeyword(tok::objc_protocol)) { Diag(Tok, diag::err_objc_unexpected_attr); SkipUntil(tok::semi); // FIXME: better skip? - return DeclPtrTy(); + return DeclGroupPtrTy(); } const char *PrevSpec = 0; if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec)) Diag(AtLoc, diag::err_invalid_decl_spec_combination) << PrevSpec; + + DeclPtrTy TheDecl; if (Tok.isObjCAtKeyword(tok::objc_protocol)) - return ParseObjCAtProtocolDeclaration(AtLoc, DS.getAttributes()); - return ParseObjCAtInterfaceDeclaration(AtLoc, DS.getAttributes()); + TheDecl = ParseObjCAtProtocolDeclaration(AtLoc, DS.getAttributes()); + else + TheDecl = ParseObjCAtInterfaceDeclaration(AtLoc, DS.getAttributes()); + return Actions.ConvertDeclToDeclGroup(TheDecl); } // If the declspec consisted only of 'extern' and we have a string @@ -477,8 +493,10 @@ Parser::ParseDeclarationOrFunctionDefinition( // 'extern "C"'. if (Tok.is(tok::string_literal) && getLang().CPlusPlus && DS.getStorageClassSpec() == DeclSpec::SCS_extern && - DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) - return ParseLinkage(Declarator::FileContext); + DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) { + DeclPtrTy TheDecl = ParseLinkage(Declarator::FileContext); + return Actions.ConvertDeclToDeclGroup(TheDecl); + } // Parse the first declarator. Declarator DeclaratorInfo(DS, Declarator::FileContext); @@ -489,7 +507,7 @@ Parser::ParseDeclarationOrFunctionDefinition( SkipUntil(tok::r_brace, true, true); if (Tok.is(tok::semi)) ConsumeToken(); - return DeclPtrTy(); + return DeclGroupPtrTy(); } // If the declarator is the start of a function definition, handle it. @@ -500,8 +518,12 @@ Parser::ParseDeclarationOrFunctionDefinition( Tok.is(tok::kw___attribute) || // int X() __attr__ -> not a function def (getLang().CPlusPlus && Tok.is(tok::l_paren)) ) { // int X(0) -> not a function def [C++] - // FALL THROUGH. - } else if (DeclaratorInfo.isFunctionDeclarator() && + // Parse the init-declarator-list for a normal declaration. + return ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo); + } + + + if (DeclaratorInfo.isFunctionDeclarator() && (Tok.is(tok::l_brace) || // int X() {} (!getLang().CPlusPlus && isDeclarationSpecifier()) || // int X(f) int f; {} @@ -519,20 +541,18 @@ Parser::ParseDeclarationOrFunctionDefinition( } else { SkipUntil(tok::semi); } - return DeclPtrTy(); + return DeclGroupPtrTy(); } - return ParseFunctionDefinition(DeclaratorInfo); - } else { - if (DeclaratorInfo.isFunctionDeclarator()) - Diag(Tok, diag::err_expected_fn_body); - else - Diag(Tok, diag::err_invalid_token_after_toplevel_declarator); - SkipUntil(tok::semi); - return DeclPtrTy(); + DeclPtrTy TheDecl = ParseFunctionDefinition(DeclaratorInfo); + return Actions.ConvertDeclToDeclGroup(TheDecl); } - - // Parse the init-declarator-list for a normal declaration. - return ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo); + + if (DeclaratorInfo.isFunctionDeclarator()) + Diag(Tok, diag::err_expected_fn_body); + else + Diag(Tok, diag::err_invalid_token_after_toplevel_declarator); + SkipUntil(tok::semi); + return DeclGroupPtrTy(); } /// ParseFunctionDefinition - We parsed and verified that the specified diff --git a/lib/Sema/ParseAST.cpp b/lib/Sema/ParseAST.cpp index 59a04dad64..4bcb478e89 100644 --- a/lib/Sema/ParseAST.cpp +++ b/lib/Sema/ParseAST.cpp @@ -44,16 +44,14 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, Consumer->Initialize(Ctx); - Parser::DeclPtrTy ADecl; + Parser::DeclGroupPtrTy ADecl; while (!P.ParseTopLevelDecl(ADecl)) { // Not end of file. // If we got a null return and something *was* parsed, ignore it. This // is due to a top-level semicolon, an action override, or a parse error // skipping something. - if (ADecl) { - Decl *D = ADecl.getAs(); - Consumer->HandleTopLevelDecl(D); - } + if (ADecl) + Consumer->HandleTopLevelDecl(ADecl.getAsVal()); }; Consumer->HandleTranslationUnit(Ctx); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 0ebccf3581..b7903c1b59 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -328,29 +328,28 @@ public: /// an empty string if not. This is used for pretty crash reporting. virtual std::string getDeclName(DeclPtrTy D); + DeclGroupPtrTy ConvertDeclToDeclGroup(DeclPtrTy Ptr); + virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc, Scope *S, const CXXScopeSpec *SS); - virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D, - DeclPtrTy LastInGroup){ - return ActOnDeclarator(S, D, LastInGroup, false); + virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) { + return ActOnDeclarator(S, D, false); } - DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D, DeclPtrTy LastInGroup, - bool IsFunctionDefinition); + DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition); void RegisterLocallyScopedExternCDecl(NamedDecl *ND, NamedDecl *PrevDecl, Scope *S); NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, - QualType R, Decl* LastDeclarator, + QualType R, Decl* PrevDecl, bool& InvalidDecl, bool &Redeclaration); NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, - QualType R, Decl* LastDeclarator, + QualType R, NamedDecl* PrevDecl, bool& InvalidDecl, bool &Redeclaration); bool CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl, bool &Redeclaration); NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, - QualType R, Decl *LastDeclarator, - NamedDecl* PrevDecl, + QualType R, NamedDecl* PrevDecl, bool IsFunctionDefinition, bool& InvalidDecl, bool &Redeclaration); bool CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl, @@ -367,8 +366,8 @@ public: void AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit); void ActOnUninitializedDecl(DeclPtrTy dcl); virtual void SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc); - virtual DeclPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy Group); - + virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy *Group, + unsigned NumDecls); virtual void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D); virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *S, Declarator &D); virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *S, DeclPtrTy D); @@ -490,8 +489,7 @@ public: Stmt* ParentCompoundStmt); /// Subroutines of ActOnDeclarator(). - TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T, - Decl *LastDecl); + TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T); bool MergeTypeDefDecl(TypedefDecl *New, Decl *Old); bool MergeFunctionDecl(FunctionDecl *New, Decl *Old); bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old); @@ -1084,7 +1082,7 @@ public: virtual OwningStmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, MultiStmtArg Elts, bool isStmtExpr); - virtual OwningStmtResult ActOnDeclStmt(DeclPtrTy Decl, + virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc); virtual OwningStmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprArg LHSVal, @@ -1589,8 +1587,7 @@ public: virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, ExprTy *BitfieldWidth, - ExprTy *Init, - DeclPtrTy LastInGroup); + ExprTy *Init); virtual MemInitResult ActOnMemInitializer(DeclPtrTy ConstructorD, Scope *S, @@ -2076,7 +2073,7 @@ public: virtual void ActOnAtEnd(SourceLocation AtEndLoc, DeclPtrTy classDecl, DeclPtrTy *allMethods = 0, unsigned allNum = 0, DeclPtrTy *allProperties = 0, unsigned pNum = 0, - DeclPtrTy *allTUVars = 0, unsigned tuvNum = 0); + DeclGroupPtrTy *allTUVars = 0, unsigned tuvNum = 0); virtual DeclPtrTy ActOnProperty(Scope *S, SourceLocation AtLoc, FieldDeclarator &FD, ObjCDeclSpec &ODS, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index f98da95697..be9a0e24d1 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -39,6 +39,10 @@ std::string Sema::getDeclName(DeclPtrTy d) { return ""; } +Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(DeclPtrTy Ptr) { + return DeclGroupPtrTy::make(DeclGroupRef(Ptr.getAs())); +} + /// \brief If the identifier refers to a type name within this scope, /// return the declaration of that type. /// @@ -1235,10 +1239,7 @@ static bool isNearlyMatchingFunction(ASTContext &Context, } Sema::DeclPtrTy -Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclPtrTy lastDecl, - bool IsFunctionDefinition) { - NamedDecl *LastDeclarator = - dyn_cast_or_null(lastDecl.getAs()); +Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) { DeclarationName Name = GetNameForDeclarator(D); // All of these full declarators require an identifier. If it doesn't have @@ -1356,14 +1357,14 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclPtrTy lastDecl, bool Redeclaration = false; if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { - New = ActOnTypedefDeclarator(S, D, DC, R, LastDeclarator, PrevDecl, + New = ActOnTypedefDeclarator(S, D, DC, R, PrevDecl, InvalidDecl, Redeclaration); } else if (R->isFunctionType()) { - New = ActOnFunctionDeclarator(S, D, DC, R, LastDeclarator, PrevDecl, + New = ActOnFunctionDeclarator(S, D, DC, R, PrevDecl, IsFunctionDefinition, InvalidDecl, Redeclaration); } else { - New = ActOnVariableDeclarator(S, D, DC, R, LastDeclarator, PrevDecl, + New = ActOnVariableDeclarator(S, D, DC, R, PrevDecl, InvalidDecl, Redeclaration); } @@ -1454,8 +1455,7 @@ Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, NamedDecl *PrevDecl, NamedDecl* Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, - QualType R, Decl* LastDeclarator, - Decl* PrevDecl, bool& InvalidDecl, + QualType R, Decl* PrevDecl, bool& InvalidDecl, bool &Redeclaration) { // Typedef declarators cannot be qualified (C++ [dcl.meaning]p1). if (D.getCXXScopeSpec().isSet()) { @@ -1475,7 +1475,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, diag::err_virtual_non_function); } - TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, LastDeclarator); + TypedefDecl *NewTD = ParseTypedefDecl(S, D, R); if (!NewTD) return 0; // Handle attributes prior to checking for duplicates in MergeVarDecl @@ -1580,8 +1580,7 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC, NamedDecl* Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, - QualType R, Decl* LastDeclarator, - NamedDecl* PrevDecl, bool& InvalidDecl, + QualType R,NamedDecl* PrevDecl, bool& InvalidDecl, bool &Redeclaration) { DeclarationName Name = GetNameForDeclarator(D); @@ -1645,7 +1644,6 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, // FIXME: Move to DeclGroup... D.getDeclSpec().getSourceRange().getBegin()); NewVD->setThreadSpecified(ThreadSpecified); - NewVD->setNextDeclarator(LastDeclarator); // Set the lexical context. If the declarator has a C++ scope specifier, the // lexical context will be different from the semantic context. @@ -1800,8 +1798,8 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl, NamedDecl* Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, - QualType R, Decl *LastDeclarator, - NamedDecl* PrevDecl, bool IsFunctionDefinition, + QualType R, NamedDecl* PrevDecl, + bool IsFunctionDefinition, bool& InvalidDecl, bool &Redeclaration) { assert(R.getTypePtr()->isFunctionType()); @@ -1937,7 +1935,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // FIXME: Move to DeclGroup... D.getDeclSpec().getSourceRange().getBegin()); } - NewFD->setNextDeclarator(LastDeclarator); // Set the lexical context. If the declarator has a C++ // scope specifier, the lexical context will be different @@ -2517,39 +2514,29 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) { } } -/// The declarators are chained together backwards, reverse the list. -Sema::DeclPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, DeclPtrTy group) { - // Often we have single declarators, handle them quickly. - Decl *Group = group.getAs(); - if (Group == 0) - return DeclPtrTy(); +Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, DeclPtrTy *Group, + unsigned NumDecls) { + llvm::SmallVector Decls; + + for (unsigned i = 0; i != NumDecls; ++i) + if (Decl *D = Group[i].getAs()) + Decls.push_back(D); - Decl *NewGroup = 0; - if (Group->getNextDeclarator() == 0) - NewGroup = Group; - else { // reverse the list. - while (Group) { - Decl *Next = Group->getNextDeclarator(); - Group->setNextDeclarator(NewGroup); - NewGroup = Group; - Group = Next; - } - } // Perform semantic analysis that depends on having fully processed both // the declarator and initializer. - for (Decl *ID = NewGroup; ID; ID = ID->getNextDeclarator()) { - VarDecl *IDecl = dyn_cast(ID); + for (unsigned i = 0, e = Decls.size(); i != e; ++i) { + VarDecl *IDecl = dyn_cast(Decls[i]); if (!IDecl) continue; QualType T = IDecl->getType(); - + // Block scope. C99 6.7p7: If an identifier for an object is declared with // no linkage (C99 6.2.2p6), the type for the object shall be complete... if (IDecl->isBlockVarDecl() && IDecl->getStorageClass() != VarDecl::Extern) { if (!IDecl->isInvalidDecl() && RequireCompleteType(IDecl->getLocation(), T, - diag::err_typecheck_decl_incomplete_type)) + diag::err_typecheck_decl_incomplete_type)) IDecl->setInvalidDecl(); } // File scope. C99 6.9.2p2: A declaration of an identifier for and @@ -2560,13 +2547,13 @@ Sema::DeclPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, DeclPtrTy group) { if (IDecl->isTentativeDefinition(Context)) { QualType CheckType = T; unsigned DiagID = diag::err_typecheck_decl_incomplete_type; - + const IncompleteArrayType *ArrayT = Context.getAsIncompleteArrayType(T); if (ArrayT) { CheckType = ArrayT->getElementType(); DiagID = diag::err_illegal_decl_array_incomplete_type; } - + if (IDecl->isInvalidDecl()) { // Do nothing with invalid declarations } else if ((ArrayT || IDecl->getStorageClass() == VarDecl::Static) && @@ -2578,9 +2565,11 @@ Sema::DeclPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, DeclPtrTy group) { } } } - return DeclPtrTy::make(NewGroup); + return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, + &Decls[0], NumDecls)); } + /// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator() /// to introduce parameters into function prototype scope. Sema::DeclPtrTy @@ -2722,9 +2711,8 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Scope *ParentScope = FnBodyScope->getParent(); - return ActOnStartOfFunctionDef(FnBodyScope, - ActOnDeclarator(ParentScope, D, DeclPtrTy(), - /*IsFunctionDefinition=*/true)); + DeclPtrTy DP = ActOnDeclarator(ParentScope, D, /*IsFunctionDefinition=*/true); + return ActOnStartOfFunctionDef(FnBodyScope, DP); } Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { @@ -3056,8 +3044,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { } } -TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, - Decl *LastDeclarator) { +TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T) { assert(D.getIdentifier() && "Wrong callback for declspec without declarator"); assert(!T.isNull() && "GetTypeForDeclarator() returned null type"); @@ -3076,7 +3063,6 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, TD->setTypedefForAnonDecl(NewTD); } - NewTD->setNextDeclarator(LastDeclarator); if (D.getInvalidType()) NewTD->setInvalidDecl(); return NewTD; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 258641fbc4..ea2af68d16 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -473,8 +473,7 @@ void Sema::ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases, /// declarators on it. Sema::DeclPtrTy Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, - ExprTy *BW, ExprTy *InitExpr, - DeclPtrTy LastInGroup) { + ExprTy *BW, ExprTy *InitExpr) { const DeclSpec &DS = D.getDeclSpec(); DeclarationName Name = GetNameForDeclarator(D); Expr *BitWidth = static_cast(BW); @@ -553,10 +552,10 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, AS); assert(Member && "HandleField never returns null"); } else { - Member = ActOnDeclarator(S, D, LastInGroup).getAs(); + Member = ActOnDeclarator(S, D).getAs(); if (!Member) { if (BitWidth) DeleteExpr(BitWidth); - return LastInGroup; + return DeclPtrTy(); } // Non-instance-fields can't have a bitfield. @@ -595,7 +594,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, if (isInstField) { FieldCollector->Add(cast(Member)); - return LastInGroup; + return DeclPtrTy(); } return DeclPtrTy::make(Member); } diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index d84a0d1726..18e3e4f909 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1234,8 +1234,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclPtrTy classDecl, DeclPtrTy *allMethods, unsigned allNum, DeclPtrTy *allProperties, unsigned pNum, - DeclPtrTy *allTUVars, - unsigned tuvNum) { + DeclGroupPtrTy *allTUVars, unsigned tuvNum) { Decl *ClassDecl = classDecl.getAs(); // FIXME: If we don't have a ClassDecl, we have an error. We should consider @@ -1339,16 +1338,18 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclPtrTy classDecl, } } } - if (isInterfaceDeclKind) - for (unsigned i = 0; i < tuvNum; i++) { - if (VarDecl *VDecl = dyn_cast(allTUVars[i].getAs())) { - if (VDecl->getStorageClass() != VarDecl::Extern && - VDecl->getStorageClass() != VarDecl::PrivateExtern) { - NamedDecl *ClassNameDecl = dyn_cast(ClassDecl); - Diag(VDecl->getLocation(), diag::err_objc_var_decl_inclass) - << ClassNameDecl->getIdentifier(); + if (isInterfaceDeclKind) { + // Reject invalid vardecls. + for (unsigned i = 0; i != tuvNum; i++) { + DeclGroupRef DG = allTUVars[i].getAsVal(); + for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) + if (VarDecl *VDecl = dyn_cast(*I)) { + if (VDecl->getStorageClass() != VarDecl::Extern && + VDecl->getStorageClass() != VarDecl::PrivateExtern) + Diag(VDecl->getLocation(), diag::err_objc_var_decl_inclass) + << cast(ClassDecl)->getIdentifier(); } - } + } } } diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index b331911099..d258ec3869 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -37,31 +37,13 @@ Sema::OwningStmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc) { return Owned(new (Context) NullStmt(SemiLoc)); } -Sema::OwningStmtResult Sema::ActOnDeclStmt(DeclPtrTy decl, +Sema::OwningStmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, SourceLocation StartLoc, SourceLocation EndLoc) { - Decl *D = decl.getAs(); - if (D == 0) - return StmtError(); - - // This is a temporary hack until we are always passing around - // DeclGroupRefs. - llvm::SmallVector decls; - while (D) { - Decl* d = D; - D = D->getNextDeclarator(); - d->setNextDeclarator(0); - decls.push_back(d); - } - - assert (!decls.empty()); - - if (decls.size() == 1) { - DeclGroupRef DG(*decls.begin()); - return Owned(new (Context) DeclStmt(DG, StartLoc, EndLoc)); - } - - DeclGroupRef DG(DeclGroup::Create(Context, decls.size(), &decls[0])); + // If we have an invalid decl, just return an error. + if (!dg) return StmtError(); + + DeclGroupRef DG = dg.getAsVal(); return Owned(new (Context) DeclStmt(DG, StartLoc, EndLoc)); } diff --git a/tools/clang-cc/ASTConsumers.cpp b/tools/clang-cc/ASTConsumers.cpp index cb09659a58..3910c7794e 100644 --- a/tools/clang-cc/ASTConsumers.cpp +++ b/tools/clang-cc/ASTConsumers.cpp @@ -539,8 +539,9 @@ namespace { public: ASTPrinter(llvm::raw_ostream* o = NULL) : DeclPrinter(o) {} - virtual void HandleTopLevelDecl(Decl *D) { - PrintDecl(D); + virtual void HandleTopLevelDecl(DeclGroupRef D) { + for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) + PrintDecl(*I); } }; } // end anonymous namespace @@ -562,11 +563,15 @@ namespace { SM = &Context.getSourceManager(); } - virtual void HandleTopLevelDecl(Decl *D); + virtual void HandleTopLevelDecl(DeclGroupRef D) { + for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) + HandleTopLevelSingleDecl(*I); + } + void HandleTopLevelSingleDecl(Decl *D); }; } // end anonymous namespace -void ASTDumper::HandleTopLevelDecl(Decl *D) { +void ASTDumper::HandleTopLevelSingleDecl(Decl *D) { if (FunctionDecl *FD = dyn_cast(D)) { PrintFunctionDeclStart(FD); @@ -624,12 +629,17 @@ namespace { void Initialize(ASTContext &Context) { SM = &Context.getSourceManager(); } + + virtual void HandleTopLevelDecl(DeclGroupRef D) { + for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) + HandleTopLevelSingleDecl(*I); + } - virtual void HandleTopLevelDecl(Decl *D); + void HandleTopLevelSingleDecl(Decl *D); }; } -void ASTViewer::HandleTopLevelDecl(Decl *D) { +void ASTViewer::HandleTopLevelSingleDecl(Decl *D) { if (FunctionDecl *FD = dyn_cast(D)) { DeclPrinter().PrintFunctionDeclStart(FD); diff --git a/tools/clang-cc/AnalysisConsumer.cpp b/tools/clang-cc/AnalysisConsumer.cpp index 366f3844f5..bc38593404 100644 --- a/tools/clang-cc/AnalysisConsumer.cpp +++ b/tools/clang-cc/AnalysisConsumer.cpp @@ -220,7 +220,12 @@ namespace { Ctx = &Context; } - virtual void HandleTopLevelDecl(Decl *D); + virtual void HandleTopLevelDecl(DeclGroupRef D) { + for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) + HandleTopLevelSingleDecl(*I); + } + + void HandleTopLevelSingleDecl(Decl *D); virtual void HandleTranslationUnit(ASTContext &C); void HandleCode(Decl* D, Stmt* Body, Actions& actions); @@ -411,7 +416,7 @@ namespace llvm { // AnalysisConsumer implementation. //===----------------------------------------------------------------------===// -void AnalysisConsumer::HandleTopLevelDecl(Decl *D) { +void AnalysisConsumer::HandleTopLevelSingleDecl(Decl *D) { switch (D->getKind()) { case Decl::Function: { FunctionDecl* FD = cast(D); diff --git a/tools/clang-cc/Backend.cpp b/tools/clang-cc/Backend.cpp index 0faabbe8d5..3b3be31866 100644 --- a/tools/clang-cc/Backend.cpp +++ b/tools/clang-cc/Backend.cpp @@ -8,11 +8,12 @@ //===----------------------------------------------------------------------===// #include "ASTConsumers.h" +#include "clang/CodeGen/ModuleBuilder.h" +#include "clang/Frontend/CompileOptions.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTConsumer.h" +#include "clang/AST/DeclGroup.h" #include "clang/Basic/TargetInfo.h" -#include "clang/CodeGen/ModuleBuilder.h" -#include "clang/Frontend/CompileOptions.h" #include "llvm/Module.h" #include "llvm/ModuleProvider.h" #include "llvm/PassManager.h" @@ -117,13 +118,14 @@ namespace { LLVMIRGeneration.stopTimer(); } - virtual void HandleTopLevelDecl(Decl *D) { - PrettyStackTraceDecl CrashInfo(D, SourceLocation(), + virtual void HandleTopLevelDecl(DeclGroupRef D) { + PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(), Context->getSourceManager(), "LLVM IR generation of declaration"); + if (CompileOpts.TimePasses) LLVMIRGeneration.startTimer(); - + Gen->HandleTopLevelDecl(D); if (CompileOpts.TimePasses) diff --git a/tools/clang-cc/PrintParserCallbacks.cpp b/tools/clang-cc/PrintParserCallbacks.cpp index 9dce6d837b..dc25f54f3f 100644 --- a/tools/clang-cc/PrintParserCallbacks.cpp +++ b/tools/clang-cc/PrintParserCallbacks.cpp @@ -29,8 +29,7 @@ namespace { /// ActOnDeclarator - This callback is invoked when a declarator is parsed /// and 'Init' specifies the initializer if any. This is for things like: /// "int X = 4" or "typedef int foo". - virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D, - DeclPtrTy LastInGroup) { + virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) { llvm::cout << __FUNCTION__ << " "; if (IdentifierInfo *II = D.getIdentifier()) { llvm::cout << "'" << II->getName() << "'"; @@ -40,7 +39,7 @@ namespace { llvm::cout << "\n"; // Pass up to EmptyActions so that the symbol table is maintained right. - return MinimalAction::ActOnDeclarator(S, D, LastInGroup); + return MinimalAction::ActOnDeclarator(S, D); } /// ActOnPopScope - This callback is called immediately before the specified /// scope is popped and deleted. @@ -112,17 +111,20 @@ namespace { llvm::cout << __FUNCTION__ << "\n"; } - /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed, this - /// gives the actions implementation a chance to process the group as a whole. - virtual DeclPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy Group) { + /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed, + /// this gives the actions implementation a chance to process the group as + /// a whole. + virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy *Group, + unsigned NumDecls) { llvm::cout << __FUNCTION__ << "\n"; - return DeclPtrTy(); + return DeclGroupPtrTy(); } /// ActOnStartOfFunctionDef - This is called at the start of a function /// definition, instead of calling ActOnDeclarator. The Declarator includes /// information about formal arguments that are part of this function. - virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) { + virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, + Declarator &D){ llvm::cout << __FUNCTION__ << "\n"; return DeclPtrTy(); } @@ -256,7 +258,7 @@ namespace { llvm::cout << __FUNCTION__ << "\n"; return StmtEmpty(); } - virtual OwningStmtResult ActOnDeclStmt(DeclPtrTy Decl, + virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc) { llvm::cout << __FUNCTION__ << "\n"; diff --git a/tools/clang-cc/RewriteBlocks.cpp b/tools/clang-cc/RewriteBlocks.cpp index 2672d32ef0..f302913661 100644 --- a/tools/clang-cc/RewriteBlocks.cpp +++ b/tools/clang-cc/RewriteBlocks.cpp @@ -83,7 +83,11 @@ public: const char *NewStr, unsigned NewLength); // Top Level Driver code. - virtual void HandleTopLevelDecl(Decl *D); + virtual void HandleTopLevelDecl(DeclGroupRef D) { + for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) + HandleTopLevelSingleDecl(*I); + } + void HandleTopLevelSingleDecl(Decl *D); void HandleDeclInMainFile(Decl *D); // Top level @@ -336,7 +340,7 @@ void RewriteBlocks::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { // Top Level Driver Code //===----------------------------------------------------------------------===// -void RewriteBlocks::HandleTopLevelDecl(Decl *D) { +void RewriteBlocks::HandleTopLevelSingleDecl(Decl *D) { // Two cases: either the decl could be in the main file, or it could be in a // #included file. If the former, rewrite it now. If the later, check to see // if we rewrote the #include/#import. diff --git a/tools/clang-cc/RewriteObjC.cpp b/tools/clang-cc/RewriteObjC.cpp index e0267ec2d0..5fcecc6030 100644 --- a/tools/clang-cc/RewriteObjC.cpp +++ b/tools/clang-cc/RewriteObjC.cpp @@ -126,7 +126,11 @@ namespace { virtual void Initialize(ASTContext &context); // Top Level Driver code. - virtual void HandleTopLevelDecl(Decl *D); + virtual void HandleTopLevelDecl(DeclGroupRef D) { + for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) + HandleTopLevelSingleDecl(*I); + } + void HandleTopLevelSingleDecl(Decl *D); void HandleDeclInMainFile(Decl *D); RewriteObjC(std::string inFile, std::string outFile, Diagnostic &D, const LangOptions &LOpts); @@ -550,7 +554,7 @@ void RewriteObjC::Initialize(ASTContext &context) { // Top Level Driver Code //===----------------------------------------------------------------------===// -void RewriteObjC::HandleTopLevelDecl(Decl *D) { +void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) { // Two cases: either the decl could be in the main file, or it could be in a // #included file. If the former, rewrite it now. If the later, check to see // if we rewrote the #include/#import. @@ -583,7 +587,7 @@ void RewriteObjC::HandleTopLevelDecl(Decl *D) { for (DeclContext::decl_iterator DI = LSD->decls_begin(), DIEnd = LSD->decls_end(); DI != DIEnd; ++DI) - HandleTopLevelDecl(*DI); + HandleTopLevelSingleDecl(*DI); } // If we have a decl in the main file, see if we should rewrite it. if (SM->isFromMainFile(Loc)) diff --git a/tools/clang-cc/SerializationTest.cpp b/tools/clang-cc/SerializationTest.cpp index 74ccb4b4d1..fda8d8801a 100644 --- a/tools/clang-cc/SerializationTest.cpp +++ b/tools/clang-cc/SerializationTest.cpp @@ -18,6 +18,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/CFG.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclGroup.h" #include "clang.h" #include "ASTConsumers.h" #include "llvm/Support/MemoryBuffer.h" @@ -73,7 +74,7 @@ bool SerializationTest::Serialize(llvm::sys::Path& Filename, TranslationUnitDecl *TUD = Ctx.getTranslationUnitDecl(); for (DeclContext::decl_iterator I = TUD->decls_begin(), E =TUD->decls_end(); I != E; ++I) - FilePrinter->HandleTopLevelDecl(*I); + FilePrinter->HandleTopLevelDecl(DeclGroupRef(*I)); } // Serialize the translation unit. @@ -124,7 +125,7 @@ bool SerializationTest::Deserialize(llvm::sys::Path& Filename, TranslationUnitDecl *TUD = NewCtx->getTranslationUnitDecl(); for (DeclContext::decl_iterator I = TUD->decls_begin(), E = TUD->decls_end(); I != E; ++I) - FilePrinter->HandleTopLevelDecl(*I); + FilePrinter->HandleTopLevelDecl(DeclGroupRef(*I)); } delete NewCtx; diff --git a/tools/clang-cc/clang.cpp b/tools/clang-cc/clang.cpp index c0a2ae726b..5b1e6ab62d 100644 --- a/tools/clang-cc/clang.cpp +++ b/tools/clang-cc/clang.cpp @@ -37,6 +37,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclGroup.h" #include "clang/Parse/Parser.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/LexDiagnostic.h" @@ -1563,7 +1564,7 @@ static void ProcessSerializedFile(const std::string& InFile, Diagnostic& Diag, TranslationUnitDecl *TUD = Ctx->getTranslationUnitDecl(); for (DeclContext::decl_iterator I = TUD->decls_begin(), E = TUD->decls_end(); I != E; ++I) - Consumer->HandleTopLevelDecl(*I); + Consumer->HandleTopLevelDecl(DeclGroupRef(*I)); }