Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4566,13 +4566,8 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
//
// FIXME: Not all local state is mutable. Allow local constant subobjects
// to be read here (but take care with 'mutable' fields).
unsigned VisibleDepth = Depth;
if (llvm::isa_and_nonnull<ParmVarDecl>(
LVal.Base.dyn_cast<const ValueDecl *>()))
++VisibleDepth;
if ((Frame && Info.getLangOpts().CPlusPlus14 &&
Info.EvalStatus.HasSideEffects) ||
(isModification(AK) && VisibleDepth < Info.SpeculativeEvaluationDepth))
Info.EvalStatus.HasSideEffects))
return CompleteObject();

return CompleteObject(LVal.getLValueBase(), BaseVal, BaseType);
Expand Down
6 changes: 2 additions & 4 deletions clang/test/AST/ByteCode/builtin-constant-p.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,7 @@ constexpr int mutate1() {
int m = __builtin_constant_p(++n);
return n * 10 + m;
}
static_assert(mutate1() == 21); // ref-error {{static assertion failed}} \
// ref-note {{evaluates to '10 == 21'}}
static_assert(mutate1() == 21);

/// Similar for this. GCC agrees with the bytecode interpreter.
constexpr int mutate_param(bool mutate, int &param) {
Expand All @@ -119,8 +118,7 @@ constexpr int mutate6(bool mutate) {
return n * 10 + m;
}
static_assert(mutate6(false) == 11);
static_assert(mutate6(true) == 21); // ref-error {{static assertion failed}} \
// ref-note {{evaluates to '10 == 21'}}
static_assert(mutate6(true) == 21);

#define fold(x) (__builtin_constant_p(x) ? (x) : (x))
void g() {
Expand Down
22 changes: 6 additions & 16 deletions clang/test/SemaCXX/builtin-constant-p.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,25 +61,14 @@ static_assert(bcp(int_to_ptr(123))); // GCC rejects these due to not recogn
static_assert(bcp_fold(int_to_ptr(123))); // the bcp conditional in 'int_to_ptr' ...
static_assert(__builtin_constant_p((int*)123)); // ... but GCC accepts this

// State mutations in the operand are not permitted.
//
// The rule GCC uses for this is not entirely understood, but seems to depend
// in some way on what local state is mentioned in the operand of
// __builtin_constant_p and where.
//
// We approximate GCC's rule by evaluating the operand in a speculative
// evaluation context; only state created within the evaluation can be
// modified.
// State mutations in the operand are permitted.
constexpr int mutate1() {
int n = 1;
int m = __builtin_constant_p(++n);
return n * 10 + m;
}
static_assert(mutate1() == 10);
static_assert(mutate1() == 21);

// FIXME: GCC treats this as being non-constant because of the "n = 2", even
// though evaluation in the context of the enclosing constant expression
// succeeds without mutating any state.
constexpr int mutate2() {
int n = 1;
int m = __builtin_constant_p(n ? n + 1 : n = 2);
Expand Down Expand Up @@ -107,8 +96,6 @@ constexpr int mutate4() {
}
static_assert(mutate4() == 11);

// FIXME: GCC treats this as being non-constant because of something to do with
// the 'n' in the argument to internal_mutation.
constexpr int mutate5() {
int n = 1;
int m = __builtin_constant_p(n ? internal_mutation(n) : 0);
Expand All @@ -130,7 +117,7 @@ constexpr int mutate6(bool mutate) {
// No mutation of state outside __builtin_constant_p: evaluates to true.
static_assert(mutate6(false) == 11);
// Mutation of state outside __builtin_constant_p: evaluates to false.
static_assert(mutate6(true) == 10);
static_assert(mutate6(true) == 21);

// GCC strangely returns true for the address of a type_info object, despite it
// not being a pointer to the start of a string literal.
Expand All @@ -151,6 +138,9 @@ namespace dtor_side_effect {
}

#if __cplusplus >= 202002L

static_assert(__builtin_constant_p((delete new int, 0))); // expected-error {{failed}}

namespace constexpr_dtor {
struct A {
int *p;
Expand Down
Loading