Introduce ScopedDecl::getLexicalDeclContext() which is different from ScopedDecl::getDeclContext() when there are nested-names.
e.g.:
  namespace A {
    void f(); // SemanticDC (getDeclContext) == LexicalDC (getLexicalDeclContext) == 'namespace A'
  }
  void A::f(); // SemanticDC == namespace 'A'
               // LexicalDC == global namespace


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58948 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index b0fe4d1..fa5e9ce 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -140,6 +140,29 @@
 }
 
 //===----------------------------------------------------------------------===//
+// ScopedDecl Implementation
+//===----------------------------------------------------------------------===//
+
+void ScopedDecl::setLexicalDeclContext(DeclContext *DC) {
+  if (DC == getLexicalDeclContext())
+    return;
+
+  if (isInSemaDC()) {
+    MultipleDC *MDC = new MultipleDC();
+    MDC->SemanticDC = getDeclContext();
+    MDC->LexicalDC = DC;
+    DeclCtx = reinterpret_cast<uintptr_t>(MDC) | 0x1;
+  } else {
+    getMultipleDC()->LexicalDC = DC;
+  }
+}
+
+ScopedDecl::~ScopedDecl() {
+  if (isOutOfSemaDC())
+    delete getMultipleDC();
+}
+
+//===----------------------------------------------------------------------===//
 // FunctionDecl Implementation
 //===----------------------------------------------------------------------===//
 
diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp
index 34066a5..04cb719 100644
--- a/lib/AST/DeclSerialization.cpp
+++ b/lib/AST/DeclSerialization.cpp
@@ -145,15 +145,31 @@
   NamedDecl::EmitInRec(S);
   S.EmitPtr(getNext());                     // From ScopedDecl.  
   S.EmitPtr(cast_or_null<Decl>(getDeclContext()));  // From ScopedDecl.
+  S.EmitPtr(cast_or_null<Decl>(getLexicalDeclContext()));  // From ScopedDecl.
 }
 
 void ScopedDecl::ReadInRec(Deserializer& D, ASTContext& C) {
   NamedDecl::ReadInRec(D, C);
   D.ReadPtr(Next);                                  // From ScopedDecl.
-  
-  assert(DeclCtx == 0);   // Allow back-patching.  Observe that we register
-  D.ReadPtr(DeclCtx);     // the variable of the *object* for back-patching.
-                          // Its actual value will get filled in later.
+
+  assert(DeclCtx == 0);
+
+  const SerializedPtrID &SemaDCPtrID = D.ReadPtrID();
+  const SerializedPtrID &LexicalDCPtrID = D.ReadPtrID();
+
+  if (SemaDCPtrID == LexicalDCPtrID) {
+    // Allow back-patching.  Observe that we register the variable of the
+    // *object* for back-patching. Its actual value will get filled in later.
+    D.ReadUIntPtr(DeclCtx, SemaDCPtrID); 
+  }
+  else {
+    MultipleDC *MDC = new MultipleDC();
+    DeclCtx = reinterpret_cast<uintptr_t>(MDC) | 0x1;
+    // Allow back-patching.  Observe that we register the variable of the
+    // *object* for back-patching. Its actual value will get filled in later.
+    D.ReadUIntPtr(reinterpret_cast<uintptr_t&>(MDC->SemanticDC), SemaDCPtrID);
+    D.ReadUIntPtr(reinterpret_cast<uintptr_t&>(MDC->LexicalDC), LexicalDCPtrID);
+  }
 }
     
   //===------------------------------------------------------------===//
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 178ab13..d7518e0 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -109,10 +109,6 @@
   /// CurContext - This is the current declaration context of parsing.
   DeclContext *CurContext;
 
-  /// LexicalFileContext - The current lexical file declaration context,
-  /// the translation unit or a namespace.
-  DeclContext *LexicalFileContext;
-
   /// PreDeclaratorDC - Keeps the declaration context before switching to the
   /// context of a declarator's nested-name-specifier.
   DeclContext *PreDeclaratorDC;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index cae05a3..6c71d50 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -53,8 +53,8 @@
 DeclContext *Sema::getContainingDC(DeclContext *DC) {
   if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) {
     // A C++ out-of-line method will return to the file declaration context.
-    if (!MD->isInlineDefinition())
-      return LexicalFileContext;
+    if (MD->isOutOfLineDefinition())
+      return MD->getLexicalDeclContext();
 
     // A C++ inline method is parsed *after* the topmost class it was declared in
     // is fully parsed (it's "complete").
@@ -70,25 +70,24 @@
     return DC;
   }
 
-  if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC))
-    return LexicalFileContext;
+  if (isa<ObjCMethodDecl>(DC))
+    return Context.getTranslationUnitDecl();
+
+  if (ScopedDecl *SD = dyn_cast<ScopedDecl>(DC))
+    return SD->getLexicalDeclContext();
 
   return DC->getParent();
 }
 
 void Sema::PushDeclContext(DeclContext *DC) {
   assert(getContainingDC(DC) == CurContext &&
-       "The next DeclContext should be directly contained in the current one.");
+       "The next DeclContext should be lexically contained in the current one.");
   CurContext = DC;
-  if (CurContext->isFileContext())
-    LexicalFileContext = CurContext;
 }
 
 void Sema::PopDeclContext() {
   assert(CurContext && "DeclContext imbalance!");
   CurContext = getContainingDC(CurContext);
-  if (CurContext->isFileContext())
-    LexicalFileContext = CurContext;
 }
 
 /// Add this decl to the scope shadowed decl chains.
@@ -1147,6 +1146,10 @@
     New = NewVD;
   }
   
+  // Set the lexical context. If the declarator has a C++ scope specifier, the
+  // lexical context will be different from the semantic context.
+  New->setLexicalDeclContext(CurContext);
+
   // If this has an identifier, add it to the scope stack.
   if (II)
     PushOnScopeChains(New, S);
@@ -2004,10 +2007,6 @@
     Diag(Definition->getLocation(), diag::err_previous_definition);
   }
 
-  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
-    if (isa<CXXRecordDecl>(CurContext))
-      MD->setInlineDefinition(true);
-
   PushDeclContext(FD);
     
   // Check the validity of our function parameters
@@ -2267,6 +2266,11 @@
   
   if (Attr)
     ProcessDeclAttributeList(New, Attr);
+
+  // Set the lexical context. If the tag has a C++ scope specifier, the
+  // lexical context will be different from the semantic context.
+  New->setLexicalDeclContext(CurContext);
+
   return New;
 }
 
@@ -2421,6 +2425,10 @@
   if (Attr)
     ProcessDeclAttributeList(New, Attr);
 
+  // Set the lexical context. If the tag has a C++ scope specifier, the
+  // lexical context will be different from the semantic context.
+  New->setLexicalDeclContext(CurContext);
+
   return New;
 }