diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Parse/ParseTentative.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 48 |
5 files changed, 54 insertions, 4 deletions
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 74429ce31df..201115c7eb9 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -1225,9 +1225,9 @@ static const char *getTypeTraitName(UnaryTypeTrait UTT) { static const char *getTypeTraitName(BinaryTypeTrait BTT) { switch (BTT) { - default: llvm_unreachable("Unknown binary type trait"); case BTT_IsBaseOf: return "__is_base_of"; case BTT_TypeCompatible: return "__builtin_types_compatible_p"; + case BTT_IsConvertibleTo: return "__is_convertible_to"; } return ""; } diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 67351f7e2fc..5928871987f 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -537,8 +537,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// '__is_polymorphic' /// '__is_union' /// -/// [GNU] binary-type-trait: -/// '__is_base_of' [TODO] +/// binary-type-trait: +/// [GNU] '__is_base_of' +/// [MS] '__is_convertible_to' /// ExprResult Parser::ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand, @@ -988,6 +989,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___builtin_types_compatible_p: case tok::kw___is_base_of: + case tok::kw___is_convertible_to: return ParseBinaryTypeTrait(); case tok::at: { diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 5a16729d80a..e769ecac503 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -1828,6 +1828,7 @@ static BinaryTypeTrait BinaryTypeTraitFromTokKind(tok::TokenKind kind) { default: llvm_unreachable("Not a known binary type trait"); case tok::kw___is_base_of: return BTT_IsBaseOf; case tok::kw___builtin_types_compatible_p: return BTT_TypeCompatible; + case tok::kw___is_convertible_to: return BTT_IsConvertibleTo; } } diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index 35d72547cd3..a603c37a53e 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -655,6 +655,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::kw___is_abstract: case tok::kw___is_base_of: case tok::kw___is_class: + case tok::kw___is_convertible_to: case tok::kw___is_empty: case tok::kw___is_enum: case tok::kw___is_pod: diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index e95bad4d0a6..df4103a9a1b 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -2499,6 +2499,52 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, case BTT_TypeCompatible: return Self.Context.typesAreCompatible(LhsT.getUnqualifiedType(), RhsT.getUnqualifiedType()); + + case BTT_IsConvertibleTo: { + // C++0x [meta.rel]p4: + // Given the following function prototype: + // + // template <class T> + // typename add_rvalue_reference<T>::type create(); + // + // the predicate condition for a template specialization + // is_convertible<From, To> shall be satisfied if and only if + // the return expression in the following code would be + // well-formed, including any implicit conversions to the return + // type of the function: + // + // To test() { + // return create<From>(); + // } + // + // Access checking is performed as if in a context unrelated to To and + // From. Only the validity of the immediate context of the expression + // of the return-statement (including conversions to the return type) + // is considered. + // + // We model the initialization as a copy-initialization of a temporary + // of the appropriate type, which for this expression is identical to the + // return statement (since NRVO doesn't apply). + if (LhsT->isObjectType() || LhsT->isFunctionType()) + LhsT = Self.Context.getRValueReferenceType(LhsT); + + InitializedEntity To(InitializedEntity::InitializeTemporary(RhsT)); + OpaqueValueExpr From(LhsT.getNonLValueExprType(Self.Context), + Expr::getValueKindForType(LhsT)); + Expr *FromPtr = &From; + InitializationKind Kind(InitializationKind::CreateCopy(KeyLoc, + SourceLocation())); + + // Perform the initialization within a SFINAE trap. + // FIXME: We don't implement the access-checking bits yet, because we don't + // handle access control as part of SFINAE. + Sema::SFINAETrap SFINAE(Self); + InitializationSequence Init(Self, To, Kind, &FromPtr, 1); + if (Init.getKind() == InitializationSequence::FailedSequence) + return false; + ExprResult Result = Init.Perform(Self, To, Kind, MultiExprArg(&FromPtr, 1)); + return !Result.isInvalid() && !SFINAE.hasErrorOccurred(); + } } llvm_unreachable("Unknown type trait or not implemented"); } @@ -2538,9 +2584,9 @@ ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT, // Select trait result type. QualType ResultType; switch (BTT) { - default: llvm_unreachable("Unknown type trait or not implemented"); case BTT_IsBaseOf: ResultType = Context.BoolTy; break; case BTT_TypeCompatible: ResultType = Context.IntTy; break; + case BTT_IsConvertibleTo: ResultType = Context.BoolTy; break; } return Owned(new (Context) BinaryTypeTraitExpr(KWLoc, BTT, LhsTSInfo, |