def note_deleted_dtor_no_operator_delete : Note<
"virtual destructor requires an unambiguous, accessible 'operator delete'">;
def note_deleted_special_member_class_subobject : Note<
- "%select{default constructor|copy constructor|move constructor|"
- "copy assignment operator|move assignment operator|destructor}0 of "
+ "%select{default constructor of|copy constructor of|move constructor of|"
+ "copy assignment operator of|move assignment operator of|destructor of|"
+ "constructor inherited by}0 "
"%1 is implicitly deleted because "
"%select{base class %3|%select{||||variant }4field %3}2 has "
"%select{no|a deleted|multiple|an inaccessible|a non-trivial}4 "
"%select{%select{default constructor|copy constructor|move constructor|copy "
- "assignment operator|move assignment operator|destructor}0|destructor}5"
+ "assignment operator|move assignment operator|destructor|"
+ "%select{default|corresponding|default|default|default}4 constructor}0|"
+ "destructor}5"
"%select{||s||}4">;
def note_deleted_default_ctor_uninit_field : Note<
- "default constructor of %0 is implicitly deleted because field %1 of "
- "%select{reference|const-qualified}3 type %2 would not be initialized">;
+ "%select{default constructor of|constructor inherited by}0 "
+ "%1 is implicitly deleted because field %2 of "
+ "%select{reference|const-qualified}4 type %3 would not be initialized">;
def note_deleted_default_ctor_all_const : Note<
- "default constructor of %0 is implicitly deleted because all "
- "%select{data members|data members of an anonymous union member}1"
+ "%select{default constructor of|constructor inherited by}0 "
+ "%1 is implicitly deleted because all "
+ "%select{data members|data members of an anonymous union member}2"
" are const-qualified">;
def note_deleted_copy_ctor_rvalue_reference : Note<
"copy constructor of %0 is implicitly deleted because field %1 is of "
"pointer, or a vector of such types (%0 invalid)">;
def err_deleted_function_use : Error<"attempt to use a deleted function">;
+def err_deleted_inherited_ctor_use : Error<
+ "constructor inherited by %0 from base class %1 is implicitly deleted">;
def err_kern_type_not_void_return : Error<
"kernel function type %0 must have void return type">;
LHSQuals & Qualifiers::Volatile);
}
-namespace {
-struct InheritedConstructorInfo {
+class Sema::InheritedConstructorInfo {
Sema &S;
SourceLocation UseLoc;
- ConstructorUsingShadowDecl *Shadow;
/// A mapping from the base classes through which the constructor was
/// inherited to the using shadow declaration in that base class (or a null
llvm::DenseMap<CXXRecordDecl *, ConstructorUsingShadowDecl *>
InheritedFromBases;
+public:
InheritedConstructorInfo(Sema &S, SourceLocation UseLoc,
ConstructorUsingShadowDecl *Shadow)
- : S(S), UseLoc(UseLoc), Shadow(Shadow) {
+ : S(S), UseLoc(UseLoc) {
bool DiagnosedMultipleConstructedBases = false;
CXXRecordDecl *ConstructedBase = nullptr;
UsingDecl *ConstructedBaseUsing = nullptr;
return std::make_pair(Ctor, false);
}
};
-}
/// Is the special member function which would be selected to perform the
/// specified operation on the specified class type a constexpr constructor?
Sema::CXXSpecialMember CSM, unsigned Quals,
bool ConstRHS,
CXXConstructorDecl *InheritedCtor = nullptr,
- InheritedConstructorInfo *Inherited = nullptr) {
+ Sema::InheritedConstructorInfo *Inherited = nullptr) {
// If we're inheriting a constructor, see if we need to call it for this base
// class.
if (InheritedCtor) {
static bool defaultedSpecialMemberIsConstexpr(
Sema &S, CXXRecordDecl *ClassDecl, Sema::CXXSpecialMember CSM,
bool ConstArg, CXXConstructorDecl *InheritedCtor = nullptr,
- InheritedConstructorInfo *Inherited = nullptr) {
+ Sema::InheritedConstructorInfo *Inherited = nullptr) {
if (!S.getLangOpts().CPlusPlus11)
return false;
// [For a] user-provided explicitly-defaulted function [...] if such a
// function is implicitly defined as deleted, the program is ill-formed.
Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) << CSM;
- ShouldDeleteSpecialMember(MD, CSM, /*Diagnose*/true);
+ ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/true);
HadError = true;
}
}
Sema &S;
CXXMethodDecl *MD;
Sema::CXXSpecialMember CSM;
+ Sema::InheritedConstructorInfo *ICI;
bool Diagnose;
// Properties of the special member, computed for convenience.
bool AllFieldsAreConst;
SpecialMemberDeletionInfo(Sema &S, CXXMethodDecl *MD,
- Sema::CXXSpecialMember CSM, bool Diagnose)
- : S(S), MD(MD), CSM(CSM), Diagnose(Diagnose),
- IsConstructor(false), IsAssignment(false), IsMove(false),
- ConstArg(false), Loc(MD->getLocation()),
- AllFieldsAreConst(true) {
+ Sema::CXXSpecialMember CSM,
+ Sema::InheritedConstructorInfo *ICI, bool Diagnose)
+ : S(S), MD(MD), CSM(CSM), ICI(ICI), Diagnose(Diagnose),
+ IsConstructor(false), IsAssignment(false), IsMove(false),
+ ConstArg(false), Loc(MD->getLocation()), AllFieldsAreConst(true) {
switch (CSM) {
case Sema::CXXDefaultConstructor:
case Sema::CXXCopyConstructor:
bool inUnion() const { return MD->getParent()->isUnion(); }
+ Sema::CXXSpecialMember getEffectiveCSM() {
+ return ICI ? Sema::CXXInvalid : CSM;
+ }
+
/// Look up the corresponding special member in the given class.
Sema::SpecialMemberOverloadResult *lookupIn(CXXRecordDecl *Class,
unsigned Quals, bool IsMutable) {
if (Field) {
S.Diag(Field->getLocation(),
diag::note_deleted_special_member_class_subobject)
- << CSM << MD->getParent() << /*IsField*/true
+ << getEffectiveCSM() << MD->getParent() << /*IsField*/true
<< Field << DiagKind << IsDtorCallInCtor;
} else {
CXXBaseSpecifier *Base = Subobj.get<CXXBaseSpecifier*>();
S.Diag(Base->getLocStart(),
diag::note_deleted_special_member_class_subobject)
- << CSM << MD->getParent() << /*IsField*/false
+ << getEffectiveCSM() << MD->getParent() << /*IsField*/false
<< Base->getType() << DiagKind << IsDtorCallInCtor;
}
CXXRecordDecl *BaseClass = Base->getType()->getAsCXXRecordDecl();
// If program is correct, BaseClass cannot be null, but if it is, the error
// must be reported elsewhere.
- return BaseClass && shouldDeleteForClassSubobject(BaseClass, Base, 0);
+ if (!BaseClass)
+ return false;
+ // If we have an inheriting constructor, check whether we're calling an
+ // inherited constructor instead of a default constructor.
+ if (ICI) {
+ assert(CSM == Sema::CXXDefaultConstructor);
+ auto *BaseCtor =
+ ICI->findConstructorForBase(BaseClass, cast<CXXConstructorDecl>(MD)
+ ->getInheritedConstructor()
+ .getConstructor())
+ .first;
+ if (BaseCtor) {
+ if (BaseCtor->isDeleted() && Diagnose) {
+ S.Diag(Base->getLocStart(),
+ diag::note_deleted_special_member_class_subobject)
+ << getEffectiveCSM() << MD->getParent() << /*IsField*/false
+ << Base->getType() << /*Deleted*/1 << /*IsDtorCallInCtor*/false;
+ S.NoteDeletedFunction(BaseCtor);
+ }
+ return BaseCtor->isDeleted();
+ }
+ }
+ return shouldDeleteForClassSubobject(BaseClass, Base, 0);
}
/// Check whether we should delete a special member function due to the class
if (FieldType->isReferenceType() && !FD->hasInClassInitializer()) {
if (Diagnose)
S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field)
- << MD->getParent() << FD << FieldType << /*Reference*/0;
+ << !!ICI << MD->getParent() << FD << FieldType << /*Reference*/0;
return true;
}
// C++11 [class.ctor]p5: any non-variant non-static data member of
(!FieldRecord || !FieldRecord->hasUserProvidedDefaultConstructor())) {
if (Diagnose)
S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field)
- << MD->getParent() << FD << FD->getType() << /*Const*/1;
+ << !!ICI << MD->getParent() << FD << FD->getType() << /*Const*/1;
return true;
}
if (Diagnose)
S.Diag(FieldRecord->getLocation(),
diag::note_deleted_default_ctor_all_const)
- << MD->getParent() << /*anonymous union*/1;
+ << !!ICI << MD->getParent() << /*anonymous union*/1;
return true;
}
if (Diagnose)
S.Diag(MD->getParent()->getLocation(),
diag::note_deleted_default_ctor_all_const)
- << MD->getParent() << /*not anonymous union*/0;
+ << !!ICI << MD->getParent() << /*not anonymous union*/0;
return true;
}
return false;
/// deleted, as specified in C++11 [class.ctor]p5, C++11 [class.copy]p11,
/// C++11 [class.copy]p23, and C++11 [class.dtor]p5.
bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
+ InheritedConstructorInfo *ICI,
bool Diagnose) {
if (MD->isInvalidDecl())
return false;
}
}
- SpecialMemberDeletionInfo SMI(*this, MD, CSM, Diagnose);
+ SpecialMemberDeletionInfo SMI(*this, MD, CSM, ICI, Diagnose);
for (auto &BI : RD->bases())
if (!BI.isVirtual() &&
DerivedCtor->setAccess(BaseCtor->getAccess());
DerivedCtor->setParams(ParamDecls);
Derived->addDecl(DerivedCtor);
+
+ if (ShouldDeleteSpecialMember(DerivedCtor, CXXDefaultConstructor, &ICI))
+ SetDeclDeleted(DerivedCtor, UsingLoc);
+
return DerivedCtor;
}
+void Sema::NoteDeletedInheritingConstructor(CXXConstructorDecl *Ctor) {
+ InheritedConstructorInfo ICI(*this, Ctor->getLocation(),
+ Ctor->getInheritedConstructor().getShadowDecl());
+ ShouldDeleteSpecialMember(Ctor, CXXDefaultConstructor, &ICI,
+ /*Diagnose*/true);
+}
+
void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *Constructor) {
CXXRecordDecl *ClassDecl = Constructor->getParent();
bool RequiresZeroInit,
unsigned ConstructKind,
SourceRange ParenRange) {
- if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(FoundDecl))
+ if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(FoundDecl)) {
Constructor = findInheritingConstructor(ConstructLoc, Constructor, Shadow);
+ if (DiagnoseUseOfDecl(Constructor, ConstructLoc))
+ return ExprError();
+ }
return BuildCXXConstructExpr(
ConstructLoc, DeclInitType, Constructor, Elidable, ExprArgs,