Hahnfeld created this revision.
Hahnfeld added reviewers: ABataev, hfinkel, carlo.bertolli, sfantao.
Hahnfeld added a subscriber: cfe-commits.

Pointer dereference is equal to access of first array element which is already 
allowed for the `reduction` clause.

While at it also add test for CodeGen of reduction on array element which 
seemed to be missing.

http://reviews.llvm.org/D18276

Files:
  lib/CodeGen/CGStmtOpenMP.cpp
  lib/Sema/SemaOpenMP.cpp
  test/OpenMP/for_reduction_codegen.cpp
  test/OpenMP/for_reduction_messages.cpp
  test/OpenMP/parallel_ast_print.cpp
  test/OpenMP/target_parallel_ast_print.cpp
  test/OpenMP/target_parallel_for_ast_print.cpp

Index: test/OpenMP/target_parallel_for_ast_print.cpp
===================================================================
--- test/OpenMP/target_parallel_for_ast_print.cpp
+++ test/OpenMP/target_parallel_for_ast_print.cpp
@@ -104,8 +104,8 @@
 // CHECK-NEXT: #pragma omp target parallel for default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(N) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:N][0:10])
   // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
   // CHECK-NEXT: }
-#pragma omp target parallel for if (N) num_threads(s) proc_bind(close) reduction(^:e, f, arr[0:N][:argc]) reduction(&& : h)
-// CHECK-NEXT: #pragma omp target parallel for if(N) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:N][:argc]) reduction(&&: h)
+#pragma omp target parallel for if (N) num_threads(s) proc_bind(close) reduction(+:*arr1) reduction(^:e, f, arr[0:N][:argc]) reduction(&& : h)
+// CHECK-NEXT: #pragma omp target parallel for if(N) num_threads(s) proc_bind(close) reduction(+: *arr1) reduction(^: e,f,arr[0:N][:argc]) reduction(&&: h)
   for (int i = 0; i < 2; ++i) {}
   // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
   // CHECK-NEXT: }
@@ -191,8 +191,8 @@
 // CHECK-NEXT: #pragma omp target parallel for default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(5) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:5][0:10])
   // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
   // CHECK-NEXT: }
-#pragma omp target parallel for if (5) num_threads(s) proc_bind(close) reduction(^:e, f, arr[0:5][:argc]) reduction(&& : h)
-// CHECK-NEXT: #pragma omp target parallel for if(5) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: h)
+#pragma omp target parallel for if (5) num_threads(s) proc_bind(close) reduction(+:*arr1) reduction(^:e, f, arr[0:5][:argc]) reduction(&& : h)
+// CHECK-NEXT: #pragma omp target parallel for if(5) num_threads(s) proc_bind(close) reduction(+: *arr1) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: h)
   for (int i = 0; i < 2; ++i) {}
   // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
   // CHECK-NEXT: }
Index: test/OpenMP/target_parallel_ast_print.cpp
===================================================================
--- test/OpenMP/target_parallel_ast_print.cpp
+++ test/OpenMP/target_parallel_ast_print.cpp
@@ -39,7 +39,7 @@
   h=2;
 #pragma omp target parallel default(none), private(argc,b) firstprivate(argv) shared (d) if (parallel:argc > 0) num_threads(C) proc_bind(master) reduction(+:c, arr1[argc]) reduction(max:e, arr[:C][0:10])
   foo();
-#pragma omp target parallel if (C) num_threads(s) proc_bind(close) reduction(^:e, f, arr[0:C][:argc]) reduction(&& : g)
+#pragma omp target parallel if (C) num_threads(s) proc_bind(close) reduction(+:*arr1) reduction(^:e, f, arr[0:C][:argc]) reduction(&& : g)
   foo();
 #pragma omp target parallel if (target:argc > 0)
   foo();
@@ -74,7 +74,7 @@
 // CHECK-NEXT: h = 2;
 // CHECK-NEXT: #pragma omp target parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(5) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:5][0:10])
 // CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp target parallel if(5) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: g)
+// CHECK-NEXT: #pragma omp target parallel if(5) num_threads(s) proc_bind(close) reduction(+: *arr1) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: g)
 // CHECK-NEXT: foo()
 // CHECK-NEXT: #pragma omp target parallel if(target: argc > 0)
 // CHECK-NEXT: foo()
@@ -106,7 +106,7 @@
 // CHECK-NEXT: h = 2;
 // CHECK-NEXT: #pragma omp target parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(1) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:1][0:10])
 // CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp target parallel if(1) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:1][:argc]) reduction(&&: g)
