Author: rnk Date: Fri Apr 22 13:46:33 2016 New Revision: 267186 URL: http://llvm.org/viewvc/llvm-project?rev=267186&view=rev Log: Fix a bug involving deferred decl emission and PCH
For various reasons, involving dllexport and class linkage compuations, we have to wait until after the semicolon after a class declaration to emit inline methods. These are "deferred" decls. Before this change, finishing the tag decl would trigger us to deserialize some PCH so that we could make a "pretty" IR-level type. Deserializing the PCH triggered calls to HandleTopLevelDecl, which, when done, checked the deferred decl list, and emitted some dllexported decls that weren't ready. Avoid this re-entrancy. Deferred decls should not get emitted when a tag is finished, they should only be emitted after a real top level decl in the main file. Added: cfe/trunk/test/PCH/Inputs/pr27445.h cfe/trunk/test/PCH/pr27445.cpp Modified: cfe/trunk/lib/CodeGen/ModuleBuilder.cpp Modified: cfe/trunk/lib/CodeGen/ModuleBuilder.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ModuleBuilder.cpp?rev=267186&r1=267185&r2=267186&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/ModuleBuilder.cpp (original) +++ cfe/trunk/lib/CodeGen/ModuleBuilder.cpp Fri Apr 22 13:46:33 2016 @@ -36,13 +36,21 @@ namespace { const CodeGenOptions CodeGenOpts; // Intentionally copied in. unsigned HandlingTopLevelDecls; + + /// Use this when emitting decls to block re-entrant decl emission. It will + /// emit all deferred decls on scope exit. Set EmitDeferred to false if decl + /// emission must be deferred longer, like at the end of a tag definition. struct HandlingTopLevelDeclRAII { CodeGeneratorImpl &Self; - HandlingTopLevelDeclRAII(CodeGeneratorImpl &Self) : Self(Self) { + bool EmitDeferred; + HandlingTopLevelDeclRAII(CodeGeneratorImpl &Self, + bool EmitDeferred = true) + : Self(Self), EmitDeferred(EmitDeferred) { ++Self.HandlingTopLevelDecls; } ~HandlingTopLevelDeclRAII() { - if (--Self.HandlingTopLevelDecls == 0) + unsigned Level = --Self.HandlingTopLevelDecls; + if (Level == 0 && EmitDeferred) Self.EmitDeferredDecls(); } }; @@ -185,6 +193,10 @@ namespace { if (Diags.hasErrorOccurred()) return; + // Don't allow re-entrant calls to CodeGen triggered by PCH + // deserialization to emit deferred decls. + HandlingTopLevelDeclRAII HandlingDecl(*this, /*EmitDeferred=*/false); + Builder->UpdateCompletedType(D); // For MSVC compatibility, treat declarations of static data members with @@ -214,6 +226,10 @@ namespace { if (Diags.hasErrorOccurred()) return; + // Don't allow re-entrant calls to CodeGen triggered by PCH + // deserialization to emit deferred decls. + HandlingTopLevelDeclRAII HandlingDecl(*this, /*EmitDeferred=*/false); + if (CodeGen::CGDebugInfo *DI = Builder->getModuleDebugInfo()) if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) DI->completeRequiredType(RD); Added: cfe/trunk/test/PCH/Inputs/pr27445.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/Inputs/pr27445.h?rev=267186&view=auto ============================================================================== --- cfe/trunk/test/PCH/Inputs/pr27445.h (added) +++ cfe/trunk/test/PCH/Inputs/pr27445.h Fri Apr 22 13:46:33 2016 @@ -0,0 +1,4 @@ +struct Info { + virtual ~Info(); + void hash() {} +}; Added: cfe/trunk/test/PCH/pr27445.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/pr27445.cpp?rev=267186&view=auto ============================================================================== --- cfe/trunk/test/PCH/pr27445.cpp (added) +++ cfe/trunk/test/PCH/pr27445.cpp Fri Apr 22 13:46:33 2016 @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -x c++ %S/Inputs/pr27445.h -emit-pch -o %t.pch +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions %s -include-pch %t.pch -emit-llvm -o - | FileCheck %s + +class A; +void fn1(A &) {} + +class __declspec(dllexport) A { + int operator=(A) { return field_; } + void (*on_arena_allocation_)(Info); + int field_; +}; + +// CHECK: %class.A = type { void (%struct.Info*)*, i32 } +// CHECK: %struct.Info = type { i32 (...)** } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits