[cfe-commits] r114899 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclBase.cpp lib/AST/DeclCXX.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp

Douglas Gregor dgregor at apple.com
Mon Sep 27 15:06:20 PDT 2010


Author: dgregor
Date: Mon Sep 27 17:06:20 2010
New Revision: 114899

URL: http://llvm.org/viewvc/llvm-project?rev=114899&view=rev
Log:
Centralize the handling of
CXXRecordDecl::DefinitionData::DeclaredCopyAssignment, for
copy-assignment operators. Another step toward <rdar://problem/8459981>.

Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=114899&r1=114898&r2=114899&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Sep 27 17:06:20 2010
@@ -406,13 +406,12 @@
   
   friend class DeclContext;
   
-  /// \brief Notify the class that another constructor has
-  /// been added. 
+  /// \brief Notify the class that member has been added.
   ///
   /// This routine helps maintain information about the class based on which 
-  /// constructors have been added. It will be invoked by DeclContext::addDecl()
-  /// whenever a constructor is added to this record.
-  void addedConstructor(CXXConstructorDecl *ConDecl);  
+  /// members have been added. It will be invoked by DeclContext::addDecl()
+  /// whenever a member is added to this record.
+  void addedMember(Decl *D);
   
 protected:
   CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
@@ -610,11 +609,6 @@
     return data().DeclaredCopyConstructor;
   }
   
-  /// addedAssignmentOperator - Notify the class that another assignment
-  /// operator has been added. This routine helps maintain information about the
-  /// class based on which operators have been added.
-  void addedAssignmentOperator(ASTContext &Context, CXXMethodDecl *OpDecl);
-
   /// hasUserDeclaredCopyAssignment - Whether this class has a
   /// user-declared copy assignment operator. When false, a copy
   /// assigment operator will be implicitly declared.
@@ -630,12 +624,6 @@
     return data().DeclaredCopyAssignment;
   }
   
-  /// \brief Note whether this class has already had its copy assignment 
-  /// operator declared.
-  void setDeclaredCopyAssignment(bool DCA) {
-    data().DeclaredCopyAssignment = DCA;
-  }
-  
   /// hasUserDeclaredDestructor - Whether this class has a
   /// user-declared destructor. When false, a destructor will be
   /// implicitly declared.

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=114899&r1=114898&r2=114899&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Mon Sep 27 17:06:20 2010
@@ -778,14 +778,11 @@
   } else {
     FirstDecl = LastDecl = D;
   }
-  
-  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this)) {
-    Decl *InnerD = D;
-    if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
-      InnerD = FunTmpl->getTemplatedDecl();
-    if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(InnerD))
-      Record->addedConstructor(Constructor);
-  }
+
+  // Notify a C++ record declaration that we've added a member, so it can
+  // update it's class-specific state.
+  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this))
+    Record->addedMember(D);
 }
 
 void DeclContext::addDecl(Decl *D) {

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=114899&r1=114898&r2=114899&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Sep 27 17:06:20 2010
@@ -259,99 +259,126 @@
 }
 
 void
