Skip to content

Commit 4b03dd7

Browse files
committed
PR45534: don't ignore unmodeled side-effects when constant-evaluating a call to __builtin_constant_p.
Such side-effects should result in the call evaluating to 'false', even if we can still determine what value the argument expression will evaluate to.
1 parent b14e9e3 commit 4b03dd7

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10438,7 +10438,7 @@ static bool EvaluateBuiltinConstantP(EvalInfo &Info, const Expr *Arg) {
1043810438
ArgType->isAnyComplexType() || ArgType->isPointerType() ||
1043910439
ArgType->isNullPtrType()) {
1044010440
APValue V;
10441-
if (!::EvaluateAsRValue(Info, Arg, V)) {
10441+
if (!::EvaluateAsRValue(Info, Arg, V) || Info.EvalStatus.HasSideEffects) {
1044210442
Fold.keepDiagnostics();
1044310443
return false;
1044410444
}

clang/test/SemaCXX/builtin-constant-p.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %clang_cc1 -std=c++17 -verify %s
2+
// RUN: %clang_cc1 -std=c++20 -verify %s
23

34
using intptr_t = __INTPTR_TYPE__;
45

@@ -135,3 +136,33 @@ static_assert(mutate6(true) == 10);
135136
// not being a pointer to the start of a string literal.
136137
namespace std { struct type_info; }
137138
static_assert(__builtin_constant_p(&typeid(int)));
139+
140+
void mutate_as_side_effect() {
141+
int a;
142+
static_assert(!__builtin_constant_p(((void)++a, 1)));
143+
}
144+
145+
namespace dtor_side_effect {
146+
struct A {
147+
constexpr A() {}
148+
~A();
149+
};
150+
static_assert(!__builtin_constant_p((A{}, 123)));
151+
}
152+
153+
#if __cplusplus >= 202002L
154+
namespace constexpr_dtor {
155+
struct A {
156+
int *p;
157+
constexpr ~A() { *p = 0; }
158+
};
159+
struct Q { int n; constexpr int *get() { return &n; } };
160+
static_assert(!__builtin_constant_p((A{}, 123)));
161+
// FIXME: We should probably accept this. GCC does.
162+
// However, GCC appears to do so by running the destructors at the end of the
163+
// enclosing full-expression, which seems broken; running them at the end of
164+
// the evaluation of the __builtin_constant_p argument would be more
165+
// defensible.
166+
static_assert(!__builtin_constant_p((A{Q().get()}, 123)));
167+
}
168+
#endif

0 commit comments

Comments
 (0)