[cfe-commits] r168977 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/ASTImporter.cpp lib/AST/DeclCXX.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriter.cpp

Richard Smith richard-llvm at metafoo.co.uk
Thu Nov 29 21:11:39 PST 2012


Author: rsmith
Date: Thu Nov 29 23:11:39 2012
New Revision: 168977

URL: http://llvm.org/viewvc/llvm-project?rev=168977&view=rev
Log:
Refactor to reduce duplication in handling of special member functions. No functionality change.

Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=168977&r1=168976&r2=168977&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Thu Nov 29 23:11:39 2012
@@ -272,32 +272,25 @@
 
   friend void TagDecl::startDefinition();
 
+  /// Values used in DefinitionData fields to represent special members.
+  enum SpecialMemberFlags {
+    SMF_DefaultConstructor = 0x1,
+    SMF_CopyConstructor = 0x2,
+    SMF_MoveConstructor = 0x4,
+    SMF_CopyAssignment = 0x8,
+    SMF_MoveAssignment = 0x10,
+    SMF_Destructor = 0x20,
+    SMF_All = 0x3f
+  };
+
   struct DefinitionData {
     DefinitionData(CXXRecordDecl *D);
 
-    /// UserDeclaredConstructor - True when this class has a
-    /// user-declared constructor.
+    /// \brief True if this class has any user-declared constructors.
     bool UserDeclaredConstructor : 1;
 
-    /// UserDeclaredCopyConstructor - True when this class has a
-    /// user-declared copy constructor.
-    bool UserDeclaredCopyConstructor : 1;
-
-    /// UserDeclareMoveConstructor - True when this class has a
-    /// user-declared move constructor.
-    bool UserDeclaredMoveConstructor : 1;
-
-    /// UserDeclaredCopyAssignment - True when this class has a
-    /// user-declared copy assignment operator.
-    bool UserDeclaredCopyAssignment : 1;
-
-    /// UserDeclareMoveAssignment - True when this class has a
-    /// user-declared move assignment.
-    bool UserDeclaredMoveAssignment : 1;
-
-    /// UserDeclaredDestructor - True when this class has a
-    /// user-declared destructor.
-    bool UserDeclaredDestructor : 1;
+    /// The user-declared special members which this class has.
+    unsigned UserDeclaredSpecialMembers : 6;
 
     /// Aggregate - True when this class is an aggregate.
     bool Aggregate : 1;
@@ -360,21 +353,14 @@
     /// \brief True if any field has an in-class initializer.
     bool HasInClassInitializer : 1;
 
-    /// HasTrivialDefaultConstructor - True when, if this class has a default
-    /// constructor, this default constructor is trivial.
-    ///
-    /// C++0x [class.ctor]p5
-    ///    A default constructor is trivial if it is not user-provided and if
-    ///     -- its class has no virtual functions and no virtual base classes,
-    ///        and
-    ///     -- no non-static data member of its class has a
-    ///        brace-or-equal-initializer, and
-    ///     -- all the direct base classes of its class have trivial
-    ///        default constructors, and
-    ///     -- for all the nonstatic data members of its class that are of class
-    ///        type (or array thereof), each such class has a trivial
-    ///        default constructor.
-    bool HasTrivialDefaultConstructor : 1;
+    /// \brief The trivial special members which this class has, per
+    /// C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25,
+    /// C++11 [class.dtor]p5.
+    unsigned HasTrivialSpecialMembers : 6;
+
+    /// HasIrrelevantDestructor - True when this class has a destructor with no
+    /// semantic effect.
+    bool HasIrrelevantDestructor : 1;
 
     /// HasConstexprNonCopyMoveConstructor - True when this class has at least
     /// one user-declared constexpr constructor which is neither the copy nor
@@ -389,80 +375,6 @@
     /// default constructor (either user-declared or implicitly declared).
     bool HasConstexprDefaultConstructor : 1;
 
-    /// HasTrivialCopyConstructor - True when this class has a trivial copy
-    /// constructor.
-    ///
-    /// C++0x [class.copy]p13:
-    ///   A copy/move constructor for class X is trivial if it is neither
-    ///   user-provided and if
-    ///    -- class X has no virtual functions and no virtual base classes, and
-    ///    -- the constructor selected to copy/move each direct base class
-    ///       subobject is trivial, and
-    ///    -- for each non-static data member of X that is of class type (or an
-    ///       array thereof), the constructor selected to copy/move that member
-    ///       is trivial;
-    ///   otherwise the copy/move constructor is non-trivial.
-    bool HasTrivialCopyConstructor : 1;
-
-    /// HasTrivialMoveConstructor - True when this class has a trivial move
-    /// constructor.
-    ///
-    /// C++0x [class.copy]p13:
-    ///   A copy/move constructor for class X is trivial if it is neither
-    ///   user-provided and if
-    ///    -- class X has no virtual functions and no virtual base classes, and
-    ///    -- the constructor selected to copy/move each direct base class
-    ///       subobject is trivial, and
-    ///    -- for each non-static data member of X that is of class type (or an
-    ///       array thereof), the constructor selected to copy/move that member
-    ///       is trivial;
-    ///   otherwise the copy/move constructor is non-trivial.
-    bool HasTrivialMoveConstructor : 1;
-
-    /// HasTrivialCopyAssignment - True when this class has a trivial copy
-    /// assignment operator.
-    ///
-    /// C++0x [class.copy]p27:
-    ///   A copy/move assignment operator for class X is trivial if it is
-    ///   neither user-provided nor deleted and if
-    ///    -- class X has no virtual functions and no virtual base classes, and
-    ///    -- the assignment operator selected to copy/move each direct base
-    ///       class subobject is trivial, and
-    ///    -- for each non-static data member of X that is of class type (or an
-    ///       array thereof), the assignment operator selected to copy/move
-    ///       that member is trivial;
-    ///   otherwise the copy/move assignment operator is non-trivial.
-    bool HasTrivialCopyAssignment : 1;
-
-    /// HasTrivialMoveAssignment - True when this class has a trivial move
-    /// assignment operator.
-    ///
-    /// C++0x [class.copy]p27:
-    ///   A copy/move assignment operator for class X is trivial if it is
-    ///   neither user-provided nor deleted and if
-    ///    -- class X has no virtual functions and no virtual base classes, and
-    ///    -- the assignment operator selected to copy/move each direct base
-    ///       class subobject is trivial, and
-    ///    -- for each non-static data member of X that is of class type (or an
-    ///       array thereof), the assignment operator selected to copy/move
-    ///       that member is trivial;
-    ///   otherwise the copy/move assignment operator is non-trivial.
-    bool HasTrivialMoveAssignment : 1;
-
-    /// HasTrivialDestructor - True when this class has a trivial destructor.
-    ///
-    /// C++ [class.dtor]p3.  A destructor is trivial if it is an
-    /// implicitly-declared destructor and if:
-    /// * all of the direct base classes of its class have trivial destructors
-    ///   and
-    /// * for all of the non-static data members of its class that are of class
-    ///   type (or array thereof), each such class has a trivial destructor.
-    bool HasTrivialDestructor : 1;
-
-    /// HasIrrelevantDestructor - True when this class has a destructor with no
-    /// semantic effect.
-    bool HasIrrelevantDestructor : 1;
-
     /// HasNonLiteralTypeFieldsOrBases - True when this class contains at least
     /// one non-static data member or base class of non-literal or volatile
     /// type.
@@ -472,27 +384,13 @@
     /// already computed and are available.
     bool ComputedVisibleConversions : 1;
 
-    /// \brief Whether we have a C++0x user-provided default constructor (not
+    /// \brief Whether we have a C++11 user-provided default constructor (not
     /// explicitly deleted or defaulted).
     bool UserProvidedDefaultConstructor : 1;
 
-    /// \brief Whether we have already declared the default constructor.
-    bool DeclaredDefaultConstructor : 1;
-
-    /// \brief Whether we have already declared the copy constructor.
-    bool DeclaredCopyConstructor : 1;
-
-    /// \brief Whether we have already declared the move constructor.
-    bool DeclaredMoveConstructor : 1;
-
-    /// \brief Whether we have already declared the copy-assignment operator.
-    bool DeclaredCopyAssignment : 1;
-
-    /// \brief Whether we have already declared the move-assignment operator.
-    bool DeclaredMoveAssignment : 1;
-
-    /// \brief Whether we have already declared a destructor within the class.
-    bool DeclaredDestructor : 1;
+    /// \brief The special members which have been declared for this class,
+    /// either by the user or implicitly.
+    unsigned DeclaredSpecialMembers : 6;
 
     /// \brief Whether an implicit copy constructor would have a const-qualified
     /// parameter.
@@ -824,8 +722,7 @@
 
   /// \brief Determine whether this class has any default constructors.
   bool hasDefaultConstructor() const {
-    return !data().UserDeclaredConstructor ||
-           data().DeclaredDefaultConstructor;
+    return !data().UserDeclaredConstructor || hasDeclaredDefaultConstructor();
   }
 
   /// \brief Determine if we need to declare a default constructor for
@@ -833,14 +730,13 @@
   ///
   /// This value is used for lazy creation of default constructors.
   bool needsImplicitDefaultConstructor() const {
-    return !data().UserDeclaredConstructor &&
-           !data().DeclaredDefaultConstructor;
+    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().DeclaredDefaultConstructor;
+    return data().DeclaredSpecialMembers & SMF_DefaultConstructor;
   }
 
   /// hasConstCopyConstructor - Determines whether this class has a
@@ -886,7 +782,7 @@
   /// user-declared copy constructor. When false, a copy constructor
   /// will be implicitly declared.
   bool hasUserDeclaredCopyConstructor() const {
-    return data().UserDeclaredCopyConstructor;
+    return data().UserDeclaredSpecialMembers & SMF_CopyConstructor;
   }
 
   /// \brief Determine whether this class has had its copy constructor
@@ -894,7 +790,7 @@
   ///
   /// This value is used for lazy creation of copy constructors.
   bool hasDeclaredCopyConstructor() const {
-    return data().DeclaredCopyConstructor;
+    return data().DeclaredSpecialMembers & SMF_CopyConstructor;
   }
 
   /// \brief Determine whether an implicit copy constructor for this type
@@ -915,20 +811,20 @@
   /// declared move constructor or assignment operator. When false, a
   /// move constructor and assignment operator may be implicitly declared.
   bool hasUserDeclaredMoveOperation() const {
-    return data().UserDeclaredMoveConstructor ||
-           data().UserDeclaredMoveAssignment;
+    return data().UserDeclaredSpecialMembers &
+             (SMF_MoveConstructor | SMF_MoveAssignment);
   }
 
   /// \brief Determine whether this class has had a move constructor
   /// declared by the user.
   bool hasUserDeclaredMoveConstructor() const {
-    return data().UserDeclaredMoveConstructor;
+    return data().UserDeclaredSpecialMembers & SMF_MoveConstructor;
   }
 
   /// \brief Determine whether this class has had a move constructor
   /// declared.
   bool hasDeclaredMoveConstructor() const {
-    return data().DeclaredMoveConstructor;
+    return data().DeclaredSpecialMembers & SMF_MoveConstructor;
   }
 
   /// \brief Determine whether implicit move constructor generation for this
@@ -962,7 +858,7 @@
   /// user-declared copy assignment operator. When false, a copy
   /// assigment operator will be implicitly declared.
   bool hasUserDeclaredCopyAssignment() const {
-    return data().UserDeclaredCopyAssignment;
+    return data().UserDeclaredSpecialMembers & SMF_CopyAssignment;
   }
 
   /// \brief Determine whether this class has had its copy assignment operator
@@ -970,7 +866,7 @@
   ///
   /// This value is used for lazy creation of copy assignment operators.
   bool hasDeclaredCopyAssignment() const {
-    return data().DeclaredCopyAssignment;
+    return data().DeclaredSpecialMembers & SMF_CopyAssignment;
   }
 
   /// \brief Determine whether an implicit copy assignment operator for this
@@ -991,13 +887,13 @@
   /// \brief Determine whether this class has had a move assignment
   /// declared by the user.
   bool hasUserDeclaredMoveAssignment() const {
-    return data().UserDeclaredMoveAssignment;
+    return data().UserDeclaredSpecialMembers & SMF_MoveAssignment;
   }
 
   /// hasDeclaredMoveAssignment - Whether this class has a
   /// declared move assignment operator.
   bool hasDeclaredMoveAssignment() const {
-    return data().DeclaredMoveAssignment;
+    return data().DeclaredSpecialMembers & SMF_MoveAssignment;
   }
 
   /// \brief Determine whether implicit move assignment generation for this
@@ -1031,14 +927,16 @@
   /// user-declared destructor. When false, a destructor will be
   /// implicitly declared.
   bool hasUserDeclaredDestructor() const {
-    return data().UserDeclaredDestructor;
+    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().DeclaredDestructor; }
+  bool hasDeclaredDestructor() const {
+    return data().DeclaredSpecialMembers & SMF_Destructor;
+  }
 
   /// \brief Determine whether this class describes a lambda function object.
   bool isLambda() const { return hasDefinition() && data().IsLambda; }
@@ -1127,13 +1025,15 @@
   /// (C++11 [class.ctor]p5).
   /// FIXME: This can be wrong when the class has multiple default constructors.
   bool hasTrivialDefaultConstructor() const {
-    return hasDefaultConstructor() && data().HasTrivialDefaultConstructor;
+    return hasDefaultConstructor() &&
+           (data().HasTrivialSpecialMembers & SMF_DefaultConstructor);
   }
 
   /// \brief Determine whether this class has a non-trivial default constructor
   /// (C++11 [class.ctor]p5).
   bool hasNonTrivialDefaultConstructor() const {
-    return hasDefaultConstructor() && !data().HasTrivialDefaultConstructor;
+    return hasDefaultConstructor() &&
+           !(data().HasTrivialSpecialMembers & SMF_DefaultConstructor);
   }
 
   /// \brief Determine whether this class has at least one constexpr constructor
@@ -1162,13 +1062,13 @@
   /// (C++ [class.copy]p6, C++11 [class.copy]p12)
   /// FIXME: This can be wrong if the class has multiple copy constructors.
   bool hasTrivialCopyConstructor() const {
-    return data().HasTrivialCopyConstructor;
+    return data().HasTrivialSpecialMembers & SMF_CopyConstructor;
   }
 
   /// \brief Determine whether this class has a non-trivial copy constructor
   /// (C++ [class.copy]p6, C++11 [class.copy]p12)
   bool hasNonTrivialCopyConstructor() const {
-    return !data().HasTrivialCopyConstructor;
+    return !(data().HasTrivialSpecialMembers & SMF_CopyConstructor);
   }
 
   /// \brief Determine whether this class has a trivial move constructor
@@ -1176,7 +1076,7 @@
   /// 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().HasTrivialMoveConstructor &&
+    return (data().HasTrivialSpecialMembers & SMF_MoveConstructor) &&
            (hasDeclaredMoveConstructor() || needsImplicitMoveConstructor());
   }
 
