From c11438cee123fe5c375eda6b64224c69c38a2305 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 18 Aug 2006 05:17:52 +0000 Subject: [PATCH] Implement first cut of ASTBuilder class. llvm-svn: 38938 --- clang/AST/ASTStreamer.cpp | 9 ++-- clang/AST/Sema.cpp | 73 +++++++++++++++++++++++++- clang/Sema/ASTStreamer.cpp | 9 ++-- clang/Sema/Sema.cpp | 73 +++++++++++++++++++++++++- clang/clang.xcodeproj/project.pbxproj | 4 ++ clang/include/clang/AST/ASTStreamer.h | 2 +- clang/include/clang/AST/Decl.h | 17 +++++- clang/include/clang/Parse/Parser.h | 1 + clang/include/clang/Sema/ASTStreamer.h | 2 +- 9 files changed, 176 insertions(+), 14 deletions(-) diff --git a/clang/AST/ASTStreamer.cpp b/clang/AST/ASTStreamer.cpp index 59798f124a35..e1d952fd024a 100644 --- a/clang/AST/ASTStreamer.cpp +++ b/clang/AST/ASTStreamer.cpp @@ -14,20 +14,20 @@ #include "clang/AST/ASTStreamer.h" #include "clang/Parse/Action.h" #include "clang/Parse/Parser.h" - using namespace llvm; using namespace clang; - +/// Interface to the Builder.cpp file. +/// +Action *CreateASTBuilderActions(); namespace { class ASTStreamer { - EmptyAction Builder; Parser P; public: ASTStreamer(Preprocessor &PP, unsigned MainFileID) - : P(PP, Builder) { + : P(PP, *CreateASTBuilderActions()) { PP.EnterSourceFile(MainFileID, 0, true); // Initialize the parser. @@ -45,6 +45,7 @@ namespace { ~ASTStreamer() { P.Finalize(); + delete &P.getActions(); } }; } diff --git a/clang/AST/Sema.cpp b/clang/AST/Sema.cpp index 8f048a7da16b..e801c3617304 100644 --- a/clang/AST/Sema.cpp +++ b/clang/AST/Sema.cpp @@ -12,4 +12,75 @@ // //===----------------------------------------------------------------------===// -int xx; \ No newline at end of file +#include "clang/Parse/Action.h" +#include "clang/Parse/Scope.h" +#include "clang/AST/Decl.h" +#include "clang/Lex/IdentifierTable.h" +#include "llvm/Support/Visibility.h" +using namespace llvm; +using namespace clang; + +/// ASTBuilder +namespace { +class VISIBILITY_HIDDEN ASTBuilder : public Action { +public: + //===--------------------------------------------------------------------===// + // Symbol table tracking callbacks. + // + virtual bool isTypedefName(const IdentifierInfo &II, Scope *S) const; + virtual void ParseDeclarator(SourceLocation Loc, Scope *S, Declarator &D, + ExprTy *Init); + virtual void PopScope(SourceLocation Loc, Scope *S); +}; +} // end anonymous namespace + + +//===----------------------------------------------------------------------===// +// Symbol table tracking callbacks. +//===----------------------------------------------------------------------===// + +bool ASTBuilder::isTypedefName(const IdentifierInfo &II, Scope *S) const { + Decl *D = II.getFETokenInfo(); + return D != 0 && D->getDeclSpecs().StorageClassSpec == DeclSpec::SCS_typedef; +} + +void ASTBuilder::ParseDeclarator(SourceLocation Loc, Scope *S, Declarator &D, + ExprTy *Init) { + IdentifierInfo *II = D.getIdentifier(); + Decl *PrevDecl = II ? II->getFETokenInfo() : 0; + + Decl *New = new Decl(II, D.getDeclSpec(), Loc, PrevDecl); + + // If this has an identifier, add it to the scope stack. + if (II) { + // If PrevDecl includes conflicting name here, emit a diagnostic. + II->setFETokenInfo(New); + S->AddDecl(II); + } +} + +void ASTBuilder::PopScope(SourceLocation Loc, Scope *S) { + for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end(); + I != E; ++I) { + IdentifierInfo &II = *static_cast(*I); + Decl *D = II.getFETokenInfo(); + assert(D && "This decl didn't get pushed??"); + + Decl *Next = D->getNext(); + + // FIXME: Push the decl on the parent function list if in a function. + delete D; + + II.setFETokenInfo(Next); + } +} + + +/// Interface to the Builder.cpp file. +/// +Action *CreateASTBuilderActions() { + return new ASTBuilder(); +} + + + diff --git a/clang/Sema/ASTStreamer.cpp b/clang/Sema/ASTStreamer.cpp index 59798f124a35..e1d952fd024a 100644 --- a/clang/Sema/ASTStreamer.cpp +++ b/clang/Sema/ASTStreamer.cpp @@ -14,20 +14,20 @@ #include "clang/AST/ASTStreamer.h" #include "clang/Parse/Action.h" #include "clang/Parse/Parser.h" - using namespace llvm; using namespace clang; - +/// Interface to the Builder.cpp file. +/// +Action *CreateASTBuilderActions(); namespace { class ASTStreamer { - EmptyAction Builder; Parser P; public: ASTStreamer(Preprocessor &PP, unsigned MainFileID) - : P(PP, Builder) { + : P(PP, *CreateASTBuilderActions()) { PP.EnterSourceFile(MainFileID, 0, true); // Initialize the parser. @@ -45,6 +45,7 @@ namespace { ~ASTStreamer() { P.Finalize(); + delete &P.getActions(); } }; } diff --git a/clang/Sema/Sema.cpp b/clang/Sema/Sema.cpp index 8f048a7da16b..e801c3617304 100644 --- a/clang/Sema/Sema.cpp +++ b/clang/Sema/Sema.cpp @@ -12,4 +12,75 @@ // //===----------------------------------------------------------------------===// -int xx; \ No newline at end of file +#include "clang/Parse/Action.h" +#include "clang/Parse/Scope.h" +#include "clang/AST/Decl.h" +#include "clang/Lex/IdentifierTable.h" +#include "llvm/Support/Visibility.h" +using namespace llvm; +using namespace clang; + +/// ASTBuilder +namespace { +class VISIBILITY_HIDDEN ASTBuilder : public Action { +public: + //===--------------------------------------------------------------------===// + // Symbol table tracking callbacks. + // + virtual bool isTypedefName(const IdentifierInfo &II, Scope *S) const; + virtual void ParseDeclarator(SourceLocation Loc, Scope *S, Declarator &D, + ExprTy *Init); + virtual void PopScope(SourceLocation Loc, Scope *S); +}; +} // end anonymous namespace + + +//===----------------------------------------------------------------------===// +// Symbol table tracking callbacks. +//===----------------------------------------------------------------------===// + +bool ASTBuilder::isTypedefName(const IdentifierInfo &II, Scope *S) const { + Decl *D = II.getFETokenInfo(); + return D != 0 && D->getDeclSpecs().StorageClassSpec == DeclSpec::SCS_typedef; +} + +void ASTBuilder::ParseDeclarator(SourceLocation Loc, Scope *S, Declarator &D, + ExprTy *Init) { + IdentifierInfo *II = D.getIdentifier(); + Decl *PrevDecl = II ? II->getFETokenInfo() : 0; + + Decl *New = new Decl(II, D.getDeclSpec(), Loc, PrevDecl); + + // If this has an identifier, add it to the scope stack. + if (II) { + // If PrevDecl includes conflicting name here, emit a diagnostic. + II->setFETokenInfo(New); + S->AddDecl(II); + } +} + +void ASTBuilder::PopScope(SourceLocation Loc, Scope *S) { + for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end(); + I != E; ++I) { + IdentifierInfo &II = *static_cast(*I); + Decl *D = II.getFETokenInfo(); + assert(D && "This decl didn't get pushed??"); + + Decl *Next = D->getNext(); + + // FIXME: Push the decl on the parent function list if in a function. + delete D; + + II.setFETokenInfo(Next); + } +} + + +/// Interface to the Builder.cpp file. +/// +Action *CreateASTBuilderActions() { + return new ASTBuilder(); +} + + + diff --git a/clang/clang.xcodeproj/project.pbxproj b/clang/clang.xcodeproj/project.pbxproj index 51c0170a7647..a7ab865f149e 100644 --- a/clang/clang.xcodeproj/project.pbxproj +++ b/clang/clang.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ DE06D4410A8BB55C0050E87E /* Declaration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE06D4400A8BB55C0050E87E /* Declaration.cpp */; }; DE06E4D70A8FBF7A0050E87E /* Initializer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE06E4D60A8FBF7A0050E87E /* Initializer.cpp */; }; DE06E8140A8FF9330050E87E /* Action.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE06E8130A8FF9330050E87E /* Action.h */; }; + DE0FCA210A95710600248FD5 /* EmptyAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE0FCA200A95710600248FD5 /* EmptyAction.cpp */; }; DE1F22030A7D852A00FBF588 /* Parser.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE1F22020A7D852A00FBF588 /* Parser.h */; }; DE1F24820A7DCD3800FBF588 /* Declarations.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE1F24810A7DCD3800FBF588 /* Declarations.h */; }; DEAEE98B0A5A2B970045101B /* MultipleIncludeOpt.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEAEE98A0A5A2B970045101B /* MultipleIncludeOpt.h */; }; @@ -114,6 +115,7 @@ DE06D4400A8BB55C0050E87E /* Declaration.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Declaration.cpp; path = Parse/Declaration.cpp; sourceTree = ""; }; DE06E4D60A8FBF7A0050E87E /* Initializer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Initializer.cpp; path = Parse/Initializer.cpp; sourceTree = ""; }; DE06E8130A8FF9330050E87E /* Action.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Action.h; path = clang/Parse/Action.h; sourceTree = ""; }; + DE0FCA200A95710600248FD5 /* EmptyAction.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = EmptyAction.cpp; path = Parse/EmptyAction.cpp; sourceTree = ""; }; DE1F22020A7D852A00FBF588 /* Parser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Parser.h; path = clang/Parse/Parser.h; sourceTree = ""; }; DE1F24810A7DCD3800FBF588 /* Declarations.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Declarations.h; path = clang/Parse/Declarations.h; sourceTree = ""; }; DEAEE98A0A5A2B970045101B /* MultipleIncludeOpt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MultipleIncludeOpt.h; sourceTree = ""; }; @@ -225,6 +227,7 @@ isa = PBXGroup; children = ( DE06D4400A8BB55C0050E87E /* Declaration.cpp */, + DE0FCA200A95710600248FD5 /* EmptyAction.cpp */, DE06D42E0A8BB52D0050E87E /* DeclarationSemantics.cpp */, DE06CEBF0A8AE7800050E87E /* Expression.cpp */, DE06E4D60A8FBF7A0050E87E /* Initializer.cpp */, @@ -403,6 +406,7 @@ DEC8D9B60A9434FA00353FCA /* Builder.cpp in Sources */, DEC8DA1E0A94388B00353FCA /* PrintParserCallbacks.cpp in Sources */, DEC8DAAD0A94400300353FCA /* ASTStreamer.cpp in Sources */, + DE0FCA210A95710600248FD5 /* EmptyAction.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/clang/include/clang/AST/ASTStreamer.h b/clang/include/clang/AST/ASTStreamer.h index 21e3addf1a90..bd239c83cfca 100644 --- a/clang/include/clang/AST/ASTStreamer.h +++ b/clang/include/clang/AST/ASTStreamer.h @@ -1,4 +1,4 @@ -//===--- AST.h - "Umbrella" header for AST library --------------*- C++ -*-===// +//===--- ASTStreamer.h - Stream ASTs for top-level decls --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 3a07d99a8e61..6c68f33ca268 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_DECL_H #include "clang/Basic/SourceLocation.h" +#include "clang/Parse/Declarations.h" namespace llvm { namespace clang { @@ -28,6 +29,10 @@ class Decl { /// variable, the tag for a struct). IdentifierInfo *Identifier; + /// DeclarationSpecifier - Information about storage class, type specifiers, + /// etc. + DeclSpec DeclarationSpecifier; + /// Type. /// Kind. @@ -35,14 +40,22 @@ class Decl { /// SourceLocation Loc; +#if 0 /// Next - Decls are chained together in a singly-linked list by their owning /// object. Currently we allow decls to be owned by a translation unit or a /// function. This way we can deallocate a function body and all the /// declarations within it. +#endif + // Scope stack info when parsing, otherwise decl list when scope is popped. Decl *Next; public: - Decl(IdentifierInfo *Id, SourceLocation loc, Decl *next) - : Identifier(Id), Loc(loc), Next(next) {} + Decl(IdentifierInfo *Id, const DeclSpec &DS, SourceLocation loc, Decl *next) + : Identifier(Id), DeclarationSpecifier(DS), Loc(loc), Next(next) {} + + + const DeclSpec &getDeclSpecs() const { return DeclarationSpecifier; } + + Decl *getNext() const { return Next; } }; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 8014a1a6b289..f0abf7e2ebf4 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -42,6 +42,7 @@ public: ~Parser(); const LangOptions &getLang() const { return PP.getLangOptions(); } + Action &getActions() const { return Actions; } // Type forwarding. All of these are statically 'void*', but they may all be // different actual classes based on the actions in place. diff --git a/clang/include/clang/Sema/ASTStreamer.h b/clang/include/clang/Sema/ASTStreamer.h index 21e3addf1a90..bd239c83cfca 100644 --- a/clang/include/clang/Sema/ASTStreamer.h +++ b/clang/include/clang/Sema/ASTStreamer.h @@ -1,4 +1,4 @@ -//===--- AST.h - "Umbrella" header for AST library --------------*- C++ -*-===// +//===--- ASTStreamer.h - Stream ASTs for top-level decls --------*- C++ -*-===// // // The LLVM Compiler Infrastructure //