aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-04-12 17:09:20 +0000
committerDouglas Gregor <dgregor@apple.com>2010-04-12 17:09:20 +0000
commit6275e0cac39b76204644154fd99a449f57c589d4 (patch)
tree392ec2490aeacdebf34101dec57f1e9d6ffef3e8
parent454006d625f9f5f48cd80096f1afa0f5985ec25e (diff)
When creating the implicitly-declared special member functions, be
sure to introduce them into the current Scope (when we have one) in addition to the DeclContext for the class, so that they can be found by name lookup for inline members of the class. Fixes PR6570. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101047 91177308-0d34-0410-b5e6-96231b3b80d8
-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;
+ };
+
+}