[cfe-commits] r59306 - in /cfe/trunk: include/clang/AST/Expr.h include/clang/AST/ExprCXX.h include/clang/AST/StmtNodes.def include/clang/Basic/OperatorKinds.def lib/AST/Expr.cpp lib/AST/ExprCXX.cpp lib/AST/StmtPrinter.cpp lib/AST/StmtSerialization.cpp lib/Analysis/GRExprEngine.cpp lib/Basic/IdentifierTable.cpp lib/CodeGen/CGExpr.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp

Douglas Gregor doug.gregor at gmail.com
Fri Nov 14 08:09:24 PST 2008


Author: dgregor
Date: Fri Nov 14 10:09:21 2008
New Revision: 59306

URL: http://llvm.org/viewvc/llvm-project?rev=59306&view=rev
Log:
Add a new expression node, CXXOperatorCallExpr, which expresses a
function call created in response to the use of operator syntax that
resolves to an overloaded operator in C++, e.g., "str1 +
str2" that resolves to std::operator+(str1, str2)". We now build a
CXXOperatorCallExpr in C++ when we pick an overloaded operator. (But
only for binary operators, where we actually implement overloading)

I decided *not* to refactor the current CallExpr to make it abstract
(with FunctionCallExpr and CXXOperatorCallExpr as derived
classes). Doing so would allow us to make CXXOperatorCallExpr a little
bit smaller, at the cost of making the argument and callee accessors
virtual. We won't know if this is going to be a win until we can parse
lots of C++ code to determine how much memory we'll save by making
this change vs. the performance penalty due to the extra virtual
calls.


Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/AST/StmtNodes.def
    cfe/trunk/include/clang/Basic/OperatorKinds.def
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/AST/StmtSerialization.cpp
    cfe/trunk/lib/Analysis/GRExprEngine.cpp
    cfe/trunk/lib/Basic/IdentifierTable.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=59306&r1=59305&r2=59306&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Fri Nov 14 10:09:21 2008
@@ -633,8 +633,12 @@
 };
 
 
-/// CallExpr - [C99 6.5.2.2] Function Calls.
-///
+/// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
+/// CallExpr itself represents a normal function call, e.g., "f(x, 2)", 
+/// while its subclasses may represent alternative syntax that (semantically)
+/// results in a function call. For example, CXXOperatorCallExpr is 
+/// a subclass for overloaded operator calls that use operator syntax, e.g.,
+/// "str1 + str2" to resolve to a function call.
 class CallExpr : public Expr {
   enum { FN=0, ARGS_START=1 };
   Stmt **SubExprs;
@@ -642,10 +646,15 @@
   SourceLocation RParenLoc;
   
   // This version of the ctor is for deserialization.
-  CallExpr(Stmt** subexprs, unsigned numargs, QualType t, 
+  CallExpr(StmtClass SC, Stmt** subexprs, unsigned numargs, QualType t, 
            SourceLocation rparenloc)
-  : Expr(CallExprClass,t), SubExprs(subexprs), 
+  : Expr(SC,t), SubExprs(subexprs), 
     NumArgs(numargs), RParenLoc(rparenloc) {}
+
+protected:
+  // This version of the constructor is for derived classes.
+  CallExpr(StmtClass SC, Expr *fn, Expr **args, unsigned numargs, QualType t, 
+           SourceLocation rparenloc);
   
 public:
   CallExpr(Expr *fn, Expr **args, unsigned numargs, QualType t, 
@@ -705,7 +714,8 @@
   }
   
   static bool classof(const Stmt *T) { 
-    return T->getStmtClass() == CallExprClass; 
+    return T->getStmtClass() == CallExprClass ||
+           T->getStmtClass() == CXXOperatorCallExprClass; 
   }
   static bool classof(const CallExpr *) { return true; }
   
@@ -714,7 +724,8 @@
   virtual child_iterator child_end();
   
   virtual void EmitImpl(llvm::Serializer& S) const;
-  static CallExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
+  static CallExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C, 
+                              StmtClass SC);
 };
 
 /// MemberExpr - [C99 6.5.2.3] Structure and Union Members.

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=59306&r1=59305&r2=59306&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Fri Nov 14 10:09:21 2008
@@ -23,6 +23,35 @@
 // C++ Expressions.
 //===--------------------------------------------------------------------===//
 