+// CHECK-NEXT: #pragma omp target parallel if(1) num_threads(s) proc_bind(close) reduction(+: *arr1) reduction(^: e,f,arr[0:1][:argc]) reduction(&&: g)
 // CHECK-NEXT: foo()
 // CHECK-NEXT: #pragma omp target parallel if(target: argc > 0)
 // CHECK-NEXT: foo()
@@ -138,7 +138,7 @@
 // CHECK-NEXT: h = 2;
 // CHECK-NEXT: #pragma omp target parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(C) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:C][0:10])
 // CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp target parallel if(C) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:C][:argc]) reduction(&&: g)
+// CHECK-NEXT: #pragma omp target parallel if(C) num_threads(s) proc_bind(close) reduction(+: *arr1) reduction(^: e,f,arr[0:C][:argc]) reduction(&&: g)
 // CHECK-NEXT: foo()
 // CHECK-NEXT: #pragma omp target parallel if(target: argc > 0)
 // CHECK-NEXT: foo()
Index: test/OpenMP/parallel_ast_print.cpp
===================================================================
--- test/OpenMP/parallel_ast_print.cpp
+++ test/OpenMP/parallel_ast_print.cpp
@@ -54,6 +54,9 @@
 #pragma omp parallel reduction(&& : this->a) reduction(^: b[s.a.a])
     for (int k = 0; k < s.a.a; ++k)
       ++s.a.a;
+#pragma omp parallel reduction(^: *b)
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
     return *this;
   }
 };
@@ -70,6 +73,7 @@
 // CHECK: #pragma omp parallel firstprivate(this->a) firstprivate(this->a)
 // CHECK: #pragma omp parallel shared(this->a) shared(this->a)
 // CHECK: #pragma omp parallel reduction(&&: this->a) reduction(^: this->b[s.a.a])
+// CHECK: #pragma omp parallel reduction(^: *this->b)
 
 class S8 : public S7<S1> {
   S8() {}
@@ -145,7 +149,7 @@
   a=2;
 #pragma omp parallel default(none), private(argc,b) firstprivate(argv) shared (d) if (parallel:argc > 0) num_threads(C) copyin(S<T>::TS) proc_bind(master) reduction(+:c, arr1[argc]) reduction(max:e, arr[:C][0:10])
   foo();
-#pragma omp parallel if (C) num_threads(s) proc_bind(close) reduction(^:e, f, arr[0:C][:argc]) reduction(&& : g)
+#pragma omp parallel if (C) num_threads(s) proc_bind(close) reduction(+: *arr1) reduction(^:e, f, arr[0:C][:argc]) reduction(&& : g)
   foo();
   return 0;
 }
@@ -159,7 +163,7 @@
 // CHECK-NEXT: a = 2;
 // CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(5) copyin(S<int>::TS) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:5][0:10])
 // CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp parallel if(5) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: g)
+// CHECK-NEXT: #pragma omp parallel if(5) num_threads(s) proc_bind(close) reduction(+: *arr1) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: g)
 // CHECK-NEXT: foo()
 // CHECK: template <typename T = long, int C = 1> long tmain(long argc, long *argv) {
 // CHECK-NEXT: long b = argc, c, d, e, f, g;
@@ -170,7 +174,7 @@
 // CHECK-NEXT: a = 2;
 // CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(1) copyin(S<long>::TS) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:1][0:10])
 // CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp parallel if(1) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:1][:argc]) reduction(&&: g)
+// CHECK-NEXT: #pragma omp parallel if(1) num_threads(s) proc_bind(close) reduction(+: *arr1) reduction(^: e,f,arr[0:1][:argc]) reduction(&&: g)
 // CHECK-NEXT: foo()
 // CHECK: template <typename T, int C> T tmain(T argc, T *argv) {
 // CHECK-NEXT: T b = argc, c, d, e, f, g;
@@ -181,7 +185,7 @@
 // CHECK-NEXT: a = 2;
 // CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(C) copyin(S<T>::TS) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:C][0:10])
 // CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp parallel if(C) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:C][:argc]) reduction(&&: g)
+// CHECK-NEXT: #pragma omp parallel if(C) num_threads(s) proc_bind(close) reduction(+: *arr1) reduction(^: e,f,arr[0:C][:argc]) reduction(&&: g)
 // CHECK-NEXT: foo()
 
 enum Enum { };
@@ -202,9 +206,9 @@
 // CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) if(parallel: argc > 0) num_threads(ee) copyin(a) proc_bind(spread) reduction(|: c,d,arr1[argc]) reduction(*: e,arr[:10][0:argc])
   foo();
 // CHECK-NEXT: foo();
