if (!ClassDecl->hasUserDeclaredConstructor())
++ASTContext::NumImplicitDefaultConstructors;
+ // If this class inherited any constructors, declare the default constructor
+ // now in case it displaces one from a base class.
+ if (ClassDecl->needsImplicitDefaultConstructor() &&
+ ClassDecl->hasInheritedConstructor())
+ DeclareImplicitDefaultConstructor(ClassDecl);
+
if (!ClassDecl->hasUserDeclaredCopyConstructor()) {
++ASTContext::NumImplicitCopyConstructors;
// If the properties or semantics of the copy constructor couldn't be
// determined while the class was being declared, force a declaration
// of it now.
- if (ClassDecl->needsOverloadResolutionForCopyConstructor())
+ if (ClassDecl->needsOverloadResolutionForCopyConstructor() ||
+ ClassDecl->hasInheritedConstructor())
DeclareImplicitCopyConstructor(ClassDecl);
}
if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveConstructor()) {
++ASTContext::NumImplicitMoveConstructors;
- if (ClassDecl->needsOverloadResolutionForMoveConstructor())
+ if (ClassDecl->needsOverloadResolutionForMoveConstructor() ||
+ ClassDecl->hasInheritedConstructor())
DeclareImplicitMoveConstructor(ClassDecl);
}
// it shows up in the right place in the vtable and that we diagnose
// problems with the implicit exception specification.
if (ClassDecl->isDynamicClass() ||
- ClassDecl->needsOverloadResolutionForCopyAssignment())
+ ClassDecl->needsOverloadResolutionForCopyAssignment() ||
+ ClassDecl->hasInheritedAssignment())
DeclareImplicitCopyAssignment(ClassDecl);
}
// Likewise for the move assignment operator.
if (ClassDecl->isDynamicClass() ||
- ClassDecl->needsOverloadResolutionForMoveAssignment())
+ ClassDecl->needsOverloadResolutionForMoveAssignment() ||
+ ClassDecl->hasInheritedAssignment())
DeclareImplicitMoveAssignment(ClassDecl);
}
struct DeclaringSpecialMember {
Sema &S;
Sema::SpecialMemberDecl D;
+ Sema::ContextRAII SavedContext;
bool WasAlreadyBeingDeclared;
DeclaringSpecialMember(Sema &S, CXXRecordDecl *RD, Sema::CXXSpecialMember CSM)
- : S(S), D(RD, CSM) {
+ : S(S), D(RD, CSM), SavedContext(S, RD) {
WasAlreadyBeingDeclared = !S.SpecialMembersBeingDeclared.insert(D).second;
if (WasAlreadyBeingDeclared)
// This almost never happens, but if it does, ensure that our cache
};
}
+void Sema::CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD) {
+ // Look up any existing declarations, but don't trigger declaration of all
+ // implicit special members with this name.
+ DeclarationName Name = FD->getDeclName();
+ LookupResult R(*this, Name, SourceLocation(), LookupOrdinaryName,
+ ForRedeclaration);
+ for (auto *D : FD->getParent()->lookup(Name))
+ if (auto *Acceptable = R.getAcceptableDecl(D))
+ R.addDecl(Acceptable);
+ R.resolveKind();
+
+ CheckFunctionDeclaration(S, FD, R, /*IsExplicitSpecialization*/false);
+}
+
CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
CXXRecordDecl *ClassDecl) {
// C++ [class.ctor]p5:
// constructors is easy to compute.
DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor());
- if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor))
- SetDeclDeleted(DefaultCon, ClassLoc);
-
// Note that we have declared this constructor.
++ASTContext::NumImplicitDefaultConstructorsDeclared;
- if (Scope *S = getScopeForContext(ClassDecl))
+ Scope *S = getScopeForContext(ClassDecl);
+ CheckImplicitSpecialMemberDeclaration(S, DefaultCon);
+
+ if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor))
+ SetDeclDeleted(DefaultCon, ClassLoc);
+
+ if (S)
PushOnScopeChains(DefaultCon, S, false);
ClassDecl->addDecl(DefaultCon);
FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, Destructor);
Destructor->setType(Context.getFunctionType(Context.VoidTy, None, EPI));
- AddOverriddenMethods(ClassDecl, Destructor);
-
// We don't need to use SpecialMemberIsTrivial here; triviality for
// destructors is easy to compute.
Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
- if (ShouldDeleteSpecialMember(Destructor, CXXDestructor))
- SetDeclDeleted(Destructor, ClassLoc);
-
// Note that we have declared this destructor.
++ASTContext::NumImplicitDestructorsDeclared;
+ Scope *S = getScopeForContext(ClassDecl);
+ CheckImplicitSpecialMemberDeclaration(S, Destructor);
+
+ if (ShouldDeleteSpecialMember(Destructor, CXXDestructor))
+ SetDeclDeleted(Destructor, ClassLoc);
+
// Introduce this destructor into its scope.
- if (Scope *S = getScopeForContext(ClassDecl))
+ if (S)
PushOnScopeChains(Destructor, S, false);
ClassDecl->addDecl(Destructor);
nullptr);
CopyAssignment->setParams(FromParam);
- AddOverriddenMethods(ClassDecl, CopyAssignment);
-
CopyAssignment->setTrivial(
ClassDecl->needsOverloadResolutionForCopyAssignment()
? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment)
: ClassDecl->hasTrivialCopyAssignment());
- if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment))
- SetDeclDeleted(CopyAssignment, ClassLoc);
-
// Note that we have added this copy-assignment operator.
++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared;
- if (Scope *S = getScopeForContext(ClassDecl))
+ Scope *S = getScopeForContext(ClassDecl);
+ CheckImplicitSpecialMemberDeclaration(S, CopyAssignment);
+
+ if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment))
+ SetDeclDeleted(CopyAssignment, ClassLoc);
+
+ if (S)
PushOnScopeChains(CopyAssignment, S, false);
ClassDecl->addDecl(CopyAssignment);
nullptr);
MoveAssignment->setParams(FromParam);
- AddOverriddenMethods(ClassDecl, MoveAssignment);
-
MoveAssignment->setTrivial(
ClassDecl->needsOverloadResolutionForMoveAssignment()
? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment)
: ClassDecl->hasTrivialMoveAssignment());
+ // Note that we have added this copy-assignment operator.
+ ++ASTContext::NumImplicitMoveAssignmentOperatorsDeclared;
+
+ Scope *S = getScopeForContext(ClassDecl);
+ CheckImplicitSpecialMemberDeclaration(S, MoveAssignment);
+
if (ShouldDeleteSpecialMember(MoveAssignment, CXXMoveAssignment)) {
ClassDecl->setImplicitMoveAssignmentIsDeleted();
SetDeclDeleted(MoveAssignment, ClassLoc);
}
- // Note that we have added this copy-assignment operator.
- ++ASTContext::NumImplicitMoveAssignmentOperatorsDeclared;
-
- if (Scope *S = getScopeForContext(ClassDecl))
+ if (S)
PushOnScopeChains(MoveAssignment, S, false);
ClassDecl->addDecl(MoveAssignment);
? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor)
: ClassDecl->hasTrivialCopyConstructor());
- if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor))
- SetDeclDeleted(CopyConstructor, ClassLoc);
-
// Note that we have declared this constructor.
++ASTContext::NumImplicitCopyConstructorsDeclared;
- if (Scope *S = getScopeForContext(ClassDecl))
+ Scope *S = getScopeForContext(ClassDecl);
+ CheckImplicitSpecialMemberDeclaration(S, CopyConstructor);
+
+ if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor))
+ SetDeclDeleted(CopyConstructor, ClassLoc);
+
+ if (S)
PushOnScopeChains(CopyConstructor, S, false);
ClassDecl->addDecl(CopyConstructor);
? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor)
: ClassDecl->hasTrivialMoveConstructor());
+ // Note that we have declared this constructor.
+ ++ASTContext::NumImplicitMoveConstructorsDeclared;
+
+ Scope *S = getScopeForContext(ClassDecl);
+ CheckImplicitSpecialMemberDeclaration(S, MoveConstructor);
+
if (ShouldDeleteSpecialMember(MoveConstructor, CXXMoveConstructor)) {
ClassDecl->setImplicitMoveConstructorIsDeleted();
SetDeclDeleted(MoveConstructor, ClassLoc);
}
- // Note that we have declared this constructor.
- ++ASTContext::NumImplicitMoveConstructorsDeclared;
-
- if (Scope *S = getScopeForContext(ClassDecl))
+ if (S)
PushOnScopeChains(MoveConstructor, S, false);
ClassDecl->addDecl(MoveConstructor);