Author: Timm Bäder Date: 2023-03-01T17:11:57+01:00 New Revision: 730eca6a3de85ae66bb905ee32c47332b5395226
URL: https://github.com/llvm/llvm-project/commit/730eca6a3de85ae66bb905ee32c47332b5395226 DIFF: https://github.com/llvm/llvm-project/commit/730eca6a3de85ae66bb905ee32c47332b5395226.diff LOG: [clang][Interp] Handle DecompositionDecls Differential Revision: https://reviews.llvm.org/D138802 Added: clang/test/AST/Interp/cxx17.cpp Modified: clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/ByteCodeExprGen.h clang/lib/AST/Interp/ByteCodeStmtGen.cpp clang/lib/AST/Interp/Program.h Removed: ################################################################################ diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 2b4e324f7b0fa..d4c9292739609 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -28,7 +28,7 @@ namespace interp { /// Scope used to handle temporaries in toplevel variable declarations. template <class Emitter> class DeclScope final : public LocalScope<Emitter> { public: - DeclScope(ByteCodeExprGen<Emitter> *Ctx, const VarDecl *VD) + DeclScope(ByteCodeExprGen<Emitter> *Ctx, const ValueDecl *VD) : LocalScope<Emitter>(Ctx), Scope(Ctx->P, VD) {} void addExtended(const Scope::Local &Local) override { @@ -936,11 +936,11 @@ bool ByteCodeExprGen<Emitter>::dereference( if (std::optional<PrimType> T = classify(LV->getType())) { if (!LV->refersToBitField()) { // Only primitive, non bit-field types can be dereferenced directly. - if (auto *DE = dyn_cast<DeclRefExpr>(LV)) { + if (const auto *DE = dyn_cast<DeclRefExpr>(LV)) { if (!DE->getDecl()->getType()->isReferenceType()) { - if (auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl())) + if (const auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl())) return dereferenceParam(LV, *T, PD, AK, Direct, Indirect); - if (auto *VD = dyn_cast<VarDecl>(DE->getDecl())) + if (const auto *VD = dyn_cast<VarDecl>(DE->getDecl())) return dereferenceVar(LV, *T, VD, AK, Direct, Indirect); } } @@ -1823,6 +1823,8 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) { } } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(Decl)) { return this->emitConst(ECD->getInitVal(), E); + } else if (const auto *BD = dyn_cast<BindingDecl>(Decl)) { + return this->visit(BD->getBinding()); } return false; diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 74cd5984daf55..d6390116010b4 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -235,9 +235,12 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>, } /// Returns whether we should create a global variable for the - /// given VarDecl. - bool shouldBeGloballyIndexed(const VarDecl *VD) const { - return VD->hasGlobalStorage() || VD->isConstexpr(); + /// given ValueDecl. + bool shouldBeGloballyIndexed(const ValueDecl *VD) const { + if (const auto *V = dyn_cast<VarDecl>(VD)) + return V->hasGlobalStorage() || V->isConstexpr(); + + return false; } llvm::RoundingMode getRoundingMode(const Expr *E) const { diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp index 522b04254e85d..ff2727cc4d354 100644 --- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp @@ -205,17 +205,11 @@ bool ByteCodeStmtGen<Emitter>::visitCompoundStmt( template <class Emitter> bool ByteCodeStmtGen<Emitter>::visitDeclStmt(const DeclStmt *DS) { for (auto *D : DS->decls()) { - // Variable declarator. - if (auto *VD = dyn_cast<VarDecl>(D)) { - if (!this->visitVarDecl(VD)) - return false; - continue; - } - - // Decomposition declarator. - if (auto *DD = dyn_cast<DecompositionDecl>(D)) { - return this->bail(DD); - } + const auto *VD = dyn_cast<VarDecl>(D); + if (!VD) + return false; + if (!this->visitVarDecl(VD)) + return false; } return true; diff --git a/clang/lib/AST/Interp/Program.h b/clang/lib/AST/Interp/Program.h index 5a80dd1ed748e..4547ca7ac69c1 100644 --- a/clang/lib/AST/Interp/Program.h +++ b/clang/lib/AST/Interp/Program.h @@ -131,7 +131,9 @@ class Program final { /// Context to manage declaration lifetimes. class DeclScope { public: - DeclScope(Program &P, const VarDecl *VD) : P(P) { P.startDeclaration(VD); } + DeclScope(Program &P, const ValueDecl *VD) : P(P) { + P.startDeclaration(VD); + } ~DeclScope() { P.endDeclaration(); } private: @@ -222,7 +224,7 @@ class Program final { unsigned CurrentDeclaration = NoDeclaration; /// Starts evaluating a declaration. - void startDeclaration(const VarDecl *Decl) { + void startDeclaration(const ValueDecl *Decl) { LastDeclaration += 1; CurrentDeclaration = LastDeclaration; } diff --git a/clang/test/AST/Interp/cxx17.cpp b/clang/test/AST/Interp/cxx17.cpp new file mode 100644 index 0000000000000..e72ff738ff630 --- /dev/null +++ b/clang/test/AST/Interp/cxx17.cpp @@ -0,0 +1,85 @@ +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++17 -verify %s +// RUN: %clang_cc1 -std=c++17 -verify=ref %s + +// ref-no-diagnostics + +struct F { int a; int b;}; +constexpr F getF() { + return {12, 3}; +} +constexpr int f() { + auto [a1, b1] = getF(); + auto [a2, b2] = getF(); + + return a1 + a2 + b1 + b2; +} +static_assert(f() == 30); + + +constexpr int structRefs() { + const auto &[a, b] = getF(); + + 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}} + +constexpr int structRefs2() { + F f = getF(); + const auto &[a, b] = f; + + return a + b; +} +static_assert(structRefs2() == 15); + + +template<typename T> +struct Tuple { + T first; + T second; + constexpr Tuple(T a, T b) : first(a), second(b) {} +}; +template<typename T> +constexpr T addTuple(const Tuple<T> &Tu) { + auto [a, b] = Tu; + return a + b; +} + +template<typename T> +constexpr T addTuple2(const Tuple<T> &Tu) { + auto [a, b] = Tu; + return Tu.first + Tu.second; +} + +constexpr Tuple<int> T1 = Tuple(1,2); +static_assert(addTuple(T1) == 3); +static_assert(addTuple2(T1) == 3); + +constexpr Tuple<short> T2 = Tuple<short>(11,2); +static_assert(addTuple(T2) == 13); +static_assert(addTuple2(T2) == 13); + +constexpr int Modify() { + auto T = Tuple<int>(10, 20); + auto &[x, y] = T; + x += 1; + y += 1; + return T.first + T.second; +} +static_assert(Modify() == 32, ""); + +constexpr int a() { + int a[2] = {5, 3}; + auto [x, y] = a; + return x + y; +} +static_assert(a() == 8); + +constexpr int b() { + int a[2] = {5, 3}; + auto &[x, y] = a; + x += 1; + y += 2; + return a[0] + a[1]; +} +static_assert(b() == 11); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits