[cfe-commits] r58948 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/DeclCXX.h lib/AST/Decl.cpp lib/AST/DeclSerialization.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp test/SemaCXX/nested-name-spec.cpp
Argiris Kirtzidis
akyrtzi at gmail.com
Sun Nov 9 15:41:00 PST 2008
Author: akirtzidis
Date: Sun Nov 9 17:41:00 2008
New Revision: 58948
URL: http://llvm.org/viewvc/llvm-project?rev=58948&view=rev
Log:
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
Modified:
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/AST/DeclSerialization.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/SemaCXX/nested-name-spec.cpp
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=58948&r1=58947&r2=58948&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Sun Nov 9 17:41:00 2008
@@ -92,16 +92,72 @@
///
ScopedDecl *Next;
- DeclContext *DeclCtx;
+ /// DeclCtx - Holds either a DeclContext* or a MultipleDC*.
+ /// For declarations that don't contain C++ scope specifiers, it contains
+ /// the DeclContext where the ScopedDecl was declared.
+ /// For declarations with C++ scope specifiers, it contains a MultipleDC*
+ /// with the context where it semantically belongs (SemanticDC) and the
+ /// context where it was lexically declared (LexicalDC).
+ /// e.g.:
+ ///
+ /// namespace A {
+ /// void f(); // SemanticDC == LexicalDC == 'namespace A'
+ /// }
+ /// void A::f(); // SemanticDC == namespace 'A'
+ /// // LexicalDC == global namespace
+ uintptr_t DeclCtx;
+
+ struct MultipleDC {
+ DeclContext *SemanticDC;
+ DeclContext *LexicalDC;
+ };
+
+ inline bool isInSemaDC() const { return (DeclCtx & 0x1) == 0; }
+ inline bool isOutOfSemaDC() const { return (DeclCtx & 0x1) != 0; }
+ inline MultipleDC *getMultipleDC() const {
+ return reinterpret_cast<MultipleDC*>(DeclCtx & ~0x1);
+ }
protected:
ScopedDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, ScopedDecl *PrevDecl)
- : NamedDecl(DK, L, Id), NextDeclarator(PrevDecl), Next(0), DeclCtx(DC) {}
+ : NamedDecl(DK, L, Id), NextDeclarator(PrevDecl), Next(0),
+ DeclCtx(reinterpret_cast<uintptr_t>(DC)) {}
+
+ virtual ~ScopedDecl();
public:
- const DeclContext *getDeclContext() const { return DeclCtx; }
- DeclContext *getDeclContext() { return DeclCtx; }
+ const DeclContext *getDeclContext() const {
+ if (isInSemaDC())
+ return reinterpret_cast<DeclContext*>(DeclCtx);
+ return getMultipleDC()->SemanticDC;
+ }
+ DeclContext *getDeclContext() {
+ return const_cast<DeclContext*>(
+ const_cast<const ScopedDecl*>(this)->getDeclContext());
+ }
+
+ /// getLexicalDeclContext - The declaration context where this ScopedDecl was
+ /// lexically declared (LexicalDC). May be different from
+ /// getDeclContext() (SemanticDC).
+ /// e.g.:
+ ///
+ /// namespace A {
+ /// void f(); // SemanticDC == LexicalDC == 'namespace A'
+ /// }
+ /// void A::f(); // SemanticDC == namespace 'A'
+ /// // LexicalDC == global namespace
+ const DeclContext *getLexicalDeclContext() const {
+ if (isInSemaDC())
+ return reinterpret_cast<DeclContext*>(DeclCtx);
+ return getMultipleDC()->LexicalDC;
+ }
+ DeclContext *getLexicalDeclContext() {
+ return const_cast<DeclContext*>(
+ const_cast<const ScopedDecl*>(this)->getLexicalDeclContext());
+ }
+
+ void setLexicalDeclContext(DeclContext *DC);
ScopedDecl *getNext() const { return Next; }
void setNext(ScopedDecl *N) { Next = N; }
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=58948&r1=58947&r2=58948&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Sun Nov 9 17:41:00 2008
@@ -391,14 +391,12 @@
/// CXXMethodDecl - Represents a static or instance method of a
/// struct/union/class.
class CXXMethodDecl : public FunctionDecl {
- bool IsInlineDef : 1;
-
protected:
CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L,
IdentifierInfo *Id, QualType T,
bool isStatic, bool isInline, ScopedDecl *PrevDecl)
: FunctionDecl(DK, RD, L, Id, T, (isStatic ? Static : None),
- isInline, PrevDecl), IsInlineDef(false) {}
+ isInline, PrevDecl) {}
public:
static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
@@ -409,9 +407,9 @@
bool isStatic() const { return getStorageClass() == Static; }
bool isInstance() const { return !isStatic(); }
- bool isOutOfLineDefinition() const { return !isInlineDefinition(); }
- bool isInlineDefinition() const { return IsInlineDef; }
- void setInlineDefinition(bool flag) { IsInlineDef = flag; }
+ bool isOutOfLineDefinition() const {
+ return getLexicalDeclContext() != getDeclContext();
+ }
void setAccess(AccessSpecifier AS) { Access = AS; }
AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=58948&r1=58947&r2=58948&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Sun Nov 9 17:41:00 2008
@@ -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
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/lib/AST/DeclSerialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclSerialization.cpp?rev=58948&r1=58947&r2=58948&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclSerialization.cpp (original)
+++ cfe/trunk/lib/AST/DeclSerialization.cpp Sun Nov 9 17:41:00 2008
@@ -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);
+ }
}
//===------------------------------------------------------------===//
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=58948&r1=58947&r2=58948&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sun Nov 9 17:41:00 2008
@@ -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;
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=58948&r1=58947&r2=58948&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Nov 9 17:41:00 2008
@@ -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;
}
Modified: cfe/trunk/test/SemaCXX/nested-name-spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/nested-name-spec.cpp?rev=58948&r1=58947&r2=58948&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/nested-name-spec.cpp (original)
+++ cfe/trunk/test/SemaCXX/nested-name-spec.cpp Sun Nov 9 17:41:00 2008
@@ -42,6 +42,15 @@
struct S : public A::C {};
struct A::undef; // expected-error {{'undef' does not name a tag member in the specified scope}}
+namespace A2 {
+ typedef int INT;
+ struct RC;
+}
+
+struct A2::RC {
+ INT x;
+};
+
void f3() {
N::x = 0; // expected-error {{use of undeclared identifier 'N'}}
int N;
More information about the cfe-commits
mailing list