aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaExprCXX.cpp16
-rw-r--r--test/SemaCXX/conditional-expr.cpp15
2 files changed, 24 insertions, 7 deletions
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<TagType>())
+ 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);
+ }
+}