+/// CXXOperatorCallExpr - Represents a call to an overloaded operator
+/// written using operator syntax, e.g., "x + y" or "*p". While
+/// semantically equivalent to a normal call, this AST node provides
+/// better information about the syntactic representation of the call.
+class CXXOperatorCallExpr : public CallExpr {
+public:
+  CXXOperatorCallExpr(Expr *fn, Expr **args, unsigned numargs, QualType t,
+                      SourceLocation operatorloc)
+    : CallExpr(CXXOperatorCallExprClass, fn, args, numargs, t, operatorloc) { }
+
+  /// getOperator - Returns the kind of overloaded operator that this
+  /// expression refers to.
+  OverloadedOperatorKind getOperator() const;
+
+  /// getOperatorLoc - Returns the location of the operator symbol in
+  /// the expression. When @c getOperator()==OO_Call, this is the
+  /// location of the right parentheses; when @c
+  /// getOperator()==OO_Subscript, this is the location of the right
+  /// bracket.
+  SourceLocation getOperatorLoc() const { return getRParenLoc(); }
+
+  virtual SourceRange getSourceRange() const;
+  
+  static bool classof(const Stmt *T) { 
+    return T->getStmtClass() == CXXOperatorCallExprClass; 
+  }
+  static bool classof(const CXXOperatorCallExpr *) { return true; }
+};
+
 /// CXXNamedCastExpr - Abstract class common to all of the C++ "named"
 /// casts, @c static_cast, @c dynamic_cast, @c reinterpret_cast, or @c
 /// const_cast.

Modified: cfe/trunk/include/clang/AST/StmtNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtNodes.def?rev=59306&r1=59305&r2=59306&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/StmtNodes.def (original)
+++ cfe/trunk/include/clang/AST/StmtNodes.def Fri Nov 14 10:09:21 2008
@@ -90,6 +90,7 @@
 STMT(ChooseExpr           , Expr)
 
 // C++ Expressions.
+STMT(CXXOperatorCallExpr    , CallExpr)
 STMT(CXXNamedCastExpr       , ExplicitCastExpr)
 STMT(CXXStaticCastExpr      , CXXNamedCastExpr)
 STMT(CXXDynamicCastExpr     , CXXNamedCastExpr)

Modified: cfe/trunk/include/clang/Basic/OperatorKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OperatorKinds.def?rev=59306&r1=59305&r2=59306&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/OperatorKinds.def (original)
+++ cfe/trunk/include/clang/Basic/OperatorKinds.def Fri Nov 14 10:09:21 2008
@@ -56,48 +56,48 @@
     OVERLOADED_OPERATOR(Name,Spelling,unknown,Unary,Binary,MemberOnly)
 #endif
 
