r176428 - Perform non-overload placeholder conversions on the operands

Richard Smith richard at metafoo.co.uk
Mon Mar 4 14:54:53 PST 2013


On Sun, Mar 3, 2013 at 5:30 PM, John McCall <rjmccall at apple.com> 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]; }
> +  };
> +}
> + at interface Test9
> + at property test9::CString name;
> + at end
> +namespace test9 {
> +  char test(Test9 *t) {
> +    return t.name[0];
> +  }
> +}
> +
> +namespace test10 {
> +  struct A { operator const char*(); };
> +  struct B { operator const char*(); };
> +}
> + at interface Test10
> + at property test10::A a;
> + at property test10::B b;
> + at property int index;
> + at 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
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130304/e860ba9f/attachment.html>


More information about the cfe-commits mailing list