aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/Sema.h4
-rw-r--r--lib/Sema/SemaDeclCXX.cpp31
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp2
-rw-r--r--test/SemaCXX/implicit-member-functions.cpp27
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;
+ };
+
+}