Skip to content

Commit

Permalink
[clang][Interp] Add __builtin_is_constant_evaluated warnings
Browse files Browse the repository at this point in the history
Add the same warnings the current interpreter emits.
  • Loading branch information
tbaederr committed Mar 17, 2024
1 parent ca87671 commit 5143a12
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 3 deletions.
33 changes: 32 additions & 1 deletion clang/lib/AST/Interp/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>(Boolean::from(S.inConstantContext()));
return true;
}

static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
Expand Down Expand Up @@ -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>(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:
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/Interp/InterpFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ SourceRange InterpFrame::getCallRange() const {
}

const FunctionDecl *InterpFrame::getCallee() const {
if (!Func)
return nullptr;
return Func->getDecl();
}

Expand Down
4 changes: 2 additions & 2 deletions clang/test/AST/Interp/builtins.cpp
Original file line number Diff line number Diff line change
@@ -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

Expand Down
1 change: 1 addition & 0 deletions clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down

0 comments on commit 5143a12

Please sign in to comment.