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;  }  | 

