diff options
| author | Douglas Gregor <dgregor@apple.com> | 2010-07-01 16:36:15 +0000 | 
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2010-07-01 16:36:15 +0000 | 
| commit | f56ab7b6bec0b6af4bb9aeff5513e1e5c6ee6b6c (patch) | |
| tree | 9e23575f84dbf27531e39f3c272673f951cfd4c8 /clang/lib | |
| parent | b1fdde1d01a3c1eeed669256fd5fe60aac5deb40 (diff) | |
| download | bcm5719-llvm-f56ab7b6bec0b6af4bb9aeff5513e1e5c6ee6b6c.tar.gz bcm5719-llvm-f56ab7b6bec0b6af4bb9aeff5513e1e5c6ee6b6c.zip | |
Move the implicit declaration of a class's copy-assignment operator
into a separate routine. No functionality change.
llvm-svn: 107402
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Sema/Sema.h | 14 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 199 | 
2 files changed, 114 insertions, 99 deletions
| diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 93e6a06ef89..2e52bfcb945 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -2236,7 +2236,19 @@ public:                                       CXXConstructorDecl *Constructor,                                       unsigned TypeQuals); -  /// \brief Defined and implicitly-declared copy assignment operator. +  /// \brief Declare the implicit copy assignment operator for the given class. +  /// +  /// \param S The scope of the class, which may be NULL if this is a  +  /// template instantiation. +  /// +  /// \param ClassDecl The class declaration into which the implicit  +  /// copy-assignment operator will be added. +  /// +  /// \returns The implicitly-declared copy assignment operator. +  CXXMethodDecl *DeclareImplicitCopyAssignment(Scope *S,  +                                               CXXRecordDecl *ClassDecl); +   +  /// \brief Defined an implicitly-declared copy assignment operator.    void DefineImplicitCopyAssignment(SourceLocation CurrentLocation,                                      CXXMethodDecl *MethodDecl); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 94d00b26973..130aa576b67 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2779,104 +2779,8 @@ void Sema::AddImplicitlyDeclaredMembersToClass(Scope *S,        ClassDecl->addDecl(CopyConstructor);    } -  if (!ClassDecl->hasUserDeclaredCopyAssignment()) { -    // Note: The following rules are largely analoguous to the copy -    // constructor rules. Note that virtual bases are not taken into account -    // for determining the argument type of the operator. Note also that -    // operators taking an object instead of a reference are allowed. -    // -    // C++ [class.copy]p10: -    //   If the class definition does not explicitly declare a copy -    //   assignment operator, one is declared implicitly. -    //   The implicitly-defined copy assignment operator for a class X -    //   will have the form -    // -    //       X& X::operator=(const X&) -    // -    //   if -    bool HasConstCopyAssignment = true; - -    //       -- each direct base class B of X has a copy assignment operator -    //          whose parameter is of type const B&, const volatile B& or B, -    //          and -    for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), -                                         BaseEnd = ClassDecl->bases_end(); -         HasConstCopyAssignment && Base != BaseEnd; ++Base) { -      assert(!Base->getType()->isDependentType() && -            "Cannot generate implicit members for class with dependent bases."); -      const CXXRecordDecl *BaseClassDecl -        = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); -      const CXXMethodDecl *MD = 0; -      HasConstCopyAssignment = BaseClassDecl->hasConstCopyAssignment(Context, -                                                                     MD); -    } - -    //       -- for all the nonstatic data members of X that are of a class -    //          type M (or array thereof), each such class type has a copy -    //          assignment operator whose parameter is of type const M&, -    //          const volatile M& or M. -    for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), -                                    FieldEnd = ClassDecl->field_end(); -         HasConstCopyAssignment && Field != FieldEnd; -         ++Field) { -      QualType FieldType = (*Field)->getType(); -      if (const ArrayType *Array = Context.getAsArrayType(FieldType)) -        FieldType = Array->getElementType(); -      if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { -        const CXXRecordDecl *FieldClassDecl -          = cast<CXXRecordDecl>(FieldClassType->getDecl()); -        const CXXMethodDecl *MD = 0; -        HasConstCopyAssignment -          = FieldClassDecl->hasConstCopyAssignment(Context, MD); -      } -    } - -    //   Otherwise, the implicitly declared copy assignment operator will -    //   have the form -    // -    //       X& X::operator=(X&) -    QualType ArgType = ClassType; -    QualType RetType = Context.getLValueReferenceType(ArgType); -    if (HasConstCopyAssignment) -      ArgType = ArgType.withConst(); -    ArgType = Context.getLValueReferenceType(ArgType); - -    //   An implicitly-declared copy assignment operator is an inline public -    //   member of its class. -    DeclarationName Name = -      Context.DeclarationNames.getCXXOperatorName(OO_Equal); -    CXXMethodDecl *CopyAssignment = -      CXXMethodDecl::Create(Context, ClassDecl, ClassDecl->getLocation(), Name, -                            Context.getFunctionType(RetType, &ArgType, 1, -                                                    false, 0, -                                              /*FIXME: hasExceptionSpec*/false, -                                                    false, 0, 0, -                                                    FunctionType::ExtInfo()), -                            /*TInfo=*/0, /*isStatic=*/false, -                            /*StorageClassAsWritten=*/FunctionDecl::None, -                            /*isInline=*/true); -    CopyAssignment->setAccess(AS_public); -    CopyAssignment->setImplicit(); -    CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment()); -    CopyAssignment->setCopyAssignment(true); - -    // Add the parameter to the operator. -    ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment, -                                                 ClassDecl->getLocation(), -                                                 /*Id=*/0, -                                                 ArgType, /*TInfo=*/0, -                                                 VarDecl::None, -                                                 VarDecl::None, 0); -    CopyAssignment->setParams(&FromParam, 1); - -    // Don't call addedAssignmentOperator. There is no way to distinguish an -    // implicit from an explicit assignment operator. -    if (S) -      PushOnScopeChains(CopyAssignment, S, true); -    else -      ClassDecl->addDecl(CopyAssignment); -    AddOverriddenMethods(ClassDecl, CopyAssignment); -  } +  if (!ClassDecl->hasUserDeclaredCopyAssignment()) +    DeclareImplicitCopyAssignment(S, ClassDecl);    if (!ClassDecl->hasUserDeclaredDestructor()) {      // C++ [class.dtor]p2: @@ -4661,6 +4565,105 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,                          Loc, move(Copy));  } +CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(Scope *S,  +                                                   CXXRecordDecl *ClassDecl) { +  // Note: The following rules are largely analoguous to the copy +  // constructor rules. Note that virtual bases are not taken into account +  // for determining the argument type of the operator. Note also that +  // operators taking an object instead of a reference are allowed. +  // +  // C++ [class.copy]p10: +  //   If the class definition does not explicitly declare a copy +  //   assignment operator, one is declared implicitly. +  //   The implicitly-defined copy assignment operator for a class X +  //   will have the form +  // +  //       X& X::operator=(const X&) +  // +  //   if +  bool HasConstCopyAssignment = true; +   +  //       -- each direct base class B of X has a copy assignment operator +  //          whose parameter is of type const B&, const volatile B& or B, +  //          and +  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), +                                       BaseEnd = ClassDecl->bases_end(); +       HasConstCopyAssignment && Base != BaseEnd; ++Base) { +    assert(!Base->getType()->isDependentType() && +           "Cannot generate implicit members for class with dependent bases."); +    const CXXRecordDecl *BaseClassDecl +      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); +    const CXXMethodDecl *MD = 0; +    HasConstCopyAssignment = BaseClassDecl->hasConstCopyAssignment(Context, +                                                                   MD); +  } +   +  //       -- for all the nonstatic data members of X that are of a class +  //          type M (or array thereof), each such class type has a copy +  //          assignment operator whose parameter is of type const M&, +  //          const volatile M& or M. +  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), +                                  FieldEnd = ClassDecl->field_end(); +       HasConstCopyAssignment && Field != FieldEnd; +       ++Field) { +    QualType FieldType = Context.getBaseElementType((*Field)->getType()); +    if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { +      const CXXRecordDecl *FieldClassDecl +        = cast<CXXRecordDecl>(FieldClassType->getDecl()); +      const CXXMethodDecl *MD = 0; +      HasConstCopyAssignment +        = FieldClassDecl->hasConstCopyAssignment(Context, MD); +    } +  } +   +  //   Otherwise, the implicitly declared copy assignment operator will +  //   have the form +  // +  //       X& X::operator=(X&) +  QualType ArgType = Context.getTypeDeclType(ClassDecl); +  QualType RetType = Context.getLValueReferenceType(ArgType); +  if (HasConstCopyAssignment) +    ArgType = ArgType.withConst(); +  ArgType = Context.getLValueReferenceType(ArgType); +   +  //   An implicitly-declared copy assignment operator is an inline public +  //   member of its class. +  DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); +  CXXMethodDecl *CopyAssignment +    = CXXMethodDecl::Create(Context, ClassDecl, ClassDecl->getLocation(), Name, +                            Context.getFunctionType(RetType, &ArgType, 1, +                                                    false, 0, +                                              /*FIXME: hasExceptionSpec*/false, +                                                    false, 0, 0, +                                                    FunctionType::ExtInfo()), +                            /*TInfo=*/0, /*isStatic=*/false, +                            /*StorageClassAsWritten=*/FunctionDecl::None, +                            /*isInline=*/true); +  CopyAssignment->setAccess(AS_public); +  CopyAssignment->setImplicit(); +  CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment()); +  CopyAssignment->setCopyAssignment(true); +   +  // Add the parameter to the operator. +  ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment, +                                               ClassDecl->getLocation(), +                                               /*Id=*/0, +                                               ArgType, /*TInfo=*/0, +                                               VarDecl::None, +                                               VarDecl::None, 0); +  CopyAssignment->setParams(&FromParam, 1); +   +  // Don't call addedAssignmentOperator. The class does not need to know about +  // the implicitly-declared copy assignment operator. +  if (S) +    PushOnScopeChains(CopyAssignment, S, true); +  else +    ClassDecl->addDecl(CopyAssignment); +   +  AddOverriddenMethods(ClassDecl, CopyAssignment); +  return CopyAssignment; +} +  void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,                                          CXXMethodDecl *CopyAssignOperator) {    assert((CopyAssignOperator->isImplicit() &&  | 

