summaryrefslogtreecommitdiff
path: root/test/Tooling
diff options
context:
space:
mode:
Diffstat (limited to 'test/Tooling')
-rw-r--r--test/Tooling/Inputs/clang-diff-basic-src.cpp33
-rw-r--r--test/Tooling/Inputs/fixed-header.h1
-rw-r--r--test/Tooling/clang-diff-args.test12
-rw-r--r--test/Tooling/clang-diff-ast.cpp92
-rw-r--r--test/Tooling/clang-diff-basic.cpp57
-rw-r--r--test/Tooling/clang-diff-bottomup.cpp39
-rw-r--r--test/Tooling/clang-diff-html.test36
-rw-r--r--test/Tooling/clang-diff-json.cpp27
-rw-r--r--test/Tooling/clang-diff-opt.cpp45
-rw-r--r--test/Tooling/clang-diff-topdown.cpp83
-rw-r--r--test/Tooling/fixed-database.cpp19
11 files changed, 444 insertions, 0 deletions
diff --git a/test/Tooling/Inputs/clang-diff-basic-src.cpp b/test/Tooling/Inputs/clang-diff-basic-src.cpp
new file mode 100644
index 0000000000000..8f15232916d3d
--- /dev/null
+++ b/test/Tooling/Inputs/clang-diff-basic-src.cpp
@@ -0,0 +1,33 @@
+namespace src {
+
+void foo() {
+ int x = 321;
+}
+
+void main() { foo(); };
+
+const char *a = "foo";
+
+typedef unsigned int nat;
+
+int p = 1 * 2 * 3 * 4;
+int squared = p * p;
+
+class X {
+ const char *foo(int i) {
+ if (i == 0)
+ return "foo";
+ return 0;
+ }
+
+public:
+ X(){};
+
+ int id(int i) { return i; }
+};
+}
+
+void m() { int x = 0 + 0 + 0; }
+int um = 1 * 2 + 3;
+
+void f1() {{ (void) __func__;;; }}
diff --git a/test/Tooling/Inputs/fixed-header.h b/test/Tooling/Inputs/fixed-header.h
new file mode 100644
index 0000000000000..4ce318f3a4e1b
--- /dev/null
+++ b/test/Tooling/Inputs/fixed-header.h
@@ -0,0 +1 @@
+#define SECRET_SYMBOL 1
diff --git a/test/Tooling/clang-diff-args.test b/test/Tooling/clang-diff-args.test
new file mode 100644
index 0000000000000..a4ce1ea92508f
--- /dev/null
+++ b/test/Tooling/clang-diff-args.test
@@ -0,0 +1,12 @@
+RUN: echo a > %t.cpp
+
+CHECK: unknown type name 'X'
+
+check adding compiler cflags
+RUN: clang-diff -ast-dump -extra-arg=-Da=X %t.cpp -- 2>&1 | FileCheck %s
+RUN: clang-diff -ast-dump -extra-arg-before=-Da=X %t.cpp -- 2>&1 | FileCheck %s
+RUN: clang-diff -ast-dump %t.cpp -- 2>&1 -Da=X | FileCheck %s
+
+NOMATCH-CHECK-NOT: {{.}}
+RUN: clang-diff %S/clang-diff-ast.cpp %S/clang-diff-ast.cpp -- 2>&1 -std=c++11 \
+RUN: | FileCheck -check-prefix=NOMATCH-CHECK -allow-empty %s
diff --git a/test/Tooling/clang-diff-ast.cpp b/test/Tooling/clang-diff-ast.cpp
new file mode 100644
index 0000000000000..a8efda50a4052
--- /dev/null
+++ b/test/Tooling/clang-diff-ast.cpp
@@ -0,0 +1,92 @@
+// RUN: clang-diff -ast-dump %s -- -std=c++11 | FileCheck %s
+
+
+// CHECK: {{^}}TranslationUnitDecl(0)
+// CHECK: {{^}} NamespaceDecl: test;(
+namespace test {
+
+// CHECK: {{^}} FunctionDecl: :f(
+// CHECK: CompoundStmt(
+void f() {
+ // CHECK: VarDecl: i(int)(
+ // CHECK: IntegerLiteral: 1
+ auto i = 1;
+ // CHECK: FloatingLiteral: 1.5(
+ auto r = 1.5;
+ // CHECK: CXXBoolLiteralExpr: true(
+ auto b = true;
+ // CHECK: CallExpr(
+ // CHECK-NOT: ImplicitCastExpr
+ // CHECK: DeclRefExpr: :f(
+ f();
+ // CHECK: UnaryOperator: ++(
+ ++i;
+ // CHECK: BinaryOperator: =(
+ i = i;
+}
+
+} // end namespace test
+
+// CHECK: UsingDirectiveDecl: test(
+using namespace test;
+
+// CHECK: TypedefDecl: nat;unsigned int;(
+typedef unsigned nat;
+// CHECK: TypeAliasDecl: real;double;(
+using real = double;
+
+class Base {
+};
+
+// CHECK: CXXRecordDecl: X;X;(
+class X : Base {
+ int m;
+ // CHECK: CXXMethodDecl: :foo(const char *(int)
+ // CHECK: ParmVarDecl: i(int)(
+ const char *foo(int i) {
+ if (i == 0)
+ // CHECK: StringLiteral: foo(
+ return "foo";
+ // CHECK-NOT: ImplicitCastExpr
+ return 0;
+ }
+
+ // CHECK: AccessSpecDecl: public(
+public:
+ int not_initialized;
+ // CHECK: CXXConstructorDecl: :X(void (char, int){{( __attribute__\(\(thiscall\)\))?}})(
+ // CHECK-NEXT: ParmVarDecl: s(char)
+ // CHECK-NEXT: ParmVarDecl: (int)
+ // CHECK-NEXT: CXXCtorInitializer: Base
+ // CHECK-NEXT: CXXConstructExpr
+ // CHECK-NEXT: CXXCtorInitializer: m
+ // CHECK-NEXT: IntegerLiteral: 0
+ X(char s, int) : Base(), m(0) {
+ // CHECK-NEXT: CompoundStmt
+ // CHECK: MemberExpr: :m(
+ int x = m;
+ }
+ // CHECK: CXXConstructorDecl: :X(void (char){{( __attribute__\(\(thiscall\)\))?}})(
+ // CHECK: CXXCtorInitializer: X
+ X(char s) : X(s, 4) {}
+};
+
+#define M (void)1
+#define MA(a, b) (void)a, b
+// CHECK: FunctionDecl
+// CHECK-NEXT: CompoundStmt
+void macros() {
+ M;
+ MA(1, 2);
+}
+
+#ifndef GUARD
+#define GUARD
+// CHECK-NEXT: NamespaceDecl
+namespace world {
+// nodes from other files are excluded, there should be no output here
+#include "clang-diff-ast.cpp"
+}
+// CHECK-NEXT: FunctionDecl: sentinel
+void sentinel();
+#endif
diff --git a/test/Tooling/clang-diff-basic.cpp b/test/Tooling/clang-diff-basic.cpp
new file mode 100644
index 0000000000000..a0c0163530ffa
--- /dev/null
+++ b/test/Tooling/clang-diff-basic.cpp
@@ -0,0 +1,57 @@
+// RUN: clang-diff -dump-matches %S/Inputs/clang-diff-basic-src.cpp %s -- | FileCheck %s
+
+// CHECK: Match TranslationUnitDecl{{.*}} to TranslationUnitDecl
+// CHECK: Match NamespaceDecl: src{{.*}} to NamespaceDecl: dst
+namespace dst {
+// CHECK-NOT: Match NamespaceDecl: src{{.*}} to NamespaceDecl: inner
+namespace inner {
+void foo() {
+ // CHECK: Match IntegerLiteral: 321{{.*}} to IntegerLiteral: 322
+ int x = 322;
+}
+}
+
+// CHECK: Match DeclRefExpr: :foo{{.*}} to DeclRefExpr: :inner::foo
+void main() { inner::foo(); }
+
+// CHECK: Match StringLiteral: foo{{.*}} to StringLiteral: foo
+const char *b = "f" "o" "o";
+
+// unsigned is canonicalized to unsigned int
+// CHECK: Match TypedefDecl: :nat;unsigned int;{{.*}} to TypedefDecl: :nat;unsigned int;
+typedef unsigned nat;
+
+// CHECK: Match VarDecl: :p(int){{.*}} to VarDecl: :prod(double)
+// CHECK: Update VarDecl: :p(int){{.*}} to :prod(double)
+// CHECK: Match BinaryOperator: *{{.*}} to BinaryOperator: *
+double prod = 1 * 2 * 10;
+// CHECK: Update DeclRefExpr
+int squared = prod * prod;
+
+class X {
+ const char *foo(int i) {
+ if (i == 0)
+ return "Bar";
+ // CHECK: Insert IfStmt{{.*}} into IfStmt
+ // CHECK: Insert BinaryOperator: =={{.*}} into IfStmt
+ else if (i == -1)
+ return "foo";
+ return 0;
+ }
+ X(){}
+};
+}
+
+// CHECK: Move CompoundStmt{{.*}} into CompoundStmt
+void m() { { int x = 0 + 0 + 0; } }
+// CHECK: Update and Move IntegerLiteral: 7{{.*}} into BinaryOperator: +({{.*}}) at 1
+int um = 1 + 7;
+
+namespace {
+// match with parents of different type
+// CHECK: Match FunctionDecl: f1{{.*}} to FunctionDecl: (anonymous namespace)::f1
+void f1() {{ (void) __func__;;; }}
+}
+
+// CHECK: Delete AccessSpecDecl: public
+// CHECK: Delete CXXMethodDecl
diff --git a/test/Tooling/clang-diff-bottomup.cpp b/test/Tooling/clang-diff-bottomup.cpp
new file mode 100644
index 0000000000000..bc5d2cbdf4316
--- /dev/null
+++ b/test/Tooling/clang-diff-bottomup.cpp
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -E %s > %t.src.cpp
+// RUN: %clang_cc1 -E %s > %t.dst.cpp -DDEST
+// RUN: clang-diff -dump-matches -s=0 %t.src.cpp %t.dst.cpp -- | FileCheck %s
+//
+// Test the bottom-up matching, with maxsize set to 0, so that the optimal matching will never be applied.
+
+#ifndef DEST
+
+void f1() { ; {{;}} }
+void f2() { ;; {{;}} }
+
+#else
+
+// Jaccard similarity threshold is 0.5.
+
+void f1() {
+// CompoundStmt: 3 matched descendants, subtree sizes 4 and 5
+// Jaccard similarity = 3 / (4 + 5 - 3) = 3 / 6 >= 0.5
+// CHECK: Match FunctionDecl: f1(void ())(1) to FunctionDecl: f1(void ())(1)
+// CHECK: Match CompoundStmt(2) to CompoundStmt(2)
+// CHECK: Match CompoundStmt(4) to CompoundStmt(3)
+// CHECK: Match CompoundStmt(5) to CompoundStmt(4)
+// CHECK: Match NullStmt(6) to NullStmt(5)
+ {{;}} ;;
+}
+
+void f2() {
+// CompoundStmt: 3 matched descendants, subtree sizes 4 and 5
+// Jaccard similarity = 3 / (5 + 6 - 3) = 3 / 8 < 0.5
+// CHECK-NOT: Match FunctionDecl(9)
+// CHECK-NOT: Match CompoundStmt(10)
+// CHECK: Match CompoundStmt(11) to CompoundStmt(10)
+// CHECK: Match CompoundStmt(12) to CompoundStmt(11)
+// CHECK: Match NullStmt(13) to NullStmt(12)
+// CHECK-NOT: Match NullStmt(13)
+ {{;}} ;;;
+}
+
+#endif
diff --git a/test/Tooling/clang-diff-html.test b/test/Tooling/clang-diff-html.test
new file mode 100644
index 0000000000000..00d9e07d2fcf4
--- /dev/null
+++ b/test/Tooling/clang-diff-html.test
@@ -0,0 +1,36 @@
+RUN: clang-diff -html %S/Inputs/clang-diff-basic-src.cpp %S/clang-diff-basic.cpp -- | FileCheck %s
+
+CHECK: <pre><div id='L' class='code'><span id='L0' tid='R0' title='TranslationUnitDecl
+CHECK-NEXT: 0 -> 0'>
+
+match, update
+CHECK: <span id='L[[L:[0-9]+]]' tid='R[[R:[0-9]+]]' title='NamespaceDecl
+CHECK-NEXT: [[L]] -> [[R]]
+CHECK-NEXT: src;' class='u'>namespace src {
+
+match, move
+CHECK: <span id='L[[L:[0-9]+]]' tid='R[[R:[0-9]+]]' title='FunctionDecl
+CHECK-NEXT: [[L]] -> [[R]]
+CHECK-NEXT: :foo(void ())' class='m'>void foo()
+
+match
+CHECK: <span id='L[[L:[0-9]+]]' tid='R[[R:[0-9]+]]' title='FunctionDecl
+CHECK-NEXT: [[L]] -> [[R]]
+CHECK-NEXT: :main(void ())'>void main()
+
+deletion
+CHECK: <span id='L[[L:[0-9]+]]' tid='R-1' title='IntegerLiteral
+CHECK-NEXT: [[L]] -> -1
+CHECK-NEXT: 4' class='d'>4</span>
+
+update + move
+CHECK: 2' class='u m'>2</span>
+
+insertion
+CHECK: <span id='R[[R:[0-9]+]]' tid='L-1' title='StringLiteral
+CHECK-NEXT: -1 -> [[R]]
+CHECK-NEXT: Bar' class='i'>&quot;Bar&quot;</span>
+
+comments
+CHECK: // CHECK: Insert IfStmt{{.*}} into IfStmt
+CHECK: // CHECK: Delete AccessSpecDecl: public
diff --git a/test/Tooling/clang-diff-json.cpp b/test/Tooling/clang-diff-json.cpp
new file mode 100644
index 0000000000000..9aac6fa8b15bb
--- /dev/null
+++ b/test/Tooling/clang-diff-json.cpp
@@ -0,0 +1,27 @@
+// RUN: clang-diff -ast-dump-json %s -- \
+// RUN: | %python -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \
+// RUN: | FileCheck %s
+
+// CHECK: "begin": 299,
+// CHECK: "type": "FieldDecl",
+// CHECK: "end": 319,
+// CHECK: "type": "CXXRecordDecl",
+class A {
+ int x;
+};
+
+// CHECK: "children": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "begin":
+// CHECK-NEXT: "children": []
+// CHECK-NEXT: "end":
+// CHECK-NEXT: "id":
+// CHECK-NEXT: "type": "CharacterLiteral"
+// CHECK-NEXT: }
+// CHECK: ]
+// CHECK: "type": "VarDecl",
+char nl = '\n';
+
+// CHECK: "value": "abc \n\t\u0000\u001f"
+char s[] = "abc \n\t\0\x1f";
+
diff --git a/test/Tooling/clang-diff-opt.cpp b/test/Tooling/clang-diff-opt.cpp
new file mode 100644
index 0000000000000..771c6abaecb52
--- /dev/null
+++ b/test/Tooling/clang-diff-opt.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -E %s > %t.src.cpp
+// RUN: %clang_cc1 -E %s > %t.dst.cpp -DDEST
+// RUN: clang-diff -dump-matches -s=10 %t.src.cpp %t.dst.cpp -- | FileCheck %s
+//
+// Test the behaviour of the matching according to the optimal tree edit
+// distance, implemented with Zhang and Shasha's algorithm.
+// Just for testing we use a tiny value of 10 for maxsize. Subtrees bigger than
+// this size will not be processed by the optimal algorithm.
+
+#ifndef DEST
+
+void f1() { {;} {{;}} }
+
+void f2() { {;} {{;;;;;}} }
+
+void f3() { {;} {{;;;;;;}} }
+
+#else
+
+void f1() {
+// Jaccard similarity = 3 / (5 + 4 - 3) = 3 / 6 >= 0.5
+// The optimal matching algorithm should move the ; into the outer block
+// CHECK: Match CompoundStmt(2) to CompoundStmt(2)
+// CHECK-NOT: Match CompoundStmt(3)
+// CHECK-NEXT: Match NullStmt(4) to NullStmt(3)
+ ; {{;}}
+}
+
+void f2() {
+ // Jaccard similarity = 7 / (10 + 10 - 7) >= 0.5
+ // As none of the subtrees is bigger than 10 nodes, the optimal algorithm
+ // will be run.
+ // CHECK: Match NullStmt(11) to NullStmt(9)
+ ;; {{;;;;;}}
+}
+
+void f3() {
+ // Jaccard similarity = 8 / (11 + 11 - 8) >= 0.5
+ // As the subtrees are bigger than 10 nodes, the optimal algorithm will not
+ // be run.
+ // CHECK: Delete NullStmt(22)
+ ;; {{;;;;;;}}
+}
+
+#endif
diff --git a/test/Tooling/clang-diff-topdown.cpp b/test/Tooling/clang-diff-topdown.cpp
new file mode 100644
index 0000000000000..d6c1d770333ba
--- /dev/null
+++ b/test/Tooling/clang-diff-topdown.cpp
@@ -0,0 +1,83 @@
+// RUN: %clang_cc1 -E %s > %t.src.cpp
+// RUN: %clang_cc1 -E %s > %t.dst.cpp -DDEST
+// RUN: clang-diff -dump-matches -stop-diff-after=topdown %t.src.cpp %t.dst.cpp -- -std=c++11 | FileCheck %s
+//
+// Test the top-down matching of identical subtrees only.
+
+#ifndef DEST
+
+void f1()
+{
+ // Match some subtree of height greater than 2.
+ // CHECK: Match CompoundStmt(3) to CompoundStmt(3)
+ // CHECK: Match CompoundStmt(4) to CompoundStmt(4)
+ // CHECK: Match NullStmt(5) to NullStmt(5)
+ {{;}}
+
+ // Don't match subtrees that are smaller.
+ // CHECK-NOT: Match CompoundStmt(6)
+ // CHECK-NOT: Match NullStmt(7)
+ {;}
+
+ // Greedy approach - use the first matching subtree when there are multiple
+ // identical subtrees.
+ // CHECK: Match CompoundStmt(8) to CompoundStmt(8)
+ // CHECK: Match CompoundStmt(9) to CompoundStmt(9)
+ // CHECK: Match NullStmt(10) to NullStmt(10)
+ {{;;}}
+}
+
+int x;
+
+namespace src {
+ int x;
+ int x1 = x + 1;
+ int x2 = ::x + 1;
+}
+
+class A { int x = 1 + 1; void f() { int x1 = x; } };
+
+#else
+
+
+void f1() {
+
+ {{;}}
+
+ {;}
+
+ {{;;}}
+ // CHECK-NOT: Match {{.*}} to CompoundStmt(11)
+ // CHECK-NOT: Match {{.*}} to CompoundStmt(12)
+ // CHECK-NOT: Match {{.*}} to NullStmt(13)
+ {{;;}}
+
+ // CHECK-NOT: Match {{.*}} to NullStmt(14)
+ ;
+}
+
+int x;
+
+namespace dst {
+ int x;
+ // CHECK: Match DeclRefExpr: :x(17) to DeclRefExpr: :x(22)
+ int x1 = x + 1;
+ // CHECK: Match DeclRefExpr: x(21) to DeclRefExpr: x(26)
+ int x2 = ::x + 1;
+}
+
+class B {
+ // Only the class name changed; it is not included in the field value,
+ // therefore there is no update.
+ // CHECK: Match FieldDecl: :x(int)(24) to FieldDecl: :x(int)(29)
+ // CHECK-NOT: Update FieldDecl: :x(int)(24)
+ int x = 1+1;
+ void f() {
+ // CHECK: Match MemberExpr: :x(32) to MemberExpr: :x(37)
+ // CHECK-NOT: Update MemberExpr: :x(32)
+ int x1 = B::x;
+ }
+
+};
+
+#endif
diff --git a/test/Tooling/fixed-database.cpp b/test/Tooling/fixed-database.cpp
new file mode 100644
index 0000000000000..73d0779258b21
--- /dev/null
+++ b/test/Tooling/fixed-database.cpp
@@ -0,0 +1,19 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t/Src
+// RUN: cp "%s" "%t/Src/test.cpp"
+// RUN: mkdir -p %t/Include
+// RUN: cp "%S/Inputs/fixed-header.h" "%t/Include/"
+// -I flag is relative to %t (where compile_flags is), not Src/.
+// RUN: echo '-IInclude/' >> %t/compile_flags.txt
+// RUN: echo "-Dklazz=class" >> %t/compile_flags.txt
+// RUN: echo '-std=c++11' >> %t/compile_flags.txt
+// RUN: clang-check "%t/Src/test.cpp" 2>&1
+// RUN: echo > %t/compile_flags.txt
+// RUN: not clang-check "%t/Src/test.cpp" 2>&1 | FileCheck "%s" -check-prefix=NODB
+
+// NODB: unknown type name 'klazz'
+klazz F{};
+
+// NODB: 'fixed-header.h' file not found
+#include "fixed-header.h"
+static_assert(SECRET_SYMBOL == 1, "");