[clang] 5777c05 - [clang] Perform implicit lvalue-to-rvalue cast with new interpreter

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 7 22:31:47 PDT 2022


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));
+  }
+}


        


More information about the cfe-commits mailing list