diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-08-14 02:06:07 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-08-14 02:06:07 +0000 |
commit | 2217f853e1909b80f87ce0dcec5543e894d11bc9 (patch) | |
tree | 085955010a8731a57efd1c9d31ef5ac984122d7e | |
parent | f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91 (diff) |
Make __is_convertible_to handle abstract types correctly. PR13591.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161828 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 18 | ||||
-rw-r--r-- | test/SemaCXX/type-traits.cpp | 3 |
3 files changed, 21 insertions, 1 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 539ed0eac5..1d45a6823d 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3478,6 +3478,7 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, : TypeDiagnoser(DiagID == 0), DiagID(DiagID), SelID(SelID) { } virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) { + if (Suppressed) return; if (SelID == -1) S.Diag(Loc, DiagID) << T; else diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 1a3cff5bd7..27402599a4 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -3542,9 +3542,25 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, // 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). + + // Functions aren't allowed to return function or array types. + if (RhsT->isFunctionType() || RhsT->isArrayType()) + return false; + + // A return statement in a void function must have void type. + if (RhsT->isVoidType()) + return LhsT->isVoidType(); + + // A function definition requires a complete, non-abstract return type. + if (Self.RequireCompleteType(KeyLoc, RhsT, 0) || + Self.RequireNonAbstractType(KeyLoc, RhsT, 0)) + return false; + + // Compute the result of add_rvalue_reference. if (LhsT->isObjectType() || LhsT->isFunctionType()) LhsT = Self.Context.getRValueReferenceType(LhsT); - + + // Build a fake source and destination for initialization. InitializedEntity To(InitializedEntity::InitializeTemporary(RhsT)); OpaqueValueExpr From(KeyLoc, LhsT.getNonLValueExprType(Self.Context), Expr::getValueKindForType(LhsT)); diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index bf590f9c72..54294bcbb8 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -1574,6 +1574,8 @@ struct X0 { template<typename U> X0(const X0<U>&); }; +struct Abstract { virtual void f() = 0; }; + void is_convertible_to() { { int arr[T(__is_convertible_to(Int, Int))]; } { int arr[F(__is_convertible_to(Int, IntAr))]; } @@ -1598,6 +1600,7 @@ void is_convertible_to() { { int arr[F(__is_convertible_to(Function, Function))]; } { int arr[F(__is_convertible_to(PrivateCopy, PrivateCopy))]; } { int arr[T(__is_convertible_to(X0<int>, X0<float>))]; } + { int arr[F(__is_convertible_to(Abstract, Abstract))]; } } namespace is_convertible_to_instantiate { |