diff options
author | John McCall <rjmccall@apple.com> | 2013-03-04 01:30:55 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2013-03-04 01:30:55 +0000 |
commit | 7a534b94138ef2ad1a75b26b3b5bf1aa948d4121 (patch) | |
tree | eb515bbb206f6384b79a5ccd7a6e224f0c64e8a0 /lib/Sema/SemaExpr.cpp | |
parent | 0074d38bee15c25d3f91d4f16f223ed0dca3f33f (diff) |
Perform non-overload placeholder conversions on the operands
to a subscript operator.
rdar://13332183
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176428 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 55 |
1 files changed, 39 insertions, 16 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 65bdd2a47f..7dd17a028f 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3341,33 +3341,56 @@ static bool checkArithmeticOnObjCPointer(Sema &S, } 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) { // 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 |