-CXXRecordDecl::addedConstructor(CXXConstructorDecl *Constructor) {
-  // Ignore friends.
-  if (Constructor->getFriendObjectKind())
+CXXRecordDecl::addedMember(Decl *D) {
+  // Ignore friends and invalid declarations.
+  if (D->getFriendObjectKind() || D->isInvalidDecl())
     return;
   
-  if (Constructor->isImplicit()) {
-    // If this is the implicit default constructor, note that we have now
-    // declared it.
-    if (Constructor->isDefaultConstructor())
-      data().DeclaredDefaultConstructor = true;
-    // If this is the implicit copy constructor, note that we have now
-    // declared it.
-    else if (Constructor->isCopyConstructor())
-      data().DeclaredCopyConstructor = true;
+  FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
+  if (FunTmpl)
+    D = FunTmpl->getTemplatedDecl();
+  
+  if (D->isImplicit()) {
+    if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+      // If this is the implicit default constructor, note that we have now
+      // declared it.
+      if (Constructor->isDefaultConstructor())
+        data().DeclaredDefaultConstructor = true;
+      // If this is the implicit copy constructor, note that we have now
+      // declared it.
+      else if (Constructor->isCopyConstructor())
+        data().DeclaredCopyConstructor = true;
+    }
+    // FIXME: Destructors
+    else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+      // If this is the implicit copy constructor, note that we have now
+      // declared it.
+      // FIXME: Move constructors
+      if (Method->getOverloadedOperator() == OO_Equal) {
+        data().DeclaredCopyAssignment = true;
+        Method->setCopyAssignment(true);
+      }
+    }
     
-    // Nothing else to do for implicitly-declared constructors.
+    // Nothing else to do for implicitly-declared members.
     return;
   }
   
-  // Note that we have a user-declared constructor.
-  data().UserDeclaredConstructor = true;
+  // Handle (user-declared) constructors.
+  if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+    // Note that we have a user-declared constructor.
+    data().UserDeclaredConstructor = true;
 
-  // Note that we have no need of an implicitly-declared default constructor.
-  data().DeclaredDefaultConstructor = true;
-  
-  // C++ [dcl.init.aggr]p1:
-  //   An aggregate is an array or a class (clause 9) with no
-  //   user-declared constructors (12.1) [...].
-  data().Aggregate = false;
-
-  // C++ [class]p4:
-  //   A POD-struct is an aggregate class [...]
-  data().PlainOldData = false;
-
-  // C++ [class.ctor]p5:
-  //   A constructor is trivial if it is an implicitly-declared default
-  //   constructor.
-  // FIXME: C++0x: don't do this for "= default" default constructors.
-  data().HasTrivialConstructor = false;
-
-  // Note when we have a user-declared copy constructor, which will
-  // suppress the implicit declaration of a copy constructor.
-  if (!Constructor->getDescribedFunctionTemplate() &&
-      Constructor->isCopyConstructor()) {
-    data().UserDeclaredCopyConstructor = true;
-    data().DeclaredCopyConstructor = true;
+    // Note that we have no need of an implicitly-declared default constructor.
+    data().DeclaredDefaultConstructor = true;
     
-    // C++ [class.copy]p6:
-    //   A copy constructor is trivial if it is implicitly declared.
-    // FIXME: C++0x: don't do this for "= default" copy constructors.
-    data().HasTrivialCopyConstructor = false;
+    // C++ [dcl.init.aggr]p1:
+    //   An aggregate is an array or a class (clause 9) with no
+    //   user-declared constructors (12.1) [...].
+    data().Aggregate = false;
+
+    // C++ [class]p4:
+    //   A POD-struct is an aggregate class [...]
+    data().PlainOldData = false;
+
+    // C++ [class.ctor]p5:
+    //   A constructor is trivial if it is an implicitly-declared default
+    //   constructor.
+    // FIXME: C++0x: don't do this for "= default" default constructors.
+    data().HasTrivialConstructor = false;
+
+    // Note when we have a user-declared copy constructor, which will
+    // suppress the implicit declaration of a copy constructor.
+    if (!FunTmpl && Constructor->isCopyConstructor()) {
+      data().UserDeclaredCopyConstructor = true;
+      data().DeclaredCopyConstructor = true;
+      
+      // C++ [class.copy]p6:
+      //   A copy constructor is trivial if it is implicitly declared.
+      // FIXME: C++0x: don't do this for "= default" copy constructors.
+      data().HasTrivialCopyConstructor = false;
+    }
+    
+    return;
   }
-}
 
