diff options
-rw-r--r-- | clang/include/clang/AST/DeclCXX.h | 20 | ||||
-rw-r--r-- | clang/lib/AST/DeclBase.cpp | 13 | ||||
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 189 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 10 |
5 files changed, 120 insertions, 116 deletions
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index da32239b755..be5ec064712 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -406,13 +406,12 @@ class CXXRecordDecl : public RecordDecl { 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 @@ public: 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 @@ public: 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. diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 207edde5921..26ab9250d72 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -778,14 +778,11 @@ void DeclContext::addHiddenDecl(Decl *D) { } 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) { diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index ffdb98d7516..1b89ab6beda 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -259,99 +259,126 @@ CXXMethodDecl *CXXRecordDecl::getCopyAssignmentOperator(bool ArgIsConst) const { } 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; - - // 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; + // Handle (user-declared) constructors. + if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { + // Note that we have a user-declared constructor. + data().UserDeclaredConstructor = true; - // 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) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 48e36a9dc47..48beca71cf0 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -544,7 +544,9 @@ static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) { 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 { diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 025ac3bed9c..92655da609f 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4942,7 +4942,6 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { 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 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { << 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; } |