[cfe-commits] r130079 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp lib/AST/Type.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriter.cpp test/SemaCXX/literal-type.cpp

Chandler Carruth chandlerc at gmail.com
Sat Apr 23 19:49:34 PDT 2011


Author: chandlerc
Date: Sat Apr 23 21:49:34 2011
New Revision: 130079

URL: http://llvm.org/viewvc/llvm-project?rev=130079&view=rev
Log:
Implement most of the remaining logic in __is_literal type trait. This
should now support all of the C++98 types, and all of the C++0x types
Clang supports.

Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/SemaCXX/literal-type.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=130079&r1=130078&r2=130079&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Sat Apr 23 21:49:34 2011
@@ -1479,6 +1479,10 @@
   bool isPure() const { return IsPure; }
   void setPure(bool P = true);
 
+  /// Whether this is a constexpr function or constexpr constructor.
+  // FIXME: C++0x: Implement tracking of the constexpr specifier.
+  bool isConstExpr() const { return false; }
+
   /// Whether this templated function will be late parsed.
   bool isLateTemplateParsed() const { return IsLateTemplateParsed; }
   void setLateTemplateParsed(bool ILT = true) { IsLateTemplateParsed = ILT; }

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=130079&r1=130078&r2=130079&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Sat Apr 23 21:49:34 2011
@@ -316,6 +316,11 @@
     ///   (or array thereof), each such class has a trivial constructor.
     bool HasTrivialConstructor : 1;
 
+    /// HasConstExprNonCopyMoveConstructor - True when this class has at least
+    /// one constexpr constructor which is neither the copy nor move
+    /// constructor.
+    bool HasConstExprNonCopyMoveConstructor : 1;
+
     /// HasTrivialCopyConstructor - True when this class has a trivial copy
     /// constructor.
     ///
@@ -386,6 +391,10 @@
     ///   type (or array thereof), each such class has a trivial destructor.
     bool HasTrivialDestructor : 1;
 
+    /// HasNonLiteralTypeFieldsOrBases - True when this class contains at least
+    /// one non-static data member or base class of non literal type.
+    bool HasNonLiteralTypeFieldsOrBases : 1;
+
     /// ComputedVisibleConversions - True when visible conversion functions are
     /// already computed and are available.
     bool ComputedVisibleConversions : 1;
@@ -760,6 +769,12 @@
   // (C++ [class.ctor]p5)
   bool hasTrivialConstructor() const { return data().HasTrivialConstructor; }
 
+  // hasConstExprNonCopyMoveConstructor - Whether this class has at least one
+  // constexpr constructor other than the copy or move constructors
+  bool hasConstExprNonCopyMoveConstructor() const {
+    return data().HasConstExprNonCopyMoveConstructor;
+  }
+
   // hasTrivialCopyConstructor - Whether this class has a trivial copy
   // constructor (C++ [class.copy]p6, C++0x [class.copy]p13)
   bool hasTrivialCopyConstructor() const {
@@ -788,6 +803,12 @@
   // (C++ [class.dtor]p3)
   bool hasTrivialDestructor() const { return data().HasTrivialDestructor; }
 
+  // hasNonLiteralTypeFieldsOrBases - Whether this class has a non-literal type
+  // non-static data member or base class.
+  bool hasNonLiteralTypeFieldsOrBases() const {
+    return data().HasNonLiteralTypeFieldsOrBases;
+  }
+
   // isTriviallyCopyable - Whether this class is considered trivially copyable
   // (C++0x [class]p5).
   bool isTriviallyCopyable() const;

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=130079&r1=130078&r2=130079&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Sat Apr 23 21:49:34 2011
@@ -32,9 +32,11 @@
     UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false),
     Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
     Abstract(false), HasTrivialConstructor(true),
+    HasConstExprNonCopyMoveConstructor(false),
     HasTrivialCopyConstructor(true), HasTrivialMoveConstructor(true),
     HasTrivialCopyAssignment(true), HasTrivialMoveAssignment(true),