-// CHECK-NEXT: #pragma omp parallel if(b) num_threads(c) proc_bind(close) reduction(^: e,f) reduction(&&: g,arr[0:argc][:10])
+// CHECK-NEXT: #pragma omp parallel if(b) num_threads(c) proc_bind(close) reduction(+: *arr1) reduction(^: e,f) reduction(&&: g,arr[0:argc][:10])
 // CHECK-NEXT: foo()
-#pragma omp parallel if (b) num_threads(c) proc_bind(close) reduction(^:e, f) reduction(&& : g, arr[0:argc][:10])
+#pragma omp parallel if (b) num_threads(c) proc_bind(close) reduction(+:*arr1) reduction(^:e, f) reduction(&& : g, arr[0:argc][:10])
   foo();
   return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);
 }
Index: test/OpenMP/for_reduction_messages.cpp
===================================================================
--- test/OpenMP/for_reduction_messages.cpp
+++ test/OpenMP/for_reduction_messages.cpp
@@ -147,6 +147,14 @@
   for (int i = 0; i < 10; ++i)
     foo();
 #pragma omp parallel
+#pragma omp for reduction(max : *qa)
+  for (int i = 0; i < 10; ++i)
+    foo();
+#pragma omp parallel
+#pragma omp for reduction(max: !qa) // expected-error 2 {{expected variable name, array element or array section}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+#pragma omp parallel
 #pragma omp for reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
   for (int i = 0; i < 10; ++i)
     foo();
@@ -207,6 +215,10 @@
 #pragma omp for reduction(+ : qa[1], get()[0]) // expected-error 2 {{reduction variable must be shared}} expected-error {{expected variable name as a base of the array subscript}}
   for (int i = 0; i < 10; ++i)
     foo();
+#pragma omp parallel private(qa)  // expected-note 2 {{defined as private}}
+#pragma omp for reduction(+ : *qa, *(get())) // expected-error 2 {{reduction variable must be shared}} expected-error {{expected variable name as a base of the array subscript}}
+  for (int i = 0; i < 10; ++i)
+    foo();
 #pragma omp parallel shared(qa)
 #pragma omp for reduction(+ : qa[1], qa[0]) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
   for (int i = 0; i < 10; ++i)
Index: test/OpenMP/for_reduction_codegen.cpp
===================================================================
--- test/OpenMP/for_reduction_codegen.cpp
+++ test/OpenMP/for_reduction_codegen.cpp
@@ -217,6 +217,14 @@
 #pragma omp for reduction(& : var3)
   for (int i = 0; i < 10; ++i)
     ;
+#pragma omp parallel
+#pragma omp for reduction(& : var3[1])
+  for (int i = 0; i < 10; ++i)
+    ;
+#pragma omp parallel
+#pragma omp for reduction(& : *var3)
+  for (int i = 0; i < 10; ++i)
+    ;
   return tmain<int>();
 #endif
 }
@@ -231,6 +239,8 @@
 // CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [2 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK4:@.+]] to void
 // CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [2 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK5:@.+]] to void
 // CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [2 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK6:@.+]] to void
+// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [2 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK7:@.+]] to void
+// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [2 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK8:@.+]] to void
 // CHECK: = call {{.*}}i{{.+}} [[TMAIN_INT:@.+]]()
 // CHECK: call {{.*}} [[S_FLOAT_TY_DESTR:@.+]]([[S_FLOAT_TY]]*
 // CHECK: ret
@@ -1002,6 +1012,42 @@
 
 // CHECK: ret void
 
