From e1407069084cbde11c3b6ae93a1435f11c294675 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Tue, 20 Aug 2019 19:50:13 +0000 Subject: [PATCH] [OPENMP]Fix delayed diagnostics for standalone declare target directive. If the function is marked as declare target in a standalone directive, the delayed diagnostics is not emitted. Patch fixes this problem. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@369432 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 3 ++- lib/Sema/Sema.cpp | 6 +++--- lib/Sema/SemaOpenMP.cpp | 19 +++++++++++++------ test/OpenMP/nvptx_asm_delayed_diags.c | 12 ++++++++++++ test/OpenMP/nvptx_va_arg_delayed_diags.c | 13 +++++++++++++ 5 files changed, 43 insertions(+), 10 deletions(-) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index ef94becf8d..c77429befe 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -8997,7 +8997,8 @@ private: void popOpenMPFunctionRegion(const sema::FunctionScopeInfo *OldFSI); /// Check whether we're allowed to call Callee from the current function. - void checkOpenMPDeviceFunction(SourceLocation Loc, FunctionDecl *Callee); + void checkOpenMPDeviceFunction(SourceLocation Loc, FunctionDecl *Callee, + bool CheckForDelayedContext = true); /// Check if the expression is allowed to be used in expressions for the /// OpenMP devices. diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 89e7d4c9e6..9a84a3d4c8 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -1383,7 +1383,7 @@ static void emitCallStackNotes(Sema &S, FunctionDecl *FD) { // Emit any deferred diagnostics for FD and erase them from the map in which // they're stored. -static void emitDeferredDiags(Sema &S, FunctionDecl *FD) { +static void emitDeferredDiags(Sema &S, FunctionDecl *FD, bool ShowCallStack) { auto It = S.DeviceDeferredDiags.find(FD); if (It == S.DeviceDeferredDiags.end()) return; @@ -1402,7 +1402,7 @@ static void emitDeferredDiags(Sema &S, FunctionDecl *FD) { // FIXME: Should this be called after every warning/error emitted in the loop // above, instead of just once per function? That would be consistent with // how we handle immediate errors, but it also seems like a bit much. - if (HasWarningOrError) + if (HasWarningOrError && ShowCallStack) emitCallStackNotes(S, FD); } @@ -1505,7 +1505,7 @@ void Sema::markKnownEmitted( assert(!IsKnownEmitted(S, C.Callee) && "Worklist should not contain known-emitted functions."); S.DeviceKnownEmittedFns[C.Callee] = {C.Caller, C.Loc}; - emitDeferredDiags(S, C.Callee); + emitDeferredDiags(S, C.Callee, C.Caller); // If this is a template instantiation, explore its callgraph as well: // Non-dependent calls are part of the template's callgraph, while dependent diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 6d7b542ddb..9b34c88846 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -1576,7 +1576,8 @@ Sema::DeviceDiagBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc, Loc, DiagID, getCurFunctionDecl(), *this); } -void Sema::checkOpenMPDeviceFunction(SourceLocation Loc, FunctionDecl *Callee) { +void Sema::checkOpenMPDeviceFunction(SourceLocation Loc, FunctionDecl *Callee, + bool CheckForDelayedContext) { assert(LangOpts.OpenMP && LangOpts.OpenMPIsDevice && "Expected OpenMP device compilation."); assert(Callee && "Callee may not be null."); @@ -1584,9 +1585,13 @@ void Sema::checkOpenMPDeviceFunction(SourceLocation Loc, FunctionDecl *Callee) { // If the caller is known-emitted, mark the callee as known-emitted. // Otherwise, mark the call in our call graph so we can traverse it later. - if (!isOpenMPDeviceDelayedContext(*this) || + if ((CheckForDelayedContext && !isOpenMPDeviceDelayedContext(*this)) || + (!Caller && !CheckForDelayedContext) || (Caller && isKnownEmitted(*this, Caller))) - markKnownEmitted(*this, Caller, Callee, Loc, isKnownEmitted); + markKnownEmitted(*this, Caller, Callee, Loc, + [CheckForDelayedContext](Sema &S, FunctionDecl *FD) { + return CheckForDelayedContext && isKnownEmitted(S, FD); + }); else if (Caller) DeviceCallGraph[Caller].insert({Callee, Loc}); } @@ -15406,15 +15411,17 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, } if (const auto *FTD = dyn_cast(D)) D = FTD->getTemplatedDecl(); - if (const auto *FD = dyn_cast(D)) { + if (auto *FD = dyn_cast(D)) { llvm::Optional Res = OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD); - if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) { - assert(IdLoc.isValid() && "Source location is expected"); + if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) { Diag(IdLoc, diag::err_omp_function_in_link_clause); Diag(FD->getLocation(), diag::note_defined_here) << FD; return; } + // Mark the function as must be emitted for the device. + if (LangOpts.OpenMPIsDevice && Res.hasValue() && IdLoc.isValid()) + checkOpenMPDeviceFunction(IdLoc, FD, /*CheckForDelayedContext=*/false); } if (auto *VD = dyn_cast(D)) { // Problem if any with var declared with incomplete type will be reported diff --git a/test/OpenMP/nvptx_asm_delayed_diags.c b/test/OpenMP/nvptx_asm_delayed_diags.c index 460bf04b59..3d347046e5 100644 --- a/test/OpenMP/nvptx_asm_delayed_diags.c +++ b/test/OpenMP/nvptx_asm_delayed_diags.c @@ -9,6 +9,18 @@ // expected-no-diagnostics #endif // DIAGS +void foo(int r) { +#ifdef IMMEDIATE +// expected-error@+4 {{invalid input constraint 'mx' in asm}} +#endif // IMMEDIATE + __asm__("PR3908 %[lf] %[xx] %[li] %[r]" + : [ r ] "+r"(r) + : [ lf ] "mx"(0), [ li ] "mr"(0), [ xx ] "x"((double)(0))); +} +#ifdef IMMEDIATE +#pragma omp declare target to(foo) +#endif //IMMEDIATE + #ifdef IMMEDIATE #pragma omp declare target #endif //IMMEDIATE diff --git a/test/OpenMP/nvptx_va_arg_delayed_diags.c b/test/OpenMP/nvptx_va_arg_delayed_diags.c index 3420884d97..49ab99f8ee 100644 --- a/test/OpenMP/nvptx_va_arg_delayed_diags.c +++ b/test/OpenMP/nvptx_va_arg_delayed_diags.c @@ -9,6 +9,19 @@ // expected-no-diagnostics #endif // DIAGS +void foo(int r, ...) { +#ifdef IMMEDIATE +// expected-error@+4 {{CUDA device code does not support va_arg}} +#endif // IMMEDIATE + __builtin_va_list list; + __builtin_va_start(list, r); + (void)__builtin_va_arg(list, int); + __builtin_va_end(list); +} +#ifdef IMMEDIATE +#pragma omp declare target to(foo) +#endif //IMMEDIATE + #ifdef IMMEDIATE #pragma omp declare target #endif //IMMEDIATE -- 2.40.0