From d8e076972f815f20204558f0605f802cd12c029c Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Mon, 30 Apr 2012 22:12:22 +0000 Subject: [PATCH] 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 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 --- clang/include/clang/AST/ExprCXX.h | 12 +++++++++--- clang/lib/AST/ExprCXX.cpp | 4 ++-- clang/lib/Serialization/ASTReaderStmt.cpp | 3 ++- clang/lib/Serialization/ASTWriterStmt.cpp | 1 + 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index b69693d7c6a3..8d7b8c6791b0 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -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 diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 8cf519c93dc2..8fbe72108b95 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -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(); } } diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 73b5ab7ec6d1..9eda98cbc8ac 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -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) { diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 89436157df98..4f25e707c19d 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -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; }