On Sun, Mar 3, 2013 at 5:30 PM, John McCall <span dir="ltr"><<a href="mailto:rjmccall@apple.com" target="_blank">rjmccall@apple.com</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Author: rjmccall<br>
Date: Sun Mar  3 19:30:55 2013<br>
New Revision: 176428<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=176428&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=176428&view=rev</a><br>
Log:<br>
Perform non-overload placeholder conversions on the operands<br>
to a subscript operator.<br>
<br>
rdar://13332183<br>
<br>
Modified:<br>
    cfe/trunk/lib/Sema/SemaExpr.cpp<br>
    cfe/trunk/test/SemaCXX/overloaded-operator.cpp<br>
    cfe/trunk/test/SemaObjCXX/<a href="http://properties.mm" target="_blank">properties.mm</a><br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=176428&r1=176427&r2=176428&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=176428&r1=176427&r2=176428&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Sun Mar  3 19:30:55 2013<br>
@@ -3341,33 +3341,56 @@ static bool checkArithmeticOnObjCPointer<br>
 }<br>
<br>
 ExprResult<br>
-Sema::ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc,<br>
-                              Expr *Idx, SourceLocation RLoc) {<br>
+Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,<br>
+                              Expr *idx, SourceLocation rbLoc) {<br></blockquote><div><br></div><div>Why the conversion away from the coding-style-approved VariableCapitalization?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

   // Since this might be a postfix expression, get rid of ParenListExprs.<br>
-  ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);<br>
-  if (Result.isInvalid()) return ExprError();<br>
-  Base = Result.take();<br>
+  if (isa<ParenListExpr>(base)) {<br>
+    ExprResult result = MaybeConvertParenListExprToParenExpr(S, base);<br>
+    if (result.isInvalid()) return ExprError();<br>
+    base = result.take();<br>
+  }<br>
<br>
-  Expr *LHSExp = Base, *RHSExp = Idx;<br>
+  // Handle any non-overload placeholder types in the base and index<br>
+  // expressions.  We can't handle overloads here because the other<br>
+  // operand might be an overloadable type, in which case the overload<br>
+  // resolution for the operator overload should get the first crack<br>
+  // at the overload.<br>
+  if (base->getType()->isNonOverloadPlaceholderType()) {<br>
+    ExprResult result = CheckPlaceholderExpr(base);<br>
+    if (result.isInvalid()) return ExprError();<br>
+    base = result.take();<br>
+  }<br>
+  if (idx->getType()->isNonOverloadPlaceholderType()) {<br>
+    ExprResult result = CheckPlaceholderExpr(idx);<br>
+    if (result.isInvalid()) return ExprError();<br>
+    idx = result.take();<br>
+  }<br>
<br>
+  // Build an unanalyzed expression if either operand is type-dependent.<br>
   if (getLangOpts().CPlusPlus &&<br>
-      (LHSExp->isTypeDependent() || RHSExp->isTypeDependent())) {<br>
-    return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp,<br>
+      (base->isTypeDependent() || idx->isTypeDependent())) {<br>
+    return Owned(new (Context) ArraySubscriptExpr(base, idx,<br>
                                                   Context.DependentTy,<br>
                                                   VK_LValue, OK_Ordinary,<br>
-                                                  RLoc));<br>
+                                                  rbLoc));<br>
   }<br>
<br>
+  // Use C++ overloaded-operator rules if either operand has record<br>
+  // type.  The spec says to do this if either type is *overloadable*,<br>
+  // but enum types can't declare subscript operators or conversion<br>
+  // operators, so there's nothing interesting for overload resolution<br>
+  // to do if there aren't any record types involved.<br>
+  //<br>
+  // ObjC pointers have their own subscripting logic that is not tied<br>
+  // to overload resolution and so should not take this path.<br>
   if (getLangOpts().CPlusPlus &&<br>
-      (LHSExp->getType()->isRecordType() ||<br>
-       LHSExp->getType()->isEnumeralType() ||<br>
-       RHSExp->getType()->isRecordType() ||<br>
-       RHSExp->getType()->isEnumeralType()) &&<br>
-      !LHSExp->getType()->isObjCObjectPointerType()) {<br>
-    return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, Base, Idx);<br>
+      (base->getType()->isRecordType() ||<br>
+       (!base->getType()->isObjCObjectPointerType() &&<br>
+        idx->getType()->isRecordType()))) {<br>
+    return CreateOverloadedArraySubscriptExpr(lbLoc, rbLoc, base, idx);<br>
   }<br>
