[OPENMP]Fix PR44578: crash in target construct with captured global.

Target regions have implicit outer region which may erroneously capture
some globals when it should not. It may lead to a compiler crash at the
compile time.
This commit is contained in:
Alexey Bataev 2020-01-17 20:39:04 -05:00
parent 4c9d691445
commit 366356361c
14 changed files with 58 additions and 27 deletions

View File

@ -9681,7 +9681,8 @@ public:
/// Check if the specified variable is captured by 'target' directive.
/// \param Level Relative level of nested OpenMP construct for that the check
/// is performed.
bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level) const;
bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
unsigned CaptureLevel) const;
ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc,
Expr *Op);

View File

@ -16280,8 +16280,10 @@ bool Sema::tryCaptureVariable(
captureVariablyModifiedType(Context, QTy, OuterRSI);
}
}
bool IsTargetCap = !IsOpenMPPrivateDecl &&
isOpenMPTargetCapturedDecl(Var, RSI->OpenMPLevel);
bool IsTargetCap =
!IsOpenMPPrivateDecl &&
isOpenMPTargetCapturedDecl(Var, RSI->OpenMPLevel,
RSI->OpenMPCaptureLevel);
// When we detect target captures we are looking from inside the
// target region, therefore we need to propagate the capture from the
// enclosing region. Therefore, the capture is not initially nested.

View File

@ -31,6 +31,7 @@
#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/PointerEmbeddedInt.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Frontend/OpenMP/OMPConstants.h"
using namespace clang;
using namespace llvm::omp;
@ -2010,6 +2011,22 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
//
if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
return nullptr;
CapturedRegionScopeInfo *CSI = nullptr;
for (FunctionScopeInfo *FSI : llvm::drop_begin(
llvm::reverse(FunctionScopes),
CheckScopeInfo ? (FunctionScopes.size() - (StopAt + 1)) : 0)) {
if (!isa<CapturingScopeInfo>(FSI))
return nullptr;
if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
if (RSI->CapRegionKind == CR_OpenMP) {
CSI = RSI;
break;
}
}
SmallVector<OpenMPDirectiveKind, 4> Regions;
getOpenMPCaptureRegions(Regions,
DSAStack->getDirective(CSI->OpenMPLevel));
if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
return VD;
}
}
@ -2151,15 +2168,18 @@ void Sema::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
FD->addAttr(OMPCaptureKindAttr::CreateImplicit(Context, OMPC));
}
bool Sema::isOpenMPTargetCapturedDecl(const ValueDecl *D,
unsigned Level) const {
bool Sema::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
unsigned CaptureLevel) const {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
// Return true if the current level is no longer enclosed in a target region.
SmallVector<OpenMPDirectiveKind, 4> Regions;
getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
const auto *VD = dyn_cast<VarDecl>(D);
return VD && !VD->hasLocalStorage() &&
DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
Level);
Level) &&
Regions[CaptureLevel] != OMPD_task;
}
void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }

View File

@ -209,7 +209,7 @@ int foo(int n) {
// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
// CHECK: [[FAIL]]
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
@ -223,7 +223,7 @@ int foo(int n) {
// CHECK: call void (i8*, ...) %
// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],

View File

@ -112,4 +112,12 @@ int main(int argc, char **argv) {
return 0;
}
template <class> struct a { static bool b; };
template <class c, bool = a<c>::b> void e(c) { // expected-note {{candidate template ignored: substitution failure [with c = int]: non-type template argument is not a constant expression}}
#pragma omp target
{
int d ; e(d); // expected-error {{no matching function for call to 'e'}}
}
}
#endif

View File

@ -209,7 +209,7 @@ int foo(int n) {
// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
// CHECK: [[FAIL]]
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
@ -223,7 +223,7 @@ int foo(int n) {
// CHECK: call void (i8*, ...) %
// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],

View File

@ -209,7 +209,7 @@ int foo(int n) {
// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
// CHECK: [[FAIL]]
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
@ -223,7 +223,7 @@ int foo(int n) {
// CHECK: call void (i8*, ...) %
// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],

View File

@ -209,7 +209,7 @@ int foo(int n) {
// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
// CHECK: [[FAIL]]
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
@ -223,7 +223,7 @@ int foo(int n) {
// CHECK: call void (i8*, ...) %
// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],

View File

@ -209,7 +209,7 @@ int foo(int n) {
// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
// CHECK: [[FAIL]]
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
@ -223,7 +223,7 @@ int foo(int n) {
// CHECK: call void (i8*, ...) %
// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],

View File

@ -209,7 +209,7 @@ int foo(int n) {
// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
// CHECK: [[FAIL]]
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
@ -223,7 +223,7 @@ int foo(int n) {
// CHECK: call void (i8*, ...) %
// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],

View File

@ -209,7 +209,7 @@ int foo(int n) {
// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
// CHECK: [[FAIL]]
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
@ -223,7 +223,7 @@ int foo(int n) {
// CHECK: call void (i8*, ...) %
// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],

View File

@ -209,7 +209,7 @@ int foo(int n) {
// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
// CHECK: [[FAIL]]
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
@ -223,7 +223,7 @@ int foo(int n) {
// CHECK: call void (i8*, ...) %
// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],

View File

@ -209,7 +209,7 @@ int foo(int n) {
// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
// CHECK: [[FAIL]]
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
@ -223,7 +223,7 @@ int foo(int n) {
// CHECK: call void (i8*, ...) %
// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],

View File

@ -209,7 +209,7 @@ int foo(int n) {
// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
// CHECK: [[FAIL]]
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
@ -223,7 +223,7 @@ int foo(int n) {
// CHECK: call void (i8*, ...) %
// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
// CHECK: [[BP1_I32:%.+]] = load i32, i32* @
// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],