-    HasTrivialDestructor(true), ComputedVisibleConversions(false),
+    HasTrivialDestructor(true), HasNonLiteralTypeFieldsOrBases(false),
+    ComputedVisibleConversions(false),
     DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false), 
     DeclaredCopyAssignment(false), DeclaredDestructor(false),
     NumBases(0), NumVBases(0), Bases(), VBases(),
@@ -117,6 +119,10 @@
     //   polymorphic class.
     if (BaseClassDecl->isPolymorphic())
       data().Polymorphic = true;
+
+    // Record if this base is the first non-literal field or base.
+    if (!hasNonLiteralTypeFieldsOrBases() && !BaseType->isLiteralType())
+      data().HasNonLiteralTypeFieldsOrBases = true;
     
     // Now go through all virtual bases of this base and add them.
     for (CXXRecordDecl::base_class_iterator VBase =
@@ -486,6 +492,12 @@
         data().HasTrivialMoveConstructor = false;
       }
     }
+    if (Constructor->isConstExpr() &&
+        !Constructor->isCopyOrMoveConstructor()) {
+      // Record if we see any constexpr constructors which are niether copy
+      // nor move constructors.
+      data().HasConstExprNonCopyMoveConstructor = true;
+    }
 
     return;
   }
@@ -620,7 +632,11 @@
       data().PlainOldData = false;
     if (T->isReferenceType())
       data().HasTrivialConstructor = false;
-    
+
+    // Record if this field is the first non-literal field or base.
+    if (!hasNonLiteralTypeFieldsOrBases() && !T->isLiteralType())
+      data().HasNonLiteralTypeFieldsOrBases = true;
+
     if (const RecordType *RecordTy = T->getAs<RecordType>()) {
       CXXRecordDecl* FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl());
       if (FieldRec->getDefinition()) {

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=130079&r1=130078&r2=130079&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Sat Apr 23 21:49:34 2011
@@ -874,32 +874,43 @@
 
   // C++0x [basic.types]p10:
   //   A type is a literal type if it is:
-  switch (CanonicalType->getTypeClass()) {
-    // We're whitelisting
-  default: return false;
-
-    //   -- a scalar type
-  case Builtin:
-  case Complex:
-  case Pointer:
-  case MemberPointer:
-  case Vector:
-  case ExtVector:
-  case ObjCObjectPointer:
-  case Enum:
-    return true;
-
-    //   -- a class type with ...
-  case Record:
-    // FIXME: Do the tests
+  //   [...]
+  //   -- an array of literal type
+  // Extension: variable arrays cannot be literal types, since they're
+  // runtime-sized.
+  if (isArrayType() && !isConstantArrayType())
     return false;
+  const Type *BaseTy = getBaseElementTypeUnsafe();
+  assert(BaseTy && "NULL element type");
 
-    //   -- an array of literal type
-    // Extension: variable arrays cannot be literal types, since they're
-    // runtime-sized.
-  case ConstantArray:
-    return cast<ArrayType>(CanonicalType)->getElementType()->isLiteralType();
+  // C++0x [basic.types]p10:
+  //   A type is a literal type if it is:
+  //    -- a scalar type; or
+  if (BaseTy->isScalarType()) return true;
+  //    -- a reference type; or
+  if (BaseTy->isReferenceType()) return true;
+  //    -- a class type that has all of the following properties:
+  if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
+    const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+    //      -- a trivial destructor,
+    if (!ClassDecl->hasTrivialDestructor()) return false;
+    //      -- every constructor call and full-expression in the
+    //         brace-or-equal-initializers for non-static data members (if any)
+    //         is a constant expression,
+    // FIXME: C++0x: Clang doesn't yet support non-static data member
+    // declarations with initializers, or constexprs.
+    //      -- it is an aggregate type or has at least one constexpr
+    //         constructor or constructor template that is not a copy or move
+    //         constructor, and
+    if (!ClassDecl->isAggregate() &&
+        !ClassDecl->hasConstExprNonCopyMoveConstructor())
+      return false;
+    //      -- all non-static data members and base classes of literal types
+    if (ClassDecl->hasNonLiteralTypeFieldsOrBases()) return false;
+
+    return true;
   }
+  return false;
 }
 
 bool Type::isTrivialType() const {

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=130079&r1=130078&r2=130079&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Sat Apr 23 21:49:34 2011
@@ -842,11 +842,13 @@
   Data.Polymorphic = Record[Idx++];
   Data.Abstract = Record[Idx++];
   Data.HasTrivialConstructor = Record[Idx++];
+  Data.HasConstExprNonCopyMoveConstructor = Record[Idx++];
   Data.HasTrivialCopyConstructor = Record[Idx++];
   Data.HasTrivialMoveConstructor = Record[Idx++];
   Data.HasTrivialCopyAssignment = Record[Idx++];
   Data.HasTrivialMoveAssignment = Record[Idx++];
   Data.HasTrivialDestructor = Record[Idx++];
+  Data.HasNonLiteralTypeFieldsOrBases = Record[Idx++];
   Data.ComputedVisibleConversions = Record[Idx++];
   Data.DeclaredDefaultConstructor = Record[Idx++];
   Data.DeclaredCopyConstructor = Record[Idx++];

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=130079&r1=130078&r2=130079&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Sat Apr 23 21:49:34 2011
@@ -3794,11 +3794,13 @@
   Record.push_back(Data.Polymorphic);
   Record.push_back(Data.Abstract);
   Record.push_back(Data.HasTrivialConstructor);
+  Record.push_back(Data.HasConstExprNonCopyMoveConstructor);
   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.HasNonLiteralTypeFieldsOrBases);
   Record.push_back(Data.ComputedVisibleConversions);
   Record.push_back(Data.DeclaredDefaultConstructor);
   Record.push_back(Data.DeclaredCopyConstructor);

