t/clang/type-traits
Patch authored by John Wiegley.
These type traits are used for parsing code that employs certain features of
the Embarcadero C++ compiler. Several of these constructs are also desired by
libc++, according to its project pages (such as __is_standard_layout).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130342 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index f8ad763..7086176 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -2379,6 +2379,7 @@
return false;
case UTT_IsAbstract:
if (const RecordType *RT = T->getAs<RecordType>())
+ if (!Self.RequireCompleteType(KeyLoc, T, diag::err_incomplete_typeid))
return cast<CXXRecordDecl>(RT->getDecl())->isAbstract();
return false;
case UTT_IsEmpty:
@@ -2387,6 +2388,74 @@
&& cast<CXXRecordDecl>(Record->getDecl())->isEmpty();
}
return false;
+ case UTT_IsIntegral:
+ return T->isIntegralType(C);
+ case UTT_IsFloatingPoint:
+ return T->isFloatingType();
+ case UTT_IsArithmetic:
+ return T->isArithmeticType() && ! T->isEnumeralType();
+ case UTT_IsArray:
+ return T->isArrayType();
+ case UTT_IsCompleteType:
+ return ! T->isIncompleteType();
+ case UTT_IsCompound:
+ return ! (T->isVoidType() || T->isArithmeticType()) || T->isEnumeralType();
+ case UTT_IsConst:
+ return T.isConstQualified();
+ case UTT_IsFunction:
+ return T->isFunctionType();
+ case UTT_IsFundamental:
+ return T->isVoidType() || (T->isArithmeticType() && ! T->isEnumeralType());
+ case UTT_IsLvalueReference:
+ return T->isLValueReferenceType();
+ case UTT_IsMemberFunctionPointer:
+ return T->isMemberFunctionPointerType();
+ case UTT_IsMemberObjectPointer:
+ return T->isMemberDataPointerType();
+ case UTT_IsMemberPointer:
+ return T->isMemberPointerType();
+ case UTT_IsObject:
+ // Defined in Section 3.9 p8 of the Working Draft, essentially:
+ // !__is_reference(T) && !__is_function(T) && !__is_void(T).
+ return ! (T->isReferenceType() || T->isFunctionType() || T->isVoidType());
+ case UTT_IsPointer:
+ return T->isPointerType();
+ case UTT_IsReference:
+ return T->isReferenceType();
+ case UTT_IsRvalueReference:
+ return T->isRValueReferenceType();
+ case UTT_IsScalar:
+ // Scalar type is defined in Section 3.9 p10 of the Working Draft.
+ // Essentially:
+ // __is_arithmetic( T ) || __is_enumeration(T) ||
+ // __is_pointer(T) || __is_member_pointer(T)
+ return (T->isArithmeticType() || T->isEnumeralType() ||
+ T->isPointerType() || T->isMemberPointerType());
+ case UTT_IsSigned:
+ return T->isSignedIntegerType();
+ case UTT_IsStandardLayout:
+ // Error if T is an incomplete type.
+ if (Self.RequireCompleteType(KeyLoc, T, diag::err_incomplete_typeid))
+ return false;
+
+ // A standard layout type is:
+ // - a scalar type
+ // - an array of standard layout types
+ // - a standard layout class type:
+ if (EvaluateUnaryTypeTrait(Self, UTT_IsScalar, T, KeyLoc))
+ return true;
+ if (EvaluateUnaryTypeTrait(Self, UTT_IsScalar, C.getBaseElementType(T),
+ KeyLoc))
+ return true;
+ if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>())
+ return RT->hasStandardLayout(C);
+ return false;
+ case UTT_IsUnsigned:
+ return T->isUnsignedIntegerType();
+ case UTT_IsVoid:
+ return T->isVoidType();
+ case UTT_IsVolatile:
+ return T.isVolatileQualified();
case UTT_HasTrivialConstructor:
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
// If __is_pod (type) is true then the trait is true, else if type is
@@ -2579,11 +2648,12 @@
// According to http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
// all traits except __is_class, __is_enum and __is_union require a the type
// to be complete, an array of unknown bound, or void.
- if (UTT != UTT_IsClass && UTT != UTT_IsEnum && UTT != UTT_IsUnion) {
+ if (UTT != UTT_IsClass && UTT != UTT_IsEnum && UTT != UTT_IsUnion &&
+ UTT != UTT_IsCompleteType) {
QualType E = T;
if (T->isIncompleteArrayType())
E = Context.getAsArrayType(T)->getElementType();
- if (!T->isVoidType() &&
+ if (!T->isVoidType() && ! LangOpts.Borland &&
RequireCompleteType(KWLoc, E,
diag::err_incomplete_type_used_in_type_trait_expr))
return ExprError();
@@ -2651,11 +2721,12 @@
return cast<CXXRecordDecl>(rhsRecord->getDecl())
->isDerivedFrom(cast<CXXRecordDecl>(lhsRecord->getDecl()));
}
-
+ case BTT_IsSame:
+ return Self.Context.hasSameType(LhsT, RhsT);
case BTT_TypeCompatible:
return Self.Context.typesAreCompatible(LhsT.getUnqualifiedType(),
RhsT.getUnqualifiedType());
-
+ case BTT_IsConvertible:
case BTT_IsConvertibleTo: {
// C++0x [meta.rel]p4:
// Given the following function prototype:
@@ -2730,6 +2801,8 @@
QualType ResultType;
switch (BTT) {
case BTT_IsBaseOf: ResultType = Context.BoolTy; break;
+ case BTT_IsConvertible: ResultType = Context.BoolTy; break;
+ case BTT_IsSame: ResultType = Context.BoolTy; break;
case BTT_TypeCompatible: ResultType = Context.IntTy; break;
case BTT_IsConvertibleTo: ResultType = Context.BoolTy; break;
}