Clean up diagnostics for inheriting constructors.
No new diagnostics, just better wording and notes pointing at more relevant locations. llvm-svn: 186629
This commit is contained in:
parent
b946407cb7
commit
ebea0f29e2
|
@ -3398,6 +3398,10 @@ def note_unavailable_here : Note<
|
|||
"%select{unavailable|deleted|deprecated}1 here">;
|
||||
def note_implicitly_deleted : Note<
|
||||
"explicitly defaulted function was implicitly deleted here">;
|
||||
def note_inherited_deleted_here : Note<
|
||||
"deleted constructor was inherited here">;
|
||||
def note_cannot_inherit : Note<
|
||||
"constructor cannot be inherited">;
|
||||
def warn_not_enough_argument : Warning<
|
||||
"not enough variable arguments in %0 declaration to fit a sentinel">,
|
||||
InGroup<Sentinel>;
|
||||
|
|
|
@ -9991,9 +9991,7 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
|
|||
}
|
||||
|
||||
bool Sema::isImplicitlyDeleted(FunctionDecl *FD) {
|
||||
return FD->isDeleted() &&
|
||||
(FD->isDefaulted() || FD->isImplicit()) &&
|
||||
isa<CXXMethodDecl>(FD);
|
||||
return FD->isDeleted() && FD->isDefaulted() && isa<CXXMethodDecl>(FD);
|
||||
}
|
||||
|
||||
/// \brief Mark the call operator of the given lambda closure type as "used".
|
||||
|
|
|
@ -140,11 +140,13 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S,
|
|||
return Result;
|
||||
}
|
||||
|
||||
/// \brief Emit a note explaining that this function is deleted or unavailable.
|
||||
/// \brief Emit a note explaining that this function is deleted.
|
||||
void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
|
||||
assert(Decl->isDeleted());
|
||||
|
||||
CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Decl);
|
||||
|
||||
if (Method && Method->isDeleted() && !Method->isDeletedAsWritten()) {
|
||||
if (Method && Method->isDeleted() && Method->isDefaulted()) {
|
||||
// If the method was explicitly defaulted, point at that declaration.
|
||||
if (!Method->isImplicit())
|
||||
Diag(Decl->getLocation(), diag::note_implicitly_deleted);
|
||||
|
@ -158,8 +160,23 @@ void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(Decl)) {
|
||||
if (CXXConstructorDecl *BaseCD =
|
||||
const_cast<CXXConstructorDecl*>(CD->getInheritedConstructor())) {
|
||||
Diag(Decl->getLocation(), diag::note_inherited_deleted_here);
|
||||
if (BaseCD->isDeleted()) {
|
||||
NoteDeletedFunction(BaseCD);
|
||||
} else {
|
||||
// FIXME: An explanation of why exactly it can't be inherited
|
||||
// would be nice.
|
||||
Diag(BaseCD->getLocation(), diag::note_cannot_inherit);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Diag(Decl->getLocation(), diag::note_unavailable_here)
|
||||
<< 1 << Decl->isDeleted();
|
||||
<< 1 << true;
|
||||
}
|
||||
|
||||
/// \brief Determine whether a FunctionDecl was ever declared with an
|
||||
|
|
|
@ -2,31 +2,30 @@
|
|||
// Per a core issue (no number yet), an ellipsis is always dropped.
|
||||
struct A {
|
||||
A(...); // expected-note {{here}}
|
||||
A(int = 0, int = 0, int = 0, int = 0, ...); // expected-note 9{{here}}
|
||||
A(int = 0, int = 0, int = 0, int = 0, ...); // expected-note 9{{here}} expected-note 2{{constructor cannot be inherited}}
|
||||
A(int = 0, int = 0, ...); // expected-note {{here}}
|
||||
|
||||
template<typename T> A(T, int = 0, ...); // expected-note 5{{here}}
|
||||
|
||||
template<typename T, int N> A(const T (&)[N]); // expected-note 2{{here}}
|
||||
template<typename T, int N> A(const T (&)[N]); // expected-note 2{{here}} expected-note {{constructor cannot be inherited}}
|
||||
template<typename T, int N> A(const T (&)[N], int = 0); // expected-note 2{{here}}
|
||||
};
|
||||
|
||||
struct B : A { // expected-note 6{{candidate}}
|
||||
using A::A; // expected-warning 4{{inheriting constructor does not inherit ellipsis}} expected-note 16{{candidate}} expected-note 3{{deleted}}
|
||||
using A::A; // expected-warning 4{{inheriting constructor does not inherit ellipsis}} expected-note 16{{candidate}} expected-note 3{{deleted constructor was inherited here}}
|
||||
};
|
||||
|
||||
struct C {} c;
|
||||
|
||||
B b0{};
|
||||
// expected-error@-1 {{call to implicitly-deleted default constructor}}
|
||||
// expected-error@-1 {{call to implicitly-deleted default constructor of 'B'}}
|
||||
// expected-note@-8 {{default constructor of 'B' is implicitly deleted because base class 'A' has multiple default constructors}}
|
||||
|
||||
B b1{1};
|
||||
// FIXME: explain why the inheriting constructor was deleted
|
||||
// expected-error@-2 {{call to implicitly-deleted function of 'B'}}
|
||||
// expected-error@-1 {{call to deleted constructor of 'B'}}
|
||||
|
||||
B b2{1,2};
|
||||
// expected-error@-1 {{call to implicitly-deleted function of 'B'}}
|
||||
// expected-error@-1 {{call to deleted constructor of 'B'}}
|
||||
|
||||
B b3{1,2,3};
|
||||
// ok
|
||||
|
|
|
@ -43,13 +43,13 @@ FA fa2{X<2>{}}; // expected-error {{calling a private constructor}}
|
|||
|
||||
// It is deleted if the corresponding constructor [...] is deleted.
|
||||
struct G {
|
||||
G(int) = delete;
|
||||
template<typename T> G(T*) = delete;
|
||||
G(int) = delete; // expected-note {{function has been explicitly marked deleted here}}
|
||||
template<typename T> G(T*) = delete; // expected-note {{function has been explicitly marked deleted here}}
|
||||
};
|
||||
struct H : G {
|
||||
using G::G; // expected-note 2{{marked deleted here}}
|
||||
using G::G; // expected-note 2{{deleted constructor was inherited here}}
|
||||
};
|
||||
H h1(5); // expected-error {{call to implicitly-deleted function of 'H'}}
|
||||
H h1(5); // expected-error {{call to deleted constructor of 'H'}}
|
||||
H h2("foo"); // expected-error {{call to deleted constructor of 'H'}}
|
||||
|
||||
|
||||
|
@ -58,15 +58,14 @@ H h2("foo"); // expected-error {{call to deleted constructor of 'H'}}
|
|||
namespace DRnnnn {
|
||||
struct A {
|
||||
constexpr A(int, float = 0) {}
|
||||
explicit A(int, int = 0) {}
|
||||
explicit A(int, int = 0) {} // expected-note {{constructor cannot be inherited}}
|
||||
|
||||
A(int, int, int = 0) = delete;
|
||||
};
|
||||
struct B : A {
|
||||
// FIXME: produce notes indicating why it was deleted
|
||||
using A::A; // expected-note {{here}}
|
||||
};
|
||||
|
||||
constexpr B b0(0, 0.0f); // ok, constexpr
|
||||
B b1(0, 1); // expected-error {{call to implicitly-deleted}}
|
||||
B b1(0, 1); // expected-error {{call to deleted constructor of 'DRnnnn::B'}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue