]> granicus.if.org Git - clang/commitdiff
When trying to determine whether one operand of a conditional
authorDouglas Gregor <dgregor@apple.com>
Fri, 26 Mar 2010 20:59:55 +0000 (20:59 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 26 Mar 2010 20:59:55 +0000 (20:59 +0000)
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

lib/Sema/SemaExprCXX.cpp
test/SemaCXX/conditional-expr.cpp

index 52dc6d8fa4f316e37443c3ed8a1e80ca291cc32e..5a412920415e2e03ca99a37ce3d709b4d49566b5 100644 (file)
@@ -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);
index c0c78bfb36f9fabc70a5a3281238f0880bb40aba..e2a966bdd95d44542bc8dcf39f8cfe27fa9b848d 100644 (file)
@@ -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);
+  }
+}