diff options
| -rw-r--r-- | clang/include/clang/AST/Expr.h | 23 | ||||
| -rw-r--r-- | clang/include/clang/AST/ExprCXX.h | 29 | ||||
| -rw-r--r-- | clang/include/clang/AST/StmtNodes.def | 1 | ||||
| -rw-r--r-- | clang/include/clang/Basic/OperatorKinds.def | 84 | ||||
| -rw-r--r-- | clang/lib/AST/Expr.cpp | 19 | ||||
| -rw-r--r-- | clang/lib/AST/ExprCXX.cpp | 48 | ||||
| -rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 43 | ||||
| -rw-r--r-- | clang/lib/AST/StmtSerialization.cpp | 9 | ||||
| -rw-r--r-- | clang/lib/Analysis/GRExprEngine.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/Basic/IdentifierTable.cpp | 13 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 12 | 
13 files changed, 228 insertions, 64 deletions
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 6e376cedba4..5255f18445e 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -633,8 +633,12 @@ public:  }; -/// 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 @@ class CallExpr : public Expr {    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 @@ public:    }    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 @@ public:    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. diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 37f892ce3da..c855089d8f5 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -23,6 +23,35 @@ namespace clang {  // 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. diff --git a/clang/include/clang/AST/StmtNodes.def b/clang/include/clang/AST/StmtNodes.def index ed1e6a9ccd7..beb64c51f31 100644 --- a/clang/include/clang/AST/StmtNodes.def +++ b/clang/include/clang/AST/StmtNodes.def @@ -90,6 +90,7 @@ STMT(TypesCompatibleExpr  , Expr)  STMT(ChooseExpr           , Expr)  // C++ Expressions. +STMT(CXXOperatorCallExpr    , CallExpr)  STMT(CXXNamedCastExpr       , ExplicitCastExpr)  STMT(CXXStaticCastExpr      , CXXNamedCastExpr)  STMT(CXXDynamicCastExpr     , CXXNamedCastExpr) diff --git a/clang/include/clang/Basic/OperatorKinds.def b/clang/include/clang/Basic/OperatorKinds.def index bce64a7b6ab..6881e4f8763 100644 --- a/clang/include/clang/Basic/OperatorKinds.def +++ b/clang/include/clang/Basic/OperatorKinds.def @@ -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 diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 249bebc91fc..871dc4bb77a 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -101,6 +101,15 @@ const char *UnaryOperator::getOpcodeStr(Opcode Op) {  // 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 @@ bool Expr::hasLocalSideEffect() const {      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 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const {      //   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 @@ bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const {    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 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,                                      T1.getUnqualifiedType());      break;    } -  case CallExprClass: { +  case CallExprClass:  +  case CXXOperatorCallExprClass: {      const CallExpr *CE = cast<CallExpr>(this);      Result.zextOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(getType()))); diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index ff97e688b8d..22f30f451e5 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -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 @@ Stmt::child_iterator CXXConditionDeclExpr::child_end() {    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  //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index bbd53d0d494..cf6d4c0b901 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -811,6 +811,49 @@ void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) {  }  // 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() << '<'; diff --git a/clang/lib/AST/StmtSerialization.cpp b/clang/lib/AST/StmtSerialization.cpp index 667f597b8ab..268922e4813 100644 --- a/clang/lib/AST/StmtSerialization.cpp +++ b/clang/lib/AST/StmtSerialization.cpp @@ -53,7 +53,7 @@ Stmt* Stmt::Create(Deserializer& D, ASTContext& C) {        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 @@ Stmt* Stmt::Create(Deserializer& D, ASTContext& C) {      //    C++      //==--------------------------------------==// +    case CXXOperatorCallExprClass: +      return CXXOperatorCallExpr::CreateImpl(D, C, CXXOperatorCallExprClass); +      case CXXDefaultArgExprClass:        return CXXDefaultArgExpr::CreateImpl(D, C);       @@ -361,14 +364,14 @@ void CallExpr::EmitImpl(Serializer& S) const {    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 { diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp index cb7c7fe3e18..545d869379d 100644 --- a/clang/lib/Analysis/GRExprEngine.cpp +++ b/clang/lib/Analysis/GRExprEngine.cpp @@ -311,7 +311,8 @@ void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) {        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;       diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp index b8684753b2c..4d737c50bc0 100644 --- a/clang/lib/Basic/IdentifierTable.cpp +++ b/clang/lib/Basic/IdentifierTable.cpp @@ -189,11 +189,22 @@ void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {  #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"  } diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index ad2f78b8e77..5f5001732cd 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -113,7 +113,9 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {    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: diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 6dd9fa7c4bc..76835bc3abc 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1237,6 +1237,7 @@ bool Sema::CheckAddressConstantExpression(const Expr* Init) {    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 @@ bool Sema::CheckArithmeticConstantExpression(const Expr* Init) {    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. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index c9f311a204a..686a8f40083 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2851,12 +2851,12 @@ Action::ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,          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  | 

