mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 00:06:06 +00:00
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. llvm-svn: 59306
This commit is contained in:
parent
5fe5933909
commit
993603d80d
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -90,6 +90,7 @@ STMT(TypesCompatibleExpr , Expr)
|
||||
STMT(ChooseExpr , Expr)
|
||||
|
||||
// C++ Expressions.
|
||||
STMT(CXXOperatorCallExpr , CallExpr)
|
||||
STMT(CXXNamedCastExpr , ExplicitCastExpr)
|
||||
STMT(CXXStaticCastExpr , CXXNamedCastExpr)
|
||||
STMT(CXXDynamicCastExpr , CXXNamedCastExpr)
|
||||
|
@ -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
|
||||
|
@ -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())));
|
||||
|
||||
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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() << '<';
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user