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:
Argyrios Kyrtzidis 2012-04-30 22:12:22 +00:00
parent d0d5ec4a38
commit d8e076972f
4 changed files with 14 additions and 6 deletions

View File

@ -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

View File

@ -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();
}
}

View File

@ -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) {

View File

@ -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;
}