[cfe-commits] r59643 - in /cfe/trunk: Driver/PrintParserCallbacks.cpp include/clang/Parse/Action.h lib/AST/Expr.cpp lib/Parse/ParseExpr.cpp lib/Sema/Sema.h lib/Sema/SemaExpr.cpp test/SemaCXX/overloaded-builtin-operators.cpp test/SemaCXX/overloaded-operator.cpp www/cxx_status.html
Douglas Gregor
doug.gregor at gmail.com
Wed Nov 19 09:17:42 PST 2008
Author: dgregor
Date: Wed Nov 19 11:17:41 2008
New Revision: 59643
URL: http://llvm.org/viewvc/llvm-project?rev=59643&view=rev
Log:
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.
Modified:
cfe/trunk/Driver/PrintParserCallbacks.cpp
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/test/SemaCXX/overloaded-builtin-operators.cpp
cfe/trunk/test/SemaCXX/overloaded-operator.cpp
cfe/trunk/www/cxx_status.html
Modified: cfe/trunk/Driver/PrintParserCallbacks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/PrintParserCallbacks.cpp?rev=59643&r1=59642&r2=59643&view=diff
==============================================================================
--- cfe/trunk/Driver/PrintParserCallbacks.cpp (original)
+++ cfe/trunk/Driver/PrintParserCallbacks.cpp Wed Nov 19 11:17:41 2008
@@ -441,8 +441,9 @@
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;
}
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=59643&r1=59642&r2=59643&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Wed Nov 19 11:17:41 2008
@@ -513,7 +513,8 @@
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;
}
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=59643&r1=59642&r2=59643&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Wed Nov 19 11:17:41 2008
@@ -412,6 +412,11 @@
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;
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=59643&r1=59642&r2=59643&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Wed Nov 19 11:17:41 2008
@@ -672,7 +672,8 @@
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);
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=59643&r1=59642&r2=59643&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Nov 19 11:17:41 2008
@@ -652,8 +652,9 @@
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,
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=59643&r1=59642&r2=59643&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Nov 19 11:17:41 2008
@@ -861,10 +861,93 @@
}
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 @@
// 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);
Modified: cfe/trunk/test/SemaCXX/overloaded-builtin-operators.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overloaded-builtin-operators.cpp?rev=59643&r1=59642&r2=59643&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/overloaded-builtin-operators.cpp (original)
+++ cfe/trunk/test/SemaCXX/overloaded-builtin-operators.cpp Wed Nov 19 11:17:41 2008
@@ -113,5 +113,9 @@
int volatile *vip2 = +vip;
int i1 = +sr;
int i2 = -sr;
+
+ // C++ [over.built]p13:
+ int volatile &ivr2 = vip[17];
+ int const &icr2 = 17[cip];
}
Modified: cfe/trunk/test/SemaCXX/overloaded-operator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overloaded-operator.cpp?rev=59643&r1=59642&r2=59643&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/overloaded-operator.cpp (original)
+++ cfe/trunk/test/SemaCXX/overloaded-operator.cpp Wed Nov 19 11:17:41 2008
@@ -97,3 +97,27 @@
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);
+}
Modified: cfe/trunk/www/cxx_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=59643&r1=59642&r2=59643&view=diff
==============================================================================
--- cfe/trunk/www/cxx_status.html (original)
+++ cfe/trunk/www/cxx_status.html Wed Nov 19 11:17:41 2008
@@ -981,7 +981,7 @@
<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>
More information about the cfe-commits
mailing list