tbaeder updated this revision to Diff 488935.
tbaeder marked an inline comment as done.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D140668/new/
https://reviews.llvm.org/D140668
Files:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/ByteCodeExprGen.h
clang/test/AST/Interp/cxx17.cpp
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/test/AST/Interp/cxx17.cpp
===================================================================
--- clang/test/AST/Interp/cxx17.cpp
+++ clang/test/AST/Interp/cxx17.cpp
@@ -2,6 +2,7 @@
// RUN: %clang_cc1 -std=c++17 -verify=ref %s
// ref-no-diagnostics
+// expected-no-diagnostics
struct F { int a; int b;};
constexpr F getF() {
@@ -21,8 +22,7 @@
return a + b;
}
-// FIXME: This should work, but the MaterializeTemporaryExpr handling is not ready for it.
-static_assert(structRefs() == 15); // expected-error {{not an integral constant expression}}
+static_assert(structRefs() == 15);
constexpr int structRefs2() {
F f = getF();
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;
@@ -362,7 +363,10 @@
BlockScope(ByteCodeExprGen<Emitter> *Ctx) : LocalScope<Emitter>(Ctx) {}
void addExtended(const Scope::Local &Local) override {
- llvm_unreachable("Cannot create temporaries in full scopes");
+ // If we to this point, just add the variable as a normal local
+ // variable. It will be destroyed at the end of the block just
+ // like all others.
+ this->addLocal(Local);
}
};
@@ -373,8 +377,8 @@
ExprScope(ByteCodeExprGen<Emitter> *Ctx) : LocalScope<Emitter>(Ctx) {}
void addExtended(const Scope::Local &Local) override {
- assert(this->Parent);
- this->Parent->addLocal(Local);
+ if (this->Parent)
+ this->Parent->addLocal(Local);
}
};
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) {
- if (std::optional<unsigned> LocalIndex =
- allocateLocalPrimitive(SubExpr, *SubExprT, true, true)) {
+
+ return false;
+ }
+
+ // For everyhing else, use local variables.
+ if (SubExprT) {
+ if (std::optional<unsigned> LocalIndex = allocateLocalPrimitive(
+ SubExpr, *SubExprT, /*IsMutable=*/true, /*IsExtended=*/true)) {
if (!this->visitInitializer(SubExpr))
return false;
+ this->emitSetLocal(*SubExprT, *LocalIndex, E);
+ return this->emitGetPtrLocal(*LocalIndex, E);
+ }
+ } else {
+ if (std::optional<unsigned> LocalIndex =
+ allocateLocal(SubExpr, /*IsExtended=*/true)) {
+ if (!this->emitGetPtrLocal(*LocalIndex, E))
+ return false;
+ return this->visitInitializer(SubExpr);
+ }
+ }
+ return false;
+}
- if (!this->emitSetLocal(*SubExprT, *LocalIndex, E))
+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;
- return this->emitGetPtrLocal(*LocalIndex, E);
+ assert(!classify(E->getType()));
+ // FIXME: Can we even get here with primitive types?
+ return this->visitInitializer(Init);
+ }
+ }
+
+ // 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->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");
@@ -1413,6 +1445,10 @@
template <class Emitter>
bool ByteCodeExprGen<Emitter>::allocateVariable(const ValueDecl *VD,
const Expr *Init) {
+ // We don't know what to do with these, so just return false.
+ if (VD->getType().isNull())
+ return false;
+
std::optional<PrimType> VarT = classify(VD->getType());
if (shouldBeGloballyIndexed(VD)) {
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits