On Sun, Mar 3, 2013 at 5:30 PM, John McCall <[email protected]> wrote:
> Author: rjmccall > Date: Sun Mar 3 19:30:55 2013 > New Revision: 176428 > > URL: http://llvm.org/viewvc/llvm-project?rev=176428&view=rev > Log: > Perform non-overload placeholder conversions on the operands > to a subscript operator. > > rdar://13332183 > > Modified: > cfe/trunk/lib/Sema/SemaExpr.cpp > cfe/trunk/test/SemaCXX/overloaded-operator.cpp > cfe/trunk/test/SemaObjCXX/properties.mm > > Modified: cfe/trunk/lib/Sema/SemaExpr.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=176428&r1=176427&r2=176428&view=diff > > ============================================================================== > --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) > +++ cfe/trunk/lib/Sema/SemaExpr.cpp Sun Mar 3 19:30:55 2013 > @@ -3341,33 +3341,56 @@ static bool checkArithmeticOnObjCPointer > } > > ExprResult > -Sema::ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc, > - Expr *Idx, SourceLocation RLoc) { > +Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc, > + Expr *idx, SourceLocation rbLoc) { > Why the conversion away from the coding-style-approved VariableCapitalization? > // Since this might be a postfix expression, get rid of ParenListExprs. > - ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base); > - if (Result.isInvalid()) return ExprError(); > - Base = Result.take(); > + if (isa<ParenListExpr>(base)) { > + ExprResult result = MaybeConvertParenListExprToParenExpr(S, base); > + if (result.isInvalid()) return ExprError(); > + base = result.take(); > + } > > - Expr *LHSExp = Base, *RHSExp = Idx; > + // Handle any non-overload placeholder types in the base and index > + // expressions. We can't handle overloads here because the other > + // operand might be an overloadable type, in which case the overload > + // resolution for the operator overload should get the first crack > + // at the overload. > + if (base->getType()->isNonOverloadPlaceholderType()) { > + ExprResult result = CheckPlaceholderExpr(base); > + if (result.isInvalid()) return ExprError(); > + base = result.take(); > + } > + if (idx->getType()->isNonOverloadPlaceholderType()) { > + ExprResult result = CheckPlaceholderExpr(idx); > + if (result.isInvalid()) return ExprError(); > + idx = result.take(); > + } > > + // Build an unanalyzed expression if either operand is type-dependent. > if (getLangOpts().CPlusPlus && > - (LHSExp->isTypeDependent() || RHSExp->isTypeDependent())) { > - return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp, > + (base->isTypeDependent() || idx->isTypeDependent())) { > + return Owned(new (Context) ArraySubscriptExpr(base, idx, > Context.DependentTy, > VK_LValue, OK_Ordinary, > - RLoc)); > + rbLoc)); > } > > + // Use C++ overloaded-operator rules if either operand has record > + // type. The spec says to do this if either type is *overloadable*, > + // but enum types can't declare subscript operators or conversion > + // operators, so there's nothing interesting for overload resolution > + // to do if there aren't any record types involved. > + // > + // ObjC pointers have their own subscripting logic that is not tied > + // to overload resolution and so should not take this path. > if (getLangOpts().CPlusPlus && > - (LHSExp->getType()->isRecordType() || > - LHSExp->getType()->isEnumeralType() || > - RHSExp->getType()->isRecordType() || > - RHSExp->getType()->isEnumeralType()) && > - !LHSExp->getType()->isObjCObjectPointerType()) { > - return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, Base, Idx); > + (base->getType()->isRecordType() || > + (!base->getType()->isObjCObjectPointerType() && > + idx->getType()->isRecordType()))) { > + return CreateOverloadedArraySubscriptExpr(lbLoc, rbLoc, base, idx); > } > > - return CreateBuiltinArraySubscriptExpr(Base, LLoc, Idx, RLoc); > + return CreateBuiltinArraySubscriptExpr(base, lbLoc, idx, rbLoc); > } > > ExprResult > > Modified: cfe/trunk/test/SemaCXX/overloaded-operator.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overloaded-operator.cpp?rev=176428&r1=176427&r2=176428&view=diff > > ============================================================================== > --- cfe/trunk/test/SemaCXX/overloaded-operator.cpp (original) > +++ cfe/trunk/test/SemaCXX/overloaded-operator.cpp Sun Mar 3 19:30:55 2013 > @@ -415,3 +415,28 @@ namespace PR11784 { > void f(int); > void g() { A x; x = f; } > } > + > +namespace test10 { > + struct A { > + void operator[](float (*fn)(int)); // expected-note 2 {{not viable: > no overload of 'bar' matching 'float (*)(int)'}} > + }; > + > + float foo(int); > + float foo(float); > + > + template <class T> T bar(T); > + template <class T, class U> T bar(U); > + > + void test(A &a) { > + a[&foo]; > + a[foo]; > + > + a[&bar<int>]; // expected-error {{no viable overloaded operator[]}} > + a[bar<int>]; // expected-error {{no viable overloaded operator[]}} > + > + // If these fail, it's because we're not letting the overload > + // resolution for operator| resolve the overload of 'bar'. > + a[&bar<float>]; > + a[bar<float>]; > + } > +} > > Modified: cfe/trunk/test/SemaObjCXX/properties.mm > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/properties.mm?rev=176428&r1=176427&r2=176428&view=diff > > ============================================================================== > --- cfe/trunk/test/SemaObjCXX/properties.mm (original) > +++ cfe/trunk/test/SemaObjCXX/properties.mm Sun Mar 3 19:30:55 2013 > @@ -129,3 +129,38 @@ extern void* VoidType; > extern decltype(TestNonTrivialObj.p1 = NonTrivial1())* VoidType; > extern decltype(TestNonTrivialObj.p2 = NonTrivial2())* VoidType; > > +// rdar://13332183 > +namespace test9 { > + struct CString { > + const char *_data; > + char operator[](int i) const { return _data[i]; } > + }; > +} > +@interface Test9 > +@property test9::CString name; > +@end > +namespace test9 { > + char test(Test9 *t) { > + return t.name[0]; > + } > +} > + > +namespace test10 { > + struct A { operator const char*(); }; > + struct B { operator const char*(); }; > +} > +@interface Test10 > +@property test10::A a; > +@property test10::B b; > +@property int index; > +@end > +namespace test10 { > + void test(Test10 *t) { > + (void) t.a[6]; > + (void) 6[t.b]; > + (void) "help"[t.index]; > + (void) t.index["help"]; > + (void) t.a[t.index]; > + (void) t.index[t.b]; > + } > +} > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
