From: Richard Smith Date: Sat, 8 Dec 2012 04:10:18 +0000 (+0000) Subject: Remove some remnants of the assumption that there is at most one of each X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=55798658f879915992ed0ebe30b0b63fd570ff1b;p=clang Remove some remnants of the assumption that there is at most one of each flavour of special member. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@169670 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 0228794032..bf6d62333b 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -748,32 +748,6 @@ public: !(data().DeclaredSpecialMembers & SMF_DefaultConstructor); } - /// hasConstCopyConstructor - Determines whether this class has a - /// copy constructor that accepts a const-qualified argument. - bool hasConstCopyConstructor() const; - - /// getCopyConstructor - Returns the copy constructor for this class - CXXConstructorDecl *getCopyConstructor(unsigned TypeQuals) const; - - /// getMoveConstructor - Returns the move constructor for this class - CXXConstructorDecl *getMoveConstructor() const; - - /// \brief Retrieve the copy-assignment operator for this class, if available. - /// - /// This routine attempts to find the copy-assignment operator for this - /// class, using a simplistic form of overload resolution. - /// - /// \param ArgIsConst Whether the argument to the copy-assignment operator - /// is const-qualified. - /// - /// \returns The copy-assignment operator that can be invoked, or NULL if - /// a unique copy-assignment operator could not be found. - CXXMethodDecl *getCopyAssignmentOperator(bool ArgIsConst) const; - - /// getMoveAssignmentOperator - Returns the move assignment operator for this - /// class - CXXMethodDecl *getMoveAssignmentOperator() const; - /// hasUserDeclaredConstructor - Whether this class has any /// user-declared constructors. When true, a default constructor /// will not be implicitly declared. diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index dfcc154d98..712480655e 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -324,10 +324,6 @@ bool CXXRecordDecl::hasAnyDependentBases() const { return !forallBases(SawBase, 0); } -bool CXXRecordDecl::hasConstCopyConstructor() const { - return getCopyConstructor(Qualifiers::Const) != 0; -} - bool CXXRecordDecl::isTriviallyCopyable() const { // C++0x [class]p5: // A trivially copyable class is a class that: @@ -345,126 +341,6 @@ bool CXXRecordDecl::isTriviallyCopyable() const { return true; } -/// \brief Perform a simplistic form of overload resolution that only considers -/// cv-qualifiers on a single parameter, and return the best overload candidate -/// (if there is one). -static CXXMethodDecl * -GetBestOverloadCandidateSimple( - const SmallVectorImpl > &Cands) { - if (Cands.empty()) - return 0; - if (Cands.size() == 1) - return Cands[0].first; - - unsigned Best = 0, N = Cands.size(); - for (unsigned I = 1; I != N; ++I) - if (Cands[Best].second.compatiblyIncludes(Cands[I].second)) - Best = I; - - for (unsigned I = 0; I != N; ++I) - if (I != Best && Cands[Best].second.compatiblyIncludes(Cands[I].second)) - return 0; - - return Cands[Best].first; -} - -CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(unsigned TypeQuals) const{ - ASTContext &Context = getASTContext(); - QualType ClassType - = Context.getTypeDeclType(const_cast(this)); - DeclarationName ConstructorName - = Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(ClassType)); - unsigned FoundTQs; - SmallVector, 4> Found; - DeclContext::lookup_const_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = this->lookup(ConstructorName); - Con != ConEnd; ++Con) { - // C++ [class.copy]p2: - // A non-template constructor for class X is a copy constructor if [...] - if (isa(*Con)) - continue; - - CXXConstructorDecl *Constructor = cast(*Con); - if (Constructor->isCopyConstructor(FoundTQs)) { - if (((TypeQuals & Qualifiers::Const) == (FoundTQs & Qualifiers::Const)) || - (!(TypeQuals & Qualifiers::Const) && (FoundTQs & Qualifiers::Const))) - Found.push_back(std::make_pair( - const_cast(Constructor), - Qualifiers::fromCVRMask(FoundTQs))); - } - } - - return cast_or_null( - GetBestOverloadCandidateSimple(Found)); -} - -CXXConstructorDecl *CXXRecordDecl::getMoveConstructor() const { - for (ctor_iterator I = ctor_begin(), E = ctor_end(); I != E; ++I) - if (I->isMoveConstructor()) - return *I; - - return 0; -} - -CXXMethodDecl *CXXRecordDecl::getCopyAssignmentOperator(bool ArgIsConst) const { - ASTContext &Context = getASTContext(); - QualType Class = Context.getTypeDeclType(const_cast(this)); - DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); - - SmallVector, 4> Found; - DeclContext::lookup_const_iterator Op, OpEnd; - for (llvm::tie(Op, OpEnd) = this->lookup(Name); Op != OpEnd; ++Op) { - // C++ [class.copy]p9: - // A user-declared copy assignment operator is a non-static non-template - // member function of class X with exactly one parameter of type X, X&, - // const X&, volatile X& or const volatile X&. - const CXXMethodDecl* Method = dyn_cast(*Op); - if (!Method || Method->isStatic() || Method->getPrimaryTemplate()) - continue; - - const FunctionProtoType *FnType - = Method->getType()->getAs(); - assert(FnType && "Overloaded operator has no prototype."); - // Don't assert on this; an invalid decl might have been left in the AST. - if (FnType->getNumArgs() != 1 || FnType->isVariadic()) - continue; - - QualType ArgType = FnType->getArgType(0); - Qualifiers Quals; - if (const LValueReferenceType *Ref = ArgType->getAs()) { - ArgType = Ref->getPointeeType(); - // If we have a const argument and we have a reference to a non-const, - // this function does not match. - if (ArgIsConst && !ArgType.isConstQualified()) - continue; - - Quals = ArgType.getQualifiers(); - } else { - // By-value copy-assignment operators are treated like const X& - // copy-assignment operators. - Quals = Qualifiers::fromCVRMask(Qualifiers::Const); - } - - if (!Context.hasSameUnqualifiedType(ArgType, Class)) - continue; - - // Save this copy-assignment operator. It might be "the one". - Found.push_back(std::make_pair(const_cast(Method), Quals)); - } - - // Use a simplistic form of overload resolution to find the candidate. - return GetBestOverloadCandidateSimple(Found); -} - -CXXMethodDecl *CXXRecordDecl::getMoveAssignmentOperator() const { - for (method_iterator I = method_begin(), E = method_end(); I != E; ++I) - if (I->isMoveAssignmentOperator()) - return *I; - - return 0; -} - void CXXRecordDecl::markedVirtualFunctionPure() { // C++ [class.abstract]p2: // A class is abstract if it has at least one pure virtual function. diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index f4b9a92467..8666453c31 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4687,12 +4687,28 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, if (RD->hasUserDeclaredMoveConstructor() && (!getLangOpts().MicrosoftMode || CSM == CXXCopyConstructor)) { if (!Diagnose) return true; - UserDeclaredMove = RD->getMoveConstructor(); + + // Find any user-declared move constructor. + for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(), + E = RD->ctor_end(); I != E; ++I) { + if (I->isMoveConstructor()) { + UserDeclaredMove = *I; + break; + } + } assert(UserDeclaredMove); } else if (RD->hasUserDeclaredMoveAssignment() && (!getLangOpts().MicrosoftMode || CSM == CXXCopyAssignment)) { if (!Diagnose) return true; - UserDeclaredMove = RD->getMoveAssignmentOperator(); + + // Find any user-declared move assignment operator. + for (CXXRecordDecl::method_iterator I = RD->method_begin(), + E = RD->method_end(); I != E; ++I) { + if (I->isMoveAssignmentOperator()) { + UserDeclaredMove = *I; + break; + } + } assert(UserDeclaredMove); }