From c6e378e7d4e14b451f50158968d012dace6646d2 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 24 Mar 2010 23:38:29 +0000 Subject: [PATCH] Switch static_cast from the old reference-initialization code (via CheckReferenceInit) over to the new initialization code (InitializationSequence), which is better-tested and doesn't require us to compute the entire conversion sequence twice. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99452 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaCXXCast.cpp | 37 +++++++++++++++++------------------- test/SemaCXX/static-cast.cpp | 4 ++-- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index 014cec2b65..d3fe6aee5c 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -913,27 +913,24 @@ TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType, // At this point of CheckStaticCast, if the destination is a reference, // this has to work. There is no other way that works. // On the other hand, if we're checking a C-style cast, we've still got - // the reinterpret_cast way. So in C-style mode, we first try the call - // with an ICS to suppress errors. - if (CStyle) { - ImplicitConversionSequence ICS; - if(Self.CheckReferenceInit(SrcExpr, DestType, OpRange.getBegin(), - /*SuppressUserConversions=*/false, - /*AllowExplicit=*/false, /*ForceRValue=*/false, - &ICS)) - return TC_NotApplicable; + // the reinterpret_cast way. + InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType); + InitializationKind InitKind = InitializationKind::CreateCast(OpRange, + CStyle); + InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExpr, 1); + if (InitSeq.getKind() == InitializationSequence::FailedSequence && CStyle) + return TC_NotApplicable; + + Sema::OwningExprResult Result + = InitSeq.Perform(Self, Entity, InitKind, + Action::MultiExprArg(Self, (void**)&SrcExpr, 1)); + if (Result.isInvalid()) { + msg = 0; + return TC_Failed; } - // Now we're committed either way. - if(!Self.CheckReferenceInit(SrcExpr, DestType, OpRange.getBegin(), - /*SuppressUserConversions=*/false, - /*AllowExplicit=*/false, - /*ForceRValue=*/false, 0, - /*IgnoreBaseAccess=*/CStyle)) - return TC_Success; - - // We already got an error message. - msg = 0; - return TC_Failed; + + SrcExpr = Result.takeAs(); + return TC_Success; } if (DestType->isRecordType()) { diff --git a/test/SemaCXX/static-cast.cpp b/test/SemaCXX/static-cast.cpp index 2630278d9f..a5dd7e214d 100644 --- a/test/SemaCXX/static-cast.cpp +++ b/test/SemaCXX/static-cast.cpp @@ -60,7 +60,7 @@ void t_529_2() (void)static_cast((H*)0); // expected-error {{ambiguous conversion}} (void)static_cast((int*)0); // expected-error {{static_cast from 'int *' to 'int' is not allowed}} (void)static_cast((B**)0); // expected-error {{static_cast from 'B **' to 'A **' is not allowed}} - (void)static_cast(i); // expected-error {{non-const lvalue reference to type 'char' cannot be initialized with a value of type 'int'}} + (void)static_cast(i); // expected-error {{non-const lvalue reference to type 'char' cannot bind to a value of unrelated type 'int'}} } // Anything to void @@ -91,7 +91,7 @@ void t_529_5_8() (void)static_cast((A*)0); // expected-error {{ambiguous cast from base 'A' to derived 'H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}} (void)static_cast(*((A*)0)); // expected-error {{ambiguous cast from base 'A' to derived 'H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}} (void)static_cast((B*)0); // expected-error {{static_cast from 'B *' to 'E *' is not allowed}} - (void)static_cast(*((B*)0)); // expected-error {{non-const lvalue reference to type 'E' cannot be initialized with a value of type 'B'}} + (void)static_cast(*((B*)0)); // expected-error {{non-const lvalue reference to type 'E' cannot bind to a value of unrelated type 'B'}} // TODO: Test inaccessible base in context where it's accessible, i.e. // member function and friend. -- 2.40.0