if (TREE_CODE (r) == TARGET_EXPR
&& TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR)
r = TARGET_EXPR_INITIAL (r);
- if (DECL_P (r))
+ if (DECL_P (r)
+ /* P2280 allows references to unknown. */
+ && !(VAR_P (t) && TYPE_REF_P (TREE_TYPE (t))))
{
if (!ctx->quiet)
non_const_var_error (loc, r, /*fundef_p*/false);
r = build_constructor (TREE_TYPE (t), NULL);
TREE_CONSTANT (r) = true;
}
+ else if (TYPE_REF_P (TREE_TYPE (t)))
+ /* P2280 allows references to unknown... */;
+ else if (is_this_parameter (t))
+ /* ...as well as the this pointer. */;
else
{
if (!ctx->quiet)
static_assert(sz_d == 3, "Array size failure");
void f(bool (¶m)[2]) {
- static_assert(size(param) == 2, "Array size failure"); // { dg-error "" }
+ static_assert(size(param) == 2, "Array size failure");
short data[] = {-1, 2, -45, 6, 88, 99, -345};
static_assert(size(data) == 7, "Array size failure");
}
static_assert (g(ar2),""); // { dg-error "constant" }
static_assert (h(ar2),""); // { dg-error "constant" }
- static_assert (arp.g(),""); // { dg-error "constant" }
- static_assert (g(arp),""); // { dg-error "constant" }
+ static_assert (arp.g(),"");
+ static_assert (g(arp),"");
static_assert (h(arp),""); // { dg-error "constant" }
}
--- /dev/null
+// P2280R4 - Using unknown pointers and references in constant expressions
+// PR c++/106650
+// { dg-do compile { target c++11 } }
+
+using size_t = decltype(sizeof(42));
+
+template <typename T, size_t N>
+constexpr auto array_size(T (&)[N]) -> size_t {
+ return N;
+}
+
+extern int (&r)[42];
+constexpr int i = array_size (r);
+
+void check(int const (¶m)[3]) {
+ int local[] = {1, 2, 3};
+ constexpr auto s0 = array_size(local);
+ constexpr auto s1 = array_size(param);
+}
+
+template <typename T, size_t N>
+constexpr size_t array_size_ptr(T (*)[N]) {
+ return N;
+}
+
+void check_ptr(int const (*param)[3]) {
+ constexpr auto s2 = array_size_ptr(param); // { dg-error "not a constant" }
+}
+
+struct A
+{
+ constexpr int f() { return 42; }
+ void g() { constexpr int i = f(); }
+ void g2() { constexpr int i = this->f(); }
+};
+
+struct B {
+ constexpr static bool b = false;
+ void g() noexcept(b) { }
+ void g2() noexcept(this->b) { }
+};
extern int *p;
constexpr int& ri = *p; // { dg-error "p" }
-extern constexpr int &er; // { dg-error "not a definition" }
-constexpr int& ri2 = er; // { dg-error "er" }
+extern constexpr int &er; // { dg-error "not a definition|not a constant" }
+constexpr int& ri2 = er;
void f(int j)
{
{
constexpr int f () { return 0; }
bool b = true;
- void g () noexcept (f()) { } // { dg-error ".this. is not a constant" }
- void g2 () noexcept (this->f()) { } // { dg-error ".this. is not a constant" }
+ void g () noexcept (f()) { }
+ void g2 () noexcept (this->f()) { }
void g3 () noexcept (b) { } // { dg-error "use of .this. in a constant expression|use of parameter|.this. is not a constant" }
void g4 (int i) noexcept (i) { } // { dg-error "use of parameter" }
- void g5 () noexcept (A::f()) { } // { dg-error ".this. is not a constant" }
+ void g5 () noexcept (A::f()) { }
void g6 () noexcept (foo(b)) { } // { dg-error "use of .this. in a constant expression|use of parameter|.this. is not a constant" }
- void g7 () noexcept (int{f()}) { } // { dg-error ".this. is not a constant" }
+ void g7 () noexcept (int{f()}) { }
};
int main ()
constexpr auto x = f(); //ok, call constexpr const non-static method
[](auto const &f) {
- constexpr auto x = f(); // { dg-error "" }
+ constexpr auto x = f();
}(f);
[&]() {
--- /dev/null
+// P2280R4 - Using unknown pointers and references in constant expressions
+// PR c++/106650
+// { dg-do compile { target c++17 } }
+
+#include <type_traits>
+
+template <typename T, typename U>
+constexpr bool is_type(U &&)
+{
+ return std::is_same_v<T, std::decay_t<U>>;
+}
+
+auto visitor = [](auto&& v) {
+ if constexpr(is_type<int>(v)) {
+ // ...
+ } else if constexpr(is_type<char>(v)) {
+ // ...
+ }
+};
+
+void
+g (int i)
+{
+ visitor (i);
+ constexpr bool b = is_type<int>(i);
+}
--- /dev/null
+// P2280R4 - Using unknown pointers and references in constant expressions
+// PR c++/106650
+// { dg-do compile { target c++17 } }
+
+template <bool V>
+struct Widget {
+ struct Config {
+ static constexpr bool value = V;
+ } config;
+
+ void f() {
+ if constexpr (config.value) {
+ // ...
+ }
+ }
+};
+
+void
+g ()
+{
+ Widget<false> w;
+ w.f();
+}
--- /dev/null
+// P2280R4 - Using unknown pointers and references in constant expressions
+// PR c++/106650
+// { dg-do compile { target c++20 } }
+
+#include <typeinfo>
+
+using size_t = decltype(sizeof(42));
+
+template <typename T, size_t N>
+constexpr size_t array_size(T (&)[N]) {
+ return N;
+}
+
+void use_array(int const (&gold_medal_mel)[2]) {
+ constexpr auto gold = array_size(gold_medal_mel); // OK
+}
+
+constexpr auto olympic_mile() {
+ const int ledecky = 1500;
+ return []{ return ledecky; };
+}
+static_assert(olympic_mile()() == 1500); // OK
+
+struct Swim {
+ constexpr int phelps() { return 28; }
+ virtual constexpr int lochte() { return 12; }
+ int coughlin = 12;
+};
+
+constexpr int how_many(Swim& swam) {
+ Swim* p = &swam;
+ return (p + 1 - 1)->phelps();
+}
+
+void splash(Swim& swam) {
+ static_assert(swam.phelps() == 28); // OK
+ static_assert((&swam)->phelps() == 28); // OK
+
+ Swim* pswam = &swam;
+ static_assert(pswam->phelps() == 28); // { dg-error "non-constant|not usable" }
+
+ static_assert(how_many(swam) == 28); // OK
+ static_assert(Swim().lochte() == 12); // OK
+
+ static_assert(swam.lochte() == 12); // { dg-error "non-constant|not a constant" }
+
+ static_assert(swam.coughlin == 12); // { dg-error "non-constant|not a constant" }
+}
+
+extern Swim dc;
+extern Swim& trident;
+
+constexpr auto& sandeno = typeid(dc); // OK, can only be typeid(Swim)
+constexpr auto& gallagher = typeid(trident); // { dg-error "not a constant" }