-OVERLOADED_OPERATOR_MULTI(New            , "operator new"                     , true , true , false)
-OVERLOADED_OPERATOR_MULTI(Delete         , "operator delete"                  , true , true , false)
-OVERLOADED_OPERATOR_MULTI(Array_New      , "operator new[]"                   , true , true , false)
-OVERLOADED_OPERATOR_MULTI(Array_Delete   , "operator delete[]"                , true , true , false)
-OVERLOADED_OPERATOR(Plus                 , "operator+"   , plus               , true , true , false)
-OVERLOADED_OPERATOR(Minus                , "operator-"   , minus              , true , true , false)
-OVERLOADED_OPERATOR(Star                 , "operator*"   , star               , true , true , false)
-OVERLOADED_OPERATOR(Slash                , "operator/"   , slash              , false, true , false)
-OVERLOADED_OPERATOR(Percent              , "operator%"   , percent            , false, true , false)
-OVERLOADED_OPERATOR(Caret                , "operator^"   , caret              , false, true , false)
-OVERLOADED_OPERATOR(Amp                  , "operator&"   , amp                , true , true , false)
-OVERLOADED_OPERATOR(Pipe                 , "operator|"   , pipe               , false, true , false)
-OVERLOADED_OPERATOR(Tilde                , "operator~"   , tilde              , true , false, false)
-OVERLOADED_OPERATOR(Exclaim              , "operator!"   , exclaim            , true , false, false)
-OVERLOADED_OPERATOR(Equal                , "operator="   , equal              , false, true , true)
-OVERLOADED_OPERATOR(Less                 , "operator<"   , less               , false, true , false)
-OVERLOADED_OPERATOR(Greater              , "operator>"   , greater            , false, true , false)
-OVERLOADED_OPERATOR(PlusEqual            , "operator+="  , plusequal          , false, true , false)
-OVERLOADED_OPERATOR(MinusEqual           , "operator-="  , minusequal         , false, true , false)
-OVERLOADED_OPERATOR(StarEqual            , "operator*="  , starequal          , false, true , false)
-OVERLOADED_OPERATOR(SlashEqual           , "operator/="  , slashequal         , false, true , false)
-OVERLOADED_OPERATOR(PercentEqual         , "operator%="  , percentequal       , false, true , false)
-OVERLOADED_OPERATOR(CaretEqual           , "operator^="  , caretequal         , false, true , false)
-OVERLOADED_OPERATOR(AmpEqual             , "operator&="  , ampequal           , false, true , false)
-OVERLOADED_OPERATOR(PipeEqual            , "operator|="  , pipeequal          , false, true , false)
-OVERLOADED_OPERATOR(LessLess             , "operator<<"  , lessless           , false, true , false)
-OVERLOADED_OPERATOR(GreaterGreater       , "operator>>"  , greatergreater     , false, true , false)
-OVERLOADED_OPERATOR(LessLessEqual        , "operator<<=" , lesslessequal      , false, true , false)
-OVERLOADED_OPERATOR(GreaterGreaterEqual  , "operator>>=" , greatergreaterequal, false, true , false)
-OVERLOADED_OPERATOR(EqualEqual           , "operator=="  , equalequal         , false, true , false)
-OVERLOADED_OPERATOR(ExclaimEqual         , "operator!="  , exclaimequal       , false, true , false)
-OVERLOADED_OPERATOR(LessEqual            , "operator<="  , lessequal          , false, true , false)
-OVERLOADED_OPERATOR(GreaterEqual         , "operator>="  , greaterequal       , false, true , false)
-OVERLOADED_OPERATOR(AmpAmp               , "operator&&"  , ampamp             , false, true , false)
-OVERLOADED_OPERATOR(PipePipe             , "operator||"  , pipepipe           , false, true , false)
-OVERLOADED_OPERATOR(PlusPlus             , "operator++"  , plusplus           , true , true , false)
-OVERLOADED_OPERATOR(MinusMinus           , "operator--"  , minusminus         , true , true , false)
-OVERLOADED_OPERATOR(Comma                , "operator,"   , comma              , false, true , false)
-OVERLOADED_OPERATOR(ArrowStar            , "operator->*" , arrowstar          , false, true , false)
-OVERLOADED_OPERATOR(Arrow                , "operator->"  , arrow              , true , false, true)
-OVERLOADED_OPERATOR_MULTI(Call           , "operator()"                       , true , true , true)
-OVERLOADED_OPERATOR_MULTI(Subscript      , "operator[]"                       , false, true , true)
+OVERLOADED_OPERATOR_MULTI(New            , "new"                     , true , true , false)
+OVERLOADED_OPERATOR_MULTI(Delete         , "delete"                  , true , true , false)
+OVERLOADED_OPERATOR_MULTI(Array_New      , "new[]"                   , true , true , false)
+OVERLOADED_OPERATOR_MULTI(Array_Delete   , "delete[]"                , true , true , false)
+OVERLOADED_OPERATOR(Plus                 , "+"   , plus               , true , true , false)
+OVERLOADED_OPERATOR(Minus                , "-"   , minus              , true , true , false)
+OVERLOADED_OPERATOR(Star                 , "*"   , star               , true , true , false)
+OVERLOADED_OPERATOR(Slash                , "/"   , slash              , false, true , false)
+OVERLOADED_OPERATOR(Percent              , "%"   , percent            , false, true , false)
+OVERLOADED_OPERATOR(Caret                , "^"   , caret              , false, true , false)
+OVERLOADED_OPERATOR(Amp                  , "&"   , amp                , true , true , false)
+OVERLOADED_OPERATOR(Pipe                 , "|"   , pipe               , false, true , false)
+OVERLOADED_OPERATOR(Tilde                , "~"   , tilde              , true , false, false)
+OVERLOADED_OPERATOR(Exclaim              , "!"   , exclaim            , true , false, false)
+OVERLOADED_OPERATOR(Equal                , "="   , equal              , false, true , true)
+OVERLOADED_OPERATOR(Less                 , "<"   , less               , false, true , false)
+OVERLOADED_OPERATOR(Greater              , ">"   , greater            , false, true , false)
+OVERLOADED_OPERATOR(PlusEqual            , "+="  , plusequal          , false, true , false)
+OVERLOADED_OPERATOR(MinusEqual           , "-="  , minusequal         , false, true , false)
+OVERLOADED_OPERATOR(StarEqual            , "*="  , starequal          , false, true , false)
+OVERLOADED_OPERATOR(SlashEqual           , "/="  , slashequal         , false, true , false)
+OVERLOADED_OPERATOR(PercentEqual         , "%="  , percentequal       , false, true , false)
+OVERLOADED_OPERATOR(CaretEqual           , "^="  , caretequal         , false, true , false)
+OVERLOADED_OPERATOR(AmpEqual             , "&="  , ampequal           , false, true , false)
+OVERLOADED_OPERATOR(PipeEqual            , "|="  , pipeequal          , false, true , false)
+OVERLOADED_OPERATOR(LessLess             , "<<"  , lessless           , false, true , false)
+OVERLOADED_OPERATOR(GreaterGreater       , ">>"  , greatergreater     , false, true , false)
+OVERLOADED_OPERATOR(LessLessEqual        , "<<=" , lesslessequal      , false, true , false)
+OVERLOADED_OPERATOR(GreaterGreaterEqual  , ">>=" , greatergreaterequal, false, true , false)
+OVERLOADED_OPERATOR(EqualEqual           , "=="  , equalequal         , false, true , false)
+OVERLOADED_OPERATOR(ExclaimEqual         , "!="  , exclaimequal       , false, true , false)
+OVERLOADED_OPERATOR(LessEqual            , "<="  , lessequal          , false, true , false)
+OVERLOADED_OPERATOR(GreaterEqual         , ">="  , greaterequal       , false, true , false)
+OVERLOADED_OPERATOR(AmpAmp               , "&&"  , ampamp             , false, true , false)
+OVERLOADED_OPERATOR(PipePipe             , "||"  , pipepipe           , false, true , false)
+OVERLOADED_OPERATOR(PlusPlus             , "++"  , plusplus           , true , true , false)
+OVERLOADED_OPERATOR(MinusMinus           , "--"  , minusminus         , true , true , false)
+OVERLOADED_OPERATOR(Comma                , ","   , comma              , false, true , false)
+OVERLOADED_OPERATOR(ArrowStar            , "->*" , arrowstar          , false, true , false)
+OVERLOADED_OPERATOR(Arrow                , "->"  , arrow              , true , false, true)
+OVERLOADED_OPERATOR_MULTI(Call           , "()"                       , true , true , true)
+OVERLOADED_OPERATOR_MULTI(Subscript      , "[]"                       , false, true , true)
 
 #undef OVERLOADED_OPERATOR_MULTI
 #undef OVERLOADED_OPERATOR

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=59306&r1=59305&r2=59306&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Fri Nov 14 10:09:21 2008
@@ -101,6 +101,15 @@
 // Postfix Operators.
 //===----------------------------------------------------------------------===//
 
