]> granicus.if.org Git - clang/commitdiff
[OPENMP] Allow to use compound assignment operators.
authorAlexey Bataev <a.bataev@hotmail.com>
Tue, 16 Feb 2016 12:13:49 +0000 (12:13 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Tue, 16 Feb 2016 12:13:49 +0000 (12:13 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@260957 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaOpenMP.cpp
test/OpenMP/for_loop_messages.cpp

index 33f809b5d7b60df3306dcada075b5f5cf40d7073..e63b40b80d0c15a3ea9e2490d08ebe6d52898f24 100644 (file)
@@ -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);
+  }
+
+  // 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.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
+    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;
 }
 
index 895baf57e9ccc40554f3588993346dfb1931aa11..019b9849b38fa2e1576acb874e61e709807f8e36 100644 (file)
@@ -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;
 }