Author: erichkeane Date: 2025-08-20T07:55:16-07:00 New Revision: 30fcf6984546ac7e14de63921792f9df3a124d09
URL: https://github.com/llvm/llvm-project/commit/30fcf6984546ac7e14de63921792f9df3a124d09 DIFF: https://github.com/llvm/llvm-project/commit/30fcf6984546ac7e14de63921792f9df3a124d09.diff LOG: [OpenACC] Fixup rules for reduction clause variable refererence type The standard is ambiguous, but we can only support arrays/array-sections/etc of the composite type, so make sure we enforce the rule that way. This will better support how we need to do lowering. Added: Modified: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaOpenACC.cpp clang/lib/Sema/SemaOpenACCClause.cpp clang/test/SemaOpenACC/combined-construct-reduction-clause.cpp clang/test/SemaOpenACC/compute-construct-reduction-clause.c clang/test/SemaOpenACC/compute-construct-reduction-clause.cpp clang/test/SemaOpenACC/loop-construct-reduction-clause.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index c733e8823cea6..8cc82c2c44c2f 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13368,16 +13368,23 @@ def err_acc_reduction_num_gangs_conflict "appear on a '%2' construct " "with a '%3' clause%select{ with more than 1 argument|}0">; def err_acc_reduction_type - : Error<"OpenACC 'reduction' variable must be of scalar type, aggregate, " - "sub-array, or a composite of scalar types;%select{| sub-array " - "base}1 type is %0">; -def err_acc_reduction_composite_type - : Error<"OpenACC 'reduction' variable must be a composite of scalar types; " - "%1 %select{is not a class or struct|is incomplete|is not an " - "aggregate}0">; -def err_acc_reduction_composite_member_type :Error< - "OpenACC 'reduction' composite variable must not have non-scalar field">; -def note_acc_reduction_composite_member_loc : Note<"invalid field is here">; + : Error<"invalid type %0 used in OpenACC 'reduction' variable reference; " + "type is %enum_select<OACCReductionTy>{%NotScalar{not a scalar " + "value, or array of scalars, or composite of " + "scalars}|%MemberNotScalar{not a scalar value}|%NotAgg{not an " + "aggregate}|%NotComplete{not a complete type}|%NotClassStruct{not " + "a class or struct}}1">; +def note_acc_reduction_array + : Note<"used as element type of " + "%enum_select<OACCReductionArray>{%Section{sub-array" + "}|%Subscript{array}|%ArrayTy{array}}0 type %1">; +def note_acc_reduction_member_of_composite + : Note<"used as field '%0' of composite '%1'">; +def note_acc_reduction_type_summary + : Note<"OpenACC 'reduction' variable reference must be a scalar variable " + "or a " + "composite of scalars, or an array, sub-array, or element of scalar " + "types">; def err_acc_loop_not_for_loop : Error<"OpenACC '%0' construct can only be applied to a 'for' loop">; def note_acc_construct_here : Note<"'%0' construct is here">; diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 07713992da352..1457522406531 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -690,9 +690,9 @@ ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr, } } } else if (CK == OpenACCClauseKind::Reduction) { - // TODO: OpenACC: - // Reduction must have copyctor + dtor + operation in InnerTy I think? - // Need to confirm when implementing this part. + // TODO: Reduction needs to be an aggregate, which gets checked later, so + // construction here isn't a problem. However, we need to make sure that we + // can compare it correctly still. } // All 3 things need to make sure they have a dtor. diff --git a/clang/lib/Sema/SemaOpenACCClause.cpp b/clang/lib/Sema/SemaOpenACCClause.cpp index af5fd38ed6eb8..43ae4f4d3011c 100644 --- a/clang/lib/Sema/SemaOpenACCClause.cpp +++ b/clang/lib/Sema/SemaOpenACCClause.cpp @@ -1930,61 +1930,95 @@ SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses, ExprResult SemaOpenACC::CheckReductionVar(OpenACCDirectiveKind DirectiveKind, OpenACCReductionOperator ReductionOp, Expr *VarExpr) { + // For now, we only support 'scalar' types, or composites/arrays of scalar + // types. VarExpr = VarExpr->IgnoreParenCasts(); + SourceLocation VarLoc = VarExpr->getBeginLoc(); + + SmallVector<PartialDiagnosticAt> Notes; + QualType CurType = VarExpr->getType(); + + // For array like things, the expression can either be an array element + // (subscript expr), array section, or array type. Peel those off, and add + // notes in case we find an illegal kind. We'll allow scalar or composite of + // scalars inside of this. + if (auto *ASE = dyn_cast<ArraySectionExpr>(VarExpr)) { + QualType BaseType = ArraySectionExpr::getBaseOriginalType(ASE); + + PartialDiagnostic PD = PDiag(diag::note_acc_reduction_array) + << diag::OACCReductionArray::Section << BaseType; + Notes.push_back({ASE->getBeginLoc(), PD}); + + CurType = getASTContext().getBaseElementType(BaseType); + } else if (auto *SubExpr = dyn_cast<ArraySubscriptExpr>(VarExpr)) { + // Array subscript already results in the type of the thing as its type, so + // there is no type to change here. + PartialDiagnostic PD = + PDiag(diag::note_acc_reduction_array) + << diag::OACCReductionArray::Subscript + << SubExpr->getBase()->IgnoreParenImpCasts()->getType(); + Notes.push_back({SubExpr->getBeginLoc(), PD}); + } else if (auto *AT = getASTContext().getAsArrayType(CurType)) { + // If we're already the array type, peel off the array and leave the element + // type. + CurType = getASTContext().getBaseElementType(AT); + PartialDiagnostic PD = PDiag(diag::note_acc_reduction_array) + << diag::OACCReductionArray::ArrayTy << CurType; + Notes.push_back({VarLoc, PD}); + } - auto TypeIsValid = [](QualType Ty) { + auto IsValidMemberOfComposite = [](QualType Ty) { return Ty->isDependentType() || Ty->isScalarType(); }; - if (isa<ArraySectionExpr>(VarExpr)) { - Expr *ASExpr = VarExpr; - QualType BaseTy = ArraySectionExpr::getBaseOriginalType(ASExpr); - QualType EltTy = getASTContext().getBaseElementType(BaseTy); + auto EmitDiags = [&](SourceLocation Loc, PartialDiagnostic PD) { + Diag(Loc, PD); - if (!TypeIsValid(EltTy)) { - Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_type) - << EltTy << /*Sub array base type*/ 1; - return ExprError(); - } - } else if (VarExpr->getType()->isArrayType()) { - // Arrays are considered an 'aggregate variable' explicitly, so are OK, no - // additional checking required. - // - // Glossary: Aggregate variables – a variable of any non-scalar datatype, - // including array or composite variables. - // - // The next branch (record decl) checks for composite variables. - } else if (auto *RD = VarExpr->getType()->getAsRecordDecl()) { + for (auto [Loc, PD] : Notes) + Diag(Loc, PD); + + Diag(VarLoc, diag::note_acc_reduction_type_summary); + }; + + // If the type is already scalar, or is dependent, just give up. + if (IsValidMemberOfComposite(CurType)) { + // Nothing to do here, is valid. + } else if (auto *RD = CurType->getAsRecordDecl()) { if (!RD->isStruct() && !RD->isClass()) { - Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type) - << /*not class or struct*/ 0 << VarExpr->getType(); + EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type) + << RD << diag::OACCReductionTy::NotClassStruct); return ExprError(); } if (!RD->isCompleteDefinition()) { - Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type) - << /*incomplete*/ 1 << VarExpr->getType(); + EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type) + << RD << diag::OACCReductionTy::NotComplete); return ExprError(); } + if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD); CXXRD && !CXXRD->isAggregate()) { - Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type) - << /*aggregate*/ 2 << VarExpr->getType(); + EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type) + << CXXRD << diag::OACCReductionTy::NotAgg); return ExprError(); } for (FieldDecl *FD : RD->fields()) { - if (!TypeIsValid(FD->getType())) { - Diag(VarExpr->getExprLoc(), - diag::err_acc_reduction_composite_member_type); - Diag(FD->getLocation(), diag::note_acc_reduction_composite_member_loc); + if (!IsValidMemberOfComposite(FD->getType())) { + PartialDiagnostic PD = + PDiag(diag::note_acc_reduction_member_of_composite) + << FD->getName() << RD->getName(); + Notes.push_back({FD->getBeginLoc(), PD}); + // TODO: member here.note_acc_reduction_member_of_composite + EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type) + << FD->getType() + << diag::OACCReductionTy::MemberNotScalar); return ExprError(); } } - } else if (!TypeIsValid(VarExpr->getType())) { - Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_type) - << VarExpr->getType() << /*Sub array base type*/ 0; - return ExprError(); + } else { + EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type) + << CurType << diag::OACCReductionTy::NotScalar); } // OpenACC3.3: 2.9.11: Reduction clauses on nested constructs for the same diff --git a/clang/test/SemaOpenACC/combined-construct-reduction-clause.cpp b/clang/test/SemaOpenACC/combined-construct-reduction-clause.cpp index 7b1a61e526871..1a5490766e77a 100644 --- a/clang/test/SemaOpenACC/combined-construct-reduction-clause.cpp +++ b/clang/test/SemaOpenACC/combined-construct-reduction-clause.cpp @@ -39,8 +39,9 @@ void uses(unsigned Parm) { #pragma acc kernels loop reduction(min: CoS, Array[I], Array[0:I]) for(int i = 0; i < 5; ++i); - // expected-error@+2{{OpenACC 'reduction' composite variable must not have non-scalar field}} - // expected-note@#COS_FIELD{{invalid field is here}} + // expected-error@+3{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}} + // expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}} + // expected-note@+1{{OpenACC 'reduction' variable reference must be a scalar variable or a composite of scalars, or an array, sub-array, or element of scalar types}} #pragma acc parallel loop reduction(&: ChC) for(int i = 0; i < 5; ++i); @@ -166,4 +167,24 @@ void uses(unsigned Parm) { #pragma acc parallel loop reduction(&:I) for(int i = 0; i < 5; ++i); } + + CompositeHasComposite CoCArr[5]; + // expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}} + // expected-note@+3{{used as element type of array type 'CompositeHasComposite'}} + // expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}} + // expected-note@+1{{OpenACC 'reduction' variable reference must be a scalar variable or a composite of scalars, or an array, sub-array, or element of scalar types}} +#pragma acc parallel loop reduction(+:CoCArr) + for(int i = 0; i < 5; ++i); + // expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}} + // expected-note@+3{{used as element type of array type 'CompositeHasComposite[5]'}} + // expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}} + // expected-note@+1{{OpenACC 'reduction' variable reference must be a scalar variable or a composite of scalars, or an array, sub-array, or element of scalar types}} +#pragma acc parallel loop reduction(+:CoCArr[3]) + for(int i = 0; i < 5; ++i); + // expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}} + // expected-note@+3{{used as element type of sub-array type 'CompositeHasComposite'}} + // expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}} + // expected-note@+1{{OpenACC 'reduction' variable reference must be a scalar variable or a composite of scalars, or an array, sub-array, or element of scalar types}} +#pragma acc parallel loop reduction(+:CoCArr[1:1]) + for(int i = 0; i < 5; ++i); } diff --git a/clang/test/SemaOpenACC/compute-construct-reduction-clause.c b/clang/test/SemaOpenACC/compute-construct-reduction-clause.c index 995b6d3d95eb0..ebced2b92feb8 100644 --- a/clang/test/SemaOpenACC/compute-construct-reduction-clause.c +++ b/clang/test/SemaOpenACC/compute-construct-reduction-clause.c @@ -63,8 +63,9 @@ void uses(unsigned Parm) { // Vars in a reduction must be a scalar or a composite of scalars. #pragma acc parallel reduction(&: CoS, I, F) while (1); - // expected-error@+2{{OpenACC 'reduction' composite variable must not have non-scalar field}} - // expected-note@#COS_FIELD{{invalid field is here}} + // expected-error@+3{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}} + // expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}} + // expected-note@+1{{OpenACC 'reduction' variable reference must be a scalar variable or a composite of scalars, or an array, sub-array, or element of scalar types}} #pragma acc parallel reduction(&: ChC) while (1); @@ -75,7 +76,10 @@ void uses(unsigned Parm) { while (1); struct CompositeHasComposite ChCArray[5]; - // expected-error@+1{{OpenACC 'reduction' variable must be of scalar type, aggregate, sub-array, or a composite of scalar types; sub-array base type is 'struct CompositeHasComposite'}} + // expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}} + // expected-note@+3{{used as element type of sub-array type 'struct CompositeHasComposite'}} + // expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}} + // expected-note@+1{{OpenACC 'reduction' variable reference must be a scalar variable or a composite of scalars, or an array, sub-array, or element of scalar types}} #pragma acc parallel reduction(&: CoS, Array[I], ChCArray[0:I]) while (1); diff --git a/clang/test/SemaOpenACC/compute-construct-reduction-clause.cpp b/clang/test/SemaOpenACC/compute-construct-reduction-clause.cpp index b40268c9b597d..924d19939d278 100644 --- a/clang/test/SemaOpenACC/compute-construct-reduction-clause.cpp +++ b/clang/test/SemaOpenACC/compute-construct-reduction-clause.cpp @@ -66,8 +66,9 @@ void uses(unsigned Parm) { // Vars in a reduction must be a scalar or a composite of scalars. #pragma acc parallel reduction(&: CoS, I, F) while (1); - // expected-error@+2{{OpenACC 'reduction' composite variable must not have non-scalar field}} - // expected-note@#COS_FIELD{{invalid field is here}} + // expected-error@+3{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}} + // expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}} + // expected-note@+1{{OpenACC 'reduction' variable reference must be a scalar variable or a composite of scalars, or an array, sub-array, or element of scalar types}} #pragma acc parallel reduction(&: ChC) while (1); #pragma acc parallel reduction(&: Array) @@ -91,6 +92,26 @@ void uses(unsigned Parm) { // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, or composite variable member}} #pragma acc parallel reduction(&: ChCPtr->COS) while (1); + + CompositeHasComposite CoCArr[5]; + // expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}} + // expected-note@+3{{used as element type of array type 'CompositeHasComposite'}} + // expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}} + // expected-note@+1{{OpenACC 'reduction' variable reference must be a scalar variable or a composite of scalars, or an array, sub-array, or element of scalar types}} +#pragma acc parallel reduction(+:CoCArr) + while (1); + // expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}} + // expected-note@+3{{used as element type of array type 'CompositeHasComposite[5]'}} + // expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}} + // expected-note@+1{{OpenACC 'reduction' variable reference must be a scalar variable or a composite of scalars, or an array, sub-array, or element of scalar types}} +#pragma acc parallel reduction(+:CoCArr[3]) + while (1); + // expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}} + // expected-note@+3{{used as element type of sub-array type 'CompositeHasComposite'}} + // expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}} + // expected-note@+1{{OpenACC 'reduction' variable reference must be a scalar variable or a composite of scalars, or an array, sub-array, or element of scalar types}} +#pragma acc parallel reduction(+:CoCArr[1:1]) + while (1); } template<typename T, typename U, typename V> @@ -135,8 +156,9 @@ void TemplUses(T Parm, U CoS, V ChC) { // Vars in a reduction must be a scalar or a composite of scalars. #pragma acc parallel reduction(&: CoS, Var, Parm) while (1); - // expected-error@+2{{OpenACC 'reduction' composite variable must not have non-scalar field}} - // expected-note@#COS_FIELD{{invalid field is here}} + // expected-error@+3{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}} + // expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}} + // expected-note@+1{{OpenACC 'reduction' variable reference must be a scalar variable or a composite of scalars, or an array, sub-array, or element of scalar types}} #pragma acc parallel reduction(&: ChC) while (1); #pragma acc parallel reduction(&: Array) diff --git a/clang/test/SemaOpenACC/loop-construct-reduction-clause.cpp b/clang/test/SemaOpenACC/loop-construct-reduction-clause.cpp index 00bcd744b9e79..4e885166be318 100644 --- a/clang/test/SemaOpenACC/loop-construct-reduction-clause.cpp +++ b/clang/test/SemaOpenACC/loop-construct-reduction-clause.cpp @@ -42,8 +42,9 @@ void uses() { #pragma acc serial { - // expected-error@+2{{OpenACC 'reduction' composite variable must not have non-scalar field}} - // expected-note@#COS_FIELD{{invalid field is here}} + // expected-error@+3{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}} + // expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}} + // expected-note@+1{{OpenACC 'reduction' variable reference must be a scalar variable or a composite of scalars, or an array, sub-array, or element of scalar types}} #pragma acc loop reduction(+:ChC) for(int i = 0; i < 5; ++i){} } @@ -153,6 +154,26 @@ void uses() { for(int i = 0; i < 5; ++i) { } } + + CompositeHasComposite CoCArr[5]; + // expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}} + // expected-note@+3{{used as element type of array type 'CompositeHasComposite'}} + // expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}} + // expected-note@+1{{OpenACC 'reduction' variable reference must be a scalar variable or a composite of scalars, or an array, sub-array, or element of scalar types}} +#pragma acc loop reduction(+:CoCArr) + for(int i = 0; i < 5; ++i); + // expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}} + // expected-note@+3{{used as element type of array type 'CompositeHasComposite[5]'}} + // expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}} + // expected-note@+1{{OpenACC 'reduction' variable reference must be a scalar variable or a composite of scalars, or an array, sub-array, or element of scalar types}} +#pragma acc loop reduction(+:CoCArr[3]) + for(int i = 0; i < 5; ++i); + // expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}} + // expected-note@+3{{used as element type of sub-array type 'CompositeHasComposite'}} + // expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}} + // expected-note@+1{{OpenACC 'reduction' variable reference must be a scalar variable or a composite of scalars, or an array, sub-array, or element of scalar types}} +#pragma acc loop reduction(+:CoCArr[1:1]) + for(int i = 0; i < 5; ++i); } template<typename IntTy, typename CoSTy, typename ChCTy, unsigned One, @@ -177,8 +198,9 @@ void templ_uses() { #pragma acc serial { - // expected-error@+2{{OpenACC 'reduction' composite variable must not have non-scalar field}} - // expected-note@#COS_FIELD{{invalid field is here}} + // expected-error@+3{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}} + // expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}} + // expected-note@+1{{OpenACC 'reduction' variable reference must be a scalar variable or a composite of scalars, or an array, sub-array, or element of scalar types}} #pragma acc loop reduction(+:ChC) for(int i = 0; i < 5; ++i){} } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits