[cfe-commits] r147778 - in /cfe/trunk: include/clang/AST/DeclBase.h lib/AST/DeclBase.cpp lib/Serialization/ASTReader.cpp lib/Serialization/ASTReaderDecl.cpp test/Modules/Inputs/namespaces-left.h test/Modules/Inputs/namespaces-right.h test/Modules/namespaces.cpp

Douglas Gregor dgregor at apple.com
Mon Jan 9 09:30:44 PST 2012


Author: dgregor
Date: Mon Jan  9 11:30:44 2012
New Revision: 147778

URL: http://llvm.org/viewvc/llvm-project?rev=147778&view=rev
Log:
Implement redeclaration merging for namespaces defined in distinct
modules. Teach name lookup into namespaces to search in each of the
merged DeclContexts as well as the (now-primary) DeclContext. This
supports the common case where two different modules put something
into the same namespace.


Modified:
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/test/Modules/Inputs/namespaces-left.h
    cfe/trunk/test/Modules/Inputs/namespaces-right.h
    cfe/trunk/test/Modules/namespaces.cpp

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=147778&r1=147777&r2=147778&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Mon Jan  9 11:30:44 2012
@@ -514,6 +514,12 @@
     NextInContextAndBits.setInt(Bits);
   }
 
+  /// \brief Set the owning module ID.
+  void setOwningModuleID(unsigned ID) {
+    assert(isFromASTFile() && "Only works on a deserialized declaration");
+    *((unsigned*)this - 2) = ID;
+  }
+  
 public:
   
   /// \brief Determine the availability of the given declaration.
@@ -573,7 +579,16 @@
       return *((const unsigned*)this - 1);
     return 0;
   }