@@ -1185,7 +1085,7 @@
   /// FIXME: This can be wrong if the implicit move constructor would be
   /// deleted.
   bool hasNonTrivialMoveConstructor() const {
-    return !data().HasTrivialMoveConstructor &&
+    return !(data().HasTrivialSpecialMembers & SMF_MoveConstructor) &&
            (hasDeclaredMoveConstructor() || needsImplicitMoveConstructor());
   }
 
@@ -1194,13 +1094,13 @@
   /// FIXME: This can be wrong if the class has multiple copy assignment
   /// operators.
   bool hasTrivialCopyAssignment() const {
-    return data().HasTrivialCopyAssignment;
+    return data().HasTrivialSpecialMembers & SMF_CopyAssignment;
   }
 
   /// \brief Determine whether this class has a non-trivial copy assignment
   /// operator (C++ [class.copy]p11, C++11 [class.copy]p25)
   bool hasNonTrivialCopyAssignment() const {
-    return !data().HasTrivialCopyAssignment;
+    return !(data().HasTrivialSpecialMembers & SMF_CopyAssignment);
   }
 
   /// \brief Determine whether this class has a trivial move assignment operator
@@ -1208,7 +1108,7 @@
   /// 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().HasTrivialMoveAssignment &&
+    return (data().HasTrivialSpecialMembers & SMF_MoveAssignment) &&
            (hasDeclaredMoveAssignment() || needsImplicitMoveAssignment());
   }
 
