diff options
author | Justin Lebar <jlebar@google.com> | 2016-08-15 20:38:56 +0000 |
---|---|---|
committer | Justin Lebar <jlebar@google.com> | 2016-08-15 20:38:56 +0000 |
commit | 60dcc1344a27c62ba7b49dc1ff39881b606a97a3 (patch) | |
tree | 17d3403fdafc820f889f2da77c237f18e6820b37 /clang/lib/CodeGen/CodeGenModule.cpp | |
parent | 9421ba6c024151a2be99ccb58f657d09189e2464 (diff) | |
download | bcm5719-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.cpp | 37 |
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); |