forked from OSchip/llvm-project
[OPENMP] Allow to use compound assignment operators.
Loop-based directives allow to use iterators as loop counters. Iterators are allowed to define their own operators. This patch allows to use compound assignment operators for iterators. llvm-svn: 260957
This commit is contained in:
parent
6a7c3e4bac
commit
c0214e0e87
|
@ -4072,7 +4072,8 @@ static ExprResult BuildCounterUpdate(Sema &SemaRef, Scope *S,
|
|||
if (!Update.isUsable())
|
||||
return ExprError();
|
||||
|
||||
// Build 'VarRef = Start + Iter * Step'.
|
||||
// Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
|
||||
// 'VarRef = Start (+|-) Iter * Step'.
|
||||
auto NewStart = Transform.TransformExpr(Start.get()->IgnoreImplicit());
|
||||
if (NewStart.isInvalid())
|
||||
return ExprError();
|
||||
|
@ -4082,17 +4083,43 @@ static ExprResult BuildCounterUpdate(Sema &SemaRef, Scope *S,
|
|||
/*AllowExplicit=*/true);
|
||||
if (NewStart.isInvalid())
|
||||
return ExprError();
|
||||
Update = SemaRef.BuildBinOp(S, Loc, (Subtract ? BO_Sub : BO_Add),
|
||||
NewStart.get(), Update.get());
|
||||
if (!Update.isUsable())
|
||||
return ExprError();
|
||||
|
||||
Update = SemaRef.PerformImplicitConversion(
|
||||
Update.get(), VarRef.get()->getType(), Sema::AA_Converting, true);
|
||||
if (!Update.isUsable())
|
||||
return ExprError();
|
||||
// First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
|
||||
ExprResult SavedUpdate = Update;
|
||||
ExprResult UpdateVal;
|
||||
if (VarRef.get()->getType()->isOverloadableType() ||
|
||||
NewStart.get()->getType()->isOverloadableType() ||
|
||||
Update.get()->getType()->isOverloadableType()) {
|
||||
bool Suppress = SemaRef.getDiagnostics().getSuppressAllDiagnostics();
|
||||
SemaRef.getDiagnostics().setSuppressAllDiagnostics(/*Val=*/true);
|
||||
Update =
|
||||
SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
|
||||
if (Update.isUsable()) {
|
||||
UpdateVal =
|
||||
SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
|
||||
VarRef.get(), SavedUpdate.get());
|
||||
if (UpdateVal.isUsable()) {
|
||||
Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
|
||||
UpdateVal.get());
|
||||
}
|
||||
}
|
||||
SemaRef.getDiagnostics().setSuppressAllDiagnostics(Suppress);
|
||||
}
|
||||
|
||||
Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
|
||||
// Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
|
||||
if (!Update.isUsable() || !UpdateVal.isUsable()) {
|
||||
Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
|
||||
NewStart.get(), SavedUpdate.get());
|
||||
if (!Update.isUsable())
|
||||
return ExprError();
|
||||
|
||||
Update = SemaRef.PerformImplicitConversion(
|
||||
Update.get(), VarRef.get()->getType(), Sema::AA_Converting, true);
|
||||
if (!Update.isUsable())
|
||||
return ExprError();
|
||||
|
||||
Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
|
||||
}
|
||||
return Update;
|
||||
}
|
||||
|
||||
|
|
|
@ -426,6 +426,19 @@ public:
|
|||
typedef int difference_type;
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
};
|
||||
class GoodIter1 {
|
||||
public:
|
||||
GoodIter1() {}
|
||||
GoodIter1(const GoodIter1 &) {}
|
||||
GoodIter1 &operator++(int) { return *this; }
|
||||
GoodIter1 &operator=(const GoodIter1 &that) { return *this; }
|
||||
GoodIter1 &operator+=(int x) { return *this; }
|
||||
friend long operator-(const GoodIter1 &, const GoodIter1 &);
|
||||
GoodIter1 &operator-(int) { return *this; }
|
||||
bool operator<(GoodIter1 a) { return true; }
|
||||
typedef int difference_type;
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
};
|
||||
// expected-note@+2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 2nd argument}}
|
||||
// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
|
||||
int operator-(GoodIter a, GoodIter b) { return 0; }
|
||||
|
@ -572,6 +585,10 @@ int test_with_random_access_iterator() {
|
|||
#pragma omp for
|
||||
for (Iter1 I; I < end1; ++I) {
|
||||
}
|
||||
GoodIter1 I1, E1;
|
||||
#pragma omp for
|
||||
for (GoodIter1 I = I1; I < E1; I++)
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue