r278735 - Add the notion of deferred diagnostics.
Justin Lebar via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 15 13:38:57 PDT 2016
Author: jlebar
Date: Mon Aug 15 15:38:56 2016
New Revision: 278735
URL: http://llvm.org/viewvc/llvm-project?rev=278735&view=rev
Log:
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
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.h
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=278735&r1=278734&r2=278735&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Mon Aug 15 15:38:56 2016
@@ -324,6 +324,12 @@ class ASTContext : public RefCountedBase
};
llvm::DenseMap<Module*, PerModuleInitializers*> ModuleInitializers;
+ /// Diagnostics that are emitted if and only if the given function is
+ /// codegen'ed. Access these through FunctionDecl::addDeferredDiag() and
+ /// FunctionDecl::takeDeferredDiags().
+ llvm::DenseMap<const FunctionDecl *, std::vector<PartialDiagnosticAt>>
+ DeferredDiags;
+
public:
/// \brief A type synonym for the TemplateOrInstantiation mapping.
typedef llvm::PointerUnion<VarTemplateDecl *, MemberSpecializationInfo *>
@@ -597,6 +603,11 @@ public:
return DiagAllocator;
}
+ decltype(DeferredDiags) &getDeferredDiags() { return DeferredDiags; }
+ const decltype(DeferredDiags) &getDeferredDiags() const {
+ return DeferredDiags;
+ }
+
const TargetInfo &getTargetInfo() const { return *Target; }
const TargetInfo *getAuxTargetInfo() const { return AuxTarget; }
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=278735&r1=278734&r2=278735&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Mon Aug 15 15:38:56 2016
@@ -2271,6 +2271,14 @@ public:
/// returns 0.
unsigned getMemoryFunctionKind() const;
+ /// Add a diagnostic to be emitted if and when this function is codegen'ed.
+ void addDeferredDiag(PartialDiagnosticAt PD);
+
+ /// Gets this object's list of deferred diagnostics, if there are any.
+ ///
+ /// Although this is logically const, it clears our list of deferred diags.
+ std::vector<PartialDiagnosticAt> takeDeferredDiags() const;
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) {
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=278735&r1=278734&r2=278735&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Mon Aug 15 15:38:56 2016
@@ -3446,6 +3446,20 @@ unsigned FunctionDecl::getMemoryFunction
return 0;
}
+void FunctionDecl::addDeferredDiag(PartialDiagnosticAt PD) {
+ getASTContext().getDeferredDiags()[this].push_back(std::move(PD));
+}
+
+std::vector<PartialDiagnosticAt> FunctionDecl::takeDeferredDiags() const {
+ auto &DD = getASTContext().getDeferredDiags();
+ auto It = DD.find(this);
+ if (It == DD.end())
+ return {};
+ auto Ret = std::move(It->second);
+ DD.erase(It);
+ return Ret;
+}
+
//===----------------------------------------------------------------------===//
// FieldDecl Implementation
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=278735&r1=278734&r2=278735&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Mon Aug 15 15:38:56 2016
@@ -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::EmitGlobalFunctionDe
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);
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=278735&r1=278734&r2=278735&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Mon Aug 15 15:38:56 2016
@@ -490,6 +490,10 @@ private:
/// MDNodes.
llvm::DenseMap<QualType, llvm::Metadata *> MetadataIdMap;
+ /// Diags gathered from FunctionDecl::takeDeferredDiags(). Emitted at the
+ /// very end of codegen.
+ std::vector<std::pair<SourceLocation, PartialDiagnostic>> DeferredDiags;
+
public:
CodeGenModule(ASTContext &C, const HeaderSearchOptions &headersearchopts,
const PreprocessorOptions &ppopts,
More information about the cfe-commits
mailing list