From 5143a1241362616840af826d18c067025dae1111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Sun, 17 Mar 2024 17:45:42 +0100 Subject: [PATCH] [clang][Interp] Add __builtin_is_constant_evaluated warnings Add the same warnings the current interpreter emits. --- clang/lib/AST/Interp/InterpBuiltin.cpp | 33 ++++++++++++++++++- clang/lib/AST/Interp/InterpFrame.cpp | 2 ++ clang/test/AST/Interp/builtins.cpp | 4 +-- .../warn-constant-evaluated-constexpr.cpp | 1 + 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp index 45bac41ff7782a..1bf5d55314f1f2 100644 --- a/clang/lib/AST/Interp/InterpBuiltin.cpp +++ b/clang/lib/AST/Interp/InterpBuiltin.cpp @@ -119,6 +119,36 @@ static bool retPrimValue(InterpState &S, CodePtr OpPC, APValue &Result, #undef RET_CASE } +static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC, + const InterpFrame *Frame, + const CallExpr *Call) { + // The current frame is the one for __builtin_is_constant_evaluated. + // The one above that, potentially the one for std::is_constant_evaluated(). + if (S.inConstantContext() && !S.checkingPotentialConstantExpression() && + Frame->Caller && S.getEvalStatus().Diag) { + auto isStdCall = [](const FunctionDecl *F) -> bool { + return F && F->isInStdNamespace() && F->getIdentifier() && + F->getIdentifier()->isStr("is_constant_evaluated"); + }; + const InterpFrame *Caller = Frame->Caller; + + if (Caller->Caller && isStdCall(Caller->getCallee())) { + const Expr *E = Caller->Caller->getExpr(Caller->getRetPC()); + S.report(E->getExprLoc(), + diag::warn_is_constant_evaluated_always_true_constexpr) + << "std::is_constant_evaluated"; + } else { + const Expr *E = Frame->Caller->getExpr(Frame->getRetPC()); + S.report(E->getExprLoc(), + diag::warn_is_constant_evaluated_always_true_constexpr) + << "__builtin_is_constant_evaluated"; + } + } + + S.Stk.push(Boolean::from(S.inConstantContext())); + return true; +} + static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { @@ -924,7 +954,8 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, switch (F->getBuiltinID()) { case Builtin::BI__builtin_is_constant_evaluated: - S.Stk.push(Boolean::from(S.inConstantContext())); + if (!interp__builtin_is_constant_evaluated(S, OpPC, Frame, Call)) + return false; break; case Builtin::BI__builtin_assume: case Builtin::BI__assume: diff --git a/clang/lib/AST/Interp/InterpFrame.cpp b/clang/lib/AST/Interp/InterpFrame.cpp index f69ff06b5e81b5..12e2e6ff9155b9 100644 --- a/clang/lib/AST/Interp/InterpFrame.cpp +++ b/clang/lib/AST/Interp/InterpFrame.cpp @@ -190,6 +190,8 @@ SourceRange InterpFrame::getCallRange() const { } const FunctionDecl *InterpFrame::getCallee() const { + if (!Func) + return nullptr; return Func->getDecl(); } diff --git a/clang/test/AST/Interp/builtins.cpp b/clang/test/AST/Interp/builtins.cpp index 06a22b16b2dcbb..9095d1bf8d6a3a 100644 --- a/clang/test/AST/Interp/builtins.cpp +++ b/clang/test/AST/Interp/builtins.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter %s -verify -fms-extensions -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter %s -fms-extensions -S -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter %s -Wno-constant-evaluated -verify -fms-extensions +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter %s -Wno-constant-evaluated -fms-extensions -S -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -verify=ref %s -Wno-constant-evaluated -fms-extensions // RUN: %clang_cc1 -verify=ref %s -Wno-constant-evaluated %s -fms-extensions -S -emit-llvm -o - | FileCheck %s diff --git a/clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp b/clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp index 35dc69cccb3a2e..fa40c13971118d 100644 --- a/clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp +++ b/clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++2a -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++2a -fsyntax-only -verify %s -fexperimental-new-constant-interpreter namespace std { constexpr bool is_constant_evaluated() noexcept {