(UB && UB->isValueDependent()) || (Step && Step->isValueDependent());
}
+template <typename T>
+static T *getExprAsWritten(T *E) {
+ if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(E))
+ E = ExprTemp->getSubExpr();
+
+ if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
+ E = MTE->GetTemporaryExpr();
+
+ while (auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
+ E = Binder->getSubExpr();
+
+ if (auto *ICE = dyn_cast<ImplicitCastExpr>(E))
+ E = ICE->getSubExprAsWritten();
+ return E->IgnoreParens();
+}
+
bool OpenMPIterationSpaceChecker::SetVarAndLB(VarDecl *NewVar,
DeclRefExpr *NewVarRefExpr,
Expr *NewLB) {
return true;
Var = NewVar;
VarRef = NewVarRefExpr;
+ if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
+ if (const CXXConstructorDecl *Ctor = CE->getConstructor())
+ if (Ctor->isCopyConstructor() && CE->getNumArgs() == 1 &&
+ CE->getArg(0) != nullptr)
+ NewLB = CE->getArg(0)->IgnoreParenImpCasts();
LB = NewLB;
return false;
}
static const VarDecl *GetInitVarDecl(const Expr *E) {
if (!E)
return nullptr;
- E = E->IgnoreParenImpCasts();
+ E = getExprAsWritten(E);
if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
if (const CXXConstructorDecl *Ctor = CE->getConstructor())
if (Ctor->isCopyConstructor() && CE->getNumArgs() == 1 &&
SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond) << Var;
return true;
}
- S = S->IgnoreParenImpCasts();
+ S = getExprAsWritten(S);
SourceLocation CondLoc = S->getLocStart();
if (auto BO = dyn_cast<BinaryOperator>(S)) {
if (BO->isRelationalOp()) {
S, DefaultLoc, TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
: (TestIsStrictOp ? BO_GT : BO_GE),
LB, UB);
+ if (CondExpr.isUsable()) {
+ CondExpr = SemaRef.PerformImplicitConversion(
+ CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
+ /*AllowExplicit=*/true);
+ }
SemaRef.getDiagnostics().setSuppressAllDiagnostics(Suppress);
// Otherwise use original loop conditon and evaluate it in runtime.
return CondExpr.isUsable() ? CondExpr.get() : Cond;
Built.IterationVarRef = IV.get();
Built.LastIteration = LastIteration.get();
Built.NumIterations = NumIterations.get();
- Built.CalcLastIteration = CalcLastIteration.get();
+ Built.CalcLastIteration =
+ SemaRef.ActOnFinishFullExpr(CalcLastIteration.get()).get();
Built.PreCond = PreCond.get();
Built.Cond = Cond.get();
Built.Init = Init.get();
// CHECK: store i8 [[I_VAL]], i8* [[K]]
// CHECK-NOT: [[I]]
// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: call void @__kmpc_barrier(
#pragma omp for
for (i = 0; i < 2; ++i) {
k = i;
}
}
-#endif // HEADER
+struct Bool {
+ Bool(bool b) : b(b) {}
+ operator bool() const { return b; }
+ const bool b;
+};
+
+template <typename T>
+struct It {
+ It() : p(0) {}
+ It(const It &) ;
+ It(It &) ;
+ It &operator=(const It &);
+ It &operator=(It &);
+ ~It() {}
+
+ It(T *p) : p(p) {}
+
+ operator T *&() { return p; }
+ operator T *() const { return p; }
+ T *operator->() const { return p; }
+
+ It &operator++() { ++p; return *this; }
+ It &operator--() { --p; return *this; }
+ It &operator+=(unsigned n) { p += n; return *this; }
+ It &operator-=(unsigned n) { p -= n; return *this; }
+
+ T *p;
+};
+
+template <typename T>
+It<T> operator+(It<T> a, typename It<T>::difference_type n) { return a.p + n; }
+
+template <typename T>
+It<T> operator+(typename It<T>::difference_type n, It<T> a) { return a.p + n; }
+
+template <typename T>
+It<T> operator-(It<T> a, typename It<T>::difference_type n) { return a.p - n; }
+typedef Bool BoolType;
+
+template <typename T>
+BoolType operator<(It<T> a, It<T> b) { return a.p < b.p; }
+
+void loop_with_It(It<char> begin, It<char> end) {
+#pragma omp for
+ for (It<char> it = begin; it < end; ++it) {
+ *it = 0;
+ }
+}
+
+// CHECK-LABEL: loop_with_It
+// CHECK: call i32 @__kmpc_global_thread_num(
+// CHECK: call void @__kmpc_for_static_init_8(
+// CHECK: call void @__kmpc_for_static_fini(
+
+#endif // HEADER