]> granicus.if.org Git - clang/commitdiff
Addition of TranslationUnitDecl to the AST:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 17 Apr 2008 14:40:12 +0000 (14:40 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 17 Apr 2008 14:40:12 +0000 (14:40 +0000)
-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
include/clang/AST/ASTContext.h
include/clang/AST/Decl.h
include/clang/AST/DeclBase.h
lib/AST/ASTContext.cpp
lib/AST/Decl.cpp
lib/AST/DeclSerialization.cpp
lib/Sema/Sema.cpp
lib/Sema/SemaDecl.cpp

index 724b16e49a8f399a77ea4ccdb9effb2b87f2a421..ebab81fb734c7655397d13174660ea7fec15c927 100644 (file)
@@ -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<QualType, 16> 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<QualType, 16> 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) {
   }
 }
 
+
index b29c23e3f76b8539e3722bf6ac368c499265df32..1d9e0af7304788f2fa371c8748bea2a9b7341fbb 100644 (file)
@@ -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();
index 890eb88d6535219aeaff22c08a5f8d70e43048f4..0a037998a31dbf745e3338154385284c03de4333 100644 (file)
@@ -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<TranslationUnitDecl>(getDeclContext()))
       return true;
     return false;
   }
index 257ed25b9c272a2e04eac7dc38f355c0441cdffc..84e822e92107601da4c51b0bf7c20a73997aaaff 100644 (file)
@@ -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<From>::getKind(D);
     switch(DK) {
+      case Decl::TranslationUnit:
+        return static_cast<TranslationUnitDecl*>(const_cast<From*>(D));
       case Decl::Function:
         return static_cast<FunctionDecl*>(const_cast<From*>(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; }
index e4b48e21e44dad4064f0d65d1fdfcbfee6381d64..7220ce4f9f07febb5f0dc86a7685b3774b1004fc 100644 (file)
@@ -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<TranslationUnitDecl>(D.ReadOwnedPtr<Decl>(*A));
+
   // FIXME: A->CFConstantStringTypeDecl = D.ReadOwnedPtr<RecordDecl>();
   
   return A;
index 900096f1eccc18adcff0e0fd98d26c148636efce..6ebaac569ff204eb56712cea857a9b8438ffb46f 100644 (file)
@@ -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<TranslationUnitDecl>();
+  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);
index 96df1b7fbf40b6e87543e309baf115449498759c..e7442ff51cc7b555e51f9eff556c87c4da899200 100644 (file)
@@ -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>();
+  TranslationUnitDecl* decl =
+    new (Mem) TranslationUnitDecl();
+  decl->Decl::ReadInRec(D, C);
+  
+  return decl;
+}
+
 //===----------------------------------------------------------------------===//
 //      VarDecl Serialization.
 //===----------------------------------------------------------------------===//
index c6a862b2b1e2a334b474b08b5080852117230f3b..bb5316a126ac15f7885d407ede4dc0191f45701f 100644 (file)
@@ -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);
index 6d41fce555225c00e8380466851ffd99ab3728fe..f0e469791a7754496f1f3e8be8638aac70bc090d 100644 (file)
@@ -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<TranslationUnitDecl>(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.