@@ -1216,17 +1116,21 @@
   /// operator (C++11 [class.copy]p25)
   /// FIXME: This can be wrong if the implicit move assignment would be deleted.
   bool hasNonTrivialMoveAssignment() const {
-    return !data().HasTrivialMoveAssignment &&
+    return !(data().HasTrivialSpecialMembers & SMF_MoveAssignment) &&
            (hasDeclaredMoveAssignment() || needsImplicitMoveAssignment());
   }
 
   /// \brief Determine whether this class has a trivial destructor
   /// (C++ [class.dtor]p3)
-  bool hasTrivialDestructor() const { return data().HasTrivialDestructor; }
+  bool hasTrivialDestructor() const {
+    return data().HasTrivialSpecialMembers & SMF_Destructor;
+  }
 
   /// \brief Determine whether this class has a non-trivial destructor
   /// (C++ [class.dtor]p3)
-  bool hasNonTrivialDestructor() const { return !data().HasTrivialDestructor; }
+  bool hasNonTrivialDestructor() const {
+    return !(data().HasTrivialSpecialMembers & SMF_Destructor);
+  }
 
   // hasIrrelevantDestructor - Whether this class has a destructor which has no
   // semantic effect. Any such destructor will be trivial, public, defaulted

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=168977&r1=168976&r2=168977&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Thu Nov 29 23:11:39 2012
@@ -1908,11 +1908,7 @@
     struct CXXRecordDecl::DefinitionData &ToData = ToCXX->data();
     struct CXXRecordDecl::DefinitionData &FromData = FromCXX->data();
     ToData.UserDeclaredConstructor = FromData.UserDeclaredConstructor;
-    ToData.UserDeclaredCopyConstructor = FromData.UserDeclaredCopyConstructor;
-    ToData.UserDeclaredMoveConstructor = FromData.UserDeclaredMoveConstructor;
-    ToData.UserDeclaredCopyAssignment = FromData.UserDeclaredCopyAssignment;
-    ToData.UserDeclaredMoveAssignment = FromData.UserDeclaredMoveAssignment;
-    ToData.UserDeclaredDestructor = FromData.UserDeclaredDestructor;
+    ToData.UserDeclaredSpecialMembers = FromData.UserDeclaredSpecialMembers;
     ToData.Aggregate = FromData.Aggregate;
     ToData.PlainOldData = FromData.PlainOldData;
     ToData.Empty = FromData.Empty;
@@ -1926,30 +1922,20 @@
     ToData.HasMutableFields = FromData.HasMutableFields;
     ToData.HasOnlyCMembers = FromData.HasOnlyCMembers;
     ToData.HasInClassInitializer = FromData.HasInClassInitializer;
-    ToData.HasTrivialDefaultConstructor = FromData.HasTrivialDefaultConstructor;
+    ToData.HasTrivialSpecialMembers = FromData.HasTrivialSpecialMembers;
+    ToData.HasIrrelevantDestructor = FromData.HasIrrelevantDestructor;
     ToData.HasConstexprNonCopyMoveConstructor
       = FromData.HasConstexprNonCopyMoveConstructor;
     ToData.DefaultedDefaultConstructorIsConstexpr
       = FromData.DefaultedDefaultConstructorIsConstexpr;
     ToData.HasConstexprDefaultConstructor
       = FromData.HasConstexprDefaultConstructor;
-    ToData.HasTrivialCopyConstructor = FromData.HasTrivialCopyConstructor;
-    ToData.HasTrivialMoveConstructor = FromData.HasTrivialMoveConstructor;
-    ToData.HasTrivialCopyAssignment = FromData.HasTrivialCopyAssignment;
-    ToData.HasTrivialMoveAssignment = FromData.HasTrivialMoveAssignment;
-    ToData.HasTrivialDestructor = FromData.HasTrivialDestructor;
-    ToData.HasIrrelevantDestructor = FromData.HasIrrelevantDestructor;
     ToData.HasNonLiteralTypeFieldsOrBases
       = FromData.HasNonLiteralTypeFieldsOrBases;
     // ComputedVisibleConversions not imported.
     ToData.UserProvidedDefaultConstructor
       = FromData.UserProvidedDefaultConstructor;
-    ToData.DeclaredDefaultConstructor = FromData.DeclaredDefaultConstructor;
-    ToData.DeclaredCopyConstructor = FromData.DeclaredCopyConstructor;
-    ToData.DeclaredMoveConstructor = FromData.DeclaredMoveConstructor;
-    ToData.DeclaredCopyAssignment = FromData.DeclaredCopyAssignment;
-    ToData.DeclaredMoveAssignment = FromData.DeclaredMoveAssignment;
-    ToData.DeclaredDestructor = FromData.DeclaredDestructor;
+    ToData.DeclaredSpecialMembers = FromData.DeclaredSpecialMembers;
     ToData.ImplicitCopyConstructorHasConstParam
       = FromData.ImplicitCopyConstructorHasConstParam;
     ToData.ImplicitCopyAssignmentHasConstParam

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=168977&r1=168976&r2=168977&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Thu Nov 29 23:11:39 2012
@@ -36,26 +36,19 @@
 }
 
 CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
-  : UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
-    UserDeclaredMoveConstructor(false), UserDeclaredCopyAssignment(false),
-    UserDeclaredMoveAssignment(false), UserDeclaredDestructor(false),
+  : UserDeclaredConstructor(false), UserDeclaredSpecialMembers(0),
     Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
     Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true),
     HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false),
     HasMutableFields(false), HasOnlyCMembers(true),
     HasInClassInitializer(false),
