[modules] When we merge redecl chains or mark a decl used with an update
authorRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 16 Jun 2014 20:26:19 +0000 (20:26 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 16 Jun 2014 20:26:19 +0000 (20:26 +0000)
record, mark all subsequent decls as 'used' too, to maintain the AST invariant
that getPreviousDecl()->Used implies this->Used.

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

lib/Serialization/ASTReader.cpp
lib/Serialization/ASTReaderDecl.cpp
test/Modules/Inputs/cxx-decls-imported.h
test/Modules/Inputs/cxx-decls-merged.h [new file with mode: 0644]
test/Modules/Inputs/module.map
test/Modules/cxx-decls.cpp

index e8db122445ec5b165c9904313a0f7cd7ab43097d..0c9f263faf1269725bcf6d5f0e2eb5520db8db4f 100644 (file)
@@ -8088,7 +8088,10 @@ void ASTReader::finishPendingActions() {
     }
 
     // Perform any pending declaration updates.
-    while (!PendingUpdateRecords.empty()) {
+    //
+    // Don't do this if we have known-incomplete redecl chains: it relies on
+    // being able to walk redeclaration chains.
+    while (PendingDeclChains.empty() && !PendingUpdateRecords.empty()) {
       auto Update = PendingUpdateRecords.pop_back_val();
       ReadingKindTracker ReadingKind(Read_Decl, *this);
       loadDeclUpdateRecords(Update.first, Update.second);
index 7e652c47181036b8555cc97236ee395ba855a81a..47748a33f76771f7ad72e2efe4846d454de8fdff 100644 (file)
@@ -2492,6 +2492,11 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *Previous) {
       Previous->IdentifierNamespace &
       (Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type);
 
+  // If the previous declaration is marked as used, then this declaration should
+  // be too.
+  if (Previous->Used)
+    D->Used = true;
+
   // If the previous declaration is an inline function declaration, then this
   // declaration is too.
   if (auto *FD = dyn_cast<FunctionDecl>(D)) {
@@ -3280,7 +3285,14 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
     case UPD_DECL_MARKED_USED: {
       // FIXME: This doesn't send the right notifications if there are
       // ASTMutationListeners other than an ASTWriter.
-      D->Used = true;
+
+      // Maintain AST consistency: any later redeclarations are used too.
+      for (auto *Redecl = D->getMostRecentDecl(); /**/;
+           Redecl = Redecl->getPreviousDecl()) {
+        Redecl->Used = true;
+        if (Redecl == D)
+          break;
+      }
       break;
     }
 
index 5c7f6fc34427b185fc0c1b8b6b5f64e6bb2e0092..38cc00d863f2f8771c94a206e755f199cb65d1db 100644 (file)
@@ -20,3 +20,6 @@ static_assert(!__is_trivial(HasNontrivialDefaultConstructor), "");
 static_assert(!__has_trivial_constructor(HasNontrivialDefaultConstructor), "");
 
 void *operator new[](__SIZE_TYPE__);
+
+extern int mergeUsedFlag;
+inline int getMergeUsedFlag() { return mergeUsedFlag; }
diff --git a/test/Modules/Inputs/cxx-decls-merged.h b/test/Modules/Inputs/cxx-decls-merged.h
new file mode 100644 (file)
index 0000000..ccc3b01
--- /dev/null
@@ -0,0 +1 @@
+extern int mergeUsedFlag;
index a85145f87110c23195152f441fa296d56f7cfe8c..fea12015233b6fa26c9cc4321deb94454301bf6d 100644 (file)
@@ -238,6 +238,10 @@ module cxx_decls {
   }
 }
 
+module cxx_decls_merged {
+  header "cxx-decls-merged.h"
+}
+
 module config {
   header "config.h"
   config_macros [exhaustive] WANT_FOO, WANT_BAR
index 49ba8340d3e4106528b01e50e9113ce9125b9ca0..5498b47fc9fe849efcf415bf30da03ff1f164957 100644 (file)
@@ -1,5 +1,6 @@
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -x objective-c++ -fmodules -fmodules-cache-path=%t -I %S/Inputs %s -verify -std=c++11
+// RUN: %clang_cc1 -x objective-c++ -fmodules -fmodules-cache-path=%t -I %S/Inputs %s -ast-dump -ast-dump-filter merge -std=c++11 | FileCheck %s
 
 // expected-no-diagnostics
 
@@ -26,3 +27,10 @@ static_assert(!__is_trivial(HasNontrivialDefaultConstructor), "");
 static_assert(!__has_trivial_constructor(HasNontrivialDefaultConstructor), "");
 
 void use_implicit_new_again() { operator new[](3); }
+
+int importMergeUsedFlag = getMergeUsedFlag();
+
+@import cxx_decls_merged;
+
+// CHECK: VarDecl [[mergeUsedFlag:0x[0-9a-f]*]] {{.*}} in cxx_decls.imported used mergeUsedFlag
+// CHECK: VarDecl {{0x[0-9a-f]*}} prev [[mergeUsedFlag]] {{.*}} in cxx_decls_merged used mergeUsedFlag