[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