-    HasTrivialDefaultConstructor(true),
+    HasTrivialSpecialMembers(SMF_All),
+    HasIrrelevantDestructor(true),
     HasConstexprNonCopyMoveConstructor(false),
     DefaultedDefaultConstructorIsConstexpr(true),
-    HasConstexprDefaultConstructor(false), HasTrivialCopyConstructor(true),
-    HasTrivialMoveConstructor(true), HasTrivialCopyAssignment(true),
-    HasTrivialMoveAssignment(true), HasTrivialDestructor(true),
-    HasIrrelevantDestructor(true),
+    HasConstexprDefaultConstructor(false),
     HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
-    UserProvidedDefaultConstructor(false), DeclaredDefaultConstructor(false),
-    DeclaredCopyConstructor(false), DeclaredMoveConstructor(false),
-    DeclaredCopyAssignment(false), DeclaredMoveAssignment(false),
-    DeclaredDestructor(false),
+    UserProvidedDefaultConstructor(false), DeclaredSpecialMembers(0),
     ImplicitCopyConstructorHasConstParam(true),
     ImplicitCopyAssignmentHasConstParam(true),
     HasDeclaredCopyConstructorWithConstParam(false),
@@ -212,25 +205,12 @@
       //    T is a class type, but not a union type, with ... no virtual base
       //    classes
       data().Empty = false;
-      
-      // C++ [class.ctor]p5:
-      //   A default constructor is trivial [...] if:
-      //    -- its class has [...] no virtual bases
-      data().HasTrivialDefaultConstructor = false;
-
-      // C++0x [class.copy]p13:
-      //   A copy/move constructor for class X is trivial if it is neither
-      //   user-provided nor deleted and if
-      //    -- class X has no virtual functions and no virtual base classes, and
-      data().HasTrivialCopyConstructor = false;
-      data().HasTrivialMoveConstructor = false;
 
-      // C++0x [class.copy]p27:
-      //   A copy/move assignment operator for class X is trivial if it is
-      //   neither user-provided nor deleted and if
-      //    -- class X has no virtual functions and no virtual base classes, and
-      data().HasTrivialCopyAssignment = false;
-      data().HasTrivialMoveAssignment = false;
+      // C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25:
+      //   A [default constructor, copy/move constructor, or copy/move assignment
+      //   operator for a class X] is trivial [...] if:
+      //    -- class X has [...] no virtual base classes
+      data().HasTrivialSpecialMembers &= SMF_Destructor;
 
       // C++0x [class]p7:
       //   A standard-layout class is a class that: [...]
@@ -247,8 +227,8 @@
       //    -- all the direct base classes of its class have trivial default
       //       constructors.
       if (!BaseClassDecl->hasTrivialDefaultConstructor())
-        data().HasTrivialDefaultConstructor = false;
-      
+        data().HasTrivialSpecialMembers &= ~SMF_DefaultConstructor;
+
       // C++0x [class.copy]p13:
       //   A copy/move constructor for class X is trivial if [...]
       //    [...]
@@ -258,9 +238,9 @@
       // instead of all of them. For now, we treat a move constructor as being
       // non-trivial if it calls anything other than a trivial move constructor.
       if (!BaseClassDecl->hasTrivialCopyConstructor())
-        data().HasTrivialCopyConstructor = false;
+        data().HasTrivialSpecialMembers &= ~SMF_CopyConstructor;
       if (!BaseClassDecl->hasTrivialMoveConstructor())
-        data().HasTrivialMoveConstructor = false;
+        data().HasTrivialSpecialMembers &= ~SMF_MoveConstructor;
 
       // C++0x [class.copy]p27:
       //   A copy/move assignment operator for class X is trivial if [...]
@@ -270,9 +250,9 @@
       // FIXME: C++0x: We need to only consider the selected operator instead
       // of all of them.
       if (!BaseClassDecl->hasTrivialCopyAssignment())
-        data().HasTrivialCopyAssignment = false;
+        data().HasTrivialSpecialMembers &= ~SMF_CopyAssignment;
       if (!BaseClassDecl->hasTrivialMoveAssignment())
-        data().HasTrivialMoveAssignment = false;
+        data().HasTrivialSpecialMembers &= ~SMF_MoveAssignment;
 
       // C++11 [class.ctor]p6:
       //   If that user-written default constructor would satisfy the
@@ -286,7 +266,7 @@
     //   A destructor is trivial if all the direct base classes of its class
     //   have trivial destructors.
     if (!BaseClassDecl->hasTrivialDestructor())
-      data().HasTrivialDestructor = false;
+      data().HasTrivialSpecialMembers &= ~SMF_Destructor;
 
     if (!BaseClassDecl->hasIrrelevantDestructor())
       data().HasIrrelevantDestructor = false;
@@ -529,24 +509,13 @@
       //   A class that declares or inherits a virtual function is called a 
       //   polymorphic class.
       data().Polymorphic = true;
-      
-      // C++0x [class.ctor]p5
-      //   A default constructor is trivial [...] if:
-      //    -- its class has no virtual functions [...]
-      data().HasTrivialDefaultConstructor = false;
 
-      // C++0x [class.copy]p13:
-      //   A copy/move constructor for class X is trivial if [...]
+      // C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25:
+      //   A [default constructor, copy/move constructor, or copy/move
+      //   assignment operator for a class X] is trivial [...] if:
       //    -- class X has no virtual functions [...]
-      data().HasTrivialCopyConstructor = false;
-      data().HasTrivialMoveConstructor = false;
+      data().HasTrivialSpecialMembers &= SMF_Destructor;
 
