diff options
-rw-r--r-- | Driver/PrintParserCallbacks.cpp | 5 | ||||
-rw-r--r-- | include/clang/Parse/Action.h | 3 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 5 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 5 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 86 | ||||
-rw-r--r-- | test/SemaCXX/overloaded-builtin-operators.cpp | 4 | ||||
-rw-r--r-- | test/SemaCXX/overloaded-operator.cpp | 24 | ||||
-rw-r--r-- | www/cxx_status.html | 2 |
9 files changed, 128 insertions, 9 deletions
diff --git a/Driver/PrintParserCallbacks.cpp b/Driver/PrintParserCallbacks.cpp index 2a85f64646..2ee113fcda 100644 --- a/Driver/PrintParserCallbacks.cpp +++ b/Driver/PrintParserCallbacks.cpp @@ -441,8 +441,9 @@ namespace { llvm::cout << __FUNCTION__ << "\n"; return 0; } - virtual ExprResult ActOnArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc, - ExprTy *Idx, SourceLocation RLoc) { + virtual ExprResult ActOnArraySubscriptExpr(Scope *S, ExprTy *Base, + SourceLocation LLoc, ExprTy *Idx, + SourceLocation RLoc) { llvm::cout << __FUNCTION__ << "\n"; return 0; } diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 7178543003..d662529217 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -513,7 +513,8 @@ public: tok::TokenKind Kind, ExprTy *Input) { return 0; } - virtual ExprResult ActOnArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc, + virtual ExprResult ActOnArraySubscriptExpr(Scope *S, + ExprTy *Base, SourceLocation LLoc, ExprTy *Idx, SourceLocation RLoc) { return 0; } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index a179af8b14..061402076e 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -412,6 +412,11 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const { case BinaryOperatorClass: case CompoundAssignOperatorClass: { const BinaryOperator *BinOp = cast<BinaryOperator>(this); + + if (Ctx.getLangOptions().CPlusPlus && // C++ [expr.comma]p1 + BinOp->getOpcode() == BinaryOperator::Comma) + return BinOp->getRHS()->isLvalue(Ctx); + if (!BinOp->isAssignmentOp()) return LV_InvalidExpression; diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 5f36f0bb27..74b0715de2 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -672,7 +672,8 @@ Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { SourceLocation RLoc = Tok.getLocation(); if (!LHS.isInvalid && !Idx.isInvalid && Tok.is(tok::r_square)) - LHS = Actions.ActOnArraySubscriptExpr(LHS.Val, Loc, Idx.Val, RLoc); + LHS = Actions.ActOnArraySubscriptExpr(CurScope, LHS.Val, Loc, + Idx.Val, RLoc); else LHS = ExprResult(true); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index b10a98f0b3..983fa306d2 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -652,8 +652,9 @@ public: virtual ExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Kind, ExprTy *Input); - virtual ExprResult ActOnArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc, - ExprTy *Idx, SourceLocation RLoc); + virtual ExprResult ActOnArraySubscriptExpr(Scope *S, ExprTy *Base, + SourceLocation LLoc, ExprTy *Idx, + SourceLocation RLoc); virtual ExprResult ActOnMemberReferenceExpr(ExprTy *Base,SourceLocation OpLoc, tok::TokenKind OpKind, SourceLocation MemberLoc, diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index c7803722fe..a780012235 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -861,10 +861,93 @@ Action::ExprResult Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, } Action::ExprResult Sema:: -ActOnArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc, +ActOnArraySubscriptExpr(Scope *S, ExprTy *Base, SourceLocation LLoc, ExprTy *Idx, SourceLocation RLoc) { Expr *LHSExp = static_cast<Expr*>(Base), *RHSExp = static_cast<Expr*>(Idx); + if (getLangOptions().CPlusPlus && + LHSExp->getType()->isRecordType() || + LHSExp->getType()->isEnumeralType() || + RHSExp->getType()->isRecordType() || + RHSExp->getType()->isRecordType()) { + // Add the appropriate overloaded operators (C++ [over.match.oper]) + // to the candidate set. + OverloadCandidateSet CandidateSet; + Expr *Args[2] = { LHSExp, RHSExp }; + AddOperatorCandidates(OO_Subscript, S, Args, 2, CandidateSet); + + // Perform overload resolution. + OverloadCandidateSet::iterator Best; + switch (BestViableFunction(CandidateSet, Best)) { + case OR_Success: { + // We found a built-in operator or an overloaded operator. + FunctionDecl *FnDecl = Best->Function; + + if (FnDecl) { + // We matched an overloaded operator. Build a call to that + // operator. + + // Convert the arguments. + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { + if (PerformObjectArgumentInitialization(LHSExp, Method) || + PerformCopyInitialization(RHSExp, + FnDecl->getParamDecl(0)->getType(), + "passing")) + return true; + } else { + // Convert the arguments. + if (PerformCopyInitialization(LHSExp, + FnDecl->getParamDecl(0)->getType(), + "passing") || + PerformCopyInitialization(RHSExp, + FnDecl->getParamDecl(1)->getType(), + "passing")) + return true; + } + + // Determine the result type + QualType ResultTy + = FnDecl->getType()->getAsFunctionType()->getResultType(); + ResultTy = ResultTy.getNonReferenceType(); + + // Build the actual expression node. + Expr *FnExpr = new DeclRefExpr(FnDecl, FnDecl->getType(), + SourceLocation()); + UsualUnaryConversions(FnExpr); + + return new CXXOperatorCallExpr(FnExpr, Args, 2, ResultTy, LLoc); + } else { + // We matched a built-in operator. Convert the arguments, then + // break out so that we will build the appropriate built-in + // operator node. + if (PerformCopyInitialization(LHSExp, Best->BuiltinTypes.ParamTypes[0], + "passing") || + PerformCopyInitialization(RHSExp, Best->BuiltinTypes.ParamTypes[1], + "passing")) + return true; + + break; + } + } + + case OR_No_Viable_Function: + // No viable function; fall through to handling this as a + // built-in operator, which will produce an error message for us. + break; + + case OR_Ambiguous: + Diag(LLoc, diag::err_ovl_ambiguous_oper) + << "[]" + << LHSExp->getSourceRange() << RHSExp->getSourceRange(); + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); + return true; + } + + // Either we found no viable overloaded operator or we matched a + // built-in operator. In either case, fall through to trying to + // build a built-in operation. + } + // Perform default conversions. DefaultFunctionArrayConversion(LHSExp); DefaultFunctionArrayConversion(RHSExp); @@ -3009,7 +3092,6 @@ Action::ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, // built-in operator. In either case, fall through to trying to // build a built-in operation. } - // Build a built-in binary operation. return CreateBuiltinBinOp(TokLoc, Opc, lhs, rhs); diff --git a/test/SemaCXX/overloaded-builtin-operators.cpp b/test/SemaCXX/overloaded-builtin-operators.cpp index 29d721c45b..41509f96e7 100644 --- a/test/SemaCXX/overloaded-builtin-operators.cpp +++ b/test/SemaCXX/overloaded-builtin-operators.cpp @@ -113,5 +113,9 @@ void test_with_ptrs(VolatileIntPtr vip, ConstIntPtr cip, ShortRef sr, int volatile *vip2 = +vip; int i1 = +sr; int i2 = -sr; + + // C++ [over.built]p13: + int volatile &ivr2 = vip[17]; + int const &icr2 = 17[cip]; } diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp index 2948656818..1eb86bd1aa 100644 --- a/test/SemaCXX/overloaded-operator.cpp +++ b/test/SemaCXX/overloaded-operator.cpp @@ -97,3 +97,27 @@ void test_smartptr(SmartPtr ptr, const SmartPtr cptr) { int &ir = *ptr; // FIXME: reinstate long &lr = *cptr; } + + +struct ArrayLike { + int& operator[](int); +}; + +void test_arraylike(ArrayLike a) { + int& ir = a[17]; +} + +struct SmartRef { + int* operator&(); +}; + +void test_smartref(SmartRef r) { + int* ip = &r; +} + +bool& operator,(X, Y); + +void test_comma(X x, Y y) { + bool& b1 = (x, y); + X& xr = (x, x); +} diff --git a/www/cxx_status.html b/www/cxx_status.html index 7c51fb387d..6db2840b7a 100644 --- a/www/cxx_status.html +++ b/www/cxx_status.html @@ -981,7 +981,7 @@ welcome!</p> <td> 13.5.5 [over.sub]</td>
<td class="na" align="center">N/A</td>
<td class="advanced" align="center"></td>
- <td class="basic" align="center"></td>
+ <td class="advanced" align="center"></td>
<td class="broken" align="center"></td>
<td></td>
</tr>
|