DR1684: a constexpr member function need not be a member of a literal class type.

llvm-svn: 224388
This commit is contained in:
Richard Smith 2014-12-16 23:12:52 +00:00
parent 5413abf88f
commit d52186ff5a
9 changed files with 1201 additions and 616 deletions

View File

@ -1897,8 +1897,6 @@ def err_constexpr_ctor_missing_init : Error<
"constexpr constructor must initialize all members">;
def note_constexpr_ctor_missing_init : Note<
"member not initialized by constructor">;
def err_constexpr_method_non_literal : Error<
"non-literal type %0 cannot have constexpr members">;
def note_non_literal_no_constexpr_ctors : Note<
"%0 is not literal because it is not an aggregate and has no constexpr "
"constructors other than copy or move constructors">;

View File

@ -4894,42 +4894,6 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
for (auto *M : Record->methods())
DiagnoseAbsenceOfOverrideControl(M);
}
// C++11 [dcl.constexpr]p8: A constexpr specifier for a non-static member
// function that is not a constructor declares that member function to be
// const. [...] The class of which that function is a member shall be
// a literal type.
//
// If the class has virtual bases, any constexpr members will already have
// been diagnosed by the checks performed on the member declaration, so
// suppress this (less useful) diagnostic.
//
// We delay this until we know whether an explicitly-defaulted (or deleted)
// destructor for the class is trivial.
if (LangOpts.CPlusPlus11 && !Record->isDependentType() &&
!Record->isLiteral() && !Record->getNumVBases()) {
for (const auto *M : Record->methods()) {
if (M->isConstexpr() && M->isInstance() && !isa<CXXConstructorDecl>(M)) {
switch (Record->getTemplateSpecializationKind()) {
case TSK_ImplicitInstantiation:
case TSK_ExplicitInstantiationDeclaration:
case TSK_ExplicitInstantiationDefinition:
// If a template instantiates to a non-literal type, but its members
// instantiate to constexpr functions, the template is technically
// ill-formed, but we allow it for sanity.
continue;
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
RequireLiteralType(M->getLocation(), Context.getRecordType(Record),
diag::err_constexpr_method_non_literal);
break;
}
// Only produce one error per class.
break;
}
}
}
// ms_struct is a request to use the same ABI rules as MSVC. Check
// whether this class uses any C++ features that are implemented

View File

@ -38,15 +38,14 @@ constexpr ClassTemp<int> classtemplate2[] = {};
// - it has a trivial destructor
struct UserProvDtor {
constexpr int f() const; // expected-error {{non-literal type 'UserProvDtor' cannot have constexpr members}}
~UserProvDtor(); // expected-note {{has a user-provided destructor}}
};
constexpr int f(UserProvDtor) { return 0; } // expected-error {{'UserProvDtor' is not a literal type}}
struct NonTrivDtor {
constexpr NonTrivDtor();
constexpr int f() const; // expected-error {{non-literal type 'NonTrivDtor' cannot have constexpr members}}
virtual ~NonTrivDtor() = default; // expected-note {{has a non-trivial destructor}} expected-note {{because it is virtual}}
};
constexpr int f(NonTrivDtor) { return 0; } // expected-error {{'NonTrivDtor' is not a literal type}}
struct NonTrivDtorBase {
~NonTrivDtorBase();
};
@ -77,12 +76,12 @@ struct CtorTemplate {
};
struct CopyCtorOnly { // expected-note {{'CopyCtorOnly' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
constexpr CopyCtorOnly(CopyCtorOnly&);
constexpr int f() const; // expected-error {{non-literal type 'CopyCtorOnly' cannot have constexpr members}}
};
constexpr int f(CopyCtorOnly) { return 0; } // expected-error {{'CopyCtorOnly' is not a literal type}}
struct MoveCtorOnly { // expected-note {{no constexpr constructors other than copy or move constructors}}
constexpr MoveCtorOnly(MoveCtorOnly&&);
constexpr int f() const; // expected-error {{non-literal type 'MoveCtorOnly' cannot have constexpr members}}
};
constexpr int f(MoveCtorOnly) { return 0; } // expected-error {{'MoveCtorOnly' is not a literal type}}
template<typename T>
struct CtorArg {
constexpr CtorArg(T);
@ -110,8 +109,8 @@ constexpr int f(NonLitMember) {} // expected-error {{1st parameter type 'NonLitM
struct NonLitBase :
S { // expected-note {{base class 'S' of non-literal type}}
constexpr NonLitBase();
constexpr int f() const { return 0; } // expected-error {{non-literal type 'NonLitBase' cannot have constexpr members}}
};
constexpr int f(NonLitBase) { return 0; } // expected-error {{'NonLitBase' is not a literal type}}
struct LitMemBase : Agg {
Agg agg;
};

View File

@ -27,9 +27,9 @@ struct SS : S {
// The definition of a constexpr function shall satisfy the following
// constraints:
struct T : SS, NonLiteral { // expected-note {{base class 'NonLiteral' of non-literal type}}
struct T : SS, NonLiteral {
constexpr T();
constexpr int f() const; // expected-error {{non-literal type 'T' cannot have constexpr members}}
constexpr int f() const;
// - it shall not be virtual;
virtual constexpr int ExplicitlyVirtual() const { return 0; } // expected-error {{virtual function cannot be constexpr}}

View File

@ -36,10 +36,10 @@ template<typename T> constexpr T S::ts() { return T(); }
namespace std_example {
class debug_flag { // expected-note {{not an aggregate and has no constexpr constructors}}
class debug_flag {
public:
explicit debug_flag(bool);
constexpr bool is_on() const; // expected-error {{non-literal type 'std_example::debug_flag' cannot have constexpr members}}
constexpr bool is_on() const; // ok (dr1684)
private:
bool flag;
};

View File

@ -5,13 +5,13 @@
// expected-no-diagnostics
namespace DR1550 { // dr1550: yes
namespace dr1550 { // dr1550: yes
int f(bool b, int n) {
return (b ? (throw 0) : n) + (b ? n : (throw 0));
}
}
namespace DR1560 { // dr1560: 3.5
namespace dr1560 { // dr1560: 3.5
void f(bool b, int n) {
(b ? throw 0 : n) = (b ? n : throw 0) = 0;
}

View File

@ -7,7 +7,7 @@
// expected-no-diagnostics
#endif
void dr1891() { // dr1891: yes
void dr1891() { // dr1891: 3.6
#if __cplusplus >= 201103L
int n;
auto a = []{}; // expected-note 2{{candidate}}

View File

@ -206,7 +206,7 @@ namespace dr313 { // dr313: dup 299 c++11
#endif
}
namespace dr314 { // dr314: dup 1710
namespace dr314 { // FIXME 314: dup 1710
template<typename T> struct A {
template<typename U> struct B {};
};
@ -505,7 +505,7 @@ namespace dr341 {
// dr342: na
namespace dr343 { // dr343: no
namespace dr343 { // FIXME 343: no
// FIXME: dup 1710
template<typename T> struct A {
template<typename U> struct B {};

File diff suppressed because it is too large Load Diff