diff options
author | Reid Kleckner <rnk@google.com> | 2016-04-22 18:46:33 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2016-04-22 18:46:33 +0000 |
commit | ea53dba78b5064052793fe9a8bec4a2649fb3e4f (patch) | |
tree | be8be11ed6f01ed6234698dd28e737047f60fea8 /clang/lib/CodeGen/ModuleBuilder.cpp | |
parent | 658d9dbe56b78e9d8d5a768b2e68ff86cab2b39d (diff) | |
download | llvm-ea53dba78b5064052793fe9a8bec4a2649fb3e4f.zip llvm-ea53dba78b5064052793fe9a8bec4a2649fb3e4f.tar.gz llvm-ea53dba78b5064052793fe9a8bec4a2649fb3e4f.tar.bz2 |
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.
llvm-svn: 267186
Diffstat (limited to 'clang/lib/CodeGen/ModuleBuilder.cpp')
-rw-r--r-- | clang/lib/CodeGen/ModuleBuilder.cpp | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp index 5b7201e..04271296 100644 --- a/clang/lib/CodeGen/ModuleBuilder.cpp +++ b/clang/lib/CodeGen/ModuleBuilder.cpp @@ -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); |