[OPENMP]Honor constantness of captured variables.

Fixes bug reported via Stackoverflow:
https://stackoverflow.com/questions/64179168/clang-overload-resolution-failure-with-templates-and-openmp-collapse

Need to honor constantness of private/target variables to  make the code
compilable.

Differential Revision: https://reviews.llvm.org/D91644
This commit is contained in:
Alexey Bataev 2020-11-17 09:30:33 -08:00
parent 06c192d454
commit 8f51dc4967
7 changed files with 68 additions and 15 deletions

View File

@ -17468,7 +17468,11 @@ bool Sema::tryCaptureVariable(
if (IsTargetCap || IsOpenMPPrivateDecl == OMPC_private ||
(IsGlobal && !IsGlobalCap)) {
Nested = !IsTargetCap;
bool HasConst = DeclRefType.isConstQualified();
DeclRefType = DeclRefType.getUnqualifiedType();
// Don't lose diagnostics about assignments to const.
if (HasConst)
DeclRefType.addConst();
CaptureType = Context.getLValueReferenceType(DeclRefType);
break;
}

View File

@ -28,8 +28,8 @@ class S3 {
S3 &operator=(const S3 &s3);
public:
S3() : a(0) {} // expected-note {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
S3(S3 &s3) : a(s3.a) {} // expected-note {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}}
S3() : a(0) {} // expected-note 2 {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
S3(S3 &s3) : a(s3.a) {} // expected-note 2 {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}}
};
const S3 c;
const S3 ca[5];
@ -95,7 +95,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams
#pragma omp distribute firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-warning {{Type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} expected-error {{incomplete type 'S1' where a complete type is required}}
#pragma omp distribute firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-warning {{Type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-error {{no matching constructor for initialization of 'S3'}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams

View File

@ -0,0 +1,49 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
struct vector {
vector() = default;
int at(int) { return 0; }
int at(int) const { return 1; }
};
// CHECK: template <typename T> void test(const vector begin_vec) {
// CHECK: #pragma omp parallel for collapse(2)
// CHECK: for (int n = begin_vec.at(0); n < 0; n++) {
// CHECK: for (int h = begin_vec.at(1); h < 1; h++) {
// CHECK: ;
// CHECK: }
// CHECK: }
// CHECK: }
// CHECK: template<> void test<int>(const vector begin_vec) {
// CHECK: #pragma omp parallel for collapse(2)
// CHECK: for (int n = begin_vec.at(0); n < 0; n++) {
// CHECK: for (int h = begin_vec.at(1); h < 1; h++) {
// CHECK: ;
// CHECK: }
// CHECK: }
// CHECK: }
template <typename T>
void test(const vector begin_vec) {
#pragma omp parallel for collapse(2)
for (int n = begin_vec.at(0); n < 0; n++) {
for (int h = begin_vec.at(1); h < 1; h++) {
;
}
}
}
int main() {
vector v;
test<int>(v);
}
#endif

View File

@ -37,8 +37,8 @@ class S3 {
S3 &operator=(const S3 &s3);
public:
S3() : a(0) {} // expected-note {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
S3(S3 &s3) : a(s3.a) {} // expected-note {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}}
S3() : a(0) {} // expected-note 2 {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
S3(S3 &s3) : a(s3.a) {} // expected-note 2 {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}}
};
const S3 c;
const S3 ca[5];
@ -108,7 +108,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams distribute firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{incomplete type 'S1' where a complete type is required}}
#pragma omp teams distribute firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-error {{no matching constructor for initialization of 'S3'}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target

View File

@ -37,8 +37,8 @@ class S3 {
S3 &operator=(const S3 &s3);
public:
S3() : a(0) {} // expected-note {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
S3(S3 &s3) : a(s3.a) {} // expected-note {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}}
S3() : a(0) {} // expected-note 2 {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
S3(S3 &s3) : a(s3.a) {} // expected-note 2 {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}}
};
const S3 c;
const S3 ca[5];
@ -108,7 +108,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams distribute parallel for firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{incomplete type 'S1' where a complete type is required}}
#pragma omp teams distribute parallel for firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-error {{no matching constructor for initialization of 'S3'}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target

View File

@ -38,8 +38,8 @@ class S3 {
S3 &operator=(const S3 &s3);
public:
S3() : a(0) {} // expected-note {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
S3(S3 &s3) : a(s3.a) {} // expected-note {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}}
S3() : a(0) {} // expected-note 2 {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
S3(S3 &s3) : a(s3.a) {} // expected-note 2 {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}}
};
const S3 c;
const S3 ca[5];
@ -109,7 +109,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams distribute parallel for simd firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{incomplete type 'S1' where a complete type is required}}
#pragma omp teams distribute parallel for simd firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-error {{no matching constructor for initialization of 'S3'}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target

View File

@ -39,8 +39,8 @@ class S3 {
S3 &operator=(const S3 &s3);
public:
S3() : a(0) {} // expected-note {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
S3(S3 &s3) : a(s3.a) {} // expected-note {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}}
S3() : a(0) {} // expected-note 2 {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
S3(S3 &s3) : a(s3.a) {} // expected-note 2 {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}}
};
const S3 c;
const S3 ca[5];
@ -110,7 +110,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams distribute simd firstprivate (k, a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{incomplete type 'S1' where a complete type is required}}
#pragma omp teams distribute simd firstprivate (k, a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-error {{no matching constructor for initialization of 'S3'}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target