diff options
| -rw-r--r-- | clang/include/clang/AST/ASTContext.h | 7 | ||||
| -rw-r--r-- | clang/include/clang/AST/DeclCXX.h | 17 | ||||
| -rw-r--r-- | clang/lib/AST/ASTContext.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/Frontend/PCHReaderDecl.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/Frontend/PCHWriterDecl.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 41 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 30 | 
8 files changed, 88 insertions, 19 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 5e3f891e486..19b5694f0a8 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1327,6 +1327,13 @@ public:    //                    Statistics    //===--------------------------------------------------------------------===// +  /// \brief The number of implicitly-declared copy constructors. +  static unsigned NumImplicitCopyConstructors; +   +  /// \brief The number of implicitly-declared constructors for  +  /// which declarations were built. +  static unsigned NumImplicitCopyConstructorsDeclared; +    /// \brief The number of implicitly-declared copy assignment operators.    static unsigned NumImplicitCopyAssignmentOperators; diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 624bf631197..90302afc4c5 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -319,6 +319,9 @@ class CXXRecordDecl : public RecordDecl {      /// already computed and are available.      bool ComputedVisibleConversions : 1; +    /// \brief Whether we have already declared the copy constructor. +    bool DeclaredCopyConstructor : 1; +          /// \brief Whether we have already declared the copy-assignment operator.      bool DeclaredCopyAssignment : 1; @@ -576,6 +579,20 @@ public:      return data().UserDeclaredCopyConstructor;    } +  /// \brief Determine whether this class has had its copy constructor  +  /// declared, either via the user or via an implicit declaration. +  /// +  /// This value is used for lazy creation of copy constructors. +  bool hasDeclaredCopyConstructor() const { +    return data().DeclaredCopyConstructor; +  } +   +  /// \brief Note whether this class has already had its copy constructor  +  /// declared. +  void setDeclaredCopyConstructor(bool DCC) { +    data().DeclaredCopyConstructor = DCC; +  } +      /// 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. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index f44eb657215..4737abc3e35 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -31,6 +31,8 @@  using namespace clang; +unsigned ASTContext::NumImplicitCopyConstructors; +unsigned ASTContext::NumImplicitCopyConstructorsDeclared;  unsigned ASTContext::NumImplicitCopyAssignmentOperators;  unsigned ASTContext::NumImplicitCopyAssignmentOperatorsDeclared;  unsigned ASTContext::NumImplicitDestructors; @@ -259,6 +261,9 @@ void ASTContext::PrintStats() const {    fprintf(stderr, "Total bytes = %d\n", int(TotalBytes));    // Implicit special member functions. +  fprintf(stderr, "  %u/%u implicit copy constructors created\n", +          NumImplicitCopyConstructorsDeclared,  +          NumImplicitCopyConstructors);    fprintf(stderr, "  %u/%u implicit copy assignment operators created\n",            NumImplicitCopyAssignmentOperatorsDeclared,             NumImplicitCopyAssignmentOperators); diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index b54f0e2ca60..4b1909e57c6 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -32,6 +32,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)      Abstract(false), HasTrivialConstructor(true),      HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true),      HasTrivialDestructor(true), ComputedVisibleConversions(false), +    DeclaredCopyConstructor(false),       DeclaredCopyAssignment(false), DeclaredDestructor(false),      Bases(0), NumBases(0), VBases(0), NumVBases(0),      Definition(D), FirstFriend(0) { @@ -295,11 +296,13 @@ CXXRecordDecl::addedConstructor(ASTContext &Context,    // suppress the implicit declaration of a copy constructor.    if (ConDecl->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; +        }  } diff --git a/clang/lib/Frontend/PCHReaderDecl.cpp b/clang/lib/Frontend/PCHReaderDecl.cpp index 211032be8a5..a7b092abb93 100644 --- a/clang/lib/Frontend/PCHReaderDecl.cpp +++ b/clang/lib/Frontend/PCHReaderDecl.cpp @@ -657,6 +657,7 @@ void PCHDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) {        Data.HasTrivialCopyAssignment = Record[Idx++];        Data.HasTrivialDestructor = Record[Idx++];        Data.ComputedVisibleConversions = Record[Idx++]; +      Data.DeclaredCopyConstructor = Record[Idx++];        Data.DeclaredCopyAssignment = Record[Idx++];        Data.DeclaredDestructor = Record[Idx++]; diff --git a/clang/lib/Frontend/PCHWriterDecl.cpp b/clang/lib/Frontend/PCHWriterDecl.cpp index 411a125f5e9..3a053e283d1 100644 --- a/clang/lib/Frontend/PCHWriterDecl.cpp +++ b/clang/lib/Frontend/PCHWriterDecl.cpp @@ -654,6 +654,7 @@ void PCHDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {        Record.push_back(Data.HasTrivialCopyAssignment);        Record.push_back(Data.HasTrivialDestructor);        Record.push_back(Data.ComputedVisibleConversions); +      Record.push_back(Data.DeclaredCopyConstructor);        Record.push_back(Data.DeclaredCopyAssignment);        Record.push_back(Data.DeclaredDestructor); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 93caad669d9..5c98e2b1db2 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2657,7 +2657,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {      DeclareImplicitDefaultConstructor(ClassDecl);    if (!ClassDecl->hasUserDeclaredCopyConstructor()) -    DeclareImplicitCopyConstructor(ClassDecl); +    ++ASTContext::NumImplicitCopyConstructors;    if (!ClassDecl->hasUserDeclaredCopyAssignment()) {      ++ASTContext::NumImplicitCopyAssignmentOperators; @@ -5065,8 +5065,11 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(      if (Base->isVirtual())        continue; -    const CXXRecordDecl *BaseClassDecl +    CXXRecordDecl *BaseClassDecl        = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); +    if (!BaseClassDecl->hasDeclaredCopyConstructor()) +      DeclareImplicitCopyConstructor(BaseClassDecl); +        HasConstCopyConstructor        = BaseClassDecl->hasConstCopyConstructor(Context);    } @@ -5075,8 +5078,11 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(                                         BaseEnd = ClassDecl->vbases_end();         HasConstCopyConstructor && Base != BaseEnd;          ++Base) { -    const CXXRecordDecl *BaseClassDecl +    CXXRecordDecl *BaseClassDecl        = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); +    if (!BaseClassDecl->hasDeclaredCopyConstructor()) +      DeclareImplicitCopyConstructor(BaseClassDecl); +          HasConstCopyConstructor        = BaseClassDecl->hasConstCopyConstructor(Context);    } @@ -5091,8 +5097,11 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(         ++Field) {      QualType FieldType = Context.getBaseElementType((*Field)->getType());      if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { -      const CXXRecordDecl *FieldClassDecl +      CXXRecordDecl *FieldClassDecl          = cast<CXXRecordDecl>(FieldClassType->getDecl()); +      if (!FieldClassDecl->hasDeclaredCopyConstructor()) +        DeclareImplicitCopyConstructor(FieldClassDecl); +        HasConstCopyConstructor          = FieldClassDecl->hasConstCopyConstructor(Context);      } @@ -5121,8 +5130,11 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(      if (Base->isVirtual())        continue; -    const CXXRecordDecl *BaseClassDecl +    CXXRecordDecl *BaseClassDecl        = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); +    if (!BaseClassDecl->hasDeclaredCopyConstructor()) +      DeclareImplicitCopyConstructor(BaseClassDecl); +      if (CXXConstructorDecl *CopyConstructor                            = BaseClassDecl->getCopyConstructor(Context, Quals))        ExceptSpec.CalledDecl(CopyConstructor); @@ -5131,8 +5143,11 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(                                         BaseEnd = ClassDecl->vbases_end();         Base != BaseEnd;          ++Base) { -    const CXXRecordDecl *BaseClassDecl +    CXXRecordDecl *BaseClassDecl        = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); +    if (!BaseClassDecl->hasDeclaredCopyConstructor()) +      DeclareImplicitCopyConstructor(BaseClassDecl); +      if (CXXConstructorDecl *CopyConstructor                            = BaseClassDecl->getCopyConstructor(Context, Quals))        ExceptSpec.CalledDecl(CopyConstructor); @@ -5143,8 +5158,11 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(         ++Field) {      QualType FieldType = Context.getBaseElementType((*Field)->getType());      if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { -      const CXXRecordDecl *FieldClassDecl +      CXXRecordDecl *FieldClassDecl          = cast<CXXRecordDecl>(FieldClassType->getDecl()); +      if (!FieldClassDecl->hasDeclaredCopyConstructor()) +        DeclareImplicitCopyConstructor(FieldClassDecl); +        if (CXXConstructorDecl *CopyConstructor                            = FieldClassDecl->getCopyConstructor(Context, Quals))          ExceptSpec.CalledDecl(CopyConstructor); @@ -5175,6 +5193,10 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(    CopyConstructor->setImplicit();    CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor()); +  // Note that we have declared this constructor. +  ClassDecl->setDeclaredCopyConstructor(true); +  ++ASTContext::NumImplicitCopyConstructorsDeclared; +      // Add the parameter to the constructor.    ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,                                                 ClassDecl->getLocation(), @@ -5184,9 +5206,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(                                                 VarDecl::None, 0);    CopyConstructor->setParams(&FromParam, 1);    if (Scope *S = getScopeForContext(ClassDecl)) -    PushOnScopeChains(CopyConstructor, S, true); -  else -    ClassDecl->addDecl(CopyConstructor); +    PushOnScopeChains(CopyConstructor, S, false); +  ClassDecl->addDecl(CopyConstructor);    return CopyConstructor;  } diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 6d590893bdc..b13deec19ab 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -464,14 +464,19 @@ static bool CanDeclareSpecialMemberFunction(ASTContext &Context,  }  void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) { +  if (!CanDeclareSpecialMemberFunction(Context, Class)) +    return; +   +  // If the copy constructor has not yet been declared, do so now. +  if (!Class->hasDeclaredCopyConstructor()) +    DeclareImplicitCopyConstructor(Class); +      // If the copy assignment operator has not yet been declared, do so now. -  if (CanDeclareSpecialMemberFunction(Context, Class) && -      !Class->hasDeclaredCopyAssignment()) +  if (!Class->hasDeclaredCopyAssignment())      DeclareImplicitCopyAssignment(Class);    // If the destructor has not yet been declared, do so now. -  if (CanDeclareSpecialMemberFunction(Context, Class) && -      !Class->hasDeclaredDestructor()) +  if (!Class->hasDeclaredDestructor())      DeclareImplicitDestructor(Class);    } @@ -479,6 +484,7 @@ void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) {  /// special member function.  static bool isImplicitlyDeclaredMemberFunctionName(DeclarationName Name) {    switch (Name.getNameKind()) { +  case DeclarationName::CXXConstructorName:    case DeclarationName::CXXDestructorName:      return true; @@ -501,12 +507,18 @@ static void DeclareImplicitMemberFunctionsWithName(Sema &S,      return;    switch (Name.getNameKind()) { +  case DeclarationName::CXXConstructorName: +    if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) +      if (Record->getDefinition() && !Record->hasDeclaredCopyConstructor() && +          CanDeclareSpecialMemberFunction(S.Context, Record)) +        S.DeclareImplicitCopyConstructor(const_cast<CXXRecordDecl *>(Record)); +    break; +          case DeclarationName::CXXDestructorName:      if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))        if (Record->getDefinition() && !Record->hasDeclaredDestructor() &&            CanDeclareSpecialMemberFunction(S.Context, Record))          S.DeclareImplicitDestructor(const_cast<CXXRecordDecl *>(Record)); -          break;    case DeclarationName::CXXOperatorName: @@ -1992,9 +2004,11 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,  /// \brief Look up the constructors for the given class.  DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) { -  if (!Class->getDefinition()) -    return DeclContext::lookup_result(); - +  // If the copy constructor has not yet been declared, do so now. +  if (CanDeclareSpecialMemberFunction(Context, Class) && +      !Class->hasDeclaredCopyConstructor()) +    DeclareImplicitCopyConstructor(Class); +      CanQualType T = Context.getCanonicalType(Context.getTypeDeclType(Class));    DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(T);    return Class->lookup(Name);  | 