Modified: cfe/trunk/test/SemaCXX/literal-type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/literal-type.cpp?rev=130079&r1=130078&r2=130079&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/literal-type.cpp (original)
+++ cfe/trunk/test/SemaCXX/literal-type.cpp Sat Apr 23 21:49:34 2011
@@ -8,4 +8,60 @@
 static_assert(__is_literal(decltype(E1)), "fail");
 typedef int IAR[10];
 static_assert(__is_literal(IAR), "fail");
-// FIXME: Records
+
+// C++0x [basic.types]p10:
+//   A type is a literal type if it is:
+//    [...]
+//    -- a class type that has all of the following properties:
+//        -- it has a trivial destructor
+//        -- every constructor call and full-expression in the
+//           brace-or-equal-initializers for non-static data members (if an) is
+//           a constant expression,
+//        -- it is an aggregate type or has at least one constexpr constructor
+//           or constructor template that is not a copy or move constructor, and
+//        -- it has all non-static data members and base classes of literal
+//           types
+struct Empty {};
+struct LiteralType {
+  int x;
+  E e;
+  IAR arr;
+  Empty empty;
+  int method();
+};
+struct HasDtor { ~HasDtor(); };
+
+class NonAggregate { int x; };
+struct HasNonLiteralBase : NonAggregate {};
+struct HasNonLiteralMember { HasDtor x; };
+
+static_assert(__is_literal(Empty), "fail");
+static_assert(__is_literal(LiteralType), "fail");
+static_assert(!__is_literal(HasDtor), "fail");
+static_assert(!__is_literal(NonAggregate), "fail");
+static_assert(!__is_literal(HasNonLiteralBase), "fail");
+static_assert(!__is_literal(HasNonLiteralMember), "fail");
+
+// FIXME: Test constexpr constructors and non-static members with initializers
+// when Clang supports them:
+#if 0
+extern int f();
+struct HasNonConstExprMemInit {
+  int x = f();
+  constexpr HasNonConstExprMemInit(int y) {}
+};
+static_assert(!__is_literal(HasNonConstExprMemInit), "fail");
+
+class HasConstExprCtor {
+  int x;
+public:
+  constexpr HasConstExprCtor(int x) : x(x) {}
+};
+template <typename T> class HasConstExprCtorTemplate {
+  T x;
+public:
+  template <typename U> constexpr HasConstExprCtorTemplate(U y) : x(y) {}
+};
+static_assert(__is_literal(HasConstExprCtor), "fail");
+static_assert(__is_literal(HasConstExprCtorTemplate), "fail");
+#endif





More information about the cfe-commits mailing list