From: Douglas Gregor Date: Fri, 26 Mar 2010 20:59:55 +0000 (+0000) Subject: When trying to determine whether one operand of a conditional X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0fd8ff73630adab9a33123f23ef62fcf5c3cf326;p=clang When trying to determine whether one operand of a conditional expression can be converted to the type of another, only apply the lvalue-to-rvalue conversion to the type of the expression we're converting, *not* the array-to-pointer or function-to-pointer conversions. Fixes PR6595. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99652 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 52dc6d8fa4..5a41292041 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1934,7 +1934,8 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To, // can be converted to match an operand expression E2 of type T2 is defined // as follows: // -- If E2 is an lvalue: - if (To->isLvalue(Self.Context) == Expr::LV_Valid) { + bool ToIsLvalue = (To->isLvalue(Self.Context) == Expr::LV_Valid); + if (ToIsLvalue) { // E1 can be converted to match E2 if E1 can be implicitly converted to // type "lvalue reference to T2", subject to the constraint that in the // conversion the reference must bind directly to E1. @@ -1985,12 +1986,13 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To, // -- Otherwise: E1 can be converted to match E2 if E1 can be // implicitly converted to the type that expression E2 would have - // if E2 were converted to an rvalue. - // First find the decayed type. - if (TTy->isFunctionType()) - TTy = Self.Context.getPointerType(TTy); - else if (TTy->isArrayType()) - TTy = Self.Context.getArrayDecayedType(TTy); + // if E2 were converted to an rvalue (or the type it has, if E2 is + // an rvalue). + // + // This actually refers very narrowly to the lvalue-to-rvalue conversion, not + // to the array-to-pointer or function-to-pointer conversions. + if (!TTy->getAs()) + TTy = TTy.getUnqualifiedType(); InitializedEntity Entity = InitializedEntity::InitializeTemporary(TTy); InitializationSequence InitSeq(Self, Entity, Kind, &From, 1); diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp index c0c78bfb36..e2a966bdd9 100644 --- a/test/SemaCXX/conditional-expr.cpp +++ b/test/SemaCXX/conditional-expr.cpp @@ -198,3 +198,18 @@ void test() // *must* create a separate temporary copy of class objects. This can only // be properly tested at runtime, though. } + +namespace PR6595 { + struct String { + String(const char *); + operator const char*() const; + }; + + void f(bool Cond, String S) { + (void)(Cond? S : ""); + (void)(Cond? "" : S); + const char a[1] = {'a'}; + (void)(Cond? S : a); + (void)(Cond? a : S); + } +}