-      // C++0x [class.copy]p27:
-      //   A copy/move assignment operator for class X is trivial if [...]
-      //    -- class X has no virtual functions [...]
-      data().HasTrivialCopyAssignment = false;
-      data().HasTrivialMoveAssignment = false;
-            
       // C++0x [class]p7:
       //   A standard-layout class is a class that: [...]
       //    -- has no virtual functions
@@ -560,6 +529,9 @@
     if (ASTMutationListener *L = getASTMutationListener())
       L->AddedCXXImplicitMember(data().Definition, D);
 
+  // The kind of special member this declaration is, if any.
+  unsigned SMKind = 0;
+
   // Handle constructors.
   if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
     if (!Constructor->isImplicit()) {
@@ -579,45 +551,23 @@
     bool UserProvided = Constructor->isUserProvided();
 
     if (Constructor->isDefaultConstructor()) {
-      data().DeclaredDefaultConstructor = true;
-      if (UserProvided) {
-        // C++0x [class.ctor]p5:
-        //   A default constructor is trivial if it is not user-provided [...]
-        data().HasTrivialDefaultConstructor = false;
+      SMKind |= SMF_DefaultConstructor;
+
+      if (UserProvided)
         data().UserProvidedDefaultConstructor = true;
-      }
       if (Constructor->isConstexpr())
         data().HasConstexprDefaultConstructor = true;
     }
 
-    // Note when we have a user-declared copy or move constructor, which will
-    // suppress the implicit declaration of those constructors.
     if (!FunTmpl) {
       unsigned Quals;
       if (Constructor->isCopyConstructor(Quals)) {
-        if (!Constructor->isImplicit())
-          data().UserDeclaredCopyConstructor = true;
-        data().DeclaredCopyConstructor = true;
-
-        // C++0x [class.copy]p13:
-        //   A copy/move constructor for class X is trivial if it is not
-        //   user-provided [...]
-        if (UserProvided)
-          data().HasTrivialCopyConstructor = false;
+        SMKind |= SMF_CopyConstructor;
 
         if (Quals & Qualifiers::Const)
           data().HasDeclaredCopyConstructorWithConstParam = true;
-      } else if (Constructor->isMoveConstructor()) {
-        if (!Constructor->isImplicit())
-          data().UserDeclaredMoveConstructor = true;
-        data().DeclaredMoveConstructor = true;
-
-        // C++0x [class.copy]p13:
-        //   A copy/move constructor for class X is trivial if it is not
-        //   user-provided [...]
-        if (UserProvided)
-          data().HasTrivialMoveConstructor = false;
-      }
+      } else if (Constructor->isMoveConstructor())
+        SMKind |= SMF_MoveConstructor;
     }
 
     // Record if we see any constexpr constructors which are neither copy
@@ -634,57 +584,25 @@
     if (getASTContext().getLangOpts().CPlusPlus0x
           ? UserProvided : !Constructor->isImplicit())
       data().Aggregate = false;
-
-    return;
   }
 
   // Handle destructors.
   if (CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D)) {
-    data().DeclaredDestructor = true;
+    SMKind |= SMF_Destructor;
 
-    if (!DD->isImplicit()) {
-      data().UserDeclaredDestructor = true;
+    if (!DD->isImplicit())
       data().HasIrrelevantDestructor = false;
 
-      // C++ [class]p4:
-      //   A POD-struct is an aggregate class that has [...] no user-defined
-      //   destructor.
-      // This bit is the C++03 POD bit, not the 0x one.
-      data().PlainOldData = false;
-    }
-
     // C++11 [class.dtor]p5:
-    //   A destructor is trivial if it is not user-provided and if
-    //    -- the destructor is not virtual.
-    if (DD->isUserProvided() || DD->isVirtual())
-      data().HasTrivialDestructor = false;
-
-    return;
+    //   A destructor is trivial if [...] the destructor is not virtual.
+    if (DD->isVirtual())
+      data().HasTrivialSpecialMembers &= ~SMF_Destructor;
   }
 
   // Handle member functions.
   if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
     if (Method->isCopyAssignmentOperator()) {
-      // Suppress the implicit declaration of a copy constructor.
-      data().DeclaredCopyAssignment = true;
-
-      if (!Method->isImplicit()) {
-        data().UserDeclaredCopyAssignment = true;
-
-        // C++ [class]p4:
-        //   A POD-struct is an aggregate class that [...] has no user-defined
-        //   copy assignment operator [...].
-        // This is the C++03 bit only.
-        data().PlainOldData = false;
-
-        // C++11 [class.copy]p25:
-        //   A copy/move assignment operator for class X is trivial if it is
-        //   not user-provided [...]
-        // FIXME: This is bogus. Having one user-provided copy assignment
-        // doesn't stop another one from being trivial.
-        if (Method->isUserProvided())
-          data().HasTrivialCopyAssignment = false;
-      }
+      SMKind |= SMF_CopyAssignment;
 
       const ReferenceType *ParamTy =
         Method->getParamDecl(0)->getType()->getAs<ReferenceType>();
@@ -692,34 +610,16 @@
         data().HasDeclaredCopyAssignmentWithConstParam = true;
     }
 
-    if (Method->isMoveAssignmentOperator()) {
-      data().DeclaredMoveAssignment = true;
-
-      if (!Method->isImplicit()) {
-        data().UserDeclaredMoveAssignment = true;
-
-        // This is an extension in C++03 mode, but we'll keep consistency by
-        // taking a move assignment operator to induce non-POD-ness
-        data().PlainOldData = false;
-
-        // C++0x [class.copy]p27:
-        //   A copy/move assignment operator for class X is trivial if it is
-        //   neither user-provided nor deleted [...]
-        if (Method->isUserProvided())
-          data().HasTrivialMoveAssignment = false;
-      }
-    }
+    if (Method->isMoveAssignmentOperator())
+      SMKind |= SMF_MoveAssignment;
 
     // Keep the list of conversion functions up-to-date.
     if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
