diff options
author | Yaxun (Sam) Liu <yaxun.liu@amd.com> | 2020-09-16 15:42:08 -0400 |
---|---|---|
committer | Yaxun (Sam) Liu <yaxun.liu@amd.com> | 2020-09-17 11:30:42 -0400 |
commit | 40df06cdafc010002fc9cfe1dda73d689b7d27a6 (patch) | |
tree | bdf2102638fcb84c0641030d7f797ccf5197a90d /clang/lib/Sema/Sema.cpp | |
parent | d5fd3d9b903ef6d96c6b3b82434dd0461faaba55 (diff) | |
download | llvm-40df06cdafc010002fc9cfe1dda73d689b7d27a6.zip llvm-40df06cdafc010002fc9cfe1dda73d689b7d27a6.tar.gz llvm-40df06cdafc010002fc9cfe1dda73d689b7d27a6.tar.bz2 |
[CUDA][HIP] Defer overloading resolution diagnostics for host device functions
In CUDA/HIP a function may become implicit host device function by
pragma or constexpr. A host device function is checked in both
host and device compilation. However it may be emitted only
on host or device side, therefore the diagnostics should be
deferred until it is known to be emitted.
Currently clang is only able to defer certain diagnostics. This causes
false alarms and limits the usefulness of host device functions.
This patch lets clang defer all overloading resolution diagnostics for host device functions.
An option -fgpu-defer-diag is added to control this behavior. By default
it is off.
It is NFC for other languages.
Differential Revision: https://reviews.llvm.org/D84364
Diffstat (limited to 'clang/lib/Sema/Sema.cpp')
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 65 |
1 files changed, 52 insertions, 13 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 375fe3b..53ff2b6 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1436,11 +1436,24 @@ void Sema::EmitCurrentDiagnostic(unsigned DiagID) { } Sema::SemaDiagnosticBuilder -Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) { - SemaDiagnosticBuilder Builder(Diag(Loc, PD.getDiagID())); - PD.Emit(Builder); +Sema::Diag(SourceLocation Loc, const PartialDiagnostic &PD, bool DeferHint) { + return Diag(Loc, PD.getDiagID(), DeferHint) << PD; +} - return Builder; +bool Sema::hasUncompilableErrorOccurred() const { + if (getDiagnostics().hasUncompilableErrorOccurred()) + return true; + auto *FD = dyn_cast<FunctionDecl>(CurContext); + if (!FD) + return false; + auto Loc = DeviceDeferredDiags.find(FD); + if (Loc == DeviceDeferredDiags.end()) + return false; + for (auto PDAt : Loc->second) { + if (DiagnosticIDs::isDefaultMappingAsError(PDAt.second.getDiagID())) + return true; + } + return false; } // Print notes showing how we can reach FD starting from an a priori @@ -1653,9 +1666,9 @@ void Sema::emitDeferredDiags() { // until we discover that the function is known-emitted, at which point we take // it out of this map and emit the diagnostic. -Sema::DeviceDiagBuilder::DeviceDiagBuilder(Kind K, SourceLocation Loc, - unsigned DiagID, FunctionDecl *Fn, - Sema &S) +Sema::SemaDiagnosticBuilder::SemaDiagnosticBuilder(Kind K, SourceLocation Loc, + unsigned DiagID, + FunctionDecl *Fn, Sema &S) : S(S), Loc(Loc), DiagID(DiagID), Fn(Fn), ShowCallStack(K == K_ImmediateWithCallStack || K == K_Deferred) { switch (K) { @@ -1663,7 +1676,8 @@ Sema::DeviceDiagBuilder::DeviceDiagBuilder(Kind K, SourceLocation Loc, break; case K_Immediate: case K_ImmediateWithCallStack: - ImmediateDiag.emplace(S.Diag(Loc, DiagID)); + ImmediateDiag.emplace( + ImmediateDiagBuilder(S.Diags.Report(Loc, DiagID), S, DiagID)); break; case K_Deferred: assert(Fn && "Must have a function to attach the deferred diag to."); @@ -1674,7 +1688,7 @@ Sema::DeviceDiagBuilder::DeviceDiagBuilder(Kind K, SourceLocation Loc, } } -Sema::DeviceDiagBuilder::DeviceDiagBuilder(DeviceDiagBuilder &&D) +Sema::SemaDiagnosticBuilder::SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D) : S(D.S), Loc(D.Loc), DiagID(D.DiagID), Fn(D.Fn), ShowCallStack(D.ShowCallStack), ImmediateDiag(D.ImmediateDiag), PartialDiagId(D.PartialDiagId) { @@ -1684,7 +1698,7 @@ Sema::DeviceDiagBuilder::DeviceDiagBuilder(DeviceDiagBuilder &&D) D.PartialDiagId.reset(); } -Sema::DeviceDiagBuilder::~DeviceDiagBuilder() { +Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() { if (ImmediateDiag) { // Emit our diagnostic and, if it was a warning or error, output a callstack // if Fn isn't a priori known-emitted. @@ -1699,7 +1713,8 @@ Sema::DeviceDiagBuilder::~DeviceDiagBuilder() { } } -Sema::DeviceDiagBuilder Sema::targetDiag(SourceLocation Loc, unsigned DiagID) { +Sema::SemaDiagnosticBuilder Sema::targetDiag(SourceLocation Loc, + unsigned DiagID) { if (LangOpts.OpenMP) return LangOpts.OpenMPIsDevice ? diagIfOpenMPDeviceCode(Loc, DiagID) : diagIfOpenMPHostCode(Loc, DiagID); @@ -1710,8 +1725,32 @@ Sema::DeviceDiagBuilder Sema::targetDiag(SourceLocation Loc, unsigned DiagID) { if (getLangOpts().SYCLIsDevice) return SYCLDiagIfDeviceCode(Loc, DiagID); - return DeviceDiagBuilder(DeviceDiagBuilder::K_Immediate, Loc, DiagID, - getCurFunctionDecl(), *this); + return SemaDiagnosticBuilder(SemaDiagnosticBuilder::K_Immediate, Loc, DiagID, + getCurFunctionDecl(), *this); +} + +Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID, + bool DeferHint) { + bool IsError = Diags.getDiagnosticIDs()->isDefaultMappingAsError(DiagID); + bool ShouldDefer = getLangOpts().CUDA && LangOpts.GPUDeferDiag && + DiagnosticIDs::isDeferrable(DiagID) && + (DeferHint || !IsError); + auto SetIsLastErrorImmediate = [&](bool Flag) { + if (IsError) + IsLastErrorImmediate = Flag; + }; + if (!ShouldDefer) { + SetIsLastErrorImmediate(true); + return SemaDiagnosticBuilder(SemaDiagnosticBuilder::K_Immediate, Loc, + DiagID, getCurFunctionDecl(), *this); + } + + SemaDiagnosticBuilder DB = + getLangOpts().CUDAIsDevice + ? CUDADiagIfDeviceCode(Loc, DiagID) + : CUDADiagIfHostCode(Loc, DiagID); + SetIsLastErrorImmediate(DB.isImmediate()); + return DB; } void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) { |