+CallExpr::CallExpr(StmtClass SC, Expr *fn, Expr **args, unsigned numargs, 
+                   QualType t, SourceLocation rparenloc)
+  : Expr(SC, t), NumArgs(numargs) {
+  SubExprs = new Stmt*[numargs+1];
+  SubExprs[FN] = fn;
+  for (unsigned i = 0; i != numargs; ++i)
+    SubExprs[i+ARGS_START] = args[i];
+  RParenLoc = rparenloc;
+}
 
 CallExpr::CallExpr(Expr *fn, Expr **args, unsigned numargs, QualType t,
                    SourceLocation rparenloc)
@@ -285,6 +294,7 @@
     return getType().isVolatileQualified();
 
   case CallExprClass:
+  case CXXOperatorCallExprClass:
     // TODO: check attributes for pure/const.   "void foo() { strlen("bar"); }"
     // should warn.
     return true;
@@ -410,7 +420,8 @@
     //   An assignment expression [...] is not an lvalue.
     return LV_InvalidExpression;
   }
-  case CallExprClass: {
+  case CallExprClass: 
+  case CXXOperatorCallExprClass: {
     // C++ [expr.call]p10:
     //   A function call is an lvalue if and only if the result type
     //   is a reference.
@@ -586,7 +597,8 @@
   case CXXBoolLiteralExprClass:
   case AddrLabelExprClass:
     return true;
-  case CallExprClass: {
+  case CallExprClass: 
+  case CXXOperatorCallExprClass: {
     const CallExpr *CE = cast<CallExpr>(this);
 
     // Allow any constant foldable calls to builtins.
@@ -777,7 +789,8 @@
                                     T1.getUnqualifiedType());
     break;
   }
-  case CallExprClass: {
+  case CallExprClass: 
+  case CXXOperatorCallExprClass: {
     const CallExpr *CE = cast<CallExpr>(this);
     Result.zextOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(getType())));
     

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=59306&r1=59305&r2=59306&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Fri Nov 14 10:09:21 2008
@@ -11,6 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
 using namespace clang;
 
@@ -75,6 +77,52 @@
   return child_iterator();
 }
 
+OverloadedOperatorKind CXXOperatorCallExpr::getOperator() const {
+  // All simple function calls (e.g. func()) are implicitly cast to pointer to
+  // function. As a result, we try and obtain the DeclRefExpr from the 
+  // ImplicitCastExpr.
+  const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(getCallee());
+  if (!ICE) // FIXME: deal with more complex calls (e.g. (func)(), (*func)()).
+    return OO_None;
+  
+  const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr());
+  if (!DRE)
+    return OO_None;
+  
+  if (const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl()))
+    return FDecl->getIdentifier()->getOverloadedOperatorID();  
+  else if (const OverloadedFunctionDecl *Ovl 
+             = dyn_cast<OverloadedFunctionDecl>(DRE->getDecl()))
+    return Ovl->getIdentifier()->getOverloadedOperatorID();
+  else
+    return OO_None;
+}
+
+SourceRange CXXOperatorCallExpr::getSourceRange() const {
+  OverloadedOperatorKind Kind = getOperator();
+  if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) {
+    if (getNumArgs() == 1)
+      // Prefix operator
+      return SourceRange(getOperatorLoc(), 
+                         getArg(0)->getSourceRange().getEnd());
+    else
+      // Postfix operator
+      return SourceRange(getArg(0)->getSourceRange().getEnd(),
+                         getOperatorLoc());
+  } else if (Kind == OO_Call) {
+    return SourceRange(getArg(0)->getSourceRange().getBegin(), getRParenLoc());
+  } else if (Kind == OO_Subscript) {
+    return SourceRange(getArg(0)->getSourceRange().getBegin(), getRParenLoc());
+  } else if (getNumArgs() == 1) {
+    return SourceRange(getOperatorLoc(), getArg(0)->getSourceRange().getEnd());
+  } else if (getNumArgs() == 2) {
+    return SourceRange(getArg(0)->getSourceRange().getBegin(),
+                       getArg(1)->getSourceRange().getEnd());
+  } else {
+    return SourceRange();
+  }
+}
+
 //===----------------------------------------------------------------------===//
 //  Named casts
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=59306&r1=59305&r2=59306&view=diff

