From e4d7f02c0699f734a9ea83e2dc4b5512f4700ec0 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 16 Jun 2014 20:26:19 +0000 Subject: [PATCH] [modules] When we merge redecl chains or mark a decl used with an update 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 | 5 ++++- lib/Serialization/ASTReaderDecl.cpp | 14 +++++++++++++- test/Modules/Inputs/cxx-decls-imported.h | 3 +++ test/Modules/Inputs/cxx-decls-merged.h | 1 + test/Modules/Inputs/module.map | 4 ++++ test/Modules/cxx-decls.cpp | 8 ++++++++ 6 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 test/Modules/Inputs/cxx-decls-merged.h diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index e8db122445..0c9f263faf 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -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); diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 7e652c4718..47748a33f7 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -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(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; } diff --git a/test/Modules/Inputs/cxx-decls-imported.h b/test/Modules/Inputs/cxx-decls-imported.h index 5c7f6fc344..38cc00d863 100644 --- a/test/Modules/Inputs/cxx-decls-imported.h +++ b/test/Modules/Inputs/cxx-decls-imported.h @@ -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 index 0000000000..ccc3b01548 --- /dev/null +++ b/test/Modules/Inputs/cxx-decls-merged.h @@ -0,0 +1 @@ +extern int mergeUsedFlag; diff --git a/test/Modules/Inputs/module.map b/test/Modules/Inputs/module.map index a85145f871..fea1201523 100644 --- a/test/Modules/Inputs/module.map +++ b/test/Modules/Inputs/module.map @@ -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 diff --git a/test/Modules/cxx-decls.cpp b/test/Modules/cxx-decls.cpp index 49ba8340d3..5498b47fc9 100644 --- a/test/Modules/cxx-decls.cpp +++ b/test/Modules/cxx-decls.cpp @@ -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 -- 2.40.0