ricejasonf updated this revision to Diff 368485.
ricejasonf added a comment.

I added a simple lit test. The case is the reduced case mentioned in the bug. I 
spent some time trying to reproduce this outside decomposition. The only other 
way (I know of) to produce an ArrayInitLoopExpr is an implicit copy 
constructor, but the AST for that is generated lazily so it never gets 
transformed. Other entities containing OpaqueValueExpr do not appear to have 
this problem either. Let me know if there are any more deficiencies or 
suggested changes. Thank you.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D108482/new/

https://reviews.llvm.org/D108482

Files:
  clang/lib/Sema/SemaInit.cpp
  clang/lib/Sema/TreeTransform.h
  clang/test/SemaCXX/pr45964-nested-ove.cpp


Index: clang/test/SemaCXX/pr45964-nested-ove.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/pr45964-nested-ove.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=c++17 -emit-codegen-only -verify %s
+// Don't crash (Bugzilla - Bug 45964).
+
+// non-dependent ArrayInitLoop should not, upon instantiation,
+// contain an OpaqueValueExpr with a nested OpaqueValueExpr or an
+// uninstantiated source expr. (triggers asserts in CodeGen)
+
+// expected-no-diagnostics
+int a[1];
+template <int> void b() {
+  auto [c] = a;
+}
+void (*d)(){b<0>};
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -10511,7 +10511,19 @@
 TreeTransform<Derived>::TransformOpaqueValueExpr(OpaqueValueExpr *E) {
   assert((!E->getSourceExpr() || 
getDerived().AlreadyTransformed(E->getType())) &&
          "opaque value expression requires transformation");
-  return E;
+
+  // Note that SourceExpr can be nullptr
+  ExprResult SourceExpr = TransformExpr(E->getSourceExpr());
+  if (SourceExpr.isInvalid())
+    return ExprError();
+  if (SourceExpr.get() == E->getSourceExpr() && !getDerived().AlwaysRebuild()) 
{
+    return E;
+  }
+
+  OpaqueValueExpr *New = new (SemaRef.Context)
+      OpaqueValueExpr(E->getExprLoc(), E->getType(), E->getValueKind(),
+                      E->getObjectKind(), SourceExpr.get());
+  return New;
 }
 
 template<typename Derived>
Index: clang/lib/Sema/SemaInit.cpp
===================================================================
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -8643,9 +8643,13 @@
 
     case SK_ArrayLoopIndex: {
       Expr *Cur = CurInit.get();
-      Expr *BaseExpr = new (S.Context)
-          OpaqueValueExpr(Cur->getExprLoc(), Cur->getType(),
-                          Cur->getValueKind(), Cur->getObjectKind(), Cur);
+      // prevent nested OpaqueValueExprs
+      Expr *BaseExpr = dyn_cast<OpaqueValueExpr>(Cur);
+      if (!BaseExpr) {
+        BaseExpr = new (S.Context)
+            OpaqueValueExpr(Cur->getExprLoc(), Cur->getType(),
+                            Cur->getValueKind(), Cur->getObjectKind(), Cur);
+      }
       Expr *IndexExpr =
           new (S.Context) ArrayInitIndexExpr(S.Context.getSizeType());
       CurInit = S.CreateBuiltinArraySubscriptExpr(


Index: clang/test/SemaCXX/pr45964-nested-ove.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/pr45964-nested-ove.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=c++17 -emit-codegen-only -verify %s
+// Don't crash (Bugzilla - Bug 45964).
+
+// non-dependent ArrayInitLoop should not, upon instantiation,
+// contain an OpaqueValueExpr with a nested OpaqueValueExpr or an
+// uninstantiated source expr. (triggers asserts in CodeGen)
+
+// expected-no-diagnostics
+int a[1];
+template <int> void b() {
+  auto [c] = a;
+}
+void (*d)(){b<0>};
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -10511,7 +10511,19 @@
 TreeTransform<Derived>::TransformOpaqueValueExpr(OpaqueValueExpr *E) {
   assert((!E->getSourceExpr() || getDerived().AlreadyTransformed(E->getType())) &&
          "opaque value expression requires transformation");
-  return E;
+
+  // Note that SourceExpr can be nullptr
+  ExprResult SourceExpr = TransformExpr(E->getSourceExpr());
+  if (SourceExpr.isInvalid())
+    return ExprError();
+  if (SourceExpr.get() == E->getSourceExpr() && !getDerived().AlwaysRebuild()) {
+    return E;
+  }
+
+  OpaqueValueExpr *New = new (SemaRef.Context)
+      OpaqueValueExpr(E->getExprLoc(), E->getType(), E->getValueKind(),
+                      E->getObjectKind(), SourceExpr.get());
+  return New;
 }
 
 template<typename Derived>
Index: clang/lib/Sema/SemaInit.cpp
===================================================================
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -8643,9 +8643,13 @@
 
     case SK_ArrayLoopIndex: {
       Expr *Cur = CurInit.get();
-      Expr *BaseExpr = new (S.Context)
-          OpaqueValueExpr(Cur->getExprLoc(), Cur->getType(),
-                          Cur->getValueKind(), Cur->getObjectKind(), Cur);
+      // prevent nested OpaqueValueExprs
+      Expr *BaseExpr = dyn_cast<OpaqueValueExpr>(Cur);
+      if (!BaseExpr) {
+        BaseExpr = new (S.Context)
+            OpaqueValueExpr(Cur->getExprLoc(), Cur->getType(),
+                            Cur->getValueKind(), Cur->getObjectKind(), Cur);
+      }
       Expr *IndexExpr =
           new (S.Context) ArrayInitIndexExpr(S.Context.getSizeType());
       CurInit = S.CreateBuiltinArraySubscriptExpr(
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to