[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