==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Fri Nov 14 10:09:21 2008
@@ -811,6 +811,49 @@
 }
 
 // C++
+void StmtPrinter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) {
+  const char *OpStrings[NUM_OVERLOADED_OPERATORS] = {
+    "",
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+    Spelling,
+#include "clang/Basic/OperatorKinds.def"
+  };
+
+  OverloadedOperatorKind Kind = Node->getOperator();
+  if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) {
+    if (Node->getNumArgs() == 1) {
+      OS << OpStrings[Kind] << ' ';
+      PrintExpr(Node->getArg(0));
+    } else {
+      PrintExpr(Node->getArg(0));
+      OS << ' ' << OpStrings[Kind];
+    }
+  } else if (Kind == OO_Call) {
+    PrintExpr(Node->getArg(0));
+    OS << '(';
+    for (unsigned ArgIdx = 1; ArgIdx < Node->getNumArgs(); ++ArgIdx) {
+      if (ArgIdx > 1)
+        OS << ", ";
+      if (!isa<CXXDefaultArgExpr>(Node->getArg(ArgIdx)))
+        PrintExpr(Node->getArg(ArgIdx));
+    }
+    OS << ')';
+  } else if (Kind == OO_Subscript) {
+    PrintExpr(Node->getArg(0));
+    OS << '[';
+    PrintExpr(Node->getArg(1));
+    OS << ']';
+  } else if (Node->getNumArgs() == 1) {
+    OS << OpStrings[Kind] << ' ';
+    PrintExpr(Node->getArg(0));
+  } else if (Node->getNumArgs() == 2) {
+    PrintExpr(Node->getArg(0));
+    OS << ' ' << OpStrings[Kind] << ' ';
+    PrintExpr(Node->getArg(1));
+  } else {
+    assert(false && "unknown overloaded operator");
+  }
+}
 
 void StmtPrinter::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) {
   OS << Node->getCastName() << '<';

Modified: cfe/trunk/lib/AST/StmtSerialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtSerialization.cpp?rev=59306&r1=59305&r2=59306&view=diff

==============================================================================
--- cfe/trunk/lib/AST/StmtSerialization.cpp (original)
+++ cfe/trunk/lib/AST/StmtSerialization.cpp Fri Nov 14 10:09:21 2008
@@ -53,7 +53,7 @@
       return BreakStmt::CreateImpl(D, C);
      
     case CallExprClass:
-      return CallExpr::CreateImpl(D, C);
+      return CallExpr::CreateImpl(D, C, CallExprClass);
       
     case CaseStmtClass:
       return CaseStmt::CreateImpl(D, C);
@@ -198,6 +198,9 @@
     //    C++
     //==--------------------------------------==//
       
+    case CXXOperatorCallExprClass:
+      return CXXOperatorCallExpr::CreateImpl(D, C, CXXOperatorCallExprClass);
+
     case CXXDefaultArgExprClass:
       return CXXDefaultArgExpr::CreateImpl(D, C);      
 
@@ -361,14 +364,14 @@
   S.BatchEmitOwnedPtrs(NumArgs+1, SubExprs);  
 }
 
