diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 1678cd916a895b6a0f8004c752dc47ad3bd2e404..afa94989c6cebf0764e336872162b41771ddb44f 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -722,7 +722,8 @@ public: /// \brief Determine whether this class has any default constructors. bool hasDefaultConstructor() const { - return !data().UserDeclaredConstructor || hasDeclaredDefaultConstructor(); + return (data().DeclaredSpecialMembers & SMF_DefaultConstructor) || + needsImplicitDefaultConstructor(); } /// \brief Determine if we need to declare a default constructor for @@ -730,13 +731,8 @@ public: /// /// This value is used for lazy creation of default constructors. bool needsImplicitDefaultConstructor() const { - return !data().UserDeclaredConstructor && !hasDeclaredDefaultConstructor(); - } - - /// \brief Determine whether any default constructors have been declared for - /// this class (either explicitly or implicitly). - bool hasDeclaredDefaultConstructor() const { - return data().DeclaredSpecialMembers & SMF_DefaultConstructor; + return !data().UserDeclaredConstructor && + !(data().DeclaredSpecialMembers & SMF_DefaultConstructor); } /// hasConstCopyConstructor - Determines whether this class has a @@ -785,12 +781,10 @@ public: return data().UserDeclaredSpecialMembers & SMF_CopyConstructor; } - /// \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().DeclaredSpecialMembers & SMF_CopyConstructor; + /// \brief Determine whether this class needs an implicit copy + /// constructor to be lazily declared. + bool needsImplicitCopyConstructor() const { + return !(data().DeclaredSpecialMembers & SMF_CopyConstructor); } /// \brief Determine whether an implicit copy constructor for this type @@ -803,7 +797,7 @@ public: /// a parameter type which is a reference to a const-qualified type. bool hasCopyConstructorWithConstParam() const { return data().HasDeclaredCopyConstructorWithConstParam || - (!hasDeclaredCopyConstructor() && + (needsImplicitCopyConstructor() && implicitCopyConstructorHasConstParam()); } @@ -821,10 +815,12 @@ public: return data().UserDeclaredSpecialMembers & SMF_MoveConstructor; } - /// \brief Determine whether this class has had a move constructor - /// declared. - bool hasDeclaredMoveConstructor() const { - return data().DeclaredSpecialMembers & SMF_MoveConstructor; + /// \brief Determine whether this class has a move constructor. + /// FIXME: This can be wrong if the implicit move constructor would be + /// deleted. + bool hasMoveConstructor() const { + return (data().DeclaredSpecialMembers & SMF_MoveConstructor) || + needsImplicitMoveConstructor(); } /// \brief Determine whether implicit move constructor generation for this @@ -847,7 +843,7 @@ public: /// result. bool needsImplicitMoveConstructor() const { return !hasFailedImplicitMoveConstructor() && - !hasDeclaredMoveConstructor() && + !(data().DeclaredSpecialMembers & SMF_MoveConstructor) && !hasUserDeclaredCopyConstructor() && !hasUserDeclaredCopyAssignment() && !hasUserDeclaredMoveAssignment() && @@ -861,12 +857,10 @@ public: return data().UserDeclaredSpecialMembers & SMF_CopyAssignment; } - /// \brief Determine whether this class has had its copy assignment operator - /// declared, either via the user or via an implicit declaration. - /// - /// This value is used for lazy creation of copy assignment operators. - bool hasDeclaredCopyAssignment() const { - return data().DeclaredSpecialMembers & SMF_CopyAssignment; + /// \brief Determine whether this class needs an implicit copy + /// assignment operator to be lazily declared. + bool needsImplicitCopyAssignment() const { + return !(data().DeclaredSpecialMembers & SMF_CopyAssignment); } /// \brief Determine whether an implicit copy assignment operator for this @@ -880,7 +874,7 @@ public: /// a reference.. bool hasCopyAssignmentWithConstParam() const { return data().HasDeclaredCopyAssignmentWithConstParam || - (!hasDeclaredCopyAssignment() && + (needsImplicitCopyAssignment() && implicitCopyAssignmentHasConstParam()); } @@ -890,10 +884,11 @@ public: return data().UserDeclaredSpecialMembers & SMF_MoveAssignment; } - /// hasDeclaredMoveAssignment - Whether this class has a - /// declared move assignment operator. - bool hasDeclaredMoveAssignment() const { - return data().DeclaredSpecialMembers & SMF_MoveAssignment; + /// \brief Determine whether this class has a move assignment operator. + /// FIXME: This can be wrong if the implicit move assignment would be deleted. + bool hasMoveAssignment() const { + return (data().DeclaredSpecialMembers & SMF_MoveAssignment) || + needsImplicitMoveAssignment(); } /// \brief Determine whether implicit move assignment generation for this @@ -916,7 +911,7 @@ public: /// constructor wouldn't be deleted. bool needsImplicitMoveAssignment() const { return !hasFailedImplicitMoveAssignment() && - !hasDeclaredMoveAssignment() && + !(data().DeclaredSpecialMembers & SMF_MoveAssignment) && !hasUserDeclaredCopyConstructor() && !hasUserDeclaredCopyAssignment() && !hasUserDeclaredMoveConstructor() && @@ -930,12 +925,10 @@ public: return data().UserDeclaredSpecialMembers & SMF_Destructor; } - /// \brief Determine whether this class has had its destructor declared, - /// either via the user or via an implicit declaration. - /// - /// This value is used for lazy creation of destructors. - bool hasDeclaredDestructor() const { - return data().DeclaredSpecialMembers & SMF_Destructor; + /// \brief Determine whether this class needs an implicit destructor to + /// be lazily declared. + bool needsImplicitDestructor() const { + return !(data().DeclaredSpecialMembers & SMF_Destructor); } /// \brief Determine whether this class describes a lambda function object. @@ -1076,8 +1069,8 @@ public: /// FIXME: This can be wrong if the class has multiple move constructors, /// or if the implicit move constructor would be deleted. bool hasTrivialMoveConstructor() const { - return (data().HasTrivialSpecialMembers & SMF_MoveConstructor) && - (hasDeclaredMoveConstructor() || needsImplicitMoveConstructor()); + return hasMoveConstructor() && + (data().HasTrivialSpecialMembers & SMF_MoveConstructor); } /// \brief Determine whether this class has a non-trivial move constructor @@ -1085,8 +1078,8 @@ public: /// FIXME: This can be wrong if the implicit move constructor would be /// deleted. bool hasNonTrivialMoveConstructor() const { - return !(data().HasTrivialSpecialMembers & SMF_MoveConstructor) && - (hasDeclaredMoveConstructor() || needsImplicitMoveConstructor()); + return hasMoveConstructor() && + !(data().HasTrivialSpecialMembers & SMF_MoveConstructor); } /// \brief Determine whether this class has a trivial copy assignment operator @@ -1108,16 +1101,16 @@ public: /// FIXME: This can be wrong if the class has multiple move assignment /// operators, or if the implicit move assignment operator would be deleted. bool hasTrivialMoveAssignment() const { - return (data().HasTrivialSpecialMembers & SMF_MoveAssignment) && - (hasDeclaredMoveAssignment() || needsImplicitMoveAssignment()); + return hasMoveAssignment() && + (data().HasTrivialSpecialMembers & SMF_MoveAssignment); } /// \brief Determine whether this class has a non-trivial move assignment /// operator (C++11 [class.copy]p25) /// FIXME: This can be wrong if the implicit move assignment would be deleted. bool hasNonTrivialMoveAssignment() const { - return !(data().HasTrivialSpecialMembers & SMF_MoveAssignment) && - (hasDeclaredMoveAssignment() || needsImplicitMoveAssignment()); + return hasMoveAssignment() && + !(data().HasTrivialSpecialMembers & SMF_MoveAssignment); } /// \brief Determine whether this class has a trivial destructor diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 96dc1c9dee6c90fa7a747c6c741c3181f59eacb3..f3a6fb5ab2581cc19c10fd49b5598fcbd2f4eb73 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7342,7 +7342,7 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { // If a class has no user-declared destructor, a destructor is // declared implicitly. An implicitly-declared destructor is an // inline public member of its class. - assert(!ClassDecl->hasDeclaredDestructor()); + assert(ClassDecl->needsImplicitDestructor()); DeclaringSpecialMember DSM(*this, ClassDecl, CXXDestructor); if (DSM.isAlreadyBeingDeclared()) @@ -7829,7 +7829,7 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { // 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. - assert(!ClassDecl->hasDeclaredCopyAssignment()); + assert(ClassDecl->needsImplicitCopyAssignment()); DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyAssignment); if (DSM.isAlreadyBeingDeclared()) @@ -8203,14 +8203,18 @@ hasMoveOrIsTriviallyCopyable(Sema &S, QualType Type, bool IsConstructor) { return true; if (IsConstructor) { + // FIXME: Need this because otherwise hasMoveConstructor isn't guaranteed to + // give the right answer. if (ClassDecl->needsImplicitMoveConstructor()) S.DeclareImplicitMoveConstructor(ClassDecl); - return ClassDecl->hasDeclaredMoveConstructor(); + return ClassDecl->hasMoveConstructor(); } + // FIXME: Need this because otherwise hasMoveAssignment isn't guaranteed to + // give the right answer. if (ClassDecl->needsImplicitMoveAssignment()) S.DeclareImplicitMoveAssignment(ClassDecl); - return ClassDecl->hasDeclaredMoveAssignment(); + return ClassDecl->hasMoveAssignment(); } /// Determine whether all non-static data members and direct or virtual bases @@ -8613,7 +8617,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( // C++ [class.copy]p4: // If the class definition does not explicitly declare a copy // constructor, one is declared implicitly. - assert(!ClassDecl->hasDeclaredCopyConstructor()); + assert(ClassDecl->needsImplicitCopyConstructor()); DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyConstructor); if (DSM.isAlreadyBeingDeclared()) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 6344aa44b190d92796f6fba4fd469a207f25fc32..7bf1ca90e9defc5cdc65251c574a0ed39fa9475c 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2865,9 +2865,7 @@ static void TryConstructorInitialization(Sema &S, // If the initializer list has no elements and T has a default constructor, // the first phase is omitted. - if (ILE->getNumInits() != 0 || - (!DestRecordDecl->hasDeclaredDefaultConstructor() && - !DestRecordDecl->needsImplicitDefaultConstructor())) + if (ILE->getNumInits() != 0 || !DestRecordDecl->hasDefaultConstructor()) Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs, CandidateSet, Ctors, Best, CopyInitialization, AllowExplicit, @@ -3077,8 +3075,7 @@ static void TryListInitialization(Sema &S, // value-initialized. if (InitList->getNumInits() == 0) { CXXRecordDecl *RD = DestType->getAsCXXRecordDecl(); - if (RD->hasDeclaredDefaultConstructor() || - RD->needsImplicitDefaultConstructor()) { + if (RD->hasDefaultConstructor()) { TryValueInitialization(S, Entity, Kind, Sequence, InitList); return; } diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 4b1c6649be351f33dc8036aa4a40125f9122a671..ce8e8c173ea30f4c720369c6809914e11eb71cee 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -546,11 +546,11 @@ void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) { DeclareImplicitDefaultConstructor(Class); // If the copy constructor has not yet been declared, do so now. - if (!Class->hasDeclaredCopyConstructor()) + if (Class->needsImplicitCopyConstructor()) DeclareImplicitCopyConstructor(Class); // If the copy assignment operator has not yet been declared, do so now. - if (!Class->hasDeclaredCopyAssignment()) + if (Class->needsImplicitCopyAssignment()) DeclareImplicitCopyAssignment(Class); if (getLangOpts().CPlusPlus0x) { @@ -564,7 +564,7 @@ void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) { } // If the destructor has not yet been declared, do so now. - if (!Class->hasDeclaredDestructor()) + if (Class->needsImplicitDestructor()) DeclareImplicitDestructor(Class); } @@ -601,7 +601,7 @@ static void DeclareImplicitMemberFunctionsWithName(Sema &S, CXXRecordDecl *Class = const_cast(Record); if (Record->needsImplicitDefaultConstructor()) S.DeclareImplicitDefaultConstructor(Class); - if (!Record->hasDeclaredCopyConstructor()) + if (Record->needsImplicitCopyConstructor()) S.DeclareImplicitCopyConstructor(Class); if (S.getLangOpts().CPlusPlus0x && Record->needsImplicitMoveConstructor()) @@ -611,7 +611,7 @@ static void DeclareImplicitMemberFunctionsWithName(Sema &S, case DeclarationName::CXXDestructorName: if (const CXXRecordDecl *Record = dyn_cast(DC)) - if (Record->getDefinition() && !Record->hasDeclaredDestructor() && + if (Record->getDefinition() && Record->needsImplicitDestructor() && CanDeclareSpecialMemberFunction(Record)) S.DeclareImplicitDestructor(const_cast(Record)); break; @@ -623,7 +623,7 @@ static void DeclareImplicitMemberFunctionsWithName(Sema &S, if (const CXXRecordDecl *Record = dyn_cast(DC)) { if (Record->getDefinition() && CanDeclareSpecialMemberFunction(Record)) { CXXRecordDecl *Class = const_cast(Record); - if (!Record->hasDeclaredCopyAssignment()) + if (Record->needsImplicitCopyAssignment()) S.DeclareImplicitCopyAssignment(Class); if (S.getLangOpts().CPlusPlus0x && Record->needsImplicitMoveAssignment()) @@ -2257,7 +2257,7 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, SpecialMemberCache.InsertNode(Result, InsertPoint); if (SM == CXXDestructor) { - if (!RD->hasDeclaredDestructor()) + if (RD->needsImplicitDestructor()) DeclareImplicitDestructor(RD); CXXDestructorDecl *DD = RD->getDestructor(); assert(DD && "record without a destructor"); @@ -2286,13 +2286,13 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, } else { if (SM == CXXCopyConstructor || SM == CXXMoveConstructor) { Name = Context.DeclarationNames.getCXXConstructorName(CanTy); - if (!RD->hasDeclaredCopyConstructor()) + if (RD->needsImplicitCopyConstructor()) DeclareImplicitCopyConstructor(RD); if (getLangOpts().CPlusPlus0x && RD->needsImplicitMoveConstructor()) DeclareImplicitMoveConstructor(RD); } else { Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); - if (!RD->hasDeclaredCopyAssignment()) + if (RD->needsImplicitCopyAssignment()) DeclareImplicitCopyAssignment(RD); if (getLangOpts().CPlusPlus0x && RD->needsImplicitMoveAssignment()) DeclareImplicitMoveAssignment(RD); @@ -2446,7 +2446,7 @@ DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) { if (CanDeclareSpecialMemberFunction(Class)) { if (Class->needsImplicitDefaultConstructor()) DeclareImplicitDefaultConstructor(Class); - if (!Class->hasDeclaredCopyConstructor()) + if (Class->needsImplicitCopyConstructor()) DeclareImplicitCopyConstructor(Class); if (getLangOpts().CPlusPlus0x && Class->needsImplicitMoveConstructor()) DeclareImplicitMoveConstructor(Class);