[PATCH] D37663: [AST] Make RecursiveASTVisitor visit CXXOperatorCallExpr in source order

Johannes Altmanninger via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Sat Sep 9 03:46:41 PDT 2017


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


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D37663.114482.patch
Type: text/x-patch
Size: 2857 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170909/78b99f01/attachment.bin>


More information about the cfe-commits mailing list