<br>
-  return CreateBuiltinArraySubscriptExpr(Base, LLoc, Idx, RLoc);<br>
+  return CreateBuiltinArraySubscriptExpr(base, lbLoc, idx, rbLoc);<br>
 }<br>
<br>
 ExprResult<br>
<br>
Modified: cfe/trunk/test/SemaCXX/overloaded-operator.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overloaded-operator.cpp?rev=176428&r1=176427&r2=176428&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overloaded-operator.cpp?rev=176428&r1=176427&r2=176428&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/SemaCXX/overloaded-operator.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/overloaded-operator.cpp Sun Mar  3 19:30:55 2013<br>
@@ -415,3 +415,28 @@ namespace PR11784 {<br>
   void f(int);<br>
   void g() { A x; x = f; }<br>
 }<br>
+<br>
+namespace test10 {<br>
+  struct A {<br>
+    void operator[](float (*fn)(int)); // expected-note 2 {{not viable: no overload of 'bar' matching 'float (*)(int)'}}<br>
+  };<br>
+<br>
+  float foo(int);<br>
+  float foo(float);<br>
+<br>
+  template <class T> T bar(T);<br>
+  template <class T, class U> T bar(U);<br>
+<br>
+  void test(A &a) {<br>
+    a[&foo];<br>
+    a[foo];<br>
+<br>
+    a[&bar<int>]; // expected-error {{no viable overloaded operator[]}}<br>
+    a[bar<int>]; // expected-error {{no viable overloaded operator[]}}<br>
+<br>
+    // If these fail, it's because we're not letting the overload<br>
+    // resolution for operator| resolve the overload of 'bar'.<br>
+    a[&bar<float>];<br>
+    a[bar<float>];<br>
+  }<br>
+}<br>
<br>
Modified: cfe/trunk/test/SemaObjCXX/<a href="http://properties.mm" target="_blank">properties.mm</a><br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/properties.mm?rev=176428&r1=176427&r2=176428&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/properties.mm?rev=176428&r1=176427&r2=176428&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/SemaObjCXX/<a href="http://properties.mm" target="_blank">properties.mm</a> (original)<br>
+++ cfe/trunk/test/SemaObjCXX/<a href="http://properties.mm" target="_blank">properties.mm</a> Sun Mar  3 19:30:55 2013<br>
@@ -129,3 +129,38 @@ extern void* VoidType;<br>
 extern decltype(TestNonTrivialObj.p1 = NonTrivial1())* VoidType;<br>
 extern decltype(TestNonTrivialObj.p2 = NonTrivial2())* VoidType;<br>
<br>
+// rdar://13332183<br>
+namespace test9 {<br>
+  struct CString {<br>
+    const char *_data;<br>
+    char operator[](int i) const { return _data[i]; }<br>
+  };<br>
+}<br>
+@interface Test9<br>
+@property test9::CString name;<br>
+@end<br>
+namespace test9 {<br>
+  char test(Test9 *t) {<br>
+    return <a href="http://t.name" target="_blank">t.name</a>[0];<br>
+  }<br>
+}<br>
+<br>
+namespace test10 {<br>
+  struct A { operator const char*(); };<br>
+  struct B { operator const char*(); };<br>
+}<br>
+@interface Test10<br>
+@property test10::A a;<br>
+@property test10::B b;<br>
+@property int index;<br>
+@end<br>
+namespace test10 {<br>
+  void test(Test10 *t) {<br>
+    (void) t.a[6];<br>
+    (void) 6[t.b];<br>
+    (void) "help"[t.index];<br>
+    (void) t.index["help"];<br>
+    (void) t.a[t.index];<br>
+    (void) t.index[t.b];<br>
+  }<br>
+}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br>