]> granicus.if.org Git - clang/commitdiff
[modules] When collecting declarations to complete a redeclaration chain for an
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 12 Feb 2015 23:21:45 +0000 (23:21 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 12 Feb 2015 23:21:45 +0000 (23:21 +0000)
entity, put the originally-canonical decl IDs in the right places in the redecl
chain rather than reordering them all to the start. If we don't ensure that the
redecl chain order is consistent with the topological module order, we can fail
to make a declaration visible if later declarations are in more IDNSs than
earlier ones (for instance, because the earlier decls are invisible friends).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@228978 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Serialization/ASTReaderDecl.cpp
test/Modules/Inputs/merge-decl-order/a.h [new file with mode: 0644]
test/Modules/Inputs/merge-decl-order/b.h [new file with mode: 0644]
test/Modules/Inputs/merge-decl-order/module.modulemap [new file with mode: 0644]
test/Modules/cxx-templates.cpp
test/Modules/merge-decl-order.cpp [new file with mode: 0644]

index 5fc99b53122c68bf3fe6076af5e5e17679274ac0..8c16dfde8728ad269843649c6ee2d1a487fd2192 100644 (file)
@@ -3264,47 +3264,53 @@ void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) {
 }
 
 namespace {
-  /// \brief Module visitor class that finds all of the redeclarations of a 
-  /// 
+  /// \brief Module visitor class that finds all of the redeclarations of a
+  /// redeclarable declaration.
   class RedeclChainVisitor {
     ASTReader &Reader;
     SmallVectorImpl<DeclID> &SearchDecls;
     llvm::SmallPtrSetImpl<Decl *> &Deserialized;
     GlobalDeclID CanonID;
     SmallVector<Decl *, 4> Chain;
-    
+
   public:
     RedeclChainVisitor(ASTReader &Reader, SmallVectorImpl<DeclID> &SearchDecls,
                        llvm::SmallPtrSetImpl<Decl *> &Deserialized,
                        GlobalDeclID CanonID)
       : Reader(Reader), SearchDecls(SearchDecls), Deserialized(Deserialized),
-        CanonID(CanonID) { 
-      for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I)
-        addToChain(Reader.GetDecl(SearchDecls[I]));
+        CanonID(CanonID) {
+      // Ensure that the canonical ID goes at the start of the chain.
+      addToChain(Reader.GetDecl(CanonID));
     }
-    
+
     static bool visit(ModuleFile &M, bool Preorder, void *UserData) {
       if (Preorder)
         return false;
-      
+
       return static_cast<RedeclChainVisitor *>(UserData)->visit(M);
     }
-    
+
     void addToChain(Decl *D) {
       if (!D)
         return;
-      
+
       if (Deserialized.erase(D))
         Chain.push_back(D);
     }
-    
+
     void searchForID(ModuleFile &M, GlobalDeclID GlobalID) {
       // Map global ID of the first declaration down to the local ID
       // used in this module file.
       DeclID ID = Reader.mapGlobalIDToModuleFileGlobalID(M, GlobalID);
       if (!ID)
         return;
-      
+
+      // If the search decl was from this module, add it to the chain before any
+      // of its redeclarations in this module or users of it, and after any from
+      // imported modules.
+      if (CanonID != GlobalID && Reader.isDeclIDFromModule(GlobalID, M))
+        addToChain(Reader.GetDecl(GlobalID));
+
       // Perform a binary search to find the local redeclarations for this
       // declaration (if any).
       const LocalRedeclarationsInfo Compare = { ID, 0 };
diff --git a/test/Modules/Inputs/merge-decl-order/a.h b/test/Modules/Inputs/merge-decl-order/a.h
new file mode 100644 (file)
index 0000000..f505a42
--- /dev/null
@@ -0,0 +1,2 @@
+namespace N { struct SA { friend struct foo; }; }
+namespace N { struct foo; }
diff --git a/test/Modules/Inputs/merge-decl-order/b.h b/test/Modules/Inputs/merge-decl-order/b.h
new file mode 100644 (file)
index 0000000..49b06ca
--- /dev/null
@@ -0,0 +1,2 @@
+namespace N { struct SB { friend struct foo; }; }
+#include "a.h"
diff --git a/test/Modules/Inputs/merge-decl-order/module.modulemap b/test/Modules/Inputs/merge-decl-order/module.modulemap
new file mode 100644 (file)
index 0000000..61578a1
--- /dev/null
@@ -0,0 +1,2 @@
+module a { header "a.h" export * }
+module b { header "b.h" export * }
index cbe2b65bdd64779cc43e2e43071d02b79ce86086..46c2f33ef15f7079f8a78c8ced7af130fa85b2d3 100644 (file)
@@ -189,11 +189,11 @@ namespace Std {
 // CHECK-NAMESPACE-N-NEXT: `-FunctionTemplate {{.*}} 'f'
 
 // CHECK-DUMP:      ClassTemplateDecl {{.*}} <{{.*[/\\]}}cxx-templates-common.h:1:1, {{.*}}>  col:{{.*}} in cxx_templates_common SomeTemplate
-// CHECK-DUMP:        ClassTemplateSpecializationDecl {{.*}} prev [[CHAR2:[^ ]*]] {{.*}} SomeTemplate
+// CHECK-DUMP:        ClassTemplateSpecializationDecl {{.*}} prev {{.*}} SomeTemplate
 // CHECK-DUMP-NEXT:     TemplateArgument type 'char [2]'
-// CHECK-DUMP:        ClassTemplateSpecializationDecl [[CHAR2]] {{.*}} SomeTemplate definition
+// CHECK-DUMP:        ClassTemplateSpecializationDecl {{.*}} SomeTemplate definition
 // CHECK-DUMP-NEXT:     TemplateArgument type 'char [2]'
-// CHECK-DUMP:        ClassTemplateSpecializationDecl {{.*}} prev [[CHAR1:[^ ]*]] {{.*}} SomeTemplate
+// CHECK-DUMP:        ClassTemplateSpecializationDecl {{.*}} prev {{.*}} SomeTemplate
 // CHECK-DUMP-NEXT:     TemplateArgument type 'char [1]'
-// CHECK-DUMP:        ClassTemplateSpecializationDecl [[CHAR1]] {{.*}} SomeTemplate definition
+// CHECK-DUMP:        ClassTemplateSpecializationDecl {{.*}} SomeTemplate definition
 // CHECK-DUMP-NEXT:     TemplateArgument type 'char [1]'
diff --git a/test/Modules/merge-decl-order.cpp b/test/Modules/merge-decl-order.cpp
new file mode 100644 (file)
index 0000000..d3b21fd
--- /dev/null
@@ -0,0 +1,9 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I%S/Inputs/merge-decl-order -verify %s
+// expected-no-diagnostics
+
+// Check that we include all decls from 'a' before the decls from 'b' in foo's
+// redecl chain. If we don't, then name lookup only finds invisible friend
+// declarations and the lookup below will fail.
+#include "b.h"
+N::foo *use;