tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, tahonermann, erichkeane, shafik.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

I still have this mixed up with the `CompoundLiteral` code since this is was I 
used for testing. I can split this up if needed of course.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D140668

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/test/AST/Interp/literals.cpp
  clang/test/AST/Interp/records.cpp

Index: clang/test/AST/Interp/records.cpp
===================================================================
--- clang/test/AST/Interp/records.cpp
+++ clang/test/AST/Interp/records.cpp
@@ -50,9 +50,6 @@
 static_assert(ints2.b == -30, "");
 static_assert(!ints2.c, "");
 
-#if __cplusplus >= 201703L
-// FIXME: In c++14, this uses a MaterializeTemporaryExpr,
-//   which the new interpreter doesn't support yet.
 constexpr Ints getInts() {
   return {64, 128, true};
 }
@@ -60,7 +57,6 @@
 static_assert(ints3.a == 64, "");
 static_assert(ints3.b == 128, "");
 static_assert(ints3.c, "");
-#endif
 
 constexpr Ints ints4 = {
   .a = 40 * 50,
@@ -88,9 +84,9 @@
   int a = 10;
   int b;
 };
-// FIXME: Broken in the new constant interpreter.
-//   Should be rejected, but without asan errors.
-//constexpr Ints2 ints2;
+constexpr Ints2 ints22; // expected-error {{without a user-provided default constructor}} \
+                        // expected-error {{must be initialized by a constant expression}} \
+                        // ref-error {{without a user-provided default constructor}}
 
 class C {
   public:
@@ -124,9 +120,6 @@
 }
 static_assert(getPointer()->a == 100, "");
 
-#if __cplusplus >= 201703L
-// FIXME: In c++14, this uses a MaterializeTemporaryExpr,
-//   which the new interpreter doesn't support yet.
 constexpr C RVOAndParams(const C *c) {
   return C();
 }
@@ -137,7 +130,6 @@
   return C();
 }
 constexpr C RVOAndParamsResult2 = RVOAndParams(12);
-#endif
 
 class Bar { // expected-note {{definition of 'Bar' is not complete}} \
             // ref-note {{definition of 'Bar' is not complete}}
@@ -158,16 +150,16 @@
   c.a = 10;
 
   // Assignment, not an initializer.
-  // c = C(); FIXME
+  c = C();
   c.a = 10;
 
 
   // Assignment, not an initializer.
-  //c = RVOAndParams(&c); FIXME
+  c = RVOAndParams(&c);
 
   return c.a;
 }
-static_assert(locals() == 10, "");
+static_assert(locals() == 100, "");
 
 namespace thisPointer {
   struct S {
@@ -234,10 +226,7 @@
     this->a; // expected-warning {{expression result unused}} \
              // ref-warning {{expression result unused}}
     get5();
-#if __cplusplus >= 201703L
-    // FIXME: Enable once we support MaterializeConstantExpr properly.
     getInts();
-#endif
   }
 
   constexpr int m() const {
Index: clang/test/AST/Interp/literals.cpp
===================================================================
--- clang/test/AST/Interp/literals.cpp
+++ clang/test/AST/Interp/literals.cpp
@@ -665,3 +665,27 @@
                                               // ref-note {{in call to 'IntMul}}
 };
 #endif
+
+namespace CompoundLiterals {
+  constexpr int get5() {
+    return (int[]){1,2,3,4,5}[4];
+  }
+  static_assert(get5() == 5, "");
+
+  constexpr int get6(int f = (int[]){1,2,6}[2]) { // ref-note {{subexpression not valid in a constant expression}} \
+                                                  // ref-note {{declared here}}
+    return f;
+  }
+  static_assert(get6(6) == 6, "");
+  // FIXME: Who's right here?
+  static_assert(get6() == 6, ""); // ref-error {{not an integral constant expression}}
+
+#if __cplusplus >= 202002L
+  constexpr int get3() {
+    int m;
+    m = (int){3};
+    return m;
+  }
+  static_assert(get3() == 3, "");
+#endif
+};
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -88,6 +88,7 @@
   bool VisitFloatCompoundAssignOperator(const CompoundAssignOperator *E);
   bool VisitExprWithCleanups(const ExprWithCleanups *E);
   bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
+  bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E);
 
 protected:
   bool visitExpr(const Expr *E) override;
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -736,19 +736,10 @@
 template <class Emitter>
 bool ByteCodeExprGen<Emitter>::VisitMaterializeTemporaryExpr(
     const MaterializeTemporaryExpr *E) {
-  StorageDuration SD = E->getStorageDuration();
-
-  // We conservatively only support these for now.
-  if (SD != SD_Static && SD != SD_Automatic)
-    return false;
-
   const Expr *SubExpr = E->getSubExpr();
   std::optional<PrimType> SubExprT = classify(SubExpr);
-  // FIXME: Implement this for records and arrays as well.
-  if (!SubExprT)
-    return false;
 
-  if (SD == SD_Static) {
+  if (E->getStorageDuration() == SD_Static) {
     if (std::optional<unsigned> GlobalIndex = P.createGlobal(E)) {
       const LifetimeExtendedTemporaryDecl *TempDecl =
           E->getLifetimeExtendedTemporaryDecl();
@@ -760,15 +751,54 @@
         return false;
       return this->emitGetPtrGlobal(*GlobalIndex, E);
     }
-  } else if (SD == SD_Automatic) {
+
+    return false;
+  }
+
+  // For everyhing else, use local variables.
+  if (SubExprT) {
     if (std::optional<unsigned> LocalIndex =
             allocateLocalPrimitive(SubExpr, *SubExprT, true, true)) {
+      //if (!this->emitGetPtrLocal(*LocalIndex, E))
+        //return false;
       if (!this->visitInitializer(SubExpr))
         return false;
+      this->emitSetLocal(*SubExprT, *LocalIndex, E);
+      return this->emitGetPtrLocal(*LocalIndex, E);
+    }
+  } else {
+    if (std::optional<unsigned> LocalIndex = allocateLocal(SubExpr)) {
+      if (!this->emitGetPtrLocal(*LocalIndex, E))
+        return false;
+      return this->visitInitializer(SubExpr);
+    }
+  }
+  return false;
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
+  std::optional<PrimType> T = classify(E->getType());
+  const Expr *Init = E->getInitializer();
+  if (E->isFileScope()) {
+    if (std::optional<unsigned> GlobalIndex = P.createGlobal(E)) {
+      if (!this->emitGetPtrGlobal(*GlobalIndex, E))
+        return false;
+      assert(!classify(E->getType()));
+      // FIXME: Can we even get here with primitive types?
+      return this->visitInitializer(Init);
+    }
+  }
 
-      if (!this->emitSetLocal(*SubExprT, *LocalIndex, E))
+  // Otherwise, use a local variable.
+  if (T) {
+    // For primitive types, we just visit the initializer.
+    return this->visit(Init);
+  } else {
+    if (std::optional<unsigned> LocalIndex = allocateLocal(Init)) {
+      if (!this->emitGetPtrLocal(*LocalIndex, E))
         return false;
-      return this->emitGetPtrLocal(*LocalIndex, E);
+      return this->visitInitializer(Init);
     }
   }
 
@@ -1228,6 +1258,8 @@
       }
     }
     return true;
+  } else if (const auto *CLE = dyn_cast<CompoundLiteralExpr>(Initializer)) {
+    return visitInitializer(CLE->getInitializer());
   }
 
   assert(false && "Unknown expression for array initialization");
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to