From ef177820100ab583b08fd3056e2a5a52ee4b1629 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Thu, 17 Apr 2008 14:40:12 +0000 Subject: [PATCH] Addition of TranslationUnitDecl to the AST: -Added TranslationUnitDecl class to serve as top declaration context -ASTContext gets a TUDecl member and a getTranslationUnitDecl() function -All ScopedDecls get the TUDecl as DeclContext when declared at global scope git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49855 91177308-0d34-0410-b5e6-96231b3b80d8 --- Driver/RewriteObjC.cpp | 35 ++++++++++++++++++---------------- include/clang/AST/ASTContext.h | 7 ++++++- include/clang/AST/Decl.h | 27 ++++++++++++++++++++++++-- include/clang/AST/DeclBase.h | 7 +++++++ lib/AST/ASTContext.cpp | 6 +++++- lib/AST/Decl.cpp | 8 +++++++- lib/AST/DeclSerialization.cpp | 23 ++++++++++++++++++++++ lib/Sema/Sema.cpp | 11 +++++++---- lib/Sema/SemaDecl.cpp | 8 ++++++-- 9 files changed, 105 insertions(+), 27 deletions(-) diff --git a/Driver/RewriteObjC.cpp b/Driver/RewriteObjC.cpp index 724b16e49a..ebab81fb73 100644 --- a/Driver/RewriteObjC.cpp +++ b/Driver/RewriteObjC.cpp @@ -42,6 +42,7 @@ namespace { ASTContext *Context; SourceManager *SM; + TranslationUnitDecl *TUDecl; unsigned MainFileID; const char *MainFileStart, *MainFileEnd; SourceLocation LastIncLoc; @@ -255,6 +256,7 @@ ASTConsumer *clang::CreateCodeRewriterTest(const std::string& InFile, void RewriteObjC::Initialize(ASTContext &context) { Context = &context; SM = &Context->getSourceManager(); + TUDecl = Context->getTranslationUnitDecl(); MsgSendFunctionDecl = 0; MsgSendSuperFunctionDecl = 0; MsgSendStretFunctionDecl = 0; @@ -820,7 +822,7 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { std::string RecName = clsDeclared->getIdentifier()->getName(); RecName += "_IMPL"; IdentifierInfo *II = &Context->Idents.get(RecName.c_str()); - RecordDecl *RD = RecordDecl::Create(*Context, Decl::Struct, NULL, + RecordDecl *RD = RecordDecl::Create(*Context, Decl::Struct, TUDecl, SourceLocation(), II, 0); assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); @@ -1577,7 +1579,7 @@ void RewriteObjC::SynthSelGetUidFunctionDecl() { QualType getFuncType = Context->getFunctionType(Context->getObjCSelType(), &ArgTys[0], ArgTys.size(), false /*isVariadic*/); - SelGetUidFunctionDecl = FunctionDecl::Create(*Context, NULL, + SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SelGetUidIdent, getFuncType, FunctionDecl::Extern, false, 0); @@ -1592,7 +1594,7 @@ void RewriteObjC::SynthGetProtocolFunctionDecl() { QualType getFuncType = Context->getFunctionType(Context->getObjCProtoType(), &ArgTys[0], ArgTys.size(), false /*isVariadic*/); - GetProtocolFunctionDecl = FunctionDecl::Create(*Context, NULL, + GetProtocolFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SelGetProtoIdent, getFuncType, FunctionDecl::Extern, false, 0); @@ -1620,7 +1622,7 @@ void RewriteObjC::SynthSuperContructorFunctionDecl() { QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(), &ArgTys[0], ArgTys.size(), false); - SuperContructorFunctionDecl = FunctionDecl::Create(*Context, NULL, + SuperContructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), msgSendIdent, msgSendType, FunctionDecl::Extern, false, 0); @@ -1639,7 +1641,7 @@ void RewriteObjC::SynthMsgSendFunctionDecl() { QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(), &ArgTys[0], ArgTys.size(), true /*isVariadic*/); - MsgSendFunctionDecl = FunctionDecl::Create(*Context, NULL, + MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), msgSendIdent, msgSendType, FunctionDecl::Extern, false, 0); @@ -1649,7 +1651,7 @@ void RewriteObjC::SynthMsgSendFunctionDecl() { void RewriteObjC::SynthMsgSendSuperFunctionDecl() { IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper"); llvm::SmallVector ArgTys; - RecordDecl *RD = RecordDecl::Create(*Context, Decl::Struct, NULL, + RecordDecl *RD = RecordDecl::Create(*Context, Decl::Struct, TUDecl, SourceLocation(), &Context->Idents.get("objc_super"), 0); QualType argT = Context->getPointerType(Context->getTagDeclType(RD)); @@ -1661,7 +1663,7 @@ void RewriteObjC::SynthMsgSendSuperFunctionDecl() { QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(), &ArgTys[0], ArgTys.size(), true /*isVariadic*/); - MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, NULL, + MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), msgSendIdent, msgSendType, FunctionDecl::Extern, false, 0); @@ -1680,7 +1682,7 @@ void RewriteObjC::SynthMsgSendStretFunctionDecl() { QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(), &ArgTys[0], ArgTys.size(), true /*isVariadic*/); - MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, NULL, + MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), msgSendIdent, msgSendType, FunctionDecl::Extern, false, 0); @@ -1692,7 +1694,7 @@ void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() { IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper_stret"); llvm::SmallVector ArgTys; - RecordDecl *RD = RecordDecl::Create(*Context, Decl::Struct, NULL, + RecordDecl *RD = RecordDecl::Create(*Context, Decl::Struct, TUDecl, SourceLocation(), &Context->Idents.get("objc_super"), 0); QualType argT = Context->getPointerType(Context->getTagDeclType(RD)); @@ -1704,7 +1706,7 @@ void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() { QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(), &ArgTys[0], ArgTys.size(), true /*isVariadic*/); - MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, NULL, + MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), msgSendIdent, msgSendType, FunctionDecl::Extern, false, 0); @@ -1723,7 +1725,7 @@ void RewriteObjC::SynthMsgSendFpretFunctionDecl() { QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(), &ArgTys[0], ArgTys.size(), true /*isVariadic*/); - MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, NULL, + MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), msgSendIdent, msgSendType, FunctionDecl::Extern, false, 0); @@ -1738,7 +1740,7 @@ void RewriteObjC::SynthGetClassFunctionDecl() { QualType getClassType = Context->getFunctionType(Context->getObjCIdType(), &ArgTys[0], ArgTys.size(), false /*isVariadic*/); - GetClassFunctionDecl = FunctionDecl::Create(*Context, NULL, + GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), getClassIdent, getClassType, FunctionDecl::Extern, false, 0); @@ -1753,7 +1755,7 @@ void RewriteObjC::SynthGetMetaClassFunctionDecl() { QualType getClassType = Context->getFunctionType(Context->getObjCIdType(), &ArgTys[0], ArgTys.size(), false /*isVariadic*/); - GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, NULL, + GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), getClassIdent, getClassType, FunctionDecl::Extern, false, 0); @@ -1776,7 +1778,7 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { // The minus 2 removes the begin/end double quotes. Preamble += utostr(prettyBuf.str().size()-2) + "};\n"; - VarDecl *NewVD = VarDecl::Create(*Context, NULL, SourceLocation(), + VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), &Context->Idents.get(S.c_str()), strType, VarDecl::Static, NULL); DeclRefExpr *DRE = new DeclRefExpr(NewVD, strType, SourceLocation()); @@ -1824,7 +1826,7 @@ ObjCInterfaceDecl *RewriteObjC::isSuperReceiver(Expr *recExpr) { // struct objc_super { struct objc_object *receiver; struct objc_class *super; }; QualType RewriteObjC::getSuperStructType() { if (!SuperStructDecl) { - SuperStructDecl = RecordDecl::Create(*Context, Decl::Struct, NULL, + SuperStructDecl = RecordDecl::Create(*Context, Decl::Struct, TUDecl, SourceLocation(), &Context->Idents.get("objc_super"), 0); QualType FieldTypes[2]; @@ -1847,7 +1849,7 @@ QualType RewriteObjC::getSuperStructType() { QualType RewriteObjC::getConstantStringStructType() { if (!ConstantStringDecl) { - ConstantStringDecl = RecordDecl::Create(*Context, Decl::Struct, NULL, + ConstantStringDecl = RecordDecl::Create(*Context, Decl::Struct, TUDecl, SourceLocation(), &Context->Idents.get("__NSConstantStringImpl"), 0); QualType FieldTypes[4]; @@ -2988,3 +2990,4 @@ void RewriteObjC::RewriteImplementations(std::string &Result) { } } + diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index b29c23e3f7..1d9e0af730 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -75,6 +75,8 @@ class ASTContext { QualType ObjCConstantStringType; RecordDecl *CFConstantStringTypeDecl; + TranslationUnitDecl *TUDecl; + SourceManager &SourceMgr; llvm::MallocAllocator Allocator; public: @@ -88,7 +90,9 @@ public: FullSourceLoc getFullLoc(SourceLocation Loc) const { return FullSourceLoc(Loc,SourceMgr); } - + + TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; } + /// This is intentionally not serialized. It is populated by the /// ASTContext ctor, and there are no external pointers/references to /// internal variables of BuiltinInfo. @@ -113,6 +117,7 @@ public: if (size_reserve > 0) Types.reserve(size_reserve); InitBuiltinTypes(); BuiltinInfo.InitializeBuiltins(idents, Target); + TUDecl = TranslationUnitDecl::Create(*this); } ~ASTContext(); diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 890eb88d65..0a037998a3 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -22,6 +22,30 @@ class Stmt; class StringLiteral; class IdentifierInfo; +/// TranslationUnitDecl - The top declaration context. +/// FIXME: The TranslationUnit class should probably be modified to serve as +/// the top decl context. It would have ownership of the top decls so that the +/// AST is self-contained and easily de/serializable. +class TranslationUnitDecl : public Decl, public DeclContext { + TranslationUnitDecl() + : Decl(TranslationUnit, SourceLocation()), + DeclContext(TranslationUnit) {} +public: + static TranslationUnitDecl *Create(ASTContext &C); + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return D->getKind() == TranslationUnit; } + static bool classof(const TranslationUnitDecl *D) { return true; } + +protected: + /// EmitImpl - Serialize this TranslationUnitDecl. Called by Decl::Emit. + virtual void EmitImpl(llvm::Serializer& S) const; + + /// CreateImpl - Deserialize a TranslationUnitDecl. Called by Decl::Create. + static TranslationUnitDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C); + + friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C); +}; + /// NamedDecl - This represents a decl with an identifier for a name. Many /// decls have names, but not ObjCMethodDecl, @class, etc. class NamedDecl : public Decl { @@ -190,8 +214,7 @@ public: bool isFileVarDecl() const { if (getKind() != Decl::Var) return false; - // FIXME: change when TranlationUnitDecl is added as a declaration context. - if (!getDeclContext()) + if (isa(getDeclContext())) return true; return false; } diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 257ed25b9c..84e822e921 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -19,6 +19,7 @@ #include "clang/Basic/SourceLocation.h" namespace clang { +class TranslationUnitDecl; class FunctionDecl; class ObjCMethodDecl; class EnumDecl; @@ -35,6 +36,7 @@ public: // enums below. The commented out names are abstract class names. // Decl + TranslationUnit, // NamedDecl Field, ObjCIvar, @@ -195,6 +197,7 @@ protected: /// DeclContext - This is used only as base class of specific decl types that /// can act as declaration contexts. These decls are: /// +/// TranslationUnitDecl /// FunctionDecl /// ObjCMethodDecl /// EnumDecl @@ -216,6 +219,8 @@ class DeclContext { static To *CastTo(const From *D) { Decl::Kind DK = KindTrait::getKind(D); switch(DK) { + case Decl::TranslationUnit: + return static_cast(const_cast(D)); case Decl::Function: return static_cast(const_cast(D)); case Decl::ObjCMethod: @@ -256,6 +261,7 @@ public: static bool classof(const Decl *D) { switch (D->getKind()) { + case Decl::TranslationUnit: case Decl::Function: case Decl::ObjCMethod: case Decl::ObjCInterface: @@ -266,6 +272,7 @@ public: } } static bool classof(const DeclContext *D) { return true; } + static bool classof(const TranslationUnitDecl *D) { return true; } static bool classof(const FunctionDecl *D) { return true; } static bool classof(const ObjCMethodDecl *D) { return true; } static bool classof(const EnumDecl *D) { return true; } diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index e4b48e21e4..7220ce4f9f 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1175,7 +1175,7 @@ int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) { QualType ASTContext::getCFConstantStringType() { if (!CFConstantStringTypeDecl) { CFConstantStringTypeDecl = - RecordDecl::Create(*this, Decl::Struct, NULL, SourceLocation(), + RecordDecl::Create(*this, Decl::Struct, TUDecl, SourceLocation(), &Idents.get("NSConstantString"), 0); QualType FieldTypes[4]; @@ -1727,6 +1727,8 @@ void ASTContext::Emit(llvm::Serializer& S) const { I!=E;++I) (*I)->Emit(S); + S.EmitOwnedPtr(TUDecl); + // FIXME: S.EmitOwnedPtr(CFConstantStringTypeDecl); } @@ -1743,6 +1745,8 @@ ASTContext* ASTContext::Create(llvm::Deserializer& D) { for (unsigned i = 0; i < size_reserve; ++i) Type::Create(*A,i,D); + A->TUDecl = cast(D.ReadOwnedPtr(*A)); + // FIXME: A->CFConstantStringTypeDecl = D.ReadOwnedPtr(); return A; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 900096f1ec..6ebaac569f 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -198,6 +198,7 @@ void Decl::addDeclKind(Kind k) { case ObjCPropertyImpl: nObjCPropertyImplDecl++; break; case LinkageSpec: nLinkageSpecDecl++; break; case FileScopeAsm: nFileScopeAsmDecl++; break; + case TranslationUnit: break; } } @@ -205,6 +206,11 @@ void Decl::addDeclKind(Kind k) { // Decl Allocation/Deallocation Method Implementations //===----------------------------------------------------------------------===// +TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { + void *Mem = C.getAllocator().Allocate(); + return new (Mem) TranslationUnitDecl(); +} + VarDecl *VarDecl::Create(ASTContext &C, DeclContext *CD, SourceLocation L, IdentifierInfo *Id, QualType T, @@ -213,7 +219,6 @@ VarDecl *VarDecl::Create(ASTContext &C, DeclContext *CD, return new (Mem) VarDecl(Var, CD, L, Id, T, S, PrevDecl); } - ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *CD, SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S, @@ -329,6 +334,7 @@ const Attr *Decl::getAttrs() const { void Decl::Destroy(ASTContext& C) const { switch (getKind()) { + CASE(TranslationUnit); CASE(Field); CASE(ObjCIvar); CASE(ObjCCategory); diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp index 96df1b7fbf..e7442ff51c 100644 --- a/lib/AST/DeclSerialization.cpp +++ b/lib/AST/DeclSerialization.cpp @@ -41,6 +41,9 @@ Decl* Decl::Create(Deserializer& D, ASTContext& C) { assert (false && "Not implemented."); break; + case TranslationUnit: + return TranslationUnitDecl::CreateImpl(D, C); + case Var: return VarDecl::CreateImpl(D, C); @@ -191,6 +194,26 @@ void VarDecl::ReadImpl(Deserializer& D, ASTContext& C) { ReadOutRec(D, C); } +//===----------------------------------------------------------------------===// +// TranslationUnitDecl Serialization. +//===----------------------------------------------------------------------===// + +void TranslationUnitDecl::EmitImpl(llvm::Serializer& S) const +{ + Decl::EmitInRec(S); +} + +TranslationUnitDecl* TranslationUnitDecl::CreateImpl(Deserializer& D, + ASTContext& C) { + void *Mem = C.getAllocator().Allocate(); + TranslationUnitDecl* decl = + new (Mem) TranslationUnitDecl(); + + decl->Decl::ReadInRec(D, C); + + return decl; +} + //===----------------------------------------------------------------------===// // VarDecl Serialization. //===----------------------------------------------------------------------===// diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index c6a862b2b1..bb5316a126 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -42,6 +42,7 @@ bool Sema::isObjCObjectPointerType(QualType type) const { void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { TUScope = S; + CurContext = Context.getTranslationUnitDecl(); if (!PP.getLangOptions().ObjC1) return; TypedefType *t; @@ -93,14 +94,16 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer) // FIXME: Move this initialization up to Sema::ActOnTranslationUnitScope() // and make sure the decls get inserted into TUScope! if (PP.getLangOptions().ObjC1) { + TranslationUnitDecl *TUDecl = Context.getTranslationUnitDecl(); + // Synthesize "typedef struct objc_class *Class;" RecordDecl *ClassTag = RecordDecl::Create(Context, Decl::Struct, - NULL, + TUDecl, SourceLocation(), &IT.get("objc_class"), 0); QualType ClassT = Context.getPointerType(Context.getTagDeclType(ClassTag)); TypedefDecl *ClassTypedef = - TypedefDecl::Create(Context, NULL, SourceLocation(), + TypedefDecl::Create(Context, TUDecl, SourceLocation(), &Context.Idents.get("Class"), ClassT, 0); Context.setObjCClassType(ClassTypedef); @@ -113,14 +116,14 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer) // Synthesize "typedef struct objc_object { Class isa; } *id;" RecordDecl *ObjectTag = - RecordDecl::Create(Context, Decl::Struct, NULL, + RecordDecl::Create(Context, Decl::Struct, TUDecl, SourceLocation(), &IT.get("objc_object"), 0); FieldDecl *IsaDecl = FieldDecl::Create(Context, SourceLocation(), 0, Context.getObjCClassType()); ObjectTag->defineBody(&IsaDecl, 1); QualType ObjT = Context.getPointerType(Context.getTagDeclType(ObjectTag)); - TypedefDecl *IdTypedef = TypedefDecl::Create(Context, NULL, + TypedefDecl *IdTypedef = TypedefDecl::Create(Context, TUDecl, SourceLocation(), &Context.Idents.get("id"), ObjT, 0); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 6d41fce555..f0e469791a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -43,14 +43,18 @@ Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) { } void Sema::PushDeclContext(DeclContext *CD) { - assert(CD->getParent() == CurContext && + assert( ( (CD->isFunctionOrMethod() && isa(CurContext)) + || CD->getParent() == CurContext ) && "The next DeclContext should be directly contained in the current one."); CurContext = CD; } void Sema::PopDeclContext() { assert(CurContext && "DeclContext imbalance!"); - CurContext = CurContext->getParent(); + // If CurContext is a ObjC method, getParent() will return NULL. + CurContext = CurContext->isFunctionOrMethod() + ? Context.getTranslationUnitDecl() + : CurContext->getParent(); } /// Add this decl to the scope shadowed decl chains. -- 2.40.0