diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp index 3479cfb20a..a3d837fb2c 100644 --- a/Driver/ASTConsumers.cpp +++ b/Driver/ASTConsumers.cpp @@ -331,6 +331,8 @@ namespace { PrintObjcCompatibleAliasDecl(OID); } else if (isa(D)) { Out << "@class [printing todo]\n"; + } else if (TagDecl *TD = dyn_cast(D)) { + Out << "Read top-level tag decl: '" << TD->getName() << "'\n"; } else if (ScopedDecl *SD = dyn_cast(D)) { Out << "Read top-level variable decl: '" << SD->getName() << "'\n"; } else { diff --git a/Parse/Parser.cpp b/Parse/Parser.cpp index 8a0d8c7ecd..6e03328592 100644 --- a/Parse/Parser.cpp +++ b/Parse/Parser.cpp @@ -259,11 +259,10 @@ 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(DeclTy*& Result) { - Result = 0; +bool Parser::ParseTopLevelDecl() { if (Tok.is(tok::eof)) return true; - Result = ParseExternalDeclaration(); + ParseExternalDeclaration(); return false; } @@ -281,8 +280,7 @@ void Parser::Finalize() { void Parser::ParseTranslationUnit() { Initialize(); - DeclTy *Res; - while (!ParseTopLevelDecl(Res)) + while (!ParseTopLevelDecl()) /*parse them all*/; Finalize(); diff --git a/Sema/ASTStreamer.cpp b/Sema/ASTStreamer.cpp index be43289be5..5a372da088 100644 --- a/Sema/ASTStreamer.cpp +++ b/Sema/ASTStreamer.cpp @@ -24,10 +24,10 @@ ASTConsumer::~ASTConsumer() {} namespace { class ASTStreamer { Parser P; - std::vector LastInGroupList; + std::vector TopLevelDeclList; public: ASTStreamer(Preprocessor &pp, ASTContext &ctxt, unsigned MainFileID) - : P(pp, *new Sema(pp, ctxt, LastInGroupList)) { + : P(pp, *new Sema(pp, ctxt, TopLevelDeclList)) { pp.EnterMainSourceFile(MainFileID); // Initialize the parser. @@ -53,29 +53,28 @@ Decl *ASTStreamer::ReadTopLevelDecl() { /// If the previous time through we read something like 'int X, Y', return /// the next declarator. - if (!LastInGroupList.empty()) { - Result = LastInGroupList.back(); - LastInGroupList.pop_back(); + if (!TopLevelDeclList.empty()) { + Result = TopLevelDeclList.back(); + TopLevelDeclList.pop_back(); return static_cast(Result); } do { - if (P.ParseTopLevelDecl(Result)) + if (P.ParseTopLevelDecl()) return 0; // End of file. // If we got a null return and something *was* parsed, try again. This // is due to a top-level semicolon, an action override, or a parse error // skipping something. - } while (Result == 0); + } while (TopLevelDeclList.size() == 0); // If we parsed a declspec with multiple declarators, reverse the list and // return the first one. - if (!LastInGroupList.empty()) { - LastInGroupList.push_back((Decl*)Result); - std::reverse(LastInGroupList.begin(), LastInGroupList.end()); - Result = LastInGroupList.back(); - LastInGroupList.pop_back(); - } + if (TopLevelDeclList.size() > 1) + std::reverse(TopLevelDeclList.begin(), TopLevelDeclList.end()); + + Result = TopLevelDeclList.back(); + TopLevelDeclList.pop_back(); return static_cast(Result); } diff --git a/Sema/Sema.cpp b/Sema/Sema.cpp index 323483586b..d3930f60fa 100644 --- a/Sema/Sema.cpp +++ b/Sema/Sema.cpp @@ -64,7 +64,7 @@ QualType Sema::GetObjcProtoType(SourceLocation Loc) { } Sema::Sema(Preprocessor &pp, ASTContext &ctxt, std::vector &prevInGroup) - : PP(pp), Context(ctxt), CurFunctionDecl(0), LastInGroupList(prevInGroup) { + : PP(pp), Context(ctxt), CurFunctionDecl(0), TopLevelDeclList(prevInGroup) { // Get IdentifierInfo objects for known functions for which we // do extra checking. diff --git a/Sema/Sema.h b/Sema/Sema.h index 1b232df356..cbb94bc372 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -69,11 +69,9 @@ class Sema : public Action { /// the method decl for the method being parsed. ObjcMethodDecl *CurMethodDecl; - /// LastInGroupList - This vector is populated when there are multiple - /// declarators in a single decl group (e.g. "int A, B, C"). In this case, - /// all but the last decl will be entered into this. This is used by the - /// ASTStreamer. - std::vector &LastInGroupList; + /// TopLevelDeclList - This vector is populated with all declarators from + /// a top-level declaration. This is used by the ASTStreamer. + std::vector &TopLevelDeclList; /// LabelMap - This is a mapping from label identifiers to the LabelStmt for /// it (which acts like the label decl in some ways). Forward referenced @@ -231,7 +229,7 @@ private: VarDecl *MergeVarDecl(VarDecl *New, ScopedDecl *Old); /// AddTopLevelDecl - called after the decl has been fully processed. /// Allows for bookkeeping and post-processing of each declaration. - void AddTopLevelDecl(Decl *current, Decl *last); + void AddTopLevelDecl(Decl *current); /// More parsing and symbol table subroutines... ParmVarDecl *ActOnParamDeclarator(struct DeclaratorChunk::ParamInfo &PI, diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index 88635c3bc5..9907c06f2b 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -192,7 +192,7 @@ ScopedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, II->setFETokenInfo(New); } // Make sure clients iterating over decls see this. - LastInGroupList.push_back(New); + AddTopLevelDecl(New); return New; } @@ -678,7 +678,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) { } if (S->getParent() == 0) - AddTopLevelDecl(New, LastDeclarator); + AddTopLevelDecl(New); // If any semantic error occurred, mark the decl as invalid. if (D.getInvalidType() || InvalidDecl) @@ -973,7 +973,7 @@ void Sema::ObjcActOnStartOfMethodDef(Scope *FnBodyScope, DeclTy *D) { NewFD->setNext(II->getFETokenInfo()); II->setFETokenInfo(NewFD); GlobalScope->AddDecl(NewFD); - AddTopLevelDecl(NewFD, 0); + AddTopLevelDecl(NewFD); // Allow all of Sema to see that we are entering a method definition. CurMethodDecl = MDecl; @@ -1683,6 +1683,12 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK, break; } + // For top-level tag definitions, make sure we chain the the tag decl to + // the vardecl. This enables the AST streamer to see both X and D in the + // following example: struct X { int A; } D; + if (S->getParent() == 0) + AddTopLevelDecl(New); + // If this has an identifier, add it to the scope stack. if (Name) { // The scope passed in may not be a decl scope. Zip up the scope tree until @@ -1695,7 +1701,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK, Name->setFETokenInfo(New); S->AddDecl(New); } - + return New; } @@ -2456,13 +2462,12 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX, Enum->defineElements(EltList, BestType); } -void Sema::AddTopLevelDecl(Decl *current, Decl *last) { +void Sema::AddTopLevelDecl(Decl *current) { if (!current) return; // If this is a top-level decl that is chained to some other (e.g. int A,B,C;) - // remember this in the LastInGroupList list. - if (last) - LastInGroupList.push_back((Decl*)last); + // remember this in the TopLevelDeclList list. + TopLevelDeclList.push_back((Decl*)current); } void Sema::HandleDeclAttribute(Decl *New, AttributeList *rawAttr) { diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj index db10ad3f44..1585d851d9 100644 --- a/clang.xcodeproj/project.pbxproj +++ b/clang.xcodeproj/project.pbxproj @@ -766,6 +766,7 @@ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */; + compatibilityVersion = "Xcode 2.4"; hasScannedForEncodings = 1; mainGroup = 08FB7794FE84155DC02AAC07 /* clang */; projectDirPath = ""; diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 3fb3e2e7c8..7b479e6620 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -74,9 +74,9 @@ public: /// void Initialize(); - /// ParseTopLevelDecl - Parse one top-level declaration, return whatever the - /// action tells us to. This returns true if the EOF was encountered. - bool ParseTopLevelDecl(DeclTy*& Result); + /// ParseTopLevelDecl - Parse one top-level declaration. Returns true if + /// the EOF was encountered. + bool ParseTopLevelDecl(); /// Finalize - Shut down the parser. ///