forked from OSchip/llvm-project
DR1684: a constexpr member function need not be a member of a literal class type.
llvm-svn: 224388
This commit is contained in:
parent
5413abf88f
commit
d52186ff5a
|
@ -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">;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue