diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -655,9 +655,13 @@ InitRVal = RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); break; - case TEK_Aggregate: - InitRVal = RValue::getAggregate(LV.getAddress(CGF)); - break; + case TEK_Aggregate: { + OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_LValue); + CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, LV); + CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), + /*IsInitializer=*/false); + return; + } } OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue); CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -16567,8 +16567,7 @@ } if (RHSVD->isInvalidDecl()) continue; - if (!RHSVD->hasInit() && - (DeclareReductionRef.isUnset() || !S.LangOpts.CPlusPlus)) { + if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) { S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible) << Type << ReductionIdRange; bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) == diff --git a/clang/test/OpenMP/declare_reduction_ast_print.c b/clang/test/OpenMP/declare_reduction_ast_print.c --- a/clang/test/OpenMP/declare_reduction_ast_print.c +++ b/clang/test/OpenMP/declare_reduction_ast_print.c @@ -47,13 +47,18 @@ : omp_out = omp_out > omp_in ? omp_in : omp_out) \ initializer(omp_priv = 2147483647) +#pragma omp declare reduction(mymin \ + : struct SSS \ + : omp_out = omp_out.field > omp_in.field ? omp_in : omp_out) + int foo(int argc, char **argv) { int x; -#pragma omp parallel for reduction(mymin : x) + struct SSS ss; +#pragma omp parallel for reduction(mymin : x, ss) for (int i = 0; i < 1000; i++) ; return 0; } -// CHECK: #pragma omp parallel for reduction(mymin: x) +// CHECK: #pragma omp parallel for reduction(mymin: x,ss) #endif diff --git a/clang/test/OpenMP/declare_reduction_codegen.c b/clang/test/OpenMP/declare_reduction_codegen.c --- a/clang/test/OpenMP/declare_reduction_codegen.c +++ b/clang/test/OpenMP/declare_reduction_codegen.c @@ -17,6 +17,9 @@ // CHECK: [[SSS_INT:.+]] = type { i32 } // CHECK-LOAD: [[SSS_INT:.+]] = type { i32 } +// CHECK-DAG: [[SSS_INIT:@.+]] = private constant %struct.SSS zeroinitializer +// CHECK-DAG: [[INT_INIT:@.+]] = private constant i32 0 + #pragma omp declare reduction(+ : int, char : omp_out *= omp_in) // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias %0, i32* noalias %1) // CHECK: [[MUL:%.+]] = mul nsw i32 @@ -163,4 +166,27 @@ // OMP45-LOAD-NEXT: store i8 [[TRUNC]], i8* // OMP45-LOAD-NEXT: ret void // OMP45-LOAD-NEXT: } + +// CHECK-LABEL: bar +struct SSS ss; +int in; +void bar() { + // CHECK: [[SS_PRIV:%.+]] = alloca %struct.SSS, + // CHECK: [[IN_PRIV:%.+]] = alloca i32, + // CHECK: [[BC:%.+]] = bitcast %struct.SSS* [[SS_PRIV]] to i8* + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC]], i8* align 4 bitcast (%struct.SSS* [[SSS_INIT]] to i8*), i64 4, i1 false) + // CHECK: [[IN_VAL:%.+]] = load i32, i32* [[INT_INIT]], + // CHECK: store i32 [[IN_VAL]], i32* [[IN_PRIV]], + // CHECK: call void @__kmpc_for_static_init_4( +#pragma omp declare reduction(+ \ + : struct SSS \ + : omp_out = omp_in) +#pragma omp declare reduction(+ \ + : int \ + : omp_out = omp_in) +#pragma omp for reduction(+ \ + : ss, in) + for (int i = 0; i < 10; ++i) + ; +} #endif diff --git a/clang/test/OpenMP/declare_reduction_messages.c b/clang/test/OpenMP/declare_reduction_messages.c --- a/clang/test/OpenMP/declare_reduction_messages.c +++ b/clang/test/OpenMP/declare_reduction_messages.c @@ -49,9 +49,9 @@ #pragma omp declare reduction(|: struct S: omp_out.s += omp_in.s) initializer(omp_priv = { 0 }) int fun(int arg) { - struct S s;// expected-note {{'s' defined here}} + struct S s; s.s = 0; -#pragma omp parallel for reduction(+ : s) // expected-error {{list item of type 'struct S' is not valid for specified reduction operation: unable to provide default initialization value}} +#pragma omp parallel for reduction(+ : s) for (arg = 0; arg < 10; ++arg) s.s += arg; #pragma omp declare reduction(red : int : omp_out++)