summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@hotmail.com>2019-06-21 17:28:41 +0000
committerAlexey Bataev <a.bataev@hotmail.com>2019-06-21 17:28:41 +0000
commit0f21507b44784869232ad5dbb3605d8cb1c956d2 (patch)
tree7cdb296f889e0648c7f928d8f1259c1507beb952
parent6af1be96641f34e10bf3b4866f72571b63fab27c (diff)
downloadbcm5719-llvm-0f21507b44784869232ad5dbb3605d8cb1c956d2.tar.gz
bcm5719-llvm-0f21507b44784869232ad5dbb3605d8cb1c956d2.zip
[OPENMP]Fix PR42068: Vla type is not captured.
If the variably modified type is declared outside of the captured region and then used in the cast expression along with array subscript expression, the type is not captured and it leads to the compiler crash. llvm-svn: 364080
-rw-r--r--clang/lib/Sema/SemaExpr.cpp27
-rw-r--r--clang/test/OpenMP/parallel_codegen.cpp22
2 files changed, 40 insertions, 9 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 9b09059c153..8fd7e5eafab 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -4737,6 +4737,33 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
assert(VK == VK_RValue || LangOpts.CPlusPlus ||
!ResultType.isCForbiddenLValueType());
+ if (LHSExp->IgnoreParenImpCasts()->getType()->isVariablyModifiedType() &&
+ FunctionScopes.size() > 1) {
+ if (auto *TT =
+ LHSExp->IgnoreParenImpCasts()->getType()->getAs<TypedefType>()) {
+ for (auto I = FunctionScopes.rbegin(),
+ E = std::prev(FunctionScopes.rend());
+ I != E; ++I) {
+ auto *CSI = dyn_cast<CapturingScopeInfo>(*I);
+ if (CSI == nullptr)
+ break;
+ DeclContext *DC = nullptr;
+ if (auto *LSI = dyn_cast<LambdaScopeInfo>(CSI))
+ DC = LSI->CallOperator;
+ else if (auto *CRSI = dyn_cast<CapturedRegionScopeInfo>(CSI))
+ DC = CRSI->TheCapturedDecl;
+ else if (auto *BSI = dyn_cast<BlockScopeInfo>(CSI))
+ DC = BSI->TheDecl;
+ if (DC) {
+ if (DC->containsDecl(TT->getDecl()))
+ break;
+ captureVariablyModifiedType(
+ Context, LHSExp->IgnoreParenImpCasts()->getType(), CSI);
+ }
+ }
+ }
+ }
+
return new (Context)
ArraySubscriptExpr(LHSExp, RHSExp, ResultType, VK, OK, RLoc);
}
diff --git a/clang/test/OpenMP/parallel_codegen.cpp b/clang/test/OpenMP/parallel_codegen.cpp
index 87a5197fd2e..84dd44914e7 100644
--- a/clang/test/OpenMP/parallel_codegen.cpp
+++ b/clang/test/OpenMP/parallel_codegen.cpp
@@ -15,16 +15,20 @@
// CHECK-DEBUG-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DEBUG-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
// CHECK-DEBUG-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
-// CHECK-DEBUG-DAG: [[LOC1:@.+]] = private unnamed_addr constant [{{.+}} x i8] c";{{.*}}parallel_codegen.cpp;main;[[@LINE+15]];1;;\00"
-// CHECK-DEBUG-DAG: [[LOC2:@.+]] = private unnamed_addr constant [{{.+}} x i8] c";{{.*}}parallel_codegen.cpp;tmain;[[@LINE+7]];1;;\00"
+// CHECK-DEBUG-DAG: [[LOC1:@.+]] = private unnamed_addr constant [{{.+}} x i8] c";{{.*}}parallel_codegen.cpp;main;[[@LINE+19]];1;;\00"
+// CHECK-DEBUG-DAG: [[LOC2:@.+]] = private unnamed_addr constant [{{.+}} x i8] c";{{.*}}parallel_codegen.cpp;tmain;[[@LINE+8]];1;;\00"
template <class T>
void foo(T argc) {}
template <typename T>
int tmain(T argc) {
+ typedef double (*chunk_t)[argc[0][0]];
#pragma omp parallel
+ {
foo(argc);
+ chunk_t var;(void)var[0][0];
+ }
return 0;
}
@@ -90,7 +94,7 @@ int main (int argc, char **argv) {
// CHECK: define linkonce_odr {{[a-z\_\b]*[ ]?i32}} [[TMAIN]](i8** %argc)
// CHECK: store i8** %argc, i8*** [[ARGC_ADDR:%.+]],
-// CHECK-NEXT: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC_2]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i8***)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i8*** [[ARGC_ADDR]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC_2]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i8***, i64)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i8*** [[ARGC_ADDR]], i64 %{{.+}})
// CHECK-NEXT: ret i32 0
// CHECK-NEXT: }
// CHECK-DEBUG: define linkonce_odr i32 [[TMAIN]](i8** %argc)
@@ -101,23 +105,23 @@ int main (int argc, char **argv) {
// CHECK-DEBUG-NEXT: store i8** %argc, i8*** [[ARGC_ADDR:%.+]],
// CHECK-DEBUG: [[KMPC_LOC_PSOURCE_REF:%.+]] = getelementptr inbounds %struct.ident_t, %struct.ident_t* [[LOC_2_ADDR]], i32 0, i32 4
// CHECK-DEBUG-NEXT: store i8* getelementptr inbounds ([{{.+}} x i8], [{{.+}} x i8]* [[LOC2]], i32 0, i32 0), i8** [[KMPC_LOC_PSOURCE_REF]]
-// CHECK-DEBUG-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[LOC_2_ADDR]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i8***)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i8*** [[ARGC_ADDR]])
+// CHECK-DEBUG-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[LOC_2_ADDR]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i8***, i64)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i8*** [[ARGC_ADDR]], i64 %{{.+}})
// CHECK-DEBUG-NEXT: ret i32 0
// CHECK-DEBUG-NEXT: }
-// CHECK: define internal {{.*}}void [[OMP_OUTLINED]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i8*** dereferenceable({{4|8}}) %argc)
+// CHECK: define internal {{.*}}void [[OMP_OUTLINED]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i8*** dereferenceable({{4|8}}) %argc, i64 %{{.+}})
// CHECK: store i8*** %argc, i8**** [[ARGC_PTR_ADDR:%.+]],
// CHECK: [[ARGC_REF:%.+]] = load i8***, i8**** [[ARGC_PTR_ADDR]]
-// CHECK-NEXT: [[ARGC:%.+]] = load i8**, i8*** [[ARGC_REF]]
+// CHECK: [[ARGC:%.+]] = load i8**, i8*** [[ARGC_REF]]
// CHECK-NEXT: invoke {{.*}}void [[FOO1:@.+foo.+]](i8** [[ARGC]])
// CHECK: ret void
// CHECK: call {{.*}}void @{{.+terminate.*|abort}}(
// CHECK-NEXT: unreachable
// CHECK-NEXT: }
-// CHECK-DEBUG: define internal void [[OMP_OUTLINED_DEBUG:@.+]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i8*** dereferenceable({{4|8}}) %argc)
+// CHECK-DEBUG: define internal void [[OMP_OUTLINED_DEBUG:@.+]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i8*** dereferenceable({{4|8}}) %argc, i64 %{{.+}})
// CHECK-DEBUG: store i8*** %argc, i8**** [[ARGC_PTR_ADDR:%.+]],
// CHECK-DEBUG: [[ARGC_REF:%.+]] = load i8***, i8**** [[ARGC_PTR_ADDR]]
-// CHECK-DEBUG-NEXT: [[ARGC:%.+]] = load i8**, i8*** [[ARGC_REF]]
+// CHECK-DEBUG: [[ARGC:%.+]] = load i8**, i8*** [[ARGC_REF]]
// CHECK-DEBUG-NEXT: invoke void [[FOO1:@.+foo.+]](i8** [[ARGC]])
// CHECK-DEBUG: ret void
// CHECK-DEBUG: call void @{{.+terminate.*|abort}}(
@@ -126,7 +130,7 @@ int main (int argc, char **argv) {
// CHECK: define linkonce_odr {{.*}}void [[FOO1]](i8** %argc)
// CHECK-DEBUG-DAG: define linkonce_odr void [[FOO1]](i8** %argc)
-// CHECK-DEBUG-DAG: define internal void [[OMP_OUTLINED]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i8*** dereferenceable({{4|8}}) %argc)
+// CHECK-DEBUG-DAG: define internal void [[OMP_OUTLINED]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i8*** dereferenceable({{4|8}}) %argc, i64 %{{.+}})
// CHECK-DEBUG-DAG: call void [[OMP_OUTLINED_DEBUG]]({{[^)]+}}){{[^,]*}}, !dbg
// CHECK: attributes #[[FN_ATTRS]] = {{.+}} nounwind
OpenPOWER on IntegriCloud