From 15241ba4dd8009cd89676f6f280d5de870e958ab Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 30 Nov 2016 00:25:36 +0000 Subject: [PATCH] Stop handling interesting deserialized decls after HandleTranslationUnit Other AST consumers can deserialize interesting decls that we might codegen, but they won't make it to the final object file and can trigger assertions in debug information generation after finalization. llvm-svn: 288221 --- clang/lib/CodeGen/CodeGenAction.cpp | 13 ++++++++++++ clang/test/Frontend/plugin-vs-debug-info.cpp | 30 ++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 clang/test/Frontend/plugin-vs-debug-info.cpp diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index da8f372..795b3a0 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -53,6 +53,11 @@ namespace clang { Timer LLVMIRGeneration; unsigned LLVMIRGenerationRefCount; + /// True if we've finished generating IR. This prevents us from generating + /// additional LLVM IR after emitting output in HandleTranslationUnit. This + /// can happen when Clang plugins trigger additional AST deserialization. + bool IRGenFinished = false; + std::unique_ptr Gen; SmallVector>, 4> @@ -147,6 +152,12 @@ namespace clang { LLVMIRGeneration.stopTimer(); } + void HandleInterestingDecl(DeclGroupRef D) { + // Ignore interesting decls from the AST reader after IRGen is finished. + if (!IRGenFinished) + HandleTopLevelDecl(D); + } + void HandleTranslationUnit(ASTContext &C) override { { PrettyStackTraceString CrashInfo("Per-file LLVM IR generation"); @@ -163,6 +174,8 @@ namespace clang { if (LLVMIRGenerationRefCount == 0) LLVMIRGeneration.stopTimer(); } + + IRGenFinished = true; } // Silently ignore if we weren't initialized for some reason. diff --git a/clang/test/Frontend/plugin-vs-debug-info.cpp b/clang/test/Frontend/plugin-vs-debug-info.cpp new file mode 100644 index 0000000..dceb2f1 --- /dev/null +++ b/clang/test/Frontend/plugin-vs-debug-info.cpp @@ -0,0 +1,30 @@ +// This test uses PrintFunctionNames with -fdelayed-template-parsing because it +// happens to use a RecursiveASTVisitor that forces deserialization of AST +// files. +// +// RUN: %clang_cc1 -fdelayed-template-parsing -std=c++14 -emit-pch -o %t.pch %s +// RUN: %clang_cc1 -load %llvmshlibdir/PrintFunctionNames%pluginext \ +// RUN: -add-plugin print-fns -std=c++14 -include-pch %t.pch %s -emit-llvm \ +// RUN: -fdelayed-template-parsing -debug-info-kind=limited \ +// RUN: -o %t.ll 2>&1 | FileCheck --check-prefix=DECLS %s +// RUN: FileCheck --check-prefix=IR %s < %t.ll +// +// REQUIRES: plugins, examples + +// DECLS: top-level-decl: "func" + +// IR: define {{.*}}void @_Z4funcv() + +#ifndef HEADER +#define HEADER + +struct nullopt_t { + constexpr explicit nullopt_t(int) {} +}; +constexpr nullopt_t nullopt(0); + +#else + +void func() { } + +#endif -- 2.7.4