-CallExpr* CallExpr::CreateImpl(Deserializer& D, ASTContext& C) {
+CallExpr* CallExpr::CreateImpl(Deserializer& D, ASTContext& C, StmtClass SC) {
   QualType t = QualType::ReadVal(D);
   SourceLocation L = SourceLocation::ReadVal(D);
   unsigned NumArgs = D.ReadInt();
   Stmt** SubExprs = new Stmt*[NumArgs+1];
   D.BatchReadOwnedPtrs(NumArgs+1, SubExprs, C);
 
-  return new CallExpr(SubExprs,NumArgs,t,L);  
+  return new CallExpr(SC, SubExprs,NumArgs,t,L);  
 }
 
 void CaseStmt::EmitImpl(Serializer& S) const {

Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=59306&r1=59305&r2=59306&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Fri Nov 14 10:09:21 2008
@@ -311,7 +311,8 @@
       break;
     }
       
-    case Stmt::CallExprClass: {
+    case Stmt::CallExprClass:
+    case Stmt::CXXOperatorCallExprClass: {
       CallExpr* C = cast<CallExpr>(S);
       VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst);
       break;      

Modified: cfe/trunk/lib/Basic/IdentifierTable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/IdentifierTable.cpp?rev=59306&r1=59305&r2=59306&view=diff

==============================================================================
--- cfe/trunk/lib/Basic/IdentifierTable.cpp (original)
+++ cfe/trunk/lib/Basic/IdentifierTable.cpp Fri Nov 14 10:09:21 2008
@@ -189,11 +189,22 @@
 #include "clang/Basic/TokenKinds.def"
 }
 
+/// addOperatorPrefix - Add the prefix "operator" (possible with a
+/// space after it) to the given operator symbol, and return the
+/// result.
+static std::string addOperatorPrefix(const char* Symbol) {
+  std::string result = "operator";
+  if (Symbol[0] >= 'a' && Symbol[0] <= 'z')
+    result += ' ';
+  result += Symbol;
+  return result;
+}
+
 /// AddOverloadedOperators - Register the name of all C++ overloadable
 /// operators ("operator+", "operator[]", etc.)
 void IdentifierTable::AddOverloadedOperators() {
 #define OVERLOADED_OPERATOR(Name,Spelling,Token, Unary, Binary, MemberOnly) \
-  OverloadedOperators[OO_##Name] = &get(Spelling);                      \
+  OverloadedOperators[OO_##Name] = &get(addOperatorPrefix(Spelling));   \
   OverloadedOperators[OO_##Name]->setOverloadedOperatorID(OO_##Name);
 #include "clang/Basic/OperatorKinds.def"
 }

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=59306&r1=59305&r2=59306&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Fri Nov 14 10:09:21 2008
@@ -113,7 +113,9 @@
 
   case Expr::BinaryOperatorClass: 
     return EmitBinaryOperatorLValue(cast<BinaryOperator>(E));
-  case Expr::CallExprClass: return EmitCallExprLValue(cast<CallExpr>(E));
+  case Expr::CallExprClass: 
+  case Expr::CXXOperatorCallExprClass:
+    return EmitCallExprLValue(cast<CallExpr>(E));
   case Expr::DeclRefExprClass: return EmitDeclRefLValue(cast<DeclRefExpr>(E));
   case Expr::ParenExprClass:return EmitLValue(cast<ParenExpr>(E)->getSubExpr());
   case Expr::PredefinedExprClass:

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=59306&r1=59305&r2=59306&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Nov 14 10:09:21 2008
@@ -1237,6 +1237,7 @@
   case Expr::ObjCStringLiteralClass:
     return false;
   case Expr::CallExprClass:
+  case Expr::CXXOperatorCallExprClass:
     // __builtin___CFStringMakeConstantString is a valid constant l-value.
     if (cast<CallExpr>(Init)->isBuiltinCall() == 
            Builtin::BI__builtin___CFStringMakeConstantString)
@@ -1432,7 +1433,8 @@
   case Expr::TypesCompatibleExprClass:
   case Expr::CXXBoolLiteralExprClass:
     return false;
-  case Expr::CallExprClass: {
+  case Expr::CallExprClass: 
+  case Expr::CXXOperatorCallExprClass: {
     const CallExpr *CE = cast<CallExpr>(Init);
 
     // Allow any constant foldable calls to builtins.

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=59306&r1=59305&r2=59306&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Nov 14 10:09:21 2008
@@ -2851,12 +2851,12 @@
         ResultTy = ResultTy.getNonReferenceType();
         
         // Build the actual expression node.
-        // FIXME: We lose the fact that we have a function here!
-        if (Opc > BinaryOperator::Assign && Opc <= BinaryOperator::OrAssign)
-          return new CompoundAssignOperator(lhs, rhs, Opc, ResultTy, ResultTy,
-                                            TokLoc);
-        else
-          return new BinaryOperator(lhs, rhs, Opc, ResultTy, TokLoc);
+        Expr *FnExpr = new DeclRefExpr(FnDecl, FnDecl->getType(), 
+                                       SourceLocation());
+        UsualUnaryConversions(FnExpr);
+
+        Expr *Args[2] = { lhs, rhs };
+        return new CXXOperatorCallExpr(FnExpr, Args, 2, ResultTy, TokLoc);
       } else {
         // We matched a built-in operator. Convert the arguments, then
         // break out so that we will build the appropriate built-in





More information about the cfe-commits mailing list