-              
+  
+  /// \brief Retrieve the global ID of the module that owns this particular
+  /// declaration.
+  unsigned getOwningModuleID() const {
+    if (isFromASTFile())
+      return *((const unsigned*)this - 2);
+    
+    return 0;
+  }
+  
   unsigned getIdentifierNamespace() const {
     return IdentifierNamespace;
   }

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=147778&r1=147777&r2=147778&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Mon Jan  9 11:30:44 2012
@@ -45,14 +45,17 @@
                                      unsigned ID,
                                      unsigned Size) {
   // Allocate an extra 8 bytes worth of storage, which ensures that the
-  // resulting pointer will still be 8-byte aligned. At present, we're only
-  // using the latter 4 bytes of this storage.
+  // resulting pointer will still be 8-byte aligned. 
   void *Start = Context.Allocate(Size + 8);
   void *Result = (char*)Start + 8;
   
-  // Store the global declaration ID 
-  unsigned *IDPtr = (unsigned*)Result - 1;
-  *IDPtr = ID;
+  unsigned *PrefixPtr = (unsigned *)Result - 2;
+  
+  // Zero out the first 4 bytes; this is used to store the owning module ID.
+  PrefixPtr[0] = 0;
+  
+  // Store the global declaration ID in the second 4 bytes.
+  PrefixPtr[1] = ID;
   
   return Result;
 }

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=147778&r1=147777&r2=147778&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Mon Jan  9 11:30:44 2012
@@ -4808,15 +4808,17 @@
   /// declaration context.
   class DeclContextNameLookupVisitor {
     ASTReader &Reader;
+    llvm::SmallVectorImpl<const DeclContext *> &Contexts;
     const DeclContext *DC;
     DeclarationName Name;
     SmallVectorImpl<NamedDecl *> &Decls;
 
   public:
     DeclContextNameLookupVisitor(ASTReader &Reader, 
-                                 const DeclContext *DC, DeclarationName Name,
+                                 SmallVectorImpl<const DeclContext *> &Contexts, 
+                                 DeclarationName Name,
                                  SmallVectorImpl<NamedDecl *> &Decls)
-      : Reader(Reader), DC(DC), Name(Name), Decls(Decls) { }
+      : Reader(Reader), Contexts(Contexts), Name(Name), Decls(Decls) { }
 
     static bool visit(ModuleFile &M, void *UserData) {
       DeclContextNameLookupVisitor *This
@@ -4824,11 +4826,20 @@
 
       // Check whether we have any visible declaration information for
       // this context in this module.
-      ModuleFile::DeclContextInfosMap::iterator Info
-        = M.DeclContextInfos.find(This->DC);
-      if (Info == M.DeclContextInfos.end() || !Info->second.NameLookupTableData)
-        return false;
+      ModuleFile::DeclContextInfosMap::iterator Info;
+      bool FoundInfo = false;
+      for (unsigned I = 0, N = This->Contexts.size(); I != N; ++I) {
+        Info = M.DeclContextInfos.find(This->Contexts[I]);
+        if (Info != M.DeclContextInfos.end() && 
+            Info->second.NameLookupTableData) {
+          FoundInfo = true;
+          break;
+        }
+      }
 
+      if (!FoundInfo)
+        return false;
+      
       // Look for this name within this module.
       ASTDeclContextNameLookupTable *LookupTable =
         (ASTDeclContextNameLookupTable*)Info->second.NameLookupTableData;
@@ -4870,7 +4881,24 @@
                                       DeclContext::lookup_iterator(0));
 
   SmallVector<NamedDecl *, 64> Decls;
-  DeclContextNameLookupVisitor Visitor(*this, DC, Name, Decls);
+  
+  // Compute the declaration contexts we need to look into. Multiple such
+  // declaration contexts occur when two declaration contexts from disjoint
+  // modules get merged, e.g., when two namespaces with the same name are 
+  // independently defined in separate modules.
+  SmallVector<const DeclContext *, 2> Contexts;
+  Contexts.push_back(DC);
+  
+  if (DC->isNamespace()) {
+    MergedDeclsMap::iterator Merged
+      = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
+    if (Merged != MergedDecls.end()) {
+      for (unsigned I = 0, N = Merged->second.size(); I != N; ++I)
+        Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));
+    }
+  }
+  
+  DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls);
   ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor);
   ++NumVisibleDeclContextsRead;
   SetExternalVisibleDeclsForName(DC, Name, Decls);

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=147778&r1=147777&r2=147778&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Mon Jan  9 11:30:44 2012
@@ -369,6 +369,9 @@
   // Determine whether this declaration is part of a (sub)module. If so, it
   // may not yet be visible.
   if (unsigned SubmoduleID = readSubmoduleID(Record, Idx)) {
+    // Store the owning submodule ID in the declaration.
+    D->setOwningModuleID(SubmoduleID);
+    
     // Module-private declarations are never visible, so there is no work to do.
     if (!D->isModulePrivate()) {
       if (Module *Owner = Reader.getSubmodule(SubmoduleID)) {
@@ -972,7 +975,8 @@
   D->setInline(Record[Idx++]);
   D->LocStart = ReadSourceLocation(Record, Idx);
   D->RBraceLoc = ReadSourceLocation(Record, Idx);
-  
+  mergeRedeclarable(D, Redecl);
+
   if (Redecl.getFirstID() == ThisDeclID) {
     // FIXME: If there's already an anonymous namespace, do we merge it with
     // this one? Or do we, when loading modules, just forget about anonymous
@@ -1232,7 +1236,7 @@
   RedeclKind Kind = (RedeclKind)Record[Idx++];
   
   // Determine the first declaration ID.
-  DeclID FirstDeclID;
+  DeclID FirstDeclID = 0;
   switch (Kind) {
   case FirstDeclaration: {
     FirstDeclID = ThisDeclID;
@@ -1489,7 +1493,7 @@
   enum RedeclKind { FirstDeclaration = 0, FirstInFile, PointsToPrevious };
   RedeclKind Kind = (RedeclKind)Record[Idx++];
   
-  DeclID FirstDeclID;
+  DeclID FirstDeclID = 0;
   switch (Kind) {
   case FirstDeclaration:
     FirstDeclID = ThisDeclID;
@@ -1545,6 +1549,13 @@
         D->RedeclLink 
           = typename Redeclarable<T>::PreviousDeclLink(ExistingCanon);
         
+        // When we merge a namespace, update its pointer to the first namespace.
+        if (NamespaceDecl *Namespace
+              = dyn_cast<NamespaceDecl>(static_cast<T*>(D))) {
+          Namespace->AnonOrFirstNamespaceAndInline.setPointer(
+            static_cast<NamespaceDecl *>(static_cast<void*>(ExistingCanon)));
+        }
+        
         // Don't introduce DCanon into the set of pending declaration chains.
         Redecl.suppress();
         
@@ -1719,6 +1730,12 @@
       VarX->getASTContext().hasSameType(VarX->getType(), VarY->getType());
   }
   
+  // Namespaces with the same name and inlinedness match.
+  if (NamespaceDecl *NamespaceX = dyn_cast<NamespaceDecl>(X)) {
+    NamespaceDecl *NamespaceY = cast<NamespaceDecl>(Y);
+    return NamespaceX->isInline() == NamespaceY->isInline();
+  }
+      
   // FIXME: Many other cases to implement.
   return false;
 }

Modified: cfe/trunk/test/Modules/Inputs/namespaces-left.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/namespaces-left.h?rev=147778&r1=147777&r2=147778&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/namespaces-left.h (original)
+++ cfe/trunk/test/Modules/Inputs/namespaces-left.h Mon Jan  9 11:30:44 2012
@@ -9,3 +9,19 @@
 namespace N2 { 
   float& f(float);
 }
+
+
+
+
+
+namespace N5 {
+  int &f(int);
+}
+
+namespace N6 {
+  int &f(int);
+}
+
+namespace N7 {
+  int &f(int);
+}

Modified: cfe/trunk/test/Modules/Inputs/namespaces-right.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/namespaces-right.h?rev=147778&r1=147777&r2=147778&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/namespaces-right.h (original)
+++ cfe/trunk/test/Modules/Inputs/namespaces-right.h Mon Jan  9 11:30:44 2012
@@ -16,3 +16,14 @@
   double& f(double);
 }
 
+namespace N5 {
+  double &f(double);
+}
+
+namespace N6 {
+  double &f(double);
+}
+
+namespace N7 {
+  double &f(double);
+}

Modified: cfe/trunk/test/Modules/namespaces.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/namespaces.cpp?rev=147778&r1=147777&r2=147778&view=diff
==============================================================================
--- cfe/trunk/test/Modules/namespaces.cpp (original)
+++ cfe/trunk/test/Modules/namespaces.cpp Mon Jan  9 11:30:44 2012
@@ -1,6 +1,10 @@
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -x objective-c++ -fmodules -fmodule-cache-path %t -I %S/Inputs %s -verify
 
+namespace N6 {
+  char &f(char);
+}
+
 @import namespaces_left;
 @import namespaces_right;
 
@@ -13,3 +17,20 @@
   double &dr1 = N2::f(1.0);
   double &dr2 = N3::f(1.0);
 }
+
+// Test namespaces merged without a common first declaration.
+namespace N5 {
+  char &f(char);
+}
+
+void testMerged() {
+  int &ir1 = N5::f(17);
+  int &ir2 = N6::f(17);
+  int &ir3 = N7::f(17);
+  double &fr1 = N5::f(1.0);
+  double &fr2 = N6::f(1.0);
+  double &fr3 = N7::f(1.0);
+  char &cr1 = N5::f('a');
+  char &cr2 = N6::f('b');
+}
+





More information about the cfe-commits mailing list