]> granicus.if.org Git - clang/commitdiff
When creating the implicitly-declared special member functions, be
authorDouglas Gregor <dgregor@apple.com>
Mon, 12 Apr 2010 17:09:20 +0000 (17:09 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 12 Apr 2010 17:09:20 +0000 (17:09 +0000)
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

lib/Sema/Sema.h
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaTemplateInstantiate.cpp
test/SemaCXX/implicit-member-functions.cpp

index 93867d7e5501ef3c773d5f57ab7cfb2e537ff8d9..adae0faa71f1189a04e61cf152ace6356da6130a 100644 (file)
@@ -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,
index 0b26e9be3aad6cf33f189e2234e191b8b24fccad..d83297805471bdab2924d61d36f9883240e41928 100644 (file)
@@ -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));
index 0e2d7f1f106fd47f42f37f1ba64e12e2fb7ba4e3..1943a2ae176f2f66af3d6f7516d1166fcb7af11d 100644 (file)
@@ -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;
   
index 40a61e47fd3c3b16a3faf25534f3f84069cf10b5..2112188ae6784755012e2e03044a6dc90247118d 100644 (file)
@@ -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;
+  };
+
+}