Store the source range of a CXXOperatorCallExpr in the Expr object instead of
calculating it recursively. boost::assign::tuple_list_of uses the trick of chaining call operator expressions in order to declare a "list of tuples", e.g: std::vector<tuple> v = boost::assign::tuple_list_of(1, "foo")(2, "bar")(3, "qqq"); Due to CXXOperatorCallExpr calculating its source range recursively we would get significant slowdowns with a large number of chained call operator expressions and the potential for stack overflow. rdar://11350116 llvm-svn: 155848
This commit is contained in:
parent
d0d5ec4a38
commit
d8e076972f
|
@ -50,14 +50,18 @@ class TemplateArgumentListInfo;
|
|||
class CXXOperatorCallExpr : public CallExpr {
|
||||
/// \brief The overloaded operator.
|
||||
OverloadedOperatorKind Operator;
|
||||
SourceRange Range;
|
||||
|
||||
SourceRange getSourceRangeImpl() const LLVM_READONLY;
|
||||
public:
|
||||
CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn,
|
||||
Expr **args, unsigned numargs, QualType t,
|
||||
ExprValueKind VK, SourceLocation operatorloc)
|
||||
: CallExpr(C, CXXOperatorCallExprClass, fn, 0, args, numargs, t, VK,
|
||||
operatorloc),
|
||||
Operator(Op) {}
|
||||
Operator(Op) {
|
||||
Range = getSourceRangeImpl();
|
||||
}
|
||||
explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) :
|
||||
CallExpr(C, CXXOperatorCallExprClass, Empty) { }
|
||||
|
||||
|
@ -65,7 +69,6 @@ public:
|
|||
/// getOperator - Returns the kind of overloaded operator that this
|
||||
/// expression refers to.
|
||||
OverloadedOperatorKind getOperator() const { return Operator; }
|
||||
void setOperator(OverloadedOperatorKind Kind) { Operator = Kind; }
|
||||
|
||||
/// getOperatorLoc - Returns the location of the operator symbol in
|
||||
/// the expression. When @c getOperator()==OO_Call, this is the
|
||||
|
@ -74,12 +77,15 @@ public:
|
|||
/// bracket.
|
||||
SourceLocation getOperatorLoc() const { return getRParenLoc(); }
|
||||
|
||||
SourceRange getSourceRange() const LLVM_READONLY;
|
||||
SourceRange getSourceRange() const { return Range; }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CXXOperatorCallExprClass;
|
||||
}
|
||||
static bool classof(const CXXOperatorCallExpr *) { return true; }
|
||||
|
||||
friend class ASTStmtReader;
|
||||
friend class ASTStmtWriter;
|
||||
};
|
||||
|
||||
/// CXXMemberCallExpr - Represents a call to a member function that
|
||||
|
|
|
@ -415,7 +415,7 @@ SourceRange CXXConstructExpr::getSourceRange() const {
|
|||
return SourceRange(Loc, End);
|
||||
}
|
||||
|
||||
SourceRange CXXOperatorCallExpr::getSourceRange() const {
|
||||
SourceRange CXXOperatorCallExpr::getSourceRangeImpl() const {
|
||||
OverloadedOperatorKind Kind = getOperator();
|
||||
if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) {
|
||||
if (getNumArgs() == 1)
|
||||
|
@ -438,7 +438,7 @@ SourceRange CXXOperatorCallExpr::getSourceRange() const {
|
|||
return SourceRange(getArg(0)->getSourceRange().getBegin(),
|
||||
getArg(1)->getSourceRange().getEnd());
|
||||
} else {
|
||||
return SourceRange();
|
||||
return getOperatorLoc();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1074,7 +1074,8 @@ void ASTStmtReader::VisitMSDependentExistsStmt(MSDependentExistsStmt *S) {
|
|||
|
||||
void ASTStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
|
||||
VisitCallExpr(E);
|
||||
E->setOperator((OverloadedOperatorKind)Record[Idx++]);
|
||||
E->Operator = (OverloadedOperatorKind)Record[Idx++];
|
||||
E->Range = Reader.ReadSourceRange(F, Record, Idx);
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) {
|
||||
|
|
|
@ -1045,6 +1045,7 @@ void ASTStmtWriter::VisitMSDependentExistsStmt(MSDependentExistsStmt *S) {
|
|||
void ASTStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
|
||||
VisitCallExpr(E);
|
||||
Record.push_back(E->getOperator());
|
||||
Writer.AddSourceRange(E->Range, Record);
|
||||
Code = serialization::EXPR_CXX_OPERATOR_CALL;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue