r360370 - DR1872: don't allow any calls to virtual functions in constant
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu May 9 12:45:50 PDT 2019
Author: rsmith
Date: Thu May 9 12:45:49 2019
New Revision: 360370
URL: http://llvm.org/viewvc/llvm-project?rev=360370&view=rev
Log:
DR1872: don't allow any calls to virtual functions in constant
evaluation.
Not even in cases where we would not actually perform virtual dispatch.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp
cfe/trunk/test/CXX/drs/dr13xx.cpp
cfe/trunk/test/CXX/drs/dr18xx.cpp
cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
cfe/trunk/test/SemaCXX/constant-expression-cxx1y.cpp
cfe/trunk/www/cxx_dr_status.html
Modified: cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td?rev=360370&r1=360369&r2=360370&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td Thu May 9 12:45:49 2019
@@ -31,7 +31,7 @@ def note_constexpr_invalid_inhctor : Not
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">;
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=360370&r1=360369&r2=360370&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Thu May 9 12:45:49 2019
@@ -4381,6 +4381,14 @@ static bool CheckConstexprFunction(EvalI
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)
@@ -4999,12 +5007,6 @@ public:
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);
Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp?rev=360370&r1=360369&r2=360370&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp Thu May 9 12:45:49 2019
@@ -27,9 +27,9 @@ template<typename T> struct ImplicitVirt
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; }
Modified: cfe/trunk/test/CXX/drs/dr13xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr13xx.cpp?rev=360370&r1=360369&r2=360370&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr13xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr13xx.cpp Thu May 9 12:45:49 2019
@@ -267,6 +267,42 @@ namespace dr1347 { // dr1347: yes
#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; };
Modified: cfe/trunk/test/CXX/drs/dr18xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr18xx.cpp?rev=360370&r1=360369&r2=360370&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr18xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr18xx.cpp Thu May 9 12:45:49 2019
@@ -1,7 +1,8 @@
// 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 at +1 {{variadic macro}}
@@ -41,6 +42,23 @@ namespace dr1815 { // dr1815: no
#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; };
@@ -56,19 +74,31 @@ namespace dr1881 { // dr1881: 7
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 at -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 at -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 at -3 {{copy assignment operator is implicitly deleted}}
+ // expected-error at -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
Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=360370&r1=360369&r2=360370&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Thu May 9 12:45:49 2019
@@ -1862,7 +1862,7 @@ namespace VirtualFromBase {
// 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;
Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx1y.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx1y.cpp?rev=360370&r1=360369&r2=360370&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constant-expression-cxx1y.cpp (original)
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx1y.cpp Thu May 9 12:45:49 2019
@@ -841,7 +841,7 @@ namespace VirtualFromBase {
// 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 {
Modified: cfe/trunk/www/cxx_dr_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_dr_status.html?rev=360370&r1=360369&r2=360370&view=diff
==============================================================================
--- cfe/trunk/www/cxx_dr_status.html (original)
+++ cfe/trunk/www/cxx_dr_status.html Thu May 9 12:45:49 2019
@@ -7963,7 +7963,7 @@ and <I>POD class</I></td>
<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>
@@ -11047,7 +11047,7 @@ and <I>POD class</I></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>
More information about the cfe-commits
mailing list