+// CHECK: define internal void [[MAIN_MICROTASK7]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [2 x [[S_FLOAT_TY]]]* dereferenceable(8) %{{.+}})
+
+// CHECK: [[VAR3_ORIG_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*,
+// CHECK: [[VAR3_PRIV:%.+]] = alloca [[S_FLOAT_TY]],
+
+// Reduction list for runtime.
+// CHECK: [[RED_LIST:%.+]] = alloca [1 x i8*],
+
+// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]],
+
+// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],
+// CHECK: [[VAR3_ELEM:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], i64 0, i64 1
+
+// CHECK: [[VAR3_PRIV_ELEM:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[VAR3_PRIV]],
+// CHECK: [[VAR3_PRIV_ELEM_CASTED:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR3_PRIV_ELEM]] to [2 x [[S_FLOAT_TY]]]*
+// CHECK: store [2 x [[S_FLOAT_TY]]]* [[VAR3_PRIV_ELEM_CASTED]], [2 x [[S_FLOAT_TY]]]** %
+
+// CHECK: ret void
+
+// CHECK: define internal void [[MAIN_MICROTASK8]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [2 x [[S_FLOAT_TY]]]* dereferenceable(8) %{{.+}})
+
+// CHECK: [[VAR3_ORIG_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*,
+// CHECK: [[VAR3_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]],
+
+// Reduction list for runtime.
+// CHECK: [[RED_LIST:%.+]] = alloca [1 x i8*],
+
+// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]],
+
+// CHECK: load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],
+
+// CHECK: [[VAR3_PRIV_ELEM:%.+]] = getelementptr [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VAR3_PRIV]],
+// CHECK: store [2 x [[S_FLOAT_TY]]]* [[VAR3_PRIV_ELEM_CASTED]], [2 x [[S_FLOAT_TY]]]** %
+
+// CHECK: ret void
+
 // CHECK: define {{.*}} i{{[0-9]+}} [[TMAIN_INT]]()
 // CHECK: [[TEST:%.+]] = alloca [[S_INT_TY]],
 // CHECK: call {{.*}} [[S_INT_TY_CONSTR:@.+]]([[S_INT_TY]]* [[TEST]])
Index: lib/Sema/SemaOpenMP.cpp
===================================================================
--- lib/Sema/SemaOpenMP.cpp
+++ lib/Sema/SemaOpenMP.cpp
@@ -7138,6 +7138,11 @@
         Base = TempASE->getBase()->IgnoreParenImpCasts();
       RefExpr = Base;
       IsArrayExpr = OMPArraySection;
+    } else if (auto *UO = dyn_cast_or_null<UnaryOperator>(RefExpr)) {
+      if (UO->getOpcode() == UO_Deref) {
+        RefExpr = UO->getSubExpr()->IgnoreParenImpCasts();
+        IsArrayExpr = ArraySubscript;
+      }
     }
   }
   ELoc = RefExpr->getExprLoc();
@@ -8077,6 +8082,7 @@
     QualType Type;
     auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
     auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr->IgnoreParens());
+    auto *UO = dyn_cast<UnaryOperator>(RefExpr->IgnoreParens());
     if (ASE)
       Type = ASE->getType().getNonReferenceType();
     else if (OASE) {
@@ -8086,6 +8092,9 @@
       else
         Type = BaseType->getPointeeType();
       Type = Type.getNonReferenceType();
+    } else if (UO) {
+      assert(UO->getOpcode() == UO_Deref && "should be a dereference");
+      Type = UO->getType().getNonReferenceType();
     } else
       Type = Context.getBaseElementType(D->getType().getNonReferenceType());
     auto *VD = dyn_cast<VarDecl>(D);
Index: lib/CodeGen/CGStmtOpenMP.cpp
===================================================================
--- lib/CodeGen/CGStmtOpenMP.cpp
+++ lib/CodeGen/CGStmtOpenMP.cpp
@@ -910,13 +910,23 @@
         PrivateScope.addPrivate(RHSVD, [this, PrivateVD]() -> Address {
           return GetAddrOfLocalVar(PrivateVD);
         });
-      } else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(IRef)) {
-        auto *Base = ASE->getBase()->IgnoreParenImpCasts();
-        while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
-          Base = TempASE->getBase()->IgnoreParenImpCasts();
+      } else if (isa<ArraySubscriptExpr>(IRef) || isa<UnaryOperator>(IRef)) {
+        const Expr *Array;
+        const Expr *Base;
+        if (auto* ASE = dyn_cast<ArraySubscriptExpr>(IRef)) {
+          Array = ASE;
+          Base = ASE->getBase()->IgnoreParenImpCasts();
+          while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
+            Base = TempASE->getBase()->IgnoreParenImpCasts();
+        } else {
+          auto* UO = cast<UnaryOperator>(IRef);
+          assert(UO->getOpcode() == UO_Deref && "should be a dereference");
+          Array = UO;
+          Base = UO->getSubExpr()->IgnoreParenImpCasts();
+        }
         auto *DE = cast<DeclRefExpr>(Base);
         auto *OrigVD = cast<VarDecl>(DE->getDecl());
-        auto ASELValue = EmitLValue(ASE);
+        auto ASELValue = EmitLValue(Array);
         auto OriginalBaseLValue = EmitLValue(DE);
         LValue BaseLValue = loadToBegin(
             *this, OrigVD->getType(), ASELValue.getType(), OriginalBaseLValue);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to