From: Richard Smith Date: Sun, 23 Mar 2014 00:27:18 +0000 (+0000) Subject: If an update record makes a declaration interesting, pass it to the consumer. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9f36ccd5471491806c69f8ac2639543c6a096ca6;p=clang If an update record makes a declaration interesting, pass it to the consumer. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@204550 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index abb6c9cc39..fc8c030833 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2892,6 +2892,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { Error("invalid DECL_UPDATE_OFFSETS block in AST file"); return true; } + // FIXME: If we've already loaded the decl, perform the updates now. for (unsigned I = 0, N = Record.size(); I != N; I += 2) DeclUpdateOffsets[getGlobalDeclID(F, Record[I])] .push_back(std::make_pair(&F, Record[I+1])); @@ -6313,6 +6314,15 @@ static void PassObjCImplDeclToConsumer(ObjCImplDecl *ImplD, void ASTReader::PassInterestingDeclsToConsumer() { assert(Consumer); + + if (PassingDeclsToConsumer) + return; + + // Guard variable to avoid recursively redoing the process of passing + // decls to consumer. + SaveAndRestore GuardPassingDeclsToConsumer(PassingDeclsToConsumer, + true); + while (!InterestingDecls.empty()) { Decl *D = InterestingDecls.front(); InterestingDecls.pop_front(); @@ -7922,20 +7932,10 @@ void ASTReader::FinishedDeserializing() { } --NumCurrentElementsDeserializing; - if (NumCurrentElementsDeserializing == 0 && - Consumer && !PassingDeclsToConsumer) { - // Guard variable to avoid recursively redoing the process of passing - // decls to consumer. - SaveAndRestore GuardPassingDeclsToConsumer(PassingDeclsToConsumer, - true); - - while (!InterestingDecls.empty()) { - // We are not in recursive loading, so it's safe to pass the "interesting" - // decls to the consumer. - Decl *D = InterestingDecls.front(); - InterestingDecls.pop_front(); - PassInterestingDeclToConsumer(D); - } + if (NumCurrentElementsDeserializing == 0 && Consumer) { + // We are not in recursive loading, so it's safe to pass the "interesting" + // decls to the consumer. + PassInterestingDeclsToConsumer(); } } diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index d6660e8b9b..5596bb4e74 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -2644,6 +2644,7 @@ void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) { DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID); if (UpdI != DeclUpdateOffsets.end()) { FileOffsetsTy &UpdateOffsets = UpdI->second; + bool WasInteresting = isConsumerInterestedIn(D, false); for (FileOffsetsTy::iterator I = UpdateOffsets.begin(), E = UpdateOffsets.end(); I != E; ++I) { ModuleFile *F = I->first; @@ -2656,10 +2657,18 @@ void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) { unsigned RecCode = Cursor.readRecord(Code, Record); (void)RecCode; assert(RecCode == DECL_UPDATES && "Expected DECL_UPDATES record!"); - + unsigned Idx = 0; ASTDeclReader Reader(*this, *F, ID, 0, Record, Idx); Reader.UpdateDecl(D, *F, Record); + + // We might have made this declaration interesting. If so, remember that + // we need to hand it off to the consumer. + if (!WasInteresting && + isConsumerInterestedIn(D, Reader.hasPendingBody())) { + InterestingDecls.push_back(D); + WasInteresting = true; + } } } } @@ -2958,6 +2967,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, Reader.ReadCXXCtorInitializers(ModuleFile, Record, Idx); // Store the offset of the body so we can lazily load it later. Reader.PendingBodies[FD] = GetCurrentCursorOffset(); + HasPendingBody = true; assert(Idx == Record.size() && "lazy body must be last"); break; } diff --git a/test/Modules/Inputs/cxx-irgen-left.h b/test/Modules/Inputs/cxx-irgen-left.h index d2f9d7fe10..970ac764fc 100644 --- a/test/Modules/Inputs/cxx-irgen-left.h +++ b/test/Modules/Inputs/cxx-irgen-left.h @@ -1,3 +1,7 @@ #include "cxx-irgen-top.h" S s; + +inline int instantiate_min() { + return min(1, 2); +} diff --git a/test/Modules/Inputs/cxx-irgen-top.h b/test/Modules/Inputs/cxx-irgen-top.h index 05f8e19ee1..8113e94def 100644 --- a/test/Modules/Inputs/cxx-irgen-top.h +++ b/test/Modules/Inputs/cxx-irgen-top.h @@ -4,3 +4,7 @@ template struct S { }; extern template struct S; + +template T min(T a, T b) { return a < b ? a : b; } + +extern decltype(min(1, 2)) instantiate_min_decl; diff --git a/test/Modules/cxx-irgen.cpp b/test/Modules/cxx-irgen.cpp index 91657fdc0e..7a42cb6b8c 100644 --- a/test/Modules/cxx-irgen.cpp +++ b/test/Modules/cxx-irgen.cpp @@ -1,15 +1,18 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -fmodules -x objective-c++ -fmodules-cache-path=%t -I %S/Inputs -triple %itanium_abi_triple -disable-llvm-optzns -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fmodules -x objective-c++ -std=c++11 -fmodules-cache-path=%t -I %S/Inputs -triple %itanium_abi_triple -disable-llvm-optzns -emit-llvm -o - %s | FileCheck %s // FIXME: When we have a syntax for modules in C++, use that. @import cxx_irgen_top; @import cxx_irgen_left; @import cxx_irgen_right; -// CHECK: define available_externally hidden i32 @_ZN1SIiE1gEv({{.*}} #[[ALWAYS_INLINE:.*]] align +// CHECK-DAG: define available_externally hidden i32 @_ZN1SIiE1gEv({{.*}} #[[ALWAYS_INLINE:.*]] align int a = S::g(); -// CHECK: define available_externally i32 @_ZN1SIiE1fEv({{.*}} #[[ALWAYS_INLINE]] align +// CHECK-DAG: define available_externally i32 @_ZN1SIiE1fEv({{.*}} #[[ALWAYS_INLINE]] align int b = h(); +// CHECK-DAG: define linkonce_odr i32 @_Z3minIiET_S0_S0_(i32 +int c = min(1, 2); + // CHECK: attributes #[[ALWAYS_INLINE]] = {{.*}} alwaysinline