diff options
| author | Douglas Gregor <dgregor@apple.com> | 2008-11-19 17:17:41 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2008-11-19 17:17:41 +0000 |
| commit | 40412acc0282908a2e76ec419890513065884547 (patch) | |
| tree | fefa44134d9058f9ab8d52b6553bca88ff2f9411 /clang/lib/Sema | |
| parent | 0f09564ffc47f55379498ef1ea9b23bbc2eb5027 (diff) | |
| download | bcm5719-llvm-40412acc0282908a2e76ec419890513065884547.tar.gz bcm5719-llvm-40412acc0282908a2e76ec419890513065884547.zip | |
Support overloading of the subscript operator[], including support for
built-in operator candidates. Test overloading of '&' and ','.
In C++, a comma expression is an lvalue if its right-hand
subexpression is an lvalue. Update Expr::isLvalue accordingly.
llvm-svn: 59643
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/Sema.h | 5 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 86 |
2 files changed, 87 insertions, 4 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index b10a98f0b3c..983fa306d2b 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/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/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index c7803722fe9..a780012235a 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/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); |

