diff options
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 55 |
1 files changed, 39 insertions, 16 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 65bdd2a47fb..7dd17a028f6 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/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 |