summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CodeGenModule.cpp
diff options
context:
space:
mode:
authorJustin Lebar <jlebar@google.com>2016-08-15 20:38:56 +0000
committerJustin Lebar <jlebar@google.com>2016-08-15 20:38:56 +0000
commit60dcc1344a27c62ba7b49dc1ff39881b606a97a3 (patch)
tree17d3403fdafc820f889f2da77c237f18e6820b37 /clang/lib/CodeGen/CodeGenModule.cpp
parent9421ba6c024151a2be99ccb58f657d09189e2464 (diff)
downloadbcm5719-llvm-60dcc1344a27c62ba7b49dc1ff39881b606a97a3.tar.gz
bcm5719-llvm-60dcc1344a27c62ba7b49dc1ff39881b606a97a3.zip
Add the notion of deferred diagnostics.
Summary: This patch lets you create diagnostics that are emitted if and only if a particular FunctionDecl is codegen'ed. This is necessary for CUDA, where some constructs -- e.g. calls from host+device functions to host functions when compiling for device -- are allowed to appear in semantically-correct programs, but only if they're never codegen'ed. Reviewers: rnk Subscribers: cfe-commits, tra Differential Revision: https://reviews.llvm.org/D23241 llvm-svn: 278735
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp37
1 files changed, 37 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index f20baab784b..2dcccf4c6c8 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -497,6 +497,16 @@ void CodeGenModule::Release() {
EmitVersionIdentMetadata();
EmitTargetMetadata();
+
+ // Emit any deferred diagnostics gathered during codegen. We didn't emit them
+ // when we first discovered them because that would have halted codegen,
+ // preventing us from gathering other deferred diags.
+ for (const PartialDiagnosticAt &DiagAt : DeferredDiags) {
+ SourceLocation Loc = DiagAt.first;
+ const PartialDiagnostic &PD = DiagAt.second;
+ DiagnosticBuilder Builder(getDiags().Report(Loc, PD.getDiagID()));
+ PD.Emit(Builder);
+ }
}
void CodeGenModule::UpdateCompletedType(const TagDecl *TD) {
@@ -2872,6 +2882,33 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
llvm::GlobalValue *GV) {
const auto *D = cast<FunctionDecl>(GD.getDecl());
+ // Emit this function's deferred diagnostics, if none of them are errors. If
+ // any of them are errors, don't codegen the function, but also don't emit any
+ // of the diagnostics just yet. Emitting an error during codegen stops
+ // further codegen, and we want to display as many deferred diags as possible.
+ // We'll emit the now twice-deferred diags at the very end of codegen.
+ //
+ // (If a function has both error and non-error diags, we don't emit the
+ // non-error diags here, because order can be significant, e.g. with notes
+ // that follow errors.)
+ auto Diags = D->takeDeferredDiags();
+ bool HasError = llvm::any_of(Diags, [this](const PartialDiagnosticAt &PDAt) {
+ return getDiags().getDiagnosticLevel(PDAt.second.getDiagID(), PDAt.first) >=
+ DiagnosticsEngine::Error;
+ });
+ if (HasError) {
+ DeferredDiags.insert(DeferredDiags.end(),
+ std::make_move_iterator(Diags.begin()),
+ std::make_move_iterator(Diags.end()));
+ return;
+ }
+ for (PartialDiagnosticAt &PDAt : Diags) {
+ const SourceLocation &Loc = PDAt.first;
+ const PartialDiagnostic &PD = PDAt.second;
+ DiagnosticBuilder Builder(getDiags().Report(Loc, PD.getDiagID()));
+ PD.Emit(Builder);
+ }
+
// Compute the function info and LLVM type.
const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD);
llvm::FunctionType *Ty = getTypes().GetFunctionType(FI);
OpenPOWER on IntegriCloud