diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 4 | ||||
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 35 | ||||
-rw-r--r-- | clang/lib/AST/Type.cpp | 103 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 29 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 55 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 35 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 81 |
7 files changed, 314 insertions, 28 deletions
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index a71750bb4c8..7ab60303ad3 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/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<RecordType>()) + data().HasStandardLayout = RT->hasStandardLayout(Context); } void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index cf42e633791..b96591b6614 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/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/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index d43a121881e..e75ce7dfe40 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -1385,6 +1385,109 @@ bool RecordType::classof(const TagType *TT) { return isa<RecordDecl>(TT->getDecl()); } +static uint64_t countBasesWithFields(QualType BaseType) { + uint64_t BasesWithFields = 0; + if (const RecordType *T = BaseType->getAs<RecordType>()) { + CXXRecordDecl *RD = cast<CXXRecordDecl>(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<CXXRecordDecl>(getDecl()); + if (! RD) { + assert(cast<RecordDecl>(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<RecordType>()) { + 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<RecordType>()) + 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<EnumDecl>(TT->getDecl()); } diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index f59302868b5..c41798e35ee 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/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/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index c990c52e7b1..1c4a9427801 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/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/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 7bf76a917f2..aade050df44 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/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/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index f8ad763e4bd..7086176d89f 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/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<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 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T, && 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 @@ 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<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 @@ 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; } |