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">;
|
"%select{unavailable|deleted|deprecated}1 here">;
|
||||||
def note_implicitly_deleted : Note<
|
def note_implicitly_deleted : Note<
|
||||||
"explicitly defaulted function was implicitly deleted here">;
|
"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<
|
def warn_not_enough_argument : Warning<
|
||||||
"not enough variable arguments in %0 declaration to fit a sentinel">,
|
"not enough variable arguments in %0 declaration to fit a sentinel">,
|
||||||
InGroup<Sentinel>;
|
InGroup<Sentinel>;
|
||||||
|
|
|
@ -9991,9 +9991,7 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sema::isImplicitlyDeleted(FunctionDecl *FD) {
|
bool Sema::isImplicitlyDeleted(FunctionDecl *FD) {
|
||||||
return FD->isDeleted() &&
|
return FD->isDeleted() && FD->isDefaulted() && isa<CXXMethodDecl>(FD);
|
||||||
(FD->isDefaulted() || FD->isImplicit()) &&
|
|
||||||
isa<CXXMethodDecl>(FD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Mark the call operator of the given lambda closure type as "used".
|
/// \brief Mark the call operator of the given lambda closure type as "used".
|
||||||
|
|
|
@ -140,11 +140,13 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S,
|
||||||
return Result;
|
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) {
|
void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
|
||||||
|
assert(Decl->isDeleted());
|
||||||
|
|
||||||
CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Decl);
|
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 the method was explicitly defaulted, point at that declaration.
|
||||||
if (!Method->isImplicit())
|
if (!Method->isImplicit())
|
||||||
Diag(Decl->getLocation(), diag::note_implicitly_deleted);
|
Diag(Decl->getLocation(), diag::note_implicitly_deleted);
|
||||||
|
@ -158,8 +160,23 @@ void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
|
||||||
return;
|
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)
|
Diag(Decl->getLocation(), diag::note_unavailable_here)
|
||||||
<< 1 << Decl->isDeleted();
|
<< 1 << true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Determine whether a FunctionDecl was ever declared with an
|
/// \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.
|
// Per a core issue (no number yet), an ellipsis is always dropped.
|
||||||
struct A {
|
struct A {
|
||||||
A(...); // expected-note {{here}}
|
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}}
|
A(int = 0, int = 0, ...); // expected-note {{here}}
|
||||||
|
|
||||||
template<typename T> A(T, int = 0, ...); // expected-note 5{{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}}
|
template<typename T, int N> A(const T (&)[N], int = 0); // expected-note 2{{here}}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct B : A { // expected-note 6{{candidate}}
|
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;
|
struct C {} c;
|
||||||
|
|
||||||
B b0{};
|
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}}
|
// expected-note@-8 {{default constructor of 'B' is implicitly deleted because base class 'A' has multiple default constructors}}
|
||||||
|
|
||||||
B b1{1};
|
B b1{1};
|
||||||
// FIXME: explain why the inheriting constructor was deleted
|
// expected-error@-1 {{call to deleted constructor of 'B'}}
|
||||||
// expected-error@-2 {{call to implicitly-deleted function of 'B'}}
|
|
||||||
|
|
||||||
B b2{1,2};
|
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};
|
B b3{1,2,3};
|
||||||
// ok
|
// ok
|
||||||
|
|
|
@ -43,13 +43,13 @@ FA fa2{X<2>{}}; // expected-error {{calling a private constructor}}
|
||||||
|
|
||||||
// It is deleted if the corresponding constructor [...] is deleted.
|
// It is deleted if the corresponding constructor [...] is deleted.
|
||||||
struct G {
|
struct G {
|
||||||
G(int) = delete;
|
G(int) = delete; // expected-note {{function has been explicitly marked deleted here}}
|
||||||
template<typename T> G(T*) = delete;
|
template<typename T> G(T*) = delete; // expected-note {{function has been explicitly marked deleted here}}
|
||||||
};
|
};
|
||||||
struct H : G {
|
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'}}
|
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 {
|
namespace DRnnnn {
|
||||||
struct A {
|
struct A {
|
||||||
constexpr A(int, float = 0) {}
|
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;
|
A(int, int, int = 0) = delete;
|
||||||
};
|
};
|
||||||
struct B : A {
|
struct B : A {
|
||||||
// FIXME: produce notes indicating why it was deleted
|
|
||||||
using A::A; // expected-note {{here}}
|
using A::A; // expected-note {{here}}
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr B b0(0, 0.0f); // ok, constexpr
|
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