diff options
-rw-r--r-- | include/clang/AST/Expr.h | 23 | ||||
-rw-r--r-- | include/clang/AST/ExprCXX.h | 29 | ||||
-rw-r--r-- | include/clang/AST/StmtNodes.def | 1 | ||||
-rw-r--r-- | include/clang/Basic/OperatorKinds.def | 84 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 19 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 48 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 43 | ||||
-rw-r--r-- | lib/AST/StmtSerialization.cpp | 9 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 3 | ||||
-rw-r--r-- | lib/Basic/IdentifierTable.cpp | 13 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 12 |
13 files changed, 228 insertions, 64 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 6e376cedba..5255f18445 100644 --- a/include/clang/AST/Expr.h +++ b/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/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 37f892ce3d..c855089d8f 100644 --- a/include/clang/AST/ExprCXX.h +++ b/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/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def index ed1e6a9ccd..beb64c51f3 100644 --- a/include/clang/AST/StmtNodes.def +++ b/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/include/clang/Basic/OperatorKinds.def b/include/clang/Basic/OperatorKinds.def index bce64a7b6a..6881e4f876 100644 --- a/include/clang/Basic/OperatorKinds.def +++ b/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/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 249bebc91f..871dc4bb77 100644 --- a/lib/AST/Expr.cpp +++ b/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/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index ff97e688b8..22f30f451e 100644 --- a/lib/AST/ExprCXX.cpp +++ b/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/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index bbd53d0d49..cf6d4c0b90 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/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/lib/AST/StmtSerialization.cpp b/lib/AST/StmtSerialization.cpp index 667f597b8a..268922e481 100644 --- a/lib/AST/StmtSerialization.cpp +++ b/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/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index cb7c7fe3e1..545d869379 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/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/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp index b8684753b2..4d737c50bc 100644 --- a/lib/Basic/IdentifierTable.cpp +++ b/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/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index ad2f78b8e7..5f5001732c 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/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/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 6dd9fa7c4b..76835bc3ab 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/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/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index c9f311a204..686a8f4008 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/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 |