From: John Wiegley Date: Wed, 27 Apr 2011 23:09:49 +0000 (+0000) Subject: t/clang/type-traits X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=20c0da7787c9a7d2529e42a4a91d777778595d74;p=clang 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/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index f41a7d617e..bc1e018b4f 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -306,6 +306,21 @@ class CXXRecordDecl : public RecordDecl { /// one pure virtual function, (that can come from a base class). bool Abstract : 1; + /// HasStandardLayout - True when this class has standard layout. + /// + /// C++0x [class]p7. A standard-layout class is a class that: + /// * has no non-static data members of type non-standard-layout class (or + /// array of such types) or reference, + /// * has no virtual functions (10.3) and no virtual base classes (10.1), + /// * has the same access control (Clause 11) for all non-static data members + /// * has no non-standard-layout base classes, + /// * either has no non-static data members in the most derived class and at + /// most one base class with non-static data members, or has no base + /// classes with non-static data members, and + /// * has no base classes of the same type as the first non-static data + /// member. + bool HasStandardLayout : 1; + /// HasTrivialConstructor - True when this class has a trivial constructor. /// /// C++ [class.ctor]p5. A constructor is trivial if it is an @@ -765,6 +780,10 @@ public: /// which means that the class contains or inherits a pure virtual function. bool isAbstract() const { return data().Abstract; } + // hasStandardLayout - Whether this class has standard layout + // (C++ [class]p7) + bool hasStandardLayout() const { return data().HasStandardLayout; } + // hasTrivialConstructor - Whether this class has a trivial constructor // (C++ [class.ctor]p5) bool hasTrivialConstructor() const { return data().HasTrivialConstructor; } diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index cfdfae1ee3..9fa301e4aa 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1171,7 +1171,7 @@ public: /// (C++0x [basic.types]p10) bool isLiteralType() const; - /// isTrivialType - Return true if this is a literal type + /// isTrivialType - Return true if this is a trivial type /// (C++0x [basic.types]p9) bool isTrivialType() const; @@ -2832,6 +2832,9 @@ public: // const, it needs to return false. bool hasConstFields() const { return false; } + /// \brief Whether this class has standard layout + bool hasStandardLayout(ASTContext& Ctx) const; + bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index eefa9c02a6..e66922eaa2 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -350,6 +350,35 @@ KEYWORD(__is_union , KEYCXX) KEYWORD(__is_lvalue_expr , KEYCXX) KEYWORD(__is_rvalue_expr , KEYCXX) +// Embarcadero Unary Type Traits +KEYWORD(__is_arithmetic , KEYCXX) +KEYWORD(__is_floating_point , KEYCXX) +KEYWORD(__is_integral , KEYCXX) +KEYWORD(__is_complete_type , KEYCXX) +KEYWORD(__is_void , KEYCXX) +KEYWORD(__is_array , KEYCXX) +KEYWORD(__is_function , KEYCXX) +KEYWORD(__is_reference , KEYCXX) +KEYWORD(__is_lvalue_reference , KEYCXX) +KEYWORD(__is_rvalue_reference , KEYCXX) +KEYWORD(__is_fundamental , KEYCXX) +KEYWORD(__is_object , KEYCXX) +KEYWORD(__is_scalar , KEYCXX) +KEYWORD(__is_compound , KEYCXX) +KEYWORD(__is_pointer , KEYCXX) +KEYWORD(__is_member_object_pointer , KEYCXX) +KEYWORD(__is_member_function_pointer, KEYCXX) +KEYWORD(__is_member_pointer , KEYCXX) +KEYWORD(__is_const , KEYCXX) +KEYWORD(__is_volatile , KEYCXX) +KEYWORD(__is_standard_layout , KEYCXX) +KEYWORD(__is_signed , KEYCXX) +KEYWORD(__is_unsigned , KEYCXX) + +// Embarcadero Binary Type Traits +KEYWORD(__is_same , KEYCXX) +KEYWORD(__is_convertible , KEYCXX) + // Apple Extension. KEYWORD(__private_extern__ , KEYALL) diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h index 5883efe3bb..6ba1bbdeee 100644 --- a/include/clang/Basic/TypeTraits.h +++ b/include/clang/Basic/TypeTraits.h @@ -27,21 +27,48 @@ namespace clang { UTT_HasTrivialDestructor, UTT_HasVirtualDestructor, UTT_IsAbstract, + UTT_IsArithmetic, + UTT_IsArray, UTT_IsClass, + UTT_IsCompleteType, + UTT_IsCompound, + UTT_IsConst, UTT_IsEmpty, UTT_IsEnum, + UTT_IsFloatingPoint, + UTT_IsFunction, + UTT_IsFundamental, + UTT_IsIntegral, UTT_IsLiteral, + UTT_IsLvalueExpr, + UTT_IsLvalueReference, + UTT_IsMemberFunctionPointer, + UTT_IsMemberObjectPointer, + UTT_IsMemberPointer, + UTT_IsObject, UTT_IsPOD, + UTT_IsPointer, UTT_IsPolymorphic, + UTT_IsReference, + UTT_IsRvalueExpr, + UTT_IsRvalueReference, + UTT_IsScalar, + UTT_IsSigned, + UTT_IsStandardLayout, UTT_IsTrivial, - UTT_IsUnion + UTT_IsUnion, + UTT_IsUnsigned, + UTT_IsVoid, + UTT_IsVolatile }; /// BinaryTypeTrait - Names for the binary type traits. enum BinaryTypeTrait { BTT_IsBaseOf, - BTT_TypeCompatible, - BTT_IsConvertibleTo + BTT_IsConvertible, + BTT_IsConvertibleTo, + BTT_IsSame, + BTT_TypeCompatible }; /// UnaryExprOrTypeTrait - Names for the "expression or type" traits. diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index a71750bb4c..7ab60303ad 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -926,6 +926,10 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const { void CXXRecordDecl::completeDefinition() { completeDefinition(0); + + ASTContext &Context = getASTContext(); + if (const RecordType *RT = getTypeForDecl()->getAs()) + data().HasStandardLayout = RT->hasStandardLayout(Context); } void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index cf42e63379..b96591b661 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1251,23 +1251,48 @@ void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) { static const char *getTypeTraitName(UnaryTypeTrait UTT) { switch (UTT) { - default: llvm_unreachable("Unknown unary type trait"); + default: assert(false && "Unknown type trait"); case UTT_HasNothrowAssign: return "__has_nothrow_assign"; - case UTT_HasNothrowCopy: return "__has_nothrow_copy"; case UTT_HasNothrowConstructor: return "__has_nothrow_constructor"; + case UTT_HasNothrowCopy: return "__has_nothrow_copy"; case UTT_HasTrivialAssign: return "__has_trivial_assign"; - case UTT_HasTrivialCopy: return "__has_trivial_copy"; case UTT_HasTrivialConstructor: return "__has_trivial_constructor"; + case UTT_HasTrivialCopy: return "__has_trivial_copy"; case UTT_HasTrivialDestructor: return "__has_trivial_destructor"; case UTT_HasVirtualDestructor: return "__has_virtual_destructor"; case UTT_IsAbstract: return "__is_abstract"; + case UTT_IsArithmetic: return "__is_arithmetic"; + case UTT_IsArray: return "__is_array"; case UTT_IsClass: return "__is_class"; + case UTT_IsCompleteType: return "__is_complete_type"; + case UTT_IsCompound: return "__is_compound"; + case UTT_IsConst: return "__is_const"; case UTT_IsEmpty: return "__is_empty"; case UTT_IsEnum: return "__is_enum"; + case UTT_IsFloatingPoint: return "__is_floating_point"; + case UTT_IsFunction: return "__is_function"; + case UTT_IsFundamental: return "__is_fundamental"; + case UTT_IsIntegral: return "__is_integral"; + case UTT_IsLvalueExpr: return "__is_lvalue_expr"; + case UTT_IsLvalueReference: return "__is_lvalue_reference"; + case UTT_IsMemberFunctionPointer: return "__is_member_function_pointer"; + case UTT_IsMemberObjectPointer: return "__is_member_object_pointer"; + case UTT_IsMemberPointer: return "__is_member_pointer"; + case UTT_IsObject: return "__is_object"; case UTT_IsPOD: return "__is_pod"; + case UTT_IsPointer: return "__is_pointer"; case UTT_IsPolymorphic: return "__is_polymorphic"; - case UTT_IsTrivial: return "__is_trivial"; + case UTT_IsReference: return "__is_reference"; + case UTT_IsRvalueExpr: return "__is_rvalue_expr"; + case UTT_IsRvalueReference: return "__is_rvalue_reference"; + case UTT_IsScalar: return "__is_scalar"; + case UTT_IsSigned: return "__is_signed"; + case UTT_IsStandardLayout: return "__is_standard_layout"; + case UTT_IsTrivial: return "__is_trivial"; case UTT_IsUnion: return "__is_union"; + case UTT_IsUnsigned: return "__is_unsigned"; + case UTT_IsVoid: return "__is_void"; + case UTT_IsVolatile: return "__is_volatile"; } return ""; } @@ -1275,6 +1300,8 @@ static const char *getTypeTraitName(UnaryTypeTrait UTT) { static const char *getTypeTraitName(BinaryTypeTrait BTT) { switch (BTT) { case BTT_IsBaseOf: return "__is_base_of"; + case BTT_IsConvertible: return "__is_convertible"; + case BTT_IsSame: return "__is_same"; case BTT_TypeCompatible: return "__builtin_types_compatible_p"; case BTT_IsConvertibleTo: return "__is_convertible_to"; } diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index d43a121881..e75ce7dfe4 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1385,6 +1385,109 @@ bool RecordType::classof(const TagType *TT) { return isa(TT->getDecl()); } +static uint64_t countBasesWithFields(QualType BaseType) { + uint64_t BasesWithFields = 0; + if (const RecordType *T = BaseType->getAs()) { + CXXRecordDecl *RD = cast(T->getDecl()); + for (CXXRecordDecl::field_iterator Field = RD->field_begin(), + E = RD->field_end(); Field != E; ++Field) + BasesWithFields = 1; + for (CXXRecordDecl::base_class_const_iterator B = RD->bases_begin(), + BE = RD->bases_end(); B != BE; ++B) + BasesWithFields += countBasesWithFields(B->getType()); + } + return BasesWithFields; +} + +bool RecordType::hasStandardLayout(ASTContext& Context) const { + CXXRecordDecl *RD = cast(getDecl()); + if (! RD) { + assert(cast(getDecl()) && + "RecordType does not have a corresponding RecordDecl"); + return true; + } + + // A standard-layout class is a class that: + + for (CXXRecordDecl::method_iterator M = RD->method_begin(), + ME = RD->method_end(); M != ME; ++M) { + CXXMethodDecl *Method = *M; + + // C++0x [class]p7: + // A standard-layout class is a class that [...] + // -- has no virtual functions (10.3) [...] + if (Method->isVirtual()) + return false; + } + + AccessSpecifier AS = AS_none; + QualType FirstFieldType; + bool FirstFieldType_set = false; + uint64_t FieldCount = 0; + + for (CXXRecordDecl::field_iterator Field = RD->field_begin(), + E = RD->field_end(); Field != E; ++Field, ++FieldCount) { + // C++0x [class]p7: + // A standard-layout class is a class that [...] + // -- has no non-static data members of type non-standard-layout class + // (or array of such types) or reference [...] + QualType FieldType = Context.getBaseElementType((*Field)->getType()); + if (const RecordType *T = + Context.getBaseElementType(FieldType)->getAs()) { + if (! T->hasStandardLayout(Context) || T->isReferenceType()) + return false; + } + if (! FirstFieldType_set) { + FirstFieldType = FieldType; + FirstFieldType_set = true; + } + + // C++0x [class]p7: + // A standard-layout class is a class that [...] + // -- has the same access control (Clause 11) for all non-static data + // members [...] + if (AS == AS_none) + AS = (*Field)->getAccess(); + else if (AS != (*Field)->getAccess()) + return false; + } + + for (CXXRecordDecl::base_class_const_iterator B = RD->bases_begin(), + BE = RD->bases_end(); B != BE; ++B) { + // C++0x [class]p7: + // A standard-layout class is a class that [...] + // -- no virtual base classes (10.1) [...] + if (B->isVirtual()) + return false; + + QualType BT = B->getType(); + + // C++0x [class]p7: + // A standard-layout class is a class that [...] + // -- has no non-standard-layout base classes [...] + if (const RecordType *T = BT->getAs()) + if (! T->hasStandardLayout(Context)) + return false; + + // C++0x [class]p7: + // A standard-layout class is a class that [...] + // -- has no base classes of the same type as the first non-static data + // member. + if (BT == FirstFieldType) + return false; + + // C++0x [class]p7: + // A standard-layout class is a class that [...] + // -- either has no non-static data members in the most derived class + // and at most one base class with non-static data members, or has + // no base classes with non-static data members [...] + if (countBasesWithFields(BT) > (FieldCount == 0 ? 1 : 0)) + return false; + } + + return true; +} + bool EnumType::classof(const TagType *TT) { return isa(TT->getDecl()); } diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index f59302868b..c41798e35e 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -731,22 +731,19 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // styles of attributes? MaybeParseCXX0XAttributes(attrs); - if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_pod)) { - // GNU libstdc++ 4.2 uses __is_pod as the name of a struct template, but - // __is_pod is a keyword in GCC >= 4.3. Therefore, when we see the - // token sequence "struct __is_pod", make __is_pod into a normal - // identifier rather than a keyword, to allow libstdc++ 4.2 to work - // properly. - Tok.getIdentifierInfo()->RevertTokenIDToIdentifier(); - Tok.setKind(tok::identifier); - } - - if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_empty)) { - // GNU libstdc++ 4.2 uses __is_empty as the name of a struct template, but - // __is_empty is a keyword in GCC >= 4.3. Therefore, when we see the - // token sequence "struct __is_empty", make __is_empty into a normal - // identifier rather than a keyword, to allow libstdc++ 4.2 to work - // properly. + if (TagType == DeclSpec::TST_struct && + (Tok.is(tok::kw___is_pod) || + Tok.is(tok::kw___is_empty) || + Tok.is(tok::kw___is_void) || + Tok.is(tok::kw___is_pointer) || + Tok.is(tok::kw___is_arithmetic) || + Tok.is(tok::kw___is_fundamental) || + Tok.is(tok::kw___is_scalar))) { + // GNU libstdc++ 4.2 uses certain intrinsic names as the name of + // struct templates, but these are keywords in GCC >= 4.3 and + // Clang. Therefore, when we see the token sequence "struct X", make + // X into a normal identifier rather than a keyword, to allow + // libstdc++ 4.2 to work properly. Tok.getIdentifierInfo()->RevertTokenIDToIdentifier(); Tok.setKind(tok::identifier); } diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index c990c52e7b..1c4a942780 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -519,6 +519,34 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// '::'[opt] 'delete' cast-expression /// '::'[opt] 'delete' '[' ']' cast-expression /// +/// [GNU/Embarcadero] unary-type-trait: +/// '__is_arithmetic' +/// '__is_floating_point' +/// '__is_integral' +/// '__is_lvalue_expr' +/// '__is_rvalue_expr' +/// '__is_complete_type' +/// '__is_void' +/// '__is_array' +/// '__is_function' +/// '__is_reference' +/// '__is_lvalue_reference' +/// '__is_rvalue_reference' +/// '__is_fundamental' +/// '__is_object' +/// '__is_scalar' +/// '__is_compound' +/// '__is_pointer' +/// '__is_member_object_pointer' +/// '__is_member_function_pointer' +/// '__is_member_pointer' +/// '__is_const' +/// '__is_volatile' +/// '__is_trivial' +/// '__is_standard_layout' +/// '__is_signed' +/// '__is_unsigned' +/// /// [GNU] unary-type-trait: /// '__has_nothrow_assign' /// '__has_nothrow_copy' @@ -540,6 +568,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// binary-type-trait: /// [GNU] '__is_base_of' /// [MS] '__is_convertible_to' +/// '__is_convertible' +/// '__is_same' /// /// [Embarcadero] expression-trait: /// '__is_lvalue_expr' @@ -997,6 +1027,29 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___is_empty: case tok::kw___is_enum: case tok::kw___is_literal: + case tok::kw___is_arithmetic: + case tok::kw___is_integral: + case tok::kw___is_floating_point: + case tok::kw___is_complete_type: + case tok::kw___is_void: + case tok::kw___is_array: + case tok::kw___is_function: + case tok::kw___is_reference: + case tok::kw___is_lvalue_reference: + case tok::kw___is_rvalue_reference: + case tok::kw___is_fundamental: + case tok::kw___is_object: + case tok::kw___is_scalar: + case tok::kw___is_compound: + case tok::kw___is_pointer: + case tok::kw___is_member_object_pointer: + case tok::kw___is_member_function_pointer: + case tok::kw___is_member_pointer: + case tok::kw___is_const: + case tok::kw___is_volatile: + case tok::kw___is_standard_layout: + case tok::kw___is_signed: + case tok::kw___is_unsigned: case tok::kw___is_literal_type: case tok::kw___is_pod: case tok::kw___is_polymorphic: @@ -1014,6 +1067,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___builtin_types_compatible_p: case tok::kw___is_base_of: + case tok::kw___is_same: + case tok::kw___is_convertible: case tok::kw___is_convertible_to: return ParseBinaryTypeTrait(); diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 7bf76a917f..aade050df4 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -1912,25 +1912,50 @@ Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) { static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) { switch(kind) { - default: llvm_unreachable("Not a known unary type trait"); + default: assert(false && "Not a known unary type trait."); case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign; - case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy; case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor; + case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy; case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign; - case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy; case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor; + case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy; case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor; case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor; case tok::kw___is_abstract: return UTT_IsAbstract; + case tok::kw___is_arithmetic: return UTT_IsArithmetic; + case tok::kw___is_array: return UTT_IsArray; case tok::kw___is_class: return UTT_IsClass; + case tok::kw___is_complete_type: return UTT_IsCompleteType; + case tok::kw___is_compound: return UTT_IsCompound; + case tok::kw___is_const: return UTT_IsConst; case tok::kw___is_empty: return UTT_IsEmpty; case tok::kw___is_enum: return UTT_IsEnum; + case tok::kw___is_floating_point: return UTT_IsFloatingPoint; + case tok::kw___is_function: return UTT_IsFunction; + case tok::kw___is_fundamental: return UTT_IsFundamental; + case tok::kw___is_integral: return UTT_IsIntegral; + case tok::kw___is_lvalue_expr: return UTT_IsLvalueExpr; + case tok::kw___is_lvalue_reference: return UTT_IsLvalueReference; + case tok::kw___is_member_function_pointer: return UTT_IsMemberFunctionPointer; + case tok::kw___is_member_object_pointer: return UTT_IsMemberObjectPointer; + case tok::kw___is_member_pointer: return UTT_IsMemberPointer; + case tok::kw___is_object: return UTT_IsObject; case tok::kw___is_literal: return UTT_IsLiteral; case tok::kw___is_literal_type: return UTT_IsLiteral; case tok::kw___is_pod: return UTT_IsPOD; + case tok::kw___is_pointer: return UTT_IsPointer; case tok::kw___is_polymorphic: return UTT_IsPolymorphic; - case tok::kw___is_trivial: return UTT_IsTrivial; + case tok::kw___is_reference: return UTT_IsReference; + case tok::kw___is_rvalue_expr: return UTT_IsRvalueExpr; + case tok::kw___is_rvalue_reference: return UTT_IsRvalueReference; + case tok::kw___is_scalar: return UTT_IsScalar; + case tok::kw___is_signed: return UTT_IsSigned; + case tok::kw___is_standard_layout: return UTT_IsStandardLayout; + case tok::kw___is_trivial: return UTT_IsTrivial; case tok::kw___is_union: return UTT_IsUnion; + case tok::kw___is_unsigned: return UTT_IsUnsigned; + case tok::kw___is_void: return UTT_IsVoid; + case tok::kw___is_volatile: return UTT_IsVolatile; } } @@ -1938,6 +1963,8 @@ static BinaryTypeTrait BinaryTypeTraitFromTokKind(tok::TokenKind kind) { switch(kind) { default: llvm_unreachable("Not a known binary type trait"); case tok::kw___is_base_of: return BTT_IsBaseOf; + case tok::kw___is_convertible: return BTT_IsConvertible; + case tok::kw___is_same: return BTT_IsSame; case tok::kw___builtin_types_compatible_p: return BTT_TypeCompatible; case tok::kw___is_convertible_to: return BTT_IsConvertibleTo; } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index f8ad763e4b..7086176d89 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2379,6 +2379,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T, return false; case UTT_IsAbstract: if (const RecordType *RT = T->getAs()) + if (!Self.RequireCompleteType(KeyLoc, T, diag::err_incomplete_typeid)) return cast(RT->getDecl())->isAbstract(); return false; case UTT_IsEmpty: @@ -2387,6 +2388,74 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T, && cast(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()) + 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 @@ ExprResult Sema::BuildUnaryTypeTrait(UnaryTypeTrait UTT, // 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 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, return cast(rhsRecord->getDecl()) ->isDerivedFrom(cast(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 @@ ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT, 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; } diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index 05cc5587e1..27777a51c4 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -183,7 +183,7 @@ template typename T::U ft6(const T&) { return 0; } // CHECK: @_Z3ft6I1SENT_1UERKS1_ template int ft6(const S&); -template struct __is_scalar { +template struct __is_scalar_type { enum { __value = 1 }; }; @@ -194,11 +194,11 @@ template struct __enable_if { }; // PR5063 -template typename __enable_if<__is_scalar::__value, void>::__type ft7() { } +template typename __enable_if<__is_scalar_type::__value, void>::__type ft7() { } -// CHECK: @_Z3ft7IiEN11__enable_ifIXsr11__is_scalarIT_E7__valueEvE6__typeEv +// CHECK: @_Z3ft7IiEN11__enable_ifIXsr16__is_scalar_typeIT_E7__valueEvE6__typeEv template void ft7(); -// CHECK: @_Z3ft7IPvEN11__enable_ifIXsr11__is_scalarIT_E7__valueEvE6__typeEv +// CHECK: @_Z3ft7IPvEN11__enable_ifIXsr16__is_scalar_typeIT_E7__valueEvE6__typeEv template void ft7(); // PR5144 @@ -225,15 +225,15 @@ struct S7 { S7::S7() {} // PR5063 -template typename __enable_if<(__is_scalar::__value), void>::__type ft8() { } -// CHECK: @_Z3ft8IiEN11__enable_ifIXsr11__is_scalarIT_E7__valueEvE6__typeEv +template typename __enable_if<(__is_scalar_type::__value), void>::__type ft8() { } +// CHECK: @_Z3ft8IiEN11__enable_ifIXsr16__is_scalar_typeIT_E7__valueEvE6__typeEv template void ft8(); -// CHECK: @_Z3ft8IPvEN11__enable_ifIXsr11__is_scalarIT_E7__valueEvE6__typeEv +// CHECK: @_Z3ft8IPvEN11__enable_ifIXsr16__is_scalar_typeIT_E7__valueEvE6__typeEv template void ft8(); // PR5796 namespace PR5796 { -template struct __is_scalar { +template struct __is_scalar_type { enum { __value = 0 }; }; @@ -241,8 +241,8 @@ template struct __enable_if {}; template struct __enable_if { typedef T __type; }; template -// CHECK: define linkonce_odr void @_ZN6PR57968__fill_aIiEENS_11__enable_ifIXntsrNS_11__is_scalarIT_EE7__valueEvE6__typeEv -typename __enable_if::__value, void>::__type __fill_a() { }; +// CHECK: define linkonce_odr void @_ZN6PR57968__fill_aIiEENS_11__enable_ifIXntsrNS_16__is_scalar_typeIT_EE7__valueEvE6__typeEv +typename __enable_if::__value, void>::__type __fill_a() { }; void f() { __fill_a(); } } diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index fe5be63961..ef5607b20c 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -244,6 +244,773 @@ void is_polymorphic() { int arr[F(__is_polymorphic(IntArNB))]; } } +void is_integral() +{ + int t01[T(__is_integral(bool))]; + int t02[T(__is_integral(char))]; + int t03[T(__is_integral(signed char))]; + int t04[T(__is_integral(unsigned char))]; + //int t05[T(__is_integral(char16_t))]; + //int t06[T(__is_integral(char32_t))]; + int t07[T(__is_integral(wchar_t))]; + int t08[T(__is_integral(short))]; + int t09[T(__is_integral(unsigned short))]; + int t10[T(__is_integral(int))]; + int t11[T(__is_integral(unsigned int))]; + int t12[T(__is_integral(long))]; + int t13[T(__is_integral(unsigned long))]; + + int t21[F(__is_integral(float))]; + int t22[F(__is_integral(double))]; + int t23[F(__is_integral(long double))]; + int t24[F(__is_integral(Union))]; + int t25[F(__is_integral(UnionAr))]; + int t26[F(__is_integral(Derives))]; + int t27[F(__is_integral(ClassType))]; + int t28[F(__is_integral(Enum))]; + int t29[F(__is_integral(void))]; + int t30[F(__is_integral(cvoid))]; + int t31[F(__is_integral(IntArNB))]; +} + +void is_floating_point() +{ + int t01[T(__is_floating_point(float))]; + int t02[T(__is_floating_point(double))]; + int t03[T(__is_floating_point(long double))]; + + int t11[F(__is_floating_point(bool))]; + int t12[F(__is_floating_point(char))]; + int t13[F(__is_floating_point(signed char))]; + int t14[F(__is_floating_point(unsigned char))]; + //int t15[F(__is_floating_point(char16_t))]; + //int t16[F(__is_floating_point(char32_t))]; + int t17[F(__is_floating_point(wchar_t))]; + int t18[F(__is_floating_point(short))]; + int t19[F(__is_floating_point(unsigned short))]; + int t20[F(__is_floating_point(int))]; + int t21[F(__is_floating_point(unsigned int))]; + int t22[F(__is_floating_point(long))]; + int t23[F(__is_floating_point(unsigned long))]; + int t24[F(__is_floating_point(Union))]; + int t25[F(__is_floating_point(UnionAr))]; + int t26[F(__is_floating_point(Derives))]; + int t27[F(__is_floating_point(ClassType))]; + int t28[F(__is_floating_point(Enum))]; + int t29[F(__is_floating_point(void))]; + int t30[F(__is_floating_point(cvoid))]; + int t31[F(__is_floating_point(IntArNB))]; +} + +void is_arithmetic() +{ + int t01[T(__is_arithmetic(float))]; + int t02[T(__is_arithmetic(double))]; + int t03[T(__is_arithmetic(long double))]; + int t11[T(__is_arithmetic(bool))]; + int t12[T(__is_arithmetic(char))]; + int t13[T(__is_arithmetic(signed char))]; + int t14[T(__is_arithmetic(unsigned char))]; + //int t15[T(__is_arithmetic(char16_t))]; + //int t16[T(__is_arithmetic(char32_t))]; + int t17[T(__is_arithmetic(wchar_t))]; + int t18[T(__is_arithmetic(short))]; + int t19[T(__is_arithmetic(unsigned short))]; + int t20[T(__is_arithmetic(int))]; + int t21[T(__is_arithmetic(unsigned int))]; + int t22[T(__is_arithmetic(long))]; + int t23[T(__is_arithmetic(unsigned long))]; + + int t24[F(__is_arithmetic(Union))]; + int t25[F(__is_arithmetic(UnionAr))]; + int t26[F(__is_arithmetic(Derives))]; + int t27[F(__is_arithmetic(ClassType))]; + int t28[F(__is_arithmetic(Enum))]; + int t29[F(__is_arithmetic(void))]; + int t30[F(__is_arithmetic(cvoid))]; + int t31[F(__is_arithmetic(IntArNB))]; +} + +struct ACompleteType {}; +struct AnIncompleteType; + +void is_complete_type() +{ + int t01[T(__is_complete_type(float))]; + int t02[T(__is_complete_type(double))]; + int t03[T(__is_complete_type(long double))]; + int t11[T(__is_complete_type(bool))]; + int t12[T(__is_complete_type(char))]; + int t13[T(__is_complete_type(signed char))]; + int t14[T(__is_complete_type(unsigned char))]; + //int t15[T(__is_complete_type(char16_t))]; + //int t16[T(__is_complete_type(char32_t))]; + int t17[T(__is_complete_type(wchar_t))]; + int t18[T(__is_complete_type(short))]; + int t19[T(__is_complete_type(unsigned short))]; + int t20[T(__is_complete_type(int))]; + int t21[T(__is_complete_type(unsigned int))]; + int t22[T(__is_complete_type(long))]; + int t23[T(__is_complete_type(unsigned long))]; + int t24[T(__is_complete_type(ACompleteType))]; + + int t30[F(__is_complete_type(AnIncompleteType))]; +} + +void is_void() +{ + int t01[T(__is_void(void))]; + int t02[T(__is_void(cvoid))]; + + int t10[F(__is_void(float))]; + int t11[F(__is_void(double))]; + int t12[F(__is_void(long double))]; + int t13[F(__is_void(bool))]; + int t14[F(__is_void(char))]; + int t15[F(__is_void(signed char))]; + int t16[F(__is_void(unsigned char))]; + int t17[F(__is_void(wchar_t))]; + int t18[F(__is_void(short))]; + int t19[F(__is_void(unsigned short))]; + int t20[F(__is_void(int))]; + int t21[F(__is_void(unsigned int))]; + int t22[F(__is_void(long))]; + int t23[F(__is_void(unsigned long))]; + int t24[F(__is_void(Union))]; + int t25[F(__is_void(UnionAr))]; + int t26[F(__is_void(Derives))]; + int t27[F(__is_void(ClassType))]; + int t28[F(__is_void(Enum))]; + int t29[F(__is_void(IntArNB))]; + int t30[F(__is_void(void*))]; + int t31[F(__is_void(cvoid*))]; +} + +void is_array() +{ + int t01[T(__is_array(IntAr))]; + int t02[T(__is_array(IntArNB))]; + int t03[T(__is_array(UnionAr))]; + + int t10[F(__is_array(void))]; + int t11[F(__is_array(cvoid))]; + int t12[F(__is_array(float))]; + int t13[F(__is_array(double))]; + int t14[F(__is_array(long double))]; + int t15[F(__is_array(bool))]; + int t16[F(__is_array(char))]; + int t17[F(__is_array(signed char))]; + int t18[F(__is_array(unsigned char))]; + int t19[F(__is_array(wchar_t))]; + int t20[F(__is_array(short))]; + int t21[F(__is_array(unsigned short))]; + int t22[F(__is_array(int))]; + int t23[F(__is_array(unsigned int))]; + int t24[F(__is_array(long))]; + int t25[F(__is_array(unsigned long))]; + int t26[F(__is_array(Union))]; + int t27[F(__is_array(Derives))]; + int t28[F(__is_array(ClassType))]; + int t29[F(__is_array(Enum))]; + int t30[F(__is_array(void*))]; + int t31[F(__is_array(cvoid*))]; +} + +template void tmpl_func(T&) {} + +template struct type_wrapper { + typedef T type; + typedef T* ptrtype; + typedef T& reftype; +}; + +void is_function() +{ + int t01[T(__is_function(type_wrapper::type))]; + int t02[T(__is_function(typeof(tmpl_func)))]; + + typedef void (*ptr_to_func_type)(void); + + int t10[F(__is_function(void))]; + int t11[F(__is_function(cvoid))]; + int t12[F(__is_function(float))]; + int t13[F(__is_function(double))]; + int t14[F(__is_function(long double))]; + int t15[F(__is_function(bool))]; + int t16[F(__is_function(char))]; + int t17[F(__is_function(signed char))]; + int t18[F(__is_function(unsigned char))]; + int t19[F(__is_function(wchar_t))]; + int t20[F(__is_function(short))]; + int t21[F(__is_function(unsigned short))]; + int t22[F(__is_function(int))]; + int t23[F(__is_function(unsigned int))]; + int t24[F(__is_function(long))]; + int t25[F(__is_function(unsigned long))]; + int t26[F(__is_function(Union))]; + int t27[F(__is_function(Derives))]; + int t28[F(__is_function(ClassType))]; + int t29[F(__is_function(Enum))]; + int t30[F(__is_function(void*))]; + int t31[F(__is_function(cvoid*))]; + int t32[F(__is_function(void(*)()))]; + int t33[F(__is_function(ptr_to_func_type))]; + int t34[F(__is_function(type_wrapper::ptrtype))]; + int t35[F(__is_function(type_wrapper::reftype))]; +} + +void is_reference() +{ + int t01[T(__is_reference(int&))]; + int t02[T(__is_reference(const int&))]; + int t03[T(__is_reference(void *&))]; + + int t10[F(__is_reference(int))]; + int t11[F(__is_reference(const int))]; + int t12[F(__is_reference(void *))]; +} + +void is_lvalue_reference() +{ + int t01[T(__is_lvalue_reference(int&))]; + int t02[T(__is_lvalue_reference(void *&))]; + int t03[T(__is_lvalue_reference(const int&))]; + int t04[T(__is_lvalue_reference(void * const &))]; + + int t10[F(__is_lvalue_reference(int))]; + int t11[F(__is_lvalue_reference(const int))]; + int t12[F(__is_lvalue_reference(void *))]; +} + +#if __has_feature(cxx_rvalue_references) + +void is_rvalue_reference() +{ + int t01[T(__is_rvalue_reference(const int&&))]; + int t02[T(__is_rvalue_reference(void * const &&))]; + + int t10[F(__is_rvalue_reference(int&))]; + int t11[F(__is_rvalue_reference(void *&))]; + int t12[F(__is_rvalue_reference(const int&))]; + int t13[F(__is_rvalue_reference(void * const &))]; + int t14[F(__is_rvalue_reference(int))]; + int t15[F(__is_rvalue_reference(const int))]; + int t16[F(__is_rvalue_reference(void *))]; +} + +#endif + +void is_fundamental() +{ + int t01[T(__is_fundamental(float))]; + int t02[T(__is_fundamental(double))]; + int t03[T(__is_fundamental(long double))]; + int t11[T(__is_fundamental(bool))]; + int t12[T(__is_fundamental(char))]; + int t13[T(__is_fundamental(signed char))]; + int t14[T(__is_fundamental(unsigned char))]; + //int t15[T(__is_fundamental(char16_t))]; + //int t16[T(__is_fundamental(char32_t))]; + int t17[T(__is_fundamental(wchar_t))]; + int t18[T(__is_fundamental(short))]; + int t19[T(__is_fundamental(unsigned short))]; + int t20[T(__is_fundamental(int))]; + int t21[T(__is_fundamental(unsigned int))]; + int t22[T(__is_fundamental(long))]; + int t23[T(__is_fundamental(unsigned long))]; + int t24[T(__is_fundamental(void))]; + int t25[T(__is_fundamental(cvoid))]; + + int t30[F(__is_fundamental(Union))]; + int t31[F(__is_fundamental(UnionAr))]; + int t32[F(__is_fundamental(Derives))]; + int t33[F(__is_fundamental(ClassType))]; + int t34[F(__is_fundamental(Enum))]; + int t35[F(__is_fundamental(IntArNB))]; +} + +void is_object() +{ + int t01[T(__is_object(int))]; + int t02[T(__is_object(int *))]; + int t03[T(__is_object(void *))]; + int t04[T(__is_object(Union))]; + int t05[T(__is_object(UnionAr))]; + int t06[T(__is_object(ClassType))]; + int t07[T(__is_object(Enum))]; + + int t10[F(__is_object(type_wrapper::type))]; + int t11[F(__is_object(int&))]; + int t12[F(__is_object(void))]; +} + +void is_scalar() +{ + int t01[T(__is_scalar(float))]; + int t02[T(__is_scalar(double))]; + int t03[T(__is_scalar(long double))]; + int t04[T(__is_scalar(bool))]; + int t05[T(__is_scalar(char))]; + int t06[T(__is_scalar(signed char))]; + int t07[T(__is_scalar(unsigned char))]; + int t08[T(__is_scalar(wchar_t))]; + int t09[T(__is_scalar(short))]; + int t10[T(__is_scalar(unsigned short))]; + int t11[T(__is_scalar(int))]; + int t12[T(__is_scalar(unsigned int))]; + int t13[T(__is_scalar(long))]; + int t14[T(__is_scalar(unsigned long))]; + int t15[T(__is_scalar(Enum))]; + int t16[T(__is_scalar(void*))]; + int t17[T(__is_scalar(cvoid*))]; + + int t20[F(__is_scalar(void))]; + int t21[F(__is_scalar(cvoid))]; + int t22[F(__is_scalar(Union))]; + int t23[F(__is_scalar(UnionAr))]; + int t24[F(__is_scalar(Derives))]; + int t25[F(__is_scalar(ClassType))]; + int t26[F(__is_scalar(IntArNB))]; +} + +struct StructWithMembers { + int member; + void method() {} +}; + +void is_compound() +{ + int t01[T(__is_compound(void*))]; + int t02[T(__is_compound(cvoid*))]; + int t03[T(__is_compound(void (*)()))]; + int t04[T(__is_compound(int StructWithMembers::*))]; + int t05[T(__is_compound(void (StructWithMembers::*)()))]; + int t06[T(__is_compound(int&))]; + int t07[T(__is_compound(Union))]; + int t08[T(__is_compound(UnionAr))]; + int t09[T(__is_compound(Derives))]; + int t10[T(__is_compound(ClassType))]; + int t11[T(__is_compound(IntArNB))]; + int t12[T(__is_compound(Enum))]; + + int t20[F(__is_compound(float))]; + int t21[F(__is_compound(double))]; + int t22[F(__is_compound(long double))]; + int t23[F(__is_compound(bool))]; + int t24[F(__is_compound(char))]; + int t25[F(__is_compound(signed char))]; + int t26[F(__is_compound(unsigned char))]; + int t27[F(__is_compound(wchar_t))]; + int t28[F(__is_compound(short))]; + int t29[F(__is_compound(unsigned short))]; + int t30[F(__is_compound(int))]; + int t31[F(__is_compound(unsigned int))]; + int t32[F(__is_compound(long))]; + int t33[F(__is_compound(unsigned long))]; + int t34[F(__is_compound(void))]; + int t35[F(__is_compound(cvoid))]; +} + +void is_pointer() +{ + StructWithMembers x; + + int t01[T(__is_pointer(void*))]; + int t02[T(__is_pointer(cvoid*))]; + int t03[T(__is_pointer(cvoid*))]; + int t04[T(__is_pointer(char*))]; + int t05[T(__is_pointer(int*))]; + int t06[T(__is_pointer(int**))]; + int t07[T(__is_pointer(ClassType*))]; + int t08[T(__is_pointer(Derives*))]; + int t09[T(__is_pointer(Enum*))]; + int t10[T(__is_pointer(IntArNB*))]; + int t11[T(__is_pointer(Union*))]; + int t12[T(__is_pointer(UnionAr*))]; + int t13[T(__is_pointer(StructWithMembers*))]; + int t14[T(__is_pointer(void (*)()))]; + + int t20[F(__is_pointer(void))]; + int t21[F(__is_pointer(cvoid))]; + int t22[F(__is_pointer(cvoid))]; + int t23[F(__is_pointer(char))]; + int t24[F(__is_pointer(int))]; + int t25[F(__is_pointer(int))]; + int t26[F(__is_pointer(ClassType))]; + int t27[F(__is_pointer(Derives))]; + int t28[F(__is_pointer(Enum))]; + int t29[F(__is_pointer(IntArNB))]; + int t30[F(__is_pointer(Union))]; + int t31[F(__is_pointer(UnionAr))]; + int t32[F(__is_pointer(StructWithMembers))]; + int t33[F(__is_pointer(int StructWithMembers::*))]; + int t34[F(__is_pointer(void (StructWithMembers::*) ()))]; +} + +void is_member_object_pointer() +{ + StructWithMembers x; + + int t01[T(__is_member_object_pointer(int StructWithMembers::*))]; + + int t10[F(__is_member_object_pointer(void (StructWithMembers::*) ()))]; + int t11[F(__is_member_object_pointer(void*))]; + int t12[F(__is_member_object_pointer(cvoid*))]; + int t13[F(__is_member_object_pointer(cvoid*))]; + int t14[F(__is_member_object_pointer(char*))]; + int t15[F(__is_member_object_pointer(int*))]; + int t16[F(__is_member_object_pointer(int**))]; + int t17[F(__is_member_object_pointer(ClassType*))]; + int t18[F(__is_member_object_pointer(Derives*))]; + int t19[F(__is_member_object_pointer(Enum*))]; + int t20[F(__is_member_object_pointer(IntArNB*))]; + int t21[F(__is_member_object_pointer(Union*))]; + int t22[F(__is_member_object_pointer(UnionAr*))]; + int t23[F(__is_member_object_pointer(StructWithMembers*))]; + int t24[F(__is_member_object_pointer(void))]; + int t25[F(__is_member_object_pointer(cvoid))]; + int t26[F(__is_member_object_pointer(cvoid))]; + int t27[F(__is_member_object_pointer(char))]; + int t28[F(__is_member_object_pointer(int))]; + int t29[F(__is_member_object_pointer(int))]; + int t30[F(__is_member_object_pointer(ClassType))]; + int t31[F(__is_member_object_pointer(Derives))]; + int t32[F(__is_member_object_pointer(Enum))]; + int t33[F(__is_member_object_pointer(IntArNB))]; + int t34[F(__is_member_object_pointer(Union))]; + int t35[F(__is_member_object_pointer(UnionAr))]; + int t36[F(__is_member_object_pointer(StructWithMembers))]; + int t37[F(__is_member_object_pointer(void (*)()))]; +} + +void is_member_function_pointer() +{ + StructWithMembers x; + + int t01[T(__is_member_function_pointer(void (StructWithMembers::*) ()))]; + + int t10[F(__is_member_function_pointer(int StructWithMembers::*))]; + int t11[F(__is_member_function_pointer(void*))]; + int t12[F(__is_member_function_pointer(cvoid*))]; + int t13[F(__is_member_function_pointer(cvoid*))]; + int t14[F(__is_member_function_pointer(char*))]; + int t15[F(__is_member_function_pointer(int*))]; + int t16[F(__is_member_function_pointer(int**))]; + int t17[F(__is_member_function_pointer(ClassType*))]; + int t18[F(__is_member_function_pointer(Derives*))]; + int t19[F(__is_member_function_pointer(Enum*))]; + int t20[F(__is_member_function_pointer(IntArNB*))]; + int t21[F(__is_member_function_pointer(Union*))]; + int t22[F(__is_member_function_pointer(UnionAr*))]; + int t23[F(__is_member_function_pointer(StructWithMembers*))]; + int t24[F(__is_member_function_pointer(void))]; + int t25[F(__is_member_function_pointer(cvoid))]; + int t26[F(__is_member_function_pointer(cvoid))]; + int t27[F(__is_member_function_pointer(char))]; + int t28[F(__is_member_function_pointer(int))]; + int t29[F(__is_member_function_pointer(int))]; + int t30[F(__is_member_function_pointer(ClassType))]; + int t31[F(__is_member_function_pointer(Derives))]; + int t32[F(__is_member_function_pointer(Enum))]; + int t33[F(__is_member_function_pointer(IntArNB))]; + int t34[F(__is_member_function_pointer(Union))]; + int t35[F(__is_member_function_pointer(UnionAr))]; + int t36[F(__is_member_function_pointer(StructWithMembers))]; + int t37[F(__is_member_function_pointer(void (*)()))]; +} + +void is_member_pointer() +{ + StructWithMembers x; + + int t01[T(__is_member_pointer(int StructWithMembers::*))]; + int t02[T(__is_member_pointer(void (StructWithMembers::*) ()))]; + + int t10[F(__is_member_pointer(void*))]; + int t11[F(__is_member_pointer(cvoid*))]; + int t12[F(__is_member_pointer(cvoid*))]; + int t13[F(__is_member_pointer(char*))]; + int t14[F(__is_member_pointer(int*))]; + int t15[F(__is_member_pointer(int**))]; + int t16[F(__is_member_pointer(ClassType*))]; + int t17[F(__is_member_pointer(Derives*))]; + int t18[F(__is_member_pointer(Enum*))]; + int t19[F(__is_member_pointer(IntArNB*))]; + int t20[F(__is_member_pointer(Union*))]; + int t21[F(__is_member_pointer(UnionAr*))]; + int t22[F(__is_member_pointer(StructWithMembers*))]; + int t23[F(__is_member_pointer(void))]; + int t24[F(__is_member_pointer(cvoid))]; + int t25[F(__is_member_pointer(cvoid))]; + int t26[F(__is_member_pointer(char))]; + int t27[F(__is_member_pointer(int))]; + int t28[F(__is_member_pointer(int))]; + int t29[F(__is_member_pointer(ClassType))]; + int t30[F(__is_member_pointer(Derives))]; + int t31[F(__is_member_pointer(Enum))]; + int t32[F(__is_member_pointer(IntArNB))]; + int t33[F(__is_member_pointer(Union))]; + int t34[F(__is_member_pointer(UnionAr))]; + int t35[F(__is_member_pointer(StructWithMembers))]; + int t36[F(__is_member_pointer(void (*)()))]; +} + +void is_const() +{ + int t01[T(__is_const(cvoid))]; + int t02[T(__is_const(const char))]; + int t03[T(__is_const(const int))]; + int t04[T(__is_const(const long))]; + int t05[T(__is_const(const short))]; + int t06[T(__is_const(const signed char))]; + int t07[T(__is_const(const wchar_t))]; + int t08[T(__is_const(const bool))]; + int t09[T(__is_const(const float))]; + int t10[T(__is_const(const double))]; + int t11[T(__is_const(const long double))]; + int t12[T(__is_const(const unsigned char))]; + int t13[T(__is_const(const unsigned int))]; + int t14[T(__is_const(const unsigned long long))]; + int t15[T(__is_const(const unsigned long))]; + int t16[T(__is_const(const unsigned short))]; + int t17[T(__is_const(const void))]; + int t18[T(__is_const(const ClassType))]; + int t19[T(__is_const(const Derives))]; + int t20[T(__is_const(const Enum))]; + int t21[T(__is_const(const IntArNB))]; + int t22[T(__is_const(const Union))]; + int t23[T(__is_const(const UnionAr))]; + + int t30[F(__is_const(char))]; + int t31[F(__is_const(int))]; + int t32[F(__is_const(long))]; + int t33[F(__is_const(short))]; + int t34[F(__is_const(signed char))]; + int t35[F(__is_const(wchar_t))]; + int t36[F(__is_const(bool))]; + int t37[F(__is_const(float))]; + int t38[F(__is_const(double))]; + int t39[F(__is_const(long double))]; + int t40[F(__is_const(unsigned char))]; + int t41[F(__is_const(unsigned int))]; + int t42[F(__is_const(unsigned long long))]; + int t43[F(__is_const(unsigned long))]; + int t44[F(__is_const(unsigned short))]; + int t45[F(__is_const(void))]; + int t46[F(__is_const(ClassType))]; + int t47[F(__is_const(Derives))]; + int t48[F(__is_const(Enum))]; + int t49[F(__is_const(IntArNB))]; + int t50[F(__is_const(Union))]; + int t51[F(__is_const(UnionAr))]; +} + +void is_volatile() +{ + int t02[T(__is_volatile(volatile char))]; + int t03[T(__is_volatile(volatile int))]; + int t04[T(__is_volatile(volatile long))]; + int t05[T(__is_volatile(volatile short))]; + int t06[T(__is_volatile(volatile signed char))]; + int t07[T(__is_volatile(volatile wchar_t))]; + int t08[T(__is_volatile(volatile bool))]; + int t09[T(__is_volatile(volatile float))]; + int t10[T(__is_volatile(volatile double))]; + int t11[T(__is_volatile(volatile long double))]; + int t12[T(__is_volatile(volatile unsigned char))]; + int t13[T(__is_volatile(volatile unsigned int))]; + int t14[T(__is_volatile(volatile unsigned long long))]; + int t15[T(__is_volatile(volatile unsigned long))]; + int t16[T(__is_volatile(volatile unsigned short))]; + int t17[T(__is_volatile(volatile void))]; + int t18[T(__is_volatile(volatile ClassType))]; + int t19[T(__is_volatile(volatile Derives))]; + int t20[T(__is_volatile(volatile Enum))]; + int t21[T(__is_volatile(volatile IntArNB))]; + int t22[T(__is_volatile(volatile Union))]; + int t23[T(__is_volatile(volatile UnionAr))]; + + int t30[F(__is_volatile(char))]; + int t31[F(__is_volatile(int))]; + int t32[F(__is_volatile(long))]; + int t33[F(__is_volatile(short))]; + int t34[F(__is_volatile(signed char))]; + int t35[F(__is_volatile(wchar_t))]; + int t36[F(__is_volatile(bool))]; + int t37[F(__is_volatile(float))]; + int t38[F(__is_volatile(double))]; + int t39[F(__is_volatile(long double))]; + int t40[F(__is_volatile(unsigned char))]; + int t41[F(__is_volatile(unsigned int))]; + int t42[F(__is_volatile(unsigned long long))]; + int t43[F(__is_volatile(unsigned long))]; + int t44[F(__is_volatile(unsigned short))]; + int t45[F(__is_volatile(void))]; + int t46[F(__is_volatile(ClassType))]; + int t47[F(__is_volatile(Derives))]; + int t48[F(__is_volatile(Enum))]; + int t49[F(__is_volatile(IntArNB))]; + int t50[F(__is_volatile(Union))]; + int t51[F(__is_volatile(UnionAr))]; +} + +struct TrivialStruct { + int member; +}; + +struct NonTrivialStruct { + int member; + NonTrivialStruct() { + member = 0; + } +}; + +void is_trivial2() +{ + int t01[T(__is_trivial(char))]; + int t02[T(__is_trivial(int))]; + int t03[T(__is_trivial(long))]; + int t04[T(__is_trivial(short))]; + int t05[T(__is_trivial(signed char))]; + int t06[T(__is_trivial(wchar_t))]; + int t07[T(__is_trivial(bool))]; + int t08[T(__is_trivial(float))]; + int t09[T(__is_trivial(double))]; + int t10[T(__is_trivial(long double))]; + int t11[T(__is_trivial(unsigned char))]; + int t12[T(__is_trivial(unsigned int))]; + int t13[T(__is_trivial(unsigned long long))]; + int t14[T(__is_trivial(unsigned long))]; + int t15[T(__is_trivial(unsigned short))]; + int t16[T(__is_trivial(ClassType))]; + int t17[T(__is_trivial(Derives))]; + int t18[T(__is_trivial(Enum))]; + int t19[T(__is_trivial(IntAr))]; + int t20[T(__is_trivial(Union))]; + int t21[T(__is_trivial(UnionAr))]; + int t22[T(__is_trivial(TrivialStruct))]; + + int t30[F(__is_trivial(void))]; + int t31[F(__is_trivial(NonTrivialStruct))]; +} + +struct CStruct { + int one; + int two; +}; + +struct CEmptyStruct {}; + +struct CppEmptyStruct : CStruct {}; +struct CppStructStandard : CEmptyStruct { + int three; + int four; +}; +struct CppStructNonStandardByBase : CStruct { + int three; + int four; +}; +struct CppStructNonStandardByVirt : CStruct { + virtual void method() {} +}; +struct CppStructNonStandardByMemb : CStruct { + CppStructNonStandardByVirt member; +}; +struct CppStructNonStandardByProt : CStruct { + int five; +protected: + int six; +}; +struct CppStructNonStandardByVirtBase : virtual CStruct { +}; +struct CppStructNonStandardBySameBase : CEmptyStruct { + CEmptyStruct member; +}; +struct CppStructNonStandardBy2ndVirtBase : CEmptyStruct { + CEmptyStruct member; +}; + +void is_standard_layout() +{ + typedef const int ConstInt; + typedef ConstInt ConstIntAr[4]; + typedef CppStructStandard CppStructStandardAr[4]; + + int t01[T(__is_standard_layout(int))]; + int t02[T(__is_standard_layout(ConstInt))]; + int t03[T(__is_standard_layout(ConstIntAr))]; + int t04[T(__is_standard_layout(CStruct))]; + int t05[T(__is_standard_layout(CppStructStandard))]; + int t06[T(__is_standard_layout(CppStructStandardAr))]; + + typedef CppStructNonStandardByBase CppStructNonStandardByBaseAr[4]; + + int t10[F(__is_standard_layout(CppStructNonStandardByVirt))]; + int t11[F(__is_standard_layout(CppStructNonStandardByMemb))]; + int t12[F(__is_standard_layout(CppStructNonStandardByProt))]; + int t13[F(__is_standard_layout(CppStructNonStandardByVirtBase))]; + int t14[F(__is_standard_layout(CppStructNonStandardByBase))]; + int t15[F(__is_standard_layout(CppStructNonStandardByBaseAr))]; + int t16[F(__is_standard_layout(CppStructNonStandardBySameBase))]; + int t17[F(__is_standard_layout(CppStructNonStandardBy2ndVirtBase))]; +} + +void is_signed() +{ + //int t01[T(__is_signed(char))]; + int t02[T(__is_signed(int))]; + int t03[T(__is_signed(long))]; + int t04[T(__is_signed(short))]; + int t05[T(__is_signed(signed char))]; + int t06[T(__is_signed(wchar_t))]; + + int t10[F(__is_signed(bool))]; + int t11[F(__is_signed(cvoid))]; + int t12[F(__is_signed(float))]; + int t13[F(__is_signed(double))]; + int t14[F(__is_signed(long double))]; + int t15[F(__is_signed(unsigned char))]; + int t16[F(__is_signed(unsigned int))]; + int t17[F(__is_signed(unsigned long long))]; + int t18[F(__is_signed(unsigned long))]; + int t19[F(__is_signed(unsigned short))]; + int t20[F(__is_signed(void))]; + int t21[F(__is_signed(ClassType))]; + int t22[F(__is_signed(Derives))]; + int t23[F(__is_signed(Enum))]; + int t24[F(__is_signed(IntArNB))]; + int t25[F(__is_signed(Union))]; + int t26[F(__is_signed(UnionAr))]; +} + +void is_unsigned() +{ + int t01[T(__is_unsigned(bool))]; + int t02[T(__is_unsigned(unsigned char))]; + int t03[T(__is_unsigned(unsigned short))]; + int t04[T(__is_unsigned(unsigned int))]; + int t05[T(__is_unsigned(unsigned long))]; + int t06[T(__is_unsigned(unsigned long long))]; + int t07[T(__is_unsigned(Enum))]; + + int t10[F(__is_unsigned(void))]; + int t11[F(__is_unsigned(cvoid))]; + int t12[F(__is_unsigned(float))]; + int t13[F(__is_unsigned(double))]; + int t14[F(__is_unsigned(long double))]; + int t16[F(__is_unsigned(char))]; + int t17[F(__is_unsigned(signed char))]; + int t18[F(__is_unsigned(wchar_t))]; + int t19[F(__is_unsigned(short))]; + int t20[F(__is_unsigned(int))]; + int t21[F(__is_unsigned(long))]; + int t22[F(__is_unsigned(Union))]; + int t23[F(__is_unsigned(UnionAr))]; + int t24[F(__is_unsigned(Derives))]; + int t25[F(__is_unsigned(ClassType))]; + int t26[F(__is_unsigned(IntArNB))]; +} + typedef Int& IntRef; typedef const IntAr ConstIntAr; typedef ConstIntAr ConstIntArAr[4]; @@ -556,6 +1323,64 @@ void is_base_of() { isBaseOfF, BaseA >(); } +#if 0 +template +class TemplateClass {}; + +template +using TemplateAlias = TemplateClass; +#endif + +typedef class Base BaseTypedef; + +void is_same() +{ + int t01[T(__is_same(Base, Base))]; + int t02[T(__is_same(Base, BaseTypedef))]; +#if 0 + int t03[T(__is_same(TemplateClass, TemplateAlias))]; +#endif + + int t10[F(__is_same(Base, const Base))]; + int t11[F(__is_same(Base, Base&))]; + int t12[F(__is_same(Base, Derived))]; +} + +struct IntWrapper +{ + int value; + IntWrapper(int _value) : value(_value) {} + operator int() const { + return value; + } +}; + +struct FloatWrapper +{ + float value; + FloatWrapper(float _value) : value(_value) {} + FloatWrapper(const IntWrapper& obj) + : value(static_cast(obj.value)) {} + operator float() const { + return value; + } + operator IntWrapper() const { + return IntWrapper(static_cast(value)); + } +}; + +void is_convertible() +{ + int t01[T(__is_convertible(IntWrapper, IntWrapper))]; + int t02[T(__is_convertible(IntWrapper, const IntWrapper))]; + int t03[T(__is_convertible(IntWrapper, int))]; + int t04[T(__is_convertible(int, IntWrapper))]; + int t05[T(__is_convertible(IntWrapper, FloatWrapper))]; + int t06[T(__is_convertible(FloatWrapper, IntWrapper))]; + int t07[T(__is_convertible(FloatWrapper, float))]; + int t08[T(__is_convertible(float, FloatWrapper))]; +} + struct FromInt { FromInt(int); }; struct ToInt { operator int(); }; typedef void Function();