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;
}