summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2016-04-22 18:46:33 +0000
committerReid Kleckner <rnk@google.com>2016-04-22 18:46:33 +0000
commitea53dba78b5064052793fe9a8bec4a2649fb3e4f (patch)
treebe8be11ed6f01ed6234698dd28e737047f60fea8
parent658d9dbe56b78e9d8d5a768b2e68ff86cab2b39d (diff)
downloadbcm5719-llvm-ea53dba78b5064052793fe9a8bec4a2649fb3e4f.tar.gz
bcm5719-llvm-ea53dba78b5064052793fe9a8bec4a2649fb3e4f.zip
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
-rw-r--r--clang/lib/CodeGen/ModuleBuilder.cpp20
-rw-r--r--clang/test/PCH/Inputs/pr27445.h4
-rw-r--r--clang/test/PCH/pr27445.cpp14
3 files changed, 36 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp
index 5b7201e12d1..042712965b0 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);
diff --git a/clang/test/PCH/Inputs/pr27445.h b/clang/test/PCH/Inputs/pr27445.h
new file mode 100644
index 00000000000..f78a1bcf859
--- /dev/null
+++ b/clang/test/PCH/Inputs/pr27445.h
@@ -0,0 +1,4 @@
+struct Info {
+ virtual ~Info();
+ void hash() {}
+};
diff --git a/clang/test/PCH/pr27445.cpp b/clang/test/PCH/pr27445.cpp
new file mode 100644
index 00000000000..2a4af5e8276
--- /dev/null
+++ b/clang/test/PCH/pr27445.cpp
@@ -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 (...)** }
OpenPOWER on IntegriCloud