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:
Eli Friedman 2013-07-18 23:29:14 +00:00
parent b946407cb7
commit ebea0f29e2
5 changed files with 37 additions and 20 deletions

View File

@ -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>;

View File

@ -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".

View File

@ -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

View File

@ -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

View File

@ -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'}}
}