-void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
-                                            CXXMethodDecl *OpDecl) {
-  // We're interested specifically in copy assignment operators.
-  const FunctionProtoType *FnType = OpDecl->getType()->getAs<FunctionProtoType>();
-  assert(FnType && "Overloaded operator has no proto function type.");
-  assert(FnType->getNumArgs() == 1 && !FnType->isVariadic());
+  // FIXME: Destructors.
   
-  // Copy assignment operators must be non-templates.
-  if (OpDecl->getPrimaryTemplate() || OpDecl->getDescribedFunctionTemplate())
-    return;
-  
-  QualType ArgType = FnType->getArgType(0);
-  if (const LValueReferenceType *Ref = ArgType->getAs<LValueReferenceType>())
-    ArgType = Ref->getPointeeType();
-
-  ArgType = ArgType.getUnqualifiedType();
-  QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
-    const_cast<CXXRecordDecl*>(this)));
-
-  if (!Context.hasSameUnqualifiedType(ClassType, ArgType))
+  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+    if (Method->getOverloadedOperator() == OO_Equal) {
+      // We're interested specifically in copy assignment operators.
+      const FunctionProtoType *FnType 
+        = Method->getType()->getAs<FunctionProtoType>();
+      assert(FnType && "Overloaded operator has no proto function type.");
+      assert(FnType->getNumArgs() == 1 && !FnType->isVariadic());
+      
+      // Copy assignment operators must be non-templates.
+      if (Method->getPrimaryTemplate() || FunTmpl)
+        return;
+      
+      ASTContext &Context = getASTContext();
+      QualType ArgType = FnType->getArgType(0);
+      if (const LValueReferenceType *Ref =ArgType->getAs<LValueReferenceType>())
+        ArgType = Ref->getPointeeType();
+      
+      ArgType = ArgType.getUnqualifiedType();
+      QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
+                                             const_cast<CXXRecordDecl*>(this)));
+      
+      if (!Context.hasSameUnqualifiedType(ClassType, ArgType))
+        return;
+      
+      // This is a copy assignment operator.
+      // Note on the decl that it is a copy assignment operator.
+      Method->setCopyAssignment(true);
+      
+      // Suppress the implicit declaration of a copy constructor.
+      data().UserDeclaredCopyAssignment = true;
+      data().DeclaredCopyAssignment = true;
+      
+      // C++ [class.copy]p11:
+      //   A copy assignment operator is trivial if it is implicitly declared.
+      // FIXME: C++0x: don't do this for "= default" copy operators.
+      data().HasTrivialCopyAssignment = false;
+      
+      // C++ [class]p4:
+      //   A POD-struct is an aggregate class that [...] has no user-defined copy
+      //   assignment operator [...].
+      data().PlainOldData = false;
+    }
+    
     return;
-
-  // This is a copy assignment operator.
-  // Note on the decl that it is a copy assignment operator.
-  OpDecl->setCopyAssignment(true);
-
-  // Suppress the implicit declaration of a copy constructor.
-  data().UserDeclaredCopyAssignment = true;
-  data().DeclaredCopyAssignment = true;
-  
-  // C++ [class.copy]p11:
-  //   A copy assignment operator is trivial if it is implicitly declared.
-  // FIXME: C++0x: don't do this for "= default" copy operators.
-  data().HasTrivialCopyAssignment = false;
-
-  // C++ [class]p4:
-  //   A POD-struct is an aggregate class that [...] has no user-defined copy
-  //   assignment operator [...].
-  data().PlainOldData = false;
+  }
 }
 
 static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=114899&r1=114898&r2=114899&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Sep 27 17:06:20 2010
@@ -544,7 +544,9 @@
 
   if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D))
     return CD->isCopyConstructor();
-  return D->isCopyAssignment();
+  if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
+    return Method->isCopyAssignmentOperator();
+  return false;
 }
 
 bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=114899&r1=114898&r2=114899&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Sep 27 17:06:20 2010
@@ -4942,7 +4942,6 @@
   CopyAssignment->setParams(&FromParam, 1);
   
   // Note that we have added this copy-assignment operator.
-  ClassDecl->setDeclaredCopyAssignment(true);
   ++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared;
   
   if (Scope *S = getScopeForContext(ClassDecl))
@@ -5952,15 +5951,6 @@
         << LastParam->getType() << (Op == OO_MinusMinus);
   }
 
-  // Notify the class if it got an assignment operator.
-  if (Op == OO_Equal) {
-    // Would have returned earlier otherwise.
-    assert(isa<CXXMethodDecl>(FnDecl) &&
-      "Overloaded = not member, but not filtered.");
-    CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
-    Method->getParent()->addedAssignmentOperator(Context, Method);
-  }
-
   return false;
 }
 





More information about the cfe-commits mailing list