1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-unknown-unknown -verify -std=c++11 -fcxx-exceptions %s
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-unknown-unknown -verify -std=c++14 -fcxx-exceptions %s
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-unknown-unknown -std=c++11 -fcxx-exceptions -Wno-invalid-constexpr %s -DNO_INVALID_CONSTEXPR
namespace StdExample {
constexpr int f(void *) { return 0; }
constexpr int f(...) { return 1; }
constexpr int g1() { return f(0); }
constexpr int g2(int n) { return f(n); }
constexpr int g3(int n) { return f(n*0); }
namespace N {
constexpr int c = 5;
constexpr int h() { return c; }
}
constexpr int c = 0;
constexpr int g4() { return N::h(); }
static_assert(f(0) == 0, "");
static_assert(f('0') == 1, "");
static_assert(g1() == 0, "");
static_assert(g2(0) == 1, "");
static_assert(g2(1) == 1, "");
static_assert(g3(0) == 1, "");
static_assert(g3(1) == 1, "");
static_assert(N::h() == 5, "");
static_assert(g4() == 5, "");
constexpr int f(bool b)
{ return b ? throw 0 : 0; } // ok
constexpr int f() { return throw 0, 0; } // expected-error {{constexpr function never produces a constant expression}} expected-note {{subexpression}}
struct B {
constexpr B(int x) : i(0) { }
int i;
};
int global; // expected-note {{declared here}}
struct D : B {
constexpr D() : B(global) { } // expected-error {{constexpr constructor never produces a constant expression}} expected-note {{read of non-const}}
};
}
namespace PotentialConstant {
constexpr int Comma(int n) { return // expected-error {{constexpr function never produces a constant expression}}
(void)(n * 2),
throw 0, // expected-note {{subexpression}}
0;
}
int ng; // expected-note 6{{here}}
constexpr int BinaryOp1(int n) { return n + ng; } // expected-error {{never produces}} expected-note {{read}}
constexpr int BinaryOp2(int n) { return ng + n; } // expected-error {{never produces}} expected-note {{read}}
double dg; // expected-note 2{{here}}
constexpr double BinaryOp1(double d) { return d + dg; } // expected-error {{never produces}} expected-note {{read}}
constexpr double BinaryOp2(double d) { return dg + d; } // expected-error {{never produces}} expected-note {{read}}
constexpr int Add(int a, int b, int c) { return a + b + c; }
constexpr int FunctionArgs(int a) { return Add(a, ng, a); } // expected-error {{never produces}} expected-note {{read}}
struct S { int a; int b; int c[2]; };
constexpr S InitList(int a) { return { a, ng }; }; // expected-error {{never produces}} expected-note {{read}}
constexpr S InitList1a(int a) { return S{ a, ng }; }; // expected-error {{never produces}} expected-note {{read}}
constexpr S InitList2(int a) { return { a, a, { ng } }; }; // expected-error {{never produces}} expected-note {{read}}
constexpr S InitList3(int a) { return a ? S{ a, a } : S{ a, ng }; }; // ok
constexpr int LogicalAnd1(int n) { return n && (throw, 0); } // ok
constexpr int LogicalAnd2(int n) { return 1 && (throw, 0); } // expected-error {{never produces}} expected-note {{subexpression}}
constexpr int LogicalOr1(int n) { return n || (throw, 0); } // ok
constexpr int LogicalOr2(int n) { return 0 || (throw, 0); } // expected-error {{never produces}} expected-note {{subexpression}}
constexpr int Conditional1(bool b, int n) { return b ? n : ng; } // ok
constexpr int Conditional2(bool b, int n) { return b ? n * ng : n + ng; } // expected-error {{never produces}} expected-note {{both arms of conditional operator are unable to produce a constant expression}}
// __builtin_constant_p ? : is magical, and is always a potential constant.
constexpr bool BcpCall(int n) {
return __builtin_constant_p((int*)n != &n) ? (int*)n != &n : (int*)n != &n; // expected-warning 3 {{cast to 'int *' from smaller integer type 'int'}}
}
static_assert(BcpCall(0), "");
// DR1311: A function template which can produce a constant expression, but
// for which a particular specialization cannot, is ok.
template<typename T> constexpr T cmin(T a, T b) {
return a < b ? a : b;
}
int n = cmin(3, 5); // ok
struct X {
constexpr X() {}
bool operator<(X); // not constexpr
};
X x = cmin(X(), X()); // ok, not constexpr
// Same with other temploids.
template<typename T>
struct Y {
constexpr Y() {}
constexpr int get() { return T(); }
#if __cplusplus < 201402L
// expected-warning@-2 {{C++14}}
#endif
};
struct Z { operator int(); };
int y1 = Y<int>().get(); // ok
int y2 = Y<Z>().get(); // ok
}
#ifndef NO_INVALID_CONSTEXPR
namespace PR14550 {
// As an "extension", we allow functions which can't produce constant
// expressions to be declared constexpr in system headers (libstdc++
// marks some functions as constexpr which use builtins which we don't
// support constant folding). Ensure that we don't mark those functions
// as invalid after suppressing the diagnostic.
# 126 "p5.cpp" 1 3
int n;
struct A {
static constexpr int f() { return n; }
};
template<typename T> struct B {
B() { g(T::f()); } // expected-error {{undeclared identifier 'g'}}
};
# 134 "p5.cpp" 2
template class B<A>; // expected-note {{here}}
}
#endif
#if __cplusplus >= 201402L
constexpr void f() { throw; } // expected-error {{never produces}} expected-note {{subexpression}}
#endif
|