[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