Author: Timm Bäder Date: 2022-09-08T07:31:07+02:00 New Revision: 5777c05d16098cb690decef95ad6c20c695a5fa9
URL: https://github.com/llvm/llvm-project/commit/5777c05d16098cb690decef95ad6c20c695a5fa9 DIFF: https://github.com/llvm/llvm-project/commit/5777c05d16098cb690decef95ad6c20c695a5fa9.diff LOG: [clang] Perform implicit lvalue-to-rvalue cast with new interpreter The EvaluateAsRValue() documentation mentions that an implicit lvalue-to-rvalue cast is being performed if the result is an lvalue. However, that was not being done if the new constant interpreter was in use. Just always do it. Differential Revision: https://reviews.llvm.org/D132136 Added: Modified: clang/lib/AST/ExprConstant.cpp clang/test/AST/Interp/literals.cpp clang/unittests/AST/EvaluateAsRValueTest.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 3df0e4292b6c..ba5690cd3c5a 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -14934,25 +14934,27 @@ static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This, /// lvalue-to-rvalue cast if it is an lvalue. static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) { assert(!E->isValueDependent()); + + if (E->getType().isNull()) + return false; + + if (!CheckLiteralType(Info, E)) + return false; + if (Info.EnableNewConstInterp) { if (!Info.Ctx.getInterpContext().evaluateAsRValue(Info, E, Result)) return false; } else { - if (E->getType().isNull()) - return false; - - if (!CheckLiteralType(Info, E)) - return false; - if (!::Evaluate(Result, Info, E)) return false; + } - if (E->isGLValue()) { - LValue LV; - LV.setFrom(Info.Ctx, Result); - if (!handleLValueToRValueConversion(Info, E, E->getType(), LV, Result)) - return false; - } + // Implicit lvalue-to-rvalue cast. + if (E->isGLValue()) { + LValue LV; + LV.setFrom(Info.Ctx, Result); + if (!handleLValueToRValueConversion(Info, E, E->getType(), LV, Result)) + return false; } // Check this core constant expression is a constant expression. diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp index f32f813a4986..6831091d596b 100644 --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -11,6 +11,7 @@ constexpr int number = 10; static_assert(number == 10, ""); static_assert(number != 10, ""); // expected-error{{failed}} \ // ref-error{{failed}} \ + // expected-note{{evaluates to}} \ // ref-note{{evaluates to}} constexpr bool getTrue() { return true; } diff --git a/clang/unittests/AST/EvaluateAsRValueTest.cpp b/clang/unittests/AST/EvaluateAsRValueTest.cpp index bf44136835f2..f6261b827671 100644 --- a/clang/unittests/AST/EvaluateAsRValueTest.cpp +++ b/clang/unittests/AST/EvaluateAsRValueTest.cpp @@ -107,3 +107,50 @@ TEST(EvaluateAsRValue, FailsGracefullyForUnknownTypes) { Args)); } } + +class CheckLValueToRValueConversionVisitor + : public clang::RecursiveASTVisitor<CheckLValueToRValueConversionVisitor> { +public: + bool VisitDeclRefExpr(const clang::DeclRefExpr *E) { + clang::Expr::EvalResult Result; + E->EvaluateAsRValue(Result, E->getDecl()->getASTContext(), true); + + EXPECT_TRUE(Result.Val.hasValue()); + // Since EvaluateAsRValue does an implicit lvalue-to-rvalue conversion, + // the result cannot be a LValue. + EXPECT_FALSE(Result.Val.isLValue()); + + return true; + } +}; + +class CheckConversionAction : public clang::ASTFrontendAction { +public: + std::unique_ptr<clang::ASTConsumer> + CreateASTConsumer(clang::CompilerInstance &Compiler, + llvm::StringRef FilePath) override { + return std::make_unique<Consumer>(); + } + +private: + class Consumer : public clang::ASTConsumer { + public: + ~Consumer() override {} + + void HandleTranslationUnit(clang::ASTContext &Ctx) override { + CheckLValueToRValueConversionVisitor Evaluator; + Evaluator.TraverseDecl(Ctx.getTranslationUnitDecl()); + } + }; +}; + +TEST(EvaluateAsRValue, LValueToRValueConversionWorks) { + std::string ModesToTest[] = {"", "-fexperimental-new-constant-interpreter"}; + for (std::string const &Mode : ModesToTest) { + std::vector<std::string> Args(1, Mode); + ASSERT_TRUE(runToolOnCodeWithArgs(std::make_unique<CheckConversionAction>(), + "constexpr int a = 20;\n" + "static_assert(a == 20, \"\");\n", + Args)); + } +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits