def note_constexpr_no_return : Note<
"control reached end of constexpr function">;
def note_constexpr_virtual_call : Note<
- "cannot evaluate virtual function call in a constant expression">;
+ "cannot evaluate call to virtual function in a constant expression">;
def note_constexpr_virtual_base : Note<
"cannot construct object of type %0 with virtual base class "
"in a constant expression">;
return false;
}
+ // DR1872: An instantiated virtual constexpr function can't be called in a
+ // constant expression.
+ if (isa<CXXMethodDecl>(Declaration) &&
+ cast<CXXMethodDecl>(Declaration)->isVirtual()) {
+ Info.FFDiag(CallLoc, diag::note_constexpr_virtual_call);
+ return false;
+ }
+
// Can we evaluate this function call?
if (Definition && Definition->isConstexpr() &&
!Definition->isInvalidDecl() && Body)
if (This && !This->checkSubobject(Info, E, CSK_This))
return false;
- // DR1358 allows virtual constexpr functions in some cases. Don't allow
- // calls to such functions in constant expressions.
- if (This && !HasQualifier &&
- isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isVirtual())
- return Error(E, diag::note_constexpr_virtual_call);
-
const FunctionDecl *Definition = nullptr;
Stmt *Body = FD->getBody(Definition);
constexpr int ImplicitlyVirtual() const { return 0; }
};
-constexpr int a = ImplicitVirtualFromDependentBase<S>().ImplicitlyVirtual(); // expected-error {{constant expression}} expected-note {{cannot evaluate virtual function call}}
+constexpr int a = ImplicitVirtualFromDependentBase<S>().ImplicitlyVirtual(); // expected-error {{constant expression}} expected-note {{cannot evaluate call to virtual function}}
constexpr int b = ImplicitVirtualFromDependentBase<T>().ImplicitlyVirtual(); // ok
-constexpr int c = ImplicitVirtualFromDependentBase<S>().ImplicitVirtualFromDependentBase<S>::ImplicitlyVirtual();
+constexpr int c = ImplicitVirtualFromDependentBase<S>().ImplicitVirtualFromDependentBase<S>::ImplicitlyVirtual(); // expected-error {{constant expression}} expected-note {{cannot evaluate call to virtual function}}
template<typename R> struct ConstexprMember {
constexpr R F() const { return 0; }
#endif
}
+namespace dr1358 { // dr1358: yes
+#if __cplusplus >= 201103L
+ struct Lit { constexpr operator int() const { return 0; } };
+ struct NonLit { NonLit(); operator int(); }; // expected-note 2{{no constexpr constructors}}
+ struct NonConstexprConv { constexpr operator int() const; };
+ struct Virt { virtual int f(int) const; };
+
+ template<typename T, typename U, typename V> struct A : V {
+ int member;
+ constexpr A(U u) : member(u) {}
+ constexpr T f(U u) const { return T(); }
+ };
+
+ constexpr A<Lit, Lit, Lit> ce = Lit();
+ constexpr int k = ce.f(Lit{});
+
+ // Can have a non-literal return type and parameter type.
+ // Constexpr function can be implicitly virtual.
+ A<NonLit, NonLit, Virt> a = NonLit();
+ void g() { a.f(NonLit()); }
+
+ // Constructor is still constexpr, so this is a literal type.
+ static_assert(__is_literal_type(decltype(a)), "");
+
+ // Constructor can call non-constexpr functions.
+ A<Lit, NonConstexprConv, Lit> b = NonConstexprConv();
+
+ // But the corresponding non-template cases are rejected.
+ struct B : Virt {
+ int member;
+ constexpr B(NonLit u) : member(u) {} // expected-error {{not a literal type}}
+ constexpr NonLit f(NonLit u) const { return NonLit(); } // expected-error {{not a literal type}}
+ };
+#endif
+}
+
namespace dr1359 { // dr1359: 3.5
#if __cplusplus >= 201103L
union A { constexpr A() = default; };
// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++2a -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
#if __cplusplus < 201103L
// expected-error@+1 {{variadic macro}}
#endif
}
+namespace dr1872 { // dr1872: 9
+#if __cplusplus >= 201103L
+ template<typename T> struct A : T {
+ constexpr int f() const { return 0; }
+ };
+ struct X {};
+ struct Y { virtual int f() const; };
+ struct Z : virtual X {};
+
+ constexpr int x = A<X>().f();
+ constexpr int y = A<Y>().f(); // expected-error {{constant expression}} expected-note {{call to virtual function}}
+ // Note, this is invalid even though it would not use virtual dispatch.
+ constexpr int y2 = A<Y>().A<Y>::f(); // expected-error {{constant expression}} expected-note {{call to virtual function}}
+ constexpr int z = A<Z>().f(); // expected-error {{constant expression}} expected-note {{non-literal type}}
+#endif
+}
+
namespace dr1881 { // dr1881: 7
struct A { int a : 4; };
struct B : A { int b : 3; };
void dr1891() { // dr1891: 4
#if __cplusplus >= 201103L
int n;
- auto a = []{}; // expected-note 2{{candidate}} expected-note 2{{here}}
- auto b = [=]{ return n; }; // expected-note 2{{candidate}} expected-note 2{{here}}
+ auto a = []{}; // expected-note 0-4{{}}
+ auto b = [=]{ return n; }; // expected-note 0-4{{}}
typedef decltype(a) A;
typedef decltype(b) B;
static_assert(!__has_trivial_constructor(A), "");
+#if __cplusplus > 201703L
+ // expected-error@-2 {{failed}}
+#endif
static_assert(!__has_trivial_constructor(B), "");
- A x; // expected-error {{no matching constructor}}
+ // C++20 allows default construction for non-capturing lambdas (P0624R2).
+ A x;
+#if __cplusplus <= 201703L
+ // expected-error@-2 {{no matching constructor}}
+#endif
B y; // expected-error {{no matching constructor}}
- a = a; // expected-error {{copy assignment operator is implicitly deleted}}
- a = static_cast<A&&>(a); // expected-error {{copy assignment operator is implicitly deleted}}
+ // C++20 allows assignment for non-capturing lambdas (P0624R2).
+ a = a;
+ a = static_cast<A&&>(a);
+#if __cplusplus <= 201703L
+ // expected-error@-3 {{copy assignment operator is implicitly deleted}}
+ // expected-error@-3 {{copy assignment operator is implicitly deleted}}
+#endif
b = b; // expected-error {{copy assignment operator is implicitly deleted}}
b = static_cast<B&&>(b); // expected-error {{copy assignment operator is implicitly deleted}}
#endif
// Virtual f(), not OK.
constexpr X<X<S1>> xxs1;
constexpr X<S1> *p = const_cast<X<X<S1>>*>(&xxs1);
- static_assert(p->f() == sizeof(X<S1>), ""); // expected-error {{constant expression}} expected-note {{virtual function call}}
+ static_assert(p->f() == sizeof(X<S1>), ""); // expected-error {{constant expression}} expected-note {{virtual function}}
// Non-virtual f(), OK.
constexpr X<X<S2>> xxs2;
// Virtual f(), not OK.
constexpr X<X<S2>> xxs2;
constexpr X<S2> *q = const_cast<X<X<S2>>*>(&xxs2);
- static_assert(q->f() == sizeof(X<S2>), ""); // expected-error {{constant expression}} expected-note {{virtual function call}}
+ static_assert(q->f() == sizeof(X<S2>), ""); // expected-error {{constant expression}} expected-note {{virtual function}}
}
namespace Lifetime {
<td><a href="http://wg21.link/cwg1358">1358</a></td>
<td>CD3</td>
<td>Unintentionally ill-formed <TT>constexpr</TT> function template instances</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="1359">
<td><a href="http://wg21.link/cwg1359">1359</a></td>
<td><a href="http://wg21.link/cwg1872">1872</a></td>
<td>CD4</td>
<td>Instantiations of <TT>constexpr</TT> templates that cannot appear in constant expressions</td>
- <td class="none" align="center">Unknown</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr id="1873">
<td><a href="http://wg21.link/cwg1873">1873</a></td>