johannes created this revision. This adds a special case for traversing CXXOperatorCallExpr. Its children are traversed in the order in which they appear in the source code, so infix and postfix operators are visited after their first argument.
This behavior was previously only in LexicallyOrderedRecursiveASTVisitor, moving it here could avoid bugs in the future. It is still tested in LexicallyOrderedRecursiveASTVisitorTest.cpp in VisitTemplateDecl. Clients that somehow rely on the original traversal order will have to be updated though. https://reviews.llvm.org/D37663 Files: include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h include/clang/AST/RecursiveASTVisitor.h Index: include/clang/AST/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h +++ include/clang/AST/RecursiveASTVisitor.h @@ -315,15 +315,40 @@ // ---- Methods on Stmts ---- - Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); } - private: template<typename T, typename U> struct has_same_member_pointer_type : std::false_type {}; template<typename T, typename U, typename R, typename... P> struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)> : std::true_type {}; + Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); } + + SmallVector<Stmt *, 8> getStmtChildren(CXXOperatorCallExpr *CE) { + SmallVector<Stmt *, 8> Children(CE->children()); + bool Swap; + // Swap the operator and the first operand for all infix and postfix + // operations. + switch (CE->getOperator()) { + case OO_Arrow: + case OO_Call: + case OO_Subscript: + Swap = true; + break; + case OO_PlusPlus: + case OO_MinusMinus: + // These are postfix unless there is exactly one argument. + Swap = Children.size() != 2; + break; + default: + Swap = CE->isInfixBinaryOp(); + break; + } + if (Swap && Children.size() > 1) + std::swap(Children[0], Children[1]); + return Children; + } + // Traverse the given statement. If the most-derived traverse function takes a // data recursion queue, pass it on; otherwise, discard it. Note that the // first branch of this conditional must compile whether or not the derived Index: include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h =================================================================== --- include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h +++ include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h @@ -111,33 +111,6 @@ return true; } - Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); } - - SmallVector<Stmt *, 8> getStmtChildren(CXXOperatorCallExpr *CE) { - SmallVector<Stmt *, 8> Children(CE->children()); - bool Swap; - // Switch the operator and the first operand for all infix and postfix - // operations. - switch (CE->getOperator()) { - case OO_Arrow: - case OO_Call: - case OO_Subscript: - Swap = true; - break; - case OO_PlusPlus: - case OO_MinusMinus: - // These are postfix unless there is exactly one argument. - Swap = Children.size() != 2; - break; - default: - Swap = CE->isInfixBinaryOp(); - break; - } - if (Swap && Children.size() > 1) - std::swap(Children[0], Children[1]); - return Children; - } - private: bool TraverseAdditionalLexicallyNestedDeclarations() { // FIXME: Ideally the gathered declarations and the declarations in the
Index: include/clang/AST/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h +++ include/clang/AST/RecursiveASTVisitor.h @@ -315,15 +315,40 @@ // ---- Methods on Stmts ---- - Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); } - private: template<typename T, typename U> struct has_same_member_pointer_type : std::false_type {}; template<typename T, typename U, typename R, typename... P> struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)> : std::true_type {}; + Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); } + + SmallVector<Stmt *, 8> getStmtChildren(CXXOperatorCallExpr *CE) { + SmallVector<Stmt *, 8> Children(CE->children()); + bool Swap; + // Swap the operator and the first operand for all infix and postfix + // operations. + switch (CE->getOperator()) { + case OO_Arrow: + case OO_Call: + case OO_Subscript: + Swap = true; + break; + case OO_PlusPlus: + case OO_MinusMinus: + // These are postfix unless there is exactly one argument. + Swap = Children.size() != 2; + break; + default: + Swap = CE->isInfixBinaryOp(); + break; + } + if (Swap && Children.size() > 1) + std::swap(Children[0], Children[1]); + return Children; + } + // Traverse the given statement. If the most-derived traverse function takes a // data recursion queue, pass it on; otherwise, discard it. Note that the // first branch of this conditional must compile whether or not the derived Index: include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h =================================================================== --- include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h +++ include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h @@ -111,33 +111,6 @@ return true; } - Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); } - - SmallVector<Stmt *, 8> getStmtChildren(CXXOperatorCallExpr *CE) { - SmallVector<Stmt *, 8> Children(CE->children()); - bool Swap; - // Switch the operator and the first operand for all infix and postfix - // operations. - switch (CE->getOperator()) { - case OO_Arrow: - case OO_Call: - case OO_Subscript: - Swap = true; - break; - case OO_PlusPlus: - case OO_MinusMinus: - // These are postfix unless there is exactly one argument. - Swap = Children.size() != 2; - break; - default: - Swap = CE->isInfixBinaryOp(); - break; - } - if (Swap && Children.size() > 1) - std::swap(Children[0], Children[1]); - return Children; - } - private: bool TraverseAdditionalLexicallyNestedDeclarations() { // FIXME: Ideally the gathered declarations and the declarations in the
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits