Skip to content

Commit 30fcf69

Browse files
committed
[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.
1 parent 40e1510 commit 30fcf69

File tree

7 files changed

+169
-59
lines changed

7 files changed

+169
-59
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13368,16 +13368,23 @@ def err_acc_reduction_num_gangs_conflict
1336813368
"appear on a '%2' construct "
1336913369
"with a '%3' clause%select{ with more than 1 argument|}0">;
1337013370
def err_acc_reduction_type
13371-
: Error<"OpenACC 'reduction' variable must be of scalar type, aggregate, "
13372-
"sub-array, or a composite of scalar types;%select{| sub-array "
13373-
"base}1 type is %0">;
13374-
def err_acc_reduction_composite_type
13375-
: Error<"OpenACC 'reduction' variable must be a composite of scalar types; "
13376-
"%1 %select{is not a class or struct|is incomplete|is not an "
13377-
"aggregate}0">;
13378-
def err_acc_reduction_composite_member_type :Error<
13379-
"OpenACC 'reduction' composite variable must not have non-scalar field">;
13380-
def note_acc_reduction_composite_member_loc : Note<"invalid field is here">;
13371+
: Error<"invalid type %0 used in OpenACC 'reduction' variable reference; "
13372+
"type is %enum_select<OACCReductionTy>{%NotScalar{not a scalar "
13373+
"value, or array of scalars, or composite of "
13374+
"scalars}|%MemberNotScalar{not a scalar value}|%NotAgg{not an "
13375+
"aggregate}|%NotComplete{not a complete type}|%NotClassStruct{not "
13376+
"a class or struct}}1">;
13377+
def note_acc_reduction_array
13378+
: Note<"used as element type of "
13379+
"%enum_select<OACCReductionArray>{%Section{sub-array"
13380+
"}|%Subscript{array}|%ArrayTy{array}}0 type %1">;
13381+
def note_acc_reduction_member_of_composite
13382+
: Note<"used as field '%0' of composite '%1'">;
13383+
def note_acc_reduction_type_summary
13384+
: Note<"OpenACC 'reduction' variable reference must be a scalar variable "
13385+
"or a "
13386+
"composite of scalars, or an array, sub-array, or element of scalar "
13387+
"types">;
1338113388
def err_acc_loop_not_for_loop
1338213389
: Error<"OpenACC '%0' construct can only be applied to a 'for' loop">;
1338313390
def note_acc_construct_here : Note<"'%0' construct is here">;

clang/lib/Sema/SemaOpenACC.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -690,9 +690,9 @@ ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr,
690690
}
691691
}
692692
} else if (CK == OpenACCClauseKind::Reduction) {
693-
// TODO: OpenACC:
694-
// Reduction must have copyctor + dtor + operation in InnerTy I think?
695-
// Need to confirm when implementing this part.
693+
// TODO: Reduction needs to be an aggregate, which gets checked later, so
694+
// construction here isn't a problem. However, we need to make sure that we
695+
// can compare it correctly still.
696696
}
697697

698698
// All 3 things need to make sure they have a dtor.

clang/lib/Sema/SemaOpenACCClause.cpp

Lines changed: 67 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1930,61 +1930,95 @@ SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
19301930
ExprResult SemaOpenACC::CheckReductionVar(OpenACCDirectiveKind DirectiveKind,
19311931
OpenACCReductionOperator ReductionOp,
19321932
Expr *VarExpr) {
1933+
// For now, we only support 'scalar' types, or composites/arrays of scalar
1934+
// types.
19331935
VarExpr = VarExpr->IgnoreParenCasts();
1936+
SourceLocation VarLoc = VarExpr->getBeginLoc();
1937+
1938+
SmallVector<PartialDiagnosticAt> Notes;
1939+
QualType CurType = VarExpr->getType();
1940+
1941+
// For array like things, the expression can either be an array element
1942+
// (subscript expr), array section, or array type. Peel those off, and add
1943+
// notes in case we find an illegal kind. We'll allow scalar or composite of
1944+
// scalars inside of this.
1945+
if (auto *ASE = dyn_cast<ArraySectionExpr>(VarExpr)) {
1946+
QualType BaseType = ArraySectionExpr::getBaseOriginalType(ASE);
1947+
1948+
PartialDiagnostic PD = PDiag(diag::note_acc_reduction_array)
1949+
<< diag::OACCReductionArray::Section << BaseType;
1950+
Notes.push_back({ASE->getBeginLoc(), PD});
1951+
1952+
CurType = getASTContext().getBaseElementType(BaseType);
1953+
} else if (auto *SubExpr = dyn_cast<ArraySubscriptExpr>(VarExpr)) {
1954+
// Array subscript already results in the type of the thing as its type, so
1955+
// there is no type to change here.
1956+
PartialDiagnostic PD =
1957+
PDiag(diag::note_acc_reduction_array)
1958+
<< diag::OACCReductionArray::Subscript
1959+
<< SubExpr->getBase()->IgnoreParenImpCasts()->getType();
1960+
Notes.push_back({SubExpr->getBeginLoc(), PD});
1961+
} else if (auto *AT = getASTContext().getAsArrayType(CurType)) {
1962+
// If we're already the array type, peel off the array and leave the element
1963+
// type.
1964+
CurType = getASTContext().getBaseElementType(AT);
1965+
PartialDiagnostic PD = PDiag(diag::note_acc_reduction_array)
1966+
<< diag::OACCReductionArray::ArrayTy << CurType;
1967+
Notes.push_back({VarLoc, PD});
1968+
}
19341969

1935-
auto TypeIsValid = [](QualType Ty) {
1970+
auto IsValidMemberOfComposite = [](QualType Ty) {
19361971
return Ty->isDependentType() || Ty->isScalarType();
19371972
};
19381973

1939-
if (isa<ArraySectionExpr>(VarExpr)) {
1940-
Expr *ASExpr = VarExpr;
1941-
QualType BaseTy = ArraySectionExpr::getBaseOriginalType(ASExpr);
1942-
QualType EltTy = getASTContext().getBaseElementType(BaseTy);
1974+
auto EmitDiags = [&](SourceLocation Loc, PartialDiagnostic PD) {
1975+
Diag(Loc, PD);
19431976

1944-
if (!TypeIsValid(EltTy)) {
1945-
Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_type)
1946-
<< EltTy << /*Sub array base type*/ 1;
1947-
return ExprError();
1948-
}
1949-
} else if (VarExpr->getType()->isArrayType()) {
1950-
// Arrays are considered an 'aggregate variable' explicitly, so are OK, no
1951-
// additional checking required.
1952-
//
1953-
// Glossary: Aggregate variables – a variable of any non-scalar datatype,
1954-
// including array or composite variables.
1955-
//
1956-
// The next branch (record decl) checks for composite variables.
1957-
} else if (auto *RD = VarExpr->getType()->getAsRecordDecl()) {
1977+
for (auto [Loc, PD] : Notes)
1978+
Diag(Loc, PD);
1979+
1980+
Diag(VarLoc, diag::note_acc_reduction_type_summary);
1981+
};
1982+
1983+
// If the type is already scalar, or is dependent, just give up.
1984+
if (IsValidMemberOfComposite(CurType)) {
1985+
// Nothing to do here, is valid.
1986+
} else if (auto *RD = CurType->getAsRecordDecl()) {
19581987
if (!RD->isStruct() && !RD->isClass()) {
1959-
Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type)
1960-
<< /*not class or struct*/ 0 << VarExpr->getType();
1988+
EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type)
1989+
<< RD << diag::OACCReductionTy::NotClassStruct);
19611990
return ExprError();
19621991
}
19631992

19641993
if (!RD->isCompleteDefinition()) {
1965-
Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type)
1966-
<< /*incomplete*/ 1 << VarExpr->getType();
1994+
EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type)
1995+
<< RD << diag::OACCReductionTy::NotComplete);
19671996
return ExprError();
19681997
}
1998+
19691999
if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
19702000
CXXRD && !CXXRD->isAggregate()) {
1971-
Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type)
1972-
<< /*aggregate*/ 2 << VarExpr->getType();
2001+
EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type)
2002+
<< CXXRD << diag::OACCReductionTy::NotAgg);
19732003
return ExprError();
19742004
}
19752005

19762006
for (FieldDecl *FD : RD->fields()) {
1977-
if (!TypeIsValid(FD->getType())) {
1978-
Diag(VarExpr->getExprLoc(),
1979-
diag::err_acc_reduction_composite_member_type);
1980-
Diag(FD->getLocation(), diag::note_acc_reduction_composite_member_loc);
2007+
if (!IsValidMemberOfComposite(FD->getType())) {
2008+
PartialDiagnostic PD =
2009+
PDiag(diag::note_acc_reduction_member_of_composite)
2010+
<< FD->getName() << RD->getName();
2011+
Notes.push_back({FD->getBeginLoc(), PD});
2012+
// TODO: member here.note_acc_reduction_member_of_composite
2013+
EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type)
2014+
<< FD->getType()
2015+
<< diag::OACCReductionTy::MemberNotScalar);
19812016
return ExprError();
19822017
}
19832018
}
1984-
} else if (!TypeIsValid(VarExpr->getType())) {
1985-
Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_type)
1986-
<< VarExpr->getType() << /*Sub array base type*/ 0;
1987-
return ExprError();
2019+
} else {
2020+
EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type)
2021+
<< CurType << diag::OACCReductionTy::NotScalar);
19882022
}
19892023

19902024
// OpenACC3.3: 2.9.11: Reduction clauses on nested constructs for the same

clang/test/SemaOpenACC/combined-construct-reduction-clause.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ void uses(unsigned Parm) {
3939
#pragma acc kernels loop reduction(min: CoS, Array[I], Array[0:I])
4040
for(int i = 0; i < 5; ++i);
4141

42-
// expected-error@+2{{OpenACC 'reduction' composite variable must not have non-scalar field}}
43-
// expected-note@#COS_FIELD{{invalid field is here}}
42+
// expected-error@+3{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}}
43+
// expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}}
44+
// 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}}
4445
#pragma acc parallel loop reduction(&: ChC)
4546
for(int i = 0; i < 5; ++i);
4647

@@ -166,4 +167,24 @@ void uses(unsigned Parm) {
166167
#pragma acc parallel loop reduction(&:I)
167168
for(int i = 0; i < 5; ++i);
168169
}
170+
171+
CompositeHasComposite CoCArr[5];
172+
// expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}}
173+
// expected-note@+3{{used as element type of array type 'CompositeHasComposite'}}
174+
// expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}}
175+
// 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}}
176+
#pragma acc parallel loop reduction(+:CoCArr)
177+
for(int i = 0; i < 5; ++i);
178+
// expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}}
179+
// expected-note@+3{{used as element type of array type 'CompositeHasComposite[5]'}}
180+
// expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}}
181+
// 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}}
182+
#pragma acc parallel loop reduction(+:CoCArr[3])
183+
for(int i = 0; i < 5; ++i);
184+
// expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}}
185+
// expected-note@+3{{used as element type of sub-array type 'CompositeHasComposite'}}
186+
// expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}}
187+
// 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}}
188+
#pragma acc parallel loop reduction(+:CoCArr[1:1])
189+
for(int i = 0; i < 5; ++i);
169190
}

