// RUN: %clang_cc1 -std=c++17 -verify %s
// RUN: %clang_cc1 -std=c++20 -verify %s
using intptr_t = __INTPTR_TYPE__;
// Test interaction of constexpr and __builtin_constant_p.
constexpr bool
constexpr bool
constexpr intptr_t ensure_fold_is_generally_not_enabled = // expected-error {{constant expression}}
&ensure_fold_is_generally_not_enabled; // expected-note {{cast}}
constexpr intptr_t
constexpr int *
int x;
// Integer and floating point constants encountered during constant expression
// evaluation are considered constant. So is nullptr_t.
static_assert;
static_assert;
static_assert;
static_assert;
static_assert;
static_assert;
// Pointers to the start of strings are considered constant.
static_assert;
static_assert;
// Null pointers are considered constant.
static_assert;
static_assert;
static_assert;
static_assert;
// Other pointers are not.
static_assert;
static_assert;
// Pointers cast to integers follow the rules for pointers.
static_assert;
static_assert;
static_assert;
static_assert;
// Integers cast to pointers follow the integer rules.
static_assert;
static_assert;
static_assert; // GCC rejects these due to not recognizing
static_assert; // the bcp conditional in 'int_to_ptr' ...
static_assert; // ... 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.
constexpr int
static_assert;
// 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
static_assert;
constexpr int
constexpr int
static_assert;
constexpr int
static_assert;
// FIXME: GCC treats this as being non-constant because of something to do with
// the 'n' in the argument to internal_mutation.
constexpr int
static_assert;
constexpr int
constexpr int
// No mutation of state outside __builtin_constant_p: evaluates to true.
static_assert;
// Mutation of state outside __builtin_constant_p: evaluates to false.
static_assert;
// 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.
static_assert;
void