diff options
-rw-r--r-- | lib/Sema/Sema.h | 4 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 31 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 2 | ||||
-rw-r--r-- | test/SemaCXX/implicit-member-functions.cpp | 27 |
4 files changed, 53 insertions, 11 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 93867d7e55..adae0faa71 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2511,14 +2511,14 @@ public: /// Returns false if no work was done. bool ProcessPendingClassesWithUnmarkedVirtualMembers(); - void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl); + void AddImplicitlyDeclaredMembersToClass(Scope *S, CXXRecordDecl *ClassDecl); virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl, SourceLocation ColonLoc, MemInitTy **MemInits, unsigned NumMemInits, bool AnyErrors); - void CheckCompletedCXXClass(CXXRecordDecl *Record); + void CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record); virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, DeclPtrTy TagDecl, SourceLocation LBrac, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 0b26e9be3a..d832978054 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2136,12 +2136,12 @@ namespace { /// \brief Perform semantic checks on a class definition that has been /// completing, introducing implicitly-declared members, checking for /// abstract types, etc. -void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { +void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { if (!Record || Record->isInvalidDecl()) return; if (!Record->isDependentType()) - AddImplicitlyDeclaredMembersToClass(Record); + AddImplicitlyDeclaredMembersToClass(S, Record); if (Record->isInvalidDecl()) return; @@ -2233,7 +2233,7 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, (DeclPtrTy*)FieldCollector->getCurFields(), FieldCollector->getCurNumFields(), LBrac, RBrac, AttrList); - CheckCompletedCXXClass( + CheckCompletedCXXClass(S, dyn_cast_or_null<CXXRecordDecl>(TagDecl.getAs<Decl>())); } @@ -2242,7 +2242,10 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, /// constructor, or destructor, to the given C++ class (C++ /// [special]p1). This routine can only be executed just before the /// definition of the class is complete. -void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { +/// +/// The scope, if provided, is the class scope. +void Sema::AddImplicitlyDeclaredMembersToClass(Scope *S, + CXXRecordDecl *ClassDecl) { CanQualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); @@ -2273,7 +2276,10 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { DefaultCon->setAccess(AS_public); DefaultCon->setImplicit(); DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor()); - ClassDecl->addDecl(DefaultCon); + if (S) + PushOnScopeChains(DefaultCon, S, true); + else + ClassDecl->addDecl(DefaultCon); } if (!ClassDecl->hasUserDeclaredCopyConstructor()) { @@ -2356,7 +2362,10 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { ArgType, /*TInfo=*/0, VarDecl::None, 0); CopyConstructor->setParams(&FromParam, 1); - ClassDecl->addDecl(CopyConstructor); + if (S) + PushOnScopeChains(CopyConstructor, S, true); + else + ClassDecl->addDecl(CopyConstructor); } if (!ClassDecl->hasUserDeclaredCopyAssignment()) { @@ -2446,7 +2455,10 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { // Don't call addedAssignmentOperator. There is no way to distinguish an // implicit from an explicit assignment operator. - ClassDecl->addDecl(CopyAssignment); + if (S) + PushOnScopeChains(CopyAssignment, S, true); + else + ClassDecl->addDecl(CopyAssignment); AddOverriddenMethods(ClassDecl, CopyAssignment); } @@ -2470,7 +2482,10 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { Destructor->setAccess(AS_public); Destructor->setImplicit(); Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); - ClassDecl->addDecl(Destructor); + if (S) + PushOnScopeChains(Destructor, S, true); + else + ClassDecl->addDecl(Destructor); // This could be uniqued if it ever proves significant. Destructor->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(Ty)); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 0e2d7f1f10..1943a2ae17 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -1169,7 +1169,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, ActOnFields(0, Instantiation->getLocation(), DeclPtrTy::make(Instantiation), Fields.data(), Fields.size(), SourceLocation(), SourceLocation(), 0); - CheckCompletedCXXClass(Instantiation); + CheckCompletedCXXClass(/*Scope=*/0, Instantiation); if (Instantiation->isInvalidDecl()) Invalid = true; diff --git a/test/SemaCXX/implicit-member-functions.cpp b/test/SemaCXX/implicit-member-functions.cpp index 40a61e47fd..2112188ae6 100644 --- a/test/SemaCXX/implicit-member-functions.cpp +++ b/test/SemaCXX/implicit-member-functions.cpp @@ -12,3 +12,30 @@ C& C::operator=(const C&) { return *this; } // expected-error {{definition of im struct D { }; // expected-note {{previous implicit declaration is here}} D::~D() { } // expected-error {{definition of implicitly declared destructor}} +// Make sure that the special member functions are introduced for +// name-lookup purposes and overload with user-declared +// constructors and assignment operators. +namespace PR6570 { + class A { }; + + class B { + public: + B() {} + + B(const A& a) { + operator = (CONST); + operator = (a); + } + + B& operator = (const A& a) { + return *this; + } + + void f(const A &a) { + B b(a); + }; + + static const B CONST; + }; + +} |