clang/test/SemaOpenACC/compute-construct-reduction-clause.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ void uses(unsigned Parm) {
6363
// Vars in a reduction must be a scalar or a composite of scalars.
6464
#pragma acc parallel reduction(&: CoS, I, F)
6565
while (1);
66-
// expected-error@+2{{OpenACC 'reduction' composite variable must not have non-scalar field}}
67-
// expected-note@#COS_FIELD{{invalid field is here}}
66+
// expected-error@+3{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}}
67+
// expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}}
68+
// 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}}
6869
#pragma acc parallel reduction(&: ChC)
6970
while (1);
7071

@@ -75,7 +76,10 @@ void uses(unsigned Parm) {
7576
while (1);
7677

7778
struct CompositeHasComposite ChCArray[5];
78-
// 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'}}
79+
// expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}}
80+
// expected-note@+3{{used as element type of sub-array type 'struct CompositeHasComposite'}}
81+
// expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}}
82+
// 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}}
7983
#pragma acc parallel reduction(&: CoS, Array[I], ChCArray[0:I])
8084
while (1);
8185

clang/test/SemaOpenACC/compute-construct-reduction-clause.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,9 @@ void uses(unsigned Parm) {
6666
// Vars in a reduction must be a scalar or a composite of scalars.
6767
#pragma acc parallel reduction(&: CoS, I, F)
6868
while (1);
69-
// expected-error@+2{{OpenACC 'reduction' composite variable must not have non-scalar field}}
70-
// expected-note@#COS_FIELD{{invalid field is here}}
69+
// expected-error@+3{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}}
70+
// expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}}
71+
// 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}}
7172
#pragma acc parallel reduction(&: ChC)
7273
while (1);
7374
#pragma acc parallel reduction(&: Array)
@@ -91,6 +92,26 @@ void uses(unsigned Parm) {
9192
// expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, or composite variable member}}
9293
#pragma acc parallel reduction(&: ChCPtr->COS)
9394
while (1);
95+
96+
CompositeHasComposite CoCArr[5];
97+
// expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}}
98+
// expected-note@+3{{used as element type of array type 'CompositeHasComposite'}}
99+
// expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}}
100+
// 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}}
101+
#pragma acc parallel reduction(+:CoCArr)
102+
while (1);
103+
// expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}}
104+
// expected-note@+3{{used as element type of array type 'CompositeHasComposite[5]'}}
105+
// expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}}
106+
// 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}}
107+
#pragma acc parallel reduction(+:CoCArr[3])
108+
while (1);
109+
// expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}}
110+
// expected-note@+3{{used as element type of sub-array type 'CompositeHasComposite'}}
111+
// expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}}
112+
// 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}}
113+
#pragma acc parallel reduction(+:CoCArr[1:1])
114+
while (1);
94115
}
95116

96117
template<typename T, typename U, typename V>
@@ -135,8 +156,9 @@ void TemplUses(T Parm, U CoS, V ChC) {
135156
// Vars in a reduction must be a scalar or a composite of scalars.
136157
#pragma acc parallel reduction(&: CoS, Var, Parm)
137158
while (1);
138-
// expected-error@+2{{OpenACC 'reduction' composite variable must not have non-scalar field}}
139-
// expected-note@#COS_FIELD{{invalid field is here}}
159+
// expected-error@+3{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}}
160+
// expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}}
161+
// 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}}
140162
#pragma acc parallel reduction(&: ChC)
141163
while (1);
142164
#pragma acc parallel reduction(&: Array)

clang/test/SemaOpenACC/loop-construct-reduction-clause.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ void uses() {
4242

4343
#pragma acc serial
4444
{
45-
// expected-error@+2{{OpenACC 'reduction' composite variable must not have non-scalar field}}
46-
// expected-note@#COS_FIELD{{invalid field is here}}
45+
// expected-error@+3{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}}
46+
// expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}}
47+
// 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}}
4748
#pragma acc loop reduction(+:ChC)
4849
for(int i = 0; i < 5; ++i){}
4950
}
@@ -153,6 +154,26 @@ void uses() {
153154
for(int i = 0; i < 5; ++i) {
154155
}
155156
}
157+
158+
CompositeHasComposite CoCArr[5];
159+
// expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}}
160+
// expected-note@+3{{used as element type of array type 'CompositeHasComposite'}}
161+
// expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}}
162+
// 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}}
163+
#pragma acc loop reduction(+:CoCArr)
164+
for(int i = 0; i < 5; ++i);
165+
// expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}}
166+
// expected-note@+3{{used as element type of array type 'CompositeHasComposite[5]'}}
167+
// expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}}
168+
// 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}}
169+
#pragma acc loop reduction(+:CoCArr[3])
170+
for(int i = 0; i < 5; ++i);
171+
// expected-error@+4{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}}
172+
// expected-note@+3{{used as element type of sub-array type 'CompositeHasComposite'}}
173+
// expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}}
174+
// 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}}
175+
#pragma acc loop reduction(+:CoCArr[1:1])
176+
for(int i = 0; i < 5; ++i);
156177
}
157178

158179
template<typename IntTy, typename CoSTy, typename ChCTy, unsigned One,
@@ -177,8 +198,9 @@ void templ_uses() {
177198

178199
#pragma acc serial
179200
{
180-
// expected-error@+2{{OpenACC 'reduction' composite variable must not have non-scalar field}}
181-
// expected-note@#COS_FIELD{{invalid field is here}}
201+
// expected-error@+3{{invalid type 'struct CompositeOfScalars' used in OpenACC 'reduction' variable reference; type is not a scalar value}}
202+
// expected-note@#COS_FIELD{{used as field 'COS' of composite 'CompositeHasComposite'}}
203+
// 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}}
182204
#pragma acc loop reduction(+:ChC)
183205
for(int i = 0; i < 5; ++i){}
184206
}

0 commit comments

Comments
 (0)