Index: test/Tooling/Inputs/clang-diff-basic-src.cpp =================================================================== --- test/Tooling/Inputs/clang-diff-basic-src.cpp +++ test/Tooling/Inputs/clang-diff-basic-src.cpp @@ -53,4 +53,11 @@ visit(x); } -int x = 1; +struct str { + str& operator+(const str&); + str& operator-(const str&); + str& operator++(); + str operator++(int); +} s1, s2, s3; + +str x = s1 + s2 - s3; Index: test/Tooling/clang-diff-basic.cpp =================================================================== --- test/Tooling/clang-diff-basic.cpp +++ test/Tooling/clang-diff-basic.cpp @@ -1,4 +1,4 @@ -// RUN: clang-diff -dump-matches %S/Inputs/clang-diff-basic-src.cpp %s -- -std=c++11 | FileCheck %s +// RUN: clang-diff -dump-matches %S/Inputs/clang-diff-basic-src.cpp %s -s=200 -- -std=c++11 | FileCheck %s // CHECK: Match TranslationUnitDecl{{.*}} to TranslationUnitDecl // CHECK: Match NamespaceDecl: src{{.*}} to NamespaceDecl: dst @@ -81,5 +81,21 @@ visit(x); } +struct str { + str& operator+(const str&); + str& operator-(const str&); + str& operator++(); + str operator++(int); +} s1, s2, s3; + +// CHECK: Match CXXOperatorCallExpr +// CHECK-NEXT: Match DeclRefExpr: str::operator-{{.*}} to DeclRefExpr: str::operator- +// CHECK-NEXT: Match CXXOperatorCallExpr +// CHECK-NEXT: Match DeclRefExpr: str::operator+{{.*}} to DeclRefExpr: str::operator+ +// CHECK-NEXT: Match DeclRefExpr: s1 +// CHECK-NEXT: Match DeclRefExpr: s2 +// CHECK-NEXT: Match DeclRefExpr: s3 +str x = s1 + s2 - s3; + // CHECK: Delete AccessSpecDecl: public // CHECK: Delete CXXMethodDecl Index: test/Tooling/clang-diff-html.test =================================================================== --- test/Tooling/clang-diff-html.test +++ test/Tooling/clang-diff-html.test @@ -1,4 +1,4 @@ -RUN: clang-diff -html %S/Inputs/clang-diff-basic-src.cpp %S/clang-diff-basic.cpp -- -std=c++11 | FileCheck %s +RUN: clang-diff -html %S/Inputs/clang-diff-basic-src.cpp %S/clang-diff-basic.cpp -s=200 -- -std=c++11 | FileCheck %s CHECK:
@@ -31,6 +31,13 @@ CHECK-NEXT: -1 -> [[R]] CHECK-NEXT: Bar' class='i'>"Bar" +CHECK: CXXOperatorCallExpr +CHECK: CXXOperatorCallExpr +CHECK: s1 +CHECK: str::operator+ +CHECK: s2 +CHECK: str::operator- +CHECK: s3 + comments -CHECK: // CHECK: Insert IfStmt{{.*}} into IfStmt CHECK: // CHECK: Delete AccessSpecDecl: public Index: tools/clang-diff/CMakeLists.txt =================================================================== --- tools/clang-diff/CMakeLists.txt +++ tools/clang-diff/CMakeLists.txt @@ -7,6 +7,7 @@ ) target_link_libraries(clang-diff + clangAST clangBasic clangFrontend clangTooling Index: tools/clang-diff/ClangDiff.cpp =================================================================== --- tools/clang-diff/ClangDiff.cpp +++ tools/clang-diff/ClangDiff.cpp @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/ExprCXX.h" #include "clang/Tooling/ASTDiff/ASTDiff.h" #include "clang/Tooling/CommonOptionsParser.h" #include "clang/Tooling/Tooling.h" @@ -310,8 +311,17 @@ OS << " class='" << getChangeKindAbbr(Node.Change) << "'"; OS << ">"; - for (diff::NodeId Child : Node.Children) - Offset = printHtmlForNode(OS, Diff, Tree, IsLeft, Child, Offset); + const auto &Children = Node.Children; + auto *OpCall = Node.ASTNode.get(); + if (OpCall && OpCall->isInfixBinaryOp()) { + assert(Children.size() == 3 && + "A Binary operator is supposed to have two arguments."); + for (int I : {1, 0, 2}) + Offset = printHtmlForNode(OS, Diff, Tree, IsLeft, Children[I], Offset); + } else { + for (diff::NodeId Child : Children) + Offset = printHtmlForNode(OS, Diff, Tree, IsLeft, Child, Offset); + } for (; Offset < End; ++Offset) printHtml(OS, Code[Offset]);