-      // We don't record specializations.
-      if (Conversion->getPrimaryTemplate())
-        return;
-
       // FIXME: We intentionally don't use the decl's access here because it
       // hasn't been set yet.  That's really just a misdesign in Sema.
-
-      if (FunTmpl) {
+      if (Conversion->getPrimaryTemplate()) {
+        // We don't record specializations.
+      } else if (FunTmpl) {
         if (FunTmpl->getPreviousDecl())
           data().Conversions.replace(FunTmpl->getPreviousDecl(),
                                      FunTmpl);
@@ -734,9 +634,40 @@
       }
     }
 
+    if (SMKind) {
+      // Note when we have declared a declared special member, and suppress the
+      // implicit declaration of this special member.
+      data().DeclaredSpecialMembers |= SMKind;
+
+      if (!Method->isImplicit()) {
+        data().UserDeclaredSpecialMembers |= SMKind;
+
+        // C++03 [class]p4:
+        //   A POD-struct is an aggregate class that has [...] no user-defined
+        //   copy assignment operator and no user-defined destructor.
+        //
+        // Since the POD bit is meant to be C++03 POD-ness, and in C++03,
+        // aggregates could not have any constructors, clear it even for an
+        // explicitly defaulted or deleted constructor.
+        // type is technically an aggregate in C++0x since it wouldn't be in 03.
+        //
+        // Also, a user-declared move assignment operator makes a class non-POD.
+        // This is an extension in C++03.
+        data().PlainOldData = false;
+      }
+
+      // C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25,
+      // C++11 [class.dtor]p5:
+      //   A [special member] is trivial if it is not user-provided [...]
+      // FIXME: This is bogus. A class can have both (say) a trivial copy
+      // constructor *and* a user-provided copy constructor.
+      if (Method->isUserProvided())
+        data().HasTrivialSpecialMembers &= ~SMKind;
+    }
+
     return;
   }
-  
+
   // Handle non-static data members.
   if (FieldDecl *Field = dyn_cast<FieldDecl>(D)) {
     // C++ [class.bit]p2:
@@ -796,7 +727,7 @@
       data().PlainOldData = false;
     
     if (T->isReferenceType()) {
-      data().HasTrivialDefaultConstructor = false;
+      data().HasTrivialSpecialMembers &= ~SMF_DefaultConstructor;
 
       // C++0x [class]p7:
       //   A standard-layout class is a class that:
@@ -814,7 +745,7 @@
       // C++11 [class]p5:
       //   A default constructor is trivial if [...] no non-static data member
       //   of its class has a brace-or-equal-initializer.
-      data().HasTrivialDefaultConstructor = false;
+      data().HasTrivialSpecialMembers &= ~SMF_DefaultConstructor;
 
       // C++11 [dcl.init.aggr]p1:
       //   An aggregate is a [...] class with [...] no
@@ -835,7 +766,7 @@
         //       class type (or array thereof), each such class has a trivial
         //       default constructor.
         if (!FieldRec->hasTrivialDefaultConstructor())
-          data().HasTrivialDefaultConstructor = false;
+          data().HasTrivialSpecialMembers &= ~SMF_DefaultConstructor;
 
         // C++0x [class.copy]p13:
         //   A copy/move constructor for class X is trivial if [...]
@@ -845,9 +776,9 @@
         //       member is trivial;
         // FIXME: C++0x: We don't correctly model 'selected' constructors.
         if (!FieldRec->hasTrivialCopyConstructor())
-          data().HasTrivialCopyConstructor = false;
+          data().HasTrivialSpecialMembers &= ~SMF_CopyConstructor;
         if (!FieldRec->hasTrivialMoveConstructor())
-          data().HasTrivialMoveConstructor = false;
+          data().HasTrivialSpecialMembers &= ~SMF_MoveConstructor;
 
         // C++0x [class.copy]p27:
         //   A copy/move assignment operator for class X is trivial if [...]
@@ -857,12 +788,12 @@
         //       copy/move that member is trivial;
         // FIXME: C++0x: We don't correctly model 'selected' operators.
         if (!FieldRec->hasTrivialCopyAssignment())
-          data().HasTrivialCopyAssignment = false;
+          data().HasTrivialSpecialMembers &= ~SMF_CopyAssignment;
         if (!FieldRec->hasTrivialMoveAssignment())
-          data().HasTrivialMoveAssignment = false;
+          data().HasTrivialSpecialMembers &= ~SMF_MoveAssignment;
 
         if (!FieldRec->hasTrivialDestructor())
-          data().HasTrivialDestructor = false;
+          data().HasTrivialSpecialMembers &= ~SMF_Destructor;
         if (!FieldRec->hasIrrelevantDestructor())
           data().HasIrrelevantDestructor = false;
         if (FieldRec->hasObjectMember())
@@ -1254,12 +1185,7 @@
     //   non-trivial.
     struct DefinitionData &Data = data();
     Data.PlainOldData = false;
-    Data.HasTrivialDefaultConstructor = false;
-    Data.HasTrivialCopyConstructor = false;
-    Data.HasTrivialMoveConstructor = false;
-    Data.HasTrivialCopyAssignment = false;
-    Data.HasTrivialMoveAssignment = false;
-    Data.HasTrivialDestructor = false;
+    Data.HasTrivialSpecialMembers = 0;
     Data.HasIrrelevantDestructor = false;
   }
   

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=168977&r1=168976&r2=168977&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Thu Nov 29 23:11:39 2012
@@ -1083,11 +1083,7 @@
                                    const RecordData &Record, unsigned &Idx) {
   // Note: the caller has deserialized the IsLambda bit already.
   Data.UserDeclaredConstructor = Record[Idx++];
-  Data.UserDeclaredCopyConstructor = Record[Idx++];
-  Data.UserDeclaredMoveConstructor = Record[Idx++];
-  Data.UserDeclaredCopyAssignment = Record[Idx++];
-  Data.UserDeclaredMoveAssignment = Record[Idx++];
-  Data.UserDeclaredDestructor = Record[Idx++];
+  Data.UserDeclaredSpecialMembers = Record[Idx++];
   Data.Aggregate = Record[Idx++];
   Data.PlainOldData = Record[Idx++];
   Data.Empty = Record[Idx++];
@@ -1101,25 +1097,15 @@
   Data.HasMutableFields = Record[Idx++];
   Data.HasOnlyCMembers = Record[Idx++];
   Data.HasInClassInitializer = Record[Idx++];
-  Data.HasTrivialDefaultConstructor = Record[Idx++];
+  Data.HasTrivialSpecialMembers = Record[Idx++];
+  Data.HasIrrelevantDestructor = Record[Idx++];
   Data.HasConstexprNonCopyMoveConstructor = Record[Idx++];
   Data.DefaultedDefaultConstructorIsConstexpr = Record[Idx++];
   Data.HasConstexprDefaultConstructor = Record[Idx++];
-  Data.HasTrivialCopyConstructor = Record[Idx++];
-  Data.HasTrivialMoveConstructor = Record[Idx++];
-  Data.HasTrivialCopyAssignment = Record[Idx++];
-  Data.HasTrivialMoveAssignment = Record[Idx++];
-  Data.HasTrivialDestructor = Record[Idx++];
-  Data.HasIrrelevantDestructor = Record[Idx++];
   Data.HasNonLiteralTypeFieldsOrBases = Record[Idx++];
   Data.ComputedVisibleConversions = Record[Idx++];
   Data.UserProvidedDefaultConstructor = Record[Idx++];
-  Data.DeclaredDefaultConstructor = Record[Idx++];
-  Data.DeclaredCopyConstructor = Record[Idx++];
-  Data.DeclaredMoveConstructor = Record[Idx++];
-  Data.DeclaredCopyAssignment = Record[Idx++];
-  Data.DeclaredMoveAssignment = Record[Idx++];
-  Data.DeclaredDestructor = Record[Idx++];
+  Data.DeclaredSpecialMembers = Record[Idx++];
   Data.ImplicitCopyConstructorHasConstParam = Record[Idx++];
   Data.ImplicitCopyAssignmentHasConstParam = Record[Idx++];
   Data.HasDeclaredCopyConstructorWithConstParam = Record[Idx++];

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=168977&r1=168976&r2=168977&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Thu Nov 29 23:11:39 2012
@@ -4574,11 +4574,7 @@
   struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData;
   Record.push_back(Data.IsLambda);
   Record.push_back(Data.UserDeclaredConstructor);
-  Record.push_back(Data.UserDeclaredCopyConstructor);
-  Record.push_back(Data.UserDeclaredMoveConstructor);
-  Record.push_back(Data.UserDeclaredCopyAssignment);
-  Record.push_back(Data.UserDeclaredMoveAssignment);
-  Record.push_back(Data.UserDeclaredDestructor);
+  Record.push_back(Data.UserDeclaredSpecialMembers);
   Record.push_back(Data.Aggregate);
   Record.push_back(Data.PlainOldData);
   Record.push_back(Data.Empty);
@@ -4592,25 +4588,15 @@
   Record.push_back(Data.HasMutableFields);
   Record.push_back(Data.HasOnlyCMembers);
   Record.push_back(Data.HasInClassInitializer);
-  Record.push_back(Data.HasTrivialDefaultConstructor);
+  Record.push_back(Data.HasTrivialSpecialMembers);
+  Record.push_back(Data.HasIrrelevantDestructor);
   Record.push_back(Data.HasConstexprNonCopyMoveConstructor);
   Record.push_back(Data.DefaultedDefaultConstructorIsConstexpr);
   Record.push_back(Data.HasConstexprDefaultConstructor);
-  Record.push_back(Data.HasTrivialCopyConstructor);
-  Record.push_back(Data.HasTrivialMoveConstructor);
-  Record.push_back(Data.HasTrivialCopyAssignment);
-  Record.push_back(Data.HasTrivialMoveAssignment);
-  Record.push_back(Data.HasTrivialDestructor);
-  Record.push_back(Data.HasIrrelevantDestructor);
   Record.push_back(Data.HasNonLiteralTypeFieldsOrBases);
   Record.push_back(Data.ComputedVisibleConversions);
   Record.push_back(Data.UserProvidedDefaultConstructor);
-  Record.push_back(Data.DeclaredDefaultConstructor);
-  Record.push_back(Data.DeclaredCopyConstructor);
-  Record.push_back(Data.DeclaredMoveConstructor);
-  Record.push_back(Data.DeclaredCopyAssignment);
-  Record.push_back(Data.DeclaredMoveAssignment);
-  Record.push_back(Data.DeclaredDestructor);
+  Record.push_back(Data.DeclaredSpecialMembers);
   Record.push_back(Data.ImplicitCopyConstructorHasConstParam);
   Record.push_back(Data.ImplicitCopyAssignmentHasConstParam);
   Record.push_back(Data.HasDeclaredCopyConstructorWithConstParam);





More information about the cfe-commits mailing list