Import Cobalt 19.master.0.203780
Includes the following patches:
https://cobalt-review.googlesource.com/c/cobalt/+/5210
by errong.leng@samsung.com
https://cobalt-review.googlesource.com/c/cobalt/+/5270
by linus.wang@samsung.com
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/a.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/a.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/a.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/b.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/b.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/b.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/clang-c/c.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/clang-c/c.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/clang-c/c.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/clang/b.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/clang/b.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/clang/b.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/cross-file-a.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/cross-file-a.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/cross-file-a.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/cross-file-b.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/cross-file-b.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/cross-file-b.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/cross-file-c.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/cross-file-c.h
new file mode 100644
index 0000000..342dd34
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/cross-file-c.h
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// The line number of the following include should match the location of the
+// corresponding comment in llvm-include-order.cpp
+#include "cross-file-b.h"
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/gtest/foo.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/gtest/foo.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/gtest/foo.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/i.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/i.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/i.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/j.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/j.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/j.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/llvm-c/d.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/llvm-c/d.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/llvm-c/d.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/llvm/a.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/llvm/a.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/llvm/a.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/s.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/s.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/s.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/system-header-simulation.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/system-header-simulation.h
new file mode 100644
index 0000000..0df5305
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/system-header-simulation.h
@@ -0,0 +1,24 @@
+#pragma clang system_header
+
+namespace std {
+
+template<class T, T v>
+struct integral_constant {
+ static constexpr T value = v;
+ typedef T value_type;
+ typedef integral_constant type;
+ constexpr operator value_type() const noexcept { return value; }
+};
+
+template <bool B>
+using bool_constant = integral_constant<bool, B>;
+using true_type = bool_constant<true>;
+using false_type = bool_constant<false>;
+
+template<class T>
+struct is_error_code_enum : false_type {};
+
+template<class T>
+void swap(T &a, T &b);
+}
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/compilation-database/template.json b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/compilation-database/template.json
new file mode 100644
index 0000000..74275d9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/compilation-database/template.json
@@ -0,0 +1,32 @@
+[
+{
+ "directory": "test_dir/a",
+ "command": "clang++ -o test.o test_dir/a/a.cpp",
+ "file": "test_dir/a/a.cpp"
+},
+{
+ "directory": "test_dir/a",
+ "command": "clang++ -o test.o test_dir/a/b.cpp",
+ "file": "test_dir/a/b.cpp"
+},
+{
+ "directory": "test_dir/",
+ "command": "clang++ -o test.o test_dir/b/b.cpp",
+ "file": "test_dir/b/b.cpp"
+},
+{
+ "directory": "test_dir/b",
+ "command": "clang++ -o test.o ../b/c.cpp",
+ "file": "test_dir/b/c.cpp"
+},
+{
+ "directory": "test_dir/b",
+ "command": "clang++ -I../include -o test.o ../b/d.cpp",
+ "file": "test_dir/b/d.cpp"
+},
+{
+ "directory": "test_dir/",
+ "command": "clang++ -o test.o test_dir/b/not-exist.cpp",
+ "file": "test_dir/b/not-exist.cpp"
+}
+]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/config-files/.clang-tidy b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/config-files/.clang-tidy
new file mode 100644
index 0000000..942169f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/config-files/.clang-tidy
@@ -0,0 +1,2 @@
+Checks: 'from-parent'
+HeaderFilterRegex: 'parent'
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/config-files/1/.clang-tidy b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/config-files/1/.clang-tidy
new file mode 100644
index 0000000..800fd4e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/config-files/1/.clang-tidy
@@ -0,0 +1,2 @@
+Checks: 'from-child1'
+HeaderFilterRegex: 'child1'
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/explain-config/.clang-tidy b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/explain-config/.clang-tidy
new file mode 100644
index 0000000..4fbd09c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/explain-config/.clang-tidy
@@ -0,0 +1 @@
+Checks: '-*,modernize-use-nullptr'
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/file-filter/header1.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/file-filter/header1.h
new file mode 100644
index 0000000..ba9e3d1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/file-filter/header1.h
@@ -0,0 +1 @@
+class A1 { A1(int); };
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/file-filter/header2.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/file-filter/header2.h
new file mode 100644
index 0000000..09bfeab
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/file-filter/header2.h
@@ -0,0 +1 @@
+class A2 { A2(int); };
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/file-filter/system/system-header.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/file-filter/system/system-header.h
new file mode 100644
index 0000000..98482c4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/file-filter/system/system-header.h
@@ -0,0 +1 @@
+class A0 { A0(int); };
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/a.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/a.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/a.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/cstdarg.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/cstdarg.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/cstdarg.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/cstdlib.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/cstdlib.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/cstdlib.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/j.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/j.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/j.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/r.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/r.h
new file mode 100644
index 0000000..56757a7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/r.h
@@ -0,0 +1 @@
+void f() {}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/s.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/s.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/s.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/t.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/t.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/t.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/transitive.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/transitive.h
new file mode 100644
index 0000000..6dba769
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/transitive.h
@@ -0,0 +1,3 @@
+#include <r.h>
+#include <t.h>
+#include <s.h>
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/transitive2.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/transitive2.h
new file mode 100644
index 0000000..ea56788
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/transitive2.h
@@ -0,0 +1,2 @@
+#include <s.h>
+#include <t.h>
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/google-namespaces.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/google-namespaces.h
new file mode 100644
index 0000000..f4d87f5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/google-namespaces.h
@@ -0,0 +1,7 @@
+namespace {
+int x;
+}
+
+namespace spaaaace {
+class core;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/line-filter/header1.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/line-filter/header1.h
new file mode 100644
index 0000000..35d59ce
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/line-filter/header1.h
@@ -0,0 +1,3 @@
+class A1 { A1(int); };
+class B1 { B1(int); };
+class C1 { C1(int); };
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/line-filter/header2.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/line-filter/header2.h
new file mode 100644
index 0000000..bb12598
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/line-filter/header2.h
@@ -0,0 +1,3 @@
+class A2 { A2(int); };
+class B2 { B2(int); };
+class C2 { C2(int); };
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/line-filter/header3.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/line-filter/header3.h
new file mode 100644
index 0000000..b5198ca
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/line-filter/header3.h
@@ -0,0 +1 @@
+class A3 { A3(int); };
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/assert.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/assert.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/assert.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/complex.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/complex.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/complex.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/ctype.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/ctype.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/ctype.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/errno.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/errno.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/errno.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/fenv.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/fenv.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/fenv.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/float.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/float.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/float.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/inttypes.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/inttypes.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/inttypes.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/iso646.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/iso646.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/iso646.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/limits.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/limits.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/limits.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/locale.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/locale.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/locale.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/math.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/math.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/math.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/setjmp.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/setjmp.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/setjmp.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/signal.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/signal.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/signal.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdalign.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdalign.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdalign.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdarg.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdarg.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdarg.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdbool.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdbool.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdbool.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stddef.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stddef.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stddef.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdint.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdint.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdint.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdio.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdio.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdio.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdlib.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdlib.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdlib.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/string.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/string.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/string.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/tgmath.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/tgmath.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/tgmath.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/time.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/time.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/time.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/uchar.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/uchar.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/uchar.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/wchar.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/wchar.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/wchar.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/wctype.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/wctype.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/wctype.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-loop-convert/structures.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-loop-convert/structures.h
new file mode 100644
index 0000000..02d440c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-loop-convert/structures.h
@@ -0,0 +1,206 @@
+#ifndef STRUCTURES_H
+#define STRUCTURES_H
+
+extern "C" {
+extern int printf(const char *restrict, ...);
+}
+
+struct Val {int X; void g(); };
+
+struct MutableVal {
+ void constFun(int) const;
+ void nonConstFun(int, int);
+ void constFun(MutableVal &) const;
+ void constParamFun(const MutableVal &) const;
+ void nonConstParamFun(const MutableVal &);
+ int X;
+};
+
+struct NonTriviallyCopyable {
+ NonTriviallyCopyable() = default;
+ // Define this constructor to make this class non-trivially copyable.
+ NonTriviallyCopyable(const NonTriviallyCopyable& Ntc);
+ int X;
+};
+
+struct TriviallyCopyableButBig {
+ int X;
+ char Array[16];
+};
+
+struct S {
+ typedef MutableVal *iterator;
+ typedef const MutableVal *const_iterator;
+ const_iterator begin() const;
+ const_iterator end() const;
+ const_iterator cbegin() const;
+ const_iterator cend() const;
+ iterator begin();
+ iterator end();
+};
+
+struct T {
+ struct iterator {
+ int& operator*();
+ const int& operator*()const;
+ iterator& operator ++();
+ bool operator!=(const iterator &other);
+ void insert(int);
+ int X;
+ };
+ iterator begin();
+ iterator end();
+};
+
+struct U {
+ struct iterator {
+ Val& operator*();
+ const Val& operator*()const;
+ iterator& operator ++();
+ bool operator!=(const iterator &other);
+ Val *operator->();
+ };
+ iterator begin();
+ iterator end();
+ int X;
+};
+
+struct X {
+ S Ss;
+ T Tt;
+ U Uu;
+ S getS();
+};
+
+template<typename ElemType>
+class dependent {
+ public:
+ dependent<ElemType>();
+ struct iterator_base {
+ const ElemType& operator*()const;
+ iterator_base& operator ++();
+ bool operator!=(const iterator_base &other) const;
+ const ElemType *operator->() const;
+ };
+
+ struct iterator : iterator_base {
+ ElemType& operator*();
+ iterator& operator ++();
+ ElemType *operator->();
+ };
+
+ typedef iterator_base const_iterator;
+ const_iterator begin() const;
+ const_iterator end() const;
+ iterator begin();
+ iterator end();
+ unsigned size() const;
+ ElemType & operator[](unsigned);
+ const ElemType & operator[](unsigned) const;
+ ElemType & at(unsigned);
+ ElemType & at(unsigned, unsigned);
+ const ElemType & at(unsigned) const;
+
+ // Intentionally evil.
+ dependent<ElemType> operator*();
+
+ void foo();
+ void constFoo() const;
+};
+
+template<typename First, typename Second>
+class doublyDependent{
+ public:
+ struct Value {
+ First first;
+ Second second;
+ };
+
+ struct iterator_base {
+ const Value& operator*()const;
+ iterator_base& operator ++();
+ bool operator!=(const iterator_base &other) const;
+ const Value *operator->() const;
+ };
+
+ struct iterator : iterator_base {
+ Value& operator*();
+ Value& operator ++();
+ Value *operator->();
+ };
+
+ typedef iterator_base const_iterator;
+ const_iterator begin() const;
+ const_iterator end() const;
+ iterator begin();
+ iterator end();
+};
+
+template<typename Contained>
+class transparent {
+ public:
+ Contained *at();
+ Contained *operator->();
+ Contained operator*();
+};
+
+template<typename IteratorType>
+struct Nested {
+ typedef IteratorType* iterator;
+ typedef const IteratorType* const_iterator;
+ IteratorType *operator->();
+ IteratorType operator*();
+ iterator begin();
+ iterator end();
+ const_iterator begin() const;
+ const_iterator end() const;
+};
+
+// Like llvm::SmallPtrSet, the iterator has a dereference operator that returns
+// by value instead of by reference.
+template <typename T>
+struct PtrSet {
+ struct iterator {
+ bool operator!=(const iterator &other) const;
+ const T operator*();
+ iterator &operator++();
+ };
+ iterator begin() const;
+ iterator end() const;
+};
+
+template <typename T>
+struct TypedefDerefContainer {
+ struct iterator {
+ typedef T &deref_type;
+ bool operator!=(const iterator &other) const;
+ deref_type operator*();
+ iterator &operator++();
+ };
+ iterator begin() const;
+ iterator end() const;
+};
+
+template <typename T>
+struct RValueDerefContainer {
+ struct iterator {
+ typedef T &&deref_type;
+ bool operator!=(const iterator &other) const;
+ deref_type operator*();
+ iterator &operator++();
+ };
+ iterator begin() const;
+ iterator end() const;
+};
+
+namespace Macros {
+
+struct MacroStruct {
+ int Arr[10];
+};
+static MacroStruct *MacroSt;
+#define CONT MacroSt->
+
+} // namespace Macros
+
+#endif // STRUCTURES_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-pass-by-value/header-with-fix.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-pass-by-value/header-with-fix.h
new file mode 100644
index 0000000..62609e2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-pass-by-value/header-with-fix.h
@@ -0,0 +1,8 @@
+struct S {
+ S(S&&);
+ S(const S&);
+};
+struct Foo {
+ Foo(const S &s);
+ S s;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-pass-by-value/header.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-pass-by-value/header.h
new file mode 100644
index 0000000..c2103cb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-pass-by-value/header.h
@@ -0,0 +1,10 @@
+class ThreadId {
+public:
+ ThreadId(const ThreadId &) {}
+ ThreadId(ThreadId &&) {}
+};
+
+struct A {
+ A(const ThreadId &tid) : threadid(tid) {}
+ ThreadId threadid;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-replace-auto-ptr/memory.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-replace-auto-ptr/memory.h
new file mode 100644
index 0000000..bc476ce
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-replace-auto-ptr/memory.h
@@ -0,0 +1,45 @@
+#ifndef INPUTS_MEMORY_H
+#define INPUTS_MEMORY_H
+
+namespace std {
+
+inline namespace _1 {
+
+template <class Y> struct auto_ptr_ref {
+ Y *y_;
+};
+
+template <class X> class auto_ptr {
+public:
+ typedef X element_type;
+ explicit auto_ptr(X *p = 0) throw() {}
+ auto_ptr(auto_ptr &) throw() {}
+ template <class Y> auto_ptr(auto_ptr<Y> &) throw() {}
+ auto_ptr &operator=(auto_ptr &) throw() { return *this; }
+ template <class Y> auto_ptr &operator=(auto_ptr<Y> &) throw() {
+ return *this;
+ }
+ auto_ptr &operator=(auto_ptr_ref<X> r) throw() { return *this; }
+ ~auto_ptr() throw() {}
+ auto_ptr(auto_ptr_ref<X> r) throw() : x_(r.y_) {}
+ template <class Y> operator auto_ptr_ref<Y>() throw() {
+ auto_ptr_ref<Y> r;
+ r.y_ = x_;
+ return r;
+ }
+ template <class Y> operator auto_ptr<Y>() throw() { return auto_ptr<Y>(x_); }
+
+private:
+ X *x_;
+};
+
+template <> class auto_ptr<void> {
+public:
+ typedef void element_type;
+};
+
+} // namespace _1
+
+} // end namespace std
+
+#endif // INPUTS_MEMORY_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-smart-ptr/initializer_list.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-smart-ptr/initializer_list.h
new file mode 100644
index 0000000..28592cf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-smart-ptr/initializer_list.h
@@ -0,0 +1,32 @@
+namespace std {
+typedef decltype(sizeof(int)) size_t;
+
+template <class _E> class initializer_list {
+ const _E *__begin_;
+ size_t __size_;
+
+ initializer_list(const _E *__b, size_t __s) : __begin_(__b), __size_(__s) {}
+
+public:
+ typedef _E value_type;
+ typedef const _E &reference;
+ typedef const _E &const_reference;
+ typedef size_t size_type;
+
+ typedef const _E *iterator;
+ typedef const _E *const_iterator;
+
+ initializer_list() : __begin_(nullptr), __size_(0) {}
+
+ size_t size() const { return __size_; }
+ const _E *begin() const { return __begin_; }
+ const _E *end() const { return __begin_ + __size_; }
+};
+
+template <class _E>
+class vector {
+ public:
+ vector(initializer_list<_E> init);
+ ~vector();
+};
+} // namespace std
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-smart-ptr/shared_ptr.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-smart-ptr/shared_ptr.h
new file mode 100644
index 0000000..0f4f2a9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-smart-ptr/shared_ptr.h
@@ -0,0 +1,24 @@
+namespace std {
+
+template <typename type>
+class shared_ptr {
+public:
+ shared_ptr();
+ shared_ptr(type *ptr);
+ shared_ptr(const shared_ptr<type> &t) {}
+ shared_ptr(shared_ptr<type> &&t) {}
+ ~shared_ptr();
+ type &operator*() { return *ptr; }
+ type *operator->() { return ptr; }
+ type *release();
+ void reset();
+ void reset(type *pt);
+ shared_ptr &operator=(shared_ptr &&);
+ template <typename T>
+ shared_ptr &operator=(shared_ptr<T> &&);
+
+private:
+ type *ptr;
+};
+
+} // namespace std
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-smart-ptr/unique_ptr.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-smart-ptr/unique_ptr.h
new file mode 100644
index 0000000..5dc9e02
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-smart-ptr/unique_ptr.h
@@ -0,0 +1,28 @@
+namespace std {
+
+template <typename T>
+class default_delete {};
+
+template <typename type, typename Deleter = std::default_delete<type>>
+class unique_ptr {
+public:
+ unique_ptr() {}
+ unique_ptr(type *ptr) {}
+ unique_ptr(const unique_ptr<type> &t) = delete;
+ unique_ptr(unique_ptr<type> &&t) {}
+ ~unique_ptr() {}
+ type &operator*() { return *ptr; }
+ type *operator->() { return ptr; }
+ type *release() { return ptr; }
+ void reset() {}
+ void reset(type *pt) {}
+ void reset(type pt) {}
+ unique_ptr &operator=(unique_ptr &&) { return *this; }
+ template <typename T>
+ unique_ptr &operator=(unique_ptr<T> &&) { return *this; }
+
+private:
+ type *ptr;
+};
+
+} // namespace std
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-use-auto/containers.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-use-auto/containers.h
new file mode 100644
index 0000000..c99b7a4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-use-auto/containers.h
@@ -0,0 +1,253 @@
+#ifndef CONTAINERS_H
+#define CONTAINERS_H
+
+namespace std {
+
+template <typename T>
+class iterator {
+public:
+ iterator() {}
+ iterator(const iterator<T> &iter) : ptr(iter.ptr) {}
+
+ typedef T value_type;
+ typedef T *pointer;
+ typedef T &reference;
+
+ reference operator*() const { return *ptr; }
+ pointer operator->() const { return ptr; }
+ iterator &operator++() {
+ ++ptr;
+ return *this;
+ }
+ iterator &operator--() {
+ --ptr;
+ return *this;
+ }
+ iterator operator++(int) {
+ iterator res(*this);
+ ++ptr;
+ return res;
+ }
+ iterator operator--(int) {
+ iterator res(*this);
+ --ptr;
+ return res;
+ }
+ bool operator!=(const iterator<T> &iter) const {
+ return ptr != iter.operator->();
+ }
+
+private:
+ T *ptr;
+};
+
+template <class Iterator>
+class const_iterator {
+public:
+ const_iterator() {}
+ const_iterator(const Iterator &iter) : iter(iter) {}
+ const_iterator(const const_iterator<Iterator> &citer) : iter(citer.iter) {}
+
+ typedef const typename Iterator::value_type value_type;
+ typedef const typename Iterator::pointer pointer;
+ typedef const typename Iterator::reference reference;
+
+ reference operator*() const { return *iter; }
+ pointer operator->() const { return iter.operator->(); }
+
+ const_iterator &operator++() { return ++iter; }
+ const_iterator &operator--() { return --iter; }
+ const_iterator operator++(int) { return iter--; }
+ const_iterator operator--(int) { return iter--; }
+
+ bool operator!=(const Iterator &it) const {
+ return iter->operator->() != it.operator->();
+ }
+ bool operator!=(const const_iterator<Iterator> &it) const {
+ return iter.operator->() != it.operator->();
+ }
+
+private:
+ Iterator iter;
+};
+
+template <class Iterator>
+class forward_iterable {
+public:
+ forward_iterable() {}
+ typedef Iterator iterator;
+ typedef const_iterator<Iterator> const_iterator;
+
+ iterator begin() { return _begin; }
+ iterator end() { return _end; }
+
+ const_iterator begin() const { return _begin; }
+ const_iterator end() const { return _end; }
+
+ const_iterator cbegin() const { return _begin; }
+ const_iterator cend() const { return _end; }
+
+private:
+ iterator _begin, _end;
+};
+
+template <class Iterator>
+class reverse_iterator {
+public:
+ reverse_iterator() {}
+ reverse_iterator(const Iterator &iter) : iter(iter) {}
+ reverse_iterator(const reverse_iterator<Iterator> &rit) : iter(rit.iter) {}
+
+ typedef typename Iterator::value_type value_type;
+ typedef typename Iterator::pointer pointer;
+ typedef typename Iterator::reference reference;
+
+ reference operator*() { return *iter; }
+ pointer operator->() { return iter.operator->(); }
+
+ reverse_iterator &operator++() { return --iter; }
+ reverse_iterator &operator--() { return ++iter; }
+ reverse_iterator operator++(int) { return iter--; }
+ reverse_iterator operator--(int) { return iter++; }
+
+private:
+ Iterator iter;
+};
+
+template <class Iterator>
+class backward_iterable {
+public:
+ backward_iterable() {}
+
+ typedef reverse_iterator<Iterator> reverse_iterator;
+ typedef const_iterator<reverse_iterator> const_reverse_iterator;
+
+ reverse_iterator rbegin() { return _rbegin; }
+ reverse_iterator rend() { return _rend; }
+
+ const_reverse_iterator rbegin() const { return _rbegin; }
+ const_reverse_iterator rend() const { return _rend; }
+
+ const_reverse_iterator crbegin() const { return _rbegin; }
+ const_reverse_iterator crend() const { return _rend; }
+
+private:
+ reverse_iterator _rbegin, _rend;
+};
+
+template <class Iterator>
+class bidirectional_iterable : public forward_iterable<Iterator>,
+ public backward_iterable<Iterator> {};
+
+template <typename A, typename B>
+struct pair {
+ pair(A f, B s) : first(f), second(s) {}
+ A first;
+ B second;
+};
+
+class string {
+public:
+ string() {}
+ string(const char *) {}
+};
+
+template <typename T, int n>
+class array : public backward_iterable<iterator<T>> {
+public:
+ array() {}
+
+ typedef T *iterator;
+ typedef const T *const_iterator;
+
+ iterator begin() { return &v[0]; }
+ iterator end() { return &v[n - 1]; }
+
+ const_iterator begin() const { return &v[0]; }
+ const_iterator end() const { return &v[n - 1]; }
+
+ const_iterator cbegin() const { return &v[0]; }
+ const_iterator cend() const { return &v[n - 1]; }
+
+private:
+ T v[n];
+};
+
+template <typename T>
+class deque : public bidirectional_iterable<iterator<T>> {
+public:
+ deque() {}
+};
+
+template <typename T>
+class list : public bidirectional_iterable<iterator<T>> {
+public:
+ list() {}
+};
+
+template <typename T>
+class forward_list : public forward_iterable<iterator<T>> {
+public:
+ forward_list() {}
+};
+
+template <typename T>
+class vector : public bidirectional_iterable<iterator<T>> {
+public:
+ vector() {}
+};
+
+template <typename T>
+class set : public bidirectional_iterable<iterator<T>> {
+public:
+ set() {}
+};
+
+template <typename T>
+class multiset : public bidirectional_iterable<iterator<T>> {
+public:
+ multiset() {}
+};
+
+template <typename key, typename value>
+class map : public bidirectional_iterable<iterator<pair<key, value>>> {
+public:
+ map() {}
+
+ iterator<pair<key, value>> find(const key &) {}
+ const_iterator<iterator<pair<key, value>>> find(const key &) const {}
+};
+
+template <typename key, typename value>
+class multimap : public bidirectional_iterable<iterator<pair<key, value>>> {
+public:
+ multimap() {}
+};
+
+template <typename T>
+class unordered_set : public forward_iterable<iterator<T>> {
+public:
+ unordered_set() {}
+};
+
+template <typename T>
+class unordered_multiset : public forward_iterable<iterator<T>> {
+public:
+ unordered_multiset() {}
+};
+
+template <typename key, typename value>
+class unordered_map : public forward_iterable<iterator<pair<key, value>>> {
+public:
+ unordered_map() {}
+};
+
+template <typename key, typename value>
+class unordered_multimap : public forward_iterable<iterator<pair<key, value>>> {
+public:
+ unordered_multimap() {}
+};
+
+} // namespace std
+
+#endif // CONTAINERS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/mpi-type-mismatch/mpimock.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/mpi-type-mismatch/mpimock.h
new file mode 100644
index 0000000..cb90028
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/mpi-type-mismatch/mpimock.h
@@ -0,0 +1,64 @@
+// This Message Passing Interface mock header is used, to mock typedefs,
+// constants and functions, required for integration tests being part of
+// clang-tidy MPI checks.
+
+#ifndef MPIMOCK_H
+#define MPIMOCK_H
+
+#define NULL 0
+
+// These typedefs are used to mock MPI types, fixed width integer types and the
+// templated C++ complex number type.
+typedef int MPI_Datatype;
+typedef int MPI_Comm;
+typedef int MPI_Request;
+typedef int MPI_Status;
+typedef int MPI_Op;
+typedef int int8_t;
+typedef int uint8_t;
+typedef int uint16_t;
+typedef int int64_t;
+namespace std { template<class T> struct complex { T real; T imag; }; }
+
+// These defines are used to mock MPI constants.
+#define MPI_DATATYPE_NULL 0
+#define MPI_CHAR 0
+#define MPI_BYTE 0
+#define MPI_SHORT 0
+#define MPI_INT 0
+#define MPI_LONG 0
+#define MPI_LONG_DOUBLE 0
+#define MPI_UNSIGNED 0
+#define MPI_INT8_T 0
+#define MPI_UINT8_T 0
+#define MPI_UINT16_T 0
+#define MPI_C_FLOAT_COMPLEX 0
+#define MPI_C_LONG_DOUBLE_COMPLEX 0
+#define MPI_FLOAT 0
+#define MPI_DOUBLE 0
+#define MPI_CXX_BOOL 0
+#define MPI_CXX_FLOAT_COMPLEX 0
+#define MPI_CXX_DOUBLE_COMPLEX 0
+#define MPI_CXX_LONG_DOUBLE_COMPLEX 0
+#define MPI_IN_PLACE 0
+#define MPI_COMM_WORLD 0
+#define MPI_STATUS_IGNORE 0
+#define MPI_STATUSES_IGNORE 0
+#define MPI_SUM 0
+
+// These declarations are used to mock MPI functions.
+int MPI_Comm_size(MPI_Comm, int *);
+int MPI_Comm_rank(MPI_Comm, int *);
+int MPI_Send(const void *, int, MPI_Datatype, int, int, MPI_Comm);
+int MPI_Recv(void *, int, MPI_Datatype, int, int, MPI_Comm, MPI_Status *);
+int MPI_Isend(const void *, int, MPI_Datatype, int, int, MPI_Comm,
+ MPI_Request *);
+int MPI_Irecv(void *, int, MPI_Datatype, int, int, MPI_Comm, MPI_Request *);
+int MPI_Wait(MPI_Request *, MPI_Status *);
+int MPI_Waitall(int, MPI_Request[], MPI_Status[]);
+int MPI_Reduce(const void *, void *, int, MPI_Datatype, MPI_Op, int, MPI_Comm);
+int MPI_Ireduce(const void *, void *, int, MPI_Datatype, MPI_Op, int, MPI_Comm,
+ MPI_Request *);
+int MPI_Bcast(void *, int count, MPI_Datatype, int, MPI_Comm);
+
+#endif // end of include guard: MPIMOCK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/nolint/trigger_warning.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/nolint/trigger_warning.h
new file mode 100644
index 0000000..e8ebed2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/nolint/trigger_warning.h
@@ -0,0 +1,5 @@
+void A1(const int &In, int &Out) {
+ if (In > 123) // NOLINT
+ Out = 123;
+}
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/overlapping/o.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/overlapping/o.h
new file mode 100644
index 0000000..bfa7a0a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/overlapping/o.h
@@ -0,0 +1,9 @@
+// run: clang-tidy -checks=-*,llvm-include-order -header-filter=.* %s \
+// run: -- -isystem %S/Inputs/Headers -I %S/Inputs/overlapping | \
+// run: not grep "note: this fix will not be applied because it overlaps with another fix"
+
+#include "b.h"
+#include "a.h"
+
+// The comments above are there to match the offset of the #include with the
+// offset of the #includes in the .cpp file.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/performance-unnecessary-value-param/header-fixed.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/performance-unnecessary-value-param/header-fixed.h
new file mode 100644
index 0000000..f3e9e72
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/performance-unnecessary-value-param/header-fixed.h
@@ -0,0 +1,15 @@
+// struct ABC is expensive to copy and should be
+// passed as a const referece.
+struct ABC {
+ ABC(const ABC&);
+ int get(int) const;
+};
+
+
+int f1(int n, const ABC& v1, const ABC& v2); // line 9
+
+int f1(int n, ABC v1); // line 11
+
+
+
+int f2( int n, const ABC& v2); // line 15
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/performance-unnecessary-value-param/header.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/performance-unnecessary-value-param/header.h
new file mode 100644
index 0000000..3f55c79
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/performance-unnecessary-value-param/header.h
@@ -0,0 +1,15 @@
+// struct ABC is expensive to copy and should be
+// passed as a const referece.
+struct ABC {
+ ABC(const ABC&);
+ int get(int) const;
+};
+
+
+int f1(int n, ABC v1, ABC v2); // line 9
+
+int f1(int n, ABC v1); // line 11
+
+
+
+int f2( int n, ABC v2); // line 15
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/readability-identifier-naming/system/system-header.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/readability-identifier-naming/system/system-header.h
new file mode 100644
index 0000000..8a394a9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/readability-identifier-naming/system/system-header.h
@@ -0,0 +1,17 @@
+#ifndef SYSTEM_HEADER_H
+#define SYSTEM_HEADER_H
+
+#define SYSTEM_MACRO(m) int m = 0
+
+namespace SYSTEM_NS {
+class structure {
+ int member;
+};
+
+float global;
+
+void function() {
+}
+}
+
+#endif // SYSTEM_HEADER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/readability-identifier-naming/user-header.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/readability-identifier-naming/user-header.h
new file mode 100644
index 0000000..f03982c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/readability-identifier-naming/user-header.h
@@ -0,0 +1,17 @@
+#ifndef USER_HEADER_H
+#define USER_HEADER_H
+
+#define USER_MACRO(m) int m = 0
+
+namespace USER_NS {
+class object {
+ int member;
+};
+
+float global;
+
+void function() {
+}
+}
+
+#endif // USER_HEADER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/unused-using-decls.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/unused-using-decls.h
new file mode 100644
index 0000000..8245cb1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/unused-using-decls.h
@@ -0,0 +1,11 @@
+class MyClass {
+public:
+ template <template <typename> class S, typename T>
+ S<T> *func1(T *a) {
+ return new S<T>();
+ }
+ template <typename T, T (*S)()>
+ void func2(T a) {
+ S();
+ }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/vfsoverlay/actual_header.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/vfsoverlay/actual_header.h
new file mode 100644
index 0000000..8e1b9ae
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/vfsoverlay/actual_header.h
@@ -0,0 +1 @@
+struct X {};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/vfsoverlay/vfsoverlay.yaml b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/vfsoverlay/vfsoverlay.yaml
new file mode 100644
index 0000000..80d8fba
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/vfsoverlay/vfsoverlay.yaml
@@ -0,0 +1,12 @@
+{
+ 'version': 0,
+ 'roots': [
+ { 'name': 'OUT_DIR', 'type': 'directory',
+ 'contents': [
+ { 'name': 'not_real.h', 'type': 'file',
+ 'external-contents': 'INPUT_DIR/actual_header.h'
+ }
+ ]
+ }
+ ]
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/abseil-string-find-startswith.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/abseil-string-find-startswith.cpp
new file mode 100644
index 0000000..7d5fd73
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/abseil-string-find-startswith.cpp
@@ -0,0 +1,70 @@
+// RUN: %check_clang_tidy %s abseil-string-find-startswith %t -- \
+// RUN: -config="{CheckOptions: [{key: 'abseil-string-find-startswith.StringLikeClasses', value: '::std::basic_string;::basic_string'}]}" \
+// RUN: -- -std=c++11
+
+namespace std {
+template <typename T> class allocator {};
+template <typename T> class char_traits {};
+template <typename C, typename T = std::char_traits<C>,
+ typename A = std::allocator<C>>
+struct basic_string {
+ basic_string();
+ basic_string(const basic_string &);
+ basic_string(const C *, const A &a = A());
+ ~basic_string();
+ int find(basic_string<C> s, int pos = 0);
+ int find(const char *s, int pos = 0);
+};
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+
+struct cxx_string {
+ int find(const char *s, int pos = 0);
+};
+} // namespace std
+
+struct basic_string : public std::cxx_string {
+ basic_string();
+};
+typedef basic_string global_string;
+
+std::string foo(std::string);
+std::string bar();
+
+#define A_MACRO(x, y) ((x) == (y))
+
+void tests(std::string s, global_string s2) {
+ s.find("a") == 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith instead of find() == 0 [abseil-string-find-startswith]
+ // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, "a");{{$}}
+
+ s.find(s) == 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
+ // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, s);{{$}}
+
+ s.find("aaa") != 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
+ // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "aaa");{{$}}
+
+ s.find(foo(foo(bar()))) != 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
+ // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, foo(foo(bar())));{{$}}
+
+ if (s.find("....") == 0) { /* do something */ }
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use absl::StartsWith
+ // CHECK-FIXES: {{^[[:space:]]*}}if (absl::StartsWith(s, "....")) { /* do something */ }{{$}}
+
+ 0 != s.find("a");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
+ // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "a");{{$}}
+
+ s2.find("a") == 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
+ // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s2, "a");{{$}}
+
+ // expressions that don't trigger the check are here.
+ A_MACRO(s.find("a"), 0);
+ s.find("a", 1) == 0;
+ s.find("a", 1) == 1;
+ s.find("a") == 1;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-accept.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-accept.cpp
new file mode 100644
index 0000000..9990594
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-accept.cpp
@@ -0,0 +1,28 @@
+// RUN: %check_clang_tidy %s android-cloexec-accept %t
+
+struct sockaddr {};
+typedef int socklen_t;
+#define NULL 0
+
+extern "C" int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+
+void f() {
+ accept(0, NULL, NULL);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer accept4() to accept() because accept4() allows SOCK_CLOEXEC [android-cloexec-accept]
+ // CHECK-FIXES: accept4(0, NULL, NULL, SOCK_CLOEXEC);
+}
+
+namespace i {
+int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+void g() {
+ accept(0, NULL, NULL);
+}
+} // namespace i
+
+class C {
+public:
+ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+ void h() {
+ accept(0, NULL, NULL);
+ }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-accept4.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-accept4.cpp
new file mode 100644
index 0000000..448d4a9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-accept4.cpp
@@ -0,0 +1,66 @@
+// RUN: %check_clang_tidy %s android-cloexec-accept4 %t
+
+typedef int socklen_t;
+struct sockaddr {};
+
+#define SOCK_NONBLOCK 1
+#define __O_CLOEXEC 3
+#define SOCK_CLOEXEC __O_CLOEXEC
+#define TEMP_FAILURE_RETRY(exp) \
+ ({ \
+ int _rc; \
+ do { \
+ _rc = (exp); \
+ } while (_rc == -1); \
+ })
+#define NULL 0
+
+extern "C" int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
+
+void a() {
+ accept4(0, NULL, NULL, SOCK_NONBLOCK);
+ // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: 'accept4' should use SOCK_CLOEXEC where possible [android-cloexec-accept4]
+ // CHECK-FIXES: accept4(0, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
+ TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, SOCK_NONBLOCK));
+ // CHECK-MESSAGES: :[[@LINE-1]]:58: warning: 'accept4'
+ // CHECK-FIXES: TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC));
+}
+
+void f() {
+ accept4(0, NULL, NULL, 3);
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: 'accept4'
+ // CHECK-FIXES: accept4(0, NULL, NULL, 3 | SOCK_CLOEXEC);
+ TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, 3));
+ // CHECK-MESSAGES: :[[@LINE-1]]:46: warning: 'accept4'
+ // CHECK-FIXES: TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, 3 | SOCK_CLOEXEC));
+
+ int flag = SOCK_NONBLOCK;
+ accept4(0, NULL, NULL, flag);
+ TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, flag));
+}
+
+namespace i {
+int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
+
+void d() {
+ accept4(0, NULL, NULL, SOCK_NONBLOCK);
+ TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, SOCK_NONBLOCK));
+}
+
+} // namespace i
+
+void e() {
+ accept4(0, NULL, NULL, SOCK_CLOEXEC);
+ TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, SOCK_CLOEXEC));
+ accept4(0, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
+ TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC));
+}
+
+class G {
+public:
+ int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
+ void d() {
+ accept4(0, NULL, NULL, SOCK_NONBLOCK);
+ TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, SOCK_NONBLOCK));
+ }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-creat.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-creat.cpp
new file mode 100644
index 0000000..df57b10
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-creat.cpp
@@ -0,0 +1,35 @@
+// RUN: %check_clang_tidy %s android-cloexec-creat %t
+
+typedef int mode_t;
+
+extern "C" int creat(const char *path, mode_t, ...);
+extern "C" int create(const char *path, mode_t, ...);
+
+void f() {
+ creat("filename", 0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer open() to creat() because open() allows O_CLOEXEC [android-cloexec-creat]
+ // CHECK-FIXES: open ("filename", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0);
+ create("filename", 0);
+ // CHECK-MESSAGES-NOT: warning:
+ mode_t mode = 0755;
+ creat("filename", mode);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning:
+ // CHECK-FIXES: open ("filename", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode);
+}
+
+namespace i {
+int creat(const char *path, mode_t, ...);
+void g() {
+ creat("filename", 0);
+ // CHECK-MESSAGES-NOT: warning:
+}
+} // namespace i
+
+class C {
+public:
+ int creat(const char *path, mode_t, ...);
+ void h() {
+ creat("filename", 0);
+ // CHECK-MESSAGES-NOT: warning:
+ }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-dup.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-dup.cpp
new file mode 100644
index 0000000..f7011b8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-dup.cpp
@@ -0,0 +1,31 @@
+// RUN: %check_clang_tidy %s android-cloexec-dup %t
+
+extern "C" int dup(int oldfd);
+void f() {
+ dup(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer fcntl() to dup() because fcntl() allows F_DUPFD_CLOEXEC [android-cloexec-dup]
+ // CHECK-FIXES: fcntl(1, F_DUPFD_CLOEXEC);
+ int oldfd = 0;
+ dup(oldfd);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer
+ // CHECK-FIXES: fcntl(oldfd, F_DUPFD_CLOEXEC);
+}
+
+namespace i {
+int dup(int oldfd);
+void g() {
+ dup(0);
+ int oldfd = 1;
+ dup(oldfd);
+}
+} // namespace i
+
+class C {
+public:
+ int dup(int oldfd);
+ void h() {
+ dup(0);
+ int oldfd = 1;
+ dup(oldfd);
+ }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-epoll-create.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-epoll-create.cpp
new file mode 100644
index 0000000..d58e493
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-epoll-create.cpp
@@ -0,0 +1,24 @@
+// RUN: %check_clang_tidy %s android-cloexec-epoll-create %t
+
+extern "C" int epoll_create(int size);
+
+void f() {
+ epoll_create(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer epoll_create() to epoll_create1() because epoll_create1() allows EPOLL_CLOEXEC [android-cloexec-epoll-create]
+ // CHECK-FIXES: epoll_create1(EPOLL_CLOEXEC);
+}
+
+namespace i {
+int epoll_create(int size);
+void g() {
+ epoll_create(0);
+}
+} // namespace i
+
+class C {
+public:
+ int epoll_create(int size);
+ void h() {
+ epoll_create(0);
+ }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-epoll-create1.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-epoll-create1.cpp
new file mode 100644
index 0000000..696a20c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-epoll-create1.cpp
@@ -0,0 +1,59 @@
+// RUN: %check_clang_tidy %s android-cloexec-epoll-create1 %t
+
+#define __O_CLOEXEC 3
+#define EPOLL_CLOEXEC __O_CLOEXEC
+#define TEMP_FAILURE_RETRY(exp) \
+ ({ \
+ int _rc; \
+ do { \
+ _rc = (exp); \
+ } while (_rc == -1); \
+ })
+
+extern "C" int epoll_create1(int flags);
+
+void a() {
+ epoll_create1(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'epoll_create1' should use EPOLL_CLOEXEC where possible [android-cloexec-epoll-create1]
+ // CHECK-FIXES: epoll_create1(EPOLL_CLOEXEC);
+ TEMP_FAILURE_RETRY(epoll_create1(0));
+ // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 'epoll_create1'
+ // CHECK-FIXES: TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
+}
+
+void f() {
+ epoll_create1(3);
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'epoll_create1'
+ // CHECK-FIXES: epoll_create1(EPOLL_CLOEXEC);
+ TEMP_FAILURE_RETRY(epoll_create1(3));
+ // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 'epoll_create1'
+ // CHECK-FIXES: TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
+
+ int flag = 0;
+ epoll_create1(EPOLL_CLOEXEC);
+ TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
+}
+
+namespace i {
+int epoll_create1(int flags);
+
+void d() {
+ epoll_create1(0);
+ TEMP_FAILURE_RETRY(epoll_create1(0));
+}
+
+} // namespace i
+
+void e() {
+ epoll_create1(EPOLL_CLOEXEC);
+ TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
+}
+
+class G {
+public:
+ int epoll_create1(int flags);
+ void d() {
+ epoll_create1(EPOLL_CLOEXEC);
+ TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
+ }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-fopen.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-fopen.cpp
new file mode 100644
index 0000000..6b6c655
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-fopen.cpp
@@ -0,0 +1,57 @@
+// RUN: %check_clang_tidy %s android-cloexec-fopen %t
+
+#define FILE_OPEN_RO "r"
+
+typedef int FILE;
+
+extern "C" FILE *fopen(const char *filename, const char *mode, ...);
+extern "C" FILE *open(const char *filename, const char *mode, ...);
+
+void f() {
+ fopen("filename", "r");
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use 'fopen' mode 'e' to set O_CLOEXEC [android-cloexec-fopen]
+ // CHECK-FIXES: fopen("filename", "re");
+
+ fopen("filename", FILE_OPEN_RO);
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use 'fopen' mode 'e'
+ // CHECK-FIXES: fopen("filename", FILE_OPEN_RO "e");
+
+ fopen("filename", "er");
+ // CHECK-MESSAGES-NOT: warning:
+ fopen("filename", "re");
+ // CHECK-MESSAGES-NOT: warning:
+ fopen("filename", "e");
+ // CHECK-MESSAGES-NOT: warning:
+ open("filename", "e");
+ // CHECK-MESSAGES-NOT: warning:
+
+ char *str = "r";
+ fopen("filename", str);
+ // CHECK-MESSAGES-NOT: warning:
+ str = "re";
+ fopen("filename", str);
+ // CHECK-MESSAGES-NOT: warning:
+ char arr[2] = "r";
+ fopen("filename", arr);
+ // CHECK-MESSAGES-NOT: warning:
+ char arr2[3] = "re";
+ fopen("filename", arr2);
+ // CHECK-MESSAGES-NOT: warning:
+}
+
+namespace i {
+int *fopen(const char *filename, const char *mode, ...);
+void g() {
+ fopen("filename", "e");
+ // CHECK-MESSAGES-NOT: warning:
+}
+} // namespace i
+
+class C {
+public:
+ int *fopen(const char *filename, const char *mode, ...);
+ void h() {
+ fopen("filename", "e");
+ // CHECK-MESSAGES-NOT: warning:
+ }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-inotify-init.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-inotify-init.cpp
new file mode 100644
index 0000000..01eb51e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-inotify-init.cpp
@@ -0,0 +1,24 @@
+// RUN: %check_clang_tidy %s android-cloexec-inotify-init %t
+
+extern "C" int inotify_init();
+
+void f() {
+ inotify_init();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer inotify_init() to inotify_init1() because inotify_init1() allows IN_CLOEXEC [android-cloexec-inotify-init]
+ // CHECK-FIXES: inotify_init1(IN_CLOEXEC);
+}
+
+namespace i {
+int inotify_init();
+void g() {
+ inotify_init();
+}
+} // namespace i
+
+class C {
+public:
+ int inotify_init();
+ void h() {
+ inotify_init();
+ }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-inotify-init1.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-inotify-init1.cpp
new file mode 100644
index 0000000..2b74fad
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-inotify-init1.cpp
@@ -0,0 +1,64 @@
+// RUN: %check_clang_tidy %s android-cloexec-inotify-init1 %t
+
+#define IN_NONBLOCK 1
+#define __O_CLOEXEC 3
+#define IN_CLOEXEC __O_CLOEXEC
+#define TEMP_FAILURE_RETRY(exp) \
+ ({ \
+ int _rc; \
+ do { \
+ _rc = (exp); \
+ } while (_rc == -1); \
+ })
+
+extern "C" int inotify_init1(int flags);
+
+void a() {
+ inotify_init1(IN_NONBLOCK);
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: 'inotify_init1' should use IN_CLOEXEC where possible [android-cloexec-inotify-init1]
+ // CHECK-FIXES: inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+ TEMP_FAILURE_RETRY(inotify_init1(IN_NONBLOCK));
+ // CHECK-MESSAGES: :[[@LINE-1]]:47: warning: 'inotify_init1'
+ // CHECK-FIXES: TEMP_FAILURE_RETRY(inotify_init1(IN_NONBLOCK | IN_CLOEXEC));
+}
+
+void f() {
+ inotify_init1(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'inotify_init1'
+ // CHECK-FIXES: inotify_init1(IN_CLOEXEC);
+ TEMP_FAILURE_RETRY(inotify_init1(0));
+ // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 'inotify_init1'
+ // CHECK-FIXES: TEMP_FAILURE_RETRY(inotify_init1(IN_CLOEXEC));
+
+ int flag = 1;
+ inotify_init1(flag);
+ TEMP_FAILURE_RETRY(inotify_init1(flag));
+}
+
+namespace i {
+int inotify_init1(int flags);
+
+void d() {
+ inotify_init1(IN_NONBLOCK);
+ TEMP_FAILURE_RETRY(inotify_init1(IN_NONBLOCK));
+}
+
+} // namespace i
+
+void e() {
+ inotify_init1(IN_CLOEXEC);
+ TEMP_FAILURE_RETRY(inotify_init1(IN_CLOEXEC));
+ inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+ TEMP_FAILURE_RETRY(inotify_init1(IN_NONBLOCK | IN_CLOEXEC));
+}
+
+class G {
+public:
+ int inotify_init1(int flags);
+ void d() {
+ inotify_init1(IN_CLOEXEC);
+ TEMP_FAILURE_RETRY(inotify_init1(IN_CLOEXEC));
+ inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+ TEMP_FAILURE_RETRY(inotify_init1(IN_NONBLOCK | IN_CLOEXEC));
+ }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-memfd-create.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-memfd-create.cpp
new file mode 100644
index 0000000..a8dafd5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-memfd-create.cpp
@@ -0,0 +1,63 @@
+// RUN: %check_clang_tidy %s android-cloexec-memfd-create %t
+
+#define MFD_ALLOW_SEALING 1
+#define __O_CLOEXEC 3
+#define MFD_CLOEXEC __O_CLOEXEC
+#define TEMP_FAILURE_RETRY(exp) \
+ ({ \
+ int _rc; \
+ do { \
+ _rc = (exp); \
+ } while (_rc == -1); \
+ })
+#define NULL 0
+
+extern "C" int memfd_create(const char *name, unsigned int flags);
+
+void a() {
+ memfd_create(NULL, MFD_ALLOW_SEALING);
+ // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: 'memfd_create' should use MFD_CLOEXEC where possible [android-cloexec-memfd-create]
+ // CHECK-FIXES: memfd_create(NULL, MFD_ALLOW_SEALING | MFD_CLOEXEC)
+ TEMP_FAILURE_RETRY(memfd_create(NULL, MFD_ALLOW_SEALING));
+ // CHECK-MESSAGES: :[[@LINE-1]]:58: warning: 'memfd_create'
+ // CHECK-FIXES: TEMP_FAILURE_RETRY(memfd_create(NULL, MFD_ALLOW_SEALING | MFD_CLOEXEC))
+}
+
+void f() {
+ memfd_create(NULL, 3);
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 'memfd_create'
+ // CHECK-FIXES: memfd_create(NULL, 3 | MFD_CLOEXEC)
+ TEMP_FAILURE_RETRY(memfd_create(NULL, 3));
+ // CHECK-MESSAGES: :[[@LINE-1]]:42: warning: 'memfd_create'
+ // CHECK-FIXES: TEMP_FAILURE_RETRY(memfd_create(NULL, 3 | MFD_CLOEXEC))
+
+ int flag = 3;
+ memfd_create(NULL, flag);
+ TEMP_FAILURE_RETRY(memfd_create(NULL, flag));
+}
+
+namespace i {
+int memfd_create(const char *name, unsigned int flags);
+
+void d() {
+ memfd_create(NULL, MFD_ALLOW_SEALING);
+ TEMP_FAILURE_RETRY(memfd_create(NULL, MFD_ALLOW_SEALING));
+}
+
+} // namespace i
+
+void e() {
+ memfd_create(NULL, MFD_CLOEXEC);
+ TEMP_FAILURE_RETRY(memfd_create(NULL, MFD_CLOEXEC));
+ memfd_create(NULL, MFD_ALLOW_SEALING | MFD_CLOEXEC);
+ TEMP_FAILURE_RETRY(memfd_create(NULL, MFD_ALLOW_SEALING | MFD_CLOEXEC));
+}
+
+class G {
+public:
+ int memfd_create(const char *name, unsigned int flags);
+ void d() {
+ memfd_create(NULL, MFD_ALLOW_SEALING);
+ TEMP_FAILURE_RETRY(memfd_create(NULL, MFD_ALLOW_SEALING));
+ }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-open.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-open.cpp
new file mode 100644
index 0000000..4ef1f40
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-open.cpp
@@ -0,0 +1,180 @@
+// RUN: %check_clang_tidy %s android-cloexec-open %t
+
+#define O_RDWR 1
+#define O_EXCL 2
+#define __O_CLOEXEC 3
+#define O_CLOEXEC __O_CLOEXEC
+#define TEMP_FAILURE_RETRY(exp) \
+ ({ \
+ int _rc; \
+ do { \
+ _rc = (exp); \
+ } while (_rc == -1); \
+ })
+
+extern "C" int open(const char *fn, int flags, ...);
+extern "C" int open64(const char *fn, int flags, ...);
+extern "C" int openat(int dirfd, const char *pathname, int flags, ...);
+
+void a() {
+ open("filename", O_RDWR);
+ // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: 'open' should use O_CLOEXEC where possible [android-cloexec-open]
+ // CHECK-FIXES: O_RDWR | O_CLOEXEC
+ TEMP_FAILURE_RETRY(open("filename", O_RDWR));
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: 'open' should use O_CLOEXEC where
+ // CHECK-FIXES: O_RDWR | O_CLOEXEC
+ open("filename", O_RDWR | O_EXCL);
+ // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: 'open' should use O_CLOEXEC where
+ // CHECK-FIXES: O_RDWR | O_EXCL | O_CLOEXEC
+ TEMP_FAILURE_RETRY(open("filename", O_RDWR | O_EXCL));
+ // CHECK-MESSAGES: :[[@LINE-1]]:54: warning: 'open' should use O_CLOEXEC where
+ // CHECK-FIXES: O_RDWR | O_EXCL | O_CLOEXEC
+}
+
+void b() {
+ open64("filename", O_RDWR);
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: 'open64' should use O_CLOEXEC where possible [android-cloexec-open]
+ // CHECK-FIXES: O_RDWR | O_CLOEXEC
+ TEMP_FAILURE_RETRY(open64("filename", O_RDWR));
+ // CHECK-MESSAGES: :[[@LINE-1]]:47: warning: 'open64' should use O_CLOEXEC where
+ // CHECK-FIXES: O_RDWR | O_CLOEXEC
+ open64("filename", O_RDWR | O_EXCL);
+ // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 'open64' should use O_CLOEXEC where
+ // CHECK-FIXES: O_RDWR | O_EXCL | O_CLOEXEC
+ TEMP_FAILURE_RETRY(open64("filename", O_RDWR | O_EXCL));
+ // CHECK-MESSAGES: :[[@LINE-1]]:56: warning: 'open64' should use O_CLOEXEC where
+ // CHECK-FIXES: O_RDWR | O_EXCL | O_CLOEXEC
+}
+
+void c() {
+ openat(0, "filename", O_RDWR);
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: 'openat' should use O_CLOEXEC where possible [android-cloexec-open]
+ // CHECK-FIXES: O_RDWR | O_CLOEXEC
+ TEMP_FAILURE_RETRY(openat(0, "filename", O_RDWR));
+ // CHECK-MESSAGES: :[[@LINE-1]]:50: warning: 'openat' should use O_CLOEXEC where
+ // CHECK-FIXES: O_RDWR | O_CLOEXEC
+ openat(0, "filename", O_RDWR | O_EXCL);
+ // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: 'openat' should use O_CLOEXEC where
+ // CHECK-FIXES: O_RDWR | O_EXCL | O_CLOEXEC
+ TEMP_FAILURE_RETRY(openat(0, "filename", O_RDWR | O_EXCL));
+ // CHECK-MESSAGES: :[[@LINE-1]]:59: warning: 'openat' should use O_CLOEXEC where
+ // CHECK-FIXES: O_RDWR | O_EXCL | O_CLOEXEC
+}
+
+void f() {
+ open("filename", 3);
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: 'open' should use O_CLOEXEC where possible [android-cloexec-open]
+ // CHECK-FIXES: 3 | O_CLOEXEC
+ TEMP_FAILURE_RETRY(open("filename", 3));
+ // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: 'open' should use O_CLOEXEC where
+ // CHECK-FIXES: 3 | O_CLOEXEC
+ open64("filename", 3);
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 'open64' should use O_CLOEXEC where possible [android-cloexec-open]
+ // CHECK-FIXES: 3 | O_CLOEXEC
+ TEMP_FAILURE_RETRY(open64("filename", 3));
+ // CHECK-MESSAGES: :[[@LINE-1]]:42: warning: 'open64' should use O_CLOEXEC where
+ // CHECK-FIXES: 3 | O_CLOEXEC
+ openat(0, "filename", 3);
+ // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: 'openat' should use O_CLOEXEC where possible [android-cloexec-open]
+ // CHECK-FIXES: 3 | O_CLOEXEC
+ TEMP_FAILURE_RETRY(openat(0, "filename", 3));
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: 'openat' should use O_CLOEXEC where
+ // CHECK-FIXES: 3 | O_CLOEXEC
+
+ int flag = 3;
+ open("filename", flag);
+ // CHECK-MESSAGES-NOT: warning:
+ TEMP_FAILURE_RETRY(open("filename", flag));
+ // CHECK-MESSAGES-NOT: warning:
+ open64("filename", flag);
+ // CHECK-MESSAGES-NOT: warning:
+ TEMP_FAILURE_RETRY(open64("filename", flag));
+ // CHECK-MESSAGES-NOT: warning:
+ openat(0, "filename", flag);
+ // CHECK-MESSAGES-NOT: warning:
+ TEMP_FAILURE_RETRY(openat(0, "filename", flag));
+ // CHECK-MESSAGES-NOT: warning:
+}
+
+namespace i {
+int open(const char *pathname, int flags, ...);
+int open64(const char *pathname, int flags, ...);
+int openat(int dirfd, const char *pathname, int flags, ...);
+
+void d() {
+ open("filename", O_RDWR);
+ // CHECK-MESSAGES-NOT: warning:
+ TEMP_FAILURE_RETRY(open("filename", O_RDWR));
+ // CHECK-MESSAGES-NOT: warning:
+ open64("filename", O_RDWR);
+ // CHECK-MESSAGES-NOT: warning:
+ TEMP_FAILURE_RETRY(open64("filename", O_RDWR));
+ // CHECK-MESSAGES-NOT: warning:
+ openat(0, "filename", O_RDWR);
+ // CHECK-MESSAGES-NOT: warning:
+ TEMP_FAILURE_RETRY(openat(0, "filename", O_RDWR));
+ // CHECK-MESSAGES-NOT: warning:
+}
+
+} // namespace i
+
+void e() {
+ open("filename", O_CLOEXEC);
+ // CHECK-MESSAGES-NOT: warning:
+ TEMP_FAILURE_RETRY(open("filename", O_CLOEXEC));
+ // CHECK-MESSAGES-NOT: warning:
+ open("filename", O_RDWR | O_CLOEXEC);
+ // CHECK-MESSAGES-NOT: warning:
+ TEMP_FAILURE_RETRY(open("filename", O_RDWR | O_CLOEXEC));
+ // CHECK-MESSAGES-NOT: warning:
+ open("filename", O_RDWR | O_CLOEXEC | O_EXCL);
+ // CHECK-MESSAGES-NOT: warning:
+ TEMP_FAILURE_RETRY(open("filename", O_RDWR | O_CLOEXEC | O_EXCL));
+ // CHECK-MESSAGES-NOT: warning:
+ open64("filename", O_CLOEXEC);
+ // CHECK-MESSAGES-NOT: warning:
+ TEMP_FAILURE_RETRY(open64("filename", O_CLOEXEC));
+ // CHECK-MESSAGES-NOT: warning:
+ open64("filename", O_RDWR | O_CLOEXEC);
+ // CHECK-MESSAGES-NOT: warning:
+ TEMP_FAILURE_RETRY(open64("filename", O_RDWR | O_CLOEXEC));
+ // CHECK-MESSAGES-NOT: warning:
+ open64("filename", O_RDWR | O_CLOEXEC | O_EXCL);
+ // CHECK-MESSAGES-NOT: warning:
+ TEMP_FAILURE_RETRY(open64("filename", O_RDWR | O_CLOEXEC | O_EXCL));
+ // CHECK-MESSAGES-NOT: warning:
+ openat(0, "filename", O_CLOEXEC);
+ // CHECK-MESSAGES-NOT: warning:
+ TEMP_FAILURE_RETRY(openat(0, "filename", O_CLOEXEC));
+ // CHECK-MESSAGES-NOT: warning:
+ openat(0, "filename", O_RDWR | O_CLOEXEC);
+ // CHECK-MESSAGES-NOT: warning:
+ TEMP_FAILURE_RETRY(openat(0, "filename", O_RDWR | O_CLOEXEC));
+ // CHECK-MESSAGES-NOT: warning:
+ openat(0, "filename", O_RDWR | O_CLOEXEC | O_EXCL);
+ // CHECK-MESSAGES-NOT: warning:
+ TEMP_FAILURE_RETRY(openat(0, "filename", O_RDWR | O_CLOEXEC | O_EXCL));
+ // CHECK-MESSAGES-NOT: warning:
+}
+
+class G {
+public:
+ int open(const char *pathname, int flags, ...);
+ int open64(const char *pathname, int flags, ...);
+ int openat(int dirfd, const char *pathname, int flags, ...);
+
+ void h() {
+ open("filename", O_RDWR);
+ // CHECK-MESSAGES-NOT: warning:
+ TEMP_FAILURE_RETRY(open("filename", O_RDWR));
+ // CHECK-MESSAGES-NOT: warning:
+ open64("filename", O_RDWR);
+ // CHECK-MESSAGES-NOT: warning:
+ TEMP_FAILURE_RETRY(open64("filename", O_RDWR));
+ // CHECK-MESSAGES-NOT: warning:
+ openat(0, "filename", O_RDWR);
+ // CHECK-MESSAGES-NOT: warning:
+ TEMP_FAILURE_RETRY(openat(0, "filename", O_RDWR));
+ // CHECK-MESSAGES-NOT: warning:
+ }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-socket.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-socket.cpp
new file mode 100644
index 0000000..25f332d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-socket.cpp
@@ -0,0 +1,75 @@
+// RUN: %check_clang_tidy %s android-cloexec-socket %t
+
+#define SOCK_STREAM 1
+#define SOCK_DGRAM 2
+#define __O_CLOEXEC 3
+#define SOCK_CLOEXEC __O_CLOEXEC
+#define TEMP_FAILURE_RETRY(exp) \
+ ({ \
+ int _rc; \
+ do { \
+ _rc = (exp); \
+ } while (_rc == -1); \
+ })
+
+extern "C" int socket(int domain, int type, int protocol);
+
+void a() {
+ socket(0, SOCK_STREAM, 0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: 'socket' should use SOCK_CLOEXEC where possible [android-cloexec-socket]
+ // CHECK-FIXES: socket(0, SOCK_STREAM | SOCK_CLOEXEC, 0)
+ TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM, 0));
+ // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: 'socket'
+ // CHECK-FIXES: TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_CLOEXEC, 0))
+ socket(0, SOCK_STREAM | SOCK_DGRAM, 0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 'socket'
+ // CHECK-FIXES: socket(0, SOCK_STREAM | SOCK_DGRAM | SOCK_CLOEXEC, 0)
+ TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_DGRAM, 0));
+ // CHECK-MESSAGES: :[[@LINE-1]]:56: warning: 'socket'
+ // CHECK-FIXES: TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_DGRAM | SOCK_CLOEXEC, 0))
+}
+
+void f() {
+ socket(0, 3, 0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: 'socket'
+ // CHECK-FIXES: socket(0, 3 | SOCK_CLOEXEC, 0)
+ TEMP_FAILURE_RETRY(socket(0, 3, 0));
+ // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: 'socket'
+ // CHECK-FIXES: TEMP_FAILURE_RETRY(socket(0, 3 | SOCK_CLOEXEC, 0))
+
+ int flag = 3;
+ socket(0, flag, 0);
+ TEMP_FAILURE_RETRY(socket(0, flag, 0));
+}
+
+namespace i {
+int socket(int domain, int type, int protocol);
+
+void d() {
+ socket(0, SOCK_STREAM, 0);
+ TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM, 0));
+ socket(0, SOCK_STREAM | SOCK_DGRAM, 0);
+ TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_DGRAM, 0));
+}
+
+} // namespace i
+
+void e() {
+ socket(0, SOCK_CLOEXEC, 0);
+ TEMP_FAILURE_RETRY(socket(0, SOCK_CLOEXEC, 0));
+ socket(0, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_CLOEXEC, 0));
+ socket(0, SOCK_STREAM | SOCK_CLOEXEC | SOCK_DGRAM, 0);
+ TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_CLOEXEC | SOCK_DGRAM, 0));
+}
+
+class G {
+public:
+ int socket(int domain, int type, int protocol);
+ void d() {
+ socket(0, SOCK_STREAM, 0);
+ TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM, 0));
+ socket(0, SOCK_STREAM | SOCK_DGRAM, 0);
+ TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_DGRAM, 0));
+ }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-comparison-in-temp-failure-retry.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-comparison-in-temp-failure-retry.c
new file mode 100644
index 0000000..3be3eec
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-comparison-in-temp-failure-retry.c
@@ -0,0 +1,148 @@
+// RUN: %check_clang_tidy %s android-comparison-in-temp-failure-retry %t
+
+#define TEMP_FAILURE_RETRY(x) \
+ ({ \
+ typeof(x) __z; \
+ do \
+ __z = (x); \
+ while (__z == -1); \
+ __z; \
+ })
+
+int foo();
+int bar(int a);
+
+void test() {
+ int i;
+ TEMP_FAILURE_RETRY((i = foo()));
+ TEMP_FAILURE_RETRY(foo());
+ TEMP_FAILURE_RETRY((foo()));
+
+ TEMP_FAILURE_RETRY(foo() == 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: top-level comparison in TEMP_FAILURE_RETRY [android-comparison-in-temp-failure-retry]
+ TEMP_FAILURE_RETRY((foo() == 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: top-level comparison in TEMP_FAILURE_RETRY
+ TEMP_FAILURE_RETRY((int)(foo() == 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+ TEMP_FAILURE_RETRY(bar(foo() == 1));
+ TEMP_FAILURE_RETRY((bar(foo() == 1)));
+ TEMP_FAILURE_RETRY((bar(foo() == 1)) == 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: top-level comparison in TEMP_FAILURE_RETRY
+ TEMP_FAILURE_RETRY(((bar(foo() == 1)) == 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:41: warning: top-level comparison in TEMP_FAILURE_RETRY
+ TEMP_FAILURE_RETRY((int)((bar(foo() == 1)) == 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:46: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+#define INDIRECT TEMP_FAILURE_RETRY
+ INDIRECT(foo());
+ INDIRECT((foo() == 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: top-level comparison in TEMP_FAILURE_RETRY
+ INDIRECT(bar(foo() == 1));
+ INDIRECT((int)((bar(foo() == 1)) == 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+#define TFR(x) TEMP_FAILURE_RETRY(x)
+ TFR(foo());
+ TFR((foo() == 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: top-level comparison in TEMP_FAILURE_RETRY
+ TFR(bar(foo() == 1));
+ TFR((int)((bar(foo() == 1)) == 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+#define ADD_TFR(x) (1 + TEMP_FAILURE_RETRY(x) + 1)
+ ADD_TFR(foo());
+ ADD_TFR(foo() == 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+ ADD_TFR(bar(foo() == 1));
+ ADD_TFR((int)((bar(foo() == 1)) == 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+#define ADDP_TFR(x) (1 + TEMP_FAILURE_RETRY((x)) + 1)
+ ADDP_TFR(foo());
+ ADDP_TFR((foo() == 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+ ADDP_TFR(bar(foo() == 1));
+ ADDP_TFR((int)((bar(foo() == 1)) == 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+#define MACRO TEMP_FAILURE_RETRY(foo() == 1)
+ MACRO;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+ // Be sure that being a macro arg doesn't mess with this.
+#define ID(x) (x)
+ ID(ADDP_TFR(bar(foo() == 1)));
+ ID(ADDP_TFR(bar(foo() == 1) == 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: top-level comparison in TEMP_FAILURE_RETRY
+ ID(MACRO);
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+#define CMP(x) x == 1
+ TEMP_FAILURE_RETRY(CMP(foo()));
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: top-level comparison in TEMP_FAILURE_RETRY
+}
+
+// Be sure that it works inside of things like loops, if statements, etc.
+void control_flow() {
+ do {
+ if (TEMP_FAILURE_RETRY(foo())) {
+ }
+
+ if (TEMP_FAILURE_RETRY(foo() == 1)) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: top-level comparison in TEMP_FAILURE_RETRY
+ }
+
+ if (TEMP_FAILURE_RETRY(bar(foo() == 1))) {
+ }
+
+ if (TEMP_FAILURE_RETRY(bar(foo() == 1) == 1)) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: top-level comparison in TEMP_FAILURE_RETRY
+ }
+ } while (TEMP_FAILURE_RETRY(foo() == 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: top-level comparison in TEMP_FAILURE_RETRY
+}
+
+void with_nondependent_variable_type() {
+#undef TEMP_FAILURE_RETRY
+#define TEMP_FAILURE_RETRY(x) \
+ ({ \
+ long int __z; \
+ do \
+ __z = (x); \
+ while (__z == -1); \
+ __z; \
+ })
+
+ TEMP_FAILURE_RETRY((foo()));
+ TEMP_FAILURE_RETRY((int)(foo() == 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: top-level comparison in TEMP_FAILURE_RETRY
+ TEMP_FAILURE_RETRY((bar(foo() == 1)));
+ TEMP_FAILURE_RETRY((int)((bar(foo() == 1)) == 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:46: warning: top-level comparison in TEMP_FAILURE_RETRY
+}
+
+// I can't find a case where TEMP_FAILURE_RETRY is implemented like this, but if
+// we can cheaply support it, I don't see why not.
+void obscured_temp_failure_retry() {
+#undef TEMP_FAILURE_RETRY
+#define IMPL(x) \
+ ({ \
+ typeof(x) __z; \
+ do \
+ __z = (x); \
+ while (__z == -1); \
+ __z; \
+ })
+
+#define IMPL2(x) IMPL(x)
+#define TEMP_FAILURE_RETRY(x) IMPL2(x)
+ TEMP_FAILURE_RETRY((foo()));
+ TEMP_FAILURE_RETRY((int)(foo() == 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: top-level comparison in TEMP_FAILURE_RETRY
+ TEMP_FAILURE_RETRY((bar(foo() == 1)));
+ TEMP_FAILURE_RETRY((int)((bar(foo() == 1)) == 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:46: warning: top-level comparison in TEMP_FAILURE_RETRY
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/basic.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/basic.cpp
new file mode 100644
index 0000000..12eb6fe
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/basic.cpp
@@ -0,0 +1,6 @@
+// RUN: clang-tidy %s -checks='-*,llvm-namespace-comment' -- | FileCheck %s
+// RUN: c-index-test -test-load-source-reparse 2 all %s -Xclang -add-plugin -Xclang clang-tidy -Xclang -plugin-arg-clang-tidy -Xclang -checks='-*,llvm-namespace-comment' 2>&1 | FileCheck %s
+
+namespace i {
+}
+// CHECK: warning: namespace 'i' not terminated with a closing comment [llvm-namespace-comment]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/boost-use-to-string.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/boost-use-to-string.cpp
new file mode 100644
index 0000000..44ba172
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/boost-use-to-string.cpp
@@ -0,0 +1,169 @@
+// RUN: %check_clang_tidy %s boost-use-to-string %t
+
+namespace std {
+
+template <typename T>
+class basic_string {};
+
+using string = basic_string<char>;
+using wstring = basic_string<wchar_t>;
+}
+
+namespace boost {
+template <typename T, typename V>
+T lexical_cast(const V &) {
+ return T();
+};
+}
+
+struct my_weird_type {};
+
+std::string fun(const std::string &) {}
+
+void test_to_string1() {
+
+ auto xa = boost::lexical_cast<std::string>(5);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::to_string instead of boost::lexical_cast<std::string> [boost-use-to-string]
+ // CHECK-FIXES: auto xa = std::to_string(5);
+
+ auto z = boost::lexical_cast<std::string>(42LL);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use std::to_string
+ // CHECK-FIXES: auto z = std::to_string(42LL);
+
+ // this should not trigger
+ fun(boost::lexical_cast<std::string>(42.0));
+ auto non = boost::lexical_cast<my_weird_type>(42);
+ boost::lexical_cast<int>("12");
+}
+
+void test_to_string2() {
+ int a;
+ long b;
+ long long c;
+ unsigned d;
+ unsigned long e;
+ unsigned long long f;
+ float g;
+ double h;
+ long double i;
+ bool j;
+
+ fun(boost::lexical_cast<std::string>(a));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string
+ // CHECK-FIXES: fun(std::to_string(a));
+ fun(boost::lexical_cast<std::string>(b));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string
+ // CHECK-FIXES: fun(std::to_string(b));
+ fun(boost::lexical_cast<std::string>(c));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string
+ // CHECK-FIXES: fun(std::to_string(c));
+ fun(boost::lexical_cast<std::string>(d));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string
+ // CHECK-FIXES: fun(std::to_string(d));
+ fun(boost::lexical_cast<std::string>(e));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string
+ // CHECK-FIXES: fun(std::to_string(e));
+ fun(boost::lexical_cast<std::string>(f));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string
+ // CHECK-FIXES: fun(std::to_string(f));
+
+ // No change for floating numbers.
+ fun(boost::lexical_cast<std::string>(g));
+ fun(boost::lexical_cast<std::string>(h));
+ fun(boost::lexical_cast<std::string>(i));
+ // And bool.
+ fun(boost::lexical_cast<std::string>(j));
+}
+
+std::string fun(const std::wstring &) {}
+
+void test_to_wstring() {
+ int a;
+ long b;
+ long long c;
+ unsigned d;
+ unsigned long e;
+ unsigned long long f;
+ float g;
+ double h;
+ long double i;
+ bool j;
+
+ fun(boost::lexical_cast<std::wstring>(a));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring instead of boost::lexical_cast<std::wstring> [boost-use-to-string]
+ // CHECK-FIXES: fun(std::to_wstring(a));
+ fun(boost::lexical_cast<std::wstring>(b));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring
+ // CHECK-FIXES: fun(std::to_wstring(b));
+ fun(boost::lexical_cast<std::wstring>(c));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring
+ // CHECK-FIXES: fun(std::to_wstring(c));
+ fun(boost::lexical_cast<std::wstring>(d));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring
+ // CHECK-FIXES: fun(std::to_wstring(d));
+ fun(boost::lexical_cast<std::wstring>(e));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring
+ // CHECK-FIXES: fun(std::to_wstring(e));
+ fun(boost::lexical_cast<std::wstring>(f));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring
+ // CHECK-FIXES: fun(std::to_wstring(f));
+
+ // No change for floating numbers
+ fun(boost::lexical_cast<std::wstring>(g));
+ fun(boost::lexical_cast<std::wstring>(h));
+ fun(boost::lexical_cast<std::wstring>(i));
+ // and bool.
+ fun(boost::lexical_cast<std::wstring>(j));
+}
+
+const auto glob = boost::lexical_cast<std::string>(42);
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use std::to_string
+// CHECK-FIXES: const auto glob = std::to_string(42);
+
+template <typename T>
+void string_as_T(T t = T()) {
+ boost::lexical_cast<std::string>(42);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use std::to_string
+ // CHECK-FIXES: std::to_string(42);
+
+ boost::lexical_cast<T>(42);
+ string_as_T(boost::lexical_cast<T>(42));
+ auto p = boost::lexical_cast<T>(42);
+ auto p2 = (T)boost::lexical_cast<T>(42);
+ auto p3 = static_cast<T>(boost::lexical_cast<T>(42));
+}
+
+#define my_to_string boost::lexical_cast<std::string>
+
+void no_fixup_inside_macro() {
+ my_to_string(12);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use std::to_string
+}
+
+void no_warnings() {
+ fun(boost::lexical_cast<std::string>("abc"));
+ fun(boost::lexical_cast<std::wstring>("abc"));
+ fun(boost::lexical_cast<std::string>(my_weird_type{}));
+ string_as_T<int>();
+ string_as_T<std::string>();
+}
+
+struct Fields {
+ int integer;
+ float floating;
+ Fields* wierd;
+ const int &getConstInteger() const {return integer;}
+};
+
+void testFields() {
+ Fields fields;
+ auto s1 = boost::lexical_cast<std::string>(fields.integer);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::to_string
+ // CHECK-FIXES: auto s1 = std::to_string(fields.integer);
+
+ auto s2 = boost::lexical_cast<std::string>(fields.floating);
+ auto s3 = boost::lexical_cast<std::string>(fields.wierd);
+ auto s4 = boost::lexical_cast<std::string>(fields.getConstInteger());
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::to_string
+ // CHECK-FIXES: auto s4 = std::to_string(fields.getConstInteger());
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-argument-comment-gmock.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-argument-comment-gmock.cpp
new file mode 100644
index 0000000..e79395e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-argument-comment-gmock.cpp
@@ -0,0 +1,108 @@
+// RUN: %check_clang_tidy %s bugprone-argument-comment %t
+
+namespace testing {
+namespace internal {
+
+template <typename F>
+struct Function;
+
+template <typename R>
+struct Function<R()> {
+ typedef R Result;
+};
+
+template <typename R, typename A1>
+struct Function<R(A1)>
+ : Function<R()> {
+ typedef A1 Argument1;
+};
+
+template <typename R, typename A1, typename A2>
+struct Function<R(A1, A2)>
+ : Function<R(A1)> {
+ typedef A2 Argument2;
+};
+
+} // namespace internal
+
+template <typename F>
+class MockSpec {
+ public:
+ void f();
+};
+
+template <typename T>
+class Matcher {
+ public:
+ explicit Matcher();
+ Matcher(T value);
+};
+
+} // namespace testing
+
+#define GMOCK_RESULT_(tn, ...) \
+ tn ::testing::internal::Function<__VA_ARGS__>::Result
+#define GMOCK_ARG_(tn, N, ...) \
+ tn ::testing::internal::Function<__VA_ARGS__>::Argument##N
+#define GMOCK_MATCHER_(tn, N, ...) \
+ const ::testing::Matcher<GMOCK_ARG_(tn, N, __VA_ARGS__)>&
+#define GMOCK_METHOD2_(tn, constness, ct, Method, ...) \
+ GMOCK_RESULT_(tn, __VA_ARGS__) \
+ ct Method( \
+ GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
+ GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2) constness; \
+ ::testing::MockSpec<__VA_ARGS__> \
+ gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
+ GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2) constness
+#define MOCK_METHOD2(m, ...) GMOCK_METHOD2_(, , , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD2(m, ...) GMOCK_METHOD2_(, const, , m, __VA_ARGS__)
+#define GMOCK_EXPECT_CALL_IMPL_(obj, call) \
+ ((obj).gmock_##call).f()
+#define EXPECT_CALL(obj, call) GMOCK_EXPECT_CALL_IMPL_(obj, call)
+
+class Base {
+ public:
+ virtual void Method(int param_one_base, int param_two_base);
+};
+class Derived : public Base {
+ public:
+ virtual void Method(int param_one, int param_two);
+ virtual void Method2(int p_one, int p_two) const;
+};
+class MockDerived : public Derived {
+ public:
+ MOCK_METHOD2(Method, void(int a, int b));
+ MOCK_CONST_METHOD2(Method2, void(int c, int d));
+};
+
+class MockStandalone {
+ public:
+ MOCK_METHOD2(Method, void(int aaa, int bbb));
+};
+
+void test_gmock_expectations() {
+ MockDerived m;
+ EXPECT_CALL(m, Method(/*param_one=*/1, /*param_tw=*/2));
+// CHECK-MESSAGES: [[@LINE-1]]:42: warning: argument name 'param_tw' in comment does not match parameter name 'param_two'
+// CHECK-FIXES: EXPECT_CALL(m, Method(/*param_one=*/1, /*param_two=*/2));
+ EXPECT_CALL(m, Method2(/*p_on=*/3, /*p_two=*/4));
+// CHECK-MESSAGES: [[@LINE-1]]:26: warning: argument name 'p_on' in comment does not match parameter name 'p_one'
+// CHECK-FIXES: EXPECT_CALL(m, Method2(/*p_one=*/3, /*p_two=*/4));
+
+ #define PARAM1 11
+ #define PARAM2 22
+ EXPECT_CALL(m, Method2(/*p_on1=*/PARAM1, /*p_tw2=*/PARAM2));
+// CHECK-MESSAGES: [[@LINE-1]]:26: warning: argument name 'p_on1' in comment does not match parameter name 'p_one'
+// CHECK-MESSAGES: [[@LINE-2]]:44: warning: argument name 'p_tw2' in comment does not match parameter name 'p_two'
+// CHECK-FIXES: EXPECT_CALL(m, Method2(/*p_one=*/PARAM1, /*p_two=*/PARAM2));
+
+ MockStandalone m2;
+ EXPECT_CALL(m2, Method(/*aaa=*/5, /*bbc=*/6));
+}
+
+void test_gmock_direct_calls() {
+ MockDerived m;
+ m.Method(/*param_one=*/1, /*param_tw=*/2);
+// CHECK-MESSAGES: [[@LINE-1]]:29: warning: argument name 'param_tw' in comment does not match parameter name 'param_two'
+// CHECK-FIXES: m.Method(/*param_one=*/1, /*param_two=*/2);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-argument-comment-strict.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-argument-comment-strict.cpp
new file mode 100644
index 0000000..0e06a4c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-argument-comment-strict.cpp
@@ -0,0 +1,19 @@
+// RUN: %check_clang_tidy %s bugprone-argument-comment %t -- \
+// RUN: -config="{CheckOptions: [{key: StrictMode, value: 1}]}" --
+
+void f(int _with_underscores_);
+void g(int x_);
+void ignores_underscores() {
+ f(/*With_Underscores=*/0);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: argument name 'With_Underscores' in comment does not match parameter name '_with_underscores_'
+// CHECK-FIXES: f(/*_with_underscores_=*/0);
+ f(/*with_underscores=*/1);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: argument name 'with_underscores' in comment does not match parameter name '_with_underscores_'
+// CHECK-FIXES: f(/*_with_underscores_=*/1);
+ f(/*_With_Underscores_=*/2);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: argument name '_With_Underscores_' in comment does not match parameter name '_with_underscores_'
+// CHECK-FIXES: f(/*_with_underscores_=*/2);
+ g(/*X=*/3);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: argument name 'X' in comment does not match parameter name 'x_'
+// CHECK-FIXES: g(/*x_=*/3);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-argument-comment.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-argument-comment.cpp
new file mode 100644
index 0000000..6452791
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-argument-comment.cpp
@@ -0,0 +1,89 @@
+// RUN: %check_clang_tidy %s bugprone-argument-comment %t
+
+// FIXME: clang-tidy should provide a -verify mode to make writing these checks
+// easier and more accurate.
+
+void ffff(int xxxx, int yyyy);
+
+void f(int x, int y);
+void g() {
+ // CHECK-MESSAGES: [[@LINE+4]]:5: warning: argument name 'y' in comment does not match parameter name 'x'
+ // CHECK-MESSAGES: :[[@LINE-3]]:12: note: 'x' declared here
+ // CHECK-MESSAGES: [[@LINE+2]]:14: warning: argument name 'z' in comment does not match parameter name 'y'
+ // CHECK-MESSAGES: :[[@LINE-5]]:19: note: 'y' declared here
+ f(/*y=*/0, /*z=*/0);
+ // CHECK-FIXES: {{^}} f(/*y=*/0, /*z=*/0);
+
+ f(/*x=*/1, /*y=*/1);
+
+ ffff(0 /*aaaa=*/, /*bbbb*/ 0); // Unsupported formats.
+}
+
+struct C {
+ C(int x, int y);
+};
+C c(/*x=*/0, /*y=*/0);
+
+struct Closure {};
+
+template <typename T1, typename T2>
+Closure *NewCallback(void (*f)(T1, T2), T1 arg1, T2 arg2) { return nullptr; }
+
+template <typename T1, typename T2>
+Closure *NewPermanentCallback(void (*f)(T1, T2), T1 arg1, T2 arg2) { return nullptr; }
+
+void h() {
+ (void)NewCallback(&ffff, /*xxxx=*/11, /*yyyy=*/22);
+ (void)NewPermanentCallback(&ffff, /*xxxx=*/11, /*yyyy=*/22);
+}
+
+template<typename... Args>
+void variadic(Args&&... args);
+
+template<typename... Args>
+void variadic2(int zzz, Args&&... args);
+
+void templates() {
+ variadic(/*xxx=*/0, /*yyy=*/1);
+ variadic2(/*zzU=*/0, /*xxx=*/1, /*yyy=*/2);
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: argument name 'zzU' in comment does not match parameter name 'zzz'
+ // CHECK-FIXES: variadic2(/*zzz=*/0, /*xxx=*/1, /*yyy=*/2);
+}
+
+#define FALSE 0
+void qqq(bool aaa);
+void f2() { qqq(/*bbb=*/FALSE); }
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: argument name 'bbb' in comment does not match parameter name 'aaa'
+// CHECK-FIXES: void f2() { qqq(/*bbb=*/FALSE); }
+
+void f3(bool _with_underscores_);
+void ignores_underscores() {
+ f3(/*With_Underscores=*/false);
+}
+
+namespace ThisEditDistanceAboveThreshold {
+void f4(int xxx);
+void g() { f4(/*xyz=*/0); }
+// CHECK-MESSAGES: [[@LINE-1]]:15: warning: argument name 'xyz' in comment does not match parameter name 'xxx'
+// CHECK-FIXES: void g() { f4(/*xyz=*/0); }
+}
+
+namespace OtherEditDistanceAboveThreshold {
+void f5(int xxx, int yyy);
+void g() { f5(/*Zxx=*/0, 0); }
+// CHECK-MESSAGES: [[@LINE-1]]:15: warning: argument name 'Zxx' in comment does not match parameter name 'xxx'
+// CHECK-FIXES: void g() { f5(/*xxx=*/0, 0); }
+struct C2 {
+ C2(int xxx, int yyy);
+};
+C2 c2(/*Zxx=*/0, 0);
+// CHECK-MESSAGES: [[@LINE-1]]:7: warning: argument name 'Zxx' in comment does not match parameter name 'xxx'
+// CHECK-FIXES: C2 c2(/*xxx=*/0, 0);
+}
+
+namespace OtherEditDistanceBelowThreshold {
+void f6(int xxx, int yyy);
+void g() { f6(/*xxy=*/0, 0); }
+// CHECK-MESSAGES: [[@LINE-1]]:15: warning: argument name 'xxy' in comment does not match parameter name 'xxx'
+// CHECK-FIXES: void g() { f6(/*xxy=*/0, 0); }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-assert-side-effect.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-assert-side-effect.cpp
new file mode 100644
index 0000000..0933402
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-assert-side-effect.cpp
@@ -0,0 +1,114 @@
+// RUN: %check_clang_tidy %s bugprone-assert-side-effect %t -- -config="{CheckOptions: [{key: bugprone-assert-side-effect.CheckFunctionCalls, value: 1}, {key: bugprone-assert-side-effect.AssertMacros, value: 'assert,assert2,my_assert,convoluted_assert,msvc_assert'}]}" -- -fexceptions
+
+//===--- assert definition block ------------------------------------------===//
+int abort() { return 0; }
+
+#ifdef NDEBUG
+#define assert(x) 1
+#else
+#define assert(x) \
+ if (!(x)) \
+ (void)abort()
+#endif
+
+void print(...);
+#define assert2(e) (__builtin_expect(!(e), 0) ? \
+ print (#e, __FILE__, __LINE__) : (void)0)
+
+#ifdef NDEBUG
+#define my_assert(x) 1
+#else
+#define my_assert(x) \
+ ((void)((x) ? 1 : abort()))
+#endif
+
+#ifdef NDEBUG
+#define not_my_assert(x) 1
+#else
+#define not_my_assert(x) \
+ if (!(x)) \
+ (void)abort()
+#endif
+
+#define real_assert(x) ((void)((x) ? 1 : abort()))
+#define wrap1(x) real_assert(x)
+#define wrap2(x) wrap1(x)
+#define convoluted_assert(x) wrap2(x)
+
+#define msvc_assert(expression) (void)( \
+ (!!(expression)) || \
+ (abort(), 0) \
+ )
+
+
+//===----------------------------------------------------------------------===//
+
+class MyClass {
+public:
+ bool badFunc(int a, int b) { return a * b > 0; }
+ bool goodFunc(int a, int b) const { return a * b > 0; }
+
+ MyClass &operator=(const MyClass &rhs) { return *this; }
+
+ int operator-() { return 1; }
+
+ operator bool() const { return true; }
+
+ void operator delete(void *p) {}
+};
+
+bool freeFunction() {
+ return true;
+}
+
+int main() {
+
+ int X = 0;
+ bool B = false;
+ assert(X == 1);
+
+ assert(X = 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() with side effect [bugprone-assert-side-effect]
+ my_assert(X = 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found my_assert() with side effect
+ convoluted_assert(X = 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found convoluted_assert() with side effect
+ not_my_assert(X = 1);
+
+ assert(++X);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() with side effect
+ assert(!B);
+
+ assert(B || true);
+
+ assert(freeFunction());
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() with side effect
+
+ MyClass mc;
+ assert(mc.badFunc(0, 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() with side effect
+ assert(mc.goodFunc(0, 1));
+
+ MyClass mc2;
+ assert(mc2 = mc);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() with side effect
+
+ assert(-mc > 0);
+
+ MyClass *mcp;
+ assert(mcp = new MyClass);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() with side effect
+
+ assert((delete mcp, false));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() with side effect
+
+ assert((throw 1, false));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() with side effect
+
+ assert2(1 == 2 - 1);
+
+ msvc_assert(mc2 = mc);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found msvc_assert() with side effect
+
+ return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-bool-pointer-implicit-conversion.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-bool-pointer-implicit-conversion.cpp
new file mode 100644
index 0000000..37c6939
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-bool-pointer-implicit-conversion.cpp
@@ -0,0 +1,82 @@
+// RUN: %check_clang_tidy %s bugprone-bool-pointer-implicit-conversion %t
+
+bool *SomeFunction();
+void SomeOtherFunction(bool*);
+bool F();
+void G(bool);
+
+
+template <typename T>
+void t(T b) {
+ if (b) {
+ }
+}
+
+void foo() {
+ bool *b = SomeFunction();
+ if (b) {
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: dubious check of 'bool *' against 'nullptr'
+// CHECK-FIXES: if (*b) {
+ }
+
+ if (F() && b) {
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: dubious check of 'bool *' against 'nullptr'
+// CHECK-FIXES: if (F() && *b) {
+ }
+
+ // TODO: warn here.
+ if (b) {
+ G(b);
+ }
+
+#define TESTMACRO if (b || F())
+
+ TESTMACRO {
+ }
+
+ t(b);
+
+ if (!b) {
+ // no-warning
+ }
+
+ if (SomeFunction()) {
+ // no-warning
+ }
+
+ bool *c = SomeFunction();
+ if (c) {
+ (void)c;
+ (void)*c; // no-warning
+ }
+
+ if (c) {
+ *c = true; // no-warning
+ }
+
+ if (c) {
+ c[0] = false; // no-warning
+ }
+
+ if (c) {
+ SomeOtherFunction(c); // no-warning
+ }
+
+ if (c) {
+ delete[] c; // no-warning
+ }
+
+ if (c) {
+ *(c) = false; // no-warning
+ }
+
+ struct {
+ bool *b;
+ } d = { SomeFunction() };
+
+ if (d.b)
+ (void)*d.b; // no-warning
+
+#define CHECK(b) if (b) {}
+ CHECK(c)
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-copy-constructor-init.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-copy-constructor-init.cpp
new file mode 100644
index 0000000..981d0b5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-copy-constructor-init.cpp
@@ -0,0 +1,188 @@
+// RUN: %check_clang_tidy %s bugprone-copy-constructor-init %t
+
+class NonCopyable {
+public:
+ NonCopyable() = default;
+ NonCopyable(const NonCopyable &) = delete;
+
+private:
+ int a;
+};
+
+class NonCopyable2 {
+public:
+ NonCopyable2() = default;
+
+private:
+ NonCopyable2(const NonCopyable2 &);
+ int a;
+};
+
+class Copyable {
+public:
+ Copyable() = default;
+ Copyable(const Copyable &) = default;
+
+private:
+ int a;
+};
+
+class Copyable2 {
+public:
+ Copyable2() = default;
+ Copyable2(const Copyable2 &) = default;
+
+private:
+ int a;
+};
+
+class Copyable3 : public Copyable {
+public:
+ Copyable3() = default;
+ Copyable3(const Copyable3 &) = default;
+};
+
+template <class C>
+class Copyable4 {
+public:
+ Copyable4() = default;
+ Copyable4(const Copyable4 &) = default;
+
+private:
+ int a;
+};
+
+template <class T, class S>
+class Copyable5 {
+public:
+ Copyable5() = default;
+ Copyable5(const Copyable5 &) = default;
+
+private:
+ int a;
+};
+
+class EmptyCopyable {
+public:
+ EmptyCopyable() = default;
+ EmptyCopyable(const EmptyCopyable &) = default;
+};
+
+template <typename T>
+using CopyableAlias = Copyable5<T, int>;
+
+typedef Copyable5<int, int> CopyableAlias2;
+
+class X : public Copyable, public EmptyCopyable {
+ X(const X &other) : Copyable(other) {}
+};
+
+class X2 : public Copyable2 {
+ X2(const X2 &other) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor other than the copy constructor [bugprone-copy-constructor-init]
+ // CHECK-FIXES: X2(const X2 &other) : Copyable2(other) {}
+};
+
+class X2_A : public Copyable2 {
+ X2_A(const X2_A &) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+ // CHECK-FIXES: X2_A(const X2_A &) {}
+};
+
+class X3 : public Copyable, public Copyable2 {
+ X3(const X3 &other) : Copyable(other) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+ // CHECK-FIXES: X3(const X3 &other) : Copyable(other) {}
+};
+
+class X4 : public Copyable {
+ X4(const X4 &other) : Copyable() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+ // CHECK-FIXES: X4(const X4 &other) : Copyable(other) {}
+};
+
+class X5 : public Copyable3 {
+ X5(const X5 &other) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+ // CHECK-FIXES: X5(const X5 &other) : Copyable3(other) {}
+};
+
+class X6 : public Copyable2, public Copyable3 {
+ X6(const X6 &other) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+ // CHECK-FIXES: X6(const X6 &other) : Copyable2(other), Copyable3(other) {}
+};
+
+class X7 : public Copyable, public Copyable2 {
+ X7(const X7 &other) : Copyable() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+ // CHECK-FIXES: X7(const X7 &other) : Copyable(other) {}
+};
+
+class X8 : public Copyable4<int> {
+ X8(const X8 &other) : Copyable4(other) {}
+};
+
+class X9 : public Copyable4<int> {
+ X9(const X9 &other) : Copyable4() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+ // CHECK-FIXES: X9(const X9 &other) : Copyable4(other) {}
+};
+
+class X10 : public Copyable4<int> {
+ X10(const X10 &other) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+ // CHECK-FIXES: X10(const X10 &other) : Copyable4(other) {}
+};
+
+class X11 : public Copyable5<int, float> {
+ X11(const X11 &other) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+ // CHECK-FIXES: X11(const X11 &other) : Copyable5(other) {}
+};
+
+class X12 : public CopyableAlias<float> {
+ X12(const X12 &other) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+ // CHECK-FIXES: X12(const X12 &other) {}
+};
+
+template <typename T>
+class X13 : T {
+ X13(const X13 &other) {}
+};
+
+template class X13<EmptyCopyable>;
+template class X13<Copyable>;
+
+#define FROMMACRO \
+ class X14 : public Copyable2 { \
+ X14(const X14 &other) {} \
+ };
+
+FROMMACRO
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: calling a base constructor
+
+class X15 : public CopyableAlias2 {
+ X15(const X15 &other) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+ // CHECK-FIXES: X15(const X15 &other) {}
+};
+
+class X16 : public NonCopyable {
+ X16(const X16 &other) {}
+};
+
+class X17 : public NonCopyable2 {
+ X17(const X17 &other) {}
+};
+
+class X18 : private Copyable {
+ X18(const X18 &other) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+ // CHECK-FIXES: X18(const X18 &other) : Copyable(other) {}
+};
+
+class X19 : private Copyable {
+ X19(const X19 &other) : Copyable(other) {}
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-dangling-handle.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-dangling-handle.cpp
new file mode 100644
index 0000000..d11a2f2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-dangling-handle.cpp
@@ -0,0 +1,195 @@
+// RUN: %check_clang_tidy %s bugprone-dangling-handle %t -- \
+// RUN: -config="{CheckOptions: \
+// RUN: [{key: bugprone-dangling-handle.HandleClasses, \
+// RUN: value: 'std::basic_string_view; ::llvm::StringRef;'}]}" \
+// RUN: -- -std=c++11
+
+namespace std {
+
+template <typename T>
+class vector {
+ public:
+ using const_iterator = const T*;
+ using iterator = T*;
+ using size_type = int;
+
+ void assign(size_type count, const T& value);
+ iterator insert(const_iterator pos, const T& value);
+ iterator insert(const_iterator pos, T&& value);
+ iterator insert(const_iterator pos, size_type count, const T& value);
+ void push_back(const T&);
+ void push_back(T&&);
+ void resize(size_type count, const T& value);
+};
+
+template <typename, typename>
+class pair {};
+
+template <typename T>
+class set {
+ public:
+ using const_iterator = const T*;
+ using iterator = T*;
+
+ std::pair<iterator, bool> insert(const T& value);
+ std::pair<iterator, bool> insert(T&& value);
+ iterator insert(const_iterator hint, const T& value);
+ iterator insert(const_iterator hint, T&& value);
+};
+
+template <typename Key, typename Value>
+class map {
+ public:
+ using value_type = pair<Key, Value>;
+ value_type& operator[](const Key& key);
+ value_type& operator[](Key&& key);
+};
+
+class basic_string_view;
+
+class basic_string {
+ public:
+ basic_string();
+ basic_string(const char*);
+
+ operator basic_string_view() const noexcept;
+
+ ~basic_string();
+};
+
+typedef basic_string string;
+
+class basic_string_view {
+ public:
+ basic_string_view(const char*);
+};
+
+typedef basic_string_view string_view;
+
+} // namespace std
+
+namespace llvm {
+
+class StringRef {
+ public:
+ StringRef();
+ StringRef(const char*);
+ StringRef(const std::string&);
+};
+
+} // namespace llvm
+
+std::string ReturnsAString();
+
+void Positives() {
+ std::string_view view1 = std::string();
+ // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
+
+ std::string_view view_2 = ReturnsAString();
+ // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives
+
+ view1 = std::string();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+
+ const std::string& str_ref = "";
+ std::string_view view3 = true ? "A" : str_ref;
+ // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives
+ view3 = true ? "A" : str_ref;
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+
+ std::string_view view4(ReturnsAString());
+ // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives
+}
+
+void OtherTypes() {
+ llvm::StringRef ref = std::string();
+ // CHECK-MESSAGES: [[@LINE-1]]:19: warning: llvm::StringRef outlives its value
+}
+
+const char static_array[] = "A";
+std::string_view ReturnStatements(int i, std::string value_arg,
+ const std::string &ref_arg) {
+ const char array[] = "A";
+ const char* ptr = "A";
+ std::string s;
+ static std::string ss;
+ switch (i) {
+ // Bad cases
+ case 0:
+ return array; // refers to local
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv
+ case 1:
+ return s; // refers to local
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv
+ case 2:
+ return std::string(); // refers to temporary
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv
+ case 3:
+ return value_arg; // refers to by-value arg
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv
+
+ // Ok cases
+ case 100:
+ return ss; // refers to static
+ case 101:
+ return static_array; // refers to static
+ case 102:
+ return ptr; // pointer is ok
+ case 103:
+ return ref_arg; // refers to by-ref arg
+ }
+
+ struct S {
+ std::string_view view() { return value; }
+ std::string value;
+ };
+
+ (void)[&]()->std::string_view {
+ // This should not warn. The string is bound by reference.
+ return s;
+ };
+ (void)[=]() -> std::string_view {
+ // This should not warn. The reference is valid as long as the lambda.
+ return s;
+ };
+ (void)[=]() -> std::string_view {
+ // FIXME: This one should warn. We are returning a reference to a local
+ // lambda variable.
+ std::string local;
+ return local;
+ };
+ return "";
+}
+
+void Containers() {
+ std::vector<std::string_view> v;
+ v.assign(3, std::string());
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+ v.insert(nullptr, std::string());
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+ v.insert(nullptr, 3, std::string());
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+ v.push_back(std::string());
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+ v.resize(3, std::string());
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+
+ std::set<std::string_view> s;
+ s.insert(std::string());
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+ s.insert(nullptr, std::string());
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+
+ std::map<std::string_view, int> m;
+ m[std::string()];
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+}
+
+void TakesAStringView(std::string_view);
+
+void Negatives(std::string_view default_arg = ReturnsAString()) {
+ std::string str;
+ std::string_view view = str;
+
+ TakesAStringView(std::string());
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-exception-escape.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-exception-escape.cpp
new file mode 100644
index 0000000..eba14bf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-exception-escape.cpp
@@ -0,0 +1,290 @@
+// RUN: %check_clang_tidy %s bugprone-exception-escape %t -- -extra-arg=-std=c++11 -extra-arg=-fexceptions -config="{CheckOptions: [{key: bugprone-exception-escape.IgnoredExceptions, value: 'ignored1,ignored2'}, {key: bugprone-exception-escape.FunctionsThatShouldNotThrow, value: 'enabled1,enabled2,enabled3'}]}" --
+
+struct throwing_destructor {
+ ~throwing_destructor() {
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function '~throwing_destructor' which should not throw exceptions
+ throw 1;
+ }
+};
+
+struct throwing_move_constructor {
+ throwing_move_constructor(throwing_move_constructor&&) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'throwing_move_constructor' which should not throw exceptions
+ throw 1;
+ }
+};
+
+struct throwing_move_assignment {
+ throwing_move_assignment& operator=(throwing_move_assignment&&) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: an exception may be thrown in function 'operator=' which should not throw exceptions
+ throw 1;
+ }
+};
+
+void throwing_noexcept() noexcept {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_noexcept' which should not throw exceptions
+ throw 1;
+}
+
+void throwing_throw_nothing() throw() {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_throw_nothing' which should not throw exceptions
+ throw 1;
+}
+
+void throw_and_catch() noexcept {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch' which should not throw exceptions
+ try {
+ throw 1;
+ } catch(int &) {
+ }
+}
+
+void throw_and_catch_some(int n) noexcept {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_some' which should not throw exceptions
+ try {
+ if (n) throw 1;
+ throw 1.1;
+ } catch(int &) {
+ }
+}
+
+void throw_and_catch_each(int n) noexcept {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_each' which should not throw exceptions
+ try {
+ if (n) throw 1;
+ throw 1.1;
+ } catch(int &) {
+ } catch(double &) {
+ }
+}
+
+void throw_and_catch_all(int n) noexcept {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_all' which should not throw exceptions
+ try {
+ if (n) throw 1;
+ throw 1.1;
+ } catch(...) {
+ }
+}
+
+void throw_and_rethrow() noexcept {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_rethrow' which should not throw exceptions
+ try {
+ throw 1;
+ } catch(int &) {
+ throw;
+ }
+}
+
+void throw_catch_throw() noexcept {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_throw' which should not throw exceptions
+ try {
+ throw 1;
+ } catch(int &) {
+ throw 2;
+ }
+}
+
+void throw_catch_rethrow_the_rest(int n) noexcept {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_rethrow_the_rest' which should not throw exceptions
+ try {
+ if (n) throw 1;
+ throw 1.1;
+ } catch(int &) {
+ } catch(...) {
+ throw;
+ }
+}
+
+class base {};
+class derived: public base {};
+
+void throw_derived_catch_base() noexcept {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base' which should not throw exceptions
+ try {
+ throw derived();
+ } catch(base &) {
+ }
+}
+
+void try_nested_try(int n) noexcept {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_try' which should not throw exceptions
+ try {
+ try {
+ if (n) throw 1;
+ throw 1.1;
+ } catch(int &) {
+ }
+ } catch(double &) {
+ }
+}
+
+void bad_try_nested_try(int n) noexcept {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'bad_try_nested_try' which should not throw exceptions
+ try {
+ if (n) throw 1;
+ try {
+ throw 1.1;
+ } catch(int &) {
+ }
+ } catch(double &) {
+ }
+}
+
+void try_nested_catch() noexcept {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_catch' which should not throw exceptions
+ try {
+ try {
+ throw 1;
+ } catch(int &) {
+ throw 1.1;
+ }
+ } catch(double &) {
+ }
+}
+
+void catch_nested_try() noexcept {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'catch_nested_try' which should not throw exceptions
+ try {
+ throw 1;
+ } catch(int &) {
+ try {
+ throw 1;
+ } catch(int &) {
+ }
+ }
+}
+
+void bad_catch_nested_try() noexcept {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'bad_catch_nested_try' which should not throw exceptions
+ try {
+ throw 1;
+ } catch(int &) {
+ try {
+ throw 1.1;
+ } catch(int &) {
+ }
+ } catch(double &) {
+ }
+}
+
+void implicit_int_thrower() {
+ throw 1;
+}
+
+void explicit_int_thrower() throw(int);
+
+void indirect_implicit() noexcept {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_implicit' which should not throw exceptions
+ implicit_int_thrower();
+}
+
+void indirect_explicit() noexcept {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_explicit' which should not throw exceptions
+ explicit_int_thrower();
+}
+
+void indirect_catch() noexcept {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_catch' which should not throw exceptions
+ try {
+ implicit_int_thrower();
+ } catch(int&) {
+ }
+}
+
+template<typename T>
+void dependent_throw() noexcept(sizeof(T)<4) {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'dependent_throw' which should not throw exceptions
+ if (sizeof(T) > 4)
+ throw 1;
+}
+
+void swap(int&, int&) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'swap' which should not throw exceptions
+ throw 1;
+}
+
+namespace std {
+class bad_alloc {};
+}
+
+void alloc() {
+ throw std::bad_alloc();
+}
+
+void allocator() noexcept {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'allocator' which should not throw exceptions
+ alloc();
+}
+
+void enabled1() {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled1' which should not throw exceptions
+ throw 1;
+}
+
+void enabled2() {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled2' which should not throw exceptions
+ enabled1();
+}
+
+void enabled3() {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled3' which should not throw exceptions
+ try {
+ enabled1();
+ } catch(...) {
+ }
+}
+
+class ignored1 {};
+class ignored2 {};
+
+void this_does_not_count() noexcept {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_does_not_count' which should not throw exceptions
+ throw ignored1();
+}
+
+void this_does_not_count_either(int n) noexcept {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_does_not_count_either' which should not throw exceptions
+ try {
+ throw 1;
+ if (n) throw ignored2();
+ } catch(int &) {
+ }
+}
+
+void this_counts(int n) noexcept {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_counts' which should not throw exceptions
+ if (n) throw 1;
+ throw ignored1();
+}
+
+void thrower(int n) {
+ throw n;
+}
+
+int directly_recursive(int n) noexcept {
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'directly_recursive' which should not throw exceptions
+ if (n == 0)
+ thrower(n);
+ return directly_recursive(n);
+}
+
+int indirectly_recursive(int n) noexcept;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'indirectly_recursive' which should not throw exceptions
+
+int recursion_helper(int n) {
+ indirectly_recursive(n);
+}
+
+int indirectly_recursive(int n) noexcept {
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'indirectly_recursive' which should not throw exceptions
+ if (n == 0)
+ thrower(n);
+ return recursion_helper(n);
+}
+
+int main() {
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'main' which should not throw exceptions
+ throw 1;
+ return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-fold-init-type.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-fold-init-type.cpp
new file mode 100644
index 0000000..e7fdf39
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-fold-init-type.cpp
@@ -0,0 +1,158 @@
+// RUN: %check_clang_tidy %s bugprone-fold-init-type %t
+
+namespace std {
+template <class InputIt, class T>
+T accumulate(InputIt first, InputIt last, T init);
+
+template <class InputIt, class T>
+T reduce(InputIt first, InputIt last, T init);
+template <class ExecutionPolicy, class InputIt, class T>
+T reduce(ExecutionPolicy &&policy,
+ InputIt first, InputIt last, T init);
+
+struct parallel_execution_policy {};
+constexpr parallel_execution_policy par{};
+
+template <class InputIt1, class InputIt2, class T>
+T inner_product(InputIt1 first1, InputIt1 last1,
+ InputIt2 first2, T value);
+
+template <class ExecutionPolicy, class InputIt1, class InputIt2, class T>
+T inner_product(ExecutionPolicy &&policy, InputIt1 first1, InputIt1 last1,
+ InputIt2 first2, T value);
+
+} // namespace std
+
+struct FloatIterator {
+ typedef float value_type;
+};
+template <typename ValueType>
+struct TypedefTemplateIterator { typedef ValueType value_type; };
+template <typename ValueType>
+struct UsingTemplateIterator { using value_type = ValueType; };
+template <typename ValueType>
+struct DependentTypedefTemplateIterator { typedef typename ValueType::value_type value_type; };
+template <typename ValueType>
+struct DependentUsingTemplateIterator : public TypedefTemplateIterator<ValueType> { using typename TypedefTemplateIterator<ValueType>::value_type; };
+using TypedeffedIterator = FloatIterator;
+
+// Positives.
+
+int accumulatePositive1() {
+ float a[1] = {0.5f};
+ return std::accumulate(a, a + 1, 0);
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
+}
+
+int accumulatePositive2() {
+ FloatIterator it;
+ return std::accumulate(it, it, 0);
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
+}
+
+int accumulatePositive3() {
+ double a[1] = {0.0};
+ return std::accumulate(a, a + 1, 0.0f);
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'double' into type 'float'
+}
+
+int accumulatePositive4() {
+ TypedefTemplateIterator<unsigned> it;
+ return std::accumulate(it, it, 0);
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int'
+}
+
+int accumulatePositive5() {
+ UsingTemplateIterator<unsigned> it;
+ return std::accumulate(it, it, 0);
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int'
+}
+
+int accumulatePositive6() {
+ DependentTypedefTemplateIterator<UsingTemplateIterator<unsigned>> it;
+ return std::accumulate(it, it, 0);
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int'
+}
+
+int accumulatePositive7() {
+ TypedeffedIterator it;
+ return std::accumulate(it, it, 0);
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
+}
+
+int accumulatePositive8() {
+ DependentUsingTemplateIterator<unsigned> it;
+ return std::accumulate(it, it, 0);
+ // FIXME: this one should trigger too.
+}
+
+int reducePositive1() {
+ float a[1] = {0.5f};
+ return std::reduce(a, a + 1, 0);
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
+}
+
+int reducePositive2() {
+ float a[1] = {0.5f};
+ return std::reduce(std::par, a, a + 1, 0);
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
+}
+
+int innerProductPositive1() {
+ float a[1] = {0.5f};
+ int b[1] = {1};
+ return std::inner_product(std::par, a, a + 1, b, 0);
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
+}
+
+int innerProductPositive2() {
+ float a[1] = {0.5f};
+ int b[1] = {1};
+ return std::inner_product(std::par, a, a + 1, b, 0);
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
+}
+
+// Negatives.
+
+int negative1() {
+ float a[1] = {0.5f};
+ // This is OK because types match.
+ return std::accumulate(a, a + 1, 0.0);
+}
+
+int negative2() {
+ float a[1] = {0.5f};
+ // This is OK because double is bigger than float.
+ return std::accumulate(a, a + 1, 0.0);
+}
+
+int negative3() {
+ float a[1] = {0.5f};
+ // This is OK because the user explicitly specified T.
+ return std::accumulate<float *, float>(a, a + 1, 0);
+}
+
+int negative4() {
+ TypedefTemplateIterator<unsigned> it;
+ // For now this is OK.
+ return std::accumulate(it, it, 0.0);
+}
+
+int negative5() {
+ float a[1] = {0.5f};
+ float b[1] = {1.0f};
+ return std::inner_product(std::par, a, a + 1, b, 0.0f);
+}
+
+namespace blah {
+namespace std {
+template <class InputIt, class T>
+T accumulate(InputIt, InputIt, T); // We should not care about this one.
+}
+
+int negative5() {
+ float a[1] = {0.5f};
+ // Note that this is using blah::std::accumulate.
+ return std::accumulate(a, a + 1, 0);
+}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-forward-declaration-namespace.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-forward-declaration-namespace.cpp
new file mode 100644
index 0000000..d938148
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-forward-declaration-namespace.cpp
@@ -0,0 +1,163 @@
+// RUN: %check_clang_tidy %s bugprone-forward-declaration-namespace %t
+
+namespace {
+// This is a declaration in a wrong namespace.
+class T_A;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration 'T_A' is never referenced, but a declaration with the same name found in another namespace 'na' [bugprone-forward-declaration-namespace]
+// CHECK-MESSAGES: note: a declaration of 'T_A' is found here
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: no definition found for 'T_A', but a definition with the same name 'T_A' found in another namespace '(global)' [bugprone-forward-declaration-namespace]
+// CHECK-MESSAGES: note: a definition of 'T_A' is found here
+}
+
+namespace na {
+// This is a declaration in a wrong namespace.
+class T_A;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration 'T_A' is never referenced, but a declaration with the same name found in another namespace '(anonymous)'
+// CHECK-MESSAGES: note: a declaration of 'T_A' is found here
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: no definition found for 'T_A', but a definition with the same name 'T_A' found in another namespace '(global)'
+// CHECK-MESSAGES: note: a definition of 'T_A' is found here
+}
+
+class T_A;
+
+class T_A {
+ int x;
+};
+
+class NESTED;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: no definition found for 'NESTED', but a definition with the same name 'NESTED' found in another namespace '(anonymous namespace)::nq::(anonymous)'
+// CHECK-MESSAGES: note: a definition of 'NESTED' is found here
+
+namespace {
+namespace nq {
+namespace {
+class NESTED {};
+}
+}
+}
+
+namespace na {
+class T_B;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration 'T_B' is never referenced, but a declaration with the same name found in another namespace 'nb'
+// CHECK-MESSAGES: note: a declaration of 'T_B' is found here
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: no definition found for 'T_B', but a definition with the same name 'T_B' found in another namespace 'nb'
+// CHECK-MESSAGES: note: a definition of 'T_B' is found here
+}
+
+namespace nb {
+class T_B;
+}
+
+namespace nb {
+class T_B {
+ int x;
+};
+}
+
+namespace na {
+class T_B;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration 'T_B' is never referenced, but a declaration with the same name found in another namespace 'nb'
+// CHECK-MESSAGES: note: a declaration of 'T_B' is found here
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: no definition found for 'T_B', but a definition with the same name 'T_B' found in another namespace 'nb'
+// CHECK-MESSAGES: note: a definition of 'T_B' is found here
+}
+
+// A simple forward declaration. Although it is never used, but no declaration
+// with the same name is found in other namespace.
+class OUTSIDER;
+
+namespace na {
+// This class is referenced declaration, we don't generate warning.
+class OUTSIDER_1;
+}
+
+void f(na::OUTSIDER_1);
+
+namespace nc {
+// This class is referenced as friend in OOP.
+class OUTSIDER_1;
+
+class OOP {
+ friend struct OUTSIDER_1;
+};
+}
+
+namespace nd {
+class OUTSIDER_1;
+void f(OUTSIDER_1 *);
+}
+
+namespace nb {
+class OUTSIDER_1;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration 'OUTSIDER_1' is never referenced, but a declaration with the same name found in another namespace 'na'
+// CHECK-MESSAGES: note: a declaration of 'OUTSIDER_1' is found here
+}
+
+
+namespace na {
+template<typename T>
+class T_C;
+}
+
+namespace nb {
+// FIXME: this is an error, but we don't consider template class declaration
+// now.
+template<typename T>
+class T_C;
+}
+
+namespace na {
+template<typename T>
+class T_C {
+ int x;
+};
+}
+
+namespace na {
+
+template <typename T>
+class T_TEMP {
+ template <typename _Tp1>
+ struct rebind { typedef T_TEMP<_Tp1> other; };
+};
+
+// We ignore class template specialization.
+template class T_TEMP<char>;
+}
+
+namespace nb {
+
+template <typename T>
+class T_TEMP_1 {
+ template <typename _Tp1>
+ struct rebind { typedef T_TEMP_1<_Tp1> other; };
+};
+
+// We ignore class template specialization.
+extern template class T_TEMP_1<char>;
+}
+
+namespace nd {
+class D;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration 'D' is never referenced, but a declaration with the same name found in another namespace 'nd::ne'
+// CHECK-MESSAGES: note: a declaration of 'D' is found here
+}
+
+namespace nd {
+namespace ne {
+class D;
+}
+}
+
+int f(nd::ne::D &d);
+
+
+// This should be ignored by the check.
+template <typename... Args>
+class Observer {
+ class Impl;
+};
+
+template <typename... Args>
+class Observer<Args...>::Impl {
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-forwarding-reference-overload.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-forwarding-reference-overload.cpp
new file mode 100644
index 0000000..3510685
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-forwarding-reference-overload.cpp
@@ -0,0 +1,145 @@
+// RUN: %check_clang_tidy %s bugprone-forwarding-reference-overload %t -- -- -std=c++14
+
+namespace std {
+template <bool B, class T = void> struct enable_if { typedef T type; };
+
+template <class T> struct enable_if<true, T> { typedef T type; };
+
+template <bool B, class T = void>
+using enable_if_t = typename enable_if<B, T>::type;
+
+template <class T> struct enable_if_nice { typedef T type; };
+} // namespace std
+
+namespace foo {
+template <class T> struct enable_if { typedef T type; };
+} // namespace foo
+
+template <typename T> constexpr bool just_true = true;
+
+class Test1 {
+public:
+ template <typename T> Test1(T &&n);
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: constructor accepting a forwarding reference can hide the copy and move constructors [bugprone-forwarding-reference-overload]
+
+ template <typename T> Test1(T &&n, int i = 5, ...);
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: constructor accepting a forwarding reference can hide the copy and move constructors
+
+ template <typename T, typename U = typename std::enable_if_nice<T>::type>
+ Test1(T &&n);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor accepting a forwarding reference can hide the copy and move constructors
+
+ template <typename T>
+ Test1(T &&n, typename foo::enable_if<long>::type i = 5, ...);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor accepting a forwarding reference can hide the copy and move constructors
+
+ Test1(const Test1 &other) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: note: copy constructor declared here
+
+ Test1(Test1 &other) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: note: copy constructor declared here
+
+ Test1(Test1 &&other) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: note: move constructor declared here
+};
+
+template <typename U> class Test2 {
+public:
+ // Two parameters without default value, can't act as copy / move constructor.
+ template <typename T, class V> Test2(T &&n, V &&m, int i = 5, ...);
+
+ // Guarded with enable_if.
+ template <typename T>
+ Test2(T &&n, int i = 5,
+ std::enable_if_t<sizeof(int) < sizeof(long), int> a = 5, ...);
+
+ // Guarded with enable_if.
+ template <typename T, typename X = typename std::enable_if<
+ sizeof(int) < sizeof(long), double>::type &>
+ Test2(T &&n);
+
+ // Guarded with enable_if.
+ template <typename T>
+ Test2(T &&n, typename std::enable_if<just_true<T>>::type **a = nullptr);
+
+ // Guarded with enable_if.
+ template <typename T, typename X = std::enable_if_t<just_true<T>> *&&>
+ Test2(T &&n, double d = 0.0);
+
+ // Not a forwarding reference parameter.
+ template <typename T> Test2(const T &&n);
+
+ // Not a forwarding reference parameter.
+ Test2(int &&x);
+
+ // Two parameters without default value, can't act as copy / move constructor.
+ template <typename T> Test2(T &&n, int x);
+
+ // Not a forwarding reference parameter.
+ template <typename T> Test2(U &&n);
+};
+
+// The copy and move constructors are both disabled.
+class Test3 {
+public:
+ template <typename T> Test3(T &&n);
+
+ template <typename T> Test3(T &&n, int I = 5, ...);
+
+ Test3(const Test3 &rhs) = delete;
+
+private:
+ Test3(Test3 &&rhs);
+};
+
+// Both the copy and the (compiler generated) move constructors can be hidden.
+class Test4 {
+public:
+ template <typename T> Test4(T &&n);
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: constructor accepting a forwarding reference can hide the copy and move constructors
+
+ Test4(const Test4 &rhs);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: note: copy constructor declared here
+};
+
+// Nothing can be hidden, the copy constructor is implicitly deleted.
+class Test5 {
+public:
+ template <typename T> Test5(T &&n);
+
+ Test5(Test5 &&rhs) = delete;
+};
+
+// Only the move constructor can be hidden.
+class Test6 {
+public:
+ template <typename T> Test6(T &&n);
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: constructor accepting a forwarding reference can hide the move constructor
+
+ Test6(Test6 &&rhs);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: note: move constructor declared here
+private:
+ Test6(const Test6 &rhs);
+};
+
+// Do not dereference a null BaseType.
+template <class _Callable> class result_of;
+template <class _Fp, class ..._Args> class result_of<_Fp(_Args...)> { };
+template <class _Tp> using result_of_t = typename result_of<_Tp>::type;
+
+template <class... _Types> struct __overload;
+template <class _Tp, class... _Types>
+struct __overload<_Tp, _Types...> : __overload<_Types...> {
+ using __overload<_Types...>::operator();
+};
+
+template <class _Tp, class... _Types>
+using __best_match_t = typename result_of_t<__overload<_Types...>(_Tp&&)>::type;
+
+template <class... _Types>
+class variant {
+public:
+ template <class _Arg, class _Tp = __best_match_t<_Arg, _Types...> >
+ constexpr variant(_Arg&& __arg) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: constructor accepting a forwarding reference can hide the copy and move constructors
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-inaccurate-erase.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-inaccurate-erase.cpp
new file mode 100644
index 0000000..d29fa9c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-inaccurate-erase.cpp
@@ -0,0 +1,100 @@
+// RUN: %check_clang_tidy %s bugprone-inaccurate-erase %t
+
+namespace std {
+template <typename T> struct vec_iterator {
+ T ptr;
+ vec_iterator operator++(int);
+
+ template <typename X>
+ vec_iterator(const vec_iterator<X> &); // Omit enable_if<...>.
+};
+
+template <typename T> struct vector {
+ typedef vec_iterator<T*> iterator;
+
+ iterator begin();
+ iterator end();
+
+ void erase(iterator);
+ void erase(iterator, iterator);
+};
+
+template <typename T> struct vector_with_const_iterator {
+ typedef vec_iterator<T*> iterator;
+ typedef vec_iterator<const T*> const_iterator;
+
+ iterator begin();
+ iterator end();
+
+ void erase(const_iterator);
+ void erase(const_iterator, const_iterator);
+};
+
+template <typename FwIt, typename T>
+FwIt remove(FwIt begin, FwIt end, const T &val);
+
+template <typename FwIt, typename Func>
+FwIt remove_if(FwIt begin, FwIt end, Func f);
+
+template <typename FwIt> FwIt unique(FwIt begin, FwIt end);
+
+template <typename T> struct unique_ptr {};
+} // namespace std
+
+struct custom_iter {};
+struct custom_container {
+ void erase(...);
+ custom_iter begin();
+ custom_iter end();
+};
+
+template <typename T> void g() {
+ T t;
+ t.erase(std::remove(t.begin(), t.end(), 10));
+ // CHECK-FIXES: {{^ }}t.erase(std::remove(t.begin(), t.end(), 10));{{$}}
+
+ std::vector<int> v;
+ v.erase(remove(v.begin(), v.end(), 10));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this call will remove at most one
+ // CHECK-FIXES: {{^ }}v.erase(remove(v.begin(), v.end(), 10), v.end());{{$}}
+}
+
+#define ERASE(x, y) x.erase(remove(x.begin(), x.end(), y))
+// CHECK-FIXES: #define ERASE(x, y) x.erase(remove(x.begin(), x.end(), y))
+
+int main() {
+ std::vector<int> v;
+
+ v.erase(remove(v.begin(), v.end(), 10));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this call will remove at most one item even when multiple items should be removed [bugprone-inaccurate-erase]
+ // CHECK-FIXES: {{^ }}v.erase(remove(v.begin(), v.end(), 10), v.end());{{$}}
+ v.erase(remove(v.begin(), v.end(), 20), v.end());
+
+ auto *p = &v;
+ p->erase(remove(p->begin(), p->end(), 11));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this call will remove at most one
+ // CHECK-FIXES: {{^ }}p->erase(remove(p->begin(), p->end(), 11), p->end());{{$}}
+
+ std::vector_with_const_iterator<int> v2;
+ v2.erase(remove(v2.begin(), v2.end(), 12));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this call will remove at most one
+ // CHECK-FIXES: {{^ }}v2.erase(remove(v2.begin(), v2.end(), 12), v2.end());{{$}}
+
+ // Fix is not trivial.
+ auto it = v.end();
+ v.erase(remove(v.begin(), it, 10));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this call will remove at most one
+ // CHECK-FIXES: {{^ }}v.erase(remove(v.begin(), it, 10));{{$}}
+
+ g<std::vector<int>>();
+ g<custom_container>();
+
+ ERASE(v, 15);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: this call will remove at most one
+ // CHECK-FIXES: {{^ }}ERASE(v, 15);{{$}}
+
+ std::vector<std::unique_ptr<int>> vupi;
+ auto iter = vupi.begin();
+ vupi.erase(iter++);
+ // CHECK-FIXES: {{^ }}vupi.erase(iter++);{{$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-incorrect-roundings.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-incorrect-roundings.cpp
new file mode 100644
index 0000000..7ada061
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-incorrect-roundings.cpp
@@ -0,0 +1,86 @@
+// RUN: %check_clang_tidy %s bugprone-incorrect-roundings %t
+
+void b(int x) {}
+
+void f1() {
+ float f;
+ double d;
+ long double ld;
+ int x;
+
+ x = (d + 0.5);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5) to integer leads to incorrect rounding; consider using lround (#include <cmath>) instead [bugprone-incorrect-roundings]
+ x = (d + 0.5f);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+ x = (f + 0.5);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+ x = (f + 0.5f);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+ x = (0.5 + d);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+ x = (0.5f + d);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+ x = (0.5 + ld);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+ x = (0.5f + ld);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+ x = (0.5 + f);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+ x = (0.5f + f);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+ x = (int)(d + 0.5);
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+ x = (int)(d + 0.5f);
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+ x = (int)(ld + 0.5);
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+ x = (int)(ld + 0.5f);
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+ x = (int)(f + 0.5);
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+ x = (int)(f + 0.5f);
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+ x = (int)(0.5 + d);
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+ x = (int)(0.5f + d);
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+ x = (int)(0.5 + ld);
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+ x = (int)(0.5f + ld);
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+ x = (int)(0.5 + f);
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+ x = (int)(0.5f + f);
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+ x = static_cast<int>(d + 0.5);
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+ x = static_cast<int>(d + 0.5f);
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+ x = static_cast<int>(ld + 0.5);
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+ x = static_cast<int>(ld + 0.5f);
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+ x = static_cast<int>(f + 0.5);
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+ x = static_cast<int>(f + 0.5f);
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+ x = static_cast<int>(0.5 + d);
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+ x = static_cast<int>(0.5f + d);
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+ x = static_cast<int>(0.5 + ld);
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+ x = static_cast<int>(0.5f + ld);
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+ x = static_cast<int>(0.5 + f);
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+ x = static_cast<int>(0.5f + f);
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+
+ // Don't warn if constant is not 0.5.
+ x = (int)(d + 0.6);
+ x = (int)(0.6 + d);
+
+ // Don't warn if binary operator is not directly beneath cast.
+ x = (int)(1 + (0.5 + f));
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-integer-division.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-integer-division.cpp
new file mode 100644
index 0000000..243ad46
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-integer-division.cpp
@@ -0,0 +1,130 @@
+// RUN: %check_clang_tidy %s bugprone-integer-division %t
+
+// Functions expecting a floating-point parameter.
+void floatArg(float x) {}
+void doubleArg(double x) {}
+void longDoubleArg(long double x) {}
+
+// Functions expected to return a floating-point value.
+float singleDiv() {
+ int x = -5;
+ int y = 2;
+ return x/y;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: result of integer division used in
+}
+
+double wrongOrder(int x, int y) {
+ return x/y/0.1;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: result of integer division used in
+}
+
+long double rightOrder(int x, int y) {
+ return 0.1/x/y; // OK
+}
+
+// Typical mathematical functions.
+float sin(float);
+double acos(double);
+long double tanh(long double);
+
+namespace std {
+ using ::sin;
+}
+
+template <typename T>
+void intDivSin(T x) {
+ sin(x);
+}
+
+int intFunc(int);
+
+struct X {
+ int n;
+ void m() {
+ sin(n / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: result of integer division used in
+ }
+};
+
+void integerDivision() {
+ char a = 2;
+ short b = -5;
+ int c = 9784;
+ enum third { x, y, z=2 };
+ third d = z;
+ char e[] = {'a', 'b', 'c'};
+ char f = *(e + 1 / a);
+ bool g = 1;
+
+ sin(1 + c / (2 + 2));
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: result of integer division used in
+ sin(c / (1 + .5));
+ sin((c + .5) / 3);
+
+ sin(intFunc(3) / 5);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: result of integer division used in
+ acos(2 / intFunc(7));
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: result of integer division used in
+
+ floatArg(1 + 2 / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: result of integer division used in
+ sin(1 + 2 / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: result of integer division used in
+ intFunc(sin(1 + 2 / 3));
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: result of integer division used in
+
+ floatArg(1 + intFunc(1 + 2 / 3));
+ floatArg(1 + 3 * intFunc(a / b));
+
+ 1 << (2 / 3);
+ 1 << intFunc(2 / 3);
+
+#define M_SIN sin(a / b);
+ M_SIN
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: result of integer division used in
+
+ intDivSin<float>(a / b);
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: result of integer division used in
+ intDivSin<double>(c / d);
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: result of integer division used in
+ intDivSin<long double>(f / g);
+// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: result of integer division used in
+
+ floatArg(1 / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: result of integer division used in
+ doubleArg(a / b);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: result of integer division used in
+ longDoubleArg(3 / d);
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: result of integer division used in
+ floatArg(a / b / 0.1);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: result of integer division used in
+ doubleArg(1 / 3 / 0.1);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: result of integer division used in
+ longDoubleArg(2 / 3 / 5);
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: result of integer division used in
+
+ std::sin(2 / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: result of integer division used in
+ ::acos(7 / d);
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: result of integer division used in
+ tanh(f / g);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: result of integer division used in
+
+ floatArg(0.1 / a / b);
+ doubleArg(0.1 / 3 / 1);
+
+ singleDiv();
+ wrongOrder(a,b);
+ rightOrder(a,b);
+
+ sin(a / b);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: result of integer division used in
+ acos(f / d);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: result of integer division used in
+ tanh(c / g);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: result of integer division used in
+
+ sin(3.0 / a);
+ acos(b / 3.14);
+ tanh(3.14 / f / g);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-lambda-function-name.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-lambda-function-name.cpp
new file mode 100644
index 0000000..145928b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-lambda-function-name.cpp
@@ -0,0 +1,41 @@
+// RUN: %check_clang_tidy %s bugprone-lambda-function-name %t
+
+void Foo(const char* a, const char* b, int c) {}
+
+#define FUNC_MACRO Foo(__func__, "", 0)
+#define FUNCTION_MACRO Foo(__FUNCTION__, "", 0)
+#define EMBED_IN_ANOTHER_MACRO1 FUNC_MACRO
+
+void Positives() {
+ [] { __func__; }();
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name]
+ [] { __FUNCTION__; }();
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: inside a lambda, '__FUNCTION__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name]
+ [] { FUNC_MACRO; }();
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name]
+ [] { FUNCTION_MACRO; }();
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: inside a lambda, '__FUNCTION__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name]
+ [] { EMBED_IN_ANOTHER_MACRO1; }();
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name]
+}
+
+#define FUNC_MACRO_WITH_FILE_AND_LINE Foo(__func__, __FILE__, __LINE__)
+#define FUNCTION_MACRO_WITH_FILE_AND_LINE Foo(__FUNCTION__, __FILE__, __LINE__)
+#define EMBED_IN_ANOTHER_MACRO2 FUNC_MACRO_WITH_FILE_AND_LINE
+
+void Negatives() {
+ __func__;
+ __FUNCTION__;
+
+ // __PRETTY_FUNCTION__ should not trigger a warning because its value is
+ // actually potentially useful.
+ __PRETTY_FUNCTION__;
+ [] { __PRETTY_FUNCTION__; }();
+
+ // Don't warn if __func__/__FUNCTION is used inside a macro that also uses
+ // __FILE__ and __LINE__, on the assumption that __FILE__ and __LINE__ will
+ // be useful even if __func__/__FUNCTION__ is not.
+ [] { FUNC_MACRO_WITH_FILE_AND_LINE; }();
+ [] { FUNCTION_MACRO_WITH_FILE_AND_LINE; }();
+ [] { EMBED_IN_ANOTHER_MACRO2; }();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-macro-parentheses-cmdline.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-macro-parentheses-cmdline.cpp
new file mode 100644
index 0000000..9ff757d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-macro-parentheses-cmdline.cpp
@@ -0,0 +1,10 @@
+// RUN: %check_clang_tidy %s bugprone-macro-parentheses %t -- -- -DVAL=0+0
+
+// The previous command-line is producing warnings and fixes with the source
+// locations from a virtual buffer. VAL is replaced by '0+0'.
+// Fixes could not be applied and should not be reported.
+int foo() { return VAL; }
+
+#define V 0+0
+int bar() { return V; }
+// CHECK-FIXES: #define V (0+0)
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-macro-parentheses.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-macro-parentheses.cpp
new file mode 100644
index 0000000..2cc45e8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-macro-parentheses.cpp
@@ -0,0 +1,49 @@
+// RUN: %check_clang_tidy %s bugprone-macro-parentheses %t
+
+#define BAD1 -1
+// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: macro replacement list should be enclosed in parentheses [bugprone-macro-parentheses]
+#define BAD2 1+2
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: macro replacement list should be enclosed in parentheses [bugprone-macro-parentheses]
+#define BAD3(A) (A+1)
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses]
+#define BAD4(x) ((unsigned char)(x & 0xff))
+// CHECK-MESSAGES: :[[@LINE-1]]:44: warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses]
+#define BAD5(X) A*B=(C*)X+2
+// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses]
+
+#define GOOD1 1
+#define GOOD2 (1+2)
+#define GOOD3(A) #A
+#define GOOD4(A,B) A ## B
+#define GOOD5(T) ((T*)0)
+#define GOOD6(B) "A" B "C"
+#define GOOD7(b) A b
+#define GOOD8(a) a B
+#define GOOD9(type) (type(123))
+#define GOOD10(car, ...) car
+#define GOOD11 a[b+c]
+#define GOOD12(x) a[x]
+#define GOOD13(x) a.x
+#define GOOD14(x) a->x
+#define GOOD15(x) ({ int a = x; a+4; })
+#define GOOD16(x) a_ ## x, b_ ## x = c_ ## x - 1,
+#define GOOD17 case 123: x=4+5; break;
+#define GOOD18(x) ;x;
+#define GOOD19 ;-2;
+#define GOOD20 void*
+#define GOOD21(a) case Fred::a:
+#define GOOD22(a) if (verbose) return a;
+#define GOOD23(type) (type::Field)
+#define GOOD24(t) std::set<t> s
+#define GOOD25(t) std::set<t,t,t> s
+#define GOOD26(x) (a->*x)
+#define GOOD27(x) (a.*x)
+#define GOOD28(x) namespace x {int b;}
+#define GOOD29(...) std::cout << __VA_ARGS__;
+#define GOOD30(args...) std::cout << args;
+#define GOOD31(X) A*X=2
+#define GOOD32(X) std::vector<X>
+
+// These are allowed for now..
+#define MAYBE1 *12.34
+#define MAYBE2 <<3
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-macro-repeated-side-effects.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-macro-repeated-side-effects.c
new file mode 100644
index 0000000..bcea47a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-macro-repeated-side-effects.c
@@ -0,0 +1,106 @@
+// RUN: %check_clang_tidy %s bugprone-macro-repeated-side-effects %t
+
+#define badA(x,y) ((x)+((x)+(y))+(y))
+void bad(int ret, int a, int b) {
+ ret = badA(a++, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: side effects in the 1st macro argument 'x' are repeated in macro expansion [bugprone-macro-repeated-side-effects]
+ ret = badA(++a, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: side effects in the 1st macro argument 'x'
+ ret = badA(a--, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: side effects in the 1st macro argument 'x'
+ ret = badA(--a, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: side effects in the 1st macro argument 'x'
+ ret = badA(a, b++);
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: side effects in the 2nd macro argument 'y'
+ ret = badA(a, ++b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: side effects in the 2nd macro argument 'y'
+ ret = badA(a, b--);
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: side effects in the 2nd macro argument 'y'
+ ret = badA(a, --b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: side effects in the 2nd macro argument 'y'
+}
+
+
+#define MIN(A,B) ((A) < (B) ? (A) : (B)) // single ?:
+#define LIMIT(X,A,B) ((X) < (A) ? (A) : ((X) > (B) ? (B) : (X))) // two ?:
+void question(int x) {
+ MIN(x++, 12);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: side effects in the 1st macro argument 'A'
+ MIN(34, x++);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: side effects in the 2nd macro argument 'B'
+ LIMIT(x++, 0, 100);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: side effects in the 1st macro argument 'X'
+ LIMIT(20, x++, 100);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: side effects in the 2nd macro argument 'A'
+ LIMIT(20, 0, x++);
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: side effects in the 3rd macro argument 'B'
+}
+
+// False positive: Repeated side effects is intentional.
+// It is hard to know when it's done by intention so right now we warn.
+#define UNROLL(A) {A A}
+void fp1(int i) {
+ UNROLL({ i++; });
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: side effects in the 1st macro argument 'A'
+}
+
+// Do not produce a false positive on a strchr() macro. Explanation; Currently the '?'
+// triggers the test to bail out, because it cannot evaluate __builtin_constant_p(c).
+# define strchrs(s, c) \
+ (__extension__ (__builtin_constant_p (c) && !__builtin_constant_p (s) \
+ && (c) == '\0' \
+ ? (char *) __rawmemchr (s, c) \
+ : __builtin_strchr (s, c)))
+char* __rawmemchr(char* a, char b) {
+ return a;
+}
+void pass(char* pstr, char ch) {
+ strchrs(pstr, ch++); // No error.
+}
+
+// Check large arguments (t=20, u=21).
+#define largeA(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, x, y, z) \
+ ((a) + (a) + (b) + (b) + (c) + (c) + (d) + (d) + (e) + (e) + (f) + (f) + (g) + (g) + \
+ (h) + (h) + (i) + (i) + (j) + (j) + (k) + (k) + (l) + (l) + (m) + (m) + (n) + (n) + \
+ (o) + (o) + (p) + (p) + (q) + (q) + (r) + (r) + (s) + (s) + (t) + (t) + (u) + (u) + \
+ (v) + (v) + (x) + (x) + (y) + (y) + (z) + (z))
+void large(int a) {
+ largeA(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a++, 0, 0, 0, 0, 0, 0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:64: warning: side effects in the 19th macro argument 's'
+ largeA(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a++, 0, 0, 0, 0, 0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:67: warning: side effects in the 20th macro argument 't'
+ largeA(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a++, 0, 0, 0, 0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:70: warning: side effects in the 21st macro argument 'u'
+}
+
+// Passing macro argument as argument to __builtin_constant_p and macros.
+#define builtinbad(x) (__builtin_constant_p(x) + (x) + (x))
+#define builtingood1(x) (__builtin_constant_p(x) + (x))
+#define builtingood2(x) ((__builtin_constant_p(x) && (x)) || (x))
+#define macrobad(x) (builtingood1(x) + (x) + (x))
+#define macrogood(x) (builtingood1(x) + (x))
+void builtins(int ret, int a) {
+ ret += builtinbad(a++);
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: side effects in the 1st macro argument 'x'
+
+ ret += builtingood1(a++);
+ ret += builtingood2(a++);
+
+ ret += macrobad(a++);
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: side effects in the 1st macro argument 'x'
+
+ ret += macrogood(a++);
+}
+
+// Bail out for conditionals.
+#define condB(x,y) if(x) {x=y;} else {x=y + 1;}
+void conditionals(int a, int b)
+{
+ condB(a, b++);
+}
+
+void log(const char *s, int v);
+#define LOG(val) log(#val, (val))
+void test_log(int a) {
+ LOG(a++);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.c
new file mode 100644
index 0000000..c5deb25
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.c
@@ -0,0 +1,85 @@
+// RUN: %check_clang_tidy %s bugprone-misplaced-operator-in-strlen-in-alloc %t
+
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
+void *alloca(size_t);
+void *calloc(size_t, size_t);
+void *realloc(void *, size_t);
+
+size_t strlen(const char *);
+size_t strnlen(const char *, size_t);
+size_t strnlen_s(const char *, size_t);
+
+typedef unsigned wchar_t;
+
+size_t wcslen(const wchar_t *);
+size_t wcsnlen(const wchar_t *, size_t);
+size_t wcsnlen_s(const wchar_t *, size_t);
+
+void bad_malloc(char *name) {
+ char *new_name = (char *)malloc(strlen(name + 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+ // CHECK-FIXES: {{^ char \*new_name = \(char \*\)malloc\(}}strlen(name) + 1{{\);$}}
+ new_name = (char *)malloc(strnlen(name + 1, 10));
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: addition operator is applied to the argument of strnlen
+ // CHECK-FIXES: {{^ new_name = \(char \*\)malloc\(}}strnlen(name, 10) + 1{{\);$}}
+ new_name = (char *)malloc(strnlen_s(name + 1, 10));
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: addition operator is applied to the argument of strnlen_s
+ // CHECK-FIXES: {{^ new_name = \(char \*\)malloc\(}}strnlen_s(name, 10) + 1{{\);$}}
+}
+
+void bad_malloc_wide(wchar_t *name) {
+ wchar_t *new_name = (wchar_t *)malloc(wcslen(name + 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: addition operator is applied to the argument of wcslen
+ // CHECK-FIXES: {{^ wchar_t \*new_name = \(wchar_t \*\)malloc\(}}wcslen(name) + 1{{\);$}}
+ new_name = (wchar_t *)malloc(wcsnlen(name + 1, 10));
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: addition operator is applied to the argument of wcsnlen
+ // CHECK-FIXES: {{^ new_name = \(wchar_t \*\)malloc\(}}wcsnlen(name, 10) + 1{{\);$}}
+ new_name = (wchar_t *)malloc(wcsnlen_s(name + 1, 10));
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: addition operator is applied to the argument of wcsnlen_s
+ // CHECK-FIXES: {{^ new_name = \(wchar_t \*\)malloc\(}}wcsnlen_s(name, 10) + 1{{\);$}}
+}
+
+void bad_alloca(char *name) {
+ char *new_name = (char *)alloca(strlen(name + 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+ // CHECK-FIXES: {{^ char \*new_name = \(char \*\)alloca\(}}strlen(name) + 1{{\);$}}
+}
+
+void bad_calloc(char *name) {
+ char *new_names = (char *)calloc(2, strlen(name + 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: addition operator is applied to the argument of strlen
+ // CHECK-FIXES: {{^ char \*new_names = \(char \*\)calloc\(2, }}strlen(name) + 1{{\);$}}
+}
+
+void bad_realloc(char *old_name, char *name) {
+ char *new_name = (char *)realloc(old_name, strlen(name + 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+ // CHECK-FIXES: {{^ char \*new_name = \(char \*\)realloc\(old_name, }}strlen(name) + 1{{\);$}}
+}
+
+void intentional1(char *name) {
+ char *new_name = (char *)malloc(strlen(name + 1) + 1);
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+ // We have + 1 outside as well so we assume this is intentional
+}
+
+void intentional2(char *name) {
+ char *new_name = (char *)malloc(strlen(name + 2));
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+ // Only give warning for + 1, not + 2
+}
+
+void intentional3(char *name) {
+ char *new_name = (char *)malloc(strlen((name + 1)));
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+ // If expression is in extra parentheses, consider it as intentional
+}
+
+void (*(*const alloc_ptr)(size_t)) = malloc;
+
+void bad_indirect_alloc(char *name) {
+ char *new_name = (char *)alloc_ptr(strlen(name + 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+ // CHECK-FIXES: {{^ char \*new_name = \(char \*\)alloc_ptr\(}}strlen(name) + 1{{\);$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.cpp
new file mode 100644
index 0000000..58d63fa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.cpp
@@ -0,0 +1,58 @@
+// RUN: %check_clang_tidy %s bugprone-misplaced-operator-in-strlen-in-alloc %t
+
+namespace std {
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
+
+size_t strlen(const char *);
+} // namespace std
+
+namespace non_std {
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
+
+size_t strlen(const char *);
+} // namespace non_std
+
+void bad_std_malloc_std_strlen(char *name) {
+ char *new_name = (char *)std::malloc(std::strlen(name + 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+ // CHECK-FIXES: {{^ char \*new_name = \(char \*\)std::malloc\(}}std::strlen(name) + 1{{\);$}}
+}
+
+void ignore_non_std_malloc_std_strlen(char *name) {
+ char *new_name = (char *)non_std::malloc(std::strlen(name + 1));
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+ // Ignore functions of the malloc family in custom namespaces
+}
+
+void ignore_std_malloc_non_std_strlen(char *name) {
+ char *new_name = (char *)std::malloc(non_std::strlen(name + 1));
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+ // Ignore functions of the strlen family in custom namespaces
+}
+
+void bad_new_strlen(char *name) {
+ char *new_name = new char[std::strlen(name + 1)];
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: addition operator is applied to the argument of strlen
+ // CHECK-FIXES: {{^ char \*new_name = new char\[}}std::strlen(name) + 1{{\];$}}
+}
+
+void good_new_strlen(char *name) {
+ char *new_name = new char[std::strlen(name) + 1];
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:20: warning: addition operator is applied to the argument of strlen
+}
+
+class C {
+ char c;
+public:
+ static void *operator new[](std::size_t count) {
+ return ::operator new(count);
+ }
+};
+
+void bad_custom_new_strlen(char *name) {
+ C *new_name = new C[std::strlen(name + 1)];
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: addition operator is applied to the argument of strlen
+ // CHECK-FIXES: {{^ C \*new_name = new C\[}}std::strlen(name) + 1{{\];$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-widening-cast-explicit-only.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-widening-cast-explicit-only.cpp
new file mode 100644
index 0000000..be12614
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-widening-cast-explicit-only.cpp
@@ -0,0 +1,64 @@
+// RUN: %check_clang_tidy %s bugprone-misplaced-widening-cast %t -- -config="{CheckOptions: [{key: bugprone-misplaced-widening-cast.CheckImplicitCasts, value: 0}]}" --
+
+void func(long arg) {}
+
+void assign(int a, int b) {
+ long l;
+
+ l = a * b;
+ l = (long)(a * b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long' is ineffective, or there is loss of precision before the conversion [bugprone-misplaced-widening-cast]
+ l = (long)a * b;
+
+ l = a << 8;
+ l = (long)(a << 8);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long'
+ l = (long)b << 8;
+
+ l = static_cast<long>(a * b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long'
+}
+
+void compare(int a, int b, long c) {
+ bool l;
+
+ l = a * b == c;
+ l = c == a * b;
+ l = (long)(a * b) == c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long'
+ l = c == (long)(a * b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: either cast from 'int' to 'long'
+ l = (long)a * b == c;
+ l = c == (long)a * b;
+}
+
+void init(unsigned int n) {
+ long l1 = n << 8;
+ long l2 = (long)(n << 8);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: either cast from 'unsigned int' to 'long'
+ long l3 = (long)n << 8;
+}
+
+void call(unsigned int n) {
+ func(n << 8);
+ func((long)(n << 8));
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: either cast from 'unsigned int' to 'long'
+ func((long)n << 8);
+}
+
+long ret(int a) {
+ if (a < 0) {
+ return a * 1000;
+ } else if (a > 0) {
+ return (long)(a * 1000);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: either cast from 'int' to 'long'
+ } else {
+ return (long)a * 1000;
+ }
+}
+
+// Shall not generate an assert. https://bugs.llvm.org/show_bug.cgi?id=33660
+template <class> class A {
+ enum Type {};
+ static char *m_fn1() { char p = (Type)(&p - m_fn1()); }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-widening-cast-implicit-enabled.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-widening-cast-implicit-enabled.cpp
new file mode 100644
index 0000000..5487b33
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-widening-cast-implicit-enabled.cpp
@@ -0,0 +1,101 @@
+// RUN: %check_clang_tidy %s bugprone-misplaced-widening-cast %t -- -config="{CheckOptions: [{key: bugprone-misplaced-widening-cast.CheckImplicitCasts, value: 1}]}" --
+
+void func(long arg) {}
+
+void assign(int a, int b) {
+ long l;
+
+ l = a * b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long' is ineffective, or there is loss of precision before the conversion [bugprone-misplaced-widening-cast]
+ l = (long)(a * b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long'
+ l = (long)a * b;
+
+ l = a << 8;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long'
+ l = (long)(a << 8);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long'
+ l = (long)b << 8;
+
+ l = static_cast<long>(a * b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long'
+}
+
+void compare(int a, int b, long c) {
+ bool l;
+
+ l = a * b == c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long'
+ l = c == a * b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: either cast from 'int' to 'long'
+ l = (long)(a * b) == c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long'
+ l = c == (long)(a * b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: either cast from 'int' to 'long'
+ l = (long)a * b == c;
+ l = c == (long)a * b;
+}
+
+void init(unsigned int n) {
+ long l1 = n << 8;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: either cast from 'unsigned int' to 'long'
+ long l2 = (long)(n << 8);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: either cast from 'unsigned int' to 'long'
+ long l3 = (long)n << 8;
+}
+
+void call(unsigned int n) {
+ func(n << 8);
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: either cast from 'unsigned int' to 'long'
+ func((long)(n << 8));
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: either cast from 'unsigned int' to 'long'
+ func((long)n << 8);
+}
+
+long ret(int a) {
+ if (a < 0) {
+ return a * 1000;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: either cast from 'int' to 'long'
+ } else if (a > 0) {
+ return (long)(a * 1000);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: either cast from 'int' to 'long'
+ } else {
+ return (long)a * 1000;
+ }
+}
+
+void dontwarn1(unsigned char a, int i, unsigned char *p) {
+ long l;
+ // The result is a 9 bit value, there is no truncation in the implicit cast.
+ l = (long)(a + 15);
+ // The result is a 12 bit value, there is no truncation in the implicit cast.
+ l = (long)(a << 4);
+ // The result is a 3 bit value, there is no truncation in the implicit cast.
+ l = (long)((i % 5) + 1);
+ // The result is a 16 bit value, there is no truncation in the implicit cast.
+ l = (long)(((*p) << 8) + *(p + 1));
+}
+
+template <class T> struct DontWarn2 {
+ void assign(T a, T b) {
+ long l;
+ l = (long)(a * b);
+ }
+};
+DontWarn2<int> DW2;
+
+// Cast is not suspicious when casting macro.
+#define A (X<<2)
+long macro1(int X) {
+ return (long)A;
+}
+
+// Don't warn about cast in macro.
+#define B(X,Y) (long)(X*Y)
+long macro2(int x, int y) {
+ return B(x,y);
+}
+
+void floatingpoint(float a, float b) {
+ double d = (double)(a * b); // Currently we don't warn for this.
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-move-forwarding-reference.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-move-forwarding-reference.cpp
new file mode 100644
index 0000000..befca29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-move-forwarding-reference.cpp
@@ -0,0 +1,125 @@
+// RUN: %check_clang_tidy %s bugprone-move-forwarding-reference %t -- -- -std=c++14 -fno-delayed-template-parsing
+
+namespace std {
+template <typename> struct remove_reference;
+
+template <typename _Tp> struct remove_reference { typedef _Tp type; };
+
+template <typename _Tp> struct remove_reference<_Tp &> { typedef _Tp type; };
+
+template <typename _Tp> struct remove_reference<_Tp &&> { typedef _Tp type; };
+
+template <typename _Tp>
+constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t);
+
+} // namespace std
+
+// Standard case.
+template <typename T, typename U> void f1(U &&SomeU) {
+ T SomeT(std::move(SomeU));
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to
+ // CHECK-FIXES: T SomeT(std::forward<U>(SomeU));
+}
+
+// Ignore parentheses around the argument to std::move().
+template <typename T, typename U> void f2(U &&SomeU) {
+ T SomeT(std::move((SomeU)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to
+ // CHECK-FIXES: T SomeT(std::forward<U>((SomeU)));
+}
+
+// Handle the case correctly where std::move() is being used through a using
+// declaration.
+template <typename T, typename U> void f3(U &&SomeU) {
+ using std::move;
+ T SomeT(move(SomeU));
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to
+ // CHECK-FIXES: T SomeT(std::forward<U>(SomeU));
+}
+
+// Handle the case correctly where a global specifier is prepended to
+// std::move().
+template <typename T, typename U> void f4(U &&SomeU) {
+ T SomeT(::std::move(SomeU));
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to
+ // CHECK-FIXES: T SomeT(::std::forward<U>(SomeU));
+}
+
+// Create a correct fix if there are spaces around the scope resolution
+// operator.
+template <typename T, typename U> void f5(U &&SomeU) {
+ {
+ T SomeT(:: std :: move(SomeU));
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: forwarding reference passed to
+ // CHECK-FIXES: T SomeT(::std::forward<U>(SomeU));
+ }
+ {
+ T SomeT(std :: move(SomeU));
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: forwarding reference passed to
+ // CHECK-FIXES: T SomeT(std::forward<U>(SomeU));
+ }
+}
+
+// Ignore const rvalue reference parameters.
+template <typename T, typename U> void f6(const U &&SomeU) {
+ T SomeT(std::move(SomeU));
+}
+
+// Ignore the case where the argument to std::move() is a lambda parameter (and
+// thus not actually a parameter of the function template).
+template <typename T, typename U> void f7() {
+ [](U &&SomeU) { T SomeT(std::move(SomeU)); };
+}
+
+// Ignore the case where the argument is a lvalue reference.
+template <typename T, typename U> void f8(U &SomeU) {
+ T SomeT(std::move(SomeU));
+}
+
+// Ignore the case where the template parameter is a class template parameter
+// (i.e. no template argument deduction is taking place).
+template <typename T, typename U> class SomeClass {
+ void f(U &&SomeU) { T SomeT(std::move(SomeU)); }
+};
+
+// Ignore the case where the function parameter in the template isn't an rvalue
+// reference but the template argument is explicitly set to be an rvalue
+// reference.
+class A {};
+template <typename T> void foo(T);
+void f8() {
+ A a;
+ foo<A &&>(std::move(a));
+}
+
+// A warning is output, but no fix is suggested, if a macro is used to rename
+// std::move.
+#define MOVE(x) std::move((x))
+template <typename T, typename U> void f9(U &&SomeU) {
+ T SomeT(MOVE(SomeU));
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to
+}
+
+// Same result if the argument is passed outside of the macro.
+#undef MOVE
+#define MOVE std::move
+template <typename T, typename U> void f10(U &&SomeU) {
+ T SomeT(MOVE(SomeU));
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to
+}
+
+// Same result if the macro does not include the "std" namespace.
+#undef MOVE
+#define MOVE move
+template <typename T, typename U> void f11(U &&SomeU) {
+ T SomeT(std::MOVE(SomeU));
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to
+}
+
+// Handle the case correctly where the forwarding reference is a parameter of a
+// generic lambda.
+template <typename T> void f12() {
+ [] (auto&& x) { T SomeT(std::move(x)); };
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: forwarding reference passed to
+ // CHECK-FIXES: [] (auto&& x) { T SomeT(std::forward<decltype(x)>(x)); }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-multiple-statement-macro.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-multiple-statement-macro.cpp
new file mode 100644
index 0000000..5b88d8d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-multiple-statement-macro.cpp
@@ -0,0 +1,85 @@
+// RUN: %check_clang_tidy %s bugprone-multiple-statement-macro %t
+
+void F();
+
+#define BAD_MACRO(x) \
+ F(); \
+ F()
+
+#define GOOD_MACRO(x) \
+ do { \
+ F(); \
+ F(); \
+ } while (0)
+
+#define GOOD_MACRO2(x) F()
+
+#define GOOD_MACRO3(x) F();
+
+#define MACRO_ARG_MACRO(X) \
+ if (54) \
+ X(2)
+
+#define ALL_IN_MACRO(X) \
+ if (43) \
+ F(); \
+ F()
+
+#define GOOD_NESTED(x) \
+ if (x) \
+ GOOD_MACRO3(x); \
+ F();
+
+#define IF(x) if(x)
+
+void positives() {
+ if (1)
+ BAD_MACRO(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: multiple statement macro used without braces; some statements will be unconditionally executed [bugprone-multiple-statement-macro]
+ if (1) {
+ } else
+ BAD_MACRO(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: multiple statement macro used
+ while (1)
+ BAD_MACRO(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: multiple statement macro used
+ for (;;)
+ BAD_MACRO(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: multiple statement macro used
+
+ MACRO_ARG_MACRO(BAD_MACRO);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: multiple statement macro used
+ MACRO_ARG_MACRO(F(); int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: multiple statement macro used
+ IF(1) BAD_MACRO(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: multiple statement macro used
+}
+
+void negatives() {
+ if (1) {
+ BAD_MACRO(1);
+ } else {
+ BAD_MACRO(1);
+ }
+ while (1) {
+ BAD_MACRO(1);
+ }
+ for (;;) {
+ BAD_MACRO(1);
+ }
+
+ if (1)
+ GOOD_MACRO(1);
+ if (1) {
+ GOOD_MACRO(1);
+ }
+ if (1)
+ GOOD_MACRO2(1);
+ if (1)
+ GOOD_MACRO3(1);
+
+ MACRO_ARG_MACRO(GOOD_MACRO);
+ ALL_IN_MACRO(1);
+
+ IF(1) GOOD_MACRO(1);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-parent-virtual-call.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-parent-virtual-call.cpp
new file mode 100755
index 0000000..ad84588
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-parent-virtual-call.cpp
@@ -0,0 +1,179 @@
+// RUN: %check_clang_tidy %s bugprone-parent-virtual-call %t
+
+extern int foo();
+
+class A {
+public:
+ A() = default;
+ virtual ~A() = default;
+
+ virtual int virt_1() { return foo() + 1; }
+ virtual int virt_2() { return foo() + 2; }
+
+ int non_virt() { return foo() + 3; }
+ static int stat() { return foo() + 4; }
+};
+
+class B : public A {
+public:
+ B() = default;
+
+ // Nothing to fix: calls to direct parent.
+ int virt_1() override { return A::virt_1() + 3; }
+ int virt_2() override { return A::virt_2() + 4; }
+};
+
+class C : public B {
+public:
+ int virt_1() override { return A::virt_1() + B::virt_1(); }
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' refers to a member overridden in subclass; did you mean 'B'? [bugprone-parent-virtual-call]
+ // CHECK-FIXES: int virt_1() override { return B::virt_1() + B::virt_1(); }
+ int virt_2() override { return A::virt_1() + B::virt_1(); }
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'B'? {{.*}}
+ // CHECK-FIXES: int virt_2() override { return B::virt_1() + B::virt_1(); }
+
+ // Test that non-virtual and static methods are not affected by this cherker.
+ int method_c() { return A::stat() + A::non_virt(); }
+};
+
+// Check aliased type names
+using A1 = A;
+typedef A A2;
+#define A3 A
+
+class C2 : public B {
+public:
+ int virt_1() override { return A1::virt_1() + A2::virt_1() + A3::virt_1(); }
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A1::virt_1' {{.*}}; did you mean 'B'? {{.*}}
+ // CHECK-MESSAGES: :[[@LINE-2]]:49: warning: qualified name 'A2::virt_1' {{.*}}; did you mean 'B'? {{.*}}
+ // CHECK-MESSAGES: :[[@LINE-3]]:64: warning: qualified name 'A3::virt_1' {{.*}}; did you mean 'B'? {{.*}}
+ // CHECK-FIXES: int virt_1() override { return B::virt_1() + B::virt_1() + B::virt_1(); }
+};
+
+// Test that the check affects grand-grand..-parent calls too.
+class D : public C {
+public:
+ int virt_1() override { return A::virt_1() + B::virt_1() + D::virt_1(); }
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'C'? {{.*}}
+ // CHECK-MESSAGES: :[[@LINE-2]]:48: warning: qualified name 'B::virt_1' {{.*}}; did you mean 'C'? {{.*}}
+ // CHECK-FIXES: int virt_1() override { return C::virt_1() + C::virt_1() + D::virt_1(); }
+ int virt_2() override { return A::virt_1() + B::virt_1() + D::virt_1(); }
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'C'? {{.*}}
+ // CHECK-MESSAGES: :[[@LINE-2]]:48: warning: qualified name 'B::virt_1' {{.*}}; did you mean 'C'? {{.*}}
+ // CHECK-FIXES: int virt_2() override { return C::virt_1() + C::virt_1() + D::virt_1(); }
+};
+
+// Test classes in namespaces.
+namespace {
+class BN : public A {
+public:
+ int virt_1() override { return A::virt_1() + 3; }
+ int virt_2() override { return A::virt_2() + 4; }
+};
+} // namespace
+
+namespace N1 {
+class A {
+public:
+ A() = default;
+ virtual int virt_1() { return foo() + 1; }
+ virtual int virt_2() { return foo() + 2; }
+};
+} // namespace N1
+
+namespace N2 {
+class BN : public N1::A {
+public:
+ int virt_1() override { return A::virt_1() + 3; }
+ int virt_2() override { return A::virt_2() + 4; }
+};
+} // namespace N2
+
+class CN : public BN {
+public:
+ int virt_1() override { return A::virt_1() + BN::virt_1(); }
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'BN'? {{.*}}
+ // CHECK-FIXES: int virt_1() override { return BN::virt_1() + BN::virt_1(); }
+ int virt_2() override { return A::virt_1() + BN::virt_1(); }
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'BN'? {{.*}}
+ // CHECK-FIXES: int virt_2() override { return BN::virt_1() + BN::virt_1(); }
+};
+
+class CNN : public N2::BN {
+public:
+ int virt_1() override { return N1::A::virt_1() + N2::BN::virt_1(); }
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'N1::A::virt_1' {{.*}}; did you mean 'N2::BN'? {{.*}}
+ // CHECK-FIXES: int virt_1() override { return N2::BN::virt_1() + N2::BN::virt_1(); }
+ int virt_2() override { return N1::A::virt_1() + N2::BN::virt_1(); }
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'N1::A::virt_1' {{.*}}; did you mean 'N2::BN'? {{.*}}
+ // CHECK-FIXES: int virt_2() override { return N2::BN::virt_1() + N2::BN::virt_1(); }
+};
+
+// Test multiple inheritance fixes
+class AA {
+public:
+ AA() = default;
+ virtual ~AA() = default;
+
+ virtual int virt_1() { return foo() + 1; }
+ virtual int virt_2() { return foo() + 2; }
+
+ int non_virt() { return foo() + 3; }
+ static int stat() { return foo() + 4; }
+};
+
+class BB_1 : virtual public AA {
+public:
+ BB_1() = default;
+
+ // Nothing to fix: calls to parent.
+ int virt_1() override { return AA::virt_1() + 3; }
+ int virt_2() override { return AA::virt_2() + 4; }
+};
+
+class BB_2 : virtual public AA {
+public:
+ BB_2() = default;
+ int virt_1() override { return AA::virt_1() + 3; }
+};
+
+class CC : public BB_1, public BB_2 {
+public:
+ int virt_1() override { return AA::virt_1() + 3; }
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'AA::virt_1' refers to a member overridden in subclasses; did you mean 'BB_1' or 'BB_2'? {{.*}}
+ // No fix available due to multiple choice of parent class.
+};
+
+// Test that virtual method is not diagnosed as not overridden in parent.
+class BI : public A {
+public:
+ BI() = default;
+};
+
+class CI : BI {
+ int virt_1() override { return A::virt_1(); }
+};
+
+// Test templated classes.
+template <class F> class BF : public A {
+public:
+ int virt_1() override { return A::virt_1() + 3; }
+};
+
+// Test templated parent class.
+class CF : public BF<int> {
+public:
+ int virt_1() override { return A::virt_1(); }
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'BF'? {{.*}}
+};
+
+// Test both templated class and its parent class.
+template <class F> class DF : public BF<F> {
+public:
+ DF() = default;
+ int virt_1() override { return A::virt_1(); }
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'BF'? {{.*}}
+};
+
+// Just to instantiate DF<F>.
+int bar() { return (new DF<int>())->virt_1(); }
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-sizeof-container.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-sizeof-container.cpp
new file mode 100644
index 0000000..27798d6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-sizeof-container.cpp
@@ -0,0 +1,103 @@
+// RUN: %check_clang_tidy %s bugprone-sizeof-container %t -- -- -std=c++11 -target x86_64-unknown-unknown
+
+namespace std {
+
+typedef unsigned int size_t;
+
+template <typename T>
+struct basic_string {
+ size_t size() const;
+};
+
+template <typename T>
+basic_string<T> operator+(const basic_string<T> &, const T *);
+
+typedef basic_string<char> string;
+
+template <typename T>
+struct vector {
+ size_t size() const;
+};
+
+// std::bitset<> is not a container. sizeof() is reasonable for it.
+template <size_t N>
+struct bitset {
+ size_t size() const;
+};
+
+// std::array<> is, well, an array. sizeof() is reasonable for it.
+template <typename T, size_t N>
+struct array {
+ size_t size() const;
+};
+
+class fake_container1 {
+ size_t size() const; // non-public
+};
+
+struct fake_container2 {
+ size_t size(); // non-const
+};
+
+}
+
+using std::size_t;
+
+#define ARRAYSIZE(a) \
+ ((sizeof(a) / sizeof(*(a))) / static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
+
+#define ARRAYSIZE2(a) \
+ (((sizeof(a)) / (sizeof(*(a)))) / static_cast<size_t>(!((sizeof(a)) % (sizeof(*(a))))))
+
+struct string {
+ std::size_t size() const;
+};
+
+template<typename T>
+void g(T t) {
+ (void)sizeof(t);
+}
+
+void f() {
+ string s1;
+ std::string s2;
+ std::vector<int> v;
+
+ int a = 42 + sizeof(s1);
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: sizeof() doesn't return the size of the container; did you mean .size()? [bugprone-sizeof-container]
+ a = 123 * sizeof(s2);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: sizeof() doesn't return the size
+ a = 45 + sizeof(s2 + "asdf");
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: sizeof() doesn't return the size
+ a = sizeof(v);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: sizeof() doesn't return the size
+ a = sizeof(std::vector<int>{});
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: sizeof() doesn't return the size
+
+ a = sizeof(a);
+ a = sizeof(int);
+ a = sizeof(std::string);
+ a = sizeof(std::vector<int>);
+
+ g(s1);
+ g(s2);
+ g(v);
+
+ std::fake_container1 fake1;
+ std::fake_container2 fake2;
+ std::bitset<7> std_bitset;
+ std::array<int, 3> std_array;
+
+ a = sizeof(fake1);
+ a = sizeof(fake2);
+ a = sizeof(std_bitset);
+ a = sizeof(std_array);
+
+
+ std::string arr[3];
+ a = ARRAYSIZE(arr);
+ a = ARRAYSIZE2(arr);
+ a = sizeof(arr) / sizeof(arr[0]);
+
+ (void)a;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-sizeof-expression.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-sizeof-expression.cpp
new file mode 100644
index 0000000..683ad08
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-sizeof-expression.cpp
@@ -0,0 +1,256 @@
+// RUN: %check_clang_tidy %s bugprone-sizeof-expression %t -- -config="{CheckOptions: [{key: bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression, value: 1}]}" --
+
+class C {
+ int size() { return sizeof(this); }
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(this)'
+};
+
+#define LEN 8
+
+int X;
+extern int A[10];
+extern short B[10];
+
+#pragma pack(1)
+struct S { char a, b, c; };
+
+enum E { E_VALUE = 0 };
+enum class EC { VALUE = 0 };
+
+bool AsBool() { return false; }
+int AsInt() { return 0; }
+E AsEnum() { return E_VALUE; }
+EC AsEnumClass() { return EC::VALUE; }
+S AsStruct() { return {}; }
+
+struct M {
+ int AsInt() { return 0; }
+ E AsEnum() { return E_VALUE; }
+ S AsStruct() { return {}; }
+};
+
+int ReturnOverload(int) { return {}; }
+S ReturnOverload(S) { return {}; }
+
+template <class T>
+T ReturnTemplate(T) { return {}; }
+
+template <class T>
+bool TestTrait1() {
+ return sizeof(ReturnOverload(T{})) == sizeof(A);
+}
+
+template <class T>
+bool TestTrait2() {
+ return sizeof(ReturnTemplate(T{})) == sizeof(A);
+}
+
+template <class T>
+bool TestTrait3() {
+ return sizeof(ReturnOverload(0)) == sizeof(T{});
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
+}
+
+template <class T>
+bool TestTrait4() {
+ return sizeof(ReturnTemplate(0)) == sizeof(T{});
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
+}
+
+bool TestTemplates() {
+ bool b = true;
+ b &= TestTrait1<int>();
+ b &= TestTrait1<S>();
+ b &= TestTrait2<int>();
+ b &= TestTrait2<S>();
+ b &= TestTrait3<int>();
+ b &= TestTrait3<S>();
+ b &= TestTrait4<int>();
+ b &= TestTrait4<S>();
+ return b;
+}
+
+int Test1(const char* ptr) {
+ int sum = 0;
+ sum += sizeof(LEN);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(K)'
+ sum += sizeof(LEN + 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(K)'
+ sum += sizeof(sum, LEN);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(..., ...)'
+ sum += sizeof(AsBool());
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
+ sum += sizeof(AsInt());
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
+ sum += sizeof(AsEnum());
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
+ sum += sizeof(AsEnumClass());
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
+ sum += sizeof(M{}.AsInt());
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
+ sum += sizeof(M{}.AsEnum());
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
+ sum += sizeof(sizeof(X));
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
+ sum += sizeof(LEN + sizeof(X));
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
+ sum += sizeof(LEN + LEN + sizeof(X));
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
+ sum += sizeof(LEN + (LEN + sizeof(X)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
+ sum += sizeof(LEN + -sizeof(X));
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
+ sum += sizeof(LEN + - + -sizeof(X));
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
+ sum += sizeof(char) / sizeof(char);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
+ sum += sizeof(A) / sizeof(S);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
+ sum += sizeof(char) / sizeof(int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
+ sum += sizeof(char) / sizeof(A);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
+ sum += sizeof(B[0]) / sizeof(A);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
+ sum += sizeof(ptr) / sizeof(char);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'
+ sum += sizeof(ptr) / sizeof(ptr[0]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'
+ sum += sizeof(ptr) / sizeof(char*);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(P*)/sizeof(Q*)'
+ sum += sizeof(ptr) / sizeof(void*);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(P*)/sizeof(Q*)'
+ sum += sizeof(ptr) / sizeof(const void volatile*);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(P*)/sizeof(Q*)'
+ sum += sizeof(ptr) / sizeof(char);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'
+ sum += sizeof(ptr) / sizeof(ptr[0]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'
+ sum += sizeof(int) * sizeof(char);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious 'sizeof' by 'sizeof' multiplication
+ sum += sizeof(ptr) * sizeof(ptr[0]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious 'sizeof' by 'sizeof' multiplication
+ sum += sizeof(int) * (2 * sizeof(char));
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious 'sizeof' by 'sizeof' multiplication
+ sum += (2 * sizeof(char)) * sizeof(int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious 'sizeof' by 'sizeof' multiplication
+ if (sizeof(A) < 0x100000) sum += 42;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: suspicious comparison of 'sizeof(expr)' to a constant
+ if (sizeof(A) <= 0xFFFFFFFEU) sum += 42;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: suspicious comparison of 'sizeof(expr)' to a constant
+ return sum;
+}
+
+typedef char MyChar;
+typedef const MyChar MyConstChar;
+
+int CE0 = sizeof sizeof(char);
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
+int CE1 = sizeof +sizeof(char);
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
+int CE2 = sizeof sizeof(const char*);
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
+int CE3 = sizeof sizeof(const volatile char* const*);
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
+int CE4 = sizeof sizeof(MyConstChar);
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
+
+int Test2(MyConstChar* A) {
+ int sum = 0;
+ sum += sizeof(MyConstChar) / sizeof(char);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
+ sum += sizeof(MyConstChar) / sizeof(MyChar);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
+ sum += sizeof(A[0]) / sizeof(char);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
+ return sum;
+}
+
+template <int T>
+int Foo() { int A[T]; return sizeof(T); }
+// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: suspicious usage of 'sizeof(K)'
+template <typename T>
+int Bar() { T A[5]; return sizeof(A[0]) / sizeof(T); }
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
+int Test3() { return Foo<42>() + Bar<char>(); }
+
+static const char* kABC = "abc";
+static const wchar_t* kDEF = L"def";
+int Test4(const char A[10]) {
+ int sum = 0;
+ sum += sizeof(kABC);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(char*)'
+ sum += sizeof(kDEF);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(char*)'
+ return sum;
+}
+
+int Test5() {
+ typedef int Array10[10];
+
+ struct MyStruct {
+ Array10 arr;
+ Array10* ptr;
+ };
+ typedef const MyStruct TMyStruct;
+
+ static TMyStruct kGlocalMyStruct = {};
+ static TMyStruct volatile * kGlocalMyStructPtr = &kGlocalMyStruct;
+
+ MyStruct S;
+ Array10 A10;
+
+ int sum = 0;
+ sum += sizeof(&S.arr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+ sum += sizeof(&kGlocalMyStruct.arr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+ sum += sizeof(&kGlocalMyStructPtr->arr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+ sum += sizeof(S.arr + 0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+ sum += sizeof(+ S.arr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+ sum += sizeof((int*)S.arr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+
+ sum += sizeof(S.ptr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+ sum += sizeof(kGlocalMyStruct.ptr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+ sum += sizeof(kGlocalMyStructPtr->ptr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+
+ sum += sizeof(&kGlocalMyStruct);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+ sum += sizeof(&S);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+ sum += sizeof(&A10);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+
+ return sum;
+}
+
+int ValidExpressions() {
+ int A[] = {1, 2, 3, 4};
+ static const char str[] = "hello";
+ static const char* ptr[] { "aaa", "bbb", "ccc" };
+ int sum = 0;
+ if (sizeof(A) < 10)
+ sum += sizeof(A);
+ sum += sizeof(int);
+ sum += sizeof(AsStruct());
+ sum += sizeof(M{}.AsStruct());
+ sum += sizeof(A[sizeof(A) / sizeof(int)]);
+ sum += sizeof(&A[sizeof(A) / sizeof(int)]);
+ sum += sizeof(sizeof(0)); // Special case: sizeof size_t.
+ sum += sizeof(void*);
+ sum += sizeof(void const *);
+ sum += sizeof(void const *) / 4;
+ sum += sizeof(str);
+ sum += sizeof(str) / sizeof(char);
+ sum += sizeof(str) / sizeof(str[0]);
+ sum += sizeof(ptr) / sizeof(ptr[0]);
+ sum += sizeof(ptr) / sizeof(*(ptr));
+ return sum;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-string-constructor.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-string-constructor.cpp
new file mode 100644
index 0000000..51d9130
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-string-constructor.cpp
@@ -0,0 +1,56 @@
+// RUN: %check_clang_tidy %s bugprone-string-constructor %t
+
+namespace std {
+template <typename T>
+class allocator {};
+template <typename T>
+class char_traits {};
+template <typename C, typename T = std::char_traits<C>, typename A = std::allocator<C> >
+struct basic_string {
+ basic_string();
+ basic_string(const C*, unsigned int size);
+ basic_string(unsigned int size, C c);
+};
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+}
+
+const char* kText = "";
+const char kText2[] = "";
+extern const char kText3[];
+
+void Test() {
+ std::string str('x', 4);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor parameters are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+ // CHECK-FIXES: std::string str(4, 'x');
+ std::wstring wstr(L'x', 4);
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: string constructor parameters are probably swapped
+ // CHECK-FIXES: std::wstring wstr(4, L'x');
+ std::string s0(0, 'x');
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: constructor creating an empty string
+ std::string s1(-4, 'x');
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: negative value used as length parameter
+ std::string s2(0x1000000, 'x');
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: suspicious large length parameter
+
+ std::string q0("test", 0);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: constructor creating an empty string
+ std::string q1(kText, -4);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: negative value used as length parameter
+ std::string q2("test", 200);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: length is bigger then string literal size
+ std::string q3(kText, 200);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: length is bigger then string literal size
+ std::string q4(kText2, 200);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: length is bigger then string literal size
+ std::string q5(kText3, 0x1000000);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: suspicious large length parameter
+}
+
+void Valid() {
+ std::string empty();
+ std::string str(4, 'x');
+ std::wstring wstr(4, L'x');
+ std::string s1("test", 4);
+ std::string s2("test", 3);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-string-integer-assignment.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-string-integer-assignment.cpp
new file mode 100644
index 0000000..c4e13fc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-string-integer-assignment.cpp
@@ -0,0 +1,53 @@
+// RUN: %check_clang_tidy %s bugprone-string-integer-assignment %t
+
+namespace std {
+template<typename T>
+struct basic_string {
+ basic_string& operator=(T);
+ basic_string& operator=(basic_string);
+ basic_string& operator+=(T);
+ basic_string& operator+=(basic_string);
+};
+
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+}
+
+typedef int MyArcaneChar;
+
+int main() {
+ std::string s;
+ std::wstring ws;
+ int x = 5;
+
+ s = 6;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: an integer is interpreted as a character code when assigning {{.*}} [bugprone-string-integer-assignment]
+// CHECK-FIXES: {{^}} s = '6';{{$}}
+ s = 66;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: an integer is interpreted as a chara
+// CHECK-FIXES: {{^}} s = "66";{{$}}
+ s = x;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: an integer is interpreted as a chara
+// CHECK-FIXES: {{^}} s = std::to_string(x);{{$}}
+ s = 'c';
+ s = static_cast<char>(6);
+
+// +=
+ ws += 6;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: an integer is interpreted as a chara
+// CHECK-FIXES: {{^}} ws += L'6';{{$}}
+ ws += 66;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: an integer is interpreted as a chara
+// CHECK-FIXES: {{^}} ws += L"66";{{$}}
+ ws += x;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: an integer is interpreted as a chara
+// CHECK-FIXES: {{^}} ws += std::to_wstring(x);{{$}}
+ ws += L'c';
+ ws += (wchar_t)6;
+
+ std::basic_string<MyArcaneChar> as;
+ as = 6;
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: an integer is interpreted as a chara
+// CHECK-FIXES: {{^}} as = 6;{{$}}
+
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-string-literal-with-embedded-nul.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-string-literal-with-embedded-nul.cpp
new file mode 100644
index 0000000..f939f52
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-string-literal-with-embedded-nul.cpp
@@ -0,0 +1,85 @@
+// RUN: %check_clang_tidy %s bugprone-string-literal-with-embedded-nul %t
+
+namespace std {
+template <typename T>
+class allocator {};
+template <typename T>
+class char_traits {};
+template <typename C, typename T, typename A>
+struct basic_string {
+ typedef basic_string<C, T, A> _Type;
+ basic_string();
+ basic_string(const C *p, const A &a = A());
+
+ _Type& operator+=(const C* s);
+ _Type& operator=(const C* s);
+};
+
+typedef basic_string<char, std::char_traits<char>, std::allocator<char>> string;
+typedef basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>> wstring;
+}
+
+bool operator==(const std::string&, const char*);
+bool operator==(const char*, const std::string&);
+
+
+const char Valid[] = "This is valid \x12.";
+const char Strange[] = "This is strange \0x12 and must be fixed";
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: suspicious embedded NUL character [bugprone-string-literal-with-embedded-nul]
+
+const char textA[] = "\0x01\0x02\0x03\0x04";
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious embedded NUL character
+const wchar_t textW[] = L"\0x01\0x02\0x03\0x04";
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: suspicious embedded NUL character
+
+const char A[] = "\0";
+const char B[] = "\0x";
+const char C[] = "\0x1";
+const char D[] = "\0x11";
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: suspicious embedded NUL character
+
+const wchar_t E[] = L"\0";
+const wchar_t F[] = L"\0x";
+const wchar_t G[] = L"\0x1";
+const wchar_t H[] = L"\0x11";
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: suspicious embedded NUL character
+
+const char I[] = "\000\000\000\000";
+const char J[] = "\0\0\0\0\0\0";
+const char K[] = "";
+
+const char L[] = "\0x12" "\0x12" "\0x12" "\0x12";
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: suspicious embedded NUL character
+
+void TestA() {
+ std::string str1 = "abc\0def";
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: truncated string literal
+ std::string str2 = "\0";
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: truncated string literal
+ std::string str3("\0");
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: truncated string literal
+ std::string str4{"\x00\x01\x02\x03"};
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: truncated string literal
+
+ std::string str;
+ str += "abc\0def";
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: truncated string literal
+ str = "abc\0def";
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: truncated string literal
+
+ if (str == "abc\0def") return;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: truncated string literal
+ if ("abc\0def" == str) return;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: truncated string literal
+}
+
+void TestW() {
+ std::wstring str1 = L"abc\0def";
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: truncated string literal
+ std::wstring str2 = L"\0";
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: truncated string literal
+ std::wstring str3(L"\0");
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: truncated string literal
+ std::wstring str4{L"\x00\x01\x02\x03"};
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: truncated string literal
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-enum-usage-strict.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-enum-usage-strict.cpp
new file mode 100644
index 0000000..d9ed8ce
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-enum-usage-strict.cpp
@@ -0,0 +1,98 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-enum-usage %t -- -config="{CheckOptions: [{key: bugprone-suspicious-enum-usage.StrictMode, value: 1}]}" --
+
+enum A {
+ A = 1,
+ B = 2,
+ C = 4,
+ D = 8,
+ E = 16,
+ F = 32,
+ G = 63
+};
+
+// CHECK-MESSAGES: :[[@LINE+2]]:1: warning: enum type seems like a bitmask (contains mostly power-of-2 literals) but a literal is not power-of-2
+// CHECK-MESSAGES: :76:7: note: used here as a bitmask
+enum X {
+ X = 8,
+ Y = 16,
+ Z = 4,
+ ZZ = 3
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: enum type seems like a bitmask (contains mostly power-of-2 literals), but this literal is not a power-of-2 [bugprone-suspicious-enum-usage]
+// CHECK-MESSAGES: :70:13: note: used here as a bitmask
+};
+// CHECK-MESSAGES: :[[@LINE+2]]:1: warning: enum type seems like a bitmask (contains mostly power-of-2 literals) but some literals are not power-of-2
+// CHECK-MESSAGES: :73:8: note: used here as a bitmask
+enum PP {
+ P = 2,
+ Q = 3,
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: enum type seems like a bitmask (contains mostly power-of-2 literals), but this literal is not a power-of-2
+ // CHECK-MESSAGES: :65:11: note: used here as a bitmask
+ R = 4,
+ S = 8,
+ T = 16,
+ U = 31
+};
+
+enum {
+ H,
+ I,
+ J,
+ K,
+ L
+};
+
+enum Days {
+ Monday,
+ Tuesday,
+ Wednesday,
+ Thursday,
+ Friday,
+ Saturday,
+ Sunday
+};
+
+Days bestDay() {
+ return Friday;
+}
+
+int trigger() {
+ if (bestDay() | A)
+ return 1;
+ // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types
+ if (I | Y)
+ return 1;
+ // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
+ if (P + Q == R)
+ return 1;
+ else if ((S | R) == T)
+ return 1;
+ else
+ int k = ZZ | Z;
+ unsigned p = R;
+ PP pp = Q;
+ p |= pp;
+
+ enum X x = Z;
+ p = x | Z;
+ return 0;
+}
+
+int dont_trigger() {
+ int a = 1, b = 5;
+ int c = a + b;
+ int d = c | H, e = b * a;
+ a = B | C;
+ b = X | Z;
+
+ unsigned bitflag;
+ enum A aa = B;
+ bitflag = aa | C;
+
+ if (Tuesday != Monday + 1 ||
+ Friday - Thursday != 1 ||
+ Sunday + Wednesday == (Sunday | Wednesday))
+ return 1;
+ if (H + I + L == 42)
+ return 1;
+ return 42;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-enum-usage.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-enum-usage.cpp
new file mode 100644
index 0000000..e1a54d4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-enum-usage.cpp
@@ -0,0 +1,96 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-enum-usage %t -- -config="{CheckOptions: [{key: bugprone-suspicious-enum-usage.StrictMode, value: 0}]}" --
+
+enum Empty {
+};
+
+enum A {
+ A = 1,
+ B = 2,
+ C = 4,
+ D = 8,
+ E = 16,
+ F = 32,
+ G = 63
+};
+
+enum X {
+ X = 8,
+ Y = 16,
+ Z = 4
+};
+
+enum {
+ P = 2,
+ Q = 3,
+ R = 4,
+ S = 8,
+ T = 16
+};
+
+enum {
+ H,
+ I,
+ J,
+ K,
+ L
+};
+
+enum Days {
+ Monday,
+ Tuesday,
+ Wednesday,
+ Thursday,
+ Friday,
+ Saturday,
+ Sunday
+};
+
+Days bestDay() {
+ return Friday;
+}
+
+int trigger() {
+ Empty EmptyVal;
+ int emptytest = EmptyVal | B;
+ if (bestDay() | A)
+ return 1;
+ // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types
+ if (I | Y)
+ return 1;
+ // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
+}
+
+int dont_trigger() {
+ unsigned p;
+ p = Q | P;
+
+ if (A + G == E)
+ return 1;
+ else if ((Q | R) == T)
+ return 1;
+ else
+ int k = T | Q;
+
+ Empty EmptyVal;
+ int emptytest = EmptyVal | B;
+
+ int a = 1, b = 5;
+ int c = a + b;
+ int d = c | H, e = b * a;
+ a = B | C;
+ b = X | Z;
+
+ if (Tuesday != Monday + 1 ||
+ Friday - Thursday != 1 ||
+ Sunday + Wednesday == (Sunday | Wednesday))
+ return 1;
+ if (H + I + L == 42)
+ return 1;
+ return 42;
+}
+
+namespace PR34400 {
+enum { E1 = 0 };
+enum { E2 = -1 };
+enum { l = E1 | E2 };
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-memset-usage.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-memset-usage.cpp
new file mode 100644
index 0000000..f33ae5a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-memset-usage.cpp
@@ -0,0 +1,77 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-memset-usage %t
+
+void *memset(void *, int, __SIZE_TYPE__);
+
+namespace std {
+ using ::memset;
+}
+
+template <typename T>
+void mtempl(int *ptr) {
+ memset(ptr, '0', sizeof(T));
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: memset fill value is char '0', potentially mistaken for int 0 [bugprone-suspicious-memset-usage]
+// CHECK-FIXES: memset(ptr, 0, sizeof(T));
+ memset(ptr, 256, sizeof(T));
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: memset fill value is out of unsigned character range, gets truncated [bugprone-suspicious-memset-usage]
+ memset(0, sizeof(T), 0);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
+// CHECK-FIXES: memset(0, 0, sizeof(T));
+ memset(0, sizeof(int), 0);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
+// CHECK-FIXES: memset(0, 0, sizeof(int));
+}
+
+void foo(int xsize, int ysize) {
+ int i[5] = {1, 2, 3, 4, 5};
+ char ca[3] = {'a', 'b', 'c'};
+ int *p = i;
+ int l = 5;
+ char z = '1';
+ char *c = &z;
+ int v = 0;
+
+ memset(p, '0', l);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: memset fill value is char '0', potentially mistaken for int 0 [bugprone-suspicious-memset-usage]
+// CHECK-FIXES: memset(p, 0, l);
+
+ memset(p, 0xabcd, l);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: memset fill value is out of unsigned character range, gets truncated [bugprone-suspicious-memset-usage]
+
+ memset(p, sizeof(int), 0);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
+// CHECK-FIXES: memset(p, 0, sizeof(int));
+ std::memset(p, sizeof(int), 0x00);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
+// CHECK-FIXES: std::memset(p, 0x00, sizeof(int));
+
+#define M_CHAR_ZERO memset(p, '0', l);
+ M_CHAR_ZERO
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset fill value is char '0', potentially mistaken for int 0 [bugprone-suspicious-memset-usage]
+
+#define M_OUTSIDE_RANGE memset(p, 0xabcd, l);
+ M_OUTSIDE_RANGE
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset fill value is out of unsigned character range, gets truncated [bugprone-suspicious-memset-usage]
+
+#define M_ZERO_LENGTH memset(p, sizeof(int), 0);
+ M_ZERO_LENGTH
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
+
+ memset(p, '2', l);
+ memset(p, 0, l);
+ memset(c, '0', 1);
+ memset(ca, '0', sizeof(ca));
+
+ memset(p, 0x00, l);
+ mtempl<int>(p);
+
+ memset(p, sizeof(int), v + 1);
+ memset(p, 0xcd, 1);
+
+ // Don't warn when the fill char and the length are both known to be
+ // zero. No bug is possible.
+ memset(p, 0, v);
+
+ // -1 is clearly not a length by virtue of being negative, so no warning
+ // despite v == 0.
+ memset(p, -1, v);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-missing-comma.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-missing-comma.cpp
new file mode 100644
index 0000000..f039310
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-missing-comma.cpp
@@ -0,0 +1,82 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-missing-comma %t
+
+const char* Cartoons[] = {
+ "Bugs Bunny",
+ "Homer Simpson",
+ "Mickey Mouse",
+ "Bart Simpson",
+ "Charlie Brown" // There is a missing comma here.
+ "Fred Flintstone",
+ "Popeye",
+};
+// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: suspicious string literal, probably missing a comma [bugprone-suspicious-missing-comma]
+
+const wchar_t* Colors[] = {
+ L"Red", L"Yellow", L"Blue", L"Green", L"Purple", L"Rose", L"White", L"Black"
+};
+
+// The following array should not trigger any warnings. There is more than 5
+// elements, but they are all concatenated string literals.
+const char* HttpCommands[] = {
+ "GET / HTTP/1.0\r\n"
+ "\r\n",
+
+ "GET /index.html HTTP/1.0\r\n"
+ "\r\n",
+
+ "GET /favicon.ico HTTP/1.0\r\n"
+ "header: dummy"
+ "\r\n",
+
+ "GET /index.html-en HTTP/1.0\r\n"
+ "\r\n",
+
+ "GET /index.html-fr HTTP/1.0\r\n"
+ "\r\n",
+
+ "GET /index.html-es HTTP/1.0\r\n"
+ "\r\n",
+};
+
+// This array is too small to trigger a warning.
+const char* SmallArray[] = {
+ "a" "b", "c"
+};
+
+// Parentheses should be enough to avoid warnings.
+const char* ParentheseArray[] = {
+ ("a" "b"), "c",
+ ("d"
+ "e"
+ "f"),
+ "g", "h", "i", "j", "k", "l"
+};
+
+// Indentation should be enough to avoid warnings.
+const char* CorrectlyIndentedArray[] = {
+ "This is a long message "
+ "which is spanning over multiple lines."
+ "And this should be fine.",
+ "a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j", "k", "l"
+};
+
+const char* IncorrectlyIndentedArray[] = {
+ "This is a long message "
+ "which is spanning over multiple lines."
+ "And this should be fine.",
+ "a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j", "k", "l"
+};
+// CHECK-MESSAGES: :[[@LINE-6]]:3: warning: suspicious string literal, probably missing a comma [bugprone-suspicious-missing-comma]
+
+const char* TooManyConcatenatedTokensArray[] = {
+ "Dummy line",
+ "Dummy line",
+ "a" "b" "c" "d" "e" "f",
+ "g" "h" "i" "j" "k" "l",
+ "Dummy line",
+ "Dummy line",
+ "Dummy line",
+ "Dummy line",
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-semicolon-fail.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-semicolon-fail.cpp
new file mode 100644
index 0000000..45fa226
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-semicolon-fail.cpp
@@ -0,0 +1,28 @@
+// RUN: not clang-tidy %s \
+// RUN: -checks="-*,bugprone-suspicious-semicolon" -- -DERROR 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-ERROR \
+// RUN: -implicit-check-not="{{warning|error}}:"
+// RUN: not clang-tidy %s \
+// RUN: -checks="-*,bugprone-suspicious-semicolon,clang-diagnostic*" \
+// RUN: -- -DWERROR -Wno-everything -Werror=unused-variable 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-WERROR \
+// RUN: -implicit-check-not="{{warning|error}}:"
+
+// Note: This test verifies that, the checker does not emit any warning for
+// files that do not compile.
+
+bool g();
+
+void f() {
+ if (g());
+ // CHECK-WERROR: :[[@LINE-1]]:11: warning: potentially unintended semicolon [bugprone-suspicious-semicolon]
+#if ERROR
+ int a
+ // CHECK-ERROR: :[[@LINE-1]]:8: error: expected ';' at end of declaration [clang-diagnostic-error]
+#elif WERROR
+ int a;
+ // CHECK-WERROR: :[[@LINE-1]]:7: error: unused variable 'a' [clang-diagnostic-unused-variable]
+#else
+#error "One of ERROR or WERROR should be defined.
+#endif
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-semicolon.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-semicolon.cpp
new file mode 100644
index 0000000..4f9f4c5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-semicolon.cpp
@@ -0,0 +1,117 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-semicolon %t
+
+int x = 5;
+
+void nop();
+
+void correct1()
+{
+ if(x < 5) nop();
+}
+
+void correct2()
+{
+ if(x == 5)
+ nop();
+}
+
+void correct3()
+{
+ if(x > 5)
+ {
+ nop();
+ }
+}
+
+void fail1()
+{
+ if(x > 5); nop();
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: potentially unintended semicolon [bugprone-suspicious-semicolon]
+ // CHECK-FIXES: if(x > 5) nop();
+}
+
+void fail2()
+{
+ if(x == 5);
+ nop();
+ // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: potentially unintended semicolon [bugprone-suspicious-semicolon]
+ // CHECK-FIXES: if(x == 5){{$}}
+}
+
+void fail3()
+{
+ if(x < 5);
+ {
+ nop();
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:11: warning: potentially unintended semicolon
+ // CHECK-FIXES: if(x < 5){{$}}
+}
+
+void correct4()
+{
+ while(x % 5 == 1);
+ nop();
+}
+
+void correct5()
+{
+ for(int i = 0; i < x; ++i)
+ ;
+}
+
+void fail4()
+{
+ for(int i = 0; i < x; ++i);
+ nop();
+ // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: potentially unintended semicolon
+ // CHECK-FIXES: for(int i = 0; i < x; ++i){{$}}
+}
+
+void fail5()
+{
+ if(x % 5 == 1);
+ nop();
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: potentially unintended semicolon
+ // CHECK-FIXES: if(x % 5 == 1){{$}}
+}
+
+void fail6() {
+ int a = 0;
+ if (a != 0) {
+ } else if (a != 1);
+ a = 2;
+ // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: potentially unintended semicolon
+ // CHECK-FIXES: } else if (a != 1){{$}}
+}
+
+void fail7() {
+ if (true)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: potentially unintended semicolon
+}
+
+void correct6()
+{
+ do; while(false);
+}
+
+int correct7()
+{
+ int t_num = 0;
+ char c = 'b';
+ char *s = "a";
+ if (s == "(" || s != "'" || c == '"') {
+ t_num += 3;
+ return (c == ')' && c == '\'');
+ }
+
+ return 0;
+}
+
+void correct8() {
+ if (true)
+ ;
+ else {
+ }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-string-compare.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-string-compare.c
new file mode 100644
index 0000000..3b3175a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-string-compare.c
@@ -0,0 +1,79 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-string-compare %t -- \
+// RUN: -config='{CheckOptions: \
+// RUN: [{key: bugprone-suspicious-string-compare.WarnOnImplicitComparison, value: 1}, \
+// RUN: {key: bugprone-suspicious-string-compare.WarnOnLogicalNotComparison, value: 1}]}' \
+// RUN: -- -std=c99
+
+static const char A[] = "abc";
+
+int strcmp(const char *, const char *);
+
+int test_warning_patterns() {
+ if (strcmp(A, "a"))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result [bugprone-suspicious-string-compare]
+ // CHECK-FIXES: if (strcmp(A, "a") != 0)
+
+ if (strcmp(A, "a") != 0 ||
+ strcmp(A, "b"))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result
+ // CHECK-FIXES: strcmp(A, "b") != 0)
+
+ if (strcmp(A, "a") == 1)
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
+
+ if (strcmp(A, "a") == -1)
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
+
+ if (strcmp(A, "a") < '0')
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
+
+ if (strcmp(A, "a") < 0.)
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' has suspicious implicit cast
+
+ if (!strcmp(A, "a"))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:8: warning: function 'strcmp' is compared using logical not operator
+ // CHECK-FIXES: if (strcmp(A, "a") == 0)
+}
+
+void test_structure_patterns() {
+ if (strcmp(A, "a")) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: function 'strcmp' is called without explicitly comparing result
+ // CHECK-FIXES: if (strcmp(A, "a") != 0) {}
+
+ while (strcmp(A, "a")) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: function 'strcmp' is called without explicitly comparing result
+ // CHECK-FIXES: while (strcmp(A, "a") != 0) {}
+
+ for (;strcmp(A, "a");) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: function 'strcmp' is called without explicitly comparing result
+ // CHECK-FIXES: for (;strcmp(A, "a") != 0;) {}
+}
+
+int test_valid_patterns() {
+ // The following cases are valid.
+ if (strcmp(A, "a") < 0) return 0;
+ if (strcmp(A, "a") == 0) return 0;
+ if (strcmp(A, "a") <= 0) return 0;
+ if (strcmp(A, "a") == strcmp(A, "b")) return 0;
+ return 1;
+}
+
+int wrapper(const char* a, const char* b) {
+ return strcmp(a, b);
+}
+
+int assignment_wrapper(const char* a, const char* b) {
+ int cmp = strcmp(a, b);
+ return cmp;
+}
+
+int condexpr_wrapper(const char* a, const char* b) {
+ return (a < b) ? strcmp(a, b) : strcmp(b, a);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-string-compare.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-string-compare.cpp
new file mode 100644
index 0000000..c1c24ff
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-string-compare.cpp
@@ -0,0 +1,337 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-string-compare %t -- \
+// RUN: -config='{CheckOptions: \
+// RUN: [{key: bugprone-suspicious-string-compare.WarnOnImplicitComparison, value: 1}, \
+// RUN: {key: bugprone-suspicious-string-compare.WarnOnLogicalNotComparison, value: 1}]}' \
+// RUN: --
+
+typedef __SIZE_TYPE__ size;
+
+struct locale_t {
+ void* dummy;
+} locale;
+
+static const char A[] = "abc";
+static const unsigned char U[] = "abc";
+static const unsigned char V[] = "xyz";
+static const wchar_t W[] = L"abc";
+
+int strlen(const char *);
+
+int memcmp(const void *, const void *, size);
+int wmemcmp(const wchar_t *, const wchar_t *, size);
+int memicmp(const void *, const void *, size);
+int _memicmp(const void *, const void *, size);
+int _memicmp_l(const void *, const void *, size, locale_t);
+
+int strcmp(const char *, const char *);
+int strncmp(const char *, const char *, size);
+int strcasecmp(const char *, const char *);
+int strncasecmp(const char *, const char *, size);
+int stricmp(const char *, const char *);
+int strcmpi(const char *, const char *);
+int strnicmp(const char *, const char *, size);
+int _stricmp(const char *, const char * );
+int _strnicmp(const char *, const char *, size);
+int _stricmp_l(const char *, const char *, locale_t);
+int _strnicmp_l(const char *, const char *, size, locale_t);
+
+int wcscmp(const wchar_t *, const wchar_t *);
+int wcsncmp(const wchar_t *, const wchar_t *, size);
+int wcscasecmp(const wchar_t *, const wchar_t *);
+int wcsicmp(const wchar_t *, const wchar_t *);
+int wcsnicmp(const wchar_t *, const wchar_t *, size);
+int _wcsicmp(const wchar_t *, const wchar_t *);
+int _wcsnicmp(const wchar_t *, const wchar_t *, size);
+int _wcsicmp_l(const wchar_t *, const wchar_t *, locale_t);
+int _wcsnicmp_l(const wchar_t *, const wchar_t *, size, locale_t);
+
+int _mbscmp(const unsigned char *, const unsigned char *);
+int _mbsncmp(const unsigned char *, const unsigned char *, size);
+int _mbsnbcmp(const unsigned char *, const unsigned char *, size);
+int _mbsnbicmp(const unsigned char *, const unsigned char *, size);
+int _mbsicmp(const unsigned char *, const unsigned char *);
+int _mbsnicmp(const unsigned char *, const unsigned char *, size);
+int _mbscmp_l(const unsigned char *, const unsigned char *, locale_t);
+int _mbsncmp_l(const unsigned char *, const unsigned char *, size, locale_t);
+int _mbsicmp_l(const unsigned char *, const unsigned char *, locale_t);
+int _mbsnicmp_l(const unsigned char *, const unsigned char *, size, locale_t);
+int _mbsnbcmp_l(const unsigned char *, const unsigned char *, size, locale_t);
+int _mbsnbicmp_l(const unsigned char *, const unsigned char *, size, locale_t);
+
+int test_warning_patterns() {
+ if (strcmp(A, "a"))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result [bugprone-suspicious-string-compare]
+ // CHECK-FIXES: if (strcmp(A, "a") != 0)
+
+ if (strcmp(A, "a") == 0 ||
+ strcmp(A, "b"))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result
+ // CHECK-FIXES: strcmp(A, "b") != 0)
+
+ if (strcmp(A, "a") == 1)
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
+
+ if (strcmp(A, "a") == -1)
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
+
+ if (strcmp(A, "a") == true)
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
+
+ if (strcmp(A, "a") < '0')
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
+
+ if (strcmp(A, "a") < 0.)
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' has suspicious implicit cast
+}
+
+int test_valid_patterns() {
+ // The following cases are valid.
+ if (strcmp(A, "a") < 0)
+ return 0;
+ if (strcmp(A, "a") == 0)
+ return 0;
+ if (strcmp(A, "a") <= 0)
+ return 0;
+
+ if (wcscmp(W, L"a") < 0)
+ return 0;
+ if (wcscmp(W, L"a") == 0)
+ return 0;
+ if (wcscmp(W, L"a") <= 0)
+ return 0;
+
+ return 1;
+}
+
+int test_implicit_compare_with_functions() {
+
+ if (memcmp(A, "a", 1))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'memcmp' is called without explicitly comparing result
+ // CHECK-FIXES: memcmp(A, "a", 1) != 0)
+
+ if (wmemcmp(W, L"a", 1))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wmemcmp' is called without explicitly comparing result
+ // CHECK-FIXES: wmemcmp(W, L"a", 1) != 0)
+
+ if (memicmp(A, "a", 1))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'memicmp' is called without explicitly comparing result
+ // CHECK-FIXES: memicmp(A, "a", 1) != 0)
+
+ if (_memicmp(A, "a", 1))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_memicmp' is called without explicitly comparing result
+ // CHECK-FIXES: _memicmp(A, "a", 1) != 0)
+
+ if (_memicmp_l(A, "a", 1, locale))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_memicmp_l' is called without explicitly comparing result
+ // CHECK-FIXES: _memicmp_l(A, "a", 1, locale) != 0)
+
+ if (strcmp(A, "a"))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result
+ // CHECK-FIXES: strcmp(A, "a") != 0)
+
+ if (strncmp(A, "a", 1))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strncmp' is called without explicitly comparing result
+ // CHECK-FIXES: strncmp(A, "a", 1) != 0)
+
+ if (strcasecmp(A, "a"))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcasecmp' is called without explicitly comparing result
+ // CHECK-FIXES: strcasecmp(A, "a") != 0)
+
+ if (strncasecmp(A, "a", 1))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strncasecmp' is called without explicitly comparing result
+ // CHECK-FIXES: strncasecmp(A, "a", 1) != 0)
+
+ if (stricmp(A, "a"))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'stricmp' is called without explicitly comparing result
+ // CHECK-FIXES: stricmp(A, "a") != 0)
+
+ if (strcmpi(A, "a"))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmpi' is called without explicitly comparing result
+ // CHECK-FIXES: strcmpi(A, "a") != 0)
+
+ if (_stricmp(A, "a"))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_stricmp' is called without explicitly comparing result
+ // CHECK-FIXES: _stricmp(A, "a") != 0)
+
+ if (strnicmp(A, "a", 1))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strnicmp' is called without explicitly comparing result
+ // CHECK-FIXES: strnicmp(A, "a", 1) != 0)
+
+ if (_strnicmp(A, "a", 1))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_strnicmp' is called without explicitly comparing result
+ // CHECK-FIXES: _strnicmp(A, "a", 1) != 0)
+
+ if (_stricmp_l(A, "a", locale))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_stricmp_l' is called without explicitly comparing result
+ // CHECK-FIXES: _stricmp_l(A, "a", locale) != 0)
+
+ if (_strnicmp_l(A, "a", 1, locale))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_strnicmp_l' is called without explicitly comparing result
+ // CHECK-FIXES: _strnicmp_l(A, "a", 1, locale) != 0)
+
+ if (wcscmp(W, L"a"))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcscmp' is called without explicitly comparing result
+ // CHECK-FIXES: wcscmp(W, L"a") != 0)
+
+ if (wcsncmp(W, L"a", 1))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcsncmp' is called without explicitly comparing result
+ // CHECK-FIXES: wcsncmp(W, L"a", 1) != 0)
+
+ if (wcscasecmp(W, L"a"))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcscasecmp' is called without explicitly comparing result
+ // CHECK-FIXES: wcscasecmp(W, L"a") != 0)
+
+ if (wcsicmp(W, L"a"))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcsicmp' is called without explicitly comparing result
+ // CHECK-FIXES: wcsicmp(W, L"a") != 0)
+
+ if (_wcsicmp(W, L"a"))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsicmp' is called without explicitly comparing result
+ // CHECK-FIXES: _wcsicmp(W, L"a") != 0)
+
+ if (_wcsicmp_l(W, L"a", locale))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsicmp_l' is called without explicitly comparing result
+ // CHECK-FIXES: _wcsicmp_l(W, L"a", locale) != 0)
+
+ if (wcsnicmp(W, L"a", 1))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcsnicmp' is called without explicitly comparing result
+ // CHECK-FIXES: wcsnicmp(W, L"a", 1) != 0)
+
+ if (_wcsnicmp(W, L"a", 1))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsnicmp' is called without explicitly comparing result
+ // CHECK-FIXES: _wcsnicmp(W, L"a", 1) != 0)
+
+ if (_wcsnicmp_l(W, L"a", 1, locale))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsnicmp_l' is called without explicitly comparing result
+ // CHECK-FIXES: _wcsnicmp_l(W, L"a", 1, locale) != 0)
+
+ if (_mbscmp(U, V))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbscmp' is called without explicitly comparing result
+ // CHECK-FIXES: _mbscmp(U, V) != 0)
+
+ if (_mbsncmp(U, V, 1))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsncmp' is called without explicitly comparing result
+ // CHECK-FIXES: _mbsncmp(U, V, 1) != 0)
+
+ if (_mbsnbcmp(U, V, 1))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbcmp' is called without explicitly comparing result
+ // CHECK-FIXES: _mbsnbcmp(U, V, 1) != 0)
+
+ if (_mbsnbicmp(U, V, 1))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbicmp' is called without explicitly comparing result
+ // CHECK-FIXES: _mbsnbicmp(U, V, 1) != 0)
+
+ if (_mbsicmp(U, V))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsicmp' is called without explicitly comparing result
+ // CHECK-FIXES: _mbsicmp(U, V) != 0)
+
+ if (_mbsnicmp(U, V, 1))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnicmp' is called without explicitly comparing result
+ // CHECK-FIXES: _mbsnicmp(U, V, 1) != 0)
+
+ if (_mbscmp_l(U, V, locale))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbscmp_l' is called without explicitly comparing result
+ // CHECK-FIXES: _mbscmp_l(U, V, locale) != 0)
+
+ if (_mbsncmp_l(U, V, 1, locale))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsncmp_l' is called without explicitly comparing result
+ // CHECK-FIXES: _mbsncmp_l(U, V, 1, locale) != 0)
+
+ if (_mbsicmp_l(U, V, locale))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsicmp_l' is called without explicitly comparing result
+ // CHECK-FIXES: _mbsicmp_l(U, V, locale) != 0)
+
+ if (_mbsnicmp_l(U, V, 1, locale))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnicmp_l' is called without explicitly comparing result
+ // CHECK-FIXES: _mbsnicmp_l(U, V, 1, locale) != 0)
+
+ if (_mbsnbcmp_l(U, V, 1, locale))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbcmp_l' is called without explicitly comparing result
+ // CHECK-FIXES: _mbsnbcmp_l(U, V, 1, locale) != 0)
+
+ if (_mbsnbicmp_l(U, V, 1, locale))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbicmp_l' is called without explicitly comparing result
+ // CHECK-FIXES: _mbsnbicmp_l(U, V, 1, locale) != 0)
+
+ return 1;
+}
+
+int strcmp_wrapper1(const char* a, const char* b) {
+ return strcmp(a, b);
+}
+
+int strcmp_wrapper2(const char* a, const char* b) {
+ return (a && b) ? strcmp(a, b) : 0;
+}
+
+#define macro_strncmp(s1, s2, n) \
+ (__extension__ (__builtin_constant_p (n) \
+ && ((__builtin_constant_p (s1) \
+ && strlen (s1) < ((size) (n))) \
+ || (__builtin_constant_p (s2) \
+ && strlen (s2) < ((size) (n)))) \
+ ? strcmp (s1, s2) : strncmp (s1, s2, n)))
+
+int strncmp_macro(const char* a, const char* b) {
+ if (macro_strncmp(a, b, 4))
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result
+
+ if (macro_strncmp(a, b, 4) == 2)
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
+
+ if (macro_strncmp(a, b, 4) <= .0)
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' has suspicious implicit cast
+
+ if (macro_strncmp(a, b, 4) + 0)
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: results of function 'strcmp' used by operator '+'
+
+ return 1;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-swapped-arguments.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-swapped-arguments.cpp
new file mode 100644
index 0000000..06fb2d8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-swapped-arguments.cpp
@@ -0,0 +1,53 @@
+// RUN: %check_clang_tidy %s bugprone-swapped-arguments %t
+
+void F(int, double);
+
+int SomeFunction();
+
+template <typename T, typename U>
+void G(T a, U b) {
+ F(a, b); // no-warning
+ F(2.0, 4);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: argument with implicit conversion from 'int' to 'double' followed by argument converted from 'double' to 'int', potentially swapped arguments.
+// CHECK-FIXES: F(4, 2.0)
+}
+
+void foo() {
+ F(1.0, 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: argument with implicit conversion from 'int' to 'double' followed by argument converted from 'double' to 'int', potentially swapped arguments.
+// CHECK-FIXES: F(3, 1.0)
+
+#define M(x, y) x##y()
+
+ double b = 1.0;
+ F(b, M(Some, Function));
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: argument with implicit conversion from 'int' to 'double' followed by argument converted from 'double' to 'int', potentially swapped arguments.
+// CHECK-FIXES: F(M(Some, Function), b);
+
+#define N F(b, SomeFunction())
+
+ N;
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: argument with implicit conversion from 'int' to 'double' followed by argument converted from 'double' to 'int', potentially swapped arguments.
+// In macro, don't emit fixits.
+// CHECK-FIXES: #define N F(b, SomeFunction())
+
+ G(b, 3);
+ G(3, 1.0);
+ G(0, 0);
+
+ F(1.0, 1.0); // no-warning
+ F(3, 1.0); // no-warning
+ F(true, false); // no-warning
+ F(0, 'c'); // no-warning
+
+#define APPLY(f, x, y) f(x, y)
+ APPLY(F, 1.0, 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: argument with implicit conversion from 'int' to 'double' followed by argument converted from 'double' to 'int', potentially swapped arguments.
+// CHECK-FIXES: APPLY(F, 3, 1.0);
+
+#define PARAMS 1.0, 3
+#define CALL(P) F(P)
+ CALL(PARAMS);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: argument with implicit conversion from 'int' to 'double' followed by argument converted from 'double' to 'int', potentially swapped arguments.
+// In macro, don't emit fixits.
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-terminating-continue.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-terminating-continue.cpp
new file mode 100644
index 0000000..4bdcbc4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-terminating-continue.cpp
@@ -0,0 +1,65 @@
+// RUN: %check_clang_tidy %s bugprone-terminating-continue %t
+
+void f() {
+ do {
+ continue;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'continue' in loop with false condition is equivalent to 'break' [bugprone-terminating-continue]
+ // CHECK-FIXES: break;
+ } while(false);
+
+ do {
+ continue;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'continue' in loop with false condition is equivalent to 'break' [bugprone-terminating-continue]
+ // CHECK-FIXES: break;
+ } while(0);
+
+ do {
+ continue;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'continue' in loop with false condition is equivalent to 'break' [bugprone-terminating-continue]
+ // CHECK-FIXES: break;
+ } while(nullptr);
+
+ do {
+ continue;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'continue' in loop with false condition is equivalent to 'break' [bugprone-terminating-continue]
+ // CHECK-FIXES: break;
+ } while(__null);
+
+
+ do {
+ int x = 1;
+ if (x > 0) continue;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'continue' in loop with false condition is equivalent to 'break' [bugprone-terminating-continue]
+ // CHECK-FIXES: if (x > 0) break;
+ } while (false);
+}
+
+void g() {
+ do {
+ do {
+ continue;
+ int x = 1;
+ } while (1 == 1);
+ } while (false);
+
+ do {
+ for (int i = 0; i < 1; ++i) {
+ continue;
+ int x = 1;
+ }
+ } while (false);
+
+ do {
+ while (true) {
+ continue;
+ int x = 1;
+ }
+ } while (false);
+
+ int v[] = {1,2,3,34};
+ do {
+ for (int n : v) {
+ if (n>2) continue;
+ }
+ } while (false);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-throw-keyword-missing.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-throw-keyword-missing.cpp
new file mode 100644
index 0000000..93ecf06
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-throw-keyword-missing.cpp
@@ -0,0 +1,167 @@
+// RUN: %check_clang_tidy %s bugprone-throw-keyword-missing %t -- -- -fexceptions
+
+namespace std {
+
+// std::string declaration (taken from test/clang-tidy/readability-redundant-string-cstr-msvc.cpp).
+template <typename T>
+class allocator {};
+template <typename T>
+class char_traits {};
+template <typename C, typename T = std::char_traits<C>, typename A = std::allocator<C>>
+struct basic_string {
+ basic_string();
+ basic_string(const basic_string &);
+ // MSVC headers define two constructors instead of using optional arguments.
+ basic_string(const C *);
+ basic_string(const C *, const A &);
+ ~basic_string();
+};
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+
+// std::exception and std::runtime_error declaration.
+struct exception {
+ exception();
+ exception(const exception &other);
+ virtual ~exception();
+};
+
+struct runtime_error : public exception {
+ explicit runtime_error(const std::string &what_arg);
+};
+
+} // namespace std
+
+// The usage of this class should never emit a warning.
+struct RegularClass {};
+
+// Class name contains the substring "exception", in certain cases using this class should emit a warning.
+struct RegularException {
+ RegularException() {}
+
+ // Constructors with a single argument are treated differently (cxxFunctionalCastExpr).
+ RegularException(int) {}
+};
+
+// --------------
+
+void stdExceptionNotTrownTest(int i) {
+ if (i < 0)
+ // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception object created but not thrown; did you mean 'throw {{.*}}'? [bugprone-throw-keyword-missing]
+ std::exception();
+
+ if (i > 0)
+ // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
+ std::runtime_error("Unexpected argument");
+}
+
+void stdExceptionThrownTest(int i) {
+ if (i < 0)
+ throw std::exception();
+
+ if (i > 0)
+ throw std::runtime_error("Unexpected argument");
+}
+
+void regularClassNotThrownTest(int i) {
+ if (i < 0)
+ RegularClass();
+}
+
+void regularClassThrownTest(int i) {
+ if (i < 0)
+ throw RegularClass();
+}
+
+void nameContainsExceptionNotThrownTest(int i) {
+ if (i < 0)
+ // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
+ RegularException();
+
+ if (i > 0)
+ // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
+ RegularException(5);
+}
+
+void nameContainsExceptionThrownTest(int i) {
+ if (i < 0)
+ throw RegularException();
+
+ if (i > 0)
+ throw RegularException(5);
+}
+
+template <class Exception>
+void f(int i, Exception excToBeThrown) {}
+
+void funcCallWithTempExcTest() {
+ f(5, RegularException());
+}
+
+// Global variable initilization test.
+RegularException exc = RegularException();
+RegularException *excptr = new RegularException();
+
+void localVariableInitTest() {
+ RegularException exc = RegularException();
+ RegularException *excptr = new RegularException();
+}
+
+class CtorInitializerListTest {
+ RegularException exc;
+
+ CtorInitializerListTest() : exc(RegularException()) {}
+
+ CtorInitializerListTest(int) try : exc(RegularException()) {
+ // Constructor body
+ } catch (...) {
+ // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
+ RegularException();
+ }
+
+ CtorInitializerListTest(float);
+};
+
+CtorInitializerListTest::CtorInitializerListTest(float) try : exc(RegularException()) {
+ // Constructor body
+} catch (...) {
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception
+ RegularException();
+}
+
+RegularException funcReturningExceptionTest(int i) {
+ return RegularException();
+}
+
+void returnedValueTest() {
+ funcReturningExceptionTest(3);
+}
+
+struct ClassBracedInitListTest {
+ ClassBracedInitListTest(RegularException exc) {}
+};
+
+void foo(RegularException, ClassBracedInitListTest) {}
+
+void bracedInitListTest() {
+ RegularException exc{};
+ ClassBracedInitListTest test = {RegularException()};
+ foo({}, {RegularException()});
+}
+
+typedef std::exception ERROR_BASE;
+class RegularError : public ERROR_BASE {};
+
+void typedefTest() {
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception
+ RegularError();
+}
+
+struct ExceptionRAII {
+ ExceptionRAII() {}
+ ~ExceptionRAII() {}
+};
+
+void exceptionRAIITest() {
+ ExceptionRAII E;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-undefined-memory-manipulation.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-undefined-memory-manipulation.cpp
new file mode 100644
index 0000000..8055010
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-undefined-memory-manipulation.cpp
@@ -0,0 +1,213 @@
+// RUN: %check_clang_tidy %s bugprone-undefined-memory-manipulation %t
+
+void *memset(void *, int, __SIZE_TYPE__);
+void *memcpy(void *, const void *, __SIZE_TYPE__);
+void *memmove(void *, const void *, __SIZE_TYPE__);
+
+namespace std {
+using ::memcpy;
+using ::memmove;
+using ::memset;
+}
+
+namespace types {
+// TriviallyCopyable types:
+struct Plain {
+ int n;
+};
+
+enum E {
+ X,
+ Y,
+ Z
+};
+
+struct Base {
+ float b;
+};
+
+struct Derived : Base {
+ bool d;
+};
+
+// not TriviallyCopyable types:
+struct Destruct {
+ ~Destruct() {}
+};
+
+struct Copy {
+ Copy() {}
+ Copy(const Copy &) {}
+};
+
+struct Move {
+ Move() {}
+ Move(Move &&) {}
+};
+
+struct VirtualFunc {
+ virtual void f() {}
+};
+
+struct VirtualBase : virtual Base {
+ int vb;
+};
+
+// Incomplete type, assume it is TriviallyCopyable.
+struct NoDef;
+
+} // end namespace types
+
+void f(types::NoDef *s) {
+ memset(s, 0, 5);
+}
+
+template <typename T>
+void memset_temp(T *b) {
+ memset(b, 0, sizeof(T));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc' is not TriviallyCopyable [bugprone-undefined-memory-manipulation]
+}
+
+template <typename S, typename T>
+void memcpy_temp(S *a, T *b) {
+ memcpy(a, b, sizeof(T));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualFunc'
+}
+
+template <typename S, typename T>
+void memmove_temp(S *a, T *b) {
+ memmove(a, b, sizeof(T));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualFunc'
+}
+
+namespace aliases {
+using Copy2 = types::Copy;
+typedef types::Move Move2;
+}
+
+void notTriviallyCopyable() {
+ types::Plain p; // TriviallyCopyable for variety
+ types::Destruct d;
+ types::Copy c;
+ types::Move m;
+ types::VirtualFunc vf;
+ types::VirtualBase vb;
+
+ memset(&vf, 0, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc'
+ memset(&d, 0, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Destruct'
+ memset(&c, 0, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Copy'
+ std::memset(&m, 0, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Move'
+ ::memset(&vb, 0, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualBase'
+
+ memcpy(&p, &vf, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualFunc'
+ memcpy(&p, &d, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Destruct'
+ memcpy(&c, &p, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Copy'
+ std::memcpy(&m, &p, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Move'
+ ::memcpy(&vb, &p, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualBase'
+
+ memmove(&vf, &p, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc'
+ memmove(&d, &p, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Destruct'
+ memmove(&p, &c, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Copy'
+ std::memmove(&p, &m, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Move'
+ ::memmove(&p, &vb, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualBase'
+
+#define MEMSET memset(&vf, 0, sizeof(int));
+ MEMSET
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc'
+#define MEMCPY memcpy(&d, &p, sizeof(int));
+ MEMCPY
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Destruct'
+#define MEMMOVE memmove(&p, &c, sizeof(int));
+ MEMMOVE
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Copy'
+
+ memset_temp<types::VirtualFunc>(&vf);
+ memcpy_temp<types::Plain, types::VirtualFunc>(&p, &vf);
+ memmove_temp<types::Plain, types::VirtualFunc>(&p, &vf);
+
+ aliases::Copy2 c2;
+ aliases::Move2 m2;
+ memset(&c2, 0, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'aliases::Copy2'
+ memset(&m2, 0, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'aliases::Move2'
+
+ typedef aliases::Copy2 Copy3;
+ typedef aliases::Copy2 *PCopy2;
+ typedef Copy3 *PCopy3;
+ Copy3 c3;
+ PCopy2 pc2;
+ PCopy3 pc3;
+ memset(&c3, 0, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'Copy3'
+ memset(pc2, 0, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'aliases::Copy2'
+ memset(pc3, 0, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'Copy3'
+}
+
+void triviallyCopyable() {
+ types::Plain p;
+ types::Base base;
+ types::Derived derived;
+
+ int i = 5;
+ int ia[3] = {1, 2, 3};
+ float f = 3.14;
+ float fa[3] = {1.1, 2.2, 3.3};
+ bool b = false;
+ bool ba[2] = {true, false};
+ types::E e = types::X;
+ p.n = 2;
+
+ memset(&p, 0, sizeof(int));
+ memset(&base, 0, sizeof(float));
+ memset(&derived, 0, sizeof(bool));
+ memset(&i, 0, sizeof(int));
+ memset(ia, 0, sizeof(int));
+ memset(&f, 0, sizeof(float));
+ memset(fa, 0, sizeof(float));
+ memset(&b, 0, sizeof(bool));
+ memset(ba, 0, sizeof(bool));
+ memset(&e, 0, sizeof(int));
+ memset(&p.n, 0, sizeof(int));
+
+ memcpy(&p, &p, sizeof(int));
+ memcpy(&base, &base, sizeof(float));
+ memcpy(&derived, &derived, sizeof(bool));
+ memcpy(&i, &i, sizeof(int));
+ memcpy(ia, ia, sizeof(int));
+ memcpy(&f, &f, sizeof(float));
+ memcpy(fa, fa, sizeof(float));
+ memcpy(&b, &b, sizeof(bool));
+ memcpy(ba, ba, sizeof(bool));
+ memcpy(&e, &e, sizeof(int));
+ memcpy(&p.n, &p.n, sizeof(int));
+
+ memmove(&p, &p, sizeof(int));
+ memmove(&base, &base, sizeof(float));
+ memmove(&derived, &derived, sizeof(bool));
+ memmove(&i, &i, sizeof(int));
+ memmove(ia, ia, sizeof(int));
+ memmove(&f, &f, sizeof(float));
+ memmove(fa, fa, sizeof(float));
+ memmove(&b, &b, sizeof(bool));
+ memmove(ba, ba, sizeof(bool));
+ memmove(&e, &e, sizeof(int));
+ memmove(&p.n, &p.n, sizeof(int));
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-undelegated-constructor-cxx98.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-undelegated-constructor-cxx98.cpp
new file mode 100644
index 0000000..f859f24
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-undelegated-constructor-cxx98.cpp
@@ -0,0 +1,23 @@
+// RUN: clang-tidy %s -checks=-*,bugprone-undelegated-constructor -- -std=c++98 | count 0
+
+// Note: this test expects no diagnostics, but FileCheck cannot handle that,
+// hence the use of | count 0.
+
+struct Ctor;
+Ctor foo();
+
+struct Ctor {
+ Ctor();
+ Ctor(int);
+ Ctor(int, int);
+ Ctor(Ctor *i) {
+ Ctor();
+ Ctor(0);
+ Ctor(1, 2);
+ foo();
+ }
+};
+
+Ctor::Ctor() {
+ Ctor(1);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-undelegated-constructor.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-undelegated-constructor.cpp
new file mode 100644
index 0000000..09b20ac
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-undelegated-constructor.cpp
@@ -0,0 +1,54 @@
+// RUN: %check_clang_tidy %s bugprone-undelegated-constructor %t
+
+struct Ctor;
+Ctor foo();
+
+struct Ctor {
+ Ctor();
+ Ctor(int);
+ Ctor(int, int);
+ Ctor(Ctor *i) {
+ Ctor();
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: did you intend to call a delegated constructor? A temporary object is created here instead [bugprone-undelegated-constructor]
+ Ctor(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: did you intend to call a delegated constructor?
+ Ctor(1, 2);
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: did you intend to call a delegated constructor?
+ foo();
+ }
+};
+
+Ctor::Ctor() {
+ Ctor(1);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: did you intend to call a delegated constructor?
+}
+
+Ctor::Ctor(int i) : Ctor(i, 1) {} // properly delegated.
+
+struct Dtor {
+ Dtor();
+ Dtor(int);
+ Dtor(int, int);
+ Dtor(Ctor *i) {
+ Dtor();
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: did you intend to call a delegated constructor?
+ Dtor(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: did you intend to call a delegated constructor?
+ Dtor(1, 2);
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: did you intend to call a delegated constructor?
+ }
+ ~Dtor();
+};
+
+struct Base {};
+struct Derived : public Base {
+ Derived() { Base(); }
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: did you intend to call a delegated constructor?
+};
+
+template <typename T>
+struct TDerived : public Base {
+ TDerived() { Base(); }
+};
+
+TDerived<int> t;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-unused-raii.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-unused-raii.cpp
new file mode 100644
index 0000000..91ade52
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-unused-raii.cpp
@@ -0,0 +1,68 @@
+// RUN: %check_clang_tidy %s bugprone-unused-raii %t
+
+struct Foo {
+ Foo();
+ Foo(int);
+ Foo(int, int);
+ ~Foo();
+};
+
+struct Bar {
+ Bar();
+};
+
+struct FooBar {
+ FooBar();
+ Foo f;
+};
+
+template <typename T>
+void qux() {
+ T(42);
+}
+
+template <typename T>
+struct TFoo {
+ TFoo(T);
+ ~TFoo();
+};
+
+Foo f();
+
+struct Ctor {
+ Ctor(int);
+ Ctor() {
+ Ctor(0); // TODO: warn here.
+ }
+};
+
+void test() {
+ Foo(42);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: object destroyed immediately after creation; did you mean to name the object?
+// CHECK-FIXES: Foo give_me_a_name(42);
+ Foo(23, 42);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: object destroyed immediately after creation; did you mean to name the object?
+// CHECK-FIXES: Foo give_me_a_name(23, 42);
+ Foo();
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: object destroyed immediately after creation; did you mean to name the object?
+// CHECK-FIXES: Foo give_me_a_name;
+ TFoo<int>(23);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: object destroyed immediately after creation; did you mean to name the object?
+// CHECK-FIXES: TFoo<int> give_me_a_name(23);
+
+ FooBar();
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: object destroyed immediately after creation; did you mean to name the object?
+// CHECK-FIXES: FooBar give_me_a_name;
+
+ Bar();
+ f();
+ qux<Foo>();
+
+#define M Foo();
+ M
+
+ {
+ Foo();
+ }
+ Foo();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-unused-return-value-custom.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-unused-return-value-custom.cpp
new file mode 100644
index 0000000..efe3705
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-unused-return-value-custom.cpp
@@ -0,0 +1,100 @@
+// RUN: %check_clang_tidy %s bugprone-unused-return-value %t \
+// RUN: -config='{CheckOptions: \
+// RUN: [{key: bugprone-unused-return-value.CheckedFunctions, \
+// RUN: value: "::fun;::ns::Outer::Inner::memFun;::ns::Type::staticFun;::ns::ClassTemplate::memFun;::ns::ClassTemplate::staticFun"}]}' \
+// RUN: --
+
+namespace std {
+
+template <typename T>
+T *launder(T *);
+
+} // namespace std
+
+namespace ns {
+
+struct Outer {
+ struct Inner {
+ bool memFun();
+ };
+};
+
+using AliasName = Outer;
+
+struct Derived : public Outer::Inner {};
+
+struct Retval {
+ int *P;
+ Retval() { P = new int; }
+ ~Retval() { delete P; }
+};
+
+struct Type {
+ Retval memFun();
+ static Retval staticFun();
+};
+
+template <typename T>
+struct ClassTemplate {
+ Retval memFun();
+ static Retval staticFun();
+};
+
+} // namespace ns
+
+int fun();
+void fun(int);
+
+void warning() {
+ fun();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ (fun());
+ // CHECK-MESSAGES: [[@LINE-1]]:4: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ ns::Outer::Inner ObjA1;
+ ObjA1.memFun();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ ns::AliasName::Inner ObjA2;
+ ObjA2.memFun();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ ns::Derived ObjA3;
+ ObjA3.memFun();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ ns::Type::staticFun();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ ns::ClassTemplate<int> ObjA4;
+ ObjA4.memFun();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ ns::ClassTemplate<int>::staticFun();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+}
+
+void noWarning() {
+ auto R1 = fun();
+
+ ns::Outer::Inner ObjB1;
+ auto R2 = ObjB1.memFun();
+
+ auto R3 = ns::Type::staticFun();
+
+ ns::ClassTemplate<int> ObjB2;
+ auto R4 = ObjB2.memFun();
+
+ auto R5 = ns::ClassTemplate<int>::staticFun();
+
+ // test calling a void overload of a checked function
+ fun(5);
+
+ // test discarding return value of functions that are not configured to be checked
+ int I = 1;
+ std::launder(&I);
+
+ ns::Type ObjB3;
+ ObjB3.memFun();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-unused-return-value.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-unused-return-value.cpp
new file mode 100644
index 0000000..b4f280e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-unused-return-value.cpp
@@ -0,0 +1,215 @@
+// RUN: %check_clang_tidy %s bugprone-unused-return-value %t -- -- -fexceptions
+
+namespace std {
+
+struct future {};
+
+enum class launch {
+ async,
+ deferred
+};
+
+template <typename Function, typename... Args>
+future async(Function &&, Args &&...);
+
+template <typename Function, typename... Args>
+future async(launch, Function &&, Args &&...);
+
+template <typename ForwardIt, typename T>
+ForwardIt remove(ForwardIt, ForwardIt, const T &);
+
+template <typename ForwardIt, typename UnaryPredicate>
+ForwardIt remove_if(ForwardIt, ForwardIt, UnaryPredicate);
+
+template <typename ForwardIt>
+ForwardIt unique(ForwardIt, ForwardIt);
+
+template <typename T>
+struct default_delete;
+
+template <typename T, typename Deleter = std::default_delete<T>>
+struct unique_ptr {
+ T *release() noexcept;
+};
+
+template <typename T>
+struct char_traits;
+
+template <typename T>
+struct allocator;
+
+template <typename CharT,
+ typename Traits = char_traits<CharT>,
+ typename Allocator = allocator<CharT>>
+struct basic_string {
+ bool empty() const;
+};
+
+typedef basic_string<char> string;
+
+template <typename T, typename Allocator = std::allocator<T>>
+struct vector {
+ bool empty() const noexcept;
+};
+
+// the check should be able to match std lib calls even if the functions are
+// declared inside inline namespaces
+inline namespace v1 {
+
+template <typename T>
+T *launder(T *);
+
+} // namespace v1
+} // namespace std
+
+struct Foo {
+ void f();
+};
+
+int increment(int i) {
+ return i + 1;
+}
+
+void useFuture(const std::future &fut);
+
+void warning() {
+ std::async(increment, 42);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ std::async(std::launch::async, increment, 42);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ Foo F;
+ std::launder(&F);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ std::remove(nullptr, nullptr, 1);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ std::remove_if(nullptr, nullptr, nullptr);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ std::unique(nullptr, nullptr);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ std::unique_ptr<Foo> UPtr;
+ UPtr.release();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ std::string Str;
+ Str.empty();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ std::vector<Foo> Vec;
+ Vec.empty();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ // test discarding return values inside different kinds of statements
+
+ auto Lambda = [] { std::remove(nullptr, nullptr, 1); };
+ // CHECK-MESSAGES: [[@LINE-1]]:22: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ if (true)
+ std::remove(nullptr, nullptr, 1);
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+ else if (true)
+ std::remove(nullptr, nullptr, 1);
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+ else
+ std::remove(nullptr, nullptr, 1);
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ while (true)
+ std::remove(nullptr, nullptr, 1);
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ do
+ std::remove(nullptr, nullptr, 1);
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+ while (true);
+
+ for (;;)
+ std::remove(nullptr, nullptr, 1);
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ for (std::remove(nullptr, nullptr, 1);;)
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the value returned by this function should be used [bugprone-unused-return-value]
+ ;
+
+ for (;; std::remove(nullptr, nullptr, 1))
+ // CHECK-MESSAGES: [[@LINE-1]]:11: warning: the value returned by this function should be used [bugprone-unused-return-value]
+ ;
+
+ for (auto C : "foo")
+ std::remove(nullptr, nullptr, 1);
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+ switch (1) {
+ case 1:
+ std::remove(nullptr, nullptr, 1);
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+ break;
+ default:
+ std::remove(nullptr, nullptr, 1);
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+ break;
+ }
+
+ try {
+ std::remove(nullptr, nullptr, 1);
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+ } catch (...) {
+ std::remove(nullptr, nullptr, 1);
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+ }
+}
+
+void noWarning() {
+ auto AsyncRetval1 = std::async(increment, 42);
+ auto AsyncRetval2 = std::async(std::launch::async, increment, 42);
+
+ Foo FNoWarning;
+ auto LaunderRetval = std::launder(&FNoWarning);
+
+ auto RemoveRetval = std::remove(nullptr, nullptr, 1);
+
+ auto RemoveIfRetval = std::remove_if(nullptr, nullptr, nullptr);
+
+ auto UniqueRetval = std::unique(nullptr, nullptr);
+
+ std::unique_ptr<Foo> UPtrNoWarning;
+ auto ReleaseRetval = UPtrNoWarning.release();
+
+ std::string StrNoWarning;
+ auto StrEmptyRetval = StrNoWarning.empty();
+
+ std::vector<Foo> VecNoWarning;
+ auto VecEmptyRetval = VecNoWarning.empty();
+
+ // test using the return value in different kinds of expressions
+ useFuture(std::async(increment, 42));
+ std::launder(&FNoWarning)->f();
+ delete std::launder(&FNoWarning);
+
+ if (std::launder(&FNoWarning))
+ ;
+ for (; std::launder(&FNoWarning);)
+ ;
+ while (std::launder(&FNoWarning))
+ ;
+ do
+ ;
+ while (std::launder(&FNoWarning));
+ switch (std::unique(1, 1))
+ ;
+
+ // cast to void should allow ignoring the return value
+ (void)std::async(increment, 42);
+
+ // test discarding return value of functions that are not configured to be checked
+ increment(1);
+
+ // test that the check is disabled inside GNU statement expressions
+ ({ std::async(increment, 42); });
+ auto StmtExprRetval = ({ std::async(increment, 42); });
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-use-after-move.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-use-after-move.cpp
new file mode 100644
index 0000000..43e6322
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-use-after-move.cpp
@@ -0,0 +1,1164 @@
+// RUN: %check_clang_tidy %s bugprone-use-after-move %t -- -- -std=c++11 -fno-delayed-template-parsing
+
+typedef decltype(nullptr) nullptr_t;
+
+namespace std {
+typedef unsigned size_t;
+
+template <typename T>
+struct unique_ptr {
+ unique_ptr();
+ T *get() const;
+ explicit operator bool() const;
+ void reset(T *ptr);
+ T &operator*() const;
+ T *operator->() const;
+ T& operator[](size_t i) const;
+};
+
+template <typename T>
+struct shared_ptr {
+ shared_ptr();
+ T *get() const;
+ explicit operator bool() const;
+ void reset(T *ptr);
+ T &operator*() const;
+ T *operator->() const;
+};
+
+template <typename T>
+struct weak_ptr {
+ weak_ptr();
+ bool expired() const;
+};
+
+#define DECLARE_STANDARD_CONTAINER(name) \
+ template <typename T> \
+ struct name { \
+ name(); \
+ void clear(); \
+ bool empty(); \
+ }
+
+#define DECLARE_STANDARD_CONTAINER_WITH_ASSIGN(name) \
+ template <typename T> \
+ struct name { \
+ name(); \
+ void clear(); \
+ bool empty(); \
+ void assign(size_t, const T &); \
+ }
+
+DECLARE_STANDARD_CONTAINER_WITH_ASSIGN(basic_string);
+DECLARE_STANDARD_CONTAINER_WITH_ASSIGN(vector);
+DECLARE_STANDARD_CONTAINER_WITH_ASSIGN(deque);
+DECLARE_STANDARD_CONTAINER_WITH_ASSIGN(forward_list);
+DECLARE_STANDARD_CONTAINER_WITH_ASSIGN(list);
+DECLARE_STANDARD_CONTAINER(set);
+DECLARE_STANDARD_CONTAINER(map);
+DECLARE_STANDARD_CONTAINER(multiset);
+DECLARE_STANDARD_CONTAINER(multimap);
+DECLARE_STANDARD_CONTAINER(unordered_set);
+DECLARE_STANDARD_CONTAINER(unordered_map);
+DECLARE_STANDARD_CONTAINER(unordered_multiset);
+DECLARE_STANDARD_CONTAINER(unordered_multimap);
+
+typedef basic_string<char> string;
+
+template <typename>
+struct remove_reference;
+
+template <typename _Tp>
+struct remove_reference {
+ typedef _Tp type;
+};
+
+template <typename _Tp>
+struct remove_reference<_Tp &> {
+ typedef _Tp type;
+};
+
+template <typename _Tp>
+struct remove_reference<_Tp &&> {
+ typedef _Tp type;
+};
+
+template <typename _Tp>
+constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t) noexcept {
+ return static_cast<typename remove_reference<_Tp>::type &&>(__t);
+}
+
+} // namespace std
+
+class A {
+public:
+ A();
+ A(const A &);
+ A(A &&);
+
+ A &operator=(const A &);
+ A &operator=(A &&);
+
+ void foo() const;
+ int getInt() const;
+
+ operator bool() const;
+
+ int i;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// General tests.
+
+// Simple case.
+void simple() {
+ A a;
+ a.foo();
+ A other_a = std::move(a);
+ a.foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:15: note: move occurred here
+}
+
+// A warning should only be emitted for one use-after-move.
+void onlyFlagOneUseAfterMove() {
+ A a;
+ a.foo();
+ A other_a = std::move(a);
+ a.foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:15: note: move occurred here
+ a.foo();
+}
+
+void moveAfterMove() {
+ // Move-after-move also counts as a use.
+ {
+ A a;
+ std::move(a);
+ std::move(a);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+ }
+ // This is also true if the move itself turns into the use on the second loop
+ // iteration.
+ {
+ A a;
+ for (int i = 0; i < 10; ++i) {
+ std::move(a);
+ // CHECK-MESSAGES: [[@LINE-1]]:17: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-2]]:7: note: move occurred here
+ // CHECK-MESSAGES: [[@LINE-3]]:17: note: the use happens in a later loop
+ }
+ }
+}
+
+// Checks also works on function parameters that have a use-after move.
+void parameters(A a) {
+ std::move(a);
+ a.foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:3: note: move occurred here
+}
+
+void standardSmartPtr() {
+ // std::unique_ptr<>, std::shared_ptr<> and std::weak_ptr<> are guaranteed to
+ // be null after a std::move. So the check only flags accesses that would
+ // dereference the pointer.
+ {
+ std::unique_ptr<A> ptr;
+ std::move(ptr);
+ ptr.get();
+ static_cast<bool>(ptr);
+ *ptr;
+ // CHECK-MESSAGES: [[@LINE-1]]:6: warning: 'ptr' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-5]]:5: note: move occurred here
+ }
+ {
+ std::unique_ptr<A> ptr;
+ std::move(ptr);
+ ptr->foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'ptr' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+ }
+ {
+ std::unique_ptr<A> ptr;
+ std::move(ptr);
+ ptr[0];
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'ptr' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+ }
+ {
+ std::shared_ptr<A> ptr;
+ std::move(ptr);
+ ptr.get();
+ static_cast<bool>(ptr);
+ *ptr;
+ // CHECK-MESSAGES: [[@LINE-1]]:6: warning: 'ptr' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-5]]:5: note: move occurred here
+ }
+ {
+ std::shared_ptr<A> ptr;
+ std::move(ptr);
+ ptr->foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'ptr' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+ }
+ {
+ // std::weak_ptr<> cannot be dereferenced directly, so we only check that
+ // member functions may be called on it after a move.
+ std::weak_ptr<A> ptr;
+ std::move(ptr);
+ ptr.expired();
+ }
+ // Make sure we recognize std::unique_ptr<> or std::shared_ptr<> if they're
+ // wrapped in a typedef.
+ {
+ typedef std::unique_ptr<A> PtrToA;
+ PtrToA ptr;
+ std::move(ptr);
+ ptr.get();
+ }
+ {
+ typedef std::shared_ptr<A> PtrToA;
+ PtrToA ptr;
+ std::move(ptr);
+ ptr.get();
+ }
+ // And we don't get confused if the template argument is a little more
+ // involved.
+ {
+ struct B {
+ typedef A AnotherNameForA;
+ };
+ std::unique_ptr<B::AnotherNameForA> ptr;
+ std::move(ptr);
+ ptr.get();
+ }
+ // We don't give any special treatment to types that are called "unique_ptr"
+ // or "shared_ptr" but are not in the "::std" namespace.
+ {
+ struct unique_ptr {
+ void get();
+ } ptr;
+ std::move(ptr);
+ ptr.get();
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'ptr' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+ }
+}
+
+// The check also works in member functions.
+class Container {
+ void useAfterMoveInMemberFunction() {
+ A a;
+ std::move(a);
+ a.foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+ }
+};
+
+// We see the std::move() if it's inside a declaration.
+void moveInDeclaration() {
+ A a;
+ A another_a(std::move(a));
+ a.foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+}
+
+// We see the std::move if it's inside an initializer list. Initializer lists
+// are a special case because they cause ASTContext::getParents() to return
+// multiple parents for certain nodes in their subtree. This is because
+// RecursiveASTVisitor visits both the syntactic and semantic forms of
+// InitListExpr, and the parent-child relationships are different between the
+// two forms.
+void moveInInitList() {
+ struct S {
+ A a;
+ };
+ A a;
+ S s{std::move(a)};
+ a.foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:7: note: move occurred here
+}
+
+void lambdas() {
+ // Use-after-moves inside a lambda should be detected.
+ {
+ A a;
+ auto lambda = [a] {
+ std::move(a);
+ a.foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:7: note: move occurred here
+ };
+ }
+ // This is just as true if the variable was declared inside the lambda.
+ {
+ auto lambda = [] {
+ A a;
+ std::move(a);
+ a.foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:7: note: move occurred here
+ };
+ }
+ // But don't warn if the move happened inside the lambda but the use happened
+ // outside -- because
+ // - the 'a' inside the lambda is a copy, and
+ // - we don't know when the lambda will get called anyway
+ {
+ A a;
+ auto lambda = [a] {
+ std::move(a);
+ };
+ a.foo();
+ }
+ // Warn if the use consists of a capture that happens after a move.
+ {
+ A a;
+ std::move(a);
+ auto lambda = [a]() { a.foo(); };
+ // CHECK-MESSAGES: [[@LINE-1]]:20: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+ }
+ // ...even if the capture was implicit.
+ {
+ A a;
+ std::move(a);
+ auto lambda = [=]() { a.foo(); };
+ // CHECK-MESSAGES: [[@LINE-1]]:27: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+ }
+ // Same tests but for capture by reference.
+ {
+ A a;
+ std::move(a);
+ auto lambda = [&a]() { a.foo(); };
+ // CHECK-MESSAGES: [[@LINE-1]]:21: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+ }
+ {
+ A a;
+ std::move(a);
+ auto lambda = [&]() { a.foo(); };
+ // CHECK-MESSAGES: [[@LINE-1]]:27: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+ }
+ // But don't warn if the move happened after the capture.
+ {
+ A a;
+ auto lambda = [a]() { a.foo(); };
+ std::move(a);
+ }
+ // ...and again, same thing with an implicit move.
+ {
+ A a;
+ auto lambda = [=]() { a.foo(); };
+ std::move(a);
+ }
+ // Same tests but for capture by reference.
+ {
+ A a;
+ auto lambda = [&a]() { a.foo(); };
+ std::move(a);
+ }
+ {
+ A a;
+ auto lambda = [&]() { a.foo(); };
+ std::move(a);
+ }
+}
+
+// Use-after-moves are detected in uninstantiated templates if the moved type
+// is not a dependent type.
+template <class T>
+void movedTypeIsNotDependentType() {
+ T t;
+ A a;
+ std::move(a);
+ a.foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:3: note: move occurred here
+}
+
+// And if the moved type is a dependent type, the use-after-move is detected if
+// the template is instantiated.
+template <class T>
+void movedTypeIsDependentType() {
+ T t;
+ std::move(t);
+ t.foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 't' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:3: note: move occurred here
+}
+template void movedTypeIsDependentType<A>();
+
+// We handle the case correctly where the move consists of an implicit call
+// to a conversion operator.
+void implicitConversionOperator() {
+ struct Convertible {
+ operator A() && { return A(); }
+ };
+ void takeA(A a);
+
+ Convertible convertible;
+ takeA(std::move(convertible));
+ convertible;
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'convertible' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:9: note: move occurred here
+}
+
+// Using decltype on an expression is not a use.
+void decltypeIsNotUse() {
+ A a;
+ std::move(a);
+ decltype(a) other_a;
+}
+
+// Ignore moves or uses that occur as part of template arguments.
+template <int>
+class ClassTemplate {
+public:
+ void foo(A a);
+};
+template <int>
+void functionTemplate(A a);
+void templateArgIsNotUse() {
+ {
+ // A pattern like this occurs in the EXPECT_EQ and ASSERT_EQ macros in
+ // Google Test.
+ A a;
+ ClassTemplate<sizeof(A(std::move(a)))>().foo(std::move(a));
+ }
+ {
+ A a;
+ functionTemplate<sizeof(A(std::move(a)))>(std::move(a));
+ }
+}
+
+// Ignore moves of global variables.
+A global_a;
+void ignoreGlobalVariables() {
+ std::move(global_a);
+ global_a.foo();
+}
+
+// Ignore moves of member variables.
+class IgnoreMemberVariables {
+ A a;
+ static A static_a;
+
+ void f() {
+ std::move(a);
+ a.foo();
+
+ std::move(static_a);
+ static_a.foo();
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Tests involving control flow.
+
+void useAndMoveInLoop() {
+ // Warn about use-after-moves if they happen in a later loop iteration than
+ // the std::move().
+ {
+ A a;
+ for (int i = 0; i < 10; ++i) {
+ a.foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE+2]]:7: note: move occurred here
+ // CHECK-MESSAGES: [[@LINE-3]]:7: note: the use happens in a later loop
+ std::move(a);
+ }
+ }
+ // However, this case shouldn't be flagged -- the scope of the declaration of
+ // 'a' is important.
+ {
+ for (int i = 0; i < 10; ++i) {
+ A a;
+ a.foo();
+ std::move(a);
+ }
+ }
+ // Same as above, except that we have an unrelated variable being declared in
+ // the same declaration as 'a'. This case is interesting because it tests that
+ // the synthetic DeclStmts generated by the CFG are sequenced correctly
+ // relative to the other statements.
+ {
+ for (int i = 0; i < 10; ++i) {
+ A a, other;
+ a.foo();
+ std::move(a);
+ }
+ }
+ // Don't warn if we return after the move.
+ {
+ A a;
+ for (int i = 0; i < 10; ++i) {
+ a.foo();
+ if (a.getInt() > 0) {
+ std::move(a);
+ return;
+ }
+ }
+ }
+}
+
+void differentBranches(int i) {
+ // Don't warn if the use is in a different branch from the move.
+ {
+ A a;
+ if (i > 0) {
+ std::move(a);
+ } else {
+ a.foo();
+ }
+ }
+ // Same thing, but with a ternary operator.
+ {
+ A a;
+ i > 0 ? (void)std::move(a) : a.foo();
+ }
+ // A variation on the theme above.
+ {
+ A a;
+ a.getInt() > 0 ? a.getInt() : A(std::move(a)).getInt();
+ }
+ // Same thing, but with a switch statement.
+ {
+ A a;
+ switch (i) {
+ case 1:
+ std::move(a);
+ break;
+ case 2:
+ a.foo();
+ break;
+ }
+ }
+ // However, if there's a fallthrough, we do warn.
+ {
+ A a;
+ switch (i) {
+ case 1:
+ std::move(a);
+ case 2:
+ a.foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-4]]:7: note: move occurred here
+ break;
+ }
+ }
+}
+
+// False positive: A use-after-move is flagged even though the "if (b)" and
+// "if (!b)" are mutually exclusive.
+void mutuallyExclusiveBranchesFalsePositive(bool b) {
+ A a;
+ if (b) {
+ std::move(a);
+ }
+ if (!b) {
+ a.foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-5]]:5: note: move occurred here
+ }
+}
+
+// Destructors marked [[noreturn]] are handled correctly in the control flow
+// analysis. (These are used in some styles of assertion macros.)
+class FailureLogger {
+public:
+ FailureLogger();
+ [[noreturn]] ~FailureLogger();
+ void log(const char *);
+};
+#define ASSERT(x) \
+ while (x) \
+ FailureLogger().log(#x)
+bool operationOnA(A);
+void noreturnDestructor() {
+ A a;
+ // The while loop in the ASSERT() would ordinarily have the potential to cause
+ // a use-after-move because the second iteration of the loop would be using a
+ // variable that had been moved from in the first iteration. Check that the
+ // CFG knows that the second iteration of the loop is never reached because
+ // the FailureLogger destructor is marked [[noreturn]].
+ ASSERT(operationOnA(std::move(a)));
+}
+#undef ASSERT
+
+////////////////////////////////////////////////////////////////////////////////
+// Tests for reinitializations
+
+template <class T>
+void swap(T &a, T &b) {
+ T tmp = std::move(a);
+ a = std::move(b);
+ b = std::move(tmp);
+}
+void assignments(int i) {
+ // Don't report a use-after-move if the variable was assigned to in the
+ // meantime.
+ {
+ A a;
+ std::move(a);
+ a = A();
+ a.foo();
+ }
+ // The assignment should also be recognized if move, assignment and use don't
+ // all happen in the same block (but the assignment is still guaranteed to
+ // prevent a use-after-move).
+ {
+ A a;
+ if (i == 1) {
+ std::move(a);
+ a = A();
+ }
+ if (i == 2) {
+ a.foo();
+ }
+ }
+ {
+ A a;
+ if (i == 1) {
+ std::move(a);
+ }
+ if (i == 2) {
+ a = A();
+ a.foo();
+ }
+ }
+ // The built-in assignment operator should also be recognized as a
+ // reinitialization. (std::move() may be called on built-in types in template
+ // code.)
+ {
+ int a1 = 1, a2 = 2;
+ swap(a1, a2);
+ }
+ // A std::move() after the assignment makes the variable invalid again.
+ {
+ A a;
+ std::move(a);
+ a = A();
+ std::move(a);
+ a.foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+ }
+ // Report a use-after-move if we can't be sure that the variable was assigned
+ // to.
+ {
+ A a;
+ std::move(a);
+ if (i < 10) {
+ a = A();
+ }
+ if (i > 5) {
+ a.foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-7]]:5: note: move occurred here
+ }
+ }
+}
+
+// Passing the object to a function through a non-const pointer or reference
+// counts as a re-initialization.
+void passByNonConstPointer(A *);
+void passByNonConstReference(A &);
+void passByNonConstPointerIsReinit() {
+ {
+ A a;
+ std::move(a);
+ passByNonConstPointer(&a);
+ a.foo();
+ }
+ {
+ A a;
+ std::move(a);
+ passByNonConstReference(a);
+ a.foo();
+ }
+}
+
+// Passing the object through a const pointer or reference counts as a use --
+// since the called function cannot reinitialize the object.
+void passByConstPointer(const A *);
+void passByConstReference(const A &);
+void passByConstPointerIsUse() {
+ {
+ // Declaring 'a' as const so that no ImplicitCastExpr is inserted into the
+ // AST -- we wouldn't want the check to rely solely on that to detect a
+ // const pointer argument.
+ const A a;
+ std::move(a);
+ passByConstPointer(&a);
+ // CHECK-MESSAGES: [[@LINE-1]]:25: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+ }
+ const A a;
+ std::move(a);
+ passByConstReference(a);
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:3: note: move occurred here
+}
+
+// Clearing a standard container using clear() is treated as a
+// re-initialization.
+void standardContainerClearIsReinit() {
+ {
+ std::string container;
+ std::move(container);
+ container.clear();
+ container.empty();
+ }
+ {
+ std::vector<int> container;
+ std::move(container);
+ container.clear();
+ container.empty();
+
+ auto container2 = container;
+ std::move(container2);
+ container2.clear();
+ container2.empty();
+ }
+ {
+ std::deque<int> container;
+ std::move(container);
+ container.clear();
+ container.empty();
+ }
+ {
+ std::forward_list<int> container;
+ std::move(container);
+ container.clear();
+ container.empty();
+ }
+ {
+ std::list<int> container;
+ std::move(container);
+ container.clear();
+ container.empty();
+ }
+ {
+ std::set<int> container;
+ std::move(container);
+ container.clear();
+ container.empty();
+ }
+ {
+ std::map<int> container;
+ std::move(container);
+ container.clear();
+ container.empty();
+ }
+ {
+ std::multiset<int> container;
+ std::move(container);
+ container.clear();
+ container.empty();
+ }
+ {
+ std::multimap<int> container;
+ std::move(container);
+ container.clear();
+ container.empty();
+ }
+ {
+ std::unordered_set<int> container;
+ std::move(container);
+ container.clear();
+ container.empty();
+ }
+ {
+ std::unordered_map<int> container;
+ std::move(container);
+ container.clear();
+ container.empty();
+ }
+ {
+ std::unordered_multiset<int> container;
+ std::move(container);
+ container.clear();
+ container.empty();
+ }
+ {
+ std::unordered_multimap<int> container;
+ std::move(container);
+ container.clear();
+ container.empty();
+ }
+ // This should also work for typedefs of standard containers.
+ {
+ typedef std::vector<int> IntVector;
+ IntVector container;
+ std::move(container);
+ container.clear();
+ container.empty();
+ }
+ // But it shouldn't work for non-standard containers.
+ {
+ // This might be called "vector", but it's not in namespace "std".
+ struct vector {
+ void clear() {}
+ } container;
+ std::move(container);
+ container.clear();
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'container' used after it was
+ // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+ }
+ // An intervening clear() on a different container does not reinitialize.
+ {
+ std::vector<int> container1, container2;
+ std::move(container1);
+ container2.clear();
+ container1.empty();
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'container1' used after it was
+ // CHECK-MESSAGES: [[@LINE-4]]:5: note: move occurred here
+ }
+}
+
+// Clearing a standard container using assign() is treated as a
+// re-initialization.
+void standardContainerAssignIsReinit() {
+ {
+ std::string container;
+ std::move(container);
+ container.assign(0, ' ');
+ container.empty();
+ }
+ {
+ std::vector<int> container;
+ std::move(container);
+ container.assign(0, 0);
+ container.empty();
+ }
+ {
+ std::deque<int> container;
+ std::move(container);
+ container.assign(0, 0);
+ container.empty();
+ }
+ {
+ std::forward_list<int> container;
+ std::move(container);
+ container.assign(0, 0);
+ container.empty();
+ }
+ {
+ std::list<int> container;
+ std::move(container);
+ container.clear();
+ container.empty();
+ }
+ // But it doesn't work for non-standard containers.
+ {
+ // This might be called "vector", but it's not in namespace "std".
+ struct vector {
+ void assign(std::size_t, int) {}
+ } container;
+ std::move(container);
+ container.assign(0, 0);
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'container' used after it was
+ // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+ }
+ // An intervening assign() on a different container does not reinitialize.
+ {
+ std::vector<int> container1, container2;
+ std::move(container1);
+ container2.assign(0, 0);
+ container1.empty();
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'container1' used after it was
+ // CHECK-MESSAGES: [[@LINE-4]]:5: note: move occurred here
+ }
+}
+
+// Resetting the standard smart pointer types using reset() is treated as a
+// re-initialization. (We don't test std::weak_ptr<> because it can't be
+// dereferenced directly.)
+void standardSmartPointerResetIsReinit() {
+ {
+ std::unique_ptr<A> ptr;
+ std::move(ptr);
+ ptr.reset(new A);
+ *ptr;
+ }
+ {
+ std::shared_ptr<A> ptr;
+ std::move(ptr);
+ ptr.reset(new A);
+ *ptr;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Tests related to order of evaluation within expressions
+
+// Relative sequencing of move and use.
+void passByRvalueReference(int i, A &&a);
+void passByValue(int i, A a);
+void passByValue(A a, int i);
+A g(A, A &&);
+int intFromA(A &&);
+int intFromInt(int);
+void sequencingOfMoveAndUse() {
+ // This case is fine because the move only happens inside
+ // passByRvalueReference(). At this point, a.getInt() is guaranteed to have
+ // been evaluated.
+ {
+ A a;
+ passByRvalueReference(a.getInt(), std::move(a));
+ }
+ // However, if we pass by value, the move happens when the move constructor is
+ // called to create a temporary, and this happens before the call to
+ // passByValue(). Because the order in which arguments are evaluated isn't
+ // defined, the move may happen before the call to a.getInt().
+ //
+ // Check that we warn about a potential use-after move for both orderings of
+ // a.getInt() and std::move(a), independent of the order in which the
+ // arguments happen to get evaluated by the compiler.
+ {
+ A a;
+ passByValue(a.getInt(), std::move(a));
+ // CHECK-MESSAGES: [[@LINE-1]]:17: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-2]]:29: note: move occurred here
+ // CHECK-MESSAGES: [[@LINE-3]]:17: note: the use and move are unsequenced
+ }
+ {
+ A a;
+ passByValue(std::move(a), a.getInt());
+ // CHECK-MESSAGES: [[@LINE-1]]:31: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-2]]:17: note: move occurred here
+ // CHECK-MESSAGES: [[@LINE-3]]:31: note: the use and move are unsequenced
+ }
+ // An even more convoluted example.
+ {
+ A a;
+ g(g(a, std::move(a)), g(a, std::move(a)));
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-2]]:27: note: move occurred here
+ // CHECK-MESSAGES: [[@LINE-3]]:9: note: the use and move are unsequenced
+ // CHECK-MESSAGES: [[@LINE-4]]:29: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-5]]:7: note: move occurred here
+ // CHECK-MESSAGES: [[@LINE-6]]:29: note: the use and move are unsequenced
+ }
+ // This case is fine because the actual move only happens inside the call to
+ // operator=(). a.getInt(), by necessity, is evaluated before that call.
+ {
+ A a;
+ A vec[1];
+ vec[a.getInt()] = std::move(a);
+ }
+ // However, in the following case, the move happens before the assignment, and
+ // so the order of evaluation is not guaranteed.
+ {
+ A a;
+ int v[3];
+ v[a.getInt()] = intFromA(std::move(a));
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-2]]:21: note: move occurred here
+ // CHECK-MESSAGES: [[@LINE-3]]:7: note: the use and move are unsequenced
+ }
+ {
+ A a;
+ int v[3];
+ v[intFromA(std::move(a))] = intFromInt(a.i);
+ // CHECK-MESSAGES: [[@LINE-1]]:44: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-2]]:7: note: move occurred here
+ // CHECK-MESSAGES: [[@LINE-3]]:44: note: the use and move are unsequenced
+ }
+}
+
+// Relative sequencing of move and reinitialization. If the two are unsequenced,
+// we conservatively assume that the move happens after the reinitialization,
+// i.e. the that object does not get reinitialized after the move.
+A MutateA(A a);
+void passByValue(A a1, A a2);
+void sequencingOfMoveAndReinit() {
+ // Move and reinitialization as function arguments (which are indeterminately
+ // sequenced). Again, check that we warn for both orderings.
+ {
+ A a;
+ passByValue(std::move(a), (a = A()));
+ a.foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:17: note: move occurred here
+ }
+ {
+ A a;
+ passByValue((a = A()), std::move(a));
+ a.foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:28: note: move occurred here
+ }
+ // Common usage pattern: Move the object to a function that mutates it in some
+ // way, then reassign the result to the object. This pattern is fine.
+ {
+ A a;
+ a = MutateA(std::move(a));
+ a.foo();
+ }
+}
+
+// Relative sequencing of reinitialization and use. If the two are unsequenced,
+// we conservatively assume that the reinitialization happens after the use,
+// i.e. that the object is not reinitialized at the point in time when it is
+// used.
+void sequencingOfReinitAndUse() {
+ // Reinitialization and use in function arguments. Again, check both possible
+ // orderings.
+ {
+ A a;
+ std::move(a);
+ passByValue(a.getInt(), (a = A()));
+ // CHECK-MESSAGES: [[@LINE-1]]:17: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+ }
+ {
+ A a;
+ std::move(a);
+ passByValue((a = A()), a.getInt());
+ // CHECK-MESSAGES: [[@LINE-1]]:28: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+ }
+}
+
+// The comma operator sequences its operands.
+void commaOperatorSequences() {
+ {
+ A a;
+ A(std::move(a))
+ , (a = A());
+ a.foo();
+ }
+ {
+ A a;
+ (a = A()), A(std::move(a));
+ a.foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:16: note: move occurred here
+ }
+}
+
+// An initializer list sequences its initialization clauses.
+void initializerListSequences() {
+ {
+ struct S1 {
+ int i;
+ A a;
+ };
+ A a;
+ S1 s1{a.getInt(), std::move(a)};
+ }
+ {
+ struct S2 {
+ A a;
+ int i;
+ };
+ A a;
+ S2 s2{std::move(a), a.getInt()};
+ // CHECK-MESSAGES: [[@LINE-1]]:25: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-2]]:11: note: move occurred here
+ }
+}
+
+// A declaration statement containing multiple declarations sequences the
+// initializer expressions.
+void declarationSequences() {
+ {
+ A a;
+ A a1 = a, a2 = std::move(a);
+ }
+ {
+ A a;
+ A a1 = std::move(a), a2 = a;
+ // CHECK-MESSAGES: [[@LINE-1]]:31: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-2]]:12: note: move occurred here
+ }
+}
+
+// The logical operators && and || sequence their operands.
+void logicalOperatorsSequence() {
+ {
+ A a;
+ if (a.getInt() > 0 && A(std::move(a)).getInt() > 0) {
+ A().foo();
+ }
+ }
+ // A variation: Negate the result of the && (which pushes the && further down
+ // into the AST).
+ {
+ A a;
+ if (!(a.getInt() > 0 && A(std::move(a)).getInt() > 0)) {
+ A().foo();
+ }
+ }
+ {
+ A a;
+ if (A(std::move(a)).getInt() > 0 && a.getInt() > 0) {
+ // CHECK-MESSAGES: [[@LINE-1]]:41: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-2]]:9: note: move occurred here
+ A().foo();
+ }
+ }
+ {
+ A a;
+ if (a.getInt() > 0 || A(std::move(a)).getInt() > 0) {
+ A().foo();
+ }
+ }
+ {
+ A a;
+ if (A(std::move(a)).getInt() > 0 || a.getInt() > 0) {
+ // CHECK-MESSAGES: [[@LINE-1]]:41: warning: 'a' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-2]]:9: note: move occurred here
+ A().foo();
+ }
+ }
+}
+
+// A range-based for sequences the loop variable declaration before the body.
+void forRangeSequences() {
+ A v[2] = {A(), A()};
+ for (A &a : v) {
+ std::move(a);
+ }
+}
+
+// If a variable is declared in an if statement, the declaration of the variable
+// (which is treated like a reinitialization by the check) is sequenced before
+// the evaluation of the condition (which constitutes a use).
+void ifStmtSequencesDeclAndCondition() {
+ for (int i = 0; i < 10; ++i) {
+ if (A a = A()) {
+ std::move(a);
+ }
+ }
+}
+
+namespace PR33020 {
+class D {
+ ~D();
+};
+struct A {
+ D d;
+};
+class B {
+ A a;
+};
+template <typename T>
+class C : T, B {
+ void m_fn1() {
+ int a;
+ std::move(a);
+ C c;
+ }
+};
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-virtual-near-miss.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-virtual-near-miss.cpp
new file mode 100644
index 0000000..553d2f4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-virtual-near-miss.cpp
@@ -0,0 +1,133 @@
+// RUN: %check_clang_tidy %s bugprone-virtual-near-miss %t
+
+class NoDefinedClass1;
+class NoDefinedClass2;
+
+struct Base {
+ virtual void func();
+ virtual void gunk();
+ virtual ~Base();
+ virtual Base &operator=(const Base &);
+ virtual NoDefinedClass1 *f();
+};
+
+struct Derived : Base {
+ // Should not warn "do you want to override 'gunk'?", because gunk is already
+ // overriden by this class.
+ virtual void funk();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Derived::funk' has a similar name and the same signature as virtual method 'Base::func'; did you mean to override it? [bugprone-virtual-near-miss]
+ // CHECK-FIXES: virtual void func();
+
+ void func2();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Derived::func2' has {{.*}} 'Base::func'
+ // CHECK-FIXES: void func();
+
+ void func22(); // Should not warn.
+
+ void gunk(); // Should not warn: gunk is override.
+
+ void fun();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Derived::fun' has {{.*}} 'Base::func'
+ // CHECK-FIXES: void func();
+
+ Derived &operator==(const Base &); // Should not warn: operators are ignored.
+
+ virtual NoDefinedClass2 *f1(); // Should not crash: non-defined class return type is ignored.
+};
+
+template <typename T>
+struct TBase {
+ virtual void tfunc(T t);
+};
+
+template <typename T>
+struct TDerived : TBase<T> {
+ virtual void tfunk(T t);
+ // Should not apply fix for template.
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: method 'TDerived<double>::tfunk' has {{.*}} 'TBase<double>::tfunc'
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: method 'TDerived<int>::tfunk' has {{.*}} 'TBase<int>::tfunc'
+ // CHECK-FIXES: virtual void tfunk(T t);
+};
+
+TDerived<int> T1;
+TDerived<double> T2;
+
+// Should not fix macro definition
+#define MACRO1 void funcM()
+// CHECK-FIXES: #define MACRO1 void funcM()
+#define MACRO2(m) void m()
+// CHECK-FIXES: #define MACRO2(m) void m()
+
+struct DerivedMacro : Base {
+ MACRO1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'DerivedMacro::funcM' has {{.*}} 'Base::func'
+ // CHECK-FIXES: MACRO1;
+
+ MACRO2(func3);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'DerivedMacro::func3' has {{.*}} 'Base::func'
+ // CHECK-FIXES: MACRO2(func);
+};
+
+typedef Derived derived_type;
+
+class Father {
+public:
+ Father();
+ virtual void func();
+ virtual Father *create(int i);
+ virtual Base &&generate();
+ virtual Base *canonical(Derived D);
+};
+
+class Mother {
+public:
+ Mother();
+ static void method();
+ virtual int method(int argc, const char **argv);
+ virtual int method(int argc) const;
+ virtual int decay(const char *str);
+};
+
+class Child : private Father, private Mother {
+public:
+ Child();
+
+ virtual void func2();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::func2' has {{.*}} 'Father::func'
+ // CHECK-FIXES: virtual void func();
+
+ int methoe(int x, char **strs); // Should not warn: parameter types don't match.
+
+ int methoe(int x);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::methoe' has {{.*}} 'Mother::method'
+ // CHECK-FIXES: int method(int x);
+
+ void methof(int x, const char **strs); // Should not warn: return types don't match.
+
+ int methoh(int x, const char **strs);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::methoh' has {{.*}} 'Mother::method'
+ // CHECK-FIXES: int method(int x, const char **strs);
+
+ virtual Child *creat(int i);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::creat' has {{.*}} 'Father::create'
+ // CHECK-FIXES: virtual Child *create(int i);
+
+ virtual Derived &&generat();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::generat' has {{.*}} 'Father::generate'
+ // CHECK-FIXES: virtual Derived &&generate();
+
+ int decaz(const char str[]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::decaz' has {{.*}} 'Mother::decay'
+ // CHECK-FIXES: int decay(const char str[]);
+
+ operator bool();
+
+ derived_type *canonica(derived_type D);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::canonica' has {{.*}} 'Father::canonical'
+ // CHECK-FIXES: derived_type *canonical(derived_type D);
+
+private:
+ void funk();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::funk' has {{.*}} 'Father::func'
+ // CHECK-FIXES: void func();
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-dcl21-cpp.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-dcl21-cpp.cpp
new file mode 100644
index 0000000..c975f70
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-dcl21-cpp.cpp
@@ -0,0 +1,134 @@
+// RUN: %check_clang_tidy %s cert-dcl21-cpp %t
+
+class A {};
+
+A operator++(A &, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: overloaded 'operator++' returns a non-constant object instead of a constant object type [cert-dcl21-cpp]
+// CHECK-FIXES: {{^}}const A operator++(A &, int);
+
+A operator--(A &, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: overloaded 'operator--' returns a no
+// CHECK-FIXES: {{^}}const A operator--(A &, int);
+
+class B {};
+
+B &operator++(B &);
+const B operator++(B &, int);
+
+B &operator--(B &);
+const B operator--(B &, int);
+
+
+class D {
+D &operator++();
+const D operator++(int);
+
+D &operator--();
+const D operator--(int);
+};
+
+class C {
+C operator++(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: overloaded 'operator++' returns a no
+// CHECK-FIXES: {{^}}const C operator++(int);
+
+C operator--(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: overloaded 'operator--' returns a no
+// CHECK-FIXES: {{^}}const C operator--(int);
+};
+
+class E {};
+
+E &operator++(E &, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: overloaded 'operator++' returns a reference instead of a constant object type [cert-dcl21-cpp]
+// CHECK-FIXES: {{^}}const E operator++(E &, int);
+
+E &operator--(E &, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: overloaded 'operator--' returns a re
+// CHECK-FIXES: {{^}}const E operator--(E &, int);
+
+class G {
+G &operator++(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: overloaded 'operator++' returns a re
+// CHECK-FIXES: {{^}}const G operator++(int);
+
+G &operator--(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: overloaded 'operator--' returns a re
+// CHECK-FIXES: {{^}}const G operator--(int);
+};
+
+class F {};
+
+const F &operator++(F &, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: overloaded 'operator++' returns a re
+// CHECK-FIXES: {{^}}const F operator++(F &, int);
+
+const F &operator--(F &, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: overloaded 'operator--' returns a re
+// CHECK-FIXES: {{^}}const F operator--(F &, int);
+
+class H {
+const H &operator++(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: overloaded 'operator++' returns a re
+// CHECK-FIXES: {{^}}const H operator++(int);
+
+const H &operator--(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: overloaded 'operator--' returns a re
+// CHECK-FIXES: {{^}}const H operator--(int);
+};
+
+
+#define FROM_MACRO P&
+class P {
+const FROM_MACRO operator++(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: overloaded 'operator++' returns a re
+// CHECK-FIXES: {{^}}const FROM_MACRO operator++(int);
+};
+
+
+template<typename T>
+class Q {
+const Q &operator++(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: overloaded 'operator++' returns a re
+// CHECK-FIXES: {{^}}const Q<T> operator++(int);
+
+const Q &operator--(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: overloaded 'operator--' returns a re
+// CHECK-FIXES: {{^}}const Q<T> operator--(int);
+};
+
+void foobar() {
+ Q<int> a;
+ Q<float> b;
+ (void)a;
+ (void)b;
+}
+
+struct S {};
+typedef S& SRef;
+
+SRef operator++(SRef, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: overloaded 'operator++' returns a re
+// CHECK-FIXES: {{^}}SRef operator++(SRef, int);
+
+struct T {
+ typedef T& TRef;
+
+ TRef operator++(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: overloaded 'operator++' returns a re
+// CHECK-FIXES: {{^}} TRef operator++(int);
+};
+
+struct U {
+ typedef const U& ConstURef;
+
+ ConstURef& operator++(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: overloaded 'operator++' returns a re
+// CHECK-FIXES: {{^}} ConstURef& operator++(int);
+};
+
+struct V {
+ V *operator++(int);
+ V *const operator--(int);
+};
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-dcl58-cpp.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-dcl58-cpp.cpp
new file mode 100644
index 0000000..34ee368
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-dcl58-cpp.cpp
@@ -0,0 +1,67 @@
+// RUN: %check_clang_tidy %s cert-dcl58-cpp %t -- -- -std=c++1z -I %S/Inputs/Headers
+
+#include "system-header-simulation.h"
+
+namespace A {
+ namespace B {
+ int b;
+ }
+}
+
+namespace A {
+ namespace B {
+ int c;
+ }
+}
+
+namespace posix {
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: modification of 'posix' namespace can result in undefined behavior [cert-dcl58-cpp]
+ namespace vmi {
+ }
+}
+
+namespace std {
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: modification of 'std' namespace can
+ int stdInt;
+}
+
+namespace foobar {
+ namespace std {
+ int bar;
+ }
+}
+
+namespace posix::a {
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: modification of 'posix' namespace
+}
+
+enum class MyError {
+ ErrorA,
+ ErrorB
+};
+
+namespace std {
+template <>
+struct is_error_code_enum<MyError> : std::true_type {};
+
+template<>
+void swap<MyError>(MyError &a, MyError &b);
+}
+
+enum class MyError2 {
+ Error2A,
+ Error2B
+};
+
+namespace std {
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: modification of 'std' namespace
+template <>
+struct is_error_code_enum<MyError2> : std::true_type {};
+
+int foobar;
+}
+
+using namespace std;
+
+int x;
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-env33-c.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-env33-c.c
new file mode 100644
index 0000000..5846b49
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-env33-c.c
@@ -0,0 +1,20 @@
+// RUN: %check_clang_tidy %s cert-env33-c %t
+
+typedef struct FILE {} FILE;
+
+extern int system(const char *);
+extern FILE *popen(const char *, const char *);
+extern FILE *_popen(const char *, const char *);
+
+void f(void) {
+ // It is permissible to check for the presence of a command processor.
+ system(0);
+
+ system("test");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling 'system' uses a command processor [cert-env33-c]
+
+ popen("test", "test");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling 'popen' uses a command processor
+ _popen("test", "test");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling '_popen' uses a command processor
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-err34-c.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-err34-c.c
new file mode 100644
index 0000000..e2cfc21
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-err34-c.c
@@ -0,0 +1,103 @@
+// RUN: %check_clang_tidy %s cert-err34-c %t -- -- -std=c11
+
+typedef __SIZE_TYPE__ size_t;
+typedef signed ptrdiff_t;
+typedef long long intmax_t;
+typedef unsigned long long uintmax_t;
+typedef void * FILE;
+
+extern FILE *stdin;
+
+extern int fscanf(FILE * restrict stream, const char * restrict format, ...);
+extern int scanf(const char * restrict format, ...);
+extern int sscanf(const char * restrict s, const char * restrict format, ...);
+
+extern double atof(const char *nptr);
+extern int atoi(const char *nptr);
+extern long int atol(const char *nptr);
+extern long long int atoll(const char *nptr);
+
+void f1(const char *in) {
+ int i;
+ long long ll;
+ unsigned int ui;
+ unsigned long long ull;
+ intmax_t im;
+ uintmax_t uim;
+ float f;
+ double d;
+ long double ld;
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'sscanf' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtol' instead [cert-err34-c]
+ sscanf(in, "%d", &i);
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'fscanf' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtoll' instead [cert-err34-c]
+ fscanf(stdin, "%lld", &ll);
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'sscanf' used to convert a string to an unsigned integer value, but function will not report conversion errors; consider using 'strtoul' instead [cert-err34-c]
+ sscanf(in, "%u", &ui);
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'fscanf' used to convert a string to an unsigned integer value, but function will not report conversion errors; consider using 'strtoull' instead [cert-err34-c]
+ fscanf(stdin, "%llu", &ull);
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtoimax' instead [cert-err34-c]
+ scanf("%jd", &im);
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'fscanf' used to convert a string to an unsigned integer value, but function will not report conversion errors; consider using 'strtoumax' instead [cert-err34-c]
+ fscanf(stdin, "%ju", &uim);
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'sscanf' used to convert a string to a floating-point value, but function will not report conversion errors; consider using 'strtof' instead [cert-err34-c]
+ sscanf(in, "%f", &f); // to float
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'fscanf' used to convert a string to a floating-point value, but function will not report conversion errors; consider using 'strtod' instead [cert-err34-c]
+ fscanf(stdin, "%lg", &d);
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'sscanf' used to convert a string to a floating-point value, but function will not report conversion errors; consider using 'strtold' instead [cert-err34-c]
+ sscanf(in, "%Le", &ld);
+
+ // These are conversions with other modifiers
+ short s;
+ char c;
+ size_t st;
+ ptrdiff_t pt;
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
+ scanf("%hhd", &c);
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
+ scanf("%hd", &s);
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
+ scanf("%zu", &st);
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
+ scanf("%td", &pt);
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
+ scanf("%o", ui);
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
+ scanf("%X", ui);
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
+ scanf("%x", ui);
+}
+
+void f2(const char *in) {
+ // CHECK-MESSAGES: :[[@LINE+1]]:11: warning: 'atoi' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtol' instead [cert-err34-c]
+ int i = atoi(in); // to int
+ // CHECK-MESSAGES: :[[@LINE+1]]:12: warning: 'atol' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtol' instead [cert-err34-c]
+ long l = atol(in); // to long
+ // CHECK-MESSAGES: :[[@LINE+1]]:18: warning: 'atoll' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtoll' instead [cert-err34-c]
+ long long ll = atoll(in); // to long long
+ // CHECK-MESSAGES: :[[@LINE+1]]:14: warning: 'atof' used to convert a string to a floating-point value, but function will not report conversion errors; consider using 'strtod' instead [cert-err34-c]
+ double d = atof(in); // to double
+}
+
+void f3(void) {
+ int i;
+ unsigned int u;
+ float f;
+ char str[32];
+
+ // Test that we don't report multiple infractions for a single call.
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
+ scanf("%d%u%f", &i, &u, &f);
+
+ // Test that we still catch infractions that are not the first specifier.
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
+ scanf("%s%d", str, &i);
+}
+
+void do_not_diagnose(void) {
+ char str[32];
+
+ scanf("%s", str); // Not a numerical conversion
+ scanf("%*d"); // Assignment suppressed
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-err34-c.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-err34-c.cpp
new file mode 100644
index 0000000..dde7dc1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-err34-c.cpp
@@ -0,0 +1,43 @@
+// RUN: %check_clang_tidy %s cert-err34-c %t -- -- -std=c++11
+
+typedef void * FILE;
+
+extern FILE *stdin;
+
+extern int fscanf(FILE * stream, const char * format, ...);
+extern int sscanf(const char * s, const char * format, ...);
+
+extern double atof(const char *nptr);
+extern int atoi(const char *nptr);
+extern long int atol(const char *nptr);
+extern long long int atoll(const char *nptr);
+
+namespace std {
+using ::FILE; using ::stdin;
+using ::fscanf; using ::sscanf;
+using ::atof; using ::atoi; using ::atol; using ::atoll;
+}
+
+void f1(const char *in) {
+ int i;
+ long long ll;
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'sscanf' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtol' instead [cert-err34-c]
+ std::sscanf(in, "%d", &i);
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'fscanf' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtoll' instead [cert-err34-c]
+ std::fscanf(std::stdin, "%lld", &ll);
+}
+
+void f2(const char *in) {
+ // CHECK-MESSAGES: :[[@LINE+1]]:11: warning: 'atoi' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtol' instead [cert-err34-c]
+ int i = std::atoi(in); // to int
+ // CHECK-MESSAGES: :[[@LINE+1]]:12: warning: 'atol' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtol' instead [cert-err34-c]
+ long l = std::atol(in); // to long
+
+ using namespace std;
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:18: warning: 'atoll' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtoll' instead [cert-err34-c]
+ long long ll = atoll(in); // to long long
+ // CHECK-MESSAGES: :[[@LINE+1]]:14: warning: 'atof' used to convert a string to a floating-point value, but function will not report conversion errors; consider using 'strtod' instead [cert-err34-c]
+ double d = atof(in); // to double
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-flp30-c.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-flp30-c.c
new file mode 100644
index 0000000..eee16be
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-flp30-c.c
@@ -0,0 +1,19 @@
+// RUN: %check_clang_tidy %s cert-flp30-c %t
+
+float g(void);
+
+void func(void) {
+ for (float x = 0.1f; x <= 1.0f; x += 0.1f) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: loop induction expression should not have floating-point type [cert-flp30-c]
+
+ float f = 1.0f;
+ for (; f > 0; --f) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: loop induction expression
+
+ for (;;g()) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: loop induction expression
+
+ for (int i = 0; i < 10; i += 1.0f) {}
+
+ for (int i = 0; i < 10; ++i) {}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-limited-randomness.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-limited-randomness.c
new file mode 100644
index 0000000..c8009b5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-limited-randomness.c
@@ -0,0 +1,13 @@
+// RUN: %check_clang_tidy %s cert-msc30-c %t
+
+extern int rand(void);
+int nonrand();
+
+int cTest() {
+ int i = rand();
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: rand() has limited randomness [cert-msc30-c]
+
+ int k = nonrand();
+
+ return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-limited-randomness.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-limited-randomness.cpp
new file mode 100644
index 0000000..845b735
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-limited-randomness.cpp
@@ -0,0 +1,28 @@
+// RUN: %check_clang_tidy %s cert-msc50-cpp %t
+
+int rand();
+int rand(int);
+
+namespace std {
+using ::rand;
+}
+
+namespace nonstd {
+ int rand();
+}
+
+void testFunction1() {
+ int i = std::rand();
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: rand() has limited randomness; use C++11 random library instead [cert-msc50-cpp]
+
+ int j = ::rand();
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: rand() has limited randomness; use C++11 random library instead [cert-msc50-cpp]
+
+ int k = rand(i);
+
+ int l = nonstd::rand();
+
+ int m = rand();
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: rand() has limited randomness; use C++11 random library instead [cert-msc50-cpp]
+}
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-msc32-c.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-msc32-c.c
new file mode 100644
index 0000000..6cc40fa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-msc32-c.c
@@ -0,0 +1,27 @@
+// RUN: %check_clang_tidy %s cert-msc32-c %t -- -config="{CheckOptions: [{key: cert-msc32-c.DisallowedSeedTypes, value: 'some_type,time_t'}]}" -- -std=c99
+
+void srand(int seed);
+typedef int time_t;
+time_t time(time_t *t);
+
+void f() {
+ srand(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc32-c]
+
+ const int a = 1;
+ srand(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc32-c]
+
+ time_t t;
+ srand(time(&t)); // Disallowed seed type
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc32-c]
+}
+
+void g() {
+ typedef int user_t;
+ user_t a = 1;
+ srand(a);
+
+ int b = 1;
+ srand(b); // Can not evaluate as int
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-msc51-cpp.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-msc51-cpp.cpp
new file mode 100644
index 0000000..8a8d778
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-msc51-cpp.cpp
@@ -0,0 +1,210 @@
+// RUN: %check_clang_tidy %s cert-msc51-cpp %t -- -config="{CheckOptions: [{key: cert-msc51-cpp.DisallowedSeedTypes, value: 'some_type,time_t'}]}" -- -std=c++11
+
+namespace std {
+
+void srand(int seed);
+
+template <class UIntType, UIntType a, UIntType c, UIntType m>
+struct linear_congruential_engine {
+ linear_congruential_engine(int _ = 0);
+ void seed(int _ = 0);
+};
+using default_random_engine = linear_congruential_engine<unsigned int, 1, 2, 3>;
+
+using size_t = int;
+template <class UIntType, size_t w, size_t n, size_t m, size_t r,
+ UIntType a, size_t u, UIntType d, size_t s,
+ UIntType b, size_t t,
+ UIntType c, size_t l, UIntType f>
+struct mersenne_twister_engine {
+ mersenne_twister_engine(int _ = 0);
+ void seed(int _ = 0);
+};
+using mt19937 = mersenne_twister_engine<unsigned int, 32, 624, 397, 21, 0x9908b0df, 11, 0xffffffff, 7, 0x9d2c5680, 15, 0xefc60000, 18, 1812433253>;
+
+template <class UIntType, size_t w, size_t s, size_t r>
+struct subtract_with_carry_engine {
+ subtract_with_carry_engine(int _ = 0);
+ void seed(int _ = 0);
+};
+using ranlux24_base = subtract_with_carry_engine<unsigned int, 24, 10, 24>;
+
+template <class Engine, size_t p, size_t r>
+struct discard_block_engine {
+ discard_block_engine();
+ discard_block_engine(int _);
+ void seed();
+ void seed(int _);
+};
+using ranlux24 = discard_block_engine<ranlux24_base, 223, 23>;
+
+template <class Engine, size_t w, class UIntType>
+struct independent_bits_engine {
+ independent_bits_engine();
+ independent_bits_engine(int _);
+ void seed();
+ void seed(int _);
+};
+using independent_bits = independent_bits_engine<ranlux24_base, 223, int>;
+
+template <class Engine, size_t k>
+struct shuffle_order_engine {
+ shuffle_order_engine();
+ shuffle_order_engine(int _);
+ void seed();
+ void seed(int _);
+};
+using shuffle_order = shuffle_order_engine<ranlux24_base, 223>;
+
+struct random_device {
+ random_device();
+ int operator()();
+};
+} // namespace std
+
+using time_t = unsigned int;
+time_t time(time_t *t);
+
+void f() {
+ const int seed = 2;
+ time_t t;
+
+ std::srand(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ std::srand(seed);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ std::srand(time(&t));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+ // One instantiation for every engine
+ std::default_random_engine engine1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+ std::default_random_engine engine2(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ std::default_random_engine engine3(seed);
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ std::default_random_engine engine4(time(&t));
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+ engine1.seed();
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+ engine1.seed(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ engine1.seed(seed);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ engine1.seed(time(&t));
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+ std::mt19937 engine5;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+ std::mt19937 engine6(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ std::mt19937 engine7(seed);
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ std::mt19937 engine8(time(&t));
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+ engine5.seed();
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+ engine5.seed(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ engine5.seed(seed);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ engine5.seed(time(&t));
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+ std::ranlux24_base engine9;
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+ std::ranlux24_base engine10(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ std::ranlux24_base engine11(seed);
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ std::ranlux24_base engine12(time(&t));
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+ engine9.seed();
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+ engine9.seed(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ engine9.seed(seed);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ engine9.seed(time(&t));
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+ std::ranlux24 engine13;
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+ std::ranlux24 engine14(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ std::ranlux24 engine15(seed);
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ std::ranlux24 engine16(time(&t));
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+ engine13.seed();
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+ engine13.seed(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ engine13.seed(seed);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ engine13.seed(time(&t));
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+ std::independent_bits engine17;
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+ std::independent_bits engine18(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ std::independent_bits engine19(seed);
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ std::independent_bits engine20(time(&t));
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+ engine17.seed();
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+ engine17.seed(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ engine17.seed(seed);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ engine17.seed(time(&t));
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+ std::shuffle_order engine21;
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+ std::shuffle_order engine22(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ std::shuffle_order engine23(seed);
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ std::shuffle_order engine24(time(&t));
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+ engine21.seed();
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+ engine21.seed(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ engine21.seed(seed);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+ engine21.seed(time(&t));
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+}
+
+struct A {
+ A(int _ = 0);
+ void seed(int _ = 0);
+};
+
+void g() {
+ int n = 1;
+ std::default_random_engine engine1(n);
+ std::mt19937 engine2(n);
+ std::ranlux24_base engine3(n);
+ std::ranlux24 engine4(n);
+ std::independent_bits engine5(n);
+ std::shuffle_order engine6(n);
+
+ std::random_device dev;
+ std::default_random_engine engine7(dev());
+ std::mt19937 engine8(dev());
+ std::ranlux24_base engine9(dev());
+ std::ranlux24 engine10(dev());
+ std::independent_bits engine11(dev());
+ std::shuffle_order engine12(dev());
+
+ A a1;
+ A a2(1);
+ a1.seed();
+ a1.seed(1);
+ a1.seed(n);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-oop11-cpp.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-oop11-cpp.cpp
new file mode 100644
index 0000000..650d6ec
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-oop11-cpp.cpp
@@ -0,0 +1,21 @@
+// RUN: %check_clang_tidy %s cert-oop11-cpp %t -- -- -std=c++11
+
+struct B {
+ B(B&&) noexcept = default;
+
+ B(const B &) = default;
+ B& operator=(const B&) = default;
+ ~B() {}
+};
+
+struct D {
+ B b;
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:14: warning: move constructor initializes class member by calling a copy constructor [cert-oop11-cpp]
+ D(D &&d) : b(d.b) {}
+
+ // This should not produce a diagnostic because it is not covered under
+ // the CERT guideline for OOP11-CPP. However, this will produce a diagnostic
+ // under performance-move-constructor-init.
+ D(B b) : b(b) {}
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-setlongjmp.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-setlongjmp.cpp
new file mode 100644
index 0000000..1bf5444
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-setlongjmp.cpp
@@ -0,0 +1,26 @@
+// RUN: %check_clang_tidy %s cert-err52-cpp %t -- -- -std=c++11
+
+typedef void *jmp_buf;
+extern int __setjmpimpl(jmp_buf);
+#define setjmp(x) __setjmpimpl(x)
+[[noreturn]] extern void longjmp(jmp_buf, int);
+
+namespace std {
+using ::jmp_buf;
+using ::longjmp;
+}
+
+static jmp_buf env;
+void g() {
+ std::longjmp(env, 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not call 'longjmp'; consider using exception handling instead [cert-err52-cpp]
+ ::longjmp(env, 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not call 'longjmp'; consider using exception handling instead
+ longjmp(env, 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not call 'longjmp'; consider using exception handling instead
+}
+
+void f() {
+ (void)setjmp(env);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not call 'setjmp'; consider using exception handling instead
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-static-object-exception.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-static-object-exception.cpp
new file mode 100644
index 0000000..aa34bbd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-static-object-exception.cpp
@@ -0,0 +1,225 @@
+// RUN: clang-tidy %s -checks="-*,cert-err58-cpp" -- -std=c++11 -target x86_64-pc-linux-gnu \
+// RUN: | FileCheck %s -check-prefix=CHECK-EXCEPTIONS \
+// RUN: -implicit-check-not="{{warning|error}}:"
+// RUN: clang-tidy %s -checks="-*,cert-err58-cpp" -- -fno-exceptions -std=c++11 -target x86_64-pc-linux-gnu \
+// RUN: | FileCheck %s -allow-empty -check-prefix=CHECK-NONEXCEPTIONS \
+// RUN: -implicit-check-not="{{warning|error}}:"
+
+struct S {
+ S() noexcept(false);
+};
+
+struct T {
+ T() noexcept;
+};
+
+struct U {
+ U() {}
+};
+
+struct V {
+ explicit V(const char *) {} // Can throw
+};
+
+struct Cleanup {
+ ~Cleanup() {}
+};
+
+struct W {
+ W(Cleanup c = {}) noexcept(false);
+};
+
+struct X {
+ X(S = {}) noexcept;
+};
+
+struct Y {
+ S s;
+};
+
+struct Z {
+ T t;
+};
+
+int f();
+int g() noexcept(false);
+int h() noexcept(true);
+
+struct UserConv_Bad {
+ operator int() noexcept(false);
+};
+
+struct UserConv_Good {
+ operator int() noexcept;
+};
+
+UserConv_Bad some_bad_func() noexcept;
+UserConv_Good some_good_func() noexcept;
+
+S s;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 's' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]
+// CHECK-EXCEPTIONS: 9:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+T t; // ok
+U u;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'u' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 17:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+V v("v");
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'v' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 21:12: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+W w;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'w' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 29:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+X x1(S{});
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'x1' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 9:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+X x2;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'x2' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 9:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+Y y;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'y' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 36:8: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+Z z;
+
+int i = f();
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:5: warning: initialization of 'i' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 44:5: note: possibly throwing function declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+int j = g();
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:5: warning: initialization of 'j' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 45:5: note: possibly throwing function declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+int k = h();
+int l = some_bad_func();
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:5: warning: initialization of 'l' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 49:3: note: possibly throwing function declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+int m = some_good_func();
+
+typedef decltype(sizeof(int)) size_t;
+inline void *operator new(size_t sz, void *here) noexcept { return here; }
+char n[sizeof(int)];
+int *o = new (n) int();
+int *p = new int();
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:6: warning: initialization of 'p' with static storage duration may throw an exception that cannot be caught
+// CHECK-NONEXCEPTIONS-NOT: warning:
+
+thread_local S s3;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 's3' with thread_local storage duration may throw an exception that cannot be caught
+// CHECK-NONEXCEPTIONS-NOT: warning:
+thread_local T t3; // ok
+thread_local U u3;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 'u3' with thread_local storage duration may throw an exception that cannot be caught
+// CHECK-NONEXCEPTIONS-NOT: warning:
+thread_local V v3("v");
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 'v3' with thread_local storage duration may throw an exception that cannot be caught
+// CHECK-NONEXCEPTIONS-NOT: warning:
+thread_local W w3;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 'w3' with thread_local storage duration may throw an exception that cannot be caught
+// CHECK-NONEXCEPTIONS-NOT: warning:
+
+void f(S s1, T t1, U u1, V v1, W w1) { // ok, ok, ok, ok, ok
+ S s2; // ok
+ T t2; // ok
+ U u2; // ok
+ V v2("v"); // ok
+ W w2; // ok
+
+ thread_local S s3; // ok
+ thread_local T t3; // ok
+ thread_local U u3; // ok
+ thread_local V v3("v"); // ok
+ thread_local W w3; // ok
+
+ static S s4; // ok
+ static T t4; // ok
+ static U u4; // ok
+ static V v4("v"); // ok
+ static W w4; // ok
+}
+
+namespace {
+S s;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 's' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]
+// CHECK-EXCEPTIONS: 9:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+T t; // ok
+U u;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'u' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 17:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+V v("v");
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'v' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 21:12: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+W w;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'w' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 29:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+
+thread_local S s3;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 's3' with thread_local storage duration may throw an exception that cannot be caught
+// CHECK-NONEXCEPTIONS-NOT: warning:
+thread_local T t3; // ok
+thread_local U u3;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 'u3' with thread_local storage duration may throw an exception that cannot be caught
+// CHECK-NONEXCEPTIONS-NOT: warning:
+thread_local V v3("v");
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 'v3' with thread_local storage duration may throw an exception that cannot be caught
+// CHECK-NONEXCEPTIONS-NOT: warning:
+thread_local W w3;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 'w3' with thread_local storage duration may throw an exception that cannot be caught
+// CHECK-NONEXCEPTIONS-NOT: warning:
+}; // namespace
+
+class Statics {
+ static S s; // warn when initialized
+ static T t; // ok
+ static U u; // warn when initialized
+ static V v; // warn when initialized
+ static W w; // warn when initialized
+
+ void f(S s, T t, U u, V v) {
+ S s2; // ok
+ T t2; // ok
+ U u2; // ok
+ V v2("v"); // ok
+ W w2; // ok
+
+ thread_local S s3; // ok
+ thread_local T t3; // ok
+ thread_local U u3; // ok
+ thread_local V v3("v"); // ok
+ thread_local W w3; // ok
+
+ static S s4; // ok
+ static T t4; // ok
+ static U u4; // ok
+ static V v4("v"); // ok
+ static W w4; // ok
+ }
+};
+
+S Statics::s;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:12: warning: initialization of 's' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]
+// CHECK-EXCEPTIONS: 9:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+T Statics::t;
+U Statics::u;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:12: warning: initialization of 'u' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 17:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+V Statics::v("v");
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:12: warning: initialization of 'v' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 21:12: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+W Statics::w;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:12: warning: initialization of 'w' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 29:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-throw-exception-type.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-throw-exception-type.cpp
new file mode 100644
index 0000000..2ff9be5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-throw-exception-type.cpp
@@ -0,0 +1,127 @@
+// RUN: %check_clang_tidy %s cert-err60-cpp %t -- -- -std=c++11 -fcxx-exceptions
+
+struct S {};
+struct T : S {};
+struct U {
+ U() = default;
+ U(const U&) = default;
+};
+
+struct V {
+ V() = default;
+ V(const V&) noexcept;
+};
+
+struct W {
+ W() = default;
+ W(const W&) noexcept(false);
+};
+
+struct X {
+ X() = default;
+ X(const X&) {}
+};
+
+struct Y {
+ Y() = default;
+ Y(const Y&) throw();
+};
+
+struct Z {
+ Z() = default;
+ Z(const Z&) throw(int);
+};
+
+void g() noexcept(false);
+
+struct A {
+ A() = default;
+ A(const A&) noexcept(noexcept(g()));
+};
+
+struct B {
+ B() = default;
+ B(const B&) = default;
+ B(const A&) noexcept(false);
+};
+
+class C {
+ W M; // W is not no-throw copy constructible
+public:
+ C() = default;
+ C(const C&) = default;
+};
+
+struct D {
+ D() = default;
+ D(const D&) noexcept(false);
+ D(D&) noexcept(true);
+};
+
+struct E {
+ E() = default;
+ E(E&) noexcept(true);
+ E(const E&) noexcept(false);
+};
+
+struct Allocates {
+ int *x;
+ Allocates() : x(new int(0)) {}
+ Allocates(const Allocates &other) : x(new int(*other.x)) {}
+};
+
+struct OptionallyAllocates {
+ int *x;
+ OptionallyAllocates() : x(new int(0)) {}
+ OptionallyAllocates(const Allocates &other) noexcept(true) {
+ try {
+ x = new int(*other.x);
+ } catch (...) {
+ x = nullptr;
+ }
+ }
+};
+
+void f() {
+ throw 12; // ok
+ throw "test"; // ok
+ throw S(); // ok
+ throw T(); // ok
+ throw U(); // ok
+ throw V(); // ok
+ throw W(); // match, noexcept(false)
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible [cert-err60-cpp]
+ throw X(); // match, no noexcept clause, nontrivial
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible
+ throw Y(); // ok
+ throw Z(); // match, throw(int)
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible
+ throw A(); // match, noexcept(false)
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible
+ throw B(); // ok
+ throw C(); // match, C has a member variable that makes it throwing on copy
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible
+ throw D(); // match, has throwing copy constructor
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible
+ throw E(); // match, has throwing copy constructor
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible
+ throw Allocates(); // match, copy constructor throws
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible
+ throw OptionallyAllocates(); // ok
+}
+
+namespace PR25574 {
+struct B {
+ B(const B&) noexcept;
+};
+
+struct D : B {
+ D();
+ virtual ~D() noexcept;
+};
+
+template <typename T>
+void f() {
+ throw D();
+}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-variadic-function-def.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-variadic-function-def.cpp
new file mode 100644
index 0000000..6b2421b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-variadic-function-def.cpp
@@ -0,0 +1,24 @@
+// RUN: %check_clang_tidy %s cert-dcl50-cpp %t
+
+// Variadic function definitions are diagnosed.
+void f1(int, ...) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: do not define a C-style variadic function; consider using a function parameter pack or currying instead [cert-dcl50-cpp]
+
+// Variadic function *declarations* are not diagnosed.
+void f2(int, ...); // ok
+
+// Function parameter packs are good, however.
+template <typename Arg, typename... Ts>
+void f3(Arg F, Ts... Rest) {}
+
+struct S {
+ void f(int, ...); // ok
+ void f1(int, ...) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: do not define a C-style variadic function; consider using a function parameter pack or currying instead
+};
+
+// Function definitions that are extern "C" are good.
+extern "C" void f4(int, ...) {} // ok
+extern "C" {
+ void f5(int, ...) {} // ok
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/check_clang_tidy.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/check_clang_tidy.cpp
new file mode 100644
index 0000000..5c1bf92
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/check_clang_tidy.cpp
@@ -0,0 +1,21 @@
+// RUN: %check_clang_tidy -check-suffix=USING-A %s misc-unused-using-decls %t -- -- -DUSING_A
+// RUN: %check_clang_tidy -check-suffix=USING-B %s misc-unused-using-decls %t -- -- -DUSING_B
+// RUN: %check_clang_tidy %s misc-unused-using-decls %t
+
+namespace a {class A {}; class B {}; class C {}; }
+namespace b {
+#if defined(USING_A)
+using a::A;
+#elif defined(USING_B)
+using a::B;
+#else
+using a::C;
+#endif
+}
+namespace c {}
+// CHECK-MESSAGES-USING-A: :[[@LINE-8]]:10: warning: using decl 'A' {{.*}}
+// CHECK-MESSAGES-USING-B: :[[@LINE-7]]:10: warning: using decl 'B' {{.*}}
+// CHECK-MESSAGES: :[[@LINE-6]]:10: warning: using decl 'C' {{.*}}
+// CHECK-FIXES-USING-A-NOT: using a::A;$
+// CHECK-FIXES-USING-B-NOT: using a::B;$
+// CHECK-FIXES-NOT: using a::C;$
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/check_clang_tidy.py b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/check_clang_tidy.py
new file mode 100755
index 0000000..bb2c5a2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/check_clang_tidy.py
@@ -0,0 +1,160 @@
+#!/usr/bin/env python
+#
+#===- check_clang_tidy.py - ClangTidy Test Helper ------------*- python -*--===#
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+r"""
+ClangTidy Test Helper
+=====================
+
+This script runs clang-tidy in fix mode and verify fixes, messages or both.
+
+Usage:
+ check_clang_tidy.py [-resource-dir=<resource-dir>] \
+ [-assume-filename=<file-with-source-extension>] \
+ [-check-suffix=<file-check-suffix>] \
+ <source-file> <check-name> <temp-file> \
+ -- [optional clang-tidy arguments]
+
+Example:
+ // RUN: %check_clang_tidy %s llvm-include-order %t -- -- -isystem %S/Inputs
+"""
+
+import argparse
+import os
+import re
+import subprocess
+import sys
+
+
+def write_file(file_name, text):
+ with open(file_name, 'w') as f:
+ f.write(text)
+ f.truncate()
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-expect-clang-tidy-error', action='store_true')
+ parser.add_argument('-resource-dir')
+ parser.add_argument('-assume-filename')
+ parser.add_argument('-check-suffix', default='')
+ parser.add_argument('input_file_name')
+ parser.add_argument('check_name')
+ parser.add_argument('temp_file_name')
+
+ args, extra_args = parser.parse_known_args()
+
+ resource_dir = args.resource_dir
+ assume_file_name = args.assume_filename
+ input_file_name = args.input_file_name
+ check_name = args.check_name
+ temp_file_name = args.temp_file_name
+ expect_clang_tidy_error = args.expect_clang_tidy_error
+
+ file_name_with_extension = assume_file_name or input_file_name
+ _, extension = os.path.splitext(file_name_with_extension)
+ if extension not in ['.c', '.hpp', '.m', '.mm']:
+ extension = '.cpp'
+ temp_file_name = temp_file_name + extension
+
+ clang_tidy_extra_args = extra_args
+ if len(clang_tidy_extra_args) == 0:
+ clang_tidy_extra_args = ['--']
+ if extension in ['.cpp', '.hpp', '.mm']:
+ clang_tidy_extra_args.append('--std=c++11')
+ if extension in ['.m', '.mm']:
+ clang_tidy_extra_args.extend(
+ ['-fobjc-abi-version=2', '-fobjc-arc'])
+
+ if args.check_suffix and not re.match('^[A-Z0-9\-]+$', args.check_suffix):
+ sys.exit('Only A..Z, 0..9 and "-" are allowed in check suffix, but "%s" was given' % (args.check_suffix))
+
+ file_check_suffix = ('-' + args.check_suffix) if args.check_suffix else ''
+ check_fixes_prefix = 'CHECK-FIXES' + file_check_suffix
+ check_messages_prefix = 'CHECK-MESSAGES' + file_check_suffix
+
+ # Tests should not rely on STL being available, and instead provide mock
+ # implementations of relevant APIs.
+ clang_tidy_extra_args.append('-nostdinc++')
+
+ if resource_dir is not None:
+ clang_tidy_extra_args.append('-resource-dir=%s' % resource_dir)
+
+ with open(input_file_name, 'r') as input_file:
+ input_text = input_file.read()
+
+ has_check_fixes = check_fixes_prefix in input_text
+ has_check_messages = check_messages_prefix in input_text
+
+ if not has_check_fixes and not has_check_messages:
+ sys.exit('Neither %s nor %s found in the input' % (check_fixes_prefix, check_messages_prefix) )
+
+ # Remove the contents of the CHECK lines to avoid CHECKs matching on
+ # themselves. We need to keep the comments to preserve line numbers while
+ # avoiding empty lines which could potentially trigger formatting-related
+ # checks.
+ cleaned_test = re.sub('// *CHECK-[A-Z0-9\-]*:[^\r\n]*', '//', input_text)
+
+ write_file(temp_file_name, cleaned_test)
+
+ original_file_name = temp_file_name + ".orig"
+ write_file(original_file_name, cleaned_test)
+
+ args = ['clang-tidy', temp_file_name, '-fix', '--checks=-*,' + check_name] + \
+ clang_tidy_extra_args
+ if expect_clang_tidy_error:
+ args.insert(0, 'not')
+ print('Running ' + repr(args) + '...')
+ try:
+ clang_tidy_output = \
+ subprocess.check_output(args, stderr=subprocess.STDOUT).decode()
+ except subprocess.CalledProcessError as e:
+ print('clang-tidy failed:\n' + e.output.decode())
+ raise
+
+ print('------------------------ clang-tidy output -----------------------\n' +
+ clang_tidy_output +
+ '\n------------------------------------------------------------------')
+
+ try:
+ diff_output = subprocess.check_output(
+ ['diff', '-u', original_file_name, temp_file_name],
+ stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ diff_output = e.output
+
+ print('------------------------------ Fixes -----------------------------\n' +
+ diff_output.decode() +
+ '\n------------------------------------------------------------------')
+
+ if has_check_fixes:
+ try:
+ subprocess.check_output(
+ ['FileCheck', '-input-file=' + temp_file_name, input_file_name,
+ '-check-prefix=' + check_fixes_prefix, '-strict-whitespace'],
+ stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ print('FileCheck failed:\n' + e.output.decode())
+ raise
+
+ if has_check_messages:
+ messages_file = temp_file_name + '.msg'
+ write_file(messages_file, clang_tidy_output)
+ try:
+ subprocess.check_output(
+ ['FileCheck', '-input-file=' + messages_file, input_file_name,
+ '-check-prefix=' + check_messages_prefix,
+ '-implicit-check-not={{warning|error}}:'],
+ stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ print('FileCheck failed:\n' + e.output.decode())
+ raise
+
+if __name__ == '__main__':
+ main()
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-__clang_analyzer__macro.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-__clang_analyzer__macro.cpp
new file mode 100644
index 0000000..0fda1a3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-__clang_analyzer__macro.cpp
@@ -0,0 +1,5 @@
+// RUN: clang-tidy %s -checks=-*,modernize-use-nullptr -- | count 0
+
+#if !defined(__clang_analyzer__)
+#error __clang_analyzer__ is not defined
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-diff.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-diff.cpp
new file mode 100644
index 0000000..146287b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-diff.cpp
@@ -0,0 +1,27 @@
+// REQUIRES: shell
+// RUN: sed 's/placeholder_for_f/f/' %s > %t.cpp
+// RUN: clang-tidy -checks=-*,modernize-use-override %t.cpp -- -std=c++11 | FileCheck -check-prefix=CHECK-SANITY %s
+// RUN: not diff -U0 %s %t.cpp | %clang_tidy_diff -checks=-*,modernize-use-override -- -std=c++11 2>&1 | FileCheck %s
+// RUN: not diff -U0 %s %t.cpp | %clang_tidy_diff -checks=-*,modernize-use-override -quiet -- -std=c++11 2>&1 | FileCheck -check-prefix=CHECK-QUIET %s
+// RUN: mkdir -p %T/compilation-database-test/
+// RUN: echo '[{"directory": "%T", "command": "clang++ -o test.o -std=c++11 %t.cpp", "file": "%t.cpp"}]' > %T/compilation-database-test/compile_commands.json
+// RUN: not diff -U0 %s %t.cpp | %clang_tidy_diff -checks=-*,modernize-use-override -path %T/compilation-database-test 2>&1 | FileCheck -check-prefix=CHECK %s
+struct A {
+ virtual void f() {}
+ virtual void g() {}
+};
+// CHECK-NOT: warning:
+// CHECK-QUIET-NOT: warning:
+struct B : public A {
+ void placeholder_for_f() {}
+// CHECK-SANITY: [[@LINE-1]]:8: warning: annotate this
+// CHECK: [[@LINE-2]]:8: warning: annotate this
+// CHECK-QUIET: [[@LINE-3]]:8: warning: annotate this
+ void g() {}
+// CHECK-SANITY: [[@LINE-1]]:8: warning: annotate this
+// CHECK-NOT: warning:
+// CHECK-QUIET-NOT: warning:
+};
+// CHECK-SANITY-NOT: Suppressed
+// CHECK: Suppressed 1 warnings (1 due to line filter).
+// CHECK-QUIET-NOT: Suppressed
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-enable-check-profile-one-tu.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-enable-check-profile-one-tu.cpp
new file mode 100644
index 0000000..df4cb93
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-enable-check-profile-one-tu.cpp
@@ -0,0 +1,24 @@
+// RUN: clang-tidy -enable-check-profile -checks='-*,readability-function-size' %s -- 2>&1 | FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' %s
+
+// CHECK: ===-------------------------------------------------------------------------===
+// CHECK-NEXT: clang-tidy checks profiling
+// CHECK-NEXT: ===-------------------------------------------------------------------------===
+// CHECK-NEXT: Total Execution Time: {{.*}} seconds ({{.*}} wall clock)
+
+// CHECK: {{.*}} --- Name ---
+// CHECK-NEXT: {{.*}} readability-function-size
+// CHECK-NEXT: {{.*}} Total
+
+// CHECK-NOT: ===-------------------------------------------------------------------------===
+// CHECK-NOT: clang-tidy checks profiling
+// CHECK-NOT: ===-------------------------------------------------------------------------===
+// CHECK-NOT: Total Execution Time: {{.*}} seconds ({{.*}} wall clock)
+
+// CHECK-NOT: {{.*}} --- Name ---
+// CHECK-NOT: {{.*}} readability-function-size
+// CHECK-NOT: {{.*}} Total
+
+class A {
+ A() {}
+ ~A() {}
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-enable-check-profile-two-tu.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-enable-check-profile-two-tu.cpp
new file mode 100644
index 0000000..30603a2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-enable-check-profile-two-tu.cpp
@@ -0,0 +1,33 @@
+// RUN: clang-tidy -enable-check-profile -checks='-*,readability-function-size' %s %s -- 2>&1 | FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' %s
+
+// CHECK: ===-------------------------------------------------------------------------===
+// CHECK-NEXT: clang-tidy checks profiling
+// CHECK-NEXT: ===-------------------------------------------------------------------------===
+// CHECK-NEXT: Total Execution Time: {{.*}} seconds ({{.*}} wall clock)
+
+// CHECK: {{.*}} --- Name ---
+// CHECK-NEXT: {{.*}} readability-function-size
+// CHECK-NEXT: {{.*}} Total
+
+// CHECK: ===-------------------------------------------------------------------------===
+// CHECK-NEXT: clang-tidy checks profiling
+// CHECK-NEXT: ===-------------------------------------------------------------------------===
+// CHECK-NEXT: Total Execution Time: {{.*}} seconds ({{.*}} wall clock)
+
+// CHECK: {{.*}} --- Name ---
+// CHECK-NEXT: {{.*}} readability-function-size
+// CHECK-NEXT: {{.*}} Total
+
+// CHECK-NOT: ===-------------------------------------------------------------------------===
+// CHECK-NOT: clang-tidy checks profiling
+// CHECK-NOT: ===-------------------------------------------------------------------------===
+// CHECK-NOT: Total Execution Time: {{.*}} seconds ({{.*}} wall clock)
+
+// CHECK-NOT: {{.*}} --- Name ---
+// CHECK-NOT: {{.*}} readability-function-size
+// CHECK-NOT: {{.*}} Total
+
+class A {
+ A() {}
+ ~A() {}
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-run-with-database.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-run-with-database.cpp
new file mode 100644
index 0000000..05bc14c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-run-with-database.cpp
@@ -0,0 +1,23 @@
+// RUN: mkdir -p %T/compilation-database-test/include
+// RUN: mkdir -p %T/compilation-database-test/a
+// RUN: mkdir -p %T/compilation-database-test/b
+// RUN: echo 'int *AA = 0;' > %T/compilation-database-test/a/a.cpp
+// RUN: echo 'int *AB = 0;' > %T/compilation-database-test/a/b.cpp
+// RUN: echo 'int *BB = 0;' > %T/compilation-database-test/b/b.cpp
+// RUN: echo 'int *BC = 0;' > %T/compilation-database-test/b/c.cpp
+// RUN: echo 'int *HP = 0;' > %T/compilation-database-test/include/header.h
+// RUN: echo '#include "header.h"' > %T/compilation-database-test/b/d.cpp
+// RUN: sed 's|test_dir|%/T/compilation-database-test|g' %S/Inputs/compilation-database/template.json > %T/compile_commands.json
+// RUN: clang-tidy --checks=-*,modernize-use-nullptr -p %T %T/compilation-database-test/b/not-exist -header-filter=.*
+// RUN: clang-tidy --checks=-*,modernize-use-nullptr -p %T %T/compilation-database-test/a/a.cpp %T/compilation-database-test/a/b.cpp %T/compilation-database-test/b/b.cpp %T/compilation-database-test/b/c.cpp %T/compilation-database-test/b/d.cpp -header-filter=.* -fix
+// RUN: FileCheck -input-file=%T/compilation-database-test/a/a.cpp %s -check-prefix=CHECK-FIX1
+// RUN: FileCheck -input-file=%T/compilation-database-test/a/b.cpp %s -check-prefix=CHECK-FIX2
+// RUN: FileCheck -input-file=%T/compilation-database-test/b/b.cpp %s -check-prefix=CHECK-FIX3
+// RUN: FileCheck -input-file=%T/compilation-database-test/b/c.cpp %s -check-prefix=CHECK-FIX4
+// RUN: FileCheck -input-file=%T/compilation-database-test/include/header.h %s -check-prefix=CHECK-FIX5
+
+// CHECK-FIX1: int *AA = nullptr;
+// CHECK-FIX2: int *AB = nullptr;
+// CHECK-FIX3: int *BB = nullptr;
+// CHECK-FIX4: int *BC = nullptr;
+// CHECK-FIX5: int *HP = nullptr;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-store-check-profile-one-tu.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-store-check-profile-one-tu.cpp
new file mode 100644
index 0000000..832723b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-store-check-profile-one-tu.cpp
@@ -0,0 +1,37 @@
+// RUN: rm -rf %T/out
+// RUN: clang-tidy -enable-check-profile -checks='-*,readability-function-size' -store-check-profile=%T/out %s -- 2>&1 | not FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' -check-prefix=CHECK-CONSOLE %s
+// RUN: cat %T/out/*-clang-tidy-store-check-profile-one-tu.cpp.json | FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' -check-prefix=CHECK-FILE %s
+// RUN: rm -rf %T/out
+// RUN: clang-tidy -enable-check-profile -checks='-*,readability-function-size' -store-check-profile=%T/out %s -- 2>&1
+// RUN: cat %T/out/*-clang-tidy-store-check-profile-one-tu.cpp.json | FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' -check-prefix=CHECK-FILE %s
+
+// CHECK-CONSOLE-NOT: ===-------------------------------------------------------------------------===
+// CHECK-CONSOLE-NOT: {{.*}} --- Name ---
+// CHECK-CONSOLE-NOT: {{.*}} readability-function-size
+// CHECK-CONSOLE-NOT: {{.*}} Total
+// CHECK-CONSOLE-NOT: ===-------------------------------------------------------------------------===
+
+// CHECK-FILE: {
+// CHECK-FILE-NEXT:"file": "{{.*}}clang-tidy-store-check-profile-one-tu.cpp",
+// CHECK-FILE-NEXT:"timestamp": "{{[0-9]+}}-{{[0-9]+}}-{{[0-9]+}} {{[0-9]+}}:{{[0-9]+}}:{{[0-9]+}}.{{[0-9]+}}",
+// CHECK-FILE-NEXT:"profile": {
+// CHECK-FILE-NEXT: "time.clang-tidy.readability-function-size.wall": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}},
+// CHECK-FILE-NEXT: "time.clang-tidy.readability-function-size.user": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}},
+// CHECK-FILE-NEXT: "time.clang-tidy.readability-function-size.sys": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}}
+// CHECK-FILE-NEXT: }
+// CHECK-FILE-NEXT: }
+
+// CHECK-FILE-NOT: {
+// CHECK-FILE-NOT: "file": {{.*}}clang-tidy-store-check-profile-one-tu.cpp{{.*}},
+// CHECK-FILE-NOT: "timestamp": "{{[0-9]+}}-{{[0-9]+}}-{{[0-9]+}} {{[0-9]+}}:{{[0-9]+}}:{{[0-9]+}}.{{[0-9]+}}",
+// CHECK-FILE-NOT: "profile": {
+// CHECK-FILE-NOT: "time.clang-tidy.readability-function-size.wall": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}},
+// CHECK-FILE-NOT: "time.clang-tidy.readability-function-size.user": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}},
+// CHECK-FILE-NOT: "time.clang-tidy.readability-function-size.sys": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}}
+// CHECK-FILE-NOT: }
+// CHECK-FILE-NOT: }
+
+class A {
+ A() {}
+ ~A() {}
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clean-up-code.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clean-up-code.cpp
new file mode 100644
index 0000000..15873ed
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clean-up-code.cpp
@@ -0,0 +1,14 @@
+// RUN: %check_clang_tidy %s misc-unused-using-decls %t
+// RUN: %check_clang_tidy %s misc-unused-using-decls %t -- -format-style=none --
+// RUN: %check_clang_tidy %s misc-unused-using-decls %t -- -format-style=llvm --
+namespace a { class A {}; }
+namespace b {
+using a::A;
+}
+namespace c {}
+// CHECK-MESSAGES: :[[@LINE-3]]:10: warning: using decl 'A' is unused [misc-unused-using-decls]
+// CHECK-FIXES: {{^namespace a { class A {}; }$}}
+// CHECK-FIXES-NOT: namespace
+// CHECK-FIXES: {{^namespace c {}$}}
+// FIXME: cleanupAroundReplacements leaves whitespace. Otherwise we could just
+// check the next line.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/config-files.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/config-files.cpp
new file mode 100644
index 0000000..65ac54a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/config-files.cpp
@@ -0,0 +1,12 @@
+// RUN: clang-tidy -dump-config %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=CHECK-BASE
+// CHECK-BASE: Checks: {{.*}}from-parent
+// CHECK-BASE: HeaderFilterRegex: parent
+// RUN: clang-tidy -dump-config %S/Inputs/config-files/1/- -- | FileCheck %s -check-prefix=CHECK-CHILD1
+// CHECK-CHILD1: Checks: {{.*}}from-child1
+// CHECK-CHILD1: HeaderFilterRegex: child1
+// RUN: clang-tidy -dump-config %S/Inputs/config-files/2/- -- | FileCheck %s -check-prefix=CHECK-CHILD2
+// CHECK-CHILD2: Checks: {{.*}}from-parent
+// CHECK-CHILD2: HeaderFilterRegex: parent
+// RUN: clang-tidy -dump-config -checks='from-command-line' -header-filter='from command line' %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=CHECK-COMMAND-LINE
+// CHECK-COMMAND-LINE: Checks: {{.*}}from-parent,from-command-line
+// CHECK-COMMAND-LINE: HeaderFilterRegex: from command line
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-avoid-goto.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-avoid-goto.cpp
new file mode 100644
index 0000000..213947f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-avoid-goto.cpp
@@ -0,0 +1,139 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-avoid-goto %t
+
+void noop() {}
+
+int main() {
+ noop();
+ goto jump_to_me;
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: avoid using 'goto' for flow control
+ // CHECK-MESSAGES: [[@LINE+3]]:1: note: label defined here
+ noop();
+
+jump_to_me:;
+
+jump_backwards:;
+ noop();
+ goto jump_backwards;
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: avoid using 'goto' for flow control
+ // CHECK-MESSAGES: [[@LINE-4]]:1: note: label defined here
+
+ goto jump_in_line;
+ ;
+jump_in_line:;
+ // CHECK-MESSAGES: [[@LINE-3]]:3: warning: avoid using 'goto' for flow control
+ // CHECK-MESSAGES: [[@LINE-2]]:1: note: label defined here
+
+ // Test the GNU extension https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
+some_label:;
+ void *dynamic_label = &&some_label;
+
+ // FIXME: `IndirectGotoStmt` is not detected.
+ goto *dynamic_label;
+}
+
+void forward_jump_out_nested_loop() {
+ int array[] = {1, 2, 3, 4, 5};
+ for (int i = 0; i < 10; ++i) {
+ noop();
+ for (int j = 0; j < 10; ++j) {
+ noop();
+ if (i + j > 10)
+ goto early_exit1;
+ }
+ noop();
+ }
+
+ for (int i = 0; i < 10; ++i) {
+ noop();
+ while (true) {
+ noop();
+ if (i > 5)
+ goto early_exit1;
+ }
+ noop();
+ }
+
+ for (auto value : array) {
+ noop();
+ for (auto number : array) {
+ noop();
+ if (number == 5)
+ goto early_exit1;
+ }
+ }
+
+ do {
+ noop();
+ do {
+ noop();
+ goto early_exit1;
+ } while (true);
+ } while (true);
+
+ do {
+ for (auto number : array) {
+ noop();
+ if (number == 2)
+ goto early_exit1;
+ }
+ } while (true);
+
+ // Jumping further results in error, because the variable declaration would
+ // be skipped.
+early_exit1:;
+
+ int i = 0;
+ while (true) {
+ noop();
+ while (true) {
+ noop();
+ if (i > 5)
+ goto early_exit2;
+ i++;
+ }
+ noop();
+ }
+
+ while (true) {
+ noop();
+ for (int j = 0; j < 10; ++j) {
+ noop();
+ if (j > 5)
+ goto early_exit2;
+ }
+ noop();
+ }
+
+ while (true) {
+ noop();
+ for (auto number : array) {
+ if (number == 1)
+ goto early_exit2;
+ noop();
+ }
+ }
+
+ while (true) {
+ noop();
+ do {
+ noop();
+ goto early_exit2;
+ } while (true);
+ }
+early_exit2:;
+}
+
+void jump_out_backwards() {
+
+before_the_loop:
+ noop();
+
+ for (int i = 0; i < 10; ++i) {
+ for (int j = 0; j < 10; ++j) {
+ if (i * j > 80)
+ goto before_the_loop;
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: avoid using 'goto' for flow control
+ // CHECK-MESSAGES: [[@LINE-8]]:1: note: label defined here
+ }
+ }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-interfaces-global-init.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-interfaces-global-init.cpp
new file mode 100644
index 0000000..51f79e5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-interfaces-global-init.cpp
@@ -0,0 +1,84 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-interfaces-global-init %t
+
+constexpr int makesInt() { return 3; }
+constexpr int takesInt(int i) { return i + 1; }
+constexpr int takesIntPtr(int *i) { return *i; }
+
+extern int ExternGlobal;
+static int GlobalScopeBadInit1 = ExternGlobal;
+// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
+static int GlobalScopeBadInit2 = takesInt(ExternGlobal);
+// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
+static int GlobalScopeBadInit3 = takesIntPtr(&ExternGlobal);
+// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
+static int GlobalScopeBadInit4 = 3 * (ExternGlobal + 2);
+// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
+
+namespace ns {
+static int NamespaceScope = makesInt();
+static int NamespaceScopeBadInit = takesInt(ExternGlobal);
+// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
+
+struct A {
+ static int ClassScope;
+ static int ClassScopeBadInit;
+};
+
+int A::ClassScopeBadInit = takesInt(ExternGlobal);
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
+
+static int FromClassBadInit = takesInt(A::ClassScope);
+// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ClassScope'
+} // namespace ns
+
+// "const int B::I;" is fine, it just ODR-defines B::I. See [9.4.3] Static
+// members [class.static]. However the ODR-definitions are not in the right
+// order (C::I after C::J, see [3.6.2.3]).
+class B1 {
+ static const int I = 0;
+ static const int J = I;
+};
+const int B1::J;
+// CHECK-MESSAGES: [[@LINE-1]]:15: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'I'
+const int B1::I;
+
+void f() {
+ // This is fine, it's executed after dynamic initialization occurs.
+ static int G = takesInt(ExternGlobal);
+}
+
+// Declaration then definition then usage is fine.
+extern int ExternGlobal2;
+extern int ExternGlobal2;
+int ExternGlobal2 = 123;
+static int GlobalScopeGoodInit1 = ExternGlobal2;
+
+
+// Defined global variables are fine:
+static int GlobalScope = makesInt();
+static int GlobalScopeGoodInit2 = takesInt(GlobalScope);
+static int GlobalScope2 = takesInt(ns::NamespaceScope);
+// Enums are fine.
+enum Enum { kEnumValue = 1 };
+static int GlobalScopeFromEnum = takesInt(kEnumValue);
+
+// Leave constexprs alone.
+extern constexpr int GlobalScopeConstexpr = makesInt();
+static constexpr int GlobalScopeConstexprOk =
+ takesInt(GlobalScopeConstexpr);
+
+// This is a pretty common instance: People are usually not using constexpr, but
+// this is what they should write:
+static constexpr const char kValue[] = "value";
+constexpr int Fingerprint(const char *value) { return 0; }
+static int kFingerprint = Fingerprint(kValue);
+
+// This is fine because the ODR-definitions are in the right order (C::J after
+// C::I).
+class B2 {
+ static const int I = 0;
+ static const int J = I;
+};
+const int B2::I;
+const int B2::J;
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions.cpp
new file mode 100644
index 0000000..ecffba6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions.cpp
@@ -0,0 +1,103 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t
+
+float ceil(float);
+namespace std {
+double ceil(double);
+long double floor(long double);
+} // namespace std
+
+namespace floats {
+
+struct ConvertsToFloat {
+ operator float() const { return 0.5; }
+};
+
+float operator "" _Pa(unsigned long long);
+
+void not_ok(double d) {
+ int i = 0;
+ i = d;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions]
+ i = 0.5f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
+ i = static_cast<float>(d);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
+ i = ConvertsToFloat();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
+ i = 15_Pa;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
+}
+
+void not_ok_binary_ops(double d) {
+ int i = 0;
+ i += 0.5;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions]
+ i += 0.5f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
+ i += d;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions]
+ // We warn on the following even though it's not dangerous because there is no
+ // reason to use a double literal here.
+ // TODO(courbet): Provide an automatic fix.
+ i += 2.0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions]
+ i += 2.0f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
+
+ i *= 0.5f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
+ i /= 0.5f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
+ i += (double)0.5f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions]
+}
+
+void ok(double d) {
+ int i = 0;
+ i = 1;
+ i = static_cast<int>(0.5);
+ i = static_cast<int>(d);
+ i = std::ceil(0.5);
+ i = ::std::floor(0.5);
+ {
+ using std::ceil;
+ i = ceil(0.5f);
+ }
+ i = ceil(0.5f);
+}
+
+void ok_binary_ops(double d) {
+ int i = 0;
+ i += 1;
+ i += static_cast<int>(0.5);
+ i += static_cast<int>(d);
+ i += (int)d;
+ i += std::ceil(0.5);
+ i += ::std::floor(0.5);
+ {
+ using std::ceil;
+ i += ceil(0.5f);
+ }
+ i += ceil(0.5f);
+}
+
+// We're bailing out in templates and macros.
+template <typename T1, typename T2>
+void f(T1 one, T2 two) {
+ one += two;
+}
+
+void template_context() {
+ f(1, 2);
+ f(1, .5);
+}
+
+#define DERP(i, j) (i += j)
+
+void macro_context() {
+ int i = 0;
+ DERP(i, 2);
+ DERP(i, .5);
+}
+
+} // namespace floats
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc-custom.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc-custom.cpp
new file mode 100644
index 0000000..89142fb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc-custom.cpp
@@ -0,0 +1,59 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-no-malloc %t \
+// RUN: -config='{CheckOptions: \
+// RUN: [{key: cppcoreguidelines-no-malloc.Allocations, value: "::malloc;::align_malloc;::calloc"},\
+// RUN: {key: cppcoreguidelines-no-malloc.Reallocations, value: "::realloc;::align_realloc"},\
+// RUN: {key: cppcoreguidelines-no-malloc.Deallocations, value: "::free;::align_free"}]}' \
+// RUN: --
+
+using size_t = __SIZE_TYPE__;
+
+void *malloc(size_t size);
+void *align_malloc(size_t size, unsigned short aligmnent);
+void *calloc(size_t num, size_t size);
+void *realloc(void *ptr, size_t size);
+void *align_realloc(void *ptr, size_t size, unsigned short alignment);
+void free(void *ptr);
+void *align_free(void *ptr);
+
+void malloced_array() {
+ int *array0 = (int *)malloc(sizeof(int) * 20);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc]
+
+ int *zeroed = (int *)calloc(20, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc]
+
+ int *aligned = (int *)align_malloc(20 * sizeof(int), 16);
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc]
+
+ // reallocation memory, std::vector shall be used
+ char *realloced = (char *)realloc(array0, 50 * sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: do not manage memory manually; consider std::vector or std::string [cppcoreguidelines-no-malloc]
+
+ char *align_realloced = (char *)align_realloc(aligned, 50 * sizeof(int), 16);
+ // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: do not manage memory manually; consider std::vector or std::string [cppcoreguidelines-no-malloc]
+
+ // freeing memory the bad way
+ free(realloced);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not manage memory manually; use RAII [cppcoreguidelines-no-malloc]
+
+ align_free(align_realloced);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not manage memory manually; use RAII [cppcoreguidelines-no-malloc]
+
+ // check if a call to malloc as function argument is found as well
+ free(malloc(20));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not manage memory manually; use RAII [cppcoreguidelines-no-malloc]
+ // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc]
+}
+
+/// newing an array is still not good, but not relevant to this checker
+void newed_array() {
+ int *new_array = new int[10]; // OK(1)
+}
+
+void arbitrary_call() {
+ // we dont want every function to raise the warning even if malloc is in the name
+ malloced_array(); // OK(2)
+
+ // completly unrelated function call to malloc
+ newed_array(); // OK(3)
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc-no-functions.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc-no-functions.cpp
new file mode 100644
index 0000000..8b4d464
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc-no-functions.cpp
@@ -0,0 +1,17 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-no-malloc %t \
+// RUN: -config='{CheckOptions: \
+// RUN: [{key: cppcoreguidelines-no-malloc.Allocations, value: "::malloc"},\
+// RUN: {key: cppcoreguidelines-no-malloc.Reallocations, value: ""},\
+// RUN: {key: cppcoreguidelines-no-malloc.Deallocations, value: ""}]}' \
+// RUN: --
+
+// Just ensure, the check will not crash, when no functions shall be checked.
+
+using size_t = __SIZE_TYPE__;
+
+void *malloc(size_t size);
+
+void malloced_array() {
+ int *array0 = (int *)malloc(sizeof(int) * 20);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc]
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc.cpp
new file mode 100644
index 0000000..7b7ccf3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc.cpp
@@ -0,0 +1,42 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-no-malloc %t
+
+using size_t = __SIZE_TYPE__;
+
+void *malloc(size_t size);
+void *calloc(size_t num, size_t size);
+void *realloc(void *ptr, size_t size);
+void free(void *ptr);
+
+void malloced_array() {
+ int *array0 = (int *)malloc(sizeof(int) * 20);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc]
+
+ int *zeroed = (int *)calloc(20, sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc]
+
+ // reallocation memory, std::vector shall be used
+ char *realloced = (char *)realloc(array0, 50 * sizeof(int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: do not manage memory manually; consider std::vector or std::string [cppcoreguidelines-no-malloc]
+
+ // freeing memory the bad way
+ free(realloced);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not manage memory manually; use RAII [cppcoreguidelines-no-malloc]
+
+ // check if a call to malloc as function argument is found as well
+ free(malloc(20));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not manage memory manually; use RAII [cppcoreguidelines-no-malloc]
+ // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc]
+}
+
+/// newing an array is still not good, but not relevant to this checker
+void newed_array() {
+ int *new_array = new int[10]; // OK(1)
+}
+
+void arbitrary_call() {
+ // we dont want every function to raise the warning even if malloc is in the name
+ malloced_array(); // OK(2)
+
+ // completly unrelated function call to malloc
+ newed_array(); // OK(3)
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-owning-memory-containers.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-owning-memory-containers.cpp
new file mode 100644
index 0000000..929b33d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-owning-memory-containers.cpp
@@ -0,0 +1,61 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-owning-memory %t
+
+namespace gsl {
+template <typename T>
+using owner = T;
+}
+
+namespace std {
+
+// Not actually a vector, but more a dynamic, fixed size array. Just to demonstrate
+// functionality or the lack of the same.
+template <typename T>
+class vector {
+public:
+ vector(unsigned long size, T val) : data{new T[size]}, size{size} {
+ for (unsigned long i = 0ul; i < size; ++i) {
+ data[i] = val;
+ }
+ }
+
+ T *begin() { return data; }
+ T *end() { return &data[size]; }
+ T &operator[](unsigned long index) { return data[index]; }
+
+private:
+ T *data;
+ unsigned long size;
+};
+
+} // namespace std
+
+// All of the following codesnippets should be valid with appropriate 'owner<>' anaylsis,
+// but currently the type information of 'gsl::owner<>' gets lost in typededuction.
+int main() {
+ std::vector<gsl::owner<int *>> OwnerStdVector(100, nullptr);
+
+ // Rangebased looping in resource vector.
+ for (auto *Element : OwnerStdVector) {
+ Element = new int(42);
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: assigning newly created 'gsl::owner<>' to non-owner 'int *'
+ }
+ for (auto *Element : OwnerStdVector) {
+ delete Element;
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: deleting a pointer through a type that is not marked 'gsl::owner<>'; consider using a smart pointer instead
+ // CHECK-MESSAGES: [[@LINE-3]]:8: note: variable declared here
+ }
+
+ // Indexbased looping in resource vector.
+ for (int i = 0; i < 100; ++i) {
+ OwnerStdVector[i] = new int(42);
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: assigning newly created 'gsl::owner<>' to non-owner 'int *'
+ }
+ for (int i = 0; i < 100; ++i) {
+ delete OwnerStdVector[i];
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: deleting a pointer through a type that is not marked 'gsl::owner<>'; consider using a smart pointer instead
+ // A note gets emitted here pointing to the return value of the operator[] from the
+ // vector implementation. Maybe this is considered misleading.
+ }
+
+ return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-owning-memory-legacy-functions.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-owning-memory-legacy-functions.cpp
new file mode 100644
index 0000000..5785e9f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-owning-memory-legacy-functions.cpp
@@ -0,0 +1,194 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-owning-memory %t \
+// RUN: -config='{CheckOptions: \
+// RUN: [{key: cppcoreguidelines-owning-memory.LegacyResourceProducers, value: "::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile"}, \
+// RUN: {key: cppcoreguidelines-owning-memory.LegacyResourceConsumers, value: "::free;::realloc;::freopen;::fclose"}]}' \
+// RUN: -- -std=c++11 -nostdlib -nostdinc++
+
+namespace gsl {
+template <class T>
+using owner = T;
+} // namespace gsl
+
+extern "C" {
+using size_t = decltype(sizeof(void*));
+using FILE = int;
+
+void *malloc(size_t ByteCount);
+void *aligned_alloc(size_t Alignment, size_t Size);
+void *calloc(size_t Count, size_t SizeSingle);
+void *realloc(void *Resource, size_t NewByteCount);
+void free(void *Resource);
+
+FILE *tmpfile(void);
+FILE *fopen(const char *filename, const char *mode);
+FILE *freopen(const char *filename, const char *mode, FILE *stream);
+void fclose(FILE *Resource);
+}
+
+namespace std {
+using ::FILE;
+using ::size_t;
+
+using ::fclose;
+using ::fopen;
+using ::freopen;
+using ::tmpfile;
+
+using ::aligned_alloc;
+using ::calloc;
+using ::free;
+using ::malloc;
+using ::realloc;
+} // namespace std
+
+void nonOwningCall(int *Resource, size_t Size) {}
+void nonOwningCall(FILE *Resource) {}
+
+void consumesResource(gsl::owner<int *> Resource, size_t Size) {}
+void consumesResource(gsl::owner<FILE *> Resource) {}
+
+void testNonCasted(void *Resource) {}
+
+void testNonCastedOwner(gsl::owner<void *> Resource) {}
+
+FILE *fileFactory1() { return ::fopen("new_file.txt", "w"); }
+// CHECK-MESSAGES: [[@LINE-1]]:24: warning: returning a newly created resource of type 'FILE *' (aka 'int *') or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>'
+gsl::owner<FILE *> fileFactory2() { return std::fopen("new_file.txt", "w"); } // Ok
+
+int *arrayFactory1() { return (int *)std::malloc(100); }
+// CHECK-MESSAGES: [[@LINE-1]]:24: warning: returning a newly created resource of type 'int *' or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>'
+gsl::owner<int *> arrayFactory2() { return (int *)std::malloc(100); } // Ok
+void *dataFactory1() { return std::malloc(100); }
+// CHECK-MESSAGES: [[@LINE-1]]:24: warning: returning a newly created resource of type 'void *' or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>'
+gsl::owner<void *> dataFactory2() { return std::malloc(100); } // Ok
+
+void test_resource_creators() {
+ const unsigned int ByteCount = 25 * sizeof(int);
+ int Bad = 42;
+
+ int *IntArray1 = (int *)std::malloc(ByteCount);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+ int *IntArray2 = static_cast<int *>(std::malloc(ByteCount)); // Bad
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+ void *IntArray3 = std::malloc(ByteCount);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'void *' with a newly created 'gsl::owner<>'
+
+ int *IntArray4 = (int *)::malloc(ByteCount);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+ int *IntArray5 = static_cast<int *>(::malloc(ByteCount)); // Bad
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+ void *IntArray6 = ::malloc(ByteCount);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'void *' with a newly created 'gsl::owner<>'
+
+ gsl::owner<int *> IntArray7 = (int *)malloc(ByteCount); // Ok
+ gsl::owner<void *> IntArray8 = malloc(ByteCount); // Ok
+
+ gsl::owner<int *> IntArray9 = &Bad;
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'
+
+ nonOwningCall((int *)malloc(ByteCount), 25);
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: initializing non-owner argument of type 'int *' with a newly created 'gsl::owner<>'
+ nonOwningCall((int *)::malloc(ByteCount), 25);
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: initializing non-owner argument of type 'int *' with a newly created 'gsl::owner<>'
+
+ consumesResource((int *)malloc(ByteCount), 25); // Ok
+ consumesResource((int *)::malloc(ByteCount), 25); // Ok
+
+ testNonCasted(malloc(ByteCount));
+ // CHECK-MESSAGES: [[@LINE-1]]:17: warning: initializing non-owner argument of type 'void *' with a newly created 'gsl::owner<>'
+ testNonCastedOwner(gsl::owner<void *>(malloc(ByteCount))); // Ok
+ testNonCastedOwner(malloc(ByteCount)); // Ok
+
+ FILE *File1 = std::fopen("test_name.txt", "w+");
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+ FILE *File2 = ::fopen("test_name.txt", "w+");
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+
+ gsl::owner<FILE *> File3 = ::fopen("test_name.txt", "w+"); // Ok
+
+ FILE *File4;
+ File4 = ::fopen("test_name.txt", "w+");
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: assigning newly created 'gsl::owner<>' to non-owner 'FILE *' (aka 'int *')
+
+ gsl::owner<FILE *> File5;
+ File5 = ::fopen("test_name.txt", "w+"); // Ok
+ File5 = File1;
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'FILE *' (aka 'int *')
+
+ gsl::owner<FILE *> File6 = File1;
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'FILE *' (aka 'int *')
+
+ FILE *File7 = tmpfile();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+ gsl::owner<FILE *> File8 = tmpfile(); // Ok
+
+ nonOwningCall(::fopen("test_name.txt", "r"));
+ // CHECK-MESSAGES: [[@LINE-1]]:17: warning: initializing non-owner argument of type 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+ nonOwningCall(std::fopen("test_name.txt", "r"));
+ // CHECK-MESSAGES: [[@LINE-1]]:17: warning: initializing non-owner argument of type 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+
+ consumesResource(::fopen("test_name.txt", "r")); // Ok
+
+ int *HeapPointer3 = (int *)aligned_alloc(16ul, 4ul * 32ul);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+ gsl::owner<int *> HeapPointer4 = static_cast<int *>(aligned_alloc(16ul, 4ul * 32ul)); // Ok
+
+ void *HeapPointer5 = calloc(10ul, 4ul);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'void *' with a newly created 'gsl::owner<>'
+ gsl::owner<void *> HeapPointer6 = calloc(10ul, 4ul); // Ok
+}
+
+void test_legacy_consumers() {
+ int StackInteger = 42;
+
+ int *StackPointer = &StackInteger;
+ int *HeapPointer1 = (int *)malloc(100);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+ gsl::owner<int *> HeapPointer2 = (int *)malloc(100);
+
+ std::free(StackPointer);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'
+ std::free(HeapPointer1);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'
+ std::free(HeapPointer2); // Ok
+ // CHECK MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'
+
+ // FIXME: the check complains about initialization of 'void *' with new created owner.
+ // This happens, because the argument of `free` is not marked as 'owner<>' (and cannot be),
+ // and the check will not figure out could be meant as owner.
+ // This property will probably never be fixed, because it is probably a rather rare
+ // use-case and 'owner<>' should be wrapped in RAII classes anyway!
+ std::free(std::malloc(100)); // Ok but silly :)
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: initializing non-owner argument of type 'void *' with a newly created 'gsl::owner<>'
+
+ // Demonstrate, that multi-argument functions are diagnosed as well.
+ std::realloc(StackPointer, 200);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'
+ std::realloc(HeapPointer1, 200);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'
+ std::realloc(HeapPointer2, 200); // Ok
+ std::realloc(std::malloc(100), 200); // Ok but silly
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: initializing non-owner argument of type 'void *' with a newly created 'gsl::owner<>'
+
+ fclose(fileFactory1());
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'
+ fclose(fileFactory2()); // Ok, same as FIXME with `free(malloc(100))` applies here
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: initializing non-owner argument of type 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+
+ gsl::owner<FILE *> File1 = fopen("testfile.txt", "r"); // Ok
+ FILE *File2 = freopen("testfile.txt", "w", File1);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+ // CHECK-MESSAGES: [[@LINE-2]]:17: warning: calling legacy resource function without passing a 'gsl::owner<>'
+ // FIXME: The warning for not passing and owner<> is a false positive since both the filename and the
+ // mode are not supposed to be owners but still pointers. The check is to coarse for
+ // this function. Maybe `freopen` gets special treatment.
+
+ gsl::owner<FILE *> File3 = freopen("testfile.txt", "w", File2); // Bad, File2 no owner
+ // CHECK-MESSAGES: [[@LINE-1]]:30: warning: calling legacy resource function without passing a 'gsl::owner<>'
+
+ FILE *TmpFile = tmpfile();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+ FILE *File6 = freopen("testfile.txt", "w", TmpFile); // Bad, both return and argument
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+ // CHECK-MESSAGES: [[@LINE-2]]:17: warning: calling legacy resource function without passing a 'gsl::owner<>'
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-owning-memory.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-owning-memory.cpp
new file mode 100644
index 0000000..47b12fb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-owning-memory.cpp
@@ -0,0 +1,391 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-owning-memory %t
+
+namespace gsl {
+template <class T>
+using owner = T;
+} // namespace gsl
+
+template <typename T>
+class unique_ptr {
+public:
+ unique_ptr(gsl::owner<T> resource) : memory(resource) {}
+ unique_ptr(const unique_ptr<T> &) = default;
+
+ ~unique_ptr() { delete memory; }
+
+private:
+ gsl::owner<T> memory;
+};
+
+void takes_owner(gsl::owner<int *> owned_int) {
+}
+
+void takes_pointer(int *unowned_int) {
+}
+
+void takes_owner_and_more(int some_int, gsl::owner<int *> owned_int, float f) {
+}
+
+template <typename T>
+void takes_templated_owner(gsl::owner<T> owned_T) {
+}
+
+gsl::owner<int *> returns_owner1() { return gsl::owner<int *>(new int(42)); } // Ok
+gsl::owner<int *> returns_owner2() { return new int(42); } // Ok
+
+int *returns_no_owner1() { return nullptr; }
+int *returns_no_owner2() {
+ return new int(42);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: returning a newly created resource of type 'int *' or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>'
+}
+int *returns_no_owner3() {
+ int *should_be_owner = new int(42);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+ return should_be_owner;
+}
+int *returns_no_owner4() {
+ gsl::owner<int *> owner = new int(42);
+ return owner;
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: returning a newly created resource of type 'int *' or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>'
+}
+
+unique_ptr<int *> returns_no_owner5() {
+ return unique_ptr<int *>(new int(42)); // Ok
+}
+
+/// FIXME: CSA finds it, but the report is misleading. Ownersemantics can catch this
+/// by flow analysis similar to bugprone-use-after-move.
+void csa_not_finding_leak() {
+ gsl::owner<int *> o1 = new int(42); // Ok
+
+ gsl::owner<int *> o2 = o1; // Ok
+ o2 = new int(45); // conceptual leak, the memory from o1 is now leaked, since its considered moved in the guidelines
+
+ delete o2;
+ // actual leak occurs here, its found, but mixed
+ delete o1;
+}
+
+void test_assignment_and_initialization() {
+ int stack_int1 = 15;
+ int stack_int2;
+
+ gsl::owner<int *> owned_int1 = &stack_int1; // BAD
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'
+
+ gsl::owner<int *> owned_int2;
+ owned_int2 = &stack_int2; // BAD since no owner, bad since uninitialized
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'int *'
+
+ gsl::owner<int *> owned_int3 = new int(42); // Good
+ owned_int3 = nullptr; // Good
+
+ gsl::owner<int *> owned_int4(nullptr); // Ok
+ owned_int4 = new int(42); // Good
+
+ gsl::owner<int *> owned_int5 = owned_int3; // Good
+
+ gsl::owner<int *> owned_int6{nullptr}; // Ok
+ owned_int6 = owned_int4; // Good
+
+ // FIXME:, flow analysis for the case of reassignment. Value must be released before
+ owned_int6 = owned_int3; // BAD, because reassignment without resource release
+
+ auto owned_int7 = returns_owner1(); // Bad, since type deduction eliminates the owner wrapper
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+ // CHECK-MESSAGES: [[@LINE-2]]:3: note: type deduction did not result in an owner
+
+ const auto owned_int8 = returns_owner2(); // Bad, since type deduction eliminates the owner wrapper
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *const' with a newly created 'gsl::owner<>'
+ // CHECK-MESSAGES: [[@LINE-2]]:3: note: type deduction did not result in an owner
+
+ gsl::owner<int *> owned_int9 = returns_owner1(); // Ok
+ int *unowned_int3 = returns_owner1(); // Bad
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+
+ gsl::owner<int *> owned_int10;
+ owned_int10 = returns_owner1(); // Ok
+
+ int *unowned_int4;
+ unowned_int4 = returns_owner1(); // Bad
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: assigning newly created 'gsl::owner<>' to non-owner 'int *'
+
+ gsl::owner<int *> owned_int11 = returns_no_owner1(); // Bad since no owner
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'
+
+ gsl::owner<int *> owned_int12;
+ owned_int12 = returns_no_owner1(); // Bad since no owner
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'int *'
+
+ int *unowned_int5 = returns_no_owner1(); // Ok
+ int *unowned_int6;
+ unowned_int6 = returns_no_owner1(); // Ok
+
+ int *unowned_int7 = new int(42); // Bad, since resource not assigned to an owner
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+
+ int *unowned_int8;
+ unowned_int8 = new int(42);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: assigning newly created 'gsl::owner<>' to non-owner 'int *'
+
+ gsl::owner<int *> owned_int13 = nullptr; // Ok
+}
+
+void test_deletion() {
+ gsl::owner<int *> owned_int1 = new int(42);
+ delete owned_int1; // Good
+
+ gsl::owner<int *> owned_int2 = new int[42];
+ delete[] owned_int2; // Good
+
+ int *unowned_int1 = new int(42); // BAD, since new creates and owner
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+ delete unowned_int1; // BAD, since no owner
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: deleting a pointer through a type that is not marked 'gsl::owner<>'; consider using a smart pointer instead
+ // CHECK-MESSAGES: [[@LINE-4]]:3: note: variable declared here
+
+ int *unowned_int2 = new int[42]; // BAD, since new creates and owner
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+ delete[] unowned_int2; // BAD since no owner
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: deleting a pointer through a type that is not marked 'gsl::owner<>'; consider using a smart pointer instead
+ // CHECK-MESSAGES: [[@LINE-4]]:3: note: variable declared here
+
+ delete new int(42); // Technically ok, but stupid
+ delete[] new int[42]; // Technically ok, but stupid
+}
+
+void test_owner_function_calls() {
+ int stack_int = 42;
+ int *unowned_int1 = &stack_int;
+ takes_owner(&stack_int); // BAD
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: expected argument of type 'gsl::owner<>'; got 'int *'
+ takes_owner(unowned_int1); // BAD
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: expected argument of type 'gsl::owner<>'; got 'int *'
+
+ gsl::owner<int *> owned_int1 = new int(42);
+ takes_owner(owned_int1); // Ok
+
+ takes_owner_and_more(42, &stack_int, 42.0f); // BAD
+ // CHECK-MESSAGES: [[@LINE-1]]:28: warning: expected argument of type 'gsl::owner<>'; got 'int *'
+ takes_owner_and_more(42, unowned_int1, 42.0f); // BAD
+ // CHECK-MESSAGES: [[@LINE-1]]:28: warning: expected argument of type 'gsl::owner<>'; got 'int *'
+
+ takes_owner_and_more(42, new int(42), 42.0f); // Ok, since new is consumed by owner
+ takes_owner_and_more(42, owned_int1, 42.0f); // Ok, since owner as argument
+
+ takes_templated_owner(owned_int1); // Ok
+ takes_templated_owner(new int(42)); // Ok
+ takes_templated_owner(unowned_int1); // Bad
+ // CHECK-MESSAGES: [[@LINE-1]]:25: warning: expected argument of type 'gsl::owner<>'; got 'int *'
+
+ takes_owner(returns_owner1()); // Ok
+ takes_owner(returns_no_owner1()); // BAD
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: expected argument of type 'gsl::owner<>'; got 'int *'
+}
+
+void test_unowned_function_calls() {
+ int stack_int = 42;
+ int *unowned_int1 = &stack_int;
+ gsl::owner<int *> owned_int1 = new int(42);
+
+ takes_pointer(&stack_int); // Ok
+ takes_pointer(unowned_int1); // Ok
+ takes_pointer(owned_int1); // Ok
+ takes_pointer(new int(42)); // Bad, since new creates and owner
+ // CHECK-MESSAGES: [[@LINE-1]]:17: warning: initializing non-owner argument of type 'int *' with a newly created 'gsl::owner<>'
+
+ takes_pointer(returns_owner1()); // Bad
+ // CHECK-MESSAGES: [[@LINE-1]]:17: warning: initializing non-owner argument of type 'int *' with a newly created 'gsl::owner<>'
+
+ takes_pointer(returns_no_owner1()); // Ok
+}
+
+// FIXME: Typedefing owner<> to something else does not work.
+// This might be necessary for code already having a similar typedef like owner<> and
+// replacing it with owner<>. This might be the same problem as with templates.
+// The canonical type will ignore the owner<> alias, since its a typedef as well.
+//
+// Check, if owners hidden by typedef are handled the same as 'obvious' owners.
+#if 0
+using heap_int = gsl::owner<int *>;
+typedef gsl::owner<float *> heap_float;
+
+// This tests only a subset, assuming that the check will either see through the
+// typedef or not (it doesn't!).
+void test_typedefed_values() {
+ // Modern typedef.
+ int StackInt1 = 42;
+ heap_int HeapInt1 = &StackInt1;
+ // CHECK MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'int *'
+
+ //FIXME: Typedef not considered correctly here.
+ // heap_int HeapInt2 = new int(42); // Ok
+ takes_pointer(HeapInt1); // Ok
+ takes_owner(HeapInt1); // Ok
+
+ // Traditional typedef.
+ float StackFloat1 = 42.0f;
+ heap_float HeapFloat1 = &StackFloat1;
+ // CHECK MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'float *'
+
+ //FIXME: Typedef not considered correctly here.
+ // heap_float HeapFloat2 = new float(42.0f);
+ HeapFloat2 = HeapFloat1; // Ok
+}
+#endif
+
+struct ArbitraryClass {};
+struct ClassWithOwner { // Does not define destructor, necessary with owner
+ ClassWithOwner() : owner_var(nullptr) {} // Ok
+
+ ClassWithOwner(ArbitraryClass &other) : owner_var(&other) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:43: warning: expected initialization of owner member variable with value of type 'gsl::owner<>'; got 'ArbitraryClass *'
+
+ ClassWithOwner(gsl::owner<ArbitraryClass *> other) : owner_var(other) {} // Ok
+
+ ClassWithOwner(gsl::owner<ArbitraryClass *> data, int /* unused */) { // Ok
+ owner_var = data; // Ok
+ }
+
+ ClassWithOwner(ArbitraryClass *bad_data, int /* unused */, int /* unused */) {
+ owner_var = bad_data;
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: expected assignment source to be of type 'gsl::owner<>'; got 'ArbitraryClass *'
+ }
+
+ ClassWithOwner(ClassWithOwner &&other) : owner_var{other.owner_var} {} // Ok
+
+ ClassWithOwner &operator=(ClassWithOwner &&other) {
+ owner_var = other.owner_var; // Ok
+ return *this;
+ }
+
+ // Returning means, that the owner is "moved", so the class should not access this
+ // variable anymore after this method gets called.
+ gsl::owner<ArbitraryClass *> buggy_but_returns_owner() { return owner_var; }
+
+ gsl::owner<ArbitraryClass *> owner_var;
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: member variable of type 'gsl::owner<>' requires the class 'ClassWithOwner' to implement a destructor to release the owned resource
+};
+
+class DefaultedDestructor { // Bad since default constructor with owner
+ ~DefaultedDestructor() = default; // Bad, since will not destroy the owner
+ gsl::owner<int *> Owner;
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: member variable of type 'gsl::owner<>' requires the class 'DefaultedDestructor' to implement a destructor to release the owned resource
+};
+
+struct DeletedDestructor {
+ ~DeletedDestructor() = delete;
+ gsl::owner<int *> Owner;
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: member variable of type 'gsl::owner<>' requires the class 'DeletedDestructor' to implement a destructor to release the owned resource
+};
+
+void test_class_with_owner() {
+ ArbitraryClass A;
+ ClassWithOwner C1; // Ok
+ ClassWithOwner C2{A}; // Bad, since the owner would be initialized with an non-owner, but catched in the class
+ ClassWithOwner C3{gsl::owner<ArbitraryClass *>(new ArbitraryClass)}; // Ok
+
+ const auto Owner1 = C3.buggy_but_returns_owner(); // BAD, deduces Owner1 to ArbitraryClass *const
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'ArbitraryClass *const' with a newly created 'gsl::owner<>'
+ // CHECK-MESSAGES: [[@LINE-2]]:3: note: type deduction did not result in an owner
+
+ auto Owner2 = C2.buggy_but_returns_owner(); // BAD, deduces Owner2 to ArbitraryClass *
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'ArbitraryClass *' with a newly created 'gsl::owner<>'
+ // CHECK-MESSAGES: [[@LINE-2]]:3: note: type deduction did not result in an owner
+
+ Owner2 = &A; // Ok, since type deduction did NOT result in owner<int*>
+
+ gsl::owner<ArbitraryClass *> Owner3 = C1.buggy_but_returns_owner(); // Ok, still an owner
+ Owner3 = &A; // Bad, since assignment of non-owner to owner
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'ArbitraryClass *'
+}
+
+template <typename T>
+struct HeapArray { // Ok, since destructor with owner
+ HeapArray() : _data(nullptr), size(0) {} // Ok
+ HeapArray(int size) : _data(new int[size]), size(size) {} // Ok
+ HeapArray(int size, T val) {
+ _data = new int[size]; // Ok
+ size = size;
+ for (auto i = 0u; i < size; ++i)
+ _data[i] = val; // Ok
+ }
+ HeapArray(int size, T val, int *problematic) : _data{problematic}, size(size) {} // Bad
+ // CHECK-MESSAGES: [[@LINE-1]]:50: warning: expected initialization of owner member variable with value of type 'gsl::owner<>'; got 'void'
+ // FIXME: void is incorrect type, probably wrong thing matched
+
+ HeapArray(HeapArray &&other) : _data(other._data), size(other.size) { // Ok
+ other._data = nullptr; // Ok
+ other.size = 0;
+ }
+
+ HeapArray<T> &operator=(HeapArray<T> &&other) {
+ _data = other._data; // Ok, NOLINT warning here about bad types, why?
+ size = other.size;
+ return *this;
+ }
+
+ ~HeapArray() { delete[] _data; } // Ok
+
+ T *data() { return _data; } // Ok NOLINT, because it "looks" like a factory
+
+ gsl::owner<T *> _data;
+ unsigned int size;
+};
+
+void test_inner_template() {
+ HeapArray<int> Array1;
+ HeapArray<int> Array2(100);
+ HeapArray<int> Array3(100, 0);
+ HeapArray<int> Array4(100, 0, nullptr);
+
+ Array1 = static_cast<HeapArray<int> &&>(Array2);
+ HeapArray<int> Array5(static_cast<HeapArray<int> &&>(Array3));
+
+ int *NonOwningPtr = Array1.data(); // Ok
+ gsl::owner<int *> OwningPtr = Array1.data(); // Bad, since it does not return the owner
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'
+}
+
+// FIXME: Typededuction removes the owner - wrapper, therefore gsl::owner can not be used
+// with Template classes like this. Is there a walkaround?
+template <typename T>
+struct TemplateValue {
+ TemplateValue() = default;
+ TemplateValue(T t) : val{t} {}
+
+ void setVal(const T &t) { val = t; }
+ const T getVal() const { return val; }
+
+ T val;
+};
+
+// FIXME: Same typededcution problems
+template <typename T>
+void template_function(T t) {
+ gsl::owner<int *> owner_t = t; // Probably bad, since type deduction still wrong
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'T'
+ // CHECK-MESSAGES: [[@LINE-2]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'
+}
+
+// FIXME: Same typededcution problems
+void test_templates() {
+ int stack_int = 42;
+ int *stack_ptr1 = &stack_int;
+
+ TemplateValue<gsl::owner<int *>> Owner0; // Ok, T should be owner, but is int*
+
+ TemplateValue<gsl::owner<int *>> Owner1(new int(42)); // Ok, T should be owner, but is int*
+ Owner1.setVal(&stack_int); // Bad since non-owner assignment
+ Owner1.setVal(stack_ptr1); // Bad since non-owner assignment
+ //Owner1.setVal(new int(42)); // Ok, but since type deduction is wrong, this one is considered harmful
+
+ int *stack_ptr2 = Owner1.getVal(); // Bad, initializing non-owner with owner
+
+ TemplateValue<int *> NonOwner1(new int(42)); // Bad, T is int *, hence dynamic memory to non-owner
+ gsl::owner<int *> IntOwner1 = NonOwner1.getVal(); // Bad, since owner initialized with non-owner
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'
+
+ template_function(IntOwner1); // Ok, but not actually ok, since type deduction removes owner
+ template_function(stack_ptr1); // Bad, but type deduction gets it wrong
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-array-to-pointer-decay.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-array-to-pointer-decay.cpp
new file mode 100644
index 0000000..ce19280
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-array-to-pointer-decay.cpp
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-array-to-pointer-decay %t
+#include <stddef.h>
+
+namespace gsl {
+template <class T>
+class array_view {
+public:
+ template <class U, size_t N>
+ array_view(U (&arr)[N]);
+};
+}
+
+void pointerfun(int *p);
+void arrayfun(int p[]);
+void arrayviewfun(gsl::array_view<int> &p);
+size_t s();
+
+void f() {
+ int a[5];
+ pointerfun(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay]
+ pointerfun((int *)a); // OK, explicit cast
+ arrayfun(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not implicitly decay an array into a pointer
+
+ pointerfun(a + s() - 10); // Convert to &a[g() - 10];
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not implicitly decay an array into a pointer
+
+ gsl::array_view<int> av(a);
+ arrayviewfun(av); // OK
+
+ int i = a[0]; // OK
+ pointerfun(&a[0]); // OK
+
+ for (auto &e : a) // OK, iteration internally decays array to pointer
+ e = 1;
+}
+
+const char *g() {
+ return "clang"; // OK, decay string literal to pointer
+}
+
+void f2(void *const *);
+void bug25362() {
+ void *a[2];
+ f2(static_cast<void *const*>(a)); // OK, explicit cast
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index-c++03.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index-c++03.cpp
new file mode 100644
index 0000000..ad9fcd9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index-c++03.cpp
@@ -0,0 +1,11 @@
+// RUN: clang-tidy %s -checks=-*,cppcoreguidelines-pro-bounds-constant-array-index -- -std=c++03 | count 0
+
+// Note: this test expects no diagnostics, but FileCheck cannot handle that,
+// hence the use of | count 0.
+template <int index> struct B {
+ int get() {
+ // The next line used to crash the check (in C++03 mode only).
+ return x[index];
+ }
+ int x[3];
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index-gslheader.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index-gslheader.cpp
new file mode 100644
index 0000000..a88a2d9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index-gslheader.cpp
@@ -0,0 +1,79 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-constant-array-index %t -- -config='{CheckOptions: [{key: cppcoreguidelines-pro-bounds-constant-array-index.GslHeader, value: "dir1/gslheader.h"}]}' -- -std=c++11
+// CHECK-FIXES: #include "dir1/gslheader.h"
+
+typedef __SIZE_TYPE__ size_t;
+
+namespace std {
+ template<typename T, size_t N>
+ struct array {
+ T& operator[](size_t n);
+ T& at(size_t n);
+ };
+}
+
+
+namespace gsl {
+ template<class T, size_t N>
+ T& at( T(&a)[N], size_t index );
+
+ template<class T, size_t N>
+ T& at( std::array<T, N> &a, size_t index );
+}
+
+constexpr int const_index(int base) {
+ return base + 3;
+}
+
+void f(std::array<int, 10> a, int pos) {
+ a [ pos / 2 /*comment*/] = 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use array subscript when the index is not an integer constant expression; use gsl::at() instead [cppcoreguidelines-pro-bounds-constant-array-index]
+ // CHECK-FIXES: gsl::at(a, pos / 2 /*comment*/) = 1;
+ int j = a[pos - 1];
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use array subscript when the index is not an integer constant expression; use gsl::at() instead
+ // CHECK-FIXES: int j = gsl::at(a, pos - 1);
+
+ a.at(pos-1) = 2; // OK, at() instead of []
+ gsl::at(a, pos-1) = 2; // OK, gsl::at() instead of []
+
+ a[-1] = 3;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index -1 is negative [cppcoreguidelines-pro-bounds-constant-array-index]
+ a[10] = 4;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements) [cppcoreguidelines-pro-bounds-constant-array-index]
+
+ a[const_index(7)] = 3;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements)
+
+ a[0] = 3; // OK, constant index and inside bounds
+ a[1] = 3; // OK, constant index and inside bounds
+ a[9] = 3; // OK, constant index and inside bounds
+ a[const_index(6)] = 3; // OK, constant index and inside bounds
+}
+
+void g() {
+ int a[10];
+ for (int i = 0; i < 10; ++i) {
+ a[i] = i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use array subscript when the index is not an integer constant expression; use gsl::at() instead
+ // CHECK-FIXES: gsl::at(a, i) = i;
+ gsl::at(a, i) = i; // OK, gsl::at() instead of []
+ }
+
+ a[-1] = 3; // flagged by clang-diagnostic-array-bounds
+ a[10] = 4; // flagged by clang-diagnostic-array-bounds
+ a[const_index(7)] = 3; // flagged by clang-diagnostic-array-bounds
+
+ a[0] = 3; // OK, constant index and inside bounds
+ a[1] = 3; // OK, constant index and inside bounds
+ a[9] = 3; // OK, constant index and inside bounds
+ a[const_index(6)] = 3; // OK, constant index and inside bounds
+}
+
+struct S {
+ int& operator[](int i);
+};
+
+void customOperator() {
+ S s;
+ int i = 0;
+ s[i] = 3; // OK, custom operator
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index.cpp
new file mode 100644
index 0000000..3519410
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index.cpp
@@ -0,0 +1,87 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-constant-array-index %t
+
+typedef __SIZE_TYPE__ size_t;
+
+namespace std {
+ template<typename T, size_t N>
+ struct array {
+ T& operator[](size_t n);
+ T& at(size_t n);
+ };
+}
+
+
+namespace gsl {
+ template<class T, size_t N>
+ T& at( T(&a)[N], size_t index );
+
+ template<class T, size_t N>
+ T& at( std::array<T, N> &a, size_t index );
+}
+
+constexpr int const_index(int base) {
+ return base + 3;
+}
+
+void f(std::array<int, 10> a, int pos) {
+ a [ pos / 2 /*comment*/] = 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use array subscript when the index is not an integer constant expression; use gsl::at() instead [cppcoreguidelines-pro-bounds-constant-array-index]
+ int j = a[pos - 1];
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use array subscript when the index is not an integer constant expression; use gsl::at() instead
+
+ a.at(pos-1) = 2; // OK, at() instead of []
+ gsl::at(a, pos-1) = 2; // OK, gsl::at() instead of []
+
+ a[-1] = 3;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index -1 is negative [cppcoreguidelines-pro-bounds-constant-array-index]
+ a[10] = 4;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements) [cppcoreguidelines-pro-bounds-constant-array-index]
+
+ a[const_index(7)] = 3;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements)
+
+ a[0] = 3; // OK, constant index and inside bounds
+ a[1] = 3; // OK, constant index and inside bounds
+ a[9] = 3; // OK, constant index and inside bounds
+ a[const_index(6)] = 3; // OK, constant index and inside bounds
+}
+
+void g() {
+ int a[10];
+ for (int i = 0; i < 10; ++i) {
+ a[i] = i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use array subscript when the index is not an integer constant expression; use gsl::at() instead
+ // CHECK-FIXES: gsl::at(a, i) = i;
+ gsl::at(a, i) = i; // OK, gsl::at() instead of []
+ }
+
+ a[-1] = 3; // flagged by clang-diagnostic-array-bounds
+ a[10] = 4; // flagged by clang-diagnostic-array-bounds
+ a[const_index(7)] = 3; // flagged by clang-diagnostic-array-bounds
+
+ a[0] = 3; // OK, constant index and inside bounds
+ a[1] = 3; // OK, constant index and inside bounds
+ a[9] = 3; // OK, constant index and inside bounds
+ a[const_index(6)] = 3; // OK, constant index and inside bounds
+}
+
+struct S {
+ int& operator[](int i);
+};
+
+void customOperator() {
+ S s;
+ int i = 0;
+ s[i] = 3; // OK, custom operator
+}
+
+struct A {
+ // The compiler-generated copy constructor uses an ArraySubscriptExpr. Don't warn.
+ int x[3];
+};
+
+void use_A() {
+ // Force the compiler to generate a copy constructor.
+ A a;
+ A a2(a);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-pointer-arithmetic-pr36489.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-pointer-arithmetic-pr36489.cpp
new file mode 100644
index 0000000..4710952
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-pointer-arithmetic-pr36489.cpp
@@ -0,0 +1,53 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-pointer-arithmetic %t -- -- -std=c++14
+
+// Fix PR36489 and detect auto-deduced value correctly.
+char *getPtr();
+auto getPtrAuto() { return getPtr(); }
+decltype(getPtr()) getPtrDeclType();
+decltype(auto) getPtrDeclTypeAuto() { return getPtr(); }
+auto getPtrWithTrailingReturnType() -> char *;
+
+void auto_deduction_binary() {
+ auto p1 = getPtr() + 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: do not use pointer arithmetic
+ auto p2 = getPtrAuto() + 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: do not use pointer arithmetic
+ auto p3 = getPtrWithTrailingReturnType() + 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: do not use pointer arithmetic
+ auto p4 = getPtr();
+ auto *p5 = getPtr();
+ p4 = p4 + 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use pointer arithmetic
+ p5 = p5 + 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use pointer arithmetic
+ auto p6 = getPtrDeclType() + 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: do not use pointer arithmetic
+ auto p7 = getPtrDeclTypeAuto() + 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: do not use pointer arithmetic
+ auto *p8 = getPtrDeclType() + 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: do not use pointer arithmetic
+ auto *p9 = getPtrDeclTypeAuto() + 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: do not use pointer arithmetic
+}
+
+void auto_deduction_subscript() {
+ char p1 = getPtr()[2];
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use pointer arithmetic
+ auto p2 = getPtr()[3];
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use pointer arithmetic
+
+ char p3 = getPtrAuto()[4];
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use pointer arithmetic
+ auto p4 = getPtrAuto()[5];
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use pointer arithmetic
+
+ char p5 = getPtrWithTrailingReturnType()[6];
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use pointer arithmetic
+ auto p6 = getPtrWithTrailingReturnType()[7];
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use pointer arithmetic
+
+ auto p7 = getPtrDeclType()[8];
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use pointer arithmetic
+ auto p8 = getPtrDeclTypeAuto()[9];
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use pointer arithmetic
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-pointer-arithmetic.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-pointer-arithmetic.cpp
new file mode 100644
index 0000000..7cbc6dd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-pointer-arithmetic.cpp
@@ -0,0 +1,89 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-pointer-arithmetic %t
+
+enum E {
+ ENUM_LITERAL = 1
+};
+
+int i = 4;
+int j = 1;
+int *p = 0;
+int *q = 0;
+
+void fail() {
+ q = p + 4;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic [cppcoreguidelines-pro-bounds-pointer-arithmetic]
+ p = q + i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic
+ p = q + ENUM_LITERAL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic
+
+ q = p - 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic
+ p = q - i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic
+ p = q - ENUM_LITERAL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic
+
+ p += 4;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic
+ p += i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic
+ p += ENUM_LITERAL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic
+
+ q -= 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic
+ q -= i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic
+ q -= ENUM_LITERAL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic
+
+ p++;
+ // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: do not use pointer arithmetic
+ ++p;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use pointer arithmetic
+
+ p--;
+ // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: do not use pointer arithmetic
+ --p;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use pointer arithmetic
+
+ i = p[1];
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use pointer arithmetic
+}
+
+struct S {
+ operator int() const;
+};
+
+void f(S &s) {
+ int *i;
+ i = i + s;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic
+}
+
+void f2(int i[]) {
+ i[1] = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use pointer arithmetic
+}
+
+void okay() {
+ int a[3];
+ i = a[2]; // OK, access to array
+
+ p = q;
+ p = &i;
+
+ i++;
+ ++i;
+ i--;
+ --i;
+ i += 1;
+ i -= 1;
+ i = j + 1;
+ i = j - 1;
+
+ auto diff = p - q; // OK, result is arithmetic
+
+ for(int ii : a) ; // OK, pointer arithmetic generated by compiler
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-const-cast.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-const-cast.cpp
new file mode 100644
index 0000000..2d32e13
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-const-cast.cpp
@@ -0,0 +1,6 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-const-cast %t
+
+const int *i;
+int *j;
+void f() { j = const_cast<int *>(i); }
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not use const_cast [cppcoreguidelines-pro-type-const-cast]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-cstyle-cast.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-cstyle-cast.cpp
new file mode 100644
index 0000000..31f59e3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-cstyle-cast.cpp
@@ -0,0 +1,141 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-cstyle-cast %t
+
+void reinterpretcast() {
+ int i = 0;
+ void *j;
+ j = (int*)j;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use C-style cast to convert between unrelated types [cppcoreguidelines-pro-type-cstyle-cast]
+}
+
+void constcast() {
+ int* i;
+ const int* j;
+ i = (int*)j;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use C-style cast to cast away constness
+ j = (const int*)i; // OK, const added
+ (void)j; // OK, not a const_cast
+}
+
+void const_and_reinterpret() {
+ int* i;
+ const void* j;
+ i = (int*)j;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use C-style cast to convert between unrelated types
+}
+
+class Base {
+};
+
+class Derived : public Base {
+};
+
+class Base2 {
+};
+
+class MultiDerived : public Base, public Base2 {
+};
+
+class PolymorphicBase {
+public:
+ virtual ~PolymorphicBase();
+};
+
+class PolymorphicDerived : public PolymorphicBase {
+};
+
+class PolymorphicMultiDerived : public Base, public PolymorphicBase {
+};
+
+void pointers() {
+
+ auto P0 = (Derived*)new Base();
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use C-style cast to downcast from a base to a derived class
+
+ const Base* B0;
+ auto PC0 = (const Derived*)(B0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use C-style cast to downcast from a base to a derived class
+
+ auto P1 = (Base*)new Derived(); // OK, upcast to a public base
+ auto P2 = (Base*)new MultiDerived(); // OK, upcast to a public base
+ auto P3 = (Base2*)new MultiDerived(); // OK, upcast to a public base
+}
+
+void pointers_polymorphic() {
+
+ auto PP0 = (PolymorphicDerived*)new PolymorphicBase();
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use C-style cast to downcast from a base to a derived class; use dynamic_cast instead
+ // CHECK-FIXES: auto PP0 = dynamic_cast<PolymorphicDerived*>(new PolymorphicBase());
+
+ const PolymorphicBase* B0;
+ auto PPC0 = (const PolymorphicDerived*)B0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: do not use C-style cast to downcast from a base to a derived class; use dynamic_cast instead
+ // CHECK-FIXES: auto PPC0 = dynamic_cast<const PolymorphicDerived*>(B0);
+
+
+ auto B1 = (PolymorphicBase*)new PolymorphicDerived(); // OK, upcast to a public base
+ auto B2 = (PolymorphicBase*)new PolymorphicMultiDerived(); // OK, upcast to a public base
+ auto B3 = (Base*)new PolymorphicMultiDerived(); // OK, upcast to a public base
+}
+
+void arrays() {
+ Base ArrayOfBase[10];
+ auto A0 = (Derived*)ArrayOfBase;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use C-style cast to downcast from a base to a derived class
+}
+
+void arrays_polymorphic() {
+ PolymorphicBase ArrayOfPolymorphicBase[10];
+ auto AP0 = (PolymorphicDerived*)ArrayOfPolymorphicBase;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use C-style cast to downcast from a base to a derived class; use dynamic_cast instead
+ // CHECK-FIXES: auto AP0 = dynamic_cast<PolymorphicDerived*>(ArrayOfPolymorphicBase);
+}
+
+void references() {
+ Base B0;
+ auto R0 = (Derived&)B0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use C-style cast to downcast from a base to a derived class
+ Base& RefToBase = B0;
+ auto R1 = (Derived&)RefToBase;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use C-style cast to downcast from a base to a derived class
+
+ const Base& ConstRefToBase = B0;
+ auto RC1 = (const Derived&)ConstRefToBase;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use C-style cast to downcast from a base to a derived class
+
+
+ Derived RD1;
+ auto R2 = (Base&)RD1; // OK, upcast to a public base
+}
+
+void references_polymorphic() {
+ PolymorphicBase B0;
+ auto RP0 = (PolymorphicDerived&)B0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use C-style cast to downcast from a base to a derived class; use dynamic_cast instead
+ // CHECK-FIXES: auto RP0 = dynamic_cast<PolymorphicDerived&>(B0);
+
+ PolymorphicBase& RefToPolymorphicBase = B0;
+ auto RP1 = (PolymorphicDerived&)RefToPolymorphicBase;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use C-style cast to downcast from a base to a derived class; use dynamic_cast instead
+ // CHECK-FIXES: auto RP1 = dynamic_cast<PolymorphicDerived&>(RefToPolymorphicBase);
+
+ const PolymorphicBase& ConstRefToPolymorphicBase = B0;
+ auto RPC2 = (const PolymorphicDerived&)(ConstRefToPolymorphicBase);
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: do not use C-style cast to downcast from a base to a derived class; use dynamic_cast instead
+ // CHECK-FIXES: auto RPC2 = dynamic_cast<const PolymorphicDerived&>(ConstRefToPolymorphicBase);
+
+ PolymorphicDerived d1;
+ auto RP2 = (PolymorphicBase&)d1; // OK, upcast to a public base
+}
+
+template<class B, class D>
+void templ() {
+ auto B0 = (B*)new D();
+}
+
+void templ_bad_call() {
+ templ<Derived, Base>(); //FIXME: this should trigger a warning
+}
+
+void templ_good_call() {
+ templ<Base, Derived>(); // OK, upcast to a public base
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx2a.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx2a.cpp
new file mode 100644
index 0000000..d3e3ade
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx2a.cpp
@@ -0,0 +1,19 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -- -std=c++2a -fno-delayed-template-parsing
+
+struct PositiveBitfieldMember {
+ PositiveBitfieldMember() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F
+ unsigned F : 5;
+ // CHECK-FIXES: unsigned F : 5{};
+};
+
+struct NegativeUnnamedBitfieldMember {
+ NegativeUnnamedBitfieldMember() {}
+ unsigned : 5;
+};
+
+struct NegativeInitializedBitfieldMembers {
+ NegativeInitializedBitfieldMembers() : F(3) { G = 2; }
+ unsigned F : 5;
+ unsigned G : 5;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
new file mode 100644
index 0000000..db97bb4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
@@ -0,0 +1,116 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -- -std=c++98 -fno-delayed-template-parsing
+
+struct PositiveFieldBeforeConstructor {
+ int F;
+ PositiveFieldBeforeConstructor() /* some comment */ {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F
+ // CHECK-FIXES: PositiveFieldBeforeConstructor() : F() /* some comment */ {}
+};
+
+struct PositiveFieldAfterConstructor {
+ PositiveFieldAfterConstructor() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F, G, H
+ // CHECK-FIXES: PositiveFieldAfterConstructor() : F(), G(), H() {}
+ int F;
+ bool G /* with comment */;
+ int *H;
+ PositiveFieldBeforeConstructor IgnoredField;
+};
+
+struct PositiveSeparateDefinition {
+ PositiveSeparateDefinition();
+ int F;
+};
+
+PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: F
+// CHECK-FIXES: PositiveSeparateDefinition::PositiveSeparateDefinition() : F() {}
+
+struct PositiveMixedFieldOrder {
+ PositiveMixedFieldOrder() : /* some comment */ J(0), L(0), M(0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: I, K, N
+ // CHECK-FIXES: PositiveMixedFieldOrder() : I(), /* some comment */ J(0), K(), L(0), M(0), N() {}
+ int I;
+ int J;
+ int K;
+ int L;
+ int M;
+ int N;
+};
+
+struct PositiveAfterBaseInitializer : public PositiveMixedFieldOrder {
+ PositiveAfterBaseInitializer() : PositiveMixedFieldOrder() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F
+ // CHECK-FIXES: PositiveAfterBaseInitializer() : PositiveMixedFieldOrder(), F() {}
+ int F;
+};
+
+struct NegativeFieldInitialized {
+ int F;
+
+ NegativeFieldInitialized() : F() {}
+};
+
+struct NegativeFieldInitializedInDefinition {
+ int F;
+
+ NegativeFieldInitializedInDefinition();
+};
+
+NegativeFieldInitializedInDefinition::NegativeFieldInitializedInDefinition() : F() {}
+
+struct NegativeInitializedInBody {
+ NegativeInitializedInBody() { I = 0; }
+ int I;
+};
+
+struct NegativeAggregateType {
+ int X;
+ int Y;
+ int Z;
+};
+
+struct TrivialType {
+ int X;
+ int Y;
+};
+
+struct PositiveUninitializedBaseOrdering : public NegativeAggregateType,
+ public TrivialType {
+ PositiveUninitializedBaseOrdering() : NegativeAggregateType(), TrivialType(), B() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A
+ // CHECK-FIXES: PositiveUninitializedBaseOrdering() : NegativeAggregateType(), TrivialType(), A(), B() {}
+
+ // This is somewhat pathological with the base class initializer at the end...
+ PositiveUninitializedBaseOrdering(int) : B(), TrivialType(), A() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType
+ // CHECK-FIXES: PositiveUninitializedBaseOrdering(int) : B(), NegativeAggregateType(), TrivialType(), A() {}
+
+ PositiveUninitializedBaseOrdering(float) : NegativeAggregateType(), A() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: TrivialType
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: constructor does not initialize these fields: B
+ // CHECK-FIXES: PositiveUninitializedBaseOrdering(float) : NegativeAggregateType(), TrivialType(), A(), B() {}
+
+ int A, B;
+};
+
+template <class T>
+class PositiveTemplateBase : T {
+public:
+ PositiveTemplateBase() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: X
+ // CHECK-FIXES: PositiveTemplateBase() : X() {}
+
+ int X;
+};
+
+class PositiveIndirectMember {
+ struct {
+ int *A;
+ };
+
+ PositiveIndirectMember() : A() {}
+ PositiveIndirectMember(int) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A
+ // CHECK-FIXES: PositiveIndirectMember(int) : A() {}
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-delayed.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-delayed.cpp
new file mode 100644
index 0000000..d3436ba
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-delayed.cpp
@@ -0,0 +1,32 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -- -fdelayed-template-parsing
+
+template <class T>
+struct PositiveFieldBeforeConstructor {
+ int F;
+ bool G /* with comment */;
+ int *H;
+ PositiveFieldBeforeConstructor() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F, G, H
+};
+// Explicit instantiation.
+template class PositiveFieldBeforeConstructor<int>;
+
+template <class T>
+struct PositiveFieldAfterConstructor {
+ PositiveFieldAfterConstructor() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F, G, H
+ int F;
+ bool G /* with comment */;
+ int *H;
+};
+// Explicit instantiation.
+template class PositiveFieldAfterConstructor<int>;
+
+// This declaration isn't used and won't be parsed 'delayed-template-parsing'.
+// The body of the declaration is 'null' and may cause crash if not handled
+// properly by checkers.
+template <class T>
+struct UnusedDelayedConstructor {
+ UnusedDelayedConstructor() {}
+ int F;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
new file mode 100644
index 0000000..86f094d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
@@ -0,0 +1,502 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -- -std=c++11 -fno-delayed-template-parsing
+
+struct PositiveFieldBeforeConstructor {
+ int F;
+ // CHECK-FIXES: int F{};
+ PositiveFieldBeforeConstructor() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F
+ // CHECK-FIXES: PositiveFieldBeforeConstructor() {}
+};
+
+struct PositiveFieldAfterConstructor {
+ PositiveFieldAfterConstructor() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F, G
+ // CHECK-FIXES: PositiveFieldAfterConstructor() {}
+ int F;
+ // CHECK-FIXES: int F{};
+ bool G /* with comment */;
+ // CHECK-FIXES: bool G{} /* with comment */;
+ PositiveFieldBeforeConstructor IgnoredField;
+};
+
+struct PositiveSeparateDefinition {
+ PositiveSeparateDefinition();
+ int F;
+ // CHECK-FIXES: int F{};
+};
+
+PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: F
+// CHECK-FIXES: PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+
+struct PositiveMixedFieldOrder {
+ PositiveMixedFieldOrder() : J(0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: I, K
+ // CHECK-FIXES: PositiveMixedFieldOrder() : J(0) {}
+ int I;
+ // CHECK-FIXES: int I{};
+ int J;
+ int K;
+ // CHECK-FIXES: int K{};
+};
+
+template <typename T>
+struct Template {
+ Template() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F
+ int F;
+ // CHECK-FIXES: int F{};
+ T T1;
+ // CHECK-FIXES: T T1;
+};
+
+void instantiate() {
+ Template<int> TInt;
+}
+
+struct NegativeFieldInitialized {
+ int F;
+
+ NegativeFieldInitialized() : F() {}
+};
+
+struct NegativeFieldInitializedInDefinition {
+ int F;
+
+ NegativeFieldInitializedInDefinition();
+};
+NegativeFieldInitializedInDefinition::NegativeFieldInitializedInDefinition() : F() {}
+
+struct NegativeInClassInitialized {
+ int F = 0;
+
+ NegativeInClassInitialized() {}
+};
+
+struct NegativeInClassInitializedDefaulted {
+ int F = 0;
+ NegativeInClassInitializedDefaulted() = default;
+};
+
+struct NegativeConstructorDelegated {
+ int F;
+
+ NegativeConstructorDelegated(int F) : F(F) {}
+ NegativeConstructorDelegated() : NegativeConstructorDelegated(0) {}
+};
+
+struct NegativeInitializedInBody {
+ NegativeInitializedInBody() { I = 0; }
+ int I;
+};
+
+struct A {};
+template <class> class AA;
+template <class T> class NegativeTemplateConstructor {
+ NegativeTemplateConstructor(const AA<T> &, A) {}
+ bool Bool{false};
+ // CHECK-FIXES: bool Bool{false};
+};
+
+#define UNINITIALIZED_FIELD_IN_MACRO_BODY(FIELD) \
+ struct UninitializedField##FIELD { \
+ UninitializedField##FIELD() {} \
+ int FIELD; \
+ }; \
+// Ensure FIELD is not initialized since fixes inside of macros are disabled.
+// CHECK-FIXES: int FIELD;
+
+UNINITIALIZED_FIELD_IN_MACRO_BODY(F);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: F
+UNINITIALIZED_FIELD_IN_MACRO_BODY(G);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: G
+
+#define UNINITIALIZED_FIELD_IN_MACRO_ARGUMENT(ARGUMENT) \
+ ARGUMENT
+
+UNINITIALIZED_FIELD_IN_MACRO_ARGUMENT(struct UninitializedFieldInMacroArg {
+ UninitializedFieldInMacroArg() {}
+ int Field;
+});
+// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: constructor does not initialize these fields: Field
+// Ensure FIELD is not initialized since fixes inside of macros are disabled.
+// CHECK-FIXES: int Field;
+
+struct NegativeAggregateType {
+ int X;
+ int Y;
+ int Z;
+};
+
+struct PositiveTrivialType {
+ PositiveTrivialType() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F
+
+ NegativeAggregateType F;
+ // CHECK-FIXES: NegativeAggregateType F{};
+};
+
+struct NegativeNonTrivialType {
+ PositiveTrivialType F;
+};
+
+static void PositiveUninitializedTrivialType() {
+ NegativeAggregateType X;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: uninitialized record type: 'X'
+ // CHECK-FIXES: NegativeAggregateType X{};
+
+ NegativeAggregateType A[10]; // Don't warn because this isn't an object type.
+}
+
+static void NegativeInitializedTrivialType() {
+ NegativeAggregateType X{};
+ NegativeAggregateType Y = {};
+ NegativeAggregateType Z = NegativeAggregateType();
+ NegativeAggregateType A[10]{};
+ NegativeAggregateType B[10] = {};
+ int C; // No need to initialize this because we don't have a constructor.
+ int D[8];
+ NegativeAggregateType E = {0, 1, 2};
+ NegativeAggregateType F({});
+}
+
+struct NonTrivialType {
+ NonTrivialType() = default;
+ NonTrivialType(const NonTrivialType &RHS) : X(RHS.X), Y(RHS.Y) {}
+
+ int X;
+ int Y;
+};
+
+static void PositiveNonTrivialTypeWithCopyConstructor() {
+ NonTrivialType T;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: uninitialized record type: 'T'
+ // CHECK-FIXES: NonTrivialType T{};
+
+ NonTrivialType A[8];
+ // Don't warn because this isn't an object type
+}
+
+struct ComplexNonTrivialType {
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these fields: Y
+ NegativeFieldInitialized X;
+ int Y;
+ // CHECK-FIXES: int Y{};
+};
+
+static void PositiveComplexNonTrivialType() {
+ ComplexNonTrivialType T;
+}
+
+struct NegativeStaticMember {
+ static NonTrivialType X;
+ static NonTrivialType Y;
+ static constexpr NonTrivialType Z{};
+};
+
+NonTrivialType NegativeStaticMember::X;
+NonTrivialType NegativeStaticMember::Y{};
+
+struct PositiveMultipleConstructors {
+ PositiveMultipleConstructors() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A, B
+
+ PositiveMultipleConstructors(int) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A, B
+
+ PositiveMultipleConstructors(const PositiveMultipleConstructors &) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A, B
+
+ // FIXME: The fix-its here collide providing an erroneous fix
+ int A, B;
+ // CHECK-FIXES: int A{}{}{}, B{}{}{};
+};
+
+typedef struct {
+ int Member;
+} CStyleStruct;
+
+struct PositiveUninitializedBase : public NegativeAggregateType, CStyleStruct {
+ PositiveUninitializedBase() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType, CStyleStruct
+ // CHECK-FIXES: PositiveUninitializedBase() : NegativeAggregateType(), CStyleStruct() {}
+};
+
+struct PositiveUninitializedBaseOrdering : public NegativeAggregateType,
+ public NonTrivialType {
+ PositiveUninitializedBaseOrdering() : B() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType, NonTrivialType
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: constructor does not initialize these fields: A
+ // CHECK-FIXES: PositiveUninitializedBaseOrdering() : NegativeAggregateType(), NonTrivialType(), B() {}
+
+ // This is somewhat pathological with the base class initializer at the end...
+ PositiveUninitializedBaseOrdering(int) : B(), NonTrivialType(), A() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType
+ // CHECK-FIXES: PositiveUninitializedBaseOrdering(int) : B(), NegativeAggregateType(), NonTrivialType(), A() {}
+
+ PositiveUninitializedBaseOrdering(float) : B(), NegativeAggregateType(), A() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NonTrivialType
+ // CHECK-FIXES: PositiveUninitializedBaseOrdering(float) : B(), NegativeAggregateType(), NonTrivialType(), A() {}
+
+ int A, B;
+ // CHECK-FIXES: int A{}, B;
+};
+
+// We shouldn't need to initialize anything because PositiveUninitializedBase
+// has a user-defined constructor.
+struct NegativeUninitializedBase : public PositiveUninitializedBase {
+ NegativeUninitializedBase() {}
+};
+
+struct InheritedAggregate : public NegativeAggregateType {
+ int F;
+};
+
+static InheritedAggregate NegativeGlobal;
+
+enum TestEnum {
+ A,
+ B,
+ C
+};
+
+enum class TestScopedEnum {
+ A,
+ B,
+ C
+};
+
+struct PositiveEnumType {
+ PositiveEnumType() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: X, Y
+ // No proposed fixes, as we don't know whether value initialization for these
+ // enums really makes sense.
+
+ TestEnum X;
+ TestScopedEnum Y;
+};
+
+extern "C" {
+struct NegativeCStruct {
+ int X, Y, Z;
+};
+
+static void PositiveCStructVariable() {
+ NegativeCStruct X;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: uninitialized record type: 'X'
+ // CHECK-FIXES: NegativeCStruct X{};
+}
+}
+
+static void NegativeStaticVariable() {
+ static NegativeCStruct S;
+ (void)S;
+}
+
+union NegativeUnionInClass {
+ NegativeUnionInClass() {} // No message as a union can only initialize one member.
+ int X = 0;
+ float Y;
+};
+
+union PositiveUnion {
+ PositiveUnion() : X() {} // No message as a union can only initialize one member.
+ PositiveUnion(int) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: union constructor should initialize one of these fields: X, Y
+
+ int X;
+ // CHECK-FIXES: int X{};
+
+ // Make sure we don't give Y an initializer.
+ float Y;
+ // CHECK-FIXES-NOT: float Y{};
+};
+
+union PositiveUnionReversed {
+ PositiveUnionReversed() : X() {} // No message as a union can only initialize one member.
+ PositiveUnionReversed(int) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: union constructor should initialize one of these fields: Y, X
+
+ // Make sure we don't give Y an initializer.
+ TestEnum Y;
+ // CHECK-FIXES-NOT: TestEnum Y{};
+
+ int X;
+ // CHECK-FIXES: int X{};
+};
+
+struct PositiveAnonymousUnionAndStruct {
+ PositiveAnonymousUnionAndStruct() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A, B, Y, Z, C, D, E, F, X
+
+ union {
+ int A;
+ // CHECK-FIXES: int A{};
+ short B;
+ };
+
+ struct {
+ int Y;
+ // CHECK-FIXES: int Y{};
+ char *Z;
+ // CHECK-FIXES: char *Z{};
+
+ struct {
+ short C;
+ // CHECK-FIXES: short C{};
+ double D;
+ // CHECK-FIXES: double D{};
+ };
+
+ union {
+ long E;
+ // CHECK-FIXES: long E{};
+ float F;
+ };
+ };
+ int X;
+ // CHECK-FIXES: int X{};
+};
+
+// This check results in a CXXConstructorDecl with no body.
+struct NegativeDeletedConstructor : NegativeAggregateType {
+ NegativeDeletedConstructor() = delete;
+
+ Template<int> F;
+};
+
+// This pathological template fails to compile if actually instantiated. It
+// results in the check seeing a null RecordDecl when examining the base class
+// initializer list.
+template <typename T>
+class PositiveSelfInitialization : NegativeAggregateType
+{
+ PositiveSelfInitialization() : PositiveSelfInitialization() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType
+ // CHECK-FIXES: PositiveSelfInitialization() : NegativeAggregateType(), PositiveSelfInitialization() {}
+};
+
+class PositiveIndirectMember {
+ struct {
+ int *A;
+ // CHECK-FIXES: int *A{};
+ };
+
+ PositiveIndirectMember() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A
+};
+
+void Bug30487()
+{
+ NegativeInClassInitializedDefaulted s;
+}
+
+struct PositiveVirtualMethod {
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these fields: F
+ int F;
+ // CHECK-FIXES: int F{};
+ virtual int f() = 0;
+};
+
+struct PositiveVirtualDestructor {
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these fields: F
+ PositiveVirtualDestructor() = default;
+ int F;
+ // CHECK-FIXES: int F{};
+ virtual ~PositiveVirtualDestructor() {}
+};
+
+struct PositiveVirtualBase : public virtual NegativeAggregateType {
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these bases: NegativeAggregateType
+ // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: constructor does not initialize these fields: F
+ int F;
+ // CHECK-FIXES: int F{};
+};
+
+template <typename T>
+struct PositiveTemplateVirtualDestructor {
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these fields: F
+ T Val;
+ int F;
+ // CHECK-FIXES: int F{};
+ virtual ~PositiveTemplateVirtualDestructor() = default;
+};
+
+template struct PositiveTemplateVirtualDestructor<int>;
+
+#define UNINITIALIZED_FIELD_IN_MACRO_BODY_VIRTUAL(FIELD) \
+ struct UninitializedFieldVirtual##FIELD { \
+ int FIELD; \
+ virtual ~UninitializedFieldVirtual##FIELD() {} \
+ }; \
+// Ensure FIELD is not initialized since fixes inside of macros are disabled.
+// CHECK-FIXES: int FIELD;
+
+UNINITIALIZED_FIELD_IN_MACRO_BODY_VIRTUAL(F);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: F
+UNINITIALIZED_FIELD_IN_MACRO_BODY_VIRTUAL(G);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: G
+
+struct NegativeEmpty {
+};
+
+static void NegativeEmptyVar() {
+ NegativeEmpty e;
+ (void)e;
+}
+
+struct NegativeEmptyMember {
+ NegativeEmptyMember() {}
+ NegativeEmpty e;
+};
+
+struct NegativeEmptyBase : NegativeEmpty {
+ NegativeEmptyBase() {}
+};
+
+struct NegativeEmptyArrayMember {
+ NegativeEmptyArrayMember() {}
+ char e[0];
+};
+
+struct NegativeIncompleteArrayMember {
+ NegativeIncompleteArrayMember() {}
+ char e[];
+};
+
+template <typename T> class NoCrash {
+ class B : public NoCrash {
+ template <typename U> B(U u) {}
+ };
+};
+
+struct PositiveBitfieldMember {
+ PositiveBitfieldMember() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F
+ unsigned F : 5;
+ // CHECK-FIXES-NOT: unsigned F : 5{};
+};
+
+struct NegativeUnnamedBitfieldMember {
+ NegativeUnnamedBitfieldMember() {}
+ unsigned : 5;
+};
+
+struct NegativeInitializedBitfieldMembers {
+ NegativeInitializedBitfieldMembers() : F(3) { G = 2; }
+ unsigned F : 5;
+ unsigned G : 5;
+};
+
+struct NegativeImplicitInheritedCtorBase {
+ NegativeImplicitInheritedCtorBase(unsigned F) : F(F) {}
+ unsigned F;
+};
+
+struct NegativeImplicitInheritedCtor : NegativeImplicitInheritedCtorBase {
+ using NegativeImplicitInheritedCtorBase::NegativeImplicitInheritedCtorBase;
+};
+
+void Bug33557() {
+ NegativeImplicitInheritedCtor I(5);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-reinterpret-cast.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-reinterpret-cast.cpp
new file mode 100644
index 0000000..5420810
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-reinterpret-cast.cpp
@@ -0,0 +1,6 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-reinterpret-cast %t
+
+int i = 0;
+void *j;
+void f() { j = reinterpret_cast<void *>(i); }
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not use reinterpret_cast [cppcoreguidelines-pro-type-reinterpret-cast]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-static-cast-downcast.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-static-cast-downcast.cpp
new file mode 100644
index 0000000..7a6c027
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-static-cast-downcast.cpp
@@ -0,0 +1,118 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-static-cast-downcast %t
+
+class Base {
+};
+
+class Derived : public Base {
+};
+
+class Base2 {
+};
+
+class MultiDerived : public Base, public Base2 {
+};
+
+class PolymorphicBase {
+public:
+ virtual ~PolymorphicBase();
+};
+
+class PolymorphicDerived : public PolymorphicBase {
+};
+
+class PolymorphicMultiDerived : public Base, public PolymorphicBase {
+};
+
+void pointers() {
+
+ auto P0 = static_cast<Derived*>(new Base());
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use static_cast to downcast from a base to a derived class [cppcoreguidelines-pro-type-static-cast-downcast]
+
+ const Base* B0;
+ auto PC0 = static_cast<const Derived*>(B0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use static_cast to downcast from a base to a derived class [cppcoreguidelines-pro-type-static-cast-downcast]
+
+ auto P1 = static_cast<Base*>(new Derived()); // OK, upcast to a public base
+ auto P2 = static_cast<Base*>(new MultiDerived()); // OK, upcast to a public base
+ auto P3 = static_cast<Base2*>(new MultiDerived()); // OK, upcast to a public base
+}
+
+void pointers_polymorphic() {
+
+ auto PP0 = static_cast<PolymorphicDerived*>(new PolymorphicBase());
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead [cppcoreguidelines-pro-type-static-cast-downcast]
+ // CHECK-FIXES: auto PP0 = dynamic_cast<PolymorphicDerived*>(new PolymorphicBase());
+
+ const PolymorphicBase* B0;
+ auto PPC0 = static_cast<const PolymorphicDerived*>(B0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead [cppcoreguidelines-pro-type-static-cast-downcast]
+ // CHECK-FIXES: auto PPC0 = dynamic_cast<const PolymorphicDerived*>(B0);
+
+
+ auto B1 = static_cast<PolymorphicBase*>(new PolymorphicDerived()); // OK, upcast to a public base
+ auto B2 = static_cast<PolymorphicBase*>(new PolymorphicMultiDerived()); // OK, upcast to a public base
+ auto B3 = static_cast<Base*>(new PolymorphicMultiDerived()); // OK, upcast to a public base
+}
+
+void arrays() {
+ Base ArrayOfBase[10];
+ auto A0 = static_cast<Derived*>(ArrayOfBase);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use static_cast to downcast from a base to a derived class [cppcoreguidelines-pro-type-static-cast-downcast]
+}
+
+void arrays_polymorphic() {
+ PolymorphicBase ArrayOfPolymorphicBase[10];
+ auto AP0 = static_cast<PolymorphicDerived*>(ArrayOfPolymorphicBase);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead
+ // CHECK-FIXES: auto AP0 = dynamic_cast<PolymorphicDerived*>(ArrayOfPolymorphicBase);
+}
+
+void references() {
+ Base B0;
+ auto R0 = static_cast<Derived&>(B0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use static_cast to downcast from a base to a derived class [cppcoreguidelines-pro-type-static-cast-downcast]
+ Base& RefToBase = B0;
+ auto R1 = static_cast<Derived&>(RefToBase);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use static_cast to downcast from a base to a derived class [cppcoreguidelines-pro-type-static-cast-downcast]
+
+ const Base& ConstRefToBase = B0;
+ auto RC1 = static_cast<const Derived&>(ConstRefToBase);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use static_cast to downcast from a base to a derived class [cppcoreguidelines-pro-type-static-cast-downcast]
+
+
+ Derived RD1;
+ auto R2 = static_cast<Base&>(RD1); // OK, upcast to a public base
+}
+
+void references_polymorphic() {
+ PolymorphicBase B0;
+ auto RP0 = static_cast<PolymorphicDerived&>(B0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead
+ // CHECK-FIXES: auto RP0 = dynamic_cast<PolymorphicDerived&>(B0);
+
+ PolymorphicBase& RefToPolymorphicBase = B0;
+ auto RP1 = static_cast<PolymorphicDerived&>(RefToPolymorphicBase);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead [cppcoreguidelines-pro-type-static-cast-downcast]
+ // CHECK-FIXES: auto RP1 = dynamic_cast<PolymorphicDerived&>(RefToPolymorphicBase);
+
+ const PolymorphicBase& ConstRefToPolymorphicBase = B0;
+ auto RPC2 = static_cast<const PolymorphicDerived&>(ConstRefToPolymorphicBase);
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead [cppcoreguidelines-pro-type-static-cast-downcast]
+ // CHECK-FIXES: auto RPC2 = dynamic_cast<const PolymorphicDerived&>(ConstRefToPolymorphicBase);
+
+ PolymorphicDerived d1;
+ auto RP2 = static_cast<PolymorphicBase&>(d1); // OK, upcast to a public base
+}
+
+template<class B, class D>
+void templ() {
+ auto B0 = static_cast<B*>(new D());
+}
+
+void templ_bad_call() {
+ templ<Derived, Base>(); //FIXME: this should trigger a warning
+}
+
+void templ_good_call() {
+ templ<Base, Derived>(); // OK, upcast to a public base
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-union-access.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-union-access.cpp
new file mode 100644
index 0000000..6abc22b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-union-access.cpp
@@ -0,0 +1,41 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-union-access %t
+
+union U {
+ bool union_member1;
+ char union_member2;
+} u;
+
+struct S {
+ int non_union_member;
+ union {
+ bool union_member;
+ };
+ union {
+ char union_member2;
+ } u;
+} s;
+
+
+void f(char);
+void f2(U);
+void f3(U&);
+void f4(U*);
+
+void check()
+{
+ u.union_member1 = true;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not access members of unions; use (boost::)variant instead [cppcoreguidelines-pro-type-union-access]
+ auto b = u.union_member2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not access members of unions; use (boost::)variant instead
+ auto a = &s.union_member;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: do not access members of unions; use (boost::)variant instead
+ f(s.u.union_member2);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not access members of unions; use (boost::)variant instead
+
+ s.non_union_member = 2; // OK
+
+ U u2 = u; // OK
+ f2(u); // OK
+ f3(u); // OK
+ f4(&u); // OK
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-vararg.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-vararg.cpp
new file mode 100644
index 0000000..021322a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-vararg.cpp
@@ -0,0 +1,51 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-vararg %t
+
+void f(int i);
+void f_vararg(int i, ...);
+
+struct C {
+ void g_vararg(...);
+ void g(const char*);
+} c;
+
+template<typename... P>
+void cpp_vararg(P... p);
+
+void check() {
+ f_vararg(1, 7, 9);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not call c-style vararg functions [cppcoreguidelines-pro-type-vararg]
+ c.g_vararg("foo");
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not call c-style vararg functions
+
+ f(3); // OK
+ c.g("foo"); // OK
+ cpp_vararg(1, 7, 9); // OK
+}
+
+// ... as a parameter is allowed (e.g. for SFINAE)
+template <typename T>
+void CallFooIfAvailableImpl(T& t, ...) {
+ // nothing
+}
+template <typename T>
+void CallFooIfAvailableImpl(T& t, decltype(t.foo())*) {
+ t.foo();
+}
+template <typename T>
+void CallFooIfAvailable(T& t) {
+ CallFooIfAvailableImpl(t, 0); // OK to call variadic function when the argument is a literal 0
+}
+
+#include <stdarg.h>
+void my_printf(const char* format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not call c-style vararg functions
+ va_list n;
+ va_copy(n, ap); // Don't warn, va_copy is anyway useless without va_start
+ int i = va_arg(ap, int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use va_start/va_arg to define c-style vararg functions; use variadic templates instead
+ va_end(ap); // Don't warn, va_end is anyway useless without va_start
+}
+
+int my_vprintf(const char* format, va_list arg ); // OK to declare function taking va_list
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-slicing.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-slicing.cpp
new file mode 100644
index 0000000..6856f52
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-slicing.cpp
@@ -0,0 +1,100 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-slicing %t
+
+class Base {
+ int i;
+ void f() {}
+ virtual void g() {}
+};
+
+class DerivedWithMemberVariables : public Base {
+ void f();
+ int j;
+};
+
+class TwiceDerivedWithNoMemberVariables : public DerivedWithMemberVariables {
+ void f();
+};
+
+class DerivedWithOverride : public Base {
+ void f();
+ void g() override {}
+};
+
+class TwiceDerivedWithNoOverride : public DerivedWithOverride {
+ void f();
+};
+
+void TakesBaseByValue(Base base);
+
+DerivedWithMemberVariables ReturnsDerived();
+
+void positivesWithMemberVariables() {
+ DerivedWithMemberVariables b;
+ Base a{b};
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state [cppcoreguidelines-slicing]
+ a = b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state
+ TakesBaseByValue(b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state
+
+ TwiceDerivedWithNoMemberVariables c;
+ a = c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'TwiceDerivedWithNoMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state
+
+ a = ReturnsDerived();
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state
+}
+
+void positivesWithOverride() {
+ DerivedWithOverride b;
+ Base a{b};
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+ a = b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+ TakesBaseByValue(b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+
+ TwiceDerivedWithNoOverride c;
+ a = c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+}
+
+void TakesBaseByReference(Base &base);
+
+class DerivedThatAddsVirtualH : public Base {
+ virtual void h();
+};
+
+class DerivedThatOverridesH : public DerivedThatAddsVirtualH {
+ void h() override;
+};
+
+void negatives() {
+ // OK, simple copying from the same type.
+ Base a;
+ TakesBaseByValue(a);
+ DerivedWithMemberVariables b;
+ DerivedWithMemberVariables c{b};
+ b = c;
+
+ // OK, derived type does not have extra state.
+ TwiceDerivedWithNoMemberVariables d;
+ DerivedWithMemberVariables e{d};
+ e = d;
+
+ // OK, derived does not override any method.
+ TwiceDerivedWithNoOverride f;
+ DerivedWithOverride g{f};
+ g = f;
+
+ // OK, no copying.
+ TakesBaseByReference(d);
+ TakesBaseByReference(f);
+
+ // Derived type overrides methods, but these methods are not in the base type,
+ // so cannot be called accidentally. Right now this triggers, but we might
+ // want to allow it.
+ DerivedThatOverridesH h;
+ a = h;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedThatOverridesH' to 'Base' discards override 'h'
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-special-member-functions-cxx-03.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-special-member-functions-cxx-03.cpp
new file mode 100644
index 0000000..8fe5e42
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-special-member-functions-cxx-03.cpp
@@ -0,0 +1,26 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-special-member-functions %t -- -- -std=c++03
+
+class DefinesDestructor {
+ ~DefinesDestructor();
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesDestructor' defines a non-default destructor but does not define a copy constructor or a copy assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesCopyConstructor {
+ DefinesCopyConstructor(const DefinesCopyConstructor &);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesCopyConstructor' defines a copy constructor but does not define a destructor or a copy assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesCopyAssignment {
+ DefinesCopyAssignment &operator=(const DefinesCopyAssignment &);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesCopyAssignment' defines a copy assignment operator but does not define a destructor or a copy constructor [cppcoreguidelines-special-member-functions]
+
+class DefinesNothing {
+};
+
+class DefinesEverything {
+ DefinesEverything(const DefinesEverything &);
+ DefinesEverything &operator=(const DefinesEverything &);
+ ~DefinesEverything();
+};
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-special-member-functions-relaxed.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-special-member-functions-relaxed.cpp
new file mode 100644
index 0000000..4fff02d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-special-member-functions-relaxed.cpp
@@ -0,0 +1,71 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-special-member-functions %t -- -config="{CheckOptions: [{key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions, value: 1}, {key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor, value: 1}]}" --
+
+class DefinesDestructor {
+ ~DefinesDestructor();
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesDestructor' defines a non-default destructor but does not define a copy constructor or a copy assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesDefaultedDestructor {
+ ~DefinesDefaultedDestructor() = default;
+};
+
+class DefinesCopyConstructor {
+ DefinesCopyConstructor(const DefinesCopyConstructor &);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesCopyConstructor' defines a copy constructor but does not define a destructor or a copy assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesCopyAssignment {
+ DefinesCopyAssignment &operator=(const DefinesCopyAssignment &);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesCopyAssignment' defines a copy assignment operator but does not define a destructor or a copy constructor [cppcoreguidelines-special-member-functions]
+
+class DefinesMoveConstructor {
+ DefinesMoveConstructor(DefinesMoveConstructor &&);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesMoveConstructor' defines a move constructor but does not define a destructor, a copy constructor, a copy assignment operator or a move assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesMoveAssignment {
+ DefinesMoveAssignment &operator=(DefinesMoveAssignment &&);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesMoveAssignment' defines a move assignment operator but does not define a destructor, a copy constructor, a copy assignment operator or a move constructor [cppcoreguidelines-special-member-functions]
+class DefinesNothing {
+};
+
+class DefinesEverything {
+ DefinesEverything(const DefinesEverything &);
+ DefinesEverything &operator=(const DefinesEverything &);
+ DefinesEverything(DefinesEverything &&);
+ DefinesEverything &operator=(DefinesEverything &&);
+ ~DefinesEverything();
+};
+
+class DeletesEverything {
+ DeletesEverything(const DeletesEverything &) = delete;
+ DeletesEverything &operator=(const DeletesEverything &) = delete;
+ DeletesEverything(DeletesEverything &&) = delete;
+ DeletesEverything &operator=(DeletesEverything &&) = delete;
+ ~DeletesEverything() = delete;
+};
+
+class DeletesCopyDefaultsMove {
+ DeletesCopyDefaultsMove(const DeletesCopyDefaultsMove &) = delete;
+ DeletesCopyDefaultsMove &operator=(const DeletesCopyDefaultsMove &) = delete;
+ DeletesCopyDefaultsMove(DeletesCopyDefaultsMove &&) = default;
+ DeletesCopyDefaultsMove &operator=(DeletesCopyDefaultsMove &&) = default;
+ ~DeletesCopyDefaultsMove() = default;
+};
+
+template <typename T>
+struct TemplateClass {
+ TemplateClass() = default;
+ TemplateClass(const TemplateClass &);
+ TemplateClass &operator=(const TemplateClass &);
+ TemplateClass(TemplateClass &&);
+ TemplateClass &operator=(TemplateClass &&);
+ ~TemplateClass();
+};
+
+// Multiple instantiations of a class template will trigger multiple matches for defined special members.
+// This should not cause problems.
+TemplateClass<int> InstantiationWithInt;
+TemplateClass<double> InstantiationWithDouble;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-special-member-functions.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-special-member-functions.cpp
new file mode 100644
index 0000000..013ba86
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-special-member-functions.cpp
@@ -0,0 +1,72 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-special-member-functions %t
+
+class DefinesDestructor {
+ ~DefinesDestructor();
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesDestructor' defines a non-default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesDefaultedDestructor {
+ ~DefinesDefaultedDestructor() = default;
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesDefaultedDestructor' defines a default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesCopyConstructor {
+ DefinesCopyConstructor(const DefinesCopyConstructor &);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesCopyConstructor' defines a copy constructor but does not define a destructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesCopyAssignment {
+ DefinesCopyAssignment &operator=(const DefinesCopyAssignment &);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesCopyAssignment' defines a copy assignment operator but does not define a destructor, a copy constructor, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesMoveConstructor {
+ DefinesMoveConstructor(DefinesMoveConstructor &&);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesMoveConstructor' defines a move constructor but does not define a destructor, a copy constructor, a copy assignment operator or a move assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesMoveAssignment {
+ DefinesMoveAssignment &operator=(DefinesMoveAssignment &&);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesMoveAssignment' defines a move assignment operator but does not define a destructor, a copy constructor, a copy assignment operator or a move constructor [cppcoreguidelines-special-member-functions]
+class DefinesNothing {
+};
+
+class DefinesEverything {
+ DefinesEverything(const DefinesEverything &);
+ DefinesEverything &operator=(const DefinesEverything &);
+ DefinesEverything(DefinesEverything &&);
+ DefinesEverything &operator=(DefinesEverything &&);
+ ~DefinesEverything();
+};
+
+class DeletesEverything {
+ DeletesEverything(const DeletesEverything &) = delete;
+ DeletesEverything &operator=(const DeletesEverything &) = delete;
+ DeletesEverything(DeletesEverything &&) = delete;
+ DeletesEverything &operator=(DeletesEverything &&) = delete;
+ ~DeletesEverything() = delete;
+};
+
+class DeletesCopyDefaultsMove {
+ DeletesCopyDefaultsMove(const DeletesCopyDefaultsMove &) = delete;
+ DeletesCopyDefaultsMove &operator=(const DeletesCopyDefaultsMove &) = delete;
+ DeletesCopyDefaultsMove(DeletesCopyDefaultsMove &&) = default;
+ DeletesCopyDefaultsMove &operator=(DeletesCopyDefaultsMove &&) = default;
+ ~DeletesCopyDefaultsMove() = default;
+};
+
+template <typename T>
+struct TemplateClass {
+ TemplateClass() = default;
+ TemplateClass(const TemplateClass &);
+ TemplateClass &operator=(const TemplateClass &);
+ TemplateClass(TemplateClass &&);
+ TemplateClass &operator=(TemplateClass &&);
+ ~TemplateClass();
+};
+
+// Multiple instantiations of a class template will trigger multiple matches for defined special members.
+// This should not cause problems.
+TemplateClass<int> InstantiationWithInt;
+TemplateClass<double> InstantiationWithDouble;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/custom-diagnostics.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/custom-diagnostics.cpp
new file mode 100644
index 0000000..8183770
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/custom-diagnostics.cpp
@@ -0,0 +1,27 @@
+// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-shadow,clang-diagnostic-float-conversion' %s -- | count 0
+//
+// Enable warnings using -config:
+// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-shadow,clang-diagnostic-float-conversion' \
+// RUN: -config='{ExtraArgs: ["-Wshadow","-Wno-unused-variable"], ExtraArgsBefore: ["-Wno-shadow","-Wfloat-conversion","-Wunused-variable"]}' %s -- \
+// RUN: | FileCheck -implicit-check-not='{{warning:|error:}}' %s
+//
+// ... -extra-arg:
+// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-shadow,clang-diagnostic-float-conversion' \
+// RUN: -extra-arg=-Wshadow -extra-arg=-Wno-unused-variable \
+// RUN: -extra-arg-before=-Wno-shadow -extra-arg-before=-Wfloat-conversion \
+// RUN: -extra-arg-before=-Wunused-variable %s -- \
+// RUN: | FileCheck -implicit-check-not='{{warning:|error:}}' %s
+//
+// ... a combination of -config and -extra-arg(-before):
+// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-shadow,clang-diagnostic-float-conversion' \
+// RUN: -config='{ExtraArgs: ["-Wno-unused-variable"], ExtraArgsBefore: ["-Wno-shadow","-Wfloat-conversion"]}' \
+// RUN: -extra-arg=-Wshadow -extra-arg-before=-Wunused-variable %s -- \
+// RUN: | FileCheck -implicit-check-not='{{warning:|error:}}' %s
+
+void f(float x) {
+ int a;
+ { int a; }
+ // CHECK: :[[@LINE-1]]:9: warning: declaration shadows a local variable [clang-diagnostic-shadow]
+ int b = x;
+ // CHECK: :[[@LINE-1]]:11: warning: implicit conversion turns floating-point number into integer: 'float' to 'int' [clang-diagnostic-float-conversion]
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/deduplication.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/deduplication.cpp
new file mode 100644
index 0000000..056fe4e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/deduplication.cpp
@@ -0,0 +1,10 @@
+// RUN: %check_clang_tidy %s google-explicit-constructor %t
+
+template<typename T>
+struct A { A(T); };
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: single-argument constructors must be marked explicit
+
+void f() {
+ A<int> a(0);
+ A<double> b(0);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/diagnostic.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/diagnostic.cpp
new file mode 100644
index 0000000..d12fc7b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/diagnostic.cpp
@@ -0,0 +1,50 @@
+// RUN: not clang-tidy -checks='-*,modernize-use-override' %s.nonexistent.cpp -- | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %s -- -fan-unknown-option | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %s -- -fan-unknown-option | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %s -- -DMACRO_FROM_COMMAND_LINE | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,modernize-use-override' %s -- -DCOMPILATION_ERROR | FileCheck -check-prefix=CHECK6 -implicit-check-not='{{warning:|error:}}' %s
+//
+// Now repeat the tests and ensure no other errors appear on stderr:
+// RUN: not clang-tidy -checks='-*,modernize-use-override' %s.nonexistent.cpp -- 2>&1 | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %s -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %s -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %s -- -DMACRO_FROM_COMMAND_LINE 2>&1 | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,modernize-use-override' %s -- -DCOMPILATION_ERROR 2>&1 | FileCheck -check-prefix=CHECK6 -implicit-check-not='{{warning:|error:}}' %s
+//
+// Now create a directory with a compilation database file and ensure we don't
+// use it after failing to parse commands from the command line:
+//
+// RUN: mkdir -p %T/diagnostics/
+// RUN: echo '[{"directory": "%/T/diagnostics/","command": "clang++ -fan-option-from-compilation-database -c %/T/diagnostics/input.cpp", "file": "%/T/diagnostics/input.cpp"}]' > %T/diagnostics/compile_commands.json
+// RUN: cat %s > %T/diagnostics/input.cpp
+// RUN: not clang-tidy -checks='-*,modernize-use-override' %T/diagnostics/nonexistent.cpp -- 2>&1 | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %T/diagnostics/input.cpp -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %T/diagnostics/input.cpp -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %T/diagnostics/input.cpp -- -DMACRO_FROM_COMMAND_LINE 2>&1 | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %T/diagnostics/input.cpp 2>&1 | FileCheck -check-prefix=CHECK5 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,modernize-use-override' %T/diagnostics/input.cpp -- -DCOMPILATION_ERROR 2>&1 | FileCheck -check-prefix=CHECK6 -implicit-check-not='{{warning:|error:}}' %s
+
+// CHECK1: error: error reading '{{.*}}nonexistent.cpp' [clang-diagnostic-error]
+// CHECK2: error: unknown argument: '-fan-unknown-option' [clang-diagnostic-error]
+// CHECK3: error: unknown argument: '-fan-unknown-option' [clang-diagnostic-error]
+// CHECK5: error: unknown argument: '-fan-option-from-compilation-database' [clang-diagnostic-error]
+
+// CHECK2: :[[@LINE+3]]:9: warning: implicit conversion from 'double' to 'int' changes value from 1.5 to 1 [clang-diagnostic-literal-conversion]
+// CHECK3: :[[@LINE+2]]:9: warning: implicit conversion from 'double' to 'int' changes value
+// CHECK5: :[[@LINE+1]]:9: warning: implicit conversion from 'double' to 'int' changes value
+int a = 1.5;
+
+// CHECK2: :[[@LINE+3]]:11: warning: single-argument constructors must be marked explicit
+// CHECK3: :[[@LINE+2]]:11: warning: single-argument constructors must be marked explicit
+// CHECK5: :[[@LINE+1]]:11: warning: single-argument constructors must be marked explicit
+class A { A(int) {} };
+
+#define MACRO_FROM_COMMAND_LINE
+// CHECK4: :[[@LINE-1]]:9: warning: 'MACRO_FROM_COMMAND_LINE' macro redefined
+
+#ifdef COMPILATION_ERROR
+void f(int a) {
+ &(a + 1);
+ // CHECK6: :[[@LINE-1]]:3: error: cannot take the address of an rvalue of type 'int' [clang-diagnostic-error]
+}
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/enable-alpha-checks.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/enable-alpha-checks.cpp
new file mode 100644
index 0000000..b1e5130
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/enable-alpha-checks.cpp
@@ -0,0 +1,6 @@
+// Check if '-allow-enabling-analyzer-alpha-checkers' is visible for users.
+// RUN: clang-tidy -help | not grep 'allow-enabling-analyzer-alpha-checkers'
+
+// Check if '-allow-enabling-analyzer-alpha-checkers' enables alpha checks.
+// RUN: clang-tidy -checks=* -list-checks | not grep 'clang-analyzer-alpha'
+// RUN: clang-tidy -checks=* -list-checks -allow-enabling-analyzer-alpha-checkers | grep 'clang-analyzer-alpha'
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/explain-checks.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/explain-checks.cpp
new file mode 100644
index 0000000..9bff30c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/explain-checks.cpp
@@ -0,0 +1,12 @@
+// RUN: clang-tidy -checks=-*,modernize-use-nullptr -explain-config | FileCheck --check-prefix=CHECK-MESSAGE1 %s
+// RUN: clang-tidy -config="{Checks: '-*,modernize-use-nullptr'}" -explain-config | FileCheck --check-prefix=CHECK-MESSAGE2 %s
+// RUN: clang-tidy -checks=modernize-use-nullptr -config="{Checks: '-*,modernize-use-nullptr'}" -explain-config | FileCheck --check-prefix=CHECK-MESSAGE3 %s
+// RUN: clang-tidy -checks=modernize-use-nullptr -config="{Checks: '-*,-modernize-use-nullptr'}" %S/Inputs/explain-config/a.cc -explain-config -- | FileCheck --check-prefix=CHECK-MESSAGE4 %s
+// RUN: clang-tidy -checks=modernize-use-nullptr -config="{Checks: '-*,modernize-*'}" -explain-config | FileCheck --check-prefix=CHECK-MESSAGE5 %s
+// RUN: clang-tidy -explain-config %S/Inputs/explain-config/a.cc -- | grep "'modernize-use-nullptr' is enabled in the .*[/\\]Inputs[/\\]explain-config[/\\].clang-tidy."
+
+// CHECK-MESSAGE1: 'modernize-use-nullptr' is enabled in the command-line option '-checks'.
+// CHECK-MESSAGE2: 'modernize-use-nullptr' is enabled in the command-line option '-config'.
+// CHECK-MESSAGE3: 'modernize-use-nullptr' is enabled in the command-line option '-checks'.
+// CHECK-MESSAGE4: 'modernize-use-nullptr' is enabled in the command-line option '-checks'.
+// CHECK-MESSAGE5: 'modernize-use-nullptr' is enabled in the command-line option '-checks'.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/extra-args.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/extra-args.cpp
new file mode 100644
index 0000000..d65aacc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/extra-args.cpp
@@ -0,0 +1,7 @@
+// RUN: clang-tidy -checks='-*,modernize-use-override' \
+// RUN: -config='{ExtraArgs: ["-DTEST4"], ExtraArgsBefore: ["-DTEST1"]}' \
+// RUN: -extra-arg=-DTEST3 -extra-arg-before=-DTEST2 %s -- -v 2>&1 \
+// RUN: | FileCheck -implicit-check-not='{{warning:|error:}}' %s
+
+// CHECK: {{^}}clang Invocation:{{$}}
+// CHECK-NEXT: {{"-D" "TEST1" .*"-D" "TEST2" .*"-D" "TEST3" .*"-D" "TEST4"}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/file-filter.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/file-filter.cpp
new file mode 100644
index 0000000..9ee5cad
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/file-filter.cpp
@@ -0,0 +1,73 @@
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='' %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck %s
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='' -quiet %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK-QUIET %s
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK2 %s
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -quiet %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK2-QUIET %s
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='header2\.h' %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK3 %s
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='header2\.h' -quiet %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK3-QUIET %s
+// FIXME: "-I %S/Inputs/file-filter/system/.." must be redundant.
+// On Win32, file-filter/system\system-header1.h precedes
+// file-filter\header*.h due to code order between '/' and '\\'.
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -system-headers %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK4 %s
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -system-headers -quiet %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK4-QUIET %s
+
+#include "header1.h"
+// CHECK-NOT: warning:
+// CHECK-QUIET-NOT: warning:
+// CHECK2: header1.h:1:12: warning: single-argument constructors must be marked explicit
+// CHECK2-QUIET: header1.h:1:12: warning: single-argument constructors must be marked explicit
+// CHECK3-NOT: warning:
+// CHECK3-QUIET-NOT: warning:
+// CHECK4: header1.h:1:12: warning: single-argument constructors
+// CHECK4-QUIET: header1.h:1:12: warning: single-argument constructors
+
+#include "header2.h"
+// CHECK-NOT: warning:
+// CHECK-QUIET-NOT: warning:
+// CHECK2: header2.h:1:12: warning: single-argument constructors
+// CHECK2-QUIET: header2.h:1:12: warning: single-argument constructors
+// CHECK3: header2.h:1:12: warning: single-argument constructors
+// CHECK3-QUIET: header2.h:1:12: warning: single-argument constructors
+// CHECK4: header2.h:1:12: warning: single-argument constructors
+// CHECK4-QUIET: header2.h:1:12: warning: single-argument constructors
+
+#include <system-header.h>
+// CHECK-NOT: warning:
+// CHECK-QUIET-NOT: warning:
+// CHECK2-NOT: warning:
+// CHECK2-QUIET-NOT: warning:
+// CHECK3-NOT: warning:
+// CHECK3-QUIET-NOT: warning:
+// CHECK4: system-header.h:1:12: warning: single-argument constructors
+// CHECK4-QUIET: system-header.h:1:12: warning: single-argument constructors
+
+class A { A(int); };
+// CHECK: :[[@LINE-1]]:11: warning: single-argument constructors
+// CHECK-QUIET: :[[@LINE-2]]:11: warning: single-argument constructors
+// CHECK2: :[[@LINE-3]]:11: warning: single-argument constructors
+// CHECK2-QUIET: :[[@LINE-4]]:11: warning: single-argument constructors
+// CHECK3: :[[@LINE-5]]:11: warning: single-argument constructors
+// CHECK3-QUIET: :[[@LINE-6]]:11: warning: single-argument constructors
+// CHECK4: :[[@LINE-7]]:11: warning: single-argument constructors
+// CHECK4-QUIET: :[[@LINE-8]]:11: warning: single-argument constructors
+
+// CHECK-NOT: warning:
+// CHECK-QUIET-NOT: warning:
+// CHECK2-NOT: warning:
+// CHECK2-QUIET-NOT: warning:
+// CHECK3-NOT: warning:
+// CHECK3-QUIET-NOT: warning:
+// CHECK4-NOT: warning:
+// CHECK4-QUIET-NOT: warning:
+
+// CHECK: Suppressed 3 warnings (3 in non-user code)
+// CHECK: Use -header-filter=.* to display errors from all non-system headers.
+// CHECK-QUIET-NOT: Suppressed
+// CHECK2: Suppressed 1 warnings (1 in non-user code)
+// CHECK2: Use -header-filter=.* {{.*}}
+// CHECK2-QUIET-NOT: Suppressed
+// CHECK3: Suppressed 2 warnings (2 in non-user code)
+// CHECK3: Use -header-filter=.* {{.*}}
+// CHECK3-QUIET-NOT: Suppressed
+// CHECK4-NOT: Suppressed {{.*}} warnings
+// CHECK4-NOT: Use -header-filter=.* {{.*}}
+// CHECK4-QUIET-NOT: Suppressed
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fix-errors.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fix-errors.cpp
new file mode 100644
index 0000000..0c02616
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fix-errors.cpp
@@ -0,0 +1,15 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: not clang-tidy %t.cpp -checks='-*,google-explicit-constructor' -fix -- > %t.msg 2>&1
+// RUN: FileCheck -input-file=%t.cpp -check-prefix=CHECK-FIX %s
+// RUN: FileCheck -input-file=%t.msg -check-prefix=CHECK-MESSAGES %s
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: clang-tidy %t.cpp -checks='-*,google-explicit-constructor' -fix-errors -- > %t.msg 2>&1
+// RUN: FileCheck -input-file=%t.cpp -check-prefix=CHECK-FIX2 %s
+// RUN: FileCheck -input-file=%t.msg -check-prefix=CHECK-MESSAGES2 %s
+
+class A { A(int i); }
+// CHECK-FIX: class A { A(int i); }{{$}}
+// CHECK-MESSAGES: Fixes have NOT been applied.
+// CHECK-FIX2: class A { explicit A(int i); };
+// CHECK-MESSAGES2: note: FIX-IT applied suggested code changes
+// CHECK-MESSAGES2: clang-tidy applied 2 of 2 suggested fixes.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fix.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fix.cpp
new file mode 100644
index 0000000..db6bc22
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fix.cpp
@@ -0,0 +1,18 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: clang-tidy %t.cpp -checks='-*,google-explicit-constructor,llvm-namespace-comment' -fix -export-fixes=%t.yaml -- > %t.msg 2>&1
+// RUN: FileCheck -input-file=%t.cpp %s
+// RUN: FileCheck -input-file=%t.msg -check-prefix=CHECK-MESSAGES %s
+// RUN: FileCheck -input-file=%t.yaml -check-prefix=CHECK-YAML %s
+
+namespace i {
+void f(); // So that the namespace isn't empty.
+}
+// CHECK: } // namespace i
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-YAML: ReplacementText: ' // namespace i'
+
+class A { A(int i); };
+// CHECK: class A { explicit A(int i); };
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-MESSAGES: clang-tidy applied 2 of 2 suggested fixes.
+// CHECK-YAML: ReplacementText: 'explicit '
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-default-arguments.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-default-arguments.cpp
new file mode 100644
index 0000000..f7b1ae6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-default-arguments.cpp
@@ -0,0 +1,81 @@
+// RUN: %check_clang_tidy %s fuchsia-default-arguments %t
+
+int foo(int value = 5) { return value; }
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments]
+// CHECK-FIXES: int foo(int value) { return value; }
+
+int f() {
+ foo();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling a function that uses a default argument is disallowed [fuchsia-default-arguments]
+ // CHECK-NEXT: note: default parameter was declared here:
+ // CHECK-NEXT: int foo(int value = 5) { return value; }
+}
+
+int bar(int value) { return value; }
+
+int n() {
+ foo(0);
+ bar(0);
+}
+
+class Baz {
+public:
+ int a(int value = 5) { return value; }
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments]
+ // CHECK-FIXES: int a(int value) { return value; }
+
+ int b(int value) { return value; }
+};
+
+class Foo {
+ // Fix should be suggested in declaration
+ int a(int value = 53);
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments]
+ // CHECK-FIXES: int a(int value);
+};
+
+// Fix shouldn't be suggested in implementation
+int Foo::a(int value) {
+ return value;
+}
+
+// Elided functions
+void f(int = 5) {};
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments]
+// CHECK-FIXES: void f(int) {};
+
+void g(int) {};
+
+// Should not suggest fix for macro-defined parameters
+#define D(val) = val
+
+void h(int i D(5));
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments]
+// CHECK-FIXES-NOT: void h(int i);
+
+void x(int i);
+void x(int i = 12);
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments]
+// CHECK-FIXES: void x(int i);
+
+void x(int i) {}
+
+struct S {
+ void x(int i);
+};
+
+void S::x(int i = 12) {}
+// CHECK-MESSAGES: [[@LINE-1]]:11: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments]
+// CHECK-FIXES: void S::x(int i) {}
+
+int main() {
+ S s;
+ s.x();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling a function that uses a default argument is disallowed [fuchsia-default-arguments]
+ // CHECK-NEXT: note: default parameter was declared here:
+ // CHECK-NEXT: void S::x(int i = 12) {}
+ x();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling a function that uses a default argument is disallowed [fuchsia-default-arguments]
+ // CHECK-NEXT: note: default parameter was declared here:
+ // CHECK-NEXT: void x(int i = 12);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-multiple-inheritance.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-multiple-inheritance.cpp
new file mode 100644
index 0000000..fd2ed14
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-multiple-inheritance.cpp
@@ -0,0 +1,147 @@
+// RUN: %check_clang_tidy %s fuchsia-multiple-inheritance %t
+
+class Base_A {
+public:
+ virtual int foo() { return 0; }
+};
+
+class Base_B {
+public:
+ virtual int bar() { return 0; }
+};
+
+class Base_A_child : public Base_A {
+public:
+ virtual int baz() { return 0; }
+};
+
+class Interface_A {
+public:
+ virtual int foo() = 0;
+};
+
+class Interface_B {
+public:
+ virtual int bar() = 0;
+};
+
+class Interface_C {
+public:
+ virtual int blat() = 0;
+};
+
+class Interface_A_with_member {
+public:
+ virtual int foo() = 0;
+ int val = 0;
+};
+
+class Interface_with_A_Parent : public Base_A {
+public:
+ virtual int baz() = 0;
+};
+
+// Inherits from multiple concrete classes.
+// CHECK-MESSAGES: [[@LINE+2]]:1: warning: inheriting mulitple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance]
+// CHECK-NEXT: class Bad_Child1 : public Base_A, Base_B {};
+class Bad_Child1 : public Base_A, Base_B {};
+
+// CHECK-MESSAGES: [[@LINE+1]]:1: warning: inheriting mulitple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance]
+class Bad_Child2 : public Base_A, Interface_A_with_member {
+ virtual int foo() override { return 0; }
+};
+
+// CHECK-MESSAGES: [[@LINE+2]]:1: warning: inheriting mulitple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance]
+// CHECK-NEXT: class Bad_Child3 : public Interface_with_A_Parent, Base_B {
+class Bad_Child3 : public Interface_with_A_Parent, Base_B {
+ virtual int baz() override { return 0; }
+};
+
+// Easy cases of single inheritance
+class Simple_Child1 : public Base_A {};
+class Simple_Child2 : public Interface_A {
+ virtual int foo() override { return 0; }
+};
+
+// Valid uses of multiple inheritance
+class Good_Child1 : public Interface_A, Interface_B {
+ virtual int foo() override { return 0; }
+ virtual int bar() override { return 0; }
+};
+
+class Good_Child2 : public Base_A, Interface_B {
+ virtual int bar() override { return 0; }
+};
+
+class Good_Child3 : public Base_A_child, Interface_C, Interface_B {
+ virtual int bar() override { return 0; }
+ virtual int blat() override { return 0; }
+};
+
+struct B1 { int x; };
+struct B2 { int x;};
+// CHECK-MESSAGES: [[@LINE+2]]:1: warning: inheriting mulitple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance]
+// CHECK-NEXT: struct D : B1, B2 {};
+struct D1 : B1, B2 {};
+
+struct Base1 { virtual void foo() = 0; };
+struct V1 : virtual Base1 {};
+struct V2 : virtual Base1 {};
+struct D2 : V1, V2 {};
+
+struct Base2 { virtual void foo(); };
+struct V3 : virtual Base2 {};
+struct V4 : virtual Base2 {};
+struct D3 : V3, V4 {};
+
+struct Base3 {};
+struct V5 : virtual Base3 { virtual void f(); };
+struct V6 : virtual Base3 { virtual void g(); };
+// CHECK-MESSAGES: [[@LINE+2]]:1: warning: inheriting mulitple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance]
+// CHECK-NEXT: struct D4 : V5, V6 {};
+struct D4 : V5, V6 {};
+
+struct Base4 {};
+struct V7 : virtual Base4 { virtual void f() = 0; };
+struct V8 : virtual Base4 { virtual void g() = 0; };
+struct D5 : V7, V8 {};
+
+struct Base5 { virtual void f() = 0; };
+struct V9 : virtual Base5 { virtual void f(); };
+struct V10 : virtual Base5 { virtual void g() = 0; };
+struct D6 : V9, V10 {};
+
+struct Base6 { virtual void f(); };
+struct Base7 { virtual void g(); };
+struct V15 : virtual Base6 { virtual void f() = 0; };
+struct V16 : virtual Base7 { virtual void g() = 0; };
+// CHECK-MESSAGES: [[@LINE+2]]:1: warning: inheriting mulitple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance]
+// CHECK-NEXT: struct D9 : V15, V16 {};
+struct D9 : V15, V16 {};
+
+struct Static_Base { static void foo(); };
+struct V11 : virtual Static_Base {};
+struct V12 : virtual Static_Base {};
+struct D7 : V11, V12 {};
+
+struct Static_Base_2 {};
+struct V13 : virtual Static_Base_2 { static void f(); };
+struct V14 : virtual Static_Base_2 { static void g(); };
+struct D8 : V13, V14 {};
+
+template<typename T> struct A : T {};
+template<typename T> struct B : virtual T {};
+
+template<typename> struct C {};
+template<typename T> struct D : C<T> {};
+
+// Check clang_tidy does not crash on this code.
+template <class T>
+struct WithTemplBase : T {
+ WithTemplBase();
+};
+
+int test_no_crash() {
+ auto foo = []() {};
+ WithTemplBase<decltype(foo)>();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-overloaded-operator.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-overloaded-operator.cpp
new file mode 100644
index 0000000..be65a32
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-overloaded-operator.cpp
@@ -0,0 +1,21 @@
+// RUN: %check_clang_tidy %s fuchsia-overloaded-operator %t
+
+class A {
+public:
+ int operator+(int);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: overloading 'operator+' is disallowed
+};
+
+class B {
+public:
+ B &operator=(const B &Other);
+ // CHECK-MESSAGES-NOT: [[@LINE-1]]:3: warning: overloading 'operator=' is disallowed
+ B &operator=(B &&Other);
+ // CHECK-MESSAGES-NOT: [[@LINE-1]]:3: warning: overloading 'operator=' is disallowed
+};
+
+A operator-(const A &A1, const A &A2);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: overloading 'operator-' is disallowed
+
+void operator delete(void*, void*) throw();
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: overloading 'operator delete' is disallowed
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes-all.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes-all.cpp
new file mode 100644
index 0000000..21f4b68
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes-all.cpp
@@ -0,0 +1,10 @@
+// RUN: %check_clang_tidy %s fuchsia-restrict-system-includes %t \
+// RUN: -- -config="{CheckOptions: [{key: fuchsia-restrict-system-includes.Includes, value: ''}]}" \
+// RUN: -- -std=c++11 -I %S/Inputs/fuchsia-restrict-system-includes -isystem %S/Inputs/fuchsia-restrict-system-includes/system
+
+#include <cstdlib.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: system include cstdlib.h not allowed
+#include <cstdarg.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: system include cstdarg.h not allowed
+#include <t.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: system include t.h not allowed
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes-glob.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes-glob.cpp
new file mode 100644
index 0000000..334990d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes-glob.cpp
@@ -0,0 +1,9 @@
+// RUN: %check_clang_tidy %s fuchsia-restrict-system-includes %t \
+// RUN: -- -config="{CheckOptions: [{key: fuchsia-restrict-system-includes.Includes, value: 'cstd*'}]}" \
+// RUN: -- -std=c++11 -I %S/Inputs/fuchsia-restrict-system-includes -isystem %S/Inputs/fuchsia-restrict-system-includes/system
+
+#include <cstdlib.h>
+#include <cstdarg.h>
+#include <t.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: system include t.h not allowed
+// CHECK-FIXES-NOT: #include <t.h>
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes-headers.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes-headers.cpp
new file mode 100644
index 0000000..f392eac
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes-headers.cpp
@@ -0,0 +1,23 @@
+// RUN: rm -rf %T/Headers
+// RUN: mkdir %T/Headers
+// RUN: cp -r %S/Inputs/fuchsia-restrict-system-includes %T/Headers/fuchsia-restrict-system-includes
+// RUN: %check_clang_tidy %s fuchsia-restrict-system-includes %t \
+// RUN: -- -config="{CheckOptions: [{key: fuchsia-restrict-system-includes.Includes, value: 'transitive.h,s.h'}]}" \
+// RUN: -system-headers -header-filter=.* \
+// RUN: -- -std=c++11 -I %T/Headers/fuchsia-restrict-system-includes -isystem %T/Headers/fuchsia-restrict-system-includes/system
+// RUN: FileCheck -input-file=%T/Headers/fuchsia-restrict-system-includes/transitive2.h %s -check-prefix=CHECK-FIXES
+// RUN: rm -rf %T/Headers
+
+// transitive.h includes <r.h> and <t.h>
+#include <transitive.h>
+// CHECK-MESSAGES: :1:1: warning: system include r.h not allowed, transitively included from {{.*}}
+// CHECK-MESSAGES: :2:1: warning: system include t.h not allowed, transitively included from {{.*}}
+
+// transitive.h includes <s.h> and <t.h>
+#include "transitive2.h"
+// CHECK-MESSAGES: :2:1: warning: system include t.h not allowed, transitively included from {{.*}}
+// CHECK-FIXES-NOT: #include <t.h>
+
+int main() {
+ // f() is declared in r.h
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes.cpp
new file mode 100644
index 0000000..e2ba710
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s fuchsia-restrict-system-includes %t \
+// RUN: -- -config="{CheckOptions: [{key: fuchsia-restrict-system-includes.Includes, value: 's.h'}]}" \
+// RUN: -- -std=c++11 -I %S/Inputs/fuchsia-restrict-system-includes -isystem %S/Inputs/fuchsia-restrict-system-includes/system
+
+#include "a.h"
+
+#include <s.h>
+#include <t.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: system include t.h not allowed
+// CHECK-FIXES-NOT: #include <t.h>
+
+#include "s.h"
+#include "t.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: system include t.h not allowed
+// CHECK-FIXES-NOT: #include "t.h"
+
+#define foo <j.h>
+
+#include foo
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: system include j.h not allowed
+// CHECK-FIXES-NOT: #include foo
+
+#/* comment */ include /* comment */ foo
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: system include j.h not allowed
+// CHECK-FIXES-NOT: # /* comment */ include /* comment */ foo
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-statically-constructed-objects.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-statically-constructed-objects.cpp
new file mode 100644
index 0000000..006494e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-statically-constructed-objects.cpp
@@ -0,0 +1,91 @@
+// RUN: %check_clang_tidy %s fuchsia-statically-constructed-objects %t
+
+// Trivial static is fine
+static int i;
+
+class ClassWithNoCtor {};
+
+class ClassWithCtor {
+public:
+ ClassWithCtor(int Val) : Val(Val) {}
+private:
+ int Val;
+};
+
+class ClassWithConstexpr {
+public:
+ ClassWithConstexpr(int Val1, int Val2) : Val(Val1) {}
+ constexpr ClassWithConstexpr(int Val) : Val(Val) {}
+
+private:
+ int Val;
+};
+
+ClassWithNoCtor A;
+ClassWithConstexpr C(0);
+ClassWithConstexpr E(0, 1);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
+// CHECK-MESSAGES-NEXT: ClassWithConstexpr E(0, 1);
+ClassWithCtor G(0);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
+// CHECK-MESSAGES-NEXT: ClassWithCtor G(0);
+
+static ClassWithNoCtor A2;
+static ClassWithConstexpr C2(0);
+static ClassWithConstexpr E2(0, 1);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
+// CHECK-MESSAGES-NEXT: static ClassWithConstexpr E2(0, 1);
+static ClassWithCtor G2(0);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
+// CHECK-MESSAGES-NEXT: static ClassWithCtor G2(0);
+
+struct StructWithConstexpr { constexpr StructWithConstexpr(int Val) {} };
+struct StructWithNoCtor {};
+struct StructWithCtor { StructWithCtor(); };
+
+StructWithNoCtor SNoCtor;
+StructWithConstexpr SConstexpr(0);
+StructWithCtor SCtor;
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
+// CHECK-MESSAGES-NEXT: StructWithCtor SCtor;
+
+static StructWithConstexpr SConstexpr2(0);
+static StructWithNoCtor SNoCtor2;
+static StructWithCtor SCtor2;
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
+// CHECK-MESSAGES-NEXT: static StructWithCtor SCtor2;
+
+extern StructWithCtor SCtor3;
+
+class ClassWithStaticMember {
+private:
+ static StructWithNoCtor S;
+};
+
+ClassWithStaticMember Z();
+
+class S {
+ int Val;
+public:
+ constexpr S(int i) : Val(100 / i) {}
+ int getVal() const { return Val; }
+};
+
+static S s1(1);
+static S s2(0);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
+// CHECK-MESSAGES-NEXT: static S s2(0);
+
+extern int get_i();
+static S s3(get_i());
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
+// CHECK-MESSAGES-NEXT: static S s3(get_i());
+
+void f() {
+ // Locally static is fine
+ static int i;
+ static ClassWithNoCtor A2;
+ static ClassWithConstexpr C2(0);
+ static ClassWithConstexpr E2(0, 1);
+ static ClassWithCtor G2(0);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-trailing-return.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-trailing-return.cpp
new file mode 100644
index 0000000..f6c943a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-trailing-return.cpp
@@ -0,0 +1,23 @@
+// RUN: %check_clang_tidy %s fuchsia-trailing-return %t
+
+int add_one(const int arg) { return arg; }
+
+auto get_add_one() -> int (*)(const int) {
+ // CHECK-MESSAGES: [[@LINE-1]]:1: warning: a trailing return type is disallowed for this type of declaration
+ // CHECK-NEXT: auto get_add_one() -> int (*)(const int) {
+ return add_one;
+}
+
+auto lambda = [](double x, double y) {return x + y;};
+
+auto lambda2 = [](double x, double y) -> double {return x + y;};
+
+int main() {
+ get_add_one()(5);
+ return 0;
+}
+
+template <typename T1, typename T2>
+auto fn(const T1 &lhs, const T2 &rhs) -> decltype(lhs + rhs) {
+ return lhs + rhs;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-virtual-inheritance.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-virtual-inheritance.cpp
new file mode 100644
index 0000000..0c3311a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-virtual-inheritance.cpp
@@ -0,0 +1,42 @@
+// RUN: %check_clang_tidy %s fuchsia-virtual-inheritance %t
+
+class A {
+public:
+ A(int value) : val(value) {}
+
+ int do_A() { return val; }
+
+private:
+ int val;
+};
+
+class B : public virtual A {
+ // CHECK-MESSAGES: [[@LINE-1]]:1: warning: direct virtual inheritance is disallowed [fuchsia-virtual-inheritance]
+ // CHECK-NEXT: class B : public virtual A {
+public:
+ B() : A(0) {}
+ int do_B() { return 1 + do_A(); }
+};
+
+class C : public virtual A {
+ // CHECK-MESSAGES: [[@LINE-1]]:1: warning: direct virtual inheritance is disallowed [fuchsia-virtual-inheritance]
+ // CHECK-NEXT: class C : public virtual A {
+public:
+ C() : A(0) {}
+ int do_C() { return 2 + do_A(); }
+};
+
+class D : public B, public C {
+public:
+ D(int value) : A(value), B(), C() {}
+
+ int do_D() { return do_A() + do_B() + do_C(); }
+};
+
+int main() {
+ A *a = new A(0);
+ B *b = new B();
+ C *c = new C();
+ D *d = new D(0);
+ return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-build-explicit-make-pair.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-build-explicit-make-pair.cpp
new file mode 100644
index 0000000..6dcd357
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-build-explicit-make-pair.cpp
@@ -0,0 +1,51 @@
+// RUN: %check_clang_tidy %s google-build-explicit-make-pair %t
+
+namespace std {
+template <class T1, class T2>
+struct pair {
+ pair(T1 x, T2 y) {}
+};
+
+template <class T1, class T2>
+pair<T1, T2> make_pair(T1 x, T2 y) {
+ return pair<T1, T2>(x, y);
+}
+}
+
+template <typename T>
+void templ(T a, T b) {
+ std::make_pair<T, unsigned>(a, b);
+ std::make_pair<int, int>(1, 2);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: for C++11-compatibility, omit template arguments from make_pair
+// CHECK-FIXES: std::make_pair(1, 2)
+}
+
+template <typename T>
+int t();
+
+void test(int i) {
+ std::make_pair<int, int>(i, i);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: for C++11-compatibility, omit template arguments from make_pair
+// CHECK-FIXES: std::make_pair(i, i)
+
+ std::make_pair<unsigned, int>(i, i);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: for C++11-compatibility, use pair directly
+// CHECK-FIXES: std::pair<unsigned, int>(i, i)
+
+ std::make_pair<int, unsigned>(i, i);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: for C++11-compatibility, use pair directly
+// CHECK-FIXES: std::pair<int, unsigned>(i, i)
+
+#define M std::make_pair<int, unsigned>(i, i);
+M
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: for C++11-compatibility, use pair directly
+// Can't fix in macros.
+// CHECK-FIXES: #define M std::make_pair<int, unsigned>(i, i);
+// CHECK-FIXES-NEXT: M
+
+ templ(i, i);
+ templ(1U, 2U);
+
+ std::make_pair(i, 1); // no-warning
+ std::make_pair(t<int>, 1);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-default-arguments.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-default-arguments.cpp
new file mode 100644
index 0000000..48d3f2d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-default-arguments.cpp
@@ -0,0 +1,29 @@
+// RUN: %check_clang_tidy %s google-default-arguments %t
+
+struct A {
+ virtual void f(int I, int J = 3);
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: default arguments on virtual or override methods are prohibited [google-default-arguments]
+};
+
+struct B : public A {
+ void f(int I, int J = 5);
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: default arguments on virtual or override methods are prohibited
+};
+
+struct C : public B {
+ void f(int I, int J = 5) override;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: default arguments on virtual or override methods are prohibited
+};
+
+// Negatives.
+struct D : public B {
+ void f(int I, int J) override;
+};
+
+struct X {
+ void f(int I, int J = 3);
+};
+
+struct Y : public X {
+ void f(int I, int J = 5);
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-explicit-constructor.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-explicit-constructor.cpp
new file mode 100644
index 0000000..921237a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-explicit-constructor.cpp
@@ -0,0 +1,188 @@
+// RUN: %check_clang_tidy %s google-explicit-constructor %t
+
+namespace std {
+ typedef decltype(sizeof(int)) size_t;
+
+ // libc++'s implementation
+ template <class _E>
+ class initializer_list
+ {
+ const _E* __begin_;
+ size_t __size_;
+
+ initializer_list(const _E* __b, size_t __s)
+ : __begin_(__b),
+ __size_(__s)
+ {}
+
+ public:
+ typedef _E value_type;
+ typedef const _E& reference;
+ typedef const _E& const_reference;
+ typedef size_t size_type;
+
+ typedef const _E* iterator;
+ typedef const _E* const_iterator;
+
+ initializer_list() : __begin_(nullptr), __size_(0) {}
+
+ size_t size() const {return __size_;}
+ const _E* begin() const {return __begin_;}
+ const _E* end() const {return __begin_ + __size_;}
+ };
+}
+
+struct A {
+ A() {}
+ A(int x, int y) {}
+
+ explicit A(void *x) {}
+ explicit A(void *x, void *y) {}
+ explicit operator bool() const { return true; }
+
+ operator double() const = delete;
+
+ explicit A(const A& a) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: copy constructor should not be declared explicit [google-explicit-constructor]
+ // CHECK-FIXES: {{^ }}A(const A& a) {}
+
+ A(int x1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: single-argument constructors must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor]
+ // CHECK-FIXES: {{^ }}explicit A(int x1);
+
+ A(double x2, double y = 3.14) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructors that are callable with a single argument must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor]
+ // CHECK-FIXES: {{^ }}explicit A(double x2, double y = 3.14) {}
+
+ template <typename... T>
+ A(T&&... args);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructors that are callable with a single argument
+ // CHECK-FIXES: {{^ }}explicit A(T&&... args);
+};
+
+inline A::A(int x1) {}
+
+struct B {
+ B(std::initializer_list<int> list1) {}
+ B(const std::initializer_list<unsigned> &list2) {}
+ B(std::initializer_list<unsigned> &&list3) {}
+
+ operator bool() const { return true; }
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator bool' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor]
+ // CHECK-FIXES: {{^ }}explicit operator bool() const { return true; }
+
+ operator double() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator double' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor]
+ // CHECK-FIXES: {{^ }}explicit operator double() const;
+
+ explicit B(::std::initializer_list<double> list4) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: initializer-list constructor should not be declared explicit [google-explicit-constructor]
+ // CHECK-FIXES: {{^ }}B(::std::initializer_list<double> list4) {}
+
+ explicit B(const ::std::initializer_list<char> &list5) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: initializer-list constructor
+ // CHECK-FIXES: {{^ }}B(const ::std::initializer_list<char> &list5) {}
+
+ explicit B(::std::initializer_list<char> &&list6) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: initializer-list constructor
+ // CHECK-FIXES: {{^ }}B(::std::initializer_list<char> &&list6) {}
+};
+
+inline B::operator double() const { return 0.0; }
+
+struct StructWithFnPointer {
+ void (*f)();
+} struct_with_fn_pointer = {[] {}};
+
+using namespace std;
+
+struct C {
+ C(initializer_list<int> list1) {}
+ C(const initializer_list<unsigned> &list2) {}
+ C(initializer_list<unsigned> &&list3) {}
+};
+
+template <typename T>
+struct C2 {
+ C2(initializer_list<int> list1) {}
+ C2(const initializer_list<unsigned> &list2) {}
+ C2(initializer_list<unsigned> &&list3) {}
+
+ explicit C2(initializer_list<double> list4) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: initializer-list constructor
+ // CHECK-FIXES: {{^ }}C2(initializer_list<double> list4) {}
+};
+
+template <typename T>
+struct C3 {
+ C3(initializer_list<T> list1) {}
+ C3(const std::initializer_list<T*> &list2) {}
+ C3(::std::initializer_list<T**> &&list3) {}
+
+ template <typename U>
+ C3(initializer_list<U> list3) {}
+};
+
+struct D {
+ template <typename T>
+ explicit D(T t) {}
+};
+
+template <typename T>
+struct E {
+ E(T *pt) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: single-argument constructors
+ // CHECK-FIXES: {{^ }}explicit E(T *pt) {}
+ template <typename U>
+ E(U *pu) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: single-argument constructors
+ // CHECK-FIXES: {{^ }}explicit E(U *pu) {}
+
+ explicit E(T t) {}
+ template <typename U>
+ explicit E(U u) {}
+};
+
+void f(std::initializer_list<int> list) {
+ D d(list);
+ E<decltype(list)> e(list);
+ E<int> e2(list);
+}
+
+template <typename T>
+struct F {};
+
+template<typename T>
+struct G {
+ operator bool() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator bool' must be marked
+ // CHECK-FIXES: {{^}} explicit operator bool() const;
+ operator F<T>() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator F<type-parameter-0-0>' must be marked
+ // CHECK-FIXES: {{^}} explicit operator F<T>() const;
+ template<typename U>
+ operator F<U>*() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator F<type-parameter-1-0> *' must be marked
+ // CHECK-FIXES: {{^}} explicit operator F<U>*() const;
+};
+
+void f2() {
+ G<int> a;
+ (void)(F<int>)a;
+ if (a) {}
+ (void)(F<int>*)a;
+ (void)(F<int*>*)a;
+
+ G<double> b;
+ (void)(F<double>)b;
+ if (b) {}
+ (void)(F<double>*)b;
+ (void)(F<double*>*)b;
+}
+
+#define DEFINE_STRUCT_WITH_OPERATOR_BOOL(name) \
+ struct name { \
+ operator bool() const; \
+ }
+
+DEFINE_STRUCT_WITH_OPERATOR_BOOL(H);
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-module.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-module.cpp
new file mode 100644
index 0000000..494ac48
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-module.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-tidy -checks='-*,google*' -config='{}' -dump-config - -- | FileCheck %s
+// CHECK: CheckOptions:
+// CHECK: {{- key: *google-readability-braces-around-statements.ShortStatementLines}}
+// CHECK-NEXT: {{value: *'1'}}
+// CHECK: {{- key: *google-readability-function-size.StatementThreshold}}
+// CHECK-NEXT: {{value: *'800'}}
+// CHECK: {{- key: *google-readability-namespace-comments.ShortNamespaceLines}}
+// CHECK-NEXT: {{value: *'10'}}
+// CHECK: {{- key: *google-readability-namespace-comments.SpacesBeforeComments}}
+// CHECK-NEXT: {{value: *'2'}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-namespaces.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-namespaces.cpp
new file mode 100644
index 0000000..9bda3c0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-namespaces.cpp
@@ -0,0 +1,52 @@
+// RUN: clang-tidy %s -checks='-*,google-build-namespaces,google-build-using-namespace' -header-filter='.*' -- | FileCheck %s -implicit-check-not="{{warning|error}}:"
+#include "Inputs/google-namespaces.h"
+// CHECK: warning: do not use unnamed namespaces in header files [google-build-namespaces]
+
+using namespace spaaaace;
+// CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
+
+using spaaaace::core; // no-warning
+
+namespace std {
+inline namespace literals {
+inline namespace chrono_literals {
+}
+inline namespace complex_literals {
+}
+inline namespace string_literals {
+}
+}
+}
+
+using namespace std::chrono_literals; // no-warning
+using namespace std::complex_literals; // no-warning
+using namespace std::literals; // no-warning
+using namespace std::literals::chrono_literals; // no-warning
+using namespace std::literals::complex_literals; // no-warning
+using namespace std::literals::string_literals; // no-warning
+using namespace std::string_literals; // no-warning
+
+namespace literals {}
+
+using namespace literals;
+// CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
+
+namespace foo {
+inline namespace literals {
+inline namespace bar_literals {}
+}
+}
+
+using namespace foo::literals;
+// CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
+
+using namespace foo::bar_literals;
+// CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
+
+using namespace foo::literals::bar_literals;
+// CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
+
+namespace foo_literals {}
+
+using namespace foo_literals;
+// CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-objc-avoid-throwing-exception.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-objc-avoid-throwing-exception.m
new file mode 100644
index 0000000..7fa32e7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-objc-avoid-throwing-exception.m
@@ -0,0 +1,32 @@
+// RUN: %check_clang_tidy %s google-objc-avoid-throwing-exception %t
+@class NSString;
+
+@interface NSException
+
++ (void)raise:(NSString *)name format:(NSString *)format;
++ (void)raise:(NSString *)name format:(NSString *)format arguments:(NSString *)args; // using NSString type since va_list cannot be recognized here
+
+@end
+
+@interface NotException
+
++ (void)raise:(NSString *)name format:(NSString *)format;
+
+@end
+
+@implementation Foo
+- (void)f {
+ NSString *foo = @"foo";
+ @throw foo;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass in NSError ** instead of throwing exception to indicate Objective-C errors [google-objc-avoid-throwing-exception]
+}
+
+- (void)f2 {
+ [NSException raise:@"TestException" format:@"Test"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: pass in NSError ** instead of throwing exception to indicate Objective-C errors [google-objc-avoid-throwing-exception]
+ [NSException raise:@"TestException" format:@"Test %@" arguments:@"bar"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: pass in NSError ** instead of throwing exception to indicate Objective-C errors [google-objc-avoid-throwing-exception]
+ [NotException raise:@"NotException" format:@"Test"];
+}
+@end
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-objc-global-variable-declaration.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-objc-global-variable-declaration.m
new file mode 100644
index 0000000..346ddec
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-objc-global-variable-declaration.m
@@ -0,0 +1,49 @@
+// RUN: %check_clang_tidy %s google-objc-global-variable-declaration %t
+
+@class NSString;
+static NSString* const myConstString = @"hello";
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: const global variable 'myConstString' must have a name which starts with an appropriate prefix [google-objc-global-variable-declaration]
+// CHECK-FIXES: static NSString* const kMyConstString = @"hello";
+
+static NSString* MyString = @"hi";
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: non-const global variable 'MyString' must have a name which starts with 'g[A-Z]' [google-objc-global-variable-declaration]
+// CHECK-FIXES: static NSString* gMyString = @"hi";
+
+NSString* globalString = @"test";
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: non-const global variable 'globalString' must have a name which starts with 'g[A-Z]' [google-objc-global-variable-declaration]
+// CHECK-FIXES: NSString* gGlobalString = @"test";
+
+static NSString* a = @"too simple";
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: non-const global variable 'a' must have a name which starts with 'g[A-Z]' [google-objc-global-variable-declaration]
+// CHECK-FIXES: static NSString* a = @"too simple";
+
+static NSString* noDef;
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: non-const global variable 'noDef' must have a name which starts with 'g[A-Z]' [google-objc-global-variable-declaration]
+// CHECK-FIXES: static NSString* gNoDef;
+
+static NSString* const _notAlpha = @"NotBeginWithAlpha";
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: const global variable '_notAlpha' must have a name which starts with an appropriate prefix [google-objc-global-variable-declaration]
+// CHECK-FIXES: static NSString* const _notAlpha = @"NotBeginWithAlpha";
+
+static NSString* const k_Alpha = @"SecondNotAlpha";
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: const global variable 'k_Alpha' must have a name which starts with an appropriate prefix [google-objc-global-variable-declaration]
+// CHECK-FIXES: static NSString* const k_Alpha = @"SecondNotAlpha";
+
+static NSString* const kGood = @"hello";
+static NSString* const XYGood = @"hello";
+static NSString* gMyIntGood = 0;
+
+extern NSString* const GTLServiceErrorDomain;
+
+enum GTLServiceError {
+ GTLServiceErrorQueryResultMissing = -3000,
+ GTLServiceErrorWaitTimedOut = -3001,
+};
+
+@implementation Foo
+- (void)f {
+ int x = 0;
+ static int bar;
+ static const int baz = 42;
+}
+@end
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-overloaded-unary-and.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-overloaded-unary-and.cpp
new file mode 100644
index 0000000..16893d2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-overloaded-unary-and.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s google-runtime-operator %t
+
+struct Foo {
+ void *operator&();
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not overload unary operator&, it is dangerous. [google-runtime-operator]
+};
+
+template <typename T>
+struct TFoo {
+ T *operator&();
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not overload unary operator&
+};
+
+TFoo<int> tfoo;
+
+struct Bar;
+void *operator&(Bar &b);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not overload unary operator&
+
+// No warnings on binary operators.
+struct Qux {
+ void *operator&(Qux &q);
+};
+
+void *operator&(Qux &q, Qux &r);
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-casting.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-casting.c
new file mode 100644
index 0000000..488bcd7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-casting.c
@@ -0,0 +1,24 @@
+// RUN: %check_clang_tidy %s google-readability-casting %t -- -- -x c
+// The testing script always adds .cpp extension to the input file name, so we
+// need to run clang-tidy directly in order to verify handling of .c files:
+// RUN: clang-tidy --checks=-*,google-readability-casting %s -- -x c++ | FileCheck %s -check-prefix=CHECK-MESSAGES -implicit-check-not='{{warning|error}}:'
+// RUN: cp %s %t.main_file.cpp
+// RUN: clang-tidy --checks=-*,google-readability-casting -header-filter='.*' %t.main_file.cpp -- -I%S -DTEST_INCLUDE -x c++ | FileCheck %s -check-prefix=CHECK-MESSAGES -implicit-check-not='{{warning|error}}:'
+
+#ifdef TEST_INCLUDE
+
+#undef TEST_INCLUDE
+#include "google-readability-casting.c"
+
+#else
+
+void f(const char *cpc) {
+ const char *cpc2 = (const char*)cpc;
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: redundant cast to the same type [google-readability-casting]
+ // CHECK-FIXES: const char *cpc2 = cpc;
+ char *pc = (char*)cpc;
+ typedef const char *Typedef1;
+ (Typedef1)cpc;
+}
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-casting.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-casting.cpp
new file mode 100644
index 0000000..d36fef6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-casting.cpp
@@ -0,0 +1,323 @@
+// RUN: %check_clang_tidy %s google-readability-casting %t
+
+bool g() { return false; }
+
+enum Enum { Enum1 };
+struct X {};
+struct Y : public X {};
+
+void f(int a, double b, const char *cpc, const void *cpv, X *pX) {
+ const char *cpc2 = (const char*)cpc;
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: redundant cast to the same type [google-readability-casting]
+ // CHECK-FIXES: const char *cpc2 = cpc;
+
+ typedef const char *Typedef1;
+ typedef const char *Typedef2;
+ Typedef1 t1;
+ (Typedef2)t1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: C-style casts are discouraged; use static_cast (if needed, the cast may be redundant) [google-readability-casting]
+ // CHECK-FIXES: {{^}} static_cast<Typedef2>(t1);
+ (const char*)t1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast (if needed
+ // CHECK-FIXES: {{^}} static_cast<const char*>(t1);
+ (Typedef1)cpc;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast (if needed
+ // CHECK-FIXES: {{^}} static_cast<Typedef1>(cpc);
+ (Typedef1)t1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant cast to the same type
+ // CHECK-FIXES: {{^}} t1;
+
+ char *pc = (char*)cpc;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use const_cast [google-readability-casting]
+ // CHECK-FIXES: char *pc = const_cast<char*>(cpc);
+ typedef char Char;
+ Char *pChar = (Char*)pc;
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}}; use static_cast (if needed
+ // CHECK-FIXES: {{^}} Char *pChar = static_cast<Char*>(pc);
+
+ (Char)*cpc;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast (if needed
+ // CHECK-FIXES: {{^}} static_cast<Char>(*cpc);
+
+ (char)*pChar;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast (if needed
+ // CHECK-FIXES: {{^}} static_cast<char>(*pChar);
+
+ (const char*)cpv;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast [
+ // CHECK-FIXES: static_cast<const char*>(cpv);
+
+ char *pc2 = (char*)(cpc + 33);
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}}; use const_cast [
+ // CHECK-FIXES: char *pc2 = const_cast<char*>(cpc + 33);
+
+ const char &crc = *cpc;
+ char &rc = (char&)crc;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}}; use const_cast [
+ // CHECK-FIXES: char &rc = const_cast<char&>(crc);
+
+ char &rc2 = (char&)*cpc;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}}; use const_cast [
+ // CHECK-FIXES: char &rc2 = const_cast<char&>(*cpc);
+
+ char ** const* const* ppcpcpc;
+ char ****ppppc = (char****)ppcpcpc;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: {{.*}}; use const_cast [
+ // CHECK-FIXES: char ****ppppc = const_cast<char****>(ppcpcpc);
+
+ char ***pppc = (char***)*(ppcpcpc);
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: {{.*}}; use const_cast [
+ // CHECK-FIXES: char ***pppc = const_cast<char***>(*(ppcpcpc));
+
+ char ***pppc2 = (char***)(*ppcpcpc);
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: {{.*}}; use const_cast [
+ // CHECK-FIXES: char ***pppc2 = const_cast<char***>(*ppcpcpc);
+
+ char *pc5 = (char*)(const char*)(cpv);
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}}; use const_cast [
+ // CHECK-MESSAGES: :[[@LINE-2]]:22: warning: {{.*}}; use static_cast [
+ // CHECK-FIXES: char *pc5 = const_cast<char*>(static_cast<const char*>(cpv));
+
+ int b1 = (int)b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: {{.*}}; use static_cast [
+ // CHECK-FIXES: int b1 = static_cast<int>(b);
+ b1 = (const int&)b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [
+ // CHECK-FIXES: b1 = (const int&)b;
+
+ b1 = (int) b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast {{.*}}
+ // CHECK-FIXES: b1 = static_cast<int>(b);
+
+ b1 = (int) b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast {{.*}}
+ // CHECK-FIXES: b1 = static_cast<int>(b);
+
+ b1 = (int) (b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast {{.*}}
+ // CHECK-FIXES: b1 = static_cast<int>(b);
+
+ b1 = (int) (b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast {{.*}}
+ // CHECK-FIXES: b1 = static_cast<int>(b);
+
+ Y *pB = (Y*)pX;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [
+ Y &rB = (Y&)*pX;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [
+
+ const char *pc3 = (const char*)cpv;
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: {{.*}}; use static_cast [
+ // CHECK-FIXES: const char *pc3 = static_cast<const char*>(cpv);
+
+ char *pc4 = (char*)cpv;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [
+ // CHECK-FIXES: char *pc4 = (char*)cpv;
+
+ b1 = (int)Enum1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast [
+ // CHECK-FIXES: b1 = static_cast<int>(Enum1);
+
+ Enum e = (Enum)b1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: {{.*}}; use static_cast [
+ // CHECK-FIXES: Enum e = static_cast<Enum>(b1);
+
+ e = (Enum)Enum1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type
+ // CHECK-FIXES: {{^}} e = Enum1;
+
+ e = (Enum)e;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type
+ // CHECK-FIXES: {{^}} e = e;
+
+ e = (Enum) e;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type
+ // CHECK-FIXES: {{^}} e = e;
+
+ e = (Enum) (e);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type
+ // CHECK-FIXES: {{^}} e = (e);
+
+ static const int kZero = 0;
+ (int)kZero;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant cast to the same type
+ // CHECK-FIXES: {{^}} kZero;
+
+ int b2 = int(b);
+ int b3 = static_cast<double>(b);
+ int b4 = b;
+ double aa = a;
+ (void)b2;
+ return (void)g();
+}
+
+template <typename T>
+void template_function(T t, int n) {
+ int i = (int)t;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [
+ // CHECK-FIXES: int i = (int)t;
+ int j = (int)n;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant cast to the same type
+ // CHECK-FIXES: int j = n;
+}
+
+template <typename T>
+struct TemplateStruct {
+ void f(T t, int n) {
+ int k = (int)t;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast
+ // CHECK-FIXES: int k = (int)t;
+ int l = (int)n;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant cast to the same type
+ // CHECK-FIXES: int l = n;
+ }
+};
+
+void test_templates() {
+ template_function(1, 42);
+ template_function(1.0, 42);
+ TemplateStruct<int>().f(1, 42);
+ TemplateStruct<double>().f(1.0, 42);
+}
+
+extern "C" {
+void extern_c_code(const char *cpc) {
+ const char *cpc2 = (const char*)cpc;
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: redundant cast to the same type
+ // CHECK-FIXES: const char *cpc2 = cpc;
+ char *pc = (char*)cpc;
+}
+}
+
+#define CAST(type, value) (type)(value)
+void macros(double d) {
+ int i = CAST(int, d);
+}
+
+enum E { E1 = 1 };
+template <E e>
+struct A {
+ // Usage of template argument e = E1 is represented as (E)1 in the AST for
+ // some reason. We have a special treatment of this case to avoid warnings
+ // here.
+ static const E ee = e;
+};
+struct B : public A<E1> {};
+
+
+void overloaded_function();
+void overloaded_function(int);
+
+template<typename Fn>
+void g(Fn fn) {
+ fn();
+}
+
+void function_casts() {
+ typedef void (*FnPtrVoid)();
+ typedef void (&FnRefVoid)();
+ typedef void (&FnRefInt)(int);
+
+ g((void (*)())overloaded_function);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: g(static_cast<void (*)()>(overloaded_function));
+ g((void (*)())&overloaded_function);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: g(static_cast<void (*)()>(&overloaded_function));
+ g((void (&)())overloaded_function);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: g(static_cast<void (&)()>(overloaded_function));
+
+ g((FnPtrVoid)overloaded_function);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: g(static_cast<FnPtrVoid>(overloaded_function));
+ g((FnPtrVoid)&overloaded_function);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: g(static_cast<FnPtrVoid>(&overloaded_function));
+ g((FnRefVoid)overloaded_function);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: g(static_cast<FnRefVoid>(overloaded_function));
+
+ FnPtrVoid fn0 = (void (*)())&overloaded_function;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: FnPtrVoid fn0 = static_cast<void (*)()>(&overloaded_function);
+ FnPtrVoid fn1 = (void (*)())overloaded_function;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: FnPtrVoid fn1 = static_cast<void (*)()>(overloaded_function);
+ FnPtrVoid fn1a = (FnPtrVoid)overloaded_function;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: FnPtrVoid fn1a = static_cast<FnPtrVoid>(overloaded_function);
+ FnRefInt fn2 = (void (&)(int))overloaded_function;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: FnRefInt fn2 = static_cast<void (&)(int)>(overloaded_function);
+ auto fn3 = (void (*)())&overloaded_function;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: auto fn3 = static_cast<void (*)()>(&overloaded_function);
+ auto fn4 = (void (*)())overloaded_function;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: auto fn4 = static_cast<void (*)()>(overloaded_function);
+ auto fn5 = (void (&)(int))overloaded_function;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: auto fn5 = static_cast<void (&)(int)>(overloaded_function);
+
+ void (*fn6)() = (void (*)())&overloaded_function;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: void (*fn6)() = static_cast<void (*)()>(&overloaded_function);
+ void (*fn7)() = (void (*)())overloaded_function;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: void (*fn7)() = static_cast<void (*)()>(overloaded_function);
+ void (*fn8)() = (FnPtrVoid)overloaded_function;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: void (*fn8)() = static_cast<FnPtrVoid>(overloaded_function);
+ void (&fn9)(int) = (void (&)(int))overloaded_function;
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: void (&fn9)(int) = static_cast<void (&)(int)>(overloaded_function);
+
+ void (*correct1)() = static_cast<void (*)()>(overloaded_function);
+ FnPtrVoid correct2 = static_cast<void (*)()>(&overloaded_function);
+ FnRefInt correct3 = static_cast<void (&)(int)>(overloaded_function);
+}
+
+struct S {
+ S(const char *);
+};
+struct ConvertibleToS {
+ operator S() const;
+};
+struct ConvertibleToSRef {
+ operator const S&() const;
+};
+
+void conversions() {
+ //auto s1 = (const S&)"";
+ // C HECK-MESSAGES: :[[@LINE-1]]:10: warning: C-style casts are discouraged; use static_cast [
+ // C HECK-FIXES: S s1 = static_cast<const S&>("");
+ auto s2 = (S)"";
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use constructor call syntax [
+ // CHECK-FIXES: auto s2 = S("");
+ auto s2a = (struct S)"";
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: auto s2a = static_cast<struct S>("");
+ auto s2b = (const S)"";
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [
+ // FIXME: This should be constructor call syntax: S("").
+ // CHECK-FIXES: auto s2b = static_cast<const S>("");
+ ConvertibleToS c;
+ auto s3 = (const S&)c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use static_cast/const_cast/reinterpret_cast [
+ // CHECK-FIXES: auto s3 = (const S&)c;
+ // FIXME: This should be a static_cast.
+ // C HECK-FIXES: auto s3 = static_cast<const S&>(c);
+ auto s4 = (S)c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use constructor call syntax [
+ // CHECK-FIXES: auto s4 = S(c);
+ ConvertibleToSRef cr;
+ auto s5 = (const S&)cr;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use static_cast/const_cast/reinterpret_cast [
+ // CHECK-FIXES: auto s5 = (const S&)cr;
+ // FIXME: This should be a static_cast.
+ // C HECK-FIXES: auto s5 = static_cast<const S&>(cr);
+ auto s6 = (S)cr;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use constructor call syntax [
+ // CHECK-FIXES: auto s6 = S(cr);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-casting.mm b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-casting.mm
new file mode 100644
index 0000000..b987dc2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-casting.mm
@@ -0,0 +1,179 @@
+// RUN: clang-tidy %s -checks=-*,google-readability-casting -- \
+// RUN: -xobjective-c++ -fobjc-abi-version=2 -fobjc-arc | count 0
+
+// Note: this test expects no diagnostics, but FileCheck cannot handle that,
+// hence the use of | count 0.
+
+bool g() { return false; }
+
+enum Enum { Enum1 };
+struct X {};
+struct Y : public X {};
+
+void f(int a, double b, const char *cpc, const void *cpv, X *pX) {
+
+ typedef const char *Typedef1;
+ typedef const char *Typedef2;
+ Typedef1 t1;
+ (Typedef2)t1;
+ (const char*)t1;
+ (Typedef1)cpc;
+
+ typedef char Char;
+ char *pc;
+ Char *pChar = (Char*)pc;
+
+ (Char)*cpc;
+
+ (char)*pChar;
+
+ (const char*)cpv;
+
+ char *pc2 = (char*)(cpc + 33);
+
+ const char &crc = *cpc;
+ char &rc = (char&)crc;
+
+ char &rc2 = (char&)*cpc;
+
+ char ** const* const* ppcpcpc;
+ char ****ppppc = (char****)ppcpcpc;
+
+ char ***pppc = (char***)*(ppcpcpc);
+
+ char ***pppc2 = (char***)(*ppcpcpc);
+
+ char *pc5 = (char*)(const char*)(cpv);
+
+ int b1 = (int)b;
+ b1 = (const int&)b;
+
+ b1 = (int) b;
+
+ b1 = (int) b;
+
+ b1 = (int) (b);
+
+ b1 = (int) (b);
+
+ Y *pB = (Y*)pX;
+ Y &rB = (Y&)*pX;
+
+ const char *pc3 = (const char*)cpv;
+
+ char *pc4 = (char*)cpv;
+
+ b1 = (int)Enum1;
+
+ Enum e = (Enum)b1;
+
+ int b2 = int(b);
+ int b3 = static_cast<double>(b);
+ int b4 = b;
+ double aa = a;
+ (void)b2;
+ return (void)g();
+}
+
+template <typename T>
+void template_function(T t, int n) {
+ int i = (int)t;
+}
+
+template <typename T>
+struct TemplateStruct {
+ void f(T t, int n) {
+ int k = (int)t;
+ }
+};
+
+void test_templates() {
+ template_function(1, 42);
+ template_function(1.0, 42);
+ TemplateStruct<int>().f(1, 42);
+ TemplateStruct<double>().f(1.0, 42);
+}
+
+extern "C" {
+void extern_c_code(const char *cpc) {
+ char *pc = (char*)cpc;
+}
+}
+
+#define CAST(type, value) (type)(value)
+void macros(double d) {
+ int i = CAST(int, d);
+}
+
+enum E { E1 = 1 };
+template <E e>
+struct A {
+ // Usage of template argument e = E1 is represented as (E)1 in the AST for
+ // some reason. We have a special treatment of this case to avoid warnings
+ // here.
+ static const E ee = e;
+};
+struct B : public A<E1> {};
+
+
+void overloaded_function();
+void overloaded_function(int);
+
+template<typename Fn>
+void g(Fn fn) {
+ fn();
+}
+
+void function_casts() {
+ typedef void (*FnPtrVoid)();
+ typedef void (&FnRefVoid)();
+ typedef void (&FnRefInt)(int);
+
+ g((void (*)())overloaded_function);
+ g((void (*)())&overloaded_function);
+ g((void (&)())overloaded_function);
+
+ g((FnPtrVoid)overloaded_function);
+ g((FnPtrVoid)&overloaded_function);
+ g((FnRefVoid)overloaded_function);
+
+ FnPtrVoid fn0 = (void (*)())&overloaded_function;
+ FnPtrVoid fn1 = (void (*)())overloaded_function;
+ FnPtrVoid fn1a = (FnPtrVoid)overloaded_function;
+ FnRefInt fn2 = (void (&)(int))overloaded_function;
+ auto fn3 = (void (*)())&overloaded_function;
+ auto fn4 = (void (*)())overloaded_function;
+ auto fn5 = (void (&)(int))overloaded_function;
+
+ void (*fn6)() = (void (*)())&overloaded_function;
+ void (*fn7)() = (void (*)())overloaded_function;
+ void (*fn8)() = (FnPtrVoid)overloaded_function;
+ void (&fn9)(int) = (void (&)(int))overloaded_function;
+
+ void (*correct1)() = static_cast<void (*)()>(overloaded_function);
+ FnPtrVoid correct2 = static_cast<void (*)()>(&overloaded_function);
+ FnRefInt correct3 = static_cast<void (&)(int)>(overloaded_function);
+}
+
+struct S {
+ S(const char *);
+};
+struct ConvertibleToS {
+ operator S() const;
+};
+struct ConvertibleToSRef {
+ operator const S&() const;
+};
+
+void conversions() {
+ //auto s1 = (const S&)"";
+ auto s2 = (S)"";
+ auto s2a = (struct S)"";
+ auto s2b = (const S)"";
+ ConvertibleToS c;
+ auto s3 = (const S&)c;
+ auto s4 = (S)c;
+ ConvertibleToSRef cr;
+ auto s5 = (const S&)cr;
+ auto s6 = (S)cr;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-namespace-comments.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-namespace-comments.cpp
new file mode 100644
index 0000000..9abb984
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-namespace-comments.cpp
@@ -0,0 +1,54 @@
+// RUN: %check_clang_tidy %s google-readability-namespace-comments %t
+
+namespace n1 {
+namespace n2 {
+
+
+void f(); // So that the namespace isn't empty.
+
+
+// CHECK-MESSAGES: :[[@LINE+4]]:2: warning: namespace 'n2' not terminated with a closing comment [google-readability-namespace-comments]
+// CHECK-MESSAGES: :[[@LINE-7]]:11: note: namespace 'n2' starts here
+// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: namespace 'n1' not terminated with
+// CHECK-MESSAGES: :[[@LINE-10]]:11: note: namespace 'n1' starts here
+}}
+// CHECK-FIXES: } // namespace n2
+// CHECK-FIXES: } // namespace n1
+
+#define MACRO macro_expansion
+namespace MACRO {
+void f(); // So that the namespace isn't empty.
+// 1
+// 2
+// 3
+// 4
+// 5
+// 6
+// 7
+// CHECK-MESSAGES: :[[@LINE+2]]:2: warning: namespace 'macro_expansion' not terminated with
+// CHECK-MESSAGES: :[[@LINE-10]]:11: note: namespace 'macro_expansion' starts here
+}
+// CHECK-FIXES: } // namespace macro_expansion
+
+namespace short1 {
+namespace short2 {
+// Namespaces covering 10 lines or fewer are exempt from this rule.
+
+
+
+
+
+}
+}
+
+namespace n3 {
+
+
+
+
+
+
+
+
+
+}; // namespace n3
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-nested-namespace-comments.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-nested-namespace-comments.cpp
new file mode 100644
index 0000000..d7765c6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-nested-namespace-comments.cpp
@@ -0,0 +1,17 @@
+// RUN: %check_clang_tidy %s google-readability-namespace-comments %t
+
+namespace n1::n2 {
+namespace n3 {
+
+// So that namespace is not empty.
+void f();
+
+
+// CHECK-MESSAGES: :[[@LINE+4]]:2: warning: namespace 'n3' not terminated with
+// CHECK-MESSAGES: :[[@LINE-7]]:11: note: namespace 'n3' starts here
+// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: namespace 'n1::n2' not terminated with a closing comment [google-readability-namespace-comments]
+// CHECK-MESSAGES: :[[@LINE-10]]:11: note: namespace 'n1::n2' starts here
+}}
+// CHECK-FIXES: } // namespace n3
+// CHECK-FIXES: } // namespace n1::n2
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-todo.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-todo.cpp
new file mode 100644
index 0000000..6b900aa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-todo.cpp
@@ -0,0 +1,26 @@
+// RUN: %check_clang_tidy %s google-readability-todo %t -- -config="{User: 'some user'}" --
+
+// TODOfix this1
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: missing username/bug in TODO
+// CHECK-FIXES: // TODO(some user): fix this1
+
+// TODO fix this2
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: missing username/bug in TODO
+// CHECK-FIXES: // TODO(some user): fix this2
+
+// TODO fix this3
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: missing username/bug in TODO
+// CHECK-FIXES: // TODO(some user): fix this3
+
+// TODO: fix this4
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: missing username/bug in TODO
+// CHECK-FIXES: // TODO(some user): fix this4
+
+// TODO(clang)fix this5
+
+// TODO(foo):shave yaks
+// TODO(bar):
+// TODO(foo): paint bikeshed
+// TODO(b/12345): find the holy grail
+// TODO (b/12345): allow spaces before parentheses
+// TODO(asdf) allow missing semicolon
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-int-std.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-int-std.cpp
new file mode 100644
index 0000000..c5d3112
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-int-std.cpp
@@ -0,0 +1,57 @@
+// RUN: %check_clang_tidy %s google-runtime-int %t -- \
+// RUN: -config='{CheckOptions: [ \
+// RUN: {key: google-runtime-int.UnsignedTypePrefix, value: "std::uint"}, \
+// RUN: {key: google-runtime-int.SignedTypePrefix, value: "std::int"}, \
+// RUN: {key: google-runtime-int.TypeSuffix, value: "_t"}, \
+// RUN: ]}' -- -std=c++11
+
+long a();
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: consider replacing 'long' with 'std::int{{..}}_t'
+
+typedef unsigned long long uint64; // NOLINT
+
+long b(long = 1);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: consider replacing 'long' with 'std::int{{..}}_t'
+// CHECK-MESSAGES: [[@LINE-2]]:8: warning: consider replacing 'long' with 'std::int{{..}}_t'
+
+template <typename T>
+void tmpl() {
+ T i;
+}
+
+short bar(const short, unsigned short) {
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: consider replacing 'short' with 'std::int16_t'
+// CHECK-MESSAGES: [[@LINE-2]]:17: warning: consider replacing 'short' with 'std::int16_t'
+// CHECK-MESSAGES: [[@LINE-3]]:24: warning: consider replacing 'unsigned short' with 'std::uint16_t'
+ long double foo = 42;
+ uint64 qux = 42;
+ unsigned short port;
+
+ const unsigned short bar = 0;
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: consider replacing 'unsigned short' with 'std::uint16_t'
+ long long *baar;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'long long' with 'std::int64_t'
+ const unsigned short &bara = bar;
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: consider replacing 'unsigned short' with 'std::uint16_t'
+ long const long moo = 1;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'long long' with 'std::int64_t'
+ long volatile long wat = 42;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'long long' with 'std::int64_t'
+ unsigned long y;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'unsigned long' with 'std::uint{{..}}_t'
+ unsigned long long **const *tmp;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'unsigned long long' with 'std::uint64_t'
+ unsigned long long **const *&z = tmp;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'unsigned long long' with 'std::uint64_t'
+ unsigned short porthole;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'unsigned short' with 'std::uint16_t'
+
+ uint64 cast = (short)42;
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: consider replacing 'short' with 'std::int16_t'
+
+#define l long
+ l x;
+
+ tmpl<short>();
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: consider replacing 'short' with 'std::int16_t'
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-int.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-int.c
new file mode 100644
index 0000000..8657e2d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-int.c
@@ -0,0 +1,27 @@
+// RUN: clang-tidy -checks=-*,google-runtime-int %s -- -x c 2>&1 | not grep 'warning:\|error:'
+
+long a();
+
+long b(long x);
+
+short bar(const short q, unsigned short w) {
+ long double foo;
+ unsigned short port;
+
+ const unsigned short bar;
+ long long *baar;
+ const unsigned short bara;
+ long const long moo;
+ long volatile long wat;
+ unsigned long y;
+ unsigned long long **const *tmp;
+ unsigned short porthole;
+
+ unsigned cast;
+ cast = (short)42;
+ return q;
+}
+
+void qux() {
+ short port;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-int.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-int.cpp
new file mode 100644
index 0000000..4bb7398
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-int.cpp
@@ -0,0 +1,91 @@
+// RUN: %check_clang_tidy %s google-runtime-int %t
+
+long a();
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: consider replacing 'long' with 'int{{..}}'
+
+typedef unsigned long long uint64; // NOLINT
+
+long b(long = 1);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: consider replacing 'long' with 'int{{..}}'
+// CHECK-MESSAGES: [[@LINE-2]]:8: warning: consider replacing 'long' with 'int{{..}}'
+
+template <typename T>
+void tmpl() {
+ T i;
+}
+
+short bar(const short, unsigned short) {
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: consider replacing 'short' with 'int16'
+// CHECK-MESSAGES: [[@LINE-2]]:17: warning: consider replacing 'short' with 'int16'
+// CHECK-MESSAGES: [[@LINE-3]]:24: warning: consider replacing 'unsigned short' with 'uint16'
+ long double foo = 42;
+ uint64 qux = 42;
+ unsigned short port;
+
+ const unsigned short bar = 0;
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: consider replacing 'unsigned short' with 'uint16'
+ long long *baar;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'long long' with 'int64'
+ const unsigned short &bara = bar;
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: consider replacing 'unsigned short' with 'uint16'
+ long const long moo = 1;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'long long' with 'int64'
+ long volatile long wat = 42;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'long long' with 'int64'
+ unsigned long y;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'unsigned long' with 'uint{{..}}'
+ unsigned long long **const *tmp;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'unsigned long long' with 'uint64'
+ unsigned long long **const *&z = tmp;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'unsigned long long' with 'uint64'
+ unsigned short porthole;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'unsigned short' with 'uint16'
+
+ uint64 cast = (short)42;
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: consider replacing 'short' with 'int16'
+
+#define l long
+ l x;
+
+ tmpl<short>();
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: consider replacing 'short' with 'int16'
+ return 0;
+}
+
+void p(unsigned short port);
+
+void qux() {
+ short port;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'short' with 'int16'
+}
+
+// FIXME: This shouldn't warn, as UD-literal operators require one of a handful
+// of types as an argument.
+struct some_value {};
+constexpr some_value operator"" _some_literal(unsigned long long int i);
+// CHECK-MESSAGES: [[@LINE-1]]:47: warning: consider replacing 'unsigned long long'
+
+struct A { A& operator=(const A&); };
+class B { A a[0]; };
+
+void fff() {
+ B a, b;
+ a = b;
+}
+
+__attribute__((__format__ (__printf__, 1, 2)))
+void myprintf(const char* s, ...);
+
+void doprint_no_warning() {
+ uint64 foo = 23;
+ myprintf("foo %lu %lu", (unsigned long)42, (unsigned long)foo);
+}
+
+void myprintf_no_attribute(const char* s, ...);
+
+void doprint_warning() {
+ uint64 foo = 23;
+ myprintf_no_attribute("foo %lu %lu", (unsigned long)42, (unsigned long)foo);
+// CHECK-MESSAGES: [[@LINE-1]]:41: warning: consider replacing 'unsigned long'
+// CHECK-MESSAGES: [[@LINE-2]]:60: warning: consider replacing 'unsigned long'
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-references.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-references.cpp
new file mode 100644
index 0000000..b9f84b6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-references.cpp
@@ -0,0 +1,152 @@
+// RUN: %check_clang_tidy %s google-runtime-references %t -- \
+// RUN: -extra-arg="-std=c++11" \
+// RUN: -config="{CheckOptions: \
+// RUN: [{key: google-runtime-references.WhiteListTypes, \
+// RUN: value: 'whitelist::A; whitelist::B'}]}" --
+
+int a;
+int &b = a;
+int *c;
+void f1(int a);
+void f2(int *b);
+void f3(const int &c);
+void f4(int const &d);
+
+// Don't warn on implicit operator= in c++11 mode.
+class A {
+ virtual void f() {}
+};
+// Don't warn on rvalue-references.
+struct A2 {
+ A2(A2&&) = default;
+ void f(A2&&) {}
+};
+
+// Don't warn on iostream parameters.
+namespace xxx {
+class istream { };
+class ostringstream { };
+}
+void g1(xxx::istream &istr);
+void g1(xxx::ostringstream &istr);
+
+void g1(int &a);
+// CHECK-MESSAGES: [[@LINE-1]]:14: warning: non-const reference parameter 'a', make it const or use a pointer [google-runtime-references]
+
+struct s {};
+void g2(int a, int b, s c, s &d);
+// CHECK-MESSAGES: [[@LINE-1]]:31: warning: non-const reference parameter 'd', {{.*}}
+
+typedef int &ref;
+void g3(ref a);
+// CHECK-MESSAGES: [[@LINE-1]]:13: warning: non-const reference {{.*}}
+
+void g4(int &a, int &b, int &);
+// CHECK-MESSAGES: [[@LINE-1]]:14: warning: non-const reference parameter 'a', {{.*}}
+// CHECK-MESSAGES: [[@LINE-2]]:22: warning: non-const reference parameter 'b', {{.*}}
+// CHECK-MESSAGES: [[@LINE-3]]:30: warning: non-const reference parameter at index 2, {{.*}}
+
+class B {
+ B(B& a) {}
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: non-const reference {{.*}}
+ virtual void f(int &a) {}
+// CHECK-MESSAGES: [[@LINE-1]]:23: warning: non-const reference {{.*}}
+ void g(int &b);
+// CHECK-MESSAGES: [[@LINE-1]]:15: warning: non-const reference {{.*}}
+
+ // Don't warn on the parameter of stream extractors defined as members.
+ B& operator>>(int& val) { return *this; }
+};
+
+// Only warn on the first declaration of each function to reduce duplicate
+// warnings.
+void B::g(int &b) {}
+
+// Don't warn on the first parameter of stream inserters.
+A& operator<<(A& s, int&) { return s; }
+// CHECK-MESSAGES: [[@LINE-1]]:25: warning: non-const reference parameter at index 1, {{.*}}
+
+// Don't warn on either parameter of stream extractors. Both need to be
+// non-const references by convention.
+A& operator>>(A& input, int& val) { return input; }
+
+// Don't warn on lambdas.
+auto lambda = [] (int&) {};
+
+// Don't warn on typedefs, as we'll warn on the function itself.
+typedef int (*fp)(int &);
+
+// Don't warn on function references.
+typedef void F();
+void g5(const F& func) {}
+void g6(F& func) {}
+
+template<typename T>
+void g7(const T& t) {}
+
+template<typename T>
+void g8(T t) {}
+
+void f5() {
+ g5(f5);
+ g6(f5);
+ g7(f5);
+ g7<F&>(f5);
+ g8(f5);
+ g8<F&>(f5);
+}
+
+// Don't warn on dependent types.
+template<typename T>
+void g9(T& t) {}
+template<typename T>
+void g10(T t) {}
+
+void f6() {
+ int i;
+ float f;
+ g9<int>(i);
+ g9<const int>(i);
+ g9<int&>(i);
+ g10<int&>(i);
+ g10<float&>(f);
+}
+
+// Warn only on the overridden methods from the base class, as the child class
+// only implements the interface.
+class C : public B {
+ C();
+ virtual void f(int &a) {}
+};
+
+// Don't warn on operator<< with streams-like interface.
+A& operator<<(A& s, int) { return s; }
+
+// Don't warn on swap().
+void swap(C& c1, C& c2) {}
+
+// Don't warn on standalone operator++, operator--, operator+=, operator-=,
+// operator*=, etc. that all need non-const references to be functional.
+A& operator++(A& a) { return a; }
+A operator++(A& a, int) { return a; }
+A& operator--(A& a) { return a; }
+A operator--(A& a, int) { return a; }
+A& operator+=(A& a, const A& b) { return a; }
+A& operator-=(A& a, const A& b) { return a; }
+A& operator*=(A& a, const A& b) { return a; }
+A& operator/=(A& a, const A& b) { return a; }
+A& operator%=(A& a, const A& b) { return a; }
+A& operator<<=(A& a, const A& b) { return a; }
+A& operator>>=(A& a, const A& b) { return a; }
+A& operator|=(A& a, const A& b) { return a; }
+A& operator^=(A& a, const A& b) { return a; }
+A& operator&=(A& a, const A& b) { return a; }
+
+namespace whitelist {
+class A {};
+class B {};
+void f7(A &);
+void f8(B &);
+}
+void f9(whitelist::A &);
+void f10(whitelist::B &);
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-exception-baseclass.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-exception-baseclass.cpp
new file mode 100644
index 0000000..9a0638b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-exception-baseclass.cpp
@@ -0,0 +1,179 @@
+// RUN: %check_clang_tidy %s hicpp-exception-baseclass %t -- -- -fcxx-exceptions
+
+namespace std {
+class exception {};
+} // namespace std
+
+class derived_exception : public std::exception {};
+class deep_hierarchy : public derived_exception {};
+class non_derived_exception {};
+class terrible_idea : public non_derived_exception, public derived_exception {};
+
+// FIXME: More complicated kinds of inheritance should be checked later, but there is
+// currently no way use ASTMatchers for this kind of task.
+#if 0
+class bad_inheritance : private std::exception {};
+class no_good_inheritance : protected std::exception {};
+class really_creative : public non_derived_exception, private std::exception {};
+#endif
+
+void problematic() {
+ try {
+ throw int(42);
+ // CHECK-MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+ } catch (int e) {
+ }
+ throw int(42);
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+
+ try {
+ throw 12;
+ // CHECK-MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+ } catch (...) {
+ throw; // Ok, even if the type is not known, conforming code can never rethrow a non-std::exception object.
+ }
+
+ try {
+ throw non_derived_exception();
+ // CHECK-MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'
+ // CHECK-MESSAGES: 9:1: note: type defined here
+ } catch (non_derived_exception &e) {
+ }
+ throw non_derived_exception();
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'
+ // CHECK-MESSAGES: 9:1: note: type defined here
+
+// FIXME: More complicated kinds of inheritance should be checked later, but there is
+// currently no way use ASTMatchers for this kind of task.
+#if 0
+ // Handle private inheritance cases correctly.
+ try {
+ throw bad_inheritance();
+ // CHECK MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'bad_inheritance' is not derived from 'std::exception'
+ // CHECK MESSAGES: 10:1: note: type defined here
+ throw no_good_inheritance();
+ // CHECK MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'no_good_inheritance' is not derived from 'std::exception'
+ // CHECK MESSAGES: 11:1: note: type defined here
+ throw really_creative();
+ // CHECK MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'really_creative' is not derived from 'std::exception'
+ // CHECK MESSAGES: 12:1: note: type defined here
+ } catch (...) {
+ }
+ throw bad_inheritance();
+ // CHECK MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'bad_inheritance' is not derived from 'std::exception'
+ // CHECK MESSAGES: 10:1: note: type defined here
+ throw no_good_inheritance();
+ // CHECK MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'no_good_inheritance' is not derived from 'std::exception'
+ // CHECK MESSAGES: 11:1: note: type defined here
+ throw really_creative();
+ // CHECK MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'really_creative' is not derived from 'std::exception'
+ // CHECK MESSAGES: 12:1: note: type defined here
+#endif
+}
+
+void allowed_throws() {
+ try {
+ throw std::exception(); // Ok
+ } catch (std::exception &e) { // Ok
+ }
+ throw std::exception();
+
+ try {
+ throw derived_exception(); // Ok
+ } catch (derived_exception &e) { // Ok
+ }
+ throw derived_exception(); // Ok
+
+ try {
+ throw deep_hierarchy(); // Ok, multiple levels of inheritance
+ } catch (deep_hierarchy &e) { // Ok
+ }
+ throw deep_hierarchy(); // Ok
+
+ try {
+ throw terrible_idea(); // Ok, but multiple inheritance isn't clean
+ } catch (std::exception &e) { // Can be caught as std::exception, even with multiple inheritance
+ }
+ throw terrible_idea(); // Ok, but multiple inheritance
+}
+
+// Templated function that throws exception based on template type
+template <typename T>
+void ThrowException() { throw T(); }
+// CHECK-MESSAGES: [[@LINE-1]]:31: warning: throwing an exception whose type 'bad_generic_exception<int>' is not derived from 'std::exception'
+// CHECK-MESSAGES: 120:1: note: type defined here
+// CHECK-MESSAGES: [[@LINE-3]]:31: warning: throwing an exception whose type 'bad_generic_exception<std::exception>' is not derived from 'std::exception'
+// CHECK-MESSAGES: 120:1: note: type defined here
+// CHECK-MESSAGES: [[@LINE-5]]:31: warning: throwing an exception whose type 'exotic_exception<non_derived_exception>' is not derived from 'std::exception'
+// CHECK-MESSAGES: 123:1: note: type defined here
+// CHECK-MESSAGES: [[@LINE-7]]:31: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+// CHECK-MESSAGES: [[@LINE-8]]:31: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'
+// CHECK-MESSAGES: 9:1: note: type defined here
+#define THROW_EXCEPTION(CLASS) ThrowException<CLASS>()
+#define THROW_BAD_EXCEPTION throw int(42);
+#define THROW_GOOD_EXCEPTION throw std::exception();
+#define THROW_DERIVED_EXCEPTION throw deep_hierarchy();
+
+template <typename T>
+class generic_exception : std::exception {};
+
+template <typename T>
+class bad_generic_exception {};
+
+template <typename T>
+class exotic_exception : public T {};
+
+void generic_exceptions() {
+ THROW_EXCEPTION(int);
+ // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+ THROW_EXCEPTION(non_derived_exception);
+ // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'
+ // CHECK MESSAGES: 9:1: note: type defined here
+ THROW_EXCEPTION(std::exception); // Ok
+ THROW_EXCEPTION(derived_exception); // Ok
+ THROW_EXCEPTION(deep_hierarchy); // Ok
+
+ THROW_BAD_EXCEPTION;
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+ // CHECK-MESSAGES: [[@LINE-25]]:35: note: expanded from macro 'THROW_BAD_EXCEPTION'
+ THROW_GOOD_EXCEPTION;
+ THROW_DERIVED_EXCEPTION;
+
+ throw generic_exception<int>(); // Ok,
+ THROW_EXCEPTION(generic_exception<float>); // Ok
+
+ throw bad_generic_exception<int>();
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'bad_generic_exception<int>' is not derived from 'std::exception'
+ throw bad_generic_exception<std::exception>();
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'bad_generic_exception<std::exception>' is not derived from 'std::exception'
+ THROW_EXCEPTION(bad_generic_exception<int>);
+ // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'bad_generic_exception<int>' is not derived from 'std::exception'
+ THROW_EXCEPTION(bad_generic_exception<std::exception>);
+ // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'bad_generic_exception<std::exception>' is not derived from 'std::exception'
+
+ throw exotic_exception<non_derived_exception>();
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'exotic_exception<non_derived_exception>' is not derived from 'std::exception'
+ THROW_EXCEPTION(exotic_exception<non_derived_exception>);
+ // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'exotic_exception<non_derived_exception>' is not derived from 'std::exception'
+
+ throw exotic_exception<derived_exception>(); // Ok
+ THROW_EXCEPTION(exotic_exception<derived_exception>); // Ok
+}
+
+// Test for typedefed exception types
+typedef int TypedefedBad;
+typedef derived_exception TypedefedGood;
+using UsingBad = int;
+using UsingGood = deep_hierarchy;
+
+void typedefed() {
+ throw TypedefedBad();
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'TypedefedBad' (aka 'int') is not derived from 'std::exception'
+ // CHECK-MESSAGES: 164:1: note: type defined here
+ throw TypedefedGood(); // Ok
+
+ throw UsingBad();
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'UsingBad' (aka 'int') is not derived from 'std::exception'
+ // CHECK-MESSAGES: 166:1: note: type defined here
+ throw UsingGood(); // Ok
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-multiway-paths-covered-else.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-multiway-paths-covered-else.cpp
new file mode 100644
index 0000000..34820b5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-multiway-paths-covered-else.cpp
@@ -0,0 +1,57 @@
+// RUN: %check_clang_tidy %s hicpp-multiway-paths-covered %t \
+// RUN: -config='{CheckOptions: \
+// RUN: [{key: hicpp-multiway-paths-covered.WarnOnMissingElse, value: 1}]}'\
+// RUN: --
+
+enum OS { Mac,
+ Windows,
+ Linux };
+
+void problematic_if(int i, enum OS os) {
+ if (i > 0) {
+ return;
+ } else if (i < 0) {
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: potentially uncovered codepath; add an ending else statement
+ return;
+ }
+
+ // Could be considered as false positive because all paths are covered logically.
+ // I still think this is valid since the possibility of a final 'everything else'
+ // codepath is expected from if-else if.
+ if (i > 0) {
+ return;
+ } else if (i <= 0) {
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: potentially uncovered codepath; add an ending else statement
+ return;
+ }
+
+ // Test if nesting of if-else chains does get caught as well.
+ if (os == Mac) {
+ return;
+ } else if (os == Linux) {
+ // These checks are kind of degenerated, but the check will not try to solve
+ // if logically all paths are covered, which is more the area of the static analyzer.
+ if (true) {
+ return;
+ } else if (false) {
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: potentially uncovered codepath; add an ending else statement
+ return;
+ }
+ return;
+ } else {
+ /* unreachable */
+ if (true) // check if the parent would match here as well
+ return;
+ // No warning for simple if statements, since it is common to just test one condition
+ // and ignore the opposite.
+ }
+
+ // Ok, because all paths are covered
+ if (i > 0) {
+ return;
+ } else if (i < 0) {
+ return;
+ } else {
+ /* error, maybe precondition failed */
+ }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-multiway-paths-covered.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-multiway-paths-covered.cpp
new file mode 100644
index 0000000..15a3407
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-multiway-paths-covered.cpp
@@ -0,0 +1,468 @@
+// RUN: %check_clang_tidy %s hicpp-multiway-paths-covered %t
+
+enum OS { Mac,
+ Windows,
+ Linux };
+
+struct Bitfields {
+ unsigned UInt : 3;
+ int SInt : 1;
+};
+
+int return_integer() { return 42; }
+
+void bad_switch(int i) {
+ switch (i) {
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: switch with only one case; use an if statement
+ case 0:
+ break;
+ }
+ // No default in this switch
+ switch (i) {
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: potential uncovered code path; add a default label
+ case 0:
+ break;
+ case 1:
+ break;
+ case 2:
+ break;
+ }
+
+ // degenerate, maybe even warning
+ switch (i) {
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: switch statement without labels has no effect
+ }
+
+ switch (int j = return_integer()) {
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: potential uncovered code path; add a default label
+ case 0:
+ case 1:
+ case 2:
+ break;
+ }
+
+ // Degenerated, only default case.
+ switch (i) {
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: degenerated switch with default label only
+ default:
+ break;
+ }
+
+ // Degenerated, only one case label and default case -> Better as if-stmt.
+ switch (i) {
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: switch could be better written as an if/else statement
+ case 0:
+ break;
+ default:
+ break;
+ }
+
+ unsigned long long BigNumber = 0;
+ switch (BigNumber) {
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: potential uncovered code path; add a default label
+ case 0:
+ case 1:
+ break;
+ }
+
+ const int &IntRef = i;
+ switch (IntRef) {
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: potential uncovered code path; add a default label
+ case 0:
+ case 1:
+ break;
+ }
+
+ char C = 'A';
+ switch (C) {
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: potential uncovered code path; add a default label
+ case 'A':
+ break;
+ case 'B':
+ break;
+ }
+
+ Bitfields Bf;
+ // UInt has 3 bits size.
+ switch (Bf.UInt) {
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: potential uncovered code path; add a default label
+ case 0:
+ case 1:
+ break;
+ }
+ // All paths explicitly covered.
+ switch (Bf.UInt) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ break;
+ }
+ // SInt has 1 bit size, so this is somewhat degenerated.
+ switch (Bf.SInt) {
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: switch with only one case; use an if statement
+ case 0:
+ break;
+ }
+ // All paths explicitly covered.
+ switch (Bf.SInt) {
+ case 0:
+ case 1:
+ break;
+ }
+
+ bool Flag = false;
+ switch (Flag) {
+ // CHECK-MESSAGES:[[@LINE-1]]:3: warning: switch with only one case; use an if statement
+ case true:
+ break;
+ }
+
+ switch (Flag) {
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: degenerated switch with default label only
+ default:
+ break;
+ }
+
+ // This `switch` will create a frontend warning from '-Wswitch-bool' but is
+ // ok for this check.
+ switch (Flag) {
+ case true:
+ break;
+ case false:
+ break;
+ }
+}
+
+void unproblematic_switch(unsigned char c) {
+ //
+ switch (c) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ case 38:
+ case 39:
+ case 40:
+ case 41:
+ case 42:
+ case 43:
+ case 44:
+ case 45:
+ case 46:
+ case 47:
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ case 57:
+ case 58:
+ case 59:
+ case 60:
+ case 61:
+ case 62:
+ case 63:
+ case 64:
+ case 65:
+ case 66:
+ case 67:
+ case 68:
+ case 69:
+ case 70:
+ case 71:
+ case 72:
+ case 73:
+ case 74:
+ case 75:
+ case 76:
+ case 77:
+ case 78:
+ case 79:
+ case 80:
+ case 81:
+ case 82:
+ case 83:
+ case 84:
+ case 85:
+ case 86:
+ case 87:
+ case 88:
+ case 89:
+ case 90:
+ case 91:
+ case 92:
+ case 93:
+ case 94:
+ case 95:
+ case 96:
+ case 97:
+ case 98:
+ case 99:
+ case 100:
+ case 101:
+ case 102:
+ case 103:
+ case 104:
+ case 105:
+ case 106:
+ case 107:
+ case 108:
+ case 109:
+ case 110:
+ case 111:
+ case 112:
+ case 113:
+ case 114:
+ case 115:
+ case 116:
+ case 117:
+ case 118:
+ case 119:
+ case 120:
+ case 121:
+ case 122:
+ case 123:
+ case 124:
+ case 125:
+ case 126:
+ case 127:
+ case 128:
+ case 129:
+ case 130:
+ case 131:
+ case 132:
+ case 133:
+ case 134:
+ case 135:
+ case 136:
+ case 137:
+ case 138:
+ case 139:
+ case 140:
+ case 141:
+ case 142:
+ case 143:
+ case 144:
+ case 145:
+ case 146:
+ case 147:
+ case 148:
+ case 149:
+ case 150:
+ case 151:
+ case 152:
+ case 153:
+ case 154:
+ case 155:
+ case 156:
+ case 157:
+ case 158:
+ case 159:
+ case 160:
+ case 161:
+ case 162:
+ case 163:
+ case 164:
+ case 165:
+ case 166:
+ case 167:
+ case 168:
+ case 169:
+ case 170:
+ case 171:
+ case 172:
+ case 173:
+ case 174:
+ case 175:
+ case 176:
+ case 177:
+ case 178:
+ case 179:
+ case 180:
+ case 181:
+ case 182:
+ case 183:
+ case 184:
+ case 185:
+ case 186:
+ case 187:
+ case 188:
+ case 189:
+ case 190:
+ case 191:
+ case 192:
+ case 193:
+ case 194:
+ case 195:
+ case 196:
+ case 197:
+ case 198:
+ case 199:
+ case 200:
+ case 201:
+ case 202:
+ case 203:
+ case 204:
+ case 205:
+ case 206:
+ case 207:
+ case 208:
+ case 209:
+ case 210:
+ case 211:
+ case 212:
+ case 213:
+ case 214:
+ case 215:
+ case 216:
+ case 217:
+ case 218:
+ case 219:
+ case 220:
+ case 221:
+ case 222:
+ case 223:
+ case 224:
+ case 225:
+ case 226:
+ case 227:
+ case 228:
+ case 229:
+ case 230:
+ case 231:
+ case 232:
+ case 233:
+ case 234:
+ case 235:
+ case 236:
+ case 237:
+ case 238:
+ case 239:
+ case 240:
+ case 241:
+ case 242:
+ case 243:
+ case 244:
+ case 245:
+ case 246:
+ case 247:
+ case 248:
+ case 249:
+ case 250:
+ case 251:
+ case 252:
+ case 253:
+ case 254:
+ case 255:
+ break;
+ }
+
+ // Some paths are covered by the switch and a default case is present.
+ switch (c) {
+ case 1:
+ case 2:
+ case 3:
+ default:
+ break;
+ }
+}
+
+OS return_enumerator() {
+ return Linux;
+}
+
+// Enumpaths are already covered by a warning, this is just to ensure, that there is
+// no interference or false positives.
+// -Wswitch warns about uncovered enum paths and each here described case is already
+// covered.
+void switch_enums(OS os) {
+ switch (os) {
+ case Linux:
+ break;
+ }
+
+ switch (OS another_os = return_enumerator()) {
+ case Linux:
+ break;
+ }
+
+ switch (os) {
+ }
+}
+
+/// All of these cases will not emit a warning per default, but with explicit activation.
+/// Covered in extra test file.
+void problematic_if(int i, enum OS os) {
+ if (i > 0) {
+ return;
+ } else if (i < 0) {
+ return;
+ }
+
+ if (os == Mac) {
+ return;
+ } else if (os == Linux) {
+ if (true) {
+ return;
+ } else if (false) {
+ return;
+ }
+ return;
+ } else {
+ /* unreachable */
+ if (true) // check if the parent would match here as well
+ return;
+ }
+
+ // Ok, because all paths are covered
+ if (i > 0) {
+ return;
+ } else if (i < 0) {
+ return;
+ } else {
+ /* error, maybe precondition failed */
+ }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-no-assembler-msvc.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-no-assembler-msvc.cpp
new file mode 100644
index 0000000..d29a9e9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-no-assembler-msvc.cpp
@@ -0,0 +1,11 @@
+// REQUIRES: system-windows
+// FIXME: Re-enable test on windows (PR36855)
+// UNSUPPORTED: system-windows
+// RUN: %check_clang_tidy %s hicpp-no-assembler %t
+
+void f() {
+ _asm {
+ mov al, 2;
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: do not use inline assembler in safety-critical code [hicpp-no-assembler]
+ }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-no-assembler.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-no-assembler.cpp
new file mode 100644
index 0000000..d08ea74
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-no-assembler.cpp
@@ -0,0 +1,12 @@
+// RUN: %check_clang_tidy %s hicpp-no-assembler %t
+
+__asm__(".symver foo, bar@v");
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not use inline assembler in safety-critical code [hicpp-no-assembler]
+
+static int s asm("spam");
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use inline assembler in safety-critical code [hicpp-no-assembler]
+
+void f() {
+ __asm("mov al, 2");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use inline assembler in safety-critical code [hicpp-no-assembler]
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise-bug34747.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise-bug34747.cpp
new file mode 100644
index 0000000..217df71
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise-bug34747.cpp
@@ -0,0 +1,29 @@
+// RUN: %check_clang_tidy %s hicpp-signed-bitwise %t --
+
+// Note: this test expects no diagnostics, but FileCheck cannot handle that,
+// hence the use of | count 0.
+
+template <typename C>
+struct OutputStream {
+ OutputStream &operator<<(C);
+};
+
+template <typename C>
+struct foo {
+ typedef OutputStream<C> stream_type;
+ foo(stream_type &o) {
+ o << 'x'; // warning occured here, fixed now
+ }
+};
+
+void bar(OutputStream<signed char> &o) {
+ foo<signed char> f(o);
+}
+
+void silence_lit() {
+ int SValue = 42;
+ int SResult;
+
+ SResult = SValue & 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise-standard-types.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise-standard-types.cpp
new file mode 100644
index 0000000..c85fe20
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise-standard-types.cpp
@@ -0,0 +1,197 @@
+// RUN: clang-tidy %s -checks='-*,hicpp-signed-bitwise' -- -std=c++11
+
+#include "hicpp-signed-bitwise-standard-types.h"
+
+void pure_bitmask_types() {
+ // std::locale::category
+ int SResult = 0;
+ std::locale::category C = std::locale::category::ctype;
+
+ SResult = std::locale::category::none | std::locale::category::collate;
+ SResult|= std::locale::category::collate;
+ SResult = std::locale::category::ctype & std::locale::category::monetary;
+ SResult&= std::locale::category::monetary;
+ SResult = std::locale::category::numeric ^ std::locale::category::time;
+ SResult^= std::locale::category::time;
+ SResult = std::locale::category::messages | std::locale::category::all;
+
+ SResult = std::locale::category::all & C;
+ SResult&= std::locale::category::all;
+ SResult = std::locale::category::all | C;
+ SResult|= std::locale::category::all;
+ SResult = std::locale::category::all ^ C;
+ SResult^= std::locale::category::all;
+
+ // std::ctype_base::mask
+ std::ctype_base::mask M = std::ctype_base::mask::punct;
+
+ SResult = std::ctype_base::mask::space | std::ctype_base::mask::print;
+ SResult = std::ctype_base::mask::cntrl & std::ctype_base::mask::upper;
+ SResult = std::ctype_base::mask::lower ^ std::ctype_base::mask::alpha;
+ SResult|= std::ctype_base::mask::digit | std::ctype_base::mask::punct;
+ SResult&= std::ctype_base::mask::xdigit & std::ctype_base::mask::alnum;
+ SResult^= std::ctype_base::mask::alnum ^ std::ctype_base::mask::graph;
+
+ SResult&= std::ctype_base::mask::space & M;
+ SResult|= std::ctype_base::mask::space | M;
+ SResult^= std::ctype_base::mask::space ^ M;
+
+ // std::ios_base::fmtflags
+ std::ios_base::fmtflags F = std::ios_base::fmtflags::floatfield;
+
+ SResult = std::ios_base::fmtflags::dec | std::ios_base::fmtflags::oct;
+ SResult = std::ios_base::fmtflags::hex & std::ios_base::fmtflags::basefield;
+ SResult = std::ios_base::fmtflags::left ^ std::ios_base::fmtflags::right;
+ SResult|= std::ios_base::fmtflags::internal | std::ios_base::fmtflags::adjustfield;
+ SResult&= std::ios_base::fmtflags::scientific & std::ios_base::fmtflags::fixed;
+ SResult^= std::ios_base::fmtflags::floatfield ^ std::ios_base::fmtflags::boolalpha;
+ SResult = std::ios_base::fmtflags::showbase | std::ios_base::fmtflags::showpoint;
+ SResult = std::ios_base::fmtflags::showpos & std::ios_base::fmtflags::skipws;
+ SResult = std::ios_base::fmtflags::unitbuf ^ std::ios_base::fmtflags::uppercase;
+
+ SResult|= std::ios_base::fmtflags::unitbuf | F;
+ SResult&= std::ios_base::fmtflags::unitbuf & F;
+ SResult^= std::ios_base::fmtflags::unitbuf ^ F;
+
+ // std::ios_base::iostate
+ std::ios_base::iostate S = std::ios_base::iostate::goodbit;
+
+ SResult^= std::ios_base::iostate::goodbit | std::ios_base::iostate::badbit;
+ SResult|= std::ios_base::iostate::failbit & std::ios_base::iostate::eofbit;
+ SResult&= std::ios_base::iostate::failbit ^ std::ios_base::iostate::eofbit;
+
+ SResult = std::ios_base::iostate::goodbit | S;
+ SResult = std::ios_base::iostate::goodbit & S;
+ SResult = std::ios_base::iostate::goodbit ^ S;
+
+ // std::ios_base::openmode
+ std::ios_base::openmode B = std::ios_base::openmode::binary;
+
+ SResult = std::ios_base::openmode::app | std::ios_base::openmode::binary;
+ SResult = std::ios_base::openmode::in & std::ios_base::openmode::out;
+ SResult = std::ios_base::openmode::trunc ^ std::ios_base::openmode::ate;
+
+ SResult&= std::ios_base::openmode::trunc | B;
+ SResult^= std::ios_base::openmode::trunc & B;
+ SResult|= std::ios_base::openmode::trunc ^ B;
+}
+
+void still_forbidden() {
+ // std::locale::category
+ unsigned int UResult = 0u;
+ int SResult = 0;
+
+ SResult = std::ctype_base::mask::print ^ 8u;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ SResult = std::ctype_base::mask::cntrl | 8;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ SResult = std::ctype_base::mask::upper & 8;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ SResult = std::ctype_base::mask::lower ^ -8;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+
+ // Staying within the allowed standard types is ok for bitwise assignment
+ // operations.
+ std::ctype_base::mask var = std::ctype_base::mask::print;
+ SResult<<= std::ctype_base::mask::upper;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ SResult>>= std::ctype_base::mask::upper;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ SResult &= std::ctype_base::mask::upper;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ SResult |= std::ctype_base::mask::upper;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ SResult ^= std::ctype_base::mask::upper;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+
+ UResult = std::locale::category::collate << 1u;
+ UResult = std::locale::category::ctype << 1;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ UResult = std::locale::category::monetary >> 1u;
+ UResult = std::locale::category::numeric >> 1;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+
+ UResult = ~std::locale::category::messages;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+ SResult = ~std::locale::category::all;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+
+ // std::ctype_base::mask
+ UResult = std::ctype_base::mask::space | 8;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ UResult = std::ctype_base::mask::print & 8u;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ UResult = std::ctype_base::mask::cntrl ^ -8;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+
+ UResult = std::ctype_base::mask::upper << 1;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ UResult = std::ctype_base::mask::lower << 1u;
+ UResult = std::ctype_base::mask::alpha >> 1u;
+ UResult = std::ctype_base::mask::digit >> 1u;
+
+ UResult = ~std::ctype_base::mask::punct;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+ SResult = ~std::ctype_base::mask::xdigit;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+
+ // std::ios_base::fmtflags
+ UResult = std::ios_base::fmtflags::dec | 1;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ UResult = std::ios_base::fmtflags::oct & 1u;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ UResult = std::ios_base::fmtflags::hex ^ -1;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+
+ UResult = std::ios_base::fmtflags::basefield >> 1;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ UResult = std::ios_base::fmtflags::left >> 1u;
+ UResult = std::ios_base::fmtflags::right << 1;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ UResult = std::ios_base::fmtflags::internal << 1u;
+
+ UResult = ~std::ios_base::fmtflags::adjustfield;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+ SResult = ~std::ios_base::fmtflags::scientific;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+
+ // std::ios_base::iostate
+ UResult = std::ios_base::iostate::goodbit | 8;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ UResult = std::ios_base::iostate::badbit & 8u;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ UResult = std::ios_base::iostate::failbit ^ -8;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+
+ UResult = std::ios_base::iostate::eofbit << 1;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ UResult = std::ios_base::iostate::goodbit << 1u;
+ UResult = std::ios_base::iostate::badbit >> 1;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ UResult = std::ios_base::iostate::failbit >> 1u;
+
+ UResult = ~std::ios_base::iostate::eofbit;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+ SResult = ~std::ios_base::iostate::goodbit;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+
+ // std::ios_base::openmode
+ UResult = std::ios_base::app | 8;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ UResult = std::ios_base::binary & 8u;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ UResult = std::ios_base::in ^ -8;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+
+ UResult = std::ios_base::out >> 1;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ UResult = std::ios_base::trunc >> 1u;
+ UResult = std::ios_base::ate << 1;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ UResult = std::ios_base::ate << 1u;
+
+ UResult = ~std::ios_base::openmode::app;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+ SResult = ~std::ios_base::openmode::binary;
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise-standard-types.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise-standard-types.h
new file mode 100644
index 0000000..e66fd09
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise-standard-types.h
@@ -0,0 +1,81 @@
+#pragma clang system_header
+
+// Implement standard types that are known to be defined as unsigned in some
+// implementations like MSVC.
+namespace std {
+namespace locale {
+enum category : int {
+ none = 0u,
+ collate = 1u << 1u,
+ ctype = 1u << 2u,
+ monetary = 1u << 3u,
+ numeric = 1u << 4u,
+ time = 1u << 5u,
+ messages = 1u << 6u,
+ all = none | collate | ctype | monetary | numeric | time | messages
+ // CHECK MESSAGES: [[@LINE-1]]:9: warning: use of a signed integer operand with a binary bitwise operator
+};
+} // namespace locale
+
+namespace ctype_base {
+enum mask : int {
+ space,
+ print,
+ cntrl,
+ upper,
+ lower,
+ alpha,
+ digit,
+ punct,
+ xdigit,
+ /* blank, // C++11 */
+ alnum = alpha | digit,
+ // CHECK MESSAGES: [[@LINE-1]]:11: warning: use of a signed integer operand with a binary bitwise operator
+ graph = alnum | punct
+ // CHECK MESSAGES: [[@LINE-1]]:11: warning: use of a signed integer operand with a binary bitwise operator
+};
+} // namespace ctype_base
+
+namespace ios_base {
+enum fmtflags : int {
+ dec = 0u,
+ oct = 1u << 2u,
+ hex = 1u << 3u,
+ basefield = dec | oct | hex | 0u,
+ // CHECK MESSAGES: [[@LINE-1]]:15: warning: use of a signed integer operand with a binary bitwise operator
+ left = 1u << 4u,
+ right = 1u << 5u,
+ internal = 1u << 6u,
+ adjustfield = left | right | internal,
+ // CHECK MESSAGES: [[@LINE-1]]:17: warning: use of a signed integer operand with a binary bitwise operator
+ scientific = 1u << 7u,
+ fixed = 1u << 8u,
+ floatfield = scientific | fixed | (scientific | fixed) | 0u,
+ // CHECK MESSAGES: [[@LINE-1]]:16: warning: use of a signed integer operand with a binary bitwise operator
+ // CHECK MESSAGES: [[@LINE-2]]:38: warning: use of a signed integer operand with a binary bitwise operator
+ boolalpha = 1u << 9u,
+ showbase = 1u << 10u,
+ showpoint = 1u << 11u,
+ showpos = 1u << 12u,
+ skipws = 1u << 13u,
+ unitbuf = 1u << 14u,
+ uppercase = 1u << 15u
+};
+
+enum iostate : int {
+ goodbit = 0u,
+ badbit = 1u << 1u,
+ failbit = 1u << 2u,
+ eofbit = 1u << 3u
+};
+
+enum openmode : int {
+ app = 0u,
+ binary = 0u << 1u,
+ in = 0u << 2u,
+ out = 0u << 3u,
+ trunc = 0u << 4u,
+ ate = 0u << 5u
+};
+} // namespace ios_base
+} // namespace std
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise.cpp
new file mode 100644
index 0000000..97a24b6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise.cpp
@@ -0,0 +1,240 @@
+// RUN: %check_clang_tidy %s hicpp-signed-bitwise %t -- -- -std=c++11 --target=x86_64-linux
+
+// These could cause false positives and should not be considered.
+struct StreamClass {
+};
+StreamClass &operator<<(StreamClass &os, unsigned int i) {
+ return os;
+}
+StreamClass &operator<<(StreamClass &os, int i) {
+ return os;
+}
+StreamClass &operator>>(StreamClass &os, unsigned int i) {
+ return os;
+}
+StreamClass &operator>>(StreamClass &os, int i) {
+ return os;
+}
+struct AnotherStream {
+ AnotherStream &operator<<(unsigned char c) { return *this; }
+ AnotherStream &operator<<(signed char c) { return *this; }
+
+ AnotherStream &operator>>(unsigned char c) { return *this; }
+ AnotherStream &operator>>(signed char c) { return *this; }
+};
+
+void binary_bitwise() {
+ int SValue = 42;
+ int SResult;
+
+ unsigned int UValue = 42;
+ unsigned int UResult;
+
+ SResult = SValue & 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ SResult = SValue & -1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ SResult = SValue & SValue;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+
+ UResult = SValue & 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ UResult = SValue & -1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ UResult&= 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator
+
+ UResult = UValue & 1u; // Ok
+ UResult = UValue & UValue; // Ok
+ UResult&= 2u; // Ok
+
+ unsigned char UByte1 = 0u;
+ unsigned char UByte2 = 16u;
+ signed char SByte1 = 0;
+ signed char SByte2 = 16;
+
+ UByte1 = UByte1 & UByte2; // Ok
+ UByte1 = SByte1 & UByte2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+ UByte1 = SByte1 & SByte2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+ SByte1 = SByte1 & SByte2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+
+ // More complex expressions.
+ UResult = UValue & (SByte1 + (SByte1 | SByte2));
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+ // CHECK-MESSAGES: :[[@LINE-2]]:33: warning: use of a signed integer operand with a binary bitwise operator
+
+ // The rest is to demonstrate functionality but all operators are matched equally.
+ // Therefore functionality is the same for all binary operations.
+ UByte1 = UByte1 | UByte2; // Ok
+ UByte1 = UByte1 | SByte2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+ UByte1|= SByte2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator
+ UByte1|= UByte2; // Ok
+
+ UByte1 = UByte1 ^ UByte2; // Ok
+ UByte1 = UByte1 ^ SByte2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+ UByte1^= SByte2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator
+ UByte1^= UByte2; // Ok
+
+ UByte1 = UByte1 >> UByte2; // Ok
+ UByte1 = UByte1 >> SByte2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+ UByte1>>= SByte2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator
+ UByte1>>= UByte2; // Ok
+
+ UByte1 = UByte1 << UByte2; // Ok
+ UByte1 = UByte1 << SByte2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+ UByte1<<= SByte2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator
+ UByte1<<= UByte2; // Ok
+
+ int SignedInt1 = 1 << 12;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use of a signed integer operand with a binary bitwise operator
+ int SignedInt2 = 1u << 12;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use of a signed integer operand with a binary bitwise operator
+}
+
+void f1(unsigned char c) {}
+void f2(signed char c) {}
+void f3(int c) {}
+
+void unary_bitwise() {
+ unsigned char UByte1 = 0u;
+ signed char SByte1 = 0;
+
+ UByte1 = ~UByte1; // Ok
+ SByte1 = ~UByte1;
+ SByte1 = ~SByte1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a unary bitwise operator
+ UByte1 = ~SByte1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a unary bitwise operator
+
+ unsigned int UInt = 0u;
+ int SInt = 0;
+
+ f1(~UByte1); // Ok
+ f1(~SByte1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use of a signed integer operand with a unary bitwise operator
+ f1(~UInt);
+ f1(~SInt);
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use of a signed integer operand with a unary bitwise operator
+ f2(~UByte1);
+ f2(~SByte1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use of a signed integer operand with a unary bitwise operator
+ f2(~UInt);
+ f2(~SInt);
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use of a signed integer operand with a unary bitwise operator
+ f3(~UByte1); // Ok
+ f3(~SByte1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use of a signed integer operand with a unary bitwise operator
+}
+
+/// HICPP uses these examples to demonstrate the rule.
+void standard_examples() {
+ int i = 3;
+ unsigned int k = 0u;
+
+ int r = i << -1; // Emits -Wshift-count-negative from clang
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use of a signed integer operand with a binary bitwise operator
+ r = i << 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+
+ r = -1 >> -1; // Emits -Wshift-count-negative from clang
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+ r = -1 >> 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+
+ r = -1 >> i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+ r = -1 >> -i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+
+ r = ~0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a unary bitwise operator
+ r = ~0u; // Ok
+ k = ~k; // Ok
+
+ unsigned int u = (-1) & 2u;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use of a signed integer operand with a binary bitwise operator
+ u = (-1) | 1u;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+ u = (-1) ^ 1u;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+}
+
+void streams_should_work() {
+ StreamClass s;
+ s << 1u; // Ok
+ s << 1; // Ok
+ s >> 1; // Ok
+ s >> 1u; // Ok
+
+ AnotherStream as;
+ unsigned char uc = 1u;
+ signed char sc = 1;
+ as << uc; // Ok
+ as << sc; // Ok
+ as >> uc; // Ok
+ as >> sc; // Ok
+}
+
+enum OldEnum {
+ ValueOne,
+ ValueTwo,
+};
+
+enum OldSigned : int {
+ IntOne,
+ IntTwo,
+};
+
+void classicEnums() {
+ OldEnum e1 = ValueOne, e2 = ValueTwo;
+ int e3; // Using the enum type, results in an error.
+ e3 = ValueOne | ValueTwo; // Ok
+ e3 = ValueOne & ValueTwo; // Ok
+ e3 = ValueOne ^ ValueTwo; // Ok
+ e3 = e1 | e2; // Ok
+ e3 = e1 & e2; // Ok
+ e3 = e1 ^ e2; // Ok
+
+ OldSigned s1 = IntOne, s2 = IntTwo;
+ int s3;
+ s3 = IntOne | IntTwo; // Signed
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator
+ s3|= IntTwo; // Signed
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator
+ s3 = IntOne & IntTwo; // Signed
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator
+ s3&= IntTwo; // Signed
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator
+ s3 = IntOne ^ IntTwo; // Signed
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator
+ s3^= IntTwo; // Signed
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator
+ s3 = s1 | s2; // Signed
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator
+ s3 = s1 & s2; // Signed
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator
+ s3 = s1 ^ s2; // Signed
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator
+}
+
+enum EnumConstruction {
+ one = 1,
+ two = 2,
+ test1 = 1 << 12,
+ // CHECK-MESSAGES: [[@LINE-1]]:11: warning: use of a signed integer operand with a binary bitwise operator
+ test2 = one << two,
+ // CHECK-MESSAGES: [[@LINE-1]]:11: warning: use of a signed integer operand with a binary bitwise operator
+ test3 = 1u << 12,
+ // CHECK-MESSAGES: [[@LINE-1]]:11: warning: use of a signed integer operand with a binary bitwise operator
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/line-filter.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/line-filter.cpp
new file mode 100644
index 0000000..ad980cf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/line-filter.cpp
@@ -0,0 +1,27 @@
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -line-filter='[{"name":"line-filter.cpp","lines":[[18,18],[22,22]]},{"name":"header1.h","lines":[[1,2]]},{"name":"header2.h"},{"name":"header3.h"}]' -header-filter='header[12]\.h$' %s -- -I %S/Inputs/line-filter 2>&1 | FileCheck %s
+
+#include "header1.h"
+// CHECK-NOT: header1.h:{{.*}} warning
+// CHECK: header1.h:1:12: warning: single-argument constructors must be marked explicit
+// CHECK: header1.h:2:12: warning: single-argument constructors {{.*}}
+// CHECK-NOT: header1.h:{{.*}} warning
+
+#include "header2.h"
+// CHECK: header2.h:1:12: warning: single-argument constructors {{.*}}
+// CHECK: header2.h:2:12: warning: single-argument constructors {{.*}}
+// CHECK: header2.h:3:12: warning: single-argument constructors {{.*}}
+// CHECK-NOT: header2.h:{{.*}} warning
+
+#include "header3.h"
+// CHECK-NOT: header3.h:{{.*}} warning
+
+class A { A(int); };
+// CHECK: :[[@LINE-1]]:11: warning: single-argument constructors {{.*}}
+class B { B(int); };
+// CHECK-NOT: :[[@LINE-1]]:{{.*}} warning
+class C { C(int); };
+// CHECK: :[[@LINE-1]]:11: warning: single-argument constructors {{.*}}
+
+// CHECK-NOT: warning:
+
+// CHECK: Suppressed 3 warnings (1 in non-user code, 2 due to line filter)
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/list-checks.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/list-checks.cpp
new file mode 100644
index 0000000..674c118
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/list-checks.cpp
@@ -0,0 +1,4 @@
+// RUN: mkdir -p %T/clang-tidy/list-checks/
+// RUN: echo '{Checks: "-*,google-*"}' > %T/clang-tidy/.clang-tidy
+// RUN: cd %T/clang-tidy/list-checks
+// RUN: clang-tidy -list-checks | grep "^ *google-"
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/llvm-include-order.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/llvm-include-order.cpp
new file mode 100644
index 0000000..7272353
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/llvm-include-order.cpp
@@ -0,0 +1,42 @@
+// RUN: %check_clang_tidy %s llvm-include-order %t -- -- -isystem %S/Inputs/Headers
+
+// CHECK-MESSAGES: [[@LINE+2]]:1: warning: #includes are not sorted properly
+#include "j.h"
+#include "gtest/foo.h"
+#include "i.h"
+#include <s.h>
+#include "llvm/a.h"
+#include "clang/b.h"
+#include "clang-c/c.h" // hi
+#include "llvm-c/d.h" // -c
+
+// CHECK-FIXES: #include "j.h"
+// CHECK-FIXES-NEXT: #include "i.h"
+// CHECK-FIXES-NEXT: #include "clang-c/c.h" // hi
+// CHECK-FIXES-NEXT: #include "clang/b.h"
+// CHECK-FIXES-NEXT: #include "llvm-c/d.h" // -c
+// CHECK-FIXES-NEXT: #include "llvm/a.h"
+// CHECK-FIXES-NEXT: #include "gtest/foo.h"
+// CHECK-FIXES-NEXT: #include <s.h>
+
+#include "b.h"
+#ifdef FOO
+#include "a.h"
+#endif
+
+// CHECK-FIXES: #include "b.h"
+// CHECK-FIXES-NEXT: #ifdef FOO
+// CHECK-FIXES-NEXT: #include "a.h"
+// CHECK-FIXES-NEXT: #endif
+
+// CHECK-MESSAGES: [[@LINE+1]]:1: warning: #includes are not sorted properly
+#include "b.h"
+#include "a.h"
+
+// CHECK-FIXES: #include "a.h"
+// CHECK-FIXES-NEXT: #include "b.h"
+
+// CHECK-MESSAGES-NOT: [[@LINE+1]]:1: warning: #includes are not sorted properly
+#include "cross-file-c.h"
+// This line number should correspond to the position of the #include in cross-file-c.h
+#include "cross-file-a.h"
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/llvm-twine-local.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/llvm-twine-local.cpp
new file mode 100644
index 0000000..06eb761
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/llvm-twine-local.cpp
@@ -0,0 +1,64 @@
+// RUN: %check_clang_tidy %s llvm-twine-local %t
+
+namespace llvm {
+class Twine {
+public:
+ Twine(const char *);
+ Twine(int);
+ Twine();
+ Twine &operator+(const Twine &);
+};
+}
+
+using namespace llvm;
+
+void foo(const Twine &x);
+
+static Twine Moo = Twine("bark") + "bah";
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: twine variables are prone to use-after-free bugs
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-FIXES: static std::string Moo = (Twine("bark") + "bah").str();
+
+int main() {
+ const Twine t = Twine("a") + "b" + Twine(42);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: twine variables are prone to use-after-free bugs
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-FIXES: std::string t = (Twine("a") + "b" + Twine(42)).str();
+ foo(Twine("a") + "b");
+
+ Twine Prefix = false ? "__INT_FAST" : "__UINT_FAST";
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: twine variables are prone to use-after-free bugs
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-FIXES: const char * Prefix = false ? "__INT_FAST" : "__UINT_FAST";
+
+ const Twine t2 = Twine();
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: twine variables are prone to use-after-free bugs
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-FIXES: std::string t2 = (Twine()).str();
+ foo(Twine() + "b");
+
+ const Twine t3 = Twine(42);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: twine variables are prone to use-after-free bugs
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-FIXES: std::string t3 = (Twine(42)).str();
+
+ const Twine t4 = Twine(42) + "b";
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: twine variables are prone to use-after-free bugs
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-FIXES: std::string t4 = (Twine(42) + "b").str();
+
+ const Twine t5 = Twine() + "b";
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: twine variables are prone to use-after-free bugs
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-FIXES: std::string t5 = (Twine() + "b").str();
+
+ const Twine t6 = true ? Twine() : Twine(42);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: twine variables are prone to use-after-free bugs
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-FIXES: std::string t6 = (true ? Twine() : Twine(42)).str();
+
+ const Twine t7 = false ? Twine() : Twine("b");
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: twine variables are prone to use-after-free bugs
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-FIXES: std::string t7 = (false ? Twine() : Twine("b")).str();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/macros.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/macros.cpp
new file mode 100644
index 0000000..fa4f32a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/macros.cpp
@@ -0,0 +1,7 @@
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' %s -- | FileCheck %s
+
+#define Q(name) class name { name(int i); }
+
+Q(A);
+// CHECK: :[[@LINE-1]]:3: warning: single-argument constructors must be marked explicit
+// CHECK: :3:30: note: expanded from macro 'Q'
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-definitions-in-headers-1z.hpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-definitions-in-headers-1z.hpp
new file mode 100644
index 0000000..79fb7bc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-definitions-in-headers-1z.hpp
@@ -0,0 +1,10 @@
+// RUN: %check_clang_tidy %s misc-definitions-in-headers %t -- -- -std=c++1z
+
+class CE {
+ constexpr static int i = 5; // OK: inline variable definition.
+};
+
+inline int i = 5; // OK: inline variable definition.
+
+int b = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'b' defined in a header file; variable definitions in header files can lead to ODR violations [misc-definitions-in-headers]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-definitions-in-headers.hpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-definitions-in-headers.hpp
new file mode 100644
index 0000000..5e83e68
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-definitions-in-headers.hpp
@@ -0,0 +1,181 @@
+// RUN: %check_clang_tidy %s misc-definitions-in-headers %t
+
+int f() {
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f' defined in a header file; function definitions in header files can lead to ODR violations [misc-definitions-in-headers]
+// CHECK-FIXES: inline int f() {
+ return 1;
+}
+
+class CA {
+ void f1() {} // OK: inline class member function definition.
+ void f2();
+ template<typename T>
+ T f3() {
+ T a = 1;
+ return a;
+ }
+ template<typename T>
+ struct CAA {
+ struct CAB {
+ void f4();
+ };
+ };
+};
+
+void CA::f2() { }
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: function 'f2' defined in a header file;
+// CHECK-FIXES: inline void CA::f2() {
+
+template <>
+int CA::f3() {
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: full function template specialization 'f3<int>' defined in a header file;
+// CHECK-FIXES: inline int CA::f3() {
+ int a = 1;
+ return a;
+}
+
+template <typename T>
+void CA::CAA<T>::CAB::f4() {
+// OK: member function definition of a nested template class in a class.
+}
+
+template <typename T>
+struct CB {
+ void f1();
+ struct CCA {
+ void f2(T a);
+ };
+ struct CCB; // OK: forward declaration.
+ static int a; // OK: class static data member declaration.
+};
+
+template <typename T>
+void CB<T>::f1() { // OK: Member function definition of a class template.
+}
+
+template <typename T>
+void CB<T>::CCA::f2(T a) {
+// OK: member function definition of a nested class in a class template.
+}
+
+template <typename T>
+struct CB<T>::CCB {
+ void f3();
+};
+
+template <typename T>
+void CB<T>::CCB::f3() {
+// OK: member function definition of a nested class in a class template.
+}
+
+template <typename T>
+int CB<T>::a = 2; // OK: static data member definition of a class template.
+
+template class CB<int>; // OK: explicitly instantiated static data member of a class template.
+inline int callCB() {
+ CB<double> cb; // OK: implicitly instantiated static data member of a class template.
+ return cb.a;
+}
+
+template <typename T>
+T tf() { // OK: template function definition.
+ T a;
+ return a;
+}
+
+
+namespace NA {
+ int f() { return 1; }
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: function 'f' defined in a header file;
+// CHECK-FIXES: inline int f() { return 1; }
+}
+
+template <typename T>
+T f3() {
+ T a = 1;
+ return a;
+}
+
+template <>
+int f3() {
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: full function template specialization 'f3<int>' defined in a header file;
+// CHECK-FIXES: inline int f3() {
+ int a = 1;
+ return a;
+}
+
+int f5(); // OK: function declaration.
+inline int f6() { return 1; } // OK: inline function definition.
+namespace {
+ int f7() { return 1; }
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: function 'f7' defined in a header file;
+}
+
+int f8() = delete; // OK: the function being marked delete is not callable.
+
+template <typename T>
+int f9(T t) { return 1; }
+
+inline void callF9() { f9(1); } // OK: implicitly instantiated function.
+template int f9(double); // OK: explicitly instantiated function.
+
+int a = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'a' defined in a header file; variable definitions in header files can lead to ODR violations [misc-definitions-in-headers]
+CA a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:4: warning: variable 'a1' defined in a header file;
+
+namespace NB {
+ int b = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: variable 'b' defined in a header file;
+ const int c = 1; // OK: internal linkage variable definition.
+}
+
+class CC {
+ static int d; // OK: class static data member declaration.
+};
+
+int CC::d = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: variable 'd' defined in a header file;
+
+const char* ca = "foo";
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: variable 'ca' defined in a header file;
+
+namespace {
+ int e = 2;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: variable 'e' defined in a header file;
+}
+
+const char* const g = "foo"; // OK: internal linkage variable definition.
+static int h = 1; // OK: internal linkage variable definition.
+const int i = 1; // OK: internal linkage variable definition.
+extern int j; // OK: internal linkage variable definition.
+
+template <typename T, typename U>
+struct CD {
+ int f();
+};
+
+template <typename T>
+struct CD<T, int> {
+ int f();
+};
+
+template <>
+struct CD<int, int> {
+ int f();
+};
+
+int CD<int, int>::f() {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: function 'f' defined in a header file;
+// CHECK-FIXES: inline int CD<int, int>::f() {
+ return 0;
+}
+
+template <typename T>
+int CD<T, int>::f() { // OK: partial template specialization.
+ return 0;
+}
+
+constexpr int k = 1; // OK: constexpr variable has internal linkage.
+
+constexpr int f10() { return 0; } // OK: constexpr function definition.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-misplaced-const-cxx17.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-misplaced-const-cxx17.cpp
new file mode 100644
index 0000000..7816a09
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-misplaced-const-cxx17.cpp
@@ -0,0 +1,15 @@
+// RUN: %check_clang_tidy -expect-clang-tidy-error %s misc-misplaced-const %t -- -- -std=c++17
+
+// This test previously would cause a failed assertion because the structured
+// binding declaration had no valid type associated with it. This ensures the
+// expected clang diagnostic is generated instead.
+// CHECK-MESSAGES: :[[@LINE+1]]:6: error: decomposition declaration '[x]' requires an initializer [clang-diagnostic-error]
+auto [x];
+
+struct S { int a; };
+S f();
+
+int main() {
+ auto [x] = f();
+}
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-misplaced-const.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-misplaced-const.c
new file mode 100644
index 0000000..cccf3a4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-misplaced-const.c
@@ -0,0 +1,45 @@
+// RUN: %check_clang_tidy %s misc-misplaced-const %t
+
+typedef int plain_i;
+typedef int *ip;
+typedef const int *cip;
+
+typedef void (*func_ptr)(void);
+
+void func(void) {
+ // ok
+ const int *i0 = 0;
+ const plain_i *i1 = 0;
+ const cip i2 = 0; // const applies to both pointer and pointee.
+
+ // Not ok
+ const ip i3 = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: 'i3' declared with a const-qualified typedef type; results in the type being 'int *const' instead of 'const int *'
+
+ ip const i4 = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: 'i4' declared with a const-qualified
+
+ const volatile ip i5 = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: 'i5' declared with a const-qualified typedef type; results in the type being 'int *const volatile' instead of 'const int *volatile'
+}
+
+void func2(const plain_i *i1,
+ const cip i2,
+ const ip i3,
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: 'i3' declared with a const-qualified
+ const int *i4) {
+}
+
+struct S {
+ const int *i0;
+ const plain_i *i1;
+ const cip i2;
+ const ip i3;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: 'i3' declared with a const-qualified
+};
+
+// Function pointers should not be diagnosed because a function
+// pointer type can never be const.
+void func3(const func_ptr fp) {
+ const func_ptr fp2 = fp;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-misplaced-const.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-misplaced-const.cpp
new file mode 100644
index 0000000..d7ea893
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-misplaced-const.cpp
@@ -0,0 +1,44 @@
+// RUN: %check_clang_tidy %s misc-misplaced-const %t
+
+typedef int plain_i;
+typedef int *ip;
+typedef const int *cip;
+
+void func() {
+ if (const int *i = 0)
+ ;
+ if (const plain_i *i = 0)
+ ;
+ if (const cip i = 0)
+ ;
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:16: warning: 'i' declared with a const-qualified typedef type; results in the type being 'int *const' instead of 'const int *'
+ if (const ip i = 0)
+ ;
+}
+
+template <typename Ty>
+struct S {
+ const Ty *i;
+ const Ty &i2;
+};
+
+template struct S<int>;
+template struct S<ip>; // ok
+template struct S<cip>;
+
+template <typename Ty>
+struct U {
+ const Ty *i;
+ const Ty &i2;
+};
+
+template struct U<int *>; // ok
+
+struct T {
+ typedef void (T::*PMF)();
+
+ void f() {
+ const PMF val = &T::f; // ok
+ }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-new-delete-overloads-sized-dealloc.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-new-delete-overloads-sized-dealloc.cpp
new file mode 100644
index 0000000..2ba60e4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-new-delete-overloads-sized-dealloc.cpp
@@ -0,0 +1,20 @@
+// RUN: %check_clang_tidy %s misc-new-delete-overloads %t -- -- -std=c++14 -fsized-deallocation
+
+typedef decltype(sizeof(int)) size_t;
+
+struct S {
+ // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: declaration of 'operator delete' has no matching declaration of 'operator new' at the same scope [misc-new-delete-overloads]
+ void operator delete(void *ptr, size_t) noexcept; // not a placement delete
+};
+
+struct T {
+ // Because we have enabled sized deallocations explicitly, this new/delete
+ // pair matches.
+ void *operator new(size_t size) noexcept;
+ void operator delete(void *ptr, size_t) noexcept; // ok because sized deallocation is enabled
+};
+
+// While we're here, check that global operator delete with no operator new
+// is also matched.
+// CHECK-MESSAGES: :[[@LINE+1]]:6: warning: declaration of 'operator delete' has no matching declaration of 'operator new' at the same scope
+void operator delete(void *ptr) noexcept;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-new-delete-overloads.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-new-delete-overloads.cpp
new file mode 100644
index 0000000..3e60537
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-new-delete-overloads.cpp
@@ -0,0 +1,81 @@
+// RUN: %check_clang_tidy %s misc-new-delete-overloads %t -- -- -std=c++14
+
+typedef decltype(sizeof(int)) size_t;
+
+struct S {
+ // CHECK-MESSAGES: :[[@LINE+1]]:9: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope [misc-new-delete-overloads]
+ void *operator new(size_t size) noexcept;
+ // CHECK-MESSAGES: :[[@LINE+1]]:9: warning: declaration of 'operator new[]' has no matching declaration of 'operator delete[]' at the same scope
+ void *operator new[](size_t size) noexcept;
+};
+
+// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope
+void *operator new(size_t size) noexcept(false);
+
+struct T {
+ // Sized deallocations are not enabled by default, and so this new/delete pair
+ // does not match. However, we expect only one warning, for the new, because
+ // the operator delete is a placement delete and we do not warn on mismatching
+ // placement operations.
+ // CHECK-MESSAGES: :[[@LINE+1]]:9: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope
+ void *operator new(size_t size) noexcept;
+ void operator delete(void *ptr, size_t) noexcept; // ok only if sized deallocation is enabled
+};
+
+struct U {
+ void *operator new(size_t size) noexcept;
+ void operator delete(void *ptr) noexcept;
+
+ void *operator new[](size_t) noexcept;
+ void operator delete[](void *) noexcept;
+};
+
+struct Z {
+ // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: declaration of 'operator delete' has no matching declaration of 'operator new' at the same scope
+ void operator delete(void *ptr) noexcept;
+ // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: declaration of 'operator delete[]' has no matching declaration of 'operator new[]' at the same scope
+ void operator delete[](void *ptr) noexcept;
+};
+
+struct A {
+ void *operator new(size_t size, Z) noexcept; // ok, placement new
+};
+
+struct B {
+ void operator delete(void *ptr, A) noexcept; // ok, placement delete
+};
+
+// It is okay to have a class with an inaccessible free store operator.
+struct C {
+ void *operator new(size_t, A) noexcept; // ok, placement new
+private:
+ void operator delete(void *) noexcept;
+};
+
+// It is also okay to have a class with a delete free store operator.
+struct D {
+ void *operator new(size_t, A) noexcept; // ok, placement new
+ void operator delete(void *) noexcept = delete;
+};
+
+struct E : U {
+ void *operator new(size_t) noexcept; // okay, we inherit operator delete from U
+};
+
+struct F : S {
+ // CHECK-MESSAGES: :[[@LINE+1]]:9: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope
+ void *operator new(size_t) noexcept;
+};
+
+class G {
+ void operator delete(void *) noexcept;
+};
+
+struct H : G {
+ // CHECK-MESSAGES: :[[@LINE+1]]:9: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope
+ void *operator new(size_t) noexcept; // base class operator is inaccessible
+};
+
+template <typename Base> struct Derived : Base {
+ void operator delete(void *);
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-non-copyable-objects.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-non-copyable-objects.c
new file mode 100644
index 0000000..ac6198e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-non-copyable-objects.c
@@ -0,0 +1,43 @@
+// RUN: %check_clang_tidy %s misc-non-copyable-objects %t
+
+typedef struct FILE {} FILE;
+typedef struct pthread_cond_t {} pthread_cond_t;
+typedef int pthread_mutex_t;
+
+// CHECK-MESSAGES: :[[@LINE+1]]:13: warning: 'f' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'? [misc-non-copyable-objects]
+void g(FILE f);
+// CHECK-MESSAGES: :[[@LINE+1]]:24: warning: 'm' declared as type 'pthread_mutex_t', which is unsafe to copy; did you mean 'pthread_mutex_t *'?
+void h(pthread_mutex_t m);
+// CHECK-MESSAGES: :[[@LINE+1]]:23: warning: 'c' declared as type 'pthread_cond_t', which is unsafe to copy; did you mean 'pthread_cond_t *'?
+void i(pthread_cond_t c);
+
+struct S {
+ pthread_cond_t c; // ok
+ // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: 'f' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+ FILE f;
+};
+
+void func(FILE *f) {
+ // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: 'f1' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+ FILE f1; // match
+ // CHECK-MESSAGES: :[[@LINE+2]]:8: warning: 'f2' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+ // CHECK-MESSAGES: :[[@LINE+1]]:13: warning: expression has opaque data structure type 'FILE'; type should only be used as a pointer and not dereferenced
+ FILE f2 = *f;
+ // CHECK-MESSAGES: :[[@LINE+1]]:15: warning: 'f3' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+ struct FILE f3;
+ // CHECK-MESSAGES: :[[@LINE+1]]:16: warning: expression has opaque data structure type 'FILE'; type should only be used as a pointer and not dereferenced
+ (void)sizeof(*f);
+ (void)sizeof(FILE);
+ // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: expression has opaque data structure type 'FILE'; type should only be used as a pointer and not dereferenced
+ g(*f);
+
+ pthread_mutex_t m; // ok
+ h(m); // ok
+
+ pthread_cond_t c; // ok
+ i(c); // ok
+
+ pthread_mutex_t *m1 = &m; // ok
+ // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: expression has opaque data structure type 'pthread_mutex_t'; type should only be used as a pointer and not dereferenced
+ h(*m1);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-non-copyable-objects.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-non-copyable-objects.cpp
new file mode 100644
index 0000000..3d716f4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-non-copyable-objects.cpp
@@ -0,0 +1,26 @@
+// RUN: %check_clang_tidy %s misc-non-copyable-objects %t
+
+namespace std {
+typedef struct FILE {} FILE;
+}
+using namespace std;
+
+// CHECK-MESSAGES: :[[@LINE+1]]:18: warning: 'f' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'? [misc-non-copyable-objects]
+void g(std::FILE f);
+
+struct S {
+ // CHECK-MESSAGES: :[[@LINE+1]]:10: warning: 'f' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+ ::FILE f;
+};
+
+void func(FILE *f) {
+ // CHECK-MESSAGES: :[[@LINE+1]]:13: warning: 'f1' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+ std::FILE f1; // match
+ // CHECK-MESSAGES: :[[@LINE+2]]:10: warning: 'f2' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+ // CHECK-MESSAGES: :[[@LINE+1]]:15: warning: expression has opaque data structure type 'FILE'; type should only be used as a pointer and not dereferenced
+ ::FILE f2 = *f; // match, match
+ // CHECK-MESSAGES: :[[@LINE+1]]:15: warning: 'f3' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+ struct FILE f3; // match
+ // CHECK-MESSAGES: :[[@LINE+1]]:16: warning: expression has opaque data structure type 'FILE'; type should only be used as a pointer and not dereferenced
+ (void)sizeof(*f); // match
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-redundant-expression.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-redundant-expression.cpp
new file mode 100644
index 0000000..3454318
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-redundant-expression.cpp
@@ -0,0 +1,727 @@
+// RUN: %check_clang_tidy %s misc-redundant-expression %t -- -- -std=c++11
+
+typedef __INT64_TYPE__ I64;
+
+struct Point {
+ int x;
+ int y;
+ int a[5];
+} P;
+
+extern Point P1;
+extern Point P2;
+
+extern int foo(int x);
+extern int bar(int x);
+extern int bat(int x, int y);
+
+int TestSimpleEquivalent(int X, int Y) {
+ if (X - X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent [misc-redundant-expression]
+ if (X / X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+ if (X % X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+
+ if (X & X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+ if (X | X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+ if (X ^ X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+
+ if (X < X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+ if (X <= X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+ if (X > X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+ if (X >= X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+
+ if (X && X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+ if (X || X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+
+ if (X != (((X)))) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+
+ if (X + 1 == X + 1) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+ if (X + 1 != X + 1) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+ if (X + 1 <= X + 1) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+ if (X + 1 >= X + 1) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+
+ if ((X != 1 || Y != 1) && (X != 1 || Y != 1)) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: both sides of operator are equivalent
+ if (P.a[X - P.x] != P.a[X - P.x]) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: both sides of operator are equivalent
+
+ if ((int)X < (int)X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent
+ if (int(X) < int(X)) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent
+
+ if ( + "dummy" == + "dummy") return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: both sides of operator are equivalent
+ if (L"abc" == L"abc") return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent
+
+ if (foo(0) - 2 < foo(0) - 2) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: both sides of operator are equivalent
+ if (foo(bar(0)) < (foo(bar((0))))) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: both sides of operator are equivalent
+
+ if (P1.x < P2.x && P1.x < P2.x) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: both sides of operator are equivalent
+ if (P2.a[P1.x + 2] < P2.x && P2.a[(P1.x) + (2)] < (P2.x)) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: both sides of operator are equivalent
+
+ return 0;
+}
+
+int Valid(int X, int Y) {
+ if (X != Y) return 1;
+ if (X == Y + 0) return 1;
+ if (P.x == P.y) return 1;
+ if (P.a[P.x] < P.a[P.y]) return 1;
+ if (P.a[0] < P.a[1]) return 1;
+
+ if (P.a[0] < P.a[0ULL]) return 1;
+ if (0 < 0ULL) return 1;
+ if ((int)0 < (int)0ULL) return 1;
+
+ if (++X != ++X) return 1;
+ if (P.a[X]++ != P.a[X]++) return 1;
+ if (P.a[X++] != P.a[X++]) return 1;
+
+ if ("abc" == "ABC") return 1;
+ if (foo(bar(0)) < (foo(bat(0, 1)))) return 1;
+ return 0;
+}
+
+#define COND_OP_MACRO 9
+#define COND_OP_OTHER_MACRO 9
+int TestConditional(int x, int y) {
+ int k = 0;
+ k += (y < 0) ? x : x;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: 'true' and 'false' expressions are equivalent
+ k += (y < 0) ? x + 1 : x + 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: 'true' and 'false' expressions are equivalent
+ k += (y < 0) ? COND_OP_MACRO : COND_OP_MACRO;
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: 'true' and 'false' expressions are equivalent
+
+ // Do not match for conditional operators with a macro and a const.
+ k += (y < 0) ? COND_OP_MACRO : 9;
+ // Do not match for conditional operators with expressions from different macros.
+ k += (y < 0) ? COND_OP_MACRO : COND_OP_OTHER_MACRO;
+ return k;
+}
+#undef COND_OP_MACRO
+#undef COND_OP_OTHER_MACRO
+
+// Overloaded operators that compare two instances of a struct.
+struct MyStruct {
+ int x;
+ bool operator==(const MyStruct& rhs) const {return this->x == rhs.x; } // not modifing
+ bool operator>=(const MyStruct& rhs) const { return this->x >= rhs.x; } // not modifing
+ bool operator<=(MyStruct& rhs) const { return this->x <= rhs.x; }
+ bool operator&&(const MyStruct& rhs){ this->x++; return this->x && rhs.x; }
+} Q;
+
+bool operator!=(const MyStruct& lhs, const MyStruct& rhs) { return lhs.x == rhs.x; } // not modifing
+bool operator<(const MyStruct& lhs, const MyStruct& rhs) { return lhs.x < rhs.x; } // not modifing
+bool operator>(const MyStruct& lhs, MyStruct& rhs) { rhs.x--; return lhs.x > rhs.x; }
+bool operator||(MyStruct& lhs, const MyStruct& rhs) { lhs.x++; return lhs.x || rhs.x; }
+
+bool TestOverloadedOperator(MyStruct& S) {
+ if (S == Q) return false;
+
+ if (S <= S) return false;
+ if (S && S) return false;
+ if (S > S) return false;
+ if (S || S) return false;
+
+ if (S == S) return true;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of overloaded operator are equivalent
+ if (S < S) return true;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of overloaded operator are equivalent
+ if (S != S) return true;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of overloaded operator are equivalent
+ if (S >= S) return true;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of overloaded operator are equivalent
+
+ return true;
+}
+
+#define LT(x, y) (void)((x) < (y))
+#define COND(x, y, z) ((x)?(y):(z))
+#define EQUALS(x, y) (x) == (y)
+
+int TestMacro(int X, int Y) {
+ LT(0, 0);
+ LT(1, 0);
+ LT(X, X);
+ LT(X+1, X + 1);
+ COND(X < Y, X, X);
+ EQUALS(Q, Q);
+ return 0;
+}
+
+int TestFalsePositive(int* A, int X, float F) {
+ // Produced by bison.
+ X = A[(2) - (2)];
+ X = A['a' - 'a'];
+
+ // Testing NaN.
+ if (F != F && F == F) return 1;
+ return 0;
+}
+
+int TestBannedMacros() {
+#define EAGAIN 3
+#define NOT_EAGAIN 3
+ if (EAGAIN == 0 | EAGAIN == 0) return 0;
+ if (NOT_EAGAIN == 0 | NOT_EAGAIN == 0) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: both sides of operator are equivalent
+ return 0;
+}
+
+struct MyClass {
+static const int Value = 42;
+};
+template <typename T, typename U>
+void TemplateCheck() {
+ static_assert(T::Value == U::Value, "should be identical");
+ static_assert(T::Value == T::Value, "should be identical");
+ // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: both sides of operator are equivalent
+}
+void TestTemplate() { TemplateCheck<MyClass, MyClass>(); }
+
+int TestArithmetic(int X, int Y) {
+ if (X + 1 == X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
+ if (X + 1 != X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+ if (X - 1 == X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
+ if (X - 1 != X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+
+ if (X + 1LL == X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
+ if (X + 1ULL == X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: logical expression is always false
+
+ if (X == X + 1) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always false
+ if (X != X + 1) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always true
+ if (X == X - 1) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always false
+ if (X != X - 1) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always true
+
+ if (X != X - 1U) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always true
+ if (X != X - 1LL) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always true
+
+ if ((X+X) != (X+X) - 1) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+
+ if (X + 1 == X + 2) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
+ if (X + 1 != X + 2) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+
+ if (X - 1 == X - 2) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
+ if (X - 1 != X - 2) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+
+ if (X + 1 == X - -1) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+ if (X + 1 != X - -1) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
+ if (X + 1 == X - -2) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
+ if (X + 1 != X - -2) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+
+ if (X + 1 == X - (~0)) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+ if (X + 1 == X - (~0U)) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+
+ if (X + 1 == X - (~0ULL)) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+
+ // Should not match.
+ if (X + 0.5 == X) return 1;
+ if (X + 1 == Y) return 1;
+ if (X + 1 == Y + 1) return 1;
+ if (X + 1 == Y + 2) return 1;
+
+ return 0;
+}
+
+int TestBitwise(int X, int Y) {
+
+ if ((X & 0xFF) == 0xF00) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
+ if ((X & 0xFF) != 0xF00) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true
+ if ((X | 0xFF) == 0xF00) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
+ if ((X | 0xFF) != 0xF00) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true
+
+ if ((X | 0xFFULL) != 0xF00) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: logical expression is always true
+ if ((X | 0xFF) != 0xF00ULL) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true
+
+ if ((0xFF & X) == 0xF00) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
+ if ((0xFF & X) != 0xF00) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true
+ if ((0xFF & X) == 0xF00) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
+ if ((0xFF & X) != 0xF00) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true
+
+ if ((0xFFLL & X) == 0xF00) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: logical expression is always false
+ if ((0xFF & X) == 0xF00ULL) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
+
+ return 0;
+}
+
+// Overloaded operators that compare an instance of a struct and an integer
+// constant.
+struct S {
+ S() { x = 1; }
+ int x;
+ // Overloaded comparison operators without any possible side effect.
+ bool operator==(const int &i) const { return x == i; } // not modifying
+ bool operator!=(int i) const { return x != i; } // not modifying
+ bool operator>(const int &i) const { return x > i; } // not modifying
+ bool operator<(int i) const { return x < i; } // not modifying
+};
+
+bool operator<=(const S &s, int i) { return s.x <= i; } // not modifying
+bool operator>=(const S &s, const int &i) { return s.x >= i; } // not modifying
+
+struct S2 {
+ S2() { x = 1; }
+ int x;
+ // Overloaded comparison operators that are able to modify their params.
+ bool operator==(const int &i) {
+ this->x++;
+ return x == i;
+ }
+ bool operator!=(int i) { return x != i; }
+ bool operator>(const int &i) { return x > i; }
+ bool operator<(int i) {
+ this->x--;
+ return x < i;
+ }
+};
+
+bool operator>=(S2 &s, const int &i) { return s.x >= i; }
+bool operator<=(S2 &s, int i) {
+ s.x++;
+ return s.x <= i;
+}
+
+int TestLogical(int X, int Y){
+#define CONFIG 0
+ if (CONFIG && X) return 1;
+#undef CONFIG
+#define CONFIG 1
+ if (CONFIG || X) return 1;
+#undef CONFIG
+
+ if (X == 10 && X != 10) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
+ if (X == 10 && (X != 10)) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
+ if (X == 10 && !(X == 10)) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
+ if (!(X != 10) && !(X == 10)) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
+
+ if (X == 10ULL && X != 10ULL) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
+ if (!(X != 10U) && !(X == 10)) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: logical expression is always false
+ if (!(X != 10LL) && !(X == 10)) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: logical expression is always false
+ if (!(X != 10ULL) && !(X == 10)) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: logical expression is always false
+
+ if (X == 0 && X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
+ if (X != 0 && !X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
+ if (X && !X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always false
+
+ if (X && !!X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: equivalent expression on both sides of logical operator
+ if (X != 0 && X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator
+ if (X != 0 && !!X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator
+ if (X == 0 && !X) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator
+
+ // Should not match.
+ if (X == 10 && Y == 10) return 1;
+ if (X != 10 && X != 12) return 1;
+ if (X == 10 || X == 12) return 1;
+ if (!X && !Y) return 1;
+ if (!X && Y) return 1;
+ if (!X && Y == 0) return 1;
+ if (X == 10 && Y != 10) return 1;
+
+ // Test for overloaded operators with constant params.
+ S s1;
+ if (s1 == 1 && s1 == 1) return true;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: equivalent expression on both sides of logical operator
+ if (s1 == 1 || s1 != 1) return true;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true
+ if (s1 > 1 && s1 < 1) return true;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
+ if (s1 >= 1 || s1 <= 1) return true;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true
+
+ // Test for overloaded operators that may modify their params.
+ S2 s2;
+ if (s2 == 1 || s2 != 1) return true;
+ if (s2 == 1 || s2 == 1) return true;
+ if (s2 > 1 && s2 < 1) return true;
+ if (s2 >= 1 || s2 <= 1) return true;
+}
+
+int TestRelational(int X, int Y) {
+ if (X == 10 && X > 10) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
+ if (X == 10 && X < 10) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
+ if (X < 10 && X > 10) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
+ if (X <= 10 && X > 10) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
+ if (X < 10 && X >= 10) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
+ if (X < 10 && X == 10) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
+
+ if (X > 5 && X <= 5) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
+ if (X > -5 && X <= -5) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
+
+ if (X < 10 || X >= 10) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always true
+ if (X <= 10 || X > 10) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true
+ if (X <= 10 || X >= 11) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true
+ if (X != 7 || X != 14) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always true
+ if (X == 7 || X != 5) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+ if (X != 7 || X == 7) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always true
+
+ if (X < 7 && X < 6) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+ if (X < 7 && X < 7) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+ if (X < 7 && X < 8) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant
+
+ if (X < 7 && X <= 5) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+ if (X < 7 && X <= 6) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: equivalent expression on both sides of logical operator
+ if (X < 7 && X <= 7) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant
+ if (X < 7 && X <= 8) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant
+
+ if (X <= 7 && X < 6) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+ if (X <= 7 && X < 7) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+ if (X <= 7 && X < 8) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator
+
+ if (X >= 7 && X > 6) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator
+ if (X >= 7 && X > 7) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+ if (X >= 7 && X > 8) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+
+ if (X <= 7 && X <= 5) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+ if (X <= 7 && X <= 6) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+ if (X <= 7 && X <= 7) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent
+ if (X <= 7 && X <= 8) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: expression is redundant
+
+ if (X == 11 && X > 10) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: expression is redundant
+ if (X == 11 && X < 12) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: expression is redundant
+ if (X > 10 && X == 11) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+ if (X < 12 && X == 11) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+
+ if (X != 11 && X == 42) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+ if (X != 11 && X > 11) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+ if (X != 11 && X < 11) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+ if (X != 11 && X < 8) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+ if (X != 11 && X > 14) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+
+ if (X < 7 || X < 6) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant
+ if (X < 7 || X < 7) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+ if (X < 7 || X < 8) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+
+ if (X > 7 || X > 6) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+ if (X > 7 || X > 7) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+ if (X > 7 || X > 8) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant
+
+ // Should not match.
+ if (X < 10 || X > 12) return 1;
+ if (X > 10 && X < 12) return 1;
+ if (X < 10 || X >= 12) return 1;
+ if (X > 10 && X <= 12) return 1;
+ if (X <= 10 || X > 12) return 1;
+ if (X >= 10 && X < 12) return 1;
+ if (X <= 10 || X >= 12) return 1;
+ if (X >= 10 && X <= 12) return 1;
+ if (X >= 10 && X <= 11) return 1;
+ if (X >= 10 && X < 11) return 1;
+ if (X > 10 && X <= 11) return 1;
+ if (X > 10 && X != 11) return 1;
+ if (X >= 10 && X <= 10) return 1;
+ if (X <= 10 && X >= 10) return 1;
+ if (X < 0 || X > 0) return 1;
+}
+
+int TestRelationalMacros(int X){
+#define SOME_MACRO 3
+#define SOME_MACRO_SAME_VALUE 3
+#define SOME_OTHER_MACRO 9
+ // Do not match for redundant relational macro expressions that can be
+ // considered intentional, and for some particular values, non redundant.
+
+ // Test cases for expressions with the same macro on both sides.
+ if (X < SOME_MACRO && X > SOME_MACRO) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: logical expression is always false
+ if (X < SOME_MACRO && X == SOME_MACRO) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: logical expression is always false
+ if (X < SOME_MACRO || X >= SOME_MACRO) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: logical expression is always true
+ if (X <= SOME_MACRO || X > SOME_MACRO) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: logical expression is always true
+ if (X != SOME_MACRO && X > SOME_MACRO) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+ if (X != SOME_MACRO && X < SOME_MACRO) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+
+ // Test cases for two different macros.
+ if (X < SOME_MACRO && X > SOME_OTHER_MACRO) return 1;
+ if (X != SOME_MACRO && X >= SOME_OTHER_MACRO) return 1;
+ if (X != SOME_MACRO && X != SOME_OTHER_MACRO) return 1;
+ if (X == SOME_MACRO || X == SOME_MACRO_SAME_VALUE) return 1;
+ if (X == SOME_MACRO || X <= SOME_MACRO_SAME_VALUE) return 1;
+ if (X == SOME_MACRO || X > SOME_MACRO_SAME_VALUE) return 1;
+ if (X < SOME_MACRO && X <= SOME_OTHER_MACRO) return 1;
+ if (X == SOME_MACRO && X > SOME_OTHER_MACRO) return 1;
+ if (X == SOME_MACRO && X != SOME_OTHER_MACRO) return 1;
+ if (X == SOME_MACRO && X != SOME_MACRO_SAME_VALUE) return 1;
+ if (X == SOME_MACRO_SAME_VALUE && X == SOME_MACRO ) return 1;
+
+ // Test cases for a macro and a const.
+ if (X < SOME_MACRO && X > 9) return 1;
+ if (X != SOME_MACRO && X >= 9) return 1;
+ if (X != SOME_MACRO && X != 9) return 1;
+ if (X == SOME_MACRO || X == 3) return 1;
+ if (X == SOME_MACRO || X <= 3) return 1;
+ if (X < SOME_MACRO && X <= 9) return 1;
+ if (X == SOME_MACRO && X != 9) return 1;
+ if (X == SOME_MACRO && X == 9) return 1;
+
+#undef SOME_OTHER_MACRO
+#undef SOME_MACRO_SAME_VALUE
+#undef SOME_MACRO
+ return 0;
+}
+
+int TestValidExpression(int X) {
+ if (X - 1 == 1 - X) return 1;
+ if (2 * X == X) return 1;
+ if ((X << 1) == X) return 1;
+
+ return 0;
+}
+
+enum Color { Red, Yellow, Green };
+int TestRelationalWithEnum(enum Color C) {
+ if (C == Red && C == Yellow) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: logical expression is always false
+ if (C == Red && C != Red) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: logical expression is always false
+ if (C != Red || C != Yellow) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: logical expression is always true
+
+ // Should not match.
+ if (C == Red || C == Yellow) return 1;
+ if (C != Red && C != Yellow) return 1;
+
+ return 0;
+}
+
+template<class T>
+int TestRelationalTemplated(int X) {
+ // This test causes a corner case with |isIntegerConstantExpr| where the type
+ // is dependent. There is an assert failing when evaluating
+ // sizeof(<incomplet-type>).
+ if (sizeof(T) == 4 || sizeof(T) == 8) return 1;
+
+ if (X + 0 == -X) return 1;
+ if (X + 0 < X) return 1;
+
+ return 0;
+}
+
+int TestWithSignedUnsigned(int X) {
+ if (X + 1 == X + 1ULL) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+
+ if ((X & 0xFFU) == 0xF00) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: logical expression is always false
+
+ if ((X & 0xFF) == 0xF00U) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
+
+ if ((X & 0xFFU) == 0xF00U) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: logical expression is always false
+
+ return 0;
+}
+
+int TestWithLong(int X, I64 Y) {
+ if (X + 0ULL == -X) return 1;
+ if (Y + 0 == -Y) return 1;
+ if (Y <= 10 && X >= 10LL) return 1;
+ if (Y <= 10 && X >= 10ULL) return 1;
+ if (X <= 10 || X > 12LL) return 1;
+ if (X <= 10 || X > 12ULL) return 1;
+ if (Y <= 10 || Y > 12) return 1;
+
+ return 0;
+}
+
+int TestWithMinMaxInt(int X) {
+ if (X <= X + 0xFFFFFFFFU) return 1;
+ if (X <= X + 0x7FFFFFFF) return 1;
+ if (X <= X + 0x80000000) return 1;
+
+ if (X <= 0xFFFFFFFFU && X > 0) return 1;
+ if (X <= 0xFFFFFFFFU && X > 0U) return 1;
+
+ if (X + 0x80000000 == X - 0x80000000) return 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: logical expression is always true
+
+ if (X > 0x7FFFFFFF || X < ((-0x7FFFFFFF)-1)) return 1;
+ if (X <= 0x7FFFFFFF && X >= ((-0x7FFFFFFF)-1)) return 1;
+
+ return 0;
+}
+
+#define FLAG1 1
+#define FLAG2 2
+#define FLAG3 4
+#define FLAGS (FLAG1 | FLAG2 | FLAG3)
+#define NOTFLAGS !(FLAG1 | FLAG2 | FLAG3)
+int operatorConfusion(int X, int Y, long Z)
+{
+ // Ineffective & expressions.
+ Y = (Y << 8) & 0xff;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and operation
+ Y = (Y << 12) & 0xfff;
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and
+ Y = (Y << 12) & 0xff;
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and
+ Y = (Y << 8) & 0x77;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and
+ Y = (Y << 5) & 0x11;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and
+
+ // Tests for unmatched types
+ Z = (Z << 8) & 0xff;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and operation
+ Y = (Y << 12) & 0xfffL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and
+ Z = (Y << 12) & 0xffLL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and
+ Y = (Z << 8L) & 0x77L;
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and
+
+ Y = (Y << 8) & 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and
+
+ Y = (Y << 8) & -1;
+
+ // Effective expressions. Do not check.
+ Y = (Y << 4) & 0x15;
+ Y = (Y << 3) & 0x250;
+ Y = (Y << 9) & 0xF33;
+
+ int K = !(1 | 2 | 4);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: ineffective logical negation operator used; did you mean '~'?
+ // CHECK-FIXES: {{^}} int K = ~(1 | 2 | 4);{{$}}
+ K = !(FLAG1 & FLAG2 & FLAG3);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: ineffective logical negation operator
+ // CHECK-FIXES: {{^}} K = ~(FLAG1 & FLAG2 & FLAG3);{{$}}
+ K = !(3 | 4);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: ineffective logical negation operator
+ // CHECK-FIXES: {{^}} K = ~(3 | 4);{{$}}
+ int NotFlags = !FLAGS;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: ineffective logical negation operator
+ // CHECK-FIXES: {{^}} int NotFlags = ~FLAGS;{{$}}
+ NotFlags = NOTFLAGS;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: ineffective logical negation operator
+ return !(1 | 2 | 4);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: ineffective logical negation operator
+ // CHECK-FIXES: {{^}} return ~(1 | 2 | 4);{{$}}
+}
+#undef FLAG1
+#undef FLAG2
+#undef FLAG3
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-static-assert.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-static-assert.c
new file mode 100644
index 0000000..e3e8304
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-static-assert.c
@@ -0,0 +1,27 @@
+// RUN: %check_clang_tidy %s misc-static-assert %t -- -- -std=c11
+// RUN: clang-tidy %s -checks=-*,misc-static-assert -- -std=c99 | count 0
+
+void abort() {}
+#ifdef NDEBUG
+#define assert(x) 1
+#else
+#define assert(x) \
+ if (!(x)) \
+ abort()
+#endif
+
+void f(void) {
+ int x = 1;
+ assert(x == 0);
+ // CHECK-FIXES: {{^ }}assert(x == 0);
+
+ #define static_assert(x, msg) _Static_assert(x, msg)
+ assert(11 == 5 + 6);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+ // CHECK-FIXES: {{^ }}static_assert(11 == 5 + 6, "");
+ #undef static_assert
+
+ assert(10 == 5 + 5);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+ // CHECK-FIXES: {{^ }}static_assert(10 == 5 + 5, "");
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-static-assert.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-static-assert.cpp
new file mode 100644
index 0000000..85ae053
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-static-assert.cpp
@@ -0,0 +1,143 @@
+// RUN: %check_clang_tidy %s misc-static-assert %t
+
+void abort() {}
+#ifdef NDEBUG
+#define assert(x) 1
+#else
+#define assert(x) \
+ if (!(x)) \
+ abort()
+#endif
+
+void print(...);
+
+#define ZERO_MACRO 0
+
+#define False false
+#define FALSE 0
+
+#define my_macro() assert(0 == 1)
+// CHECK-FIXES: #define my_macro() assert(0 == 1)
+
+constexpr bool myfunc(int a, int b) { return a * b == 0; }
+
+typedef __SIZE_TYPE__ size_t;
+extern "C" size_t strlen(const char *s);
+
+class A {
+public:
+ bool method() { return true; }
+};
+
+class B {
+public:
+ constexpr bool method() { return true; }
+};
+
+template <class T> void doSomething(T t) {
+ assert(myfunc(1, 2));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be replaced by static_assert() [misc-static-assert]
+ // CHECK-FIXES: {{^ }}static_assert(myfunc(1, 2), "");
+
+ assert(t.method());
+ // CHECK-FIXES: {{^ }}assert(t.method());
+
+ assert(sizeof(T) == 123);
+}
+
+int main() {
+ my_macro();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+ // CHECK-FIXES: {{^ }}my_macro();
+
+ assert(myfunc(1, 2) && (3 == 4));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+ // CHECK-FIXES: {{^ }}static_assert(myfunc(1, 2) && (3 == 4), "");
+
+ int x = 1;
+ assert(x == 0);
+ // CHECK-FIXES: {{^ }}assert(x == 0);
+
+ A a;
+ B b;
+
+ doSomething<A>(a);
+ doSomething<B>(b);
+
+ assert(false);
+ // CHECK-FIXES: {{^ }}assert(false);
+
+ assert(False);
+ // CHECK-FIXES: {{^ }}assert(False);
+ assert(FALSE);
+ // CHECK-FIXES: {{^ }}assert(FALSE);
+
+ assert(ZERO_MACRO);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+ // CHECK-FIXES: {{^ }}static_assert(ZERO_MACRO, "");
+
+ assert(!"Don't report me!");
+ // CHECK-FIXES: {{^ }}assert(!"Don't report me!");
+
+ assert(0 && "Don't report me!");
+ // CHECK-FIXES: {{^ }}assert(0 && "Don't report me!");
+
+ assert(false && "Don't report me!");
+ // CHECK-FIXES: {{^ }}assert(false && "Don't report me!");
+
+#define NULL ((void*)0)
+ assert(NULL && "Don't report me!");
+ // CHECK-FIXES: {{^ }}assert(NULL && "Don't report me!");
+
+ assert(NULL == "Don't report me!");
+ // CHECK-FIXES: {{^ }}assert(NULL == "Don't report me!");
+
+ assert("Don't report me!" == NULL);
+ // CHECK-FIXES: {{^ }}assert("Don't report me!" == NULL);
+
+ assert(0 == "Don't report me!");
+ // CHECK-FIXES: {{^ }}assert(0 == "Don't report me!");
+
+#define NULL ((unsigned int)0)
+ assert(NULL && "Report me!");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+ // CHECK-FIXES: {{^ }}static_assert(NULL , "Report me!");
+
+#define NULL __null
+ assert(__null == "Don't report me!");
+ // CHECK-FIXES: {{^ }}assert(__null == "Don't report me!");
+ assert(NULL == "Don't report me!");
+ // CHECK-FIXES: {{^ }}assert(NULL == "Don't report me!");
+#undef NULL
+
+ assert(ZERO_MACRO && "Report me!");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+ // CHECK-FIXES: {{^ }}static_assert(ZERO_MACRO , "Report me!");
+
+ assert(0);
+
+#define false false
+ assert(false);
+
+#define false 0
+ assert(false);
+#undef false
+
+ assert(10==5 && "Report me!");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+ // CHECK-FIXES: {{^ }}static_assert(10==5 , "Report me!");
+
+ assert(strlen("12345") == 5);
+ // CHECK-FIXES: {{^ }}assert(strlen("12345") == 5);
+
+#define assert(e) (__builtin_expect(!(e), 0) ? print (#e, __FILE__, __LINE__) : (void)0)
+ assert(false);
+ // CHECK-FIXES: {{^ }}assert(false);
+
+ assert(10 == 5 + 5);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+ // CHECK-FIXES: {{^ }}static_assert(10 == 5 + 5, "");
+#undef assert
+
+ return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-throw-by-value-catch-by-reference.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-throw-by-value-catch-by-reference.cpp
new file mode 100644
index 0000000..120b07e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-throw-by-value-catch-by-reference.cpp
@@ -0,0 +1,156 @@
+// RUN: %check_clang_tidy %s misc-throw-by-value-catch-by-reference %t -- -- -std=c++11 -fcxx-exceptions
+
+
+class logic_error {
+public:
+ logic_error(const char *message) {}
+};
+
+typedef logic_error *logic_ptr;
+typedef logic_ptr logic_double_typedef;
+
+int lastException;
+
+template <class T> struct remove_reference { typedef T type; };
+template <class T> struct remove_reference<T &> { typedef T type; };
+template <class T> struct remove_reference<T &&> { typedef T type; };
+
+template <typename T> typename remove_reference<T>::type &&move(T &&arg) {
+ return static_cast<typename remove_reference<T>::type &&>(arg);
+}
+
+logic_error CreateException() { return logic_error("created"); }
+
+void testThrowFunc() {
+ throw new logic_error("by pointer");
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression throws a pointer; it should throw a non-pointer value instead [misc-throw-by-value-catch-by-reference]
+ logic_ptr tmp = new logic_error("by pointer");
+ throw tmp;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]
+ // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: throw expression throws a pointer; it should throw a non-pointer value instead [misc-throw-by-value-catch-by-reference]
+ throw logic_error("by value");
+ auto *literal = "test";
+ throw logic_error(literal);
+ throw "test string literal";
+ throw L"throw wide string literal";
+ const char *characters = 0;
+ throw characters;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]
+ // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: throw expression throws a pointer; it should throw a non-pointer value instead [misc-throw-by-value-catch-by-reference]
+ logic_error lvalue("lvalue");
+ throw lvalue;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]
+
+ throw move(lvalue);
+ int &ex = lastException;
+ throw ex;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]
+ throw CreateException();
+}
+
+void throwReferenceFunc(logic_error &ref) { throw ref; }
+
+void catchByPointer() {
+ try {
+ testThrowFunc();
+ } catch (logic_error *e) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: catch handler catches a pointer value; should throw a non-pointer value and catch by reference instead [misc-throw-by-value-catch-by-reference]
+ }
+}
+
+void catchByValue() {
+ try {
+ testThrowFunc();
+ } catch (logic_error e) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: catch handler catches by value; should catch by reference instead [misc-throw-by-value-catch-by-reference]
+ }
+}
+
+void catchByReference() {
+ try {
+ testThrowFunc();
+ } catch (logic_error &e) {
+ }
+}
+
+void catchByConstReference() {
+ try {
+ testThrowFunc();
+ } catch (const logic_error &e) {
+ }
+}
+
+void catchTypedef() {
+ try {
+ testThrowFunc();
+ } catch (logic_ptr) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: catch handler catches a pointer value; should throw a non-pointer value and catch by reference instead [misc-throw-by-value-catch-by-reference]
+ }
+}
+
+void catchAll() {
+ try {
+ testThrowFunc();
+ } catch (...) {
+ }
+}
+
+void catchLiteral() {
+ try {
+ testThrowFunc();
+ } catch (const char *) {
+ } catch (const wchar_t *) {
+ // disabled for now until it is clear
+ // how to enable them in the test
+ //} catch (const char16_t*) {
+ //} catch (const char32_t*) {
+ }
+}
+
+// catching fundamentals should not warn
+void catchFundamental() {
+ try {
+ testThrowFunc();
+ } catch (int) {
+ } catch (double) {
+ } catch (unsigned long) {
+ }
+}
+
+struct TrivialType {
+ double x;
+ double y;
+};
+
+void catchTrivial() {
+ try {
+ testThrowFunc();
+ } catch (TrivialType) {
+ }
+}
+
+typedef logic_error &fine;
+void additionalTests() {
+ try {
+ } catch (int i) { // ok
+ throw i; // ok
+ } catch (fine e) { // ok
+ throw e; // ok
+ } catch (logic_error *e) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: catch handler catches a pointer value; should throw a non-pointer value and catch by reference instead [misc-throw-by-value-catch-by-reference]
+ throw e; // ok, despite throwing a pointer
+ } catch (...) { // ok
+ throw; // ok
+ }
+}
+
+struct S {};
+
+S &returnByReference();
+S returnByValue();
+
+void f() {
+ throw returnByReference(); // Should diagnose
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]
+ throw returnByValue(); // Should not diagnose
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unconventional-assign-operator-cxx17.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unconventional-assign-operator-cxx17.cpp
new file mode 100644
index 0000000..ba1a685
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unconventional-assign-operator-cxx17.cpp
@@ -0,0 +1,12 @@
+// RUN: %check_clang_tidy %s misc-unconventional-assign-operator %t -- -- -std=c++17 -fno-delayed-template-parsing
+
+struct BadModifier {
+ BadModifier& operator=(const BadModifier&) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should not be marked 'const'
+};
+
+struct PR35468 {
+ template<typename T> auto &operator=(const T &) {
+ return *this;
+ }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unconventional-assign-operator.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unconventional-assign-operator.cpp
new file mode 100644
index 0000000..4bd9cb2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unconventional-assign-operator.cpp
@@ -0,0 +1,111 @@
+// RUN: %check_clang_tidy %s misc-unconventional-assign-operator %t -- -- -std=c++11 -isystem %S/Inputs/Headers -fno-delayed-template-parsing
+
+namespace std {
+template <typename T>
+struct remove_reference { typedef T type; };
+template <typename T>
+struct remove_reference<T &> { typedef T type; };
+template <typename T>
+struct remove_reference<T &&> { typedef T type; };
+template <typename T>
+typename remove_reference<T>::type &&move(T &&t);
+}
+
+
+struct Good {
+ Good& operator=(const Good&);
+ Good& operator=(Good&&);
+
+ // Assign from other types is fine too.
+ Good& operator=(int);
+};
+
+struct AlsoGood {
+ // By value is also fine.
+ AlsoGood& operator=(AlsoGood);
+};
+
+struct BadReturnType {
+ void operator=(const BadReturnType&);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'BadReturnType&' [misc-unconventional-assign-operator]
+ const BadReturnType& operator=(BadReturnType&&);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'Bad
+ void operator=(int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'Bad
+};
+
+struct BadReturnType2 {
+ BadReturnType2&& operator=(const BadReturnType2&);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'Bad
+ int operator=(BadReturnType2&&);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'Bad
+};
+
+struct BadArgument {
+ BadArgument& operator=(BadArgument&);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should take 'BadArgument const&', 'BadArgument&&' or 'BadArgument'
+ BadArgument& operator=(const BadArgument&&);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should take 'BadAr
+};
+
+struct BadModifier {
+ BadModifier& operator=(const BadModifier&) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should not be marked 'const'
+};
+
+struct Deleted {
+ // We don't check the return value of deleted operators.
+ void operator=(const Deleted&) = delete;
+ void operator=(Deleted&&) = delete;
+};
+
+class Private {
+ // We don't check the return value of private operators.
+ // Pre-C++11 way of disabling assignment.
+ void operator=(const Private &);
+};
+
+struct Virtual {
+ virtual Virtual& operator=(const Virtual &);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should not be marked 'virtual'
+};
+
+class BadReturnStatement {
+ int n;
+
+public:
+ BadReturnStatement& operator=(BadReturnStatement&& rhs) {
+ n = std::move(rhs.n);
+ return rhs;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: operator=() should always return '*this'
+ }
+
+ // Do not check if return type is different from '&BadReturnStatement'
+ int operator=(int i) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'Bad
+ n = i;
+ return n;
+ }
+};
+
+namespace pr31531 {
+enum E { e };
+// This declaration makes the 'return *this' below have an unresolved operator
+// in the class template, but not in an instantiation.
+E operator*(E, E);
+
+template <typename>
+struct UnresolvedOperator {
+ UnresolvedOperator &operator=(const UnresolvedOperator &) { return *this; }
+};
+
+UnresolvedOperator<int> UnresolvedOperatorInt;
+
+template <typename>
+struct Template {
+ Template &operator=(const Template &) { return this; }
+ // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: operator=() should always return '*this'
+};
+
+Template<int> TemplateInt;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-uniqueptr-reset-release.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-uniqueptr-reset-release.cpp
new file mode 100644
index 0000000..1bd6e6f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-uniqueptr-reset-release.cpp
@@ -0,0 +1,69 @@
+// RUN: %check_clang_tidy %s misc-uniqueptr-reset-release %t
+
+namespace std {
+
+template <typename T>
+struct default_delete {};
+
+template <typename T, class Deleter = std::default_delete<T>>
+struct unique_ptr {
+ unique_ptr();
+ explicit unique_ptr(T *);
+ template <typename U, typename E>
+ unique_ptr(unique_ptr<U, E> &&);
+ void reset(T *);
+ T *release();
+};
+} // namespace std
+
+struct Foo {};
+struct Bar : Foo {};
+
+std::unique_ptr<Foo> Create();
+std::unique_ptr<Foo> &Look();
+std::unique_ptr<Foo> *Get();
+
+using FooFunc = void (*)(Foo *);
+using BarFunc = void (*)(Bar *);
+
+void f() {
+ std::unique_ptr<Foo> a, b;
+ std::unique_ptr<Bar> c;
+ std::unique_ptr<Foo> *x = &a;
+ std::unique_ptr<Foo> *y = &b;
+
+ a.reset(b.release());
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: prefer ptr1 = std::move(ptr2) over ptr1.reset(ptr2.release()) [misc-uniqueptr-reset-release]
+ // CHECK-FIXES: a = std::move(b);
+ a.reset(c.release());
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: prefer ptr1 = std::move(ptr2)
+ // CHECK-FIXES: a = std::move(c);
+ a.reset(Create().release());
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: prefer ptr = ReturnUnique() over ptr.reset(ReturnUnique().release()) [misc-uniqueptr-reset-release]
+ // CHECK-FIXES: a = Create();
+ x->reset(y->release());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: prefer ptr1 = std::move(ptr2)
+ // CHECK-FIXES: *x = std::move(*y);
+ Look().reset(Look().release());
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: prefer ptr1 = std::move(ptr2)
+ // CHECK-FIXES: Look() = std::move(Look());
+ Get()->reset(Get()->release());
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: prefer ptr1 = std::move(ptr2)
+ // CHECK-FIXES: *Get() = std::move(*Get());
+
+ std::unique_ptr<Bar, FooFunc> func_a, func_b;
+ func_a.reset(func_b.release());
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: prefer ptr1 = std::move(ptr2)
+ // CHECK-FIXES: func_a = std::move(func_b);
+}
+
+void negatives() {
+ std::unique_ptr<Foo> src;
+ struct OtherDeleter {};
+ std::unique_ptr<Foo, OtherDeleter> dest;
+ dest.reset(src.release());
+
+ std::unique_ptr<Bar, FooFunc> func_a;
+ std::unique_ptr<Bar, BarFunc> func_b;
+ func_a.reset(func_b.release());
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-alias-decls.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-alias-decls.cpp
new file mode 100644
index 0000000..6d63df4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-alias-decls.cpp
@@ -0,0 +1,12 @@
+// RUN: %check_clang_tidy %s misc-unused-alias-decls %t
+
+namespace my_namespace {
+class C {};
+}
+
+namespace unused_alias = ::my_namespace; // eol-comments aren't removed (yet)
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: namespace alias decl 'unused_alias' is unused
+// CHECK-FIXES: {{^}}// eol-comments aren't removed (yet)
+
+namespace used_alias = ::my_namespace;
+void f() { used_alias::C c; }
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-parameters-strict.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-parameters-strict.cpp
new file mode 100644
index 0000000..a334b45
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-parameters-strict.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s misc-unused-parameters %t -- \
+// RUN: -config="{CheckOptions: [{key: StrictMode, value: 1}]}" --
+
+// Warn on empty function bodies in StrictMode.
+namespace strict_mode {
+void f(int foo) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'foo' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void f(int /*foo*/) {}{{$}}
+class E {
+ int i;
+
+public:
+ E(int j) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'j' is unused
+// CHECK-FIXES: {{^}} E(int /*j*/) {}{{$}}
+};
+class F {
+ int i;
+
+public:
+ F(int j) : i() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'j' is unused
+// CHECK-FIXES: {{^}} F(int /*j*/) : i() {}{{$}}
+};
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-parameters.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-parameters.c
new file mode 100644
index 0000000..d824a80
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-parameters.c
@@ -0,0 +1,17 @@
+// RUN: %check_clang_tidy %s misc-unused-parameters %t -- -- -xc
+
+// Basic removal
+// =============
+void a(int i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void a(int /*i*/) {;}{{$}}
+
+static void b(); // In C, forward declarations can leave out parameters.
+static void b(int i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: parameter 'i' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}static void b() {;}{{$}}
+
+// Unchanged cases
+// ===============
+void h(i, c, d) int i; char *c, *d; {} // Don't mess with K&R style
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-parameters.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-parameters.cpp
new file mode 100644
index 0000000..ec1ee2d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-parameters.cpp
@@ -0,0 +1,277 @@
+// RUN: echo "static void staticFunctionHeader(int i) {;}" > %T/header.h
+// RUN: echo "static void staticFunctionHeader(int /*i*/) {;}" > %T/header-fixed.h
+// RUN: %check_clang_tidy %s misc-unused-parameters %t -- -header-filter='.*' -- -std=c++11 -fno-delayed-template-parsing
+// RUN: diff %T/header.h %T/header-fixed.h
+
+#include "header.h"
+// CHECK-MESSAGES: header.h:1:38: warning
+
+// Basic removal
+// =============
+void a(int i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void a(int /*i*/) {;}{{$}}
+
+void b(int i = 1) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void b(int /*i*/ = 1) {;}{{$}}
+
+void c(int *i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: parameter 'i' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void c(int * /*i*/) {;}{{$}}
+
+void d(int i[]) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void d(int /*i*/[]) {;}{{$}}
+
+void e(int i[1]) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void e(int /*i*/[1]) {;}{{$}}
+
+void f(void (*fn)()) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: parameter 'fn' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void f(void (* /*fn*/)()) {;}{{$}}
+
+// Unchanged cases
+// ===============
+void f(int i); // Don't remove stuff in declarations
+void g(int i = 1);
+void h(int i[]);
+void s(int i[1]);
+void u(void (*fn)());
+void w(int i) { (void)i; } // Don't remove used parameters
+
+bool useLambda(int (*fn)(int));
+static bool static_var = useLambda([] (int a) { return a; });
+
+// Remove parameters of local functions
+// ====================================
+static void staticFunctionA(int i);
+// CHECK-FIXES: {{^}}static void staticFunctionA();
+static void staticFunctionA(int i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning
+// CHECK-FIXES: {{^}}static void staticFunctionA()
+
+static void staticFunctionB(int i, int j) { (void)i; }
+// CHECK-MESSAGES: :[[@LINE-1]]:40: warning
+// CHECK-FIXES: {{^}}static void staticFunctionB(int i)
+
+static void staticFunctionC(int i, int j) { (void)j; }
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning
+// CHECK-FIXES: {{^}}static void staticFunctionC(int j)
+
+static void staticFunctionD(int i, int j, int k) { (void)i; (void)k; }
+// CHECK-MESSAGES: :[[@LINE-1]]:40: warning
+// CHECK-FIXES: {{^}}static void staticFunctionD(int i, int k)
+
+static void staticFunctionE(int i = 4) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning
+// CHECK-FIXES: {{^}}static void staticFunctionE()
+
+static void staticFunctionF(int i = 4);
+// CHECK-FIXES: {{^}}static void staticFunctionF();
+static void staticFunctionF(int i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning
+// CHECK-FIXES: {{^}}static void staticFunctionF()
+
+static void staticFunctionG(int i[]);
+// CHECK-FIXES: {{^}}static void staticFunctionG();
+static void staticFunctionG(int i[]) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning
+// CHECK-FIXES: {{^}}static void staticFunctionG()
+
+static void staticFunctionH(void (*fn)());
+// CHECK-FIXES: {{^}}static void staticFunctionH();
+static void staticFunctionH(void (*fn)()) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:36: warning
+// CHECK-FIXES: {{^}}static void staticFunctionH()
+
+static void someCallSites() {
+ staticFunctionA(1);
+// CHECK-FIXES: staticFunctionA();
+ staticFunctionB(1, 2);
+// CHECK-FIXES: staticFunctionB(1);
+ staticFunctionC(1, 2);
+// CHECK-FIXES: staticFunctionC(2);
+ staticFunctionD(1, 2, 3);
+// CHECK-FIXES: staticFunctionD(1, 3);
+ staticFunctionE(1);
+// CHECK-FIXES: staticFunctionE();
+ staticFunctionF(1);
+// CHECK-FIXES: staticFunctionF();
+ staticFunctionF();
+// CHECK-FIXES: staticFunctionF();
+ int t[] = {1};
+ staticFunctionG(t);
+// CHECK-FIXES: staticFunctionG();
+ void func();
+ staticFunctionH(&func);
+// CHECK-FIXES: staticFunctionH();
+}
+
+/*
+ * FIXME: This fails because the removals overlap and ClangTidy doesn't apply
+ * them.
+ * static void bothVarsUnused(int a, int b) {;}
+ */
+
+// Regression test for long variable names and expressions
+// =======================================================
+static int variableWithLongName1(int LongName1, int LongName2) {
+// CHECK-MESSAGES: :[[@LINE-1]]:53: warning: parameter 'LongName2' is unused
+// CHECK-FIXES: {{^}}static int variableWithLongName1(int LongName1) {
+ return LongName1;
+}
+static int variableWithLongName2(int LongName1, int LongName2) {
+// CHECK-MESSAGES: :[[@LINE-1]]:38: warning: parameter 'LongName1' is unused
+// CHECK-FIXES: {{^}}static int variableWithLongName2(int LongName2) {
+ return LongName2;
+}
+static void someLongNameCallSites() {
+ int LongName1 = 7, LongName2 = 17;
+ variableWithLongName1(LongName1, LongName2);
+// CHECK-FIXES: variableWithLongName1(LongName1);
+ variableWithLongName2(LongName1, LongName2);
+// CHECK-FIXES: variableWithLongName2(LongName2);
+}
+
+class SomeClass {
+ static void f(int i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning
+// CHECK-FIXES: static void f(int /*i*/) {;}
+ static void g(int i = 1) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning
+// CHECK-FIXES: static void g(int /*i*/ = 1) {;}
+ static void h(int i[]) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning
+// CHECK-FIXES: static void h(int /*i*/[]) {;}
+ static void s(void (*fn)()) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning
+// CHECK-FIXES: static void s(void (* /*fn*/)()) {;}
+};
+
+namespace {
+class C {
+public:
+ void f(int i);
+// CHECK-FIXES: void f();
+ void g(int i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning
+// CHECK-FIXES: void g() {;}
+ void h(int i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning
+// CHECK-FIXES: void h(int /*i*/) {;}
+ void s(int i = 1) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning
+// CHECK-FIXES: void s(int /*i*/ = 1) {;}
+ void u(int i[]) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning
+// CHECK-FIXES: void u(int /*i*/[]) {;}
+ void w(void (*fn)()) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning
+// CHECK-FIXES: void w(void (* /*fn*/)()) {;}
+};
+
+void C::f(int i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning
+// CHECK-FIXES: void C::f() {;}
+
+template <typename T>
+void useFunction(T t);
+
+void someMoreCallSites() {
+ C c;
+ c.f(1);
+// CHECK-FIXES: c.f();
+ c.g(1);
+// CHECK-FIXES: c.g();
+
+ useFunction(&C::h);
+ useFunction(&C::s);
+ useFunction(&C::u);
+ useFunction(&C::w);
+}
+
+class Base {
+ virtual void f(int i);
+};
+
+class Derived : public Base {
+ void f(int i) override {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning
+// CHECK-FIXES: void f(int /*i*/) override {;}
+};
+
+} // end namespace
+
+template <typename T> void someFunctionTemplate(T b, T e) { (void)b; (void)e; }
+
+template <typename T> void someFunctionTemplateOneUnusedParam(T b, T e) { (void)e; }
+// CHECK-MESSAGES: :[[@LINE-1]]:65: warning
+// CHECK-FIXES: {{^}}template <typename T> void someFunctionTemplateOneUnusedParam(T /*b*/, T e) { (void)e; }
+
+template <typename T> void someFunctionTemplateAllUnusedParams(T b, T e) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:66: warning
+// CHECK-MESSAGES: :[[@LINE-2]]:71: warning
+// CHECK-FIXES: {{^}}template <typename T> void someFunctionTemplateAllUnusedParams(T /*b*/, T /*e*/) {;}
+
+static void dontGetConfusedByParametersInFunctionTypes() { void (*F)(int i); }
+
+template <typename T> class Function {};
+static Function<void(int, int i)> dontGetConfusedByFunctionReturnTypes() {
+ return Function<void(int, int)>();
+}
+
+namespace PR38055 {
+namespace {
+struct a {
+ void b(int c) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: parameter 'c' is unused
+// CHECK-FIXES: {{^}} void b() {;}{{$}}
+};
+template <class>
+class d {
+ a e;
+ void f() { e.b(); }
+};
+} // namespace
+} // namespace PR38055
+
+namespace strict_mode_off {
+// Do not warn on empty function bodies.
+void f1(int foo1) {}
+void f2(int foo2) {
+ // "empty" in the AST sense, not in textual sense.
+}
+void f3(int foo3) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: parameter 'foo3' is unused
+// CHECK-FIXES: {{^}}void f3(int /*foo3*/) {;}{{$}}
+
+class E {
+ int i;
+
+public:
+ E(int j) {}
+};
+class F {
+ int i;
+
+public:
+ // Constructor initializer counts as a non-empty body.
+ F(int j) : i() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'j' is unused
+// CHECK-FIXES: {{^}} F(int /*j*/) : i() {}{{$}}
+};
+
+class A {
+public:
+ A();
+ A(int);
+};
+class B : public A {
+public:
+ B(int i) : A() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'i' is unused
+// CHECK-FIXES: {{^}} B(int /*i*/) : A() {}{{$}}
+};
+} // namespace strict_mode_off
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-using-decls-errors.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-using-decls-errors.cpp
new file mode 100644
index 0000000..1c26a69
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-using-decls-errors.cpp
@@ -0,0 +1,12 @@
+// RUN: %check_clang_tidy -expect-clang-tidy-error %s misc-unused-using-decls %t
+
+namespace n {
+class C;
+}
+
+using n::C;
+
+void f() {
+ for (C *p : unknown()) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: error: use of undeclared identifier 'unknown' [clang-diagnostic-error]
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-using-decls.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-using-decls.cpp
new file mode 100644
index 0000000..65ef0da
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-using-decls.cpp
@@ -0,0 +1,203 @@
+// RUN: %check_clang_tidy %s misc-unused-using-decls %t -- -- -fno-delayed-template-parsing -isystem %S/Inputs/
+
+
+// ----- Definitions -----
+template <typename T> class vector {};
+namespace n {
+class A;
+class B;
+class C;
+class D;
+class D { public: static int i; };
+template <typename T> class E {};
+template <typename T> class F {};
+class G { public: static void func() {} };
+class H { public: static int i; };
+class I {
+ public:
+ static int ii;
+};
+template <typename T> class J {};
+class G;
+class H;
+
+template <typename T> class K {};
+template <template <typename> class S>
+class L {};
+
+template <typename T> class M {};
+class N {};
+
+template <int T> class P {};
+const int Constant = 0;
+
+class Base {
+ public:
+ void f();
+};
+
+D UsedInstance;
+D UnusedInstance;
+
+int UsedFunc() { return 1; }
+int UnusedFunc() { return 1; }
+template <typename T> int UsedTemplateFunc() { return 1; }
+template <typename T> int UnusedTemplateFunc() { return 1; }
+template <typename T> int UsedInTemplateFunc() { return 1; }
+void OverloadFunc(int);
+void OverloadFunc(double);
+int FuncUsedByUsingDeclInMacro() { return 1; }
+
+class ostream {
+public:
+ ostream &operator<<(ostream &(*PF)(ostream &));
+};
+extern ostream cout;
+ostream &endl(ostream &os);
+
+enum Color1 { Green };
+
+enum Color2 { Red };
+
+enum Color3 { Yellow };
+
+enum Color4 { Blue };
+
+} // namespace n
+
+#include "unused-using-decls.h"
+namespace ns {
+template <typename T>
+class AA {
+ T t;
+};
+template <typename T>
+T ff() { T t; return t; }
+} // namespace ns
+
+// ----- Using declarations -----
+// eol-comments aren't removed (yet)
+using n::A; // A
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'A' is unused
+// CHECK-FIXES: {{^}}// A
+using n::B;
+using n::C;
+using n::D;
+using n::E; // E
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'E' is unused
+// CHECK-FIXES: {{^}}// E
+using n::F;
+using n::G;
+using n::H;
+using n::I;
+int I::ii = 1;
+class Derived : public n::Base {
+ public:
+ using Base::f;
+};
+using n::UsedInstance;
+using n::UsedFunc;
+using n::UsedTemplateFunc;
+using n::UnusedInstance; // UnusedInstance
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'UnusedInstance' is unused
+// CHECK-FIXES: {{^}}// UnusedInstance
+using n::UnusedFunc; // UnusedFunc
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'UnusedFunc' is unused
+// CHECK-FIXES: {{^}}// UnusedFunc
+using n::cout;
+using n::endl;
+
+using n::UsedInTemplateFunc;
+using n::J;
+template <typename T> void Callee() {
+ J<T> j;
+ UsedInTemplateFunc<T>();
+}
+
+using n::OverloadFunc; // OverloadFunc
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'OverloadFunc' is unused
+// CHECK-FIXES: {{^}}// OverloadFunc
+
+#define DEFINE_INT(name) \
+ namespace INT { \
+ static const int _##name = 1; \
+ } \
+ using INT::_##name
+DEFINE_INT(test);
+#undef DEFIND_INT
+
+#define USING_FUNC \
+ using n::FuncUsedByUsingDeclInMacro;
+USING_FUNC
+#undef USING_FUNC
+
+namespace N1 {
+// n::G is used in namespace N2.
+// Currently, the check doesn't support multiple scopes. All the relevant
+// using-decls will be marked as used once we see an usage even the usage is in
+// other scope.
+using n::G;
+}
+
+namespace N2 {
+using n::G;
+void f(G g);
+}
+
+void IgnoreFunctionScope() {
+// Using-decls defined in function scope will be ignored.
+using n::H;
+}
+
+using n::Color1;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'Color1' is unused
+using n::Green;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'Green' is unused
+using n::Color2;
+using n::Color3;
+using n::Blue;
+
+using ns::AA;
+using ns::ff;
+
+using n::K;
+
+using n::N;
+
+// FIXME: Currently non-type template arguments are not supported.
+using n::Constant;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'Constant' is unused
+
+// ----- Usages -----
+void f(B b);
+void g() {
+ vector<C> data;
+ D::i = 1;
+ F<int> f;
+ void (*func)() = &G::func;
+ int *i = &H::i;
+ UsedInstance.i;
+ UsedFunc();
+ UsedTemplateFunc<int>();
+ cout << endl;
+ Color2 color2;
+ int t1 = Color3::Yellow;
+ int t2 = Blue;
+
+ MyClass a;
+ int t3 = 0;
+ a.func1<AA>(&t3);
+ a.func2<int, ff>(t3);
+
+ n::L<K> l;
+}
+
+template<class T>
+void h(n::M<T>* t) {}
+// n::N is used the explicit template instantiation.
+template void h(n::M<N>* t);
+
+// Test on Non-type template arguments.
+template <int T>
+void i(n::P<T>* t) {}
+template void i(n::P<Constant>* t);
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-avoid-bind.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-avoid-bind.cpp
new file mode 100644
index 0000000..1c78b9e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-avoid-bind.cpp
@@ -0,0 +1,79 @@
+// RUN: %check_clang_tidy %s modernize-avoid-bind %t -- -- -std=c++14
+
+namespace std {
+inline namespace impl {
+template <class Fp, class... Arguments>
+class bind_rt {};
+
+template <class Fp, class... Arguments>
+bind_rt<Fp, Arguments...> bind(Fp &&, Arguments &&...);
+}
+}
+
+int add(int x, int y) { return x + y; }
+
+void f() {
+ auto clj = std::bind(add, 2, 2);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: prefer a lambda to std::bind [modernize-avoid-bind]
+ // CHECK-FIXES: auto clj = [] { return add(2, 2); };
+}
+
+void g() {
+ int x = 2;
+ int y = 2;
+ auto clj = std::bind(add, x, y);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: prefer a lambda to std::bind
+ // CHECK-FIXES: auto clj = [=] { return add(x, y); };
+}
+
+struct placeholder {};
+placeholder _1;
+placeholder _2;
+
+void h() {
+ int x = 2;
+ auto clj = std::bind(add, x, _1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: prefer a lambda to std::bind
+ // CHECK-FIXES: auto clj = [=](auto && arg1) { return add(x, arg1); };
+}
+
+struct A;
+struct B;
+bool ABTest(const A &, const B &);
+
+void i() {
+ auto BATest = std::bind(ABTest, _2, _1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: prefer a lambda to std::bind
+ // CHECK-FIXES: auto BATest = [](auto && arg1, auto && arg2) { return ABTest(arg2, arg1); };
+}
+
+void j() {
+ auto clj = std::bind(add, 2, 2, 2);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: prefer a lambda to std::bind
+ // No fix is applied for argument mismatches.
+ // CHECK-FIXES: auto clj = std::bind(add, 2, 2, 2);
+}
+
+void k() {
+ auto clj = std::bind(add, _1, _1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: prefer a lambda to std::bind
+ // No fix is applied for reused placeholders.
+ // CHECK-FIXES: auto clj = std::bind(add, _1, _1);
+}
+
+void m() {
+ auto clj = std::bind(add, 1, add(2, 5));
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: prefer a lambda to std::bind
+ // No fix is applied for nested calls.
+ // CHECK-FIXES: auto clj = std::bind(add, 1, add(2, 5));
+}
+
+namespace C {
+ int add(int x, int y){ return x + y; }
+}
+
+void n() {
+ auto clj = std::bind(C::add, 1, 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: prefer a lambda to std::bind
+ // CHECK-FIXES: auto clj = [] { return C::add(1, 1); };
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-deprecated-headers-cxx03.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-deprecated-headers-cxx03.cpp
new file mode 100644
index 0000000..c604ba4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-deprecated-headers-cxx03.cpp
@@ -0,0 +1,148 @@
+// RUN: %check_clang_tidy %s modernize-deprecated-headers %t -- -extra-arg-before=-isystem%S/Inputs/modernize-deprecated-headers -- -std=c++03 -v
+
+#include <assert.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'assert.h'; consider using 'cassert' instead [modernize-deprecated-headers]
+// CHECK-FIXES: {{^}}#include <cassert>{{$}}
+#include <complex.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'complex.h'; consider using 'complex' instead
+// CHECK-FIXES: {{^}}#include <complex>{{$}}
+#include <ctype.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'ctype.h'; consider using 'cctype' instead
+// CHECK-FIXES: {{^}}#include <cctype>{{$}}
+#include <errno.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'errno.h'; consider using 'cerrno' instead
+// CHECK-FIXES: {{^}}#include <cerrno>{{$}}
+#include <float.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'float.h'; consider using 'cfloat' instead
+// CHECK-FIXES: {{^}}#include <cfloat>{{$}}
+#include <limits.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'limits.h'; consider using 'climits' instead
+// CHECK-FIXES: {{^}}#include <climits>{{$}}
+#include <locale.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'locale.h'; consider using 'clocale' instead
+// CHECK-FIXES: {{^}}#include <clocale>{{$}}
+#include <math.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'math.h'; consider using 'cmath' instead
+// CHECK-FIXES: {{^}}#include <cmath>{{$}}
+#include <setjmp.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'setjmp.h'; consider using 'csetjmp' instead
+// CHECK-FIXES: {{^}}#include <csetjmp>{{$}}
+#include <signal.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'signal.h'; consider using 'csignal' instead
+// CHECK-FIXES: {{^}}#include <csignal>{{$}}
+#include <stdarg.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdarg.h'; consider using 'cstdarg' instead
+// CHECK-FIXES: {{^}}#include <cstdarg>{{$}}
+#include <stddef.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stddef.h'; consider using 'cstddef' instead
+// CHECK-FIXES: {{^}}#include <cstddef>{{$}}
+#include <stdio.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdio.h'; consider using 'cstdio' instead
+// CHECK-FIXES: {{^}}#include <cstdio>{{$}}
+#include <stdlib.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdlib.h'; consider using 'cstdlib' instead
+// CHECK-FIXES: {{^}}#include <cstdlib>{{$}}
+#include <string.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'string.h'; consider using 'cstring' instead
+// CHECK-FIXES: {{^}}#include <cstring>{{$}}
+#include <time.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'time.h'; consider using 'ctime' instead
+// CHECK-FIXES: {{^}}#include <ctime>{{$}}
+#include <wchar.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'wchar.h'; consider using 'cwchar' instead
+// CHECK-FIXES: {{^}}#include <cwchar>{{$}}
+#include <wctype.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'wctype.h'; consider using 'cwctype' instead
+// CHECK-FIXES: {{^}}#include <cwctype>{{$}}
+
+// Headers that have no effect in C++; remove them
+#include <stdalign.h> // <stdalign.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdalign.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// <stdalign.h>{{$}}
+#include <stdbool.h> // <stdbool.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdbool.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// <stdbool.h>{{$}}
+#include <iso646.h> // <iso646.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'iso646.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// <iso646.h>{{$}}
+
+// Headers deprecated since C++11: expect no diagnostics.
+#include <fenv.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <tgmath.h>
+#include <uchar.h>
+
+
+#include "assert.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'assert.h'; consider using 'cassert' instead
+// CHECK-FIXES: {{^}}#include <cassert>{{$}}
+#include "complex.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'complex.h'; consider using 'complex' instead
+// CHECK-FIXES: {{^}}#include <complex>{{$}}
+#include "ctype.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'ctype.h'; consider using 'cctype' instead
+// CHECK-FIXES: {{^}}#include <cctype>{{$}}
+#include "errno.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'errno.h'; consider using 'cerrno' instead
+// CHECK-FIXES: {{^}}#include <cerrno>{{$}}
+#include "float.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'float.h'; consider using 'cfloat' instead
+// CHECK-FIXES: {{^}}#include <cfloat>{{$}}
+#include "limits.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'limits.h'; consider using 'climits' instead
+// CHECK-FIXES: {{^}}#include <climits>{{$}}
+#include "locale.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'locale.h'; consider using 'clocale' instead
+// CHECK-FIXES: {{^}}#include <clocale>{{$}}
+#include "math.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'math.h'; consider using 'cmath' instead
+// CHECK-FIXES: {{^}}#include <cmath>{{$}}
+#include "setjmp.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'setjmp.h'; consider using 'csetjmp' instead
+// CHECK-FIXES: {{^}}#include <csetjmp>{{$}}
+#include "signal.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'signal.h'; consider using 'csignal' instead
+// CHECK-FIXES: {{^}}#include <csignal>{{$}}
+#include "stdarg.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdarg.h'; consider using 'cstdarg' instead
+// CHECK-FIXES: {{^}}#include <cstdarg>{{$}}
+#include "stddef.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stddef.h'; consider using 'cstddef' instead
+// CHECK-FIXES: {{^}}#include <cstddef>{{$}}
+#include "stdio.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdio.h'; consider using 'cstdio' instead
+// CHECK-FIXES: {{^}}#include <cstdio>{{$}}
+#include "stdlib.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdlib.h'; consider using 'cstdlib' instead
+// CHECK-FIXES: {{^}}#include <cstdlib>{{$}}
+#include "string.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'string.h'; consider using 'cstring' instead
+// CHECK-FIXES: {{^}}#include <cstring>{{$}}
+#include "time.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'time.h'; consider using 'ctime' instead
+// CHECK-FIXES: {{^}}#include <ctime>{{$}}
+#include "wchar.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'wchar.h'; consider using 'cwchar' instead
+// CHECK-FIXES: {{^}}#include <cwchar>{{$}}
+#include "wctype.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'wctype.h'; consider using 'cwctype' instead
+// CHECK-FIXES: {{^}}#include <cwctype>
+
+// Headers that have no effect in C++; remove them
+#include "stdalign.h" // "stdalign.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdalign.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// "stdalign.h"{{$}}
+#include "stdbool.h" // "stdbool.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdbool.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// "stdbool.h"{{$}}
+#include "iso646.h" // "iso646.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'iso646.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// "iso646.h"{{$}}
+
+// Headers deprecated since C++11; expect no diagnostics
+#include "fenv.h"
+#include "inttypes.h"
+#include "stdint.h"
+#include "tgmath.h"
+#include "uchar.h"
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-deprecated-headers-cxx11.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-deprecated-headers-cxx11.cpp
new file mode 100644
index 0000000..366f045
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-deprecated-headers-cxx11.cpp
@@ -0,0 +1,163 @@
+// RUN: %check_clang_tidy %s modernize-deprecated-headers %t -- -extra-arg-before=-isystem%S/Inputs/modernize-deprecated-headers -- -std=c++11 -v
+
+#include <assert.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'assert.h'; consider using 'cassert' instead [modernize-deprecated-headers]
+// CHECK-FIXES: {{^}}#include <cassert>{{$}}
+#include <complex.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'complex.h'; consider using 'complex' instead
+// CHECK-FIXES: {{^}}#include <complex>{{$}}
+#include <ctype.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'ctype.h'; consider using 'cctype' instead
+// CHECK-FIXES: {{^}}#include <cctype>{{$}}
+#include <errno.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'errno.h'; consider using 'cerrno' instead
+// CHECK-FIXES: {{^}}#include <cerrno>{{$}}
+#include <fenv.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'fenv.h'; consider using 'cfenv' instead
+// CHECK-FIXES: {{^}}#include <cfenv>{{$}}
+#include <float.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'float.h'; consider using 'cfloat' instead
+// CHECK-FIXES: {{^}}#include <cfloat>{{$}}
+#include <inttypes.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'inttypes.h'; consider using 'cinttypes' instead
+// CHECK-FIXES: {{^}}#include <cinttypes>{{$}}
+#include <limits.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'limits.h'; consider using 'climits' instead
+// CHECK-FIXES: {{^}}#include <climits>{{$}}
+#include <locale.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'locale.h'; consider using 'clocale' instead
+// CHECK-FIXES: {{^}}#include <clocale>{{$}}
+#include <math.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'math.h'; consider using 'cmath' instead
+// CHECK-FIXES: {{^}}#include <cmath>{{$}}
+#include <setjmp.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'setjmp.h'; consider using 'csetjmp' instead
+// CHECK-FIXES: {{^}}#include <csetjmp>{{$}}
+#include <signal.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'signal.h'; consider using 'csignal' instead
+// CHECK-FIXES: {{^}}#include <csignal>{{$}}
+#include <stdarg.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdarg.h'; consider using 'cstdarg' instead
+// CHECK-FIXES: {{^}}#include <cstdarg>{{$}}
+#include <stddef.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stddef.h'; consider using 'cstddef' instead
+// CHECK-FIXES: {{^}}#include <cstddef>{{$}}
+#include <stdint.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdint.h'; consider using 'cstdint' instead
+// CHECK-FIXES: {{^}}#include <cstdint>{{$}}
+#include <stdio.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdio.h'; consider using 'cstdio' instead
+// CHECK-FIXES: {{^}}#include <cstdio>{{$}}
+#include <stdlib.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdlib.h'; consider using 'cstdlib' instead
+// CHECK-FIXES: {{^}}#include <cstdlib>{{$}}
+#include <string.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'string.h'; consider using 'cstring' instead
+// CHECK-FIXES: {{^}}#include <cstring>{{$}}
+#include <tgmath.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'tgmath.h'; consider using 'ctgmath' instead
+// CHECK-FIXES: {{^}}#include <ctgmath>{{$}}
+#include <time.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'time.h'; consider using 'ctime' instead
+// CHECK-FIXES: {{^}}#include <ctime>{{$}}
+#include <uchar.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'uchar.h'; consider using 'cuchar' instead
+// CHECK-FIXES: {{^}}#include <cuchar>{{$}}
+#include <wchar.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'wchar.h'; consider using 'cwchar' instead
+// CHECK-FIXES: {{^}}#include <cwchar>{{$}}
+#include <wctype.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'wctype.h'; consider using 'cwctype' instead
+// CHECK-FIXES: {{^}}#include <cwctype>
+
+// Headers that have no effect in C++; remove them
+#include <stdalign.h> // <stdalign.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdalign.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// <stdalign.h>{{$}}
+#include <stdbool.h> // <stdbool.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdbool.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// <stdbool.h>{{$}}
+#include <iso646.h> // <iso646.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'iso646.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// <iso646.h>{{$}}
+
+#include "assert.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'assert.h'; consider using 'cassert' instead
+// CHECK-FIXES: {{^}}#include <cassert>{{$}}
+#include "complex.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'complex.h'; consider using 'complex' instead
+// CHECK-FIXES: {{^}}#include <complex>{{$}}
+#include "ctype.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'ctype.h'; consider using 'cctype' instead
+// CHECK-FIXES: {{^}}#include <cctype>{{$}}
+#include "errno.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'errno.h'; consider using 'cerrno' instead
+// CHECK-FIXES: {{^}}#include <cerrno>{{$}}
+#include "fenv.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'fenv.h'; consider using 'cfenv' instead
+// CHECK-FIXES: {{^}}#include <cfenv>{{$}}
+#include "float.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'float.h'; consider using 'cfloat' instead
+// CHECK-FIXES: {{^}}#include <cfloat>{{$}}
+#include "inttypes.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'inttypes.h'; consider using 'cinttypes' instead
+// CHECK-FIXES: {{^}}#include <cinttypes>{{$}}
+#include "limits.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'limits.h'; consider using 'climits' instead
+// CHECK-FIXES: {{^}}#include <climits>{{$}}
+#include "locale.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'locale.h'; consider using 'clocale' instead
+// CHECK-FIXES: {{^}}#include <clocale>{{$}}
+#include "math.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'math.h'; consider using 'cmath' instead
+// CHECK-FIXES: {{^}}#include <cmath>{{$}}
+#include "setjmp.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'setjmp.h'; consider using 'csetjmp' instead
+// CHECK-FIXES: {{^}}#include <csetjmp>{{$}}
+#include "signal.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'signal.h'; consider using 'csignal' instead
+// CHECK-FIXES: {{^}}#include <csignal>{{$}}
+#include "stdarg.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdarg.h'; consider using 'cstdarg' instead
+// CHECK-FIXES: {{^}}#include <cstdarg>{{$}}
+#include "stddef.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stddef.h'; consider using 'cstddef' instead
+// CHECK-FIXES: {{^}}#include <cstddef>{{$}}
+#include "stdint.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdint.h'; consider using 'cstdint' instead
+// CHECK-FIXES: {{^}}#include <cstdint>{{$}}
+#include "stdio.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdio.h'; consider using 'cstdio' instead
+// CHECK-FIXES: {{^}}#include <cstdio>{{$}}
+#include "stdlib.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdlib.h'; consider using 'cstdlib' instead
+// CHECK-FIXES: {{^}}#include <cstdlib>{{$}}
+#include "string.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'string.h'; consider using 'cstring' instead
+// CHECK-FIXES: {{^}}#include <cstring>{{$}}
+#include "tgmath.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'tgmath.h'; consider using 'ctgmath' instead
+// CHECK-FIXES: {{^}}#include <ctgmath>{{$}}
+#include "time.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'time.h'; consider using 'ctime' instead
+// CHECK-FIXES: {{^}}#include <ctime>{{$}}
+#include "uchar.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'uchar.h'; consider using 'cuchar' instead
+// CHECK-FIXES: {{^}}#include <cuchar>{{$}}
+#include "wchar.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'wchar.h'; consider using 'cwchar' instead
+// CHECK-FIXES: {{^}}#include <cwchar>{{$}}
+#include "wctype.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'wctype.h'; consider using 'cwctype' instead
+// CHECK-FIXES: {{^}}#include <cwctype>
+
+// Headers that have no effect in C++; remove them
+#include "stdalign.h" // "stdalign.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdalign.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// "stdalign.h"{{$}}
+#include "stdbool.h" // "stdbool.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdbool.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// "stdbool.h"{{$}}
+#include "iso646.h" // "iso646.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'iso646.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// "iso646.h"{{$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-assert-failure.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-assert-failure.cpp
new file mode 100644
index 0000000..fab51da
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-assert-failure.cpp
@@ -0,0 +1,18 @@
+// RUN: not clang-tidy %s -checks=-*,modernize-loop-convert --
+
+// Note: this test expects no assert failure happened in clang-tidy.
+
+class LinguisticItem {
+ LinguisticItem *x0;
+ class x1 {
+ bool operator!= ( const x1 &;
+ operator* ( ;
+ LinguisticItem * &operator-> ( ;
+ operator++ (
+ } begin() const;
+ x1 end() const {
+ LinguisticStream x2;
+ for (x1 x3 = x2.begin x3 != x2.end; ++x3)
+ x3->x0
+ }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-basic.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-basic.cpp
new file mode 100644
index 0000000..def7c4b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-basic.cpp
@@ -0,0 +1,793 @@
+// RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -std=c++11 -I %S/Inputs/modernize-loop-convert
+
+#include "structures.h"
+
+namespace Array {
+
+const int N = 6;
+const int NMinusOne = N - 1;
+int Arr[N] = {1, 2, 3, 4, 5, 6};
+const int ConstArr[N] = {1, 2, 3, 4, 5, 6};
+int (*PArr)[N] = &Arr;
+
+void f() {
+ int Sum = 0;
+
+ for (int I = 0; I < N; ++I) {
+ Sum += Arr[I];
+ int K;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead [modernize-loop-convert]
+ // CHECK-FIXES: for (int I : Arr)
+ // CHECK-FIXES-NEXT: Sum += I;
+ // CHECK-FIXES-NEXT: int K;
+
+ for (int I = 0; I < N; ++I) {
+ printf("Fibonacci number is %d\n", Arr[I]);
+ Sum += Arr[I] + 2;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : Arr)
+ // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
+ // CHECK-FIXES-NEXT: Sum += I + 2;
+
+ for (int I = 0; I < N; ++I) {
+ int X = Arr[I];
+ int Y = Arr[I] + 2;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : Arr)
+ // CHECK-FIXES-NEXT: int X = I;
+ // CHECK-FIXES-NEXT: int Y = I + 2;
+
+ for (int I = 0; I < N; ++I) {
+ int X = N;
+ X = Arr[I];
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : Arr)
+ // CHECK-FIXES-NEXT: int X = N;
+ // CHECK-FIXES-NEXT: X = I;
+
+ for (int I = 0; I < N; ++I) {
+ Arr[I] += 1;
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & I : Arr)
+ // CHECK-FIXES-NEXT: I += 1;
+
+ for (int I = 0; I < N; ++I) {
+ int X = Arr[I] + 2;
+ Arr[I]++;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & I : Arr)
+ // CHECK-FIXES-NEXT: int X = I + 2;
+ // CHECK-FIXES-NEXT: I++;
+
+ for (int I = 0; I < N; ++I) {
+ Arr[I] = 4 + Arr[I];
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & I : Arr)
+ // CHECK-FIXES-NEXT: I = 4 + I;
+
+ for (int I = 0; I < NMinusOne + 1; ++I) {
+ Sum += Arr[I];
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : Arr)
+ // CHECK-FIXES-NEXT: Sum += I;
+
+ for (int I = 0; I < N; ++I) {
+ printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
+ Sum += Arr[I] + 2;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & I : Arr)
+ // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
+ // CHECK-FIXES-NEXT: Sum += I + 2;
+
+ Val Teas[N];
+ for (int I = 0; I < N; ++I) {
+ Teas[I].g();
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & Tea : Teas)
+ // CHECK-FIXES-NEXT: Tea.g();
+}
+
+const int *constArray() {
+ for (int I = 0; I < N; ++I) {
+ printf("2 * %d = %d\n", ConstArr[I], ConstArr[I] + ConstArr[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : ConstArr)
+ // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I, I + I);
+
+ const NonTriviallyCopyable NonCopy[N]{};
+ for (int I = 0; I < N; ++I) {
+ printf("2 * %d = %d\n", NonCopy[I].X, NonCopy[I].X + NonCopy[I].X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (const auto & I : NonCopy)
+ // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X);
+
+ const TriviallyCopyableButBig Big[N]{};
+ for (int I = 0; I < N; ++I) {
+ printf("2 * %d = %d\n", Big[I].X, Big[I].X + Big[I].X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (const auto & I : Big)
+ // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X);
+
+ bool Something = false;
+ for (int I = 0; I < N; ++I) {
+ if (Something)
+ return &ConstArr[I];
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (const int & I : ConstArr)
+ // CHECK-FIXES-NEXT: if (Something)
+ // CHECK-FIXES-NEXT: return &I;
+}
+
+struct HasArr {
+ int Arr[N];
+ Val ValArr[N];
+ void implicitThis() {
+ for (int I = 0; I < N; ++I) {
+ printf("%d", Arr[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : Arr)
+ // CHECK-FIXES-NEXT: printf("%d", I);
+
+ for (int I = 0; I < N; ++I) {
+ printf("%d", ValArr[I].X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : ValArr)
+ // CHECK-FIXES-NEXT: printf("%d", I.X);
+ }
+
+ void explicitThis() {
+ for (int I = 0; I < N; ++I) {
+ printf("%d", this->Arr[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : this->Arr)
+ // CHECK-FIXES-NEXT: printf("%d", I);
+
+ for (int I = 0; I < N; ++I) {
+ printf("%d", this->ValArr[I].X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : this->ValArr)
+ // CHECK-FIXES-NEXT: printf("%d", I.X);
+ }
+};
+
+struct HasIndirectArr {
+ HasArr HA;
+ void implicitThis() {
+ for (int I = 0; I < N; ++I) {
+ printf("%d", HA.Arr[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : HA.Arr)
+ // CHECK-FIXES-NEXT: printf("%d", I);
+
+ for (int I = 0; I < N; ++I) {
+ printf("%d", HA.ValArr[I].X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : HA.ValArr)
+ // CHECK-FIXES-NEXT: printf("%d", I.X);
+ }
+
+ void explicitThis() {
+ for (int I = 0; I < N; ++I) {
+ printf("%d", this->HA.Arr[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : this->HA.Arr)
+ // CHECK-FIXES-NEXT: printf("%d", I);
+
+ for (int I = 0; I < N; ++I) {
+ printf("%d", this->HA.ValArr[I].X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : this->HA.ValArr)
+ // CHECK-FIXES-NEXT: printf("%d", I.X);
+ }
+};
+
+// Loops whose bounds are value-dependent should not be converted.
+template <int N>
+void dependentExprBound() {
+ for (int I = 0; I < N; ++I)
+ Arr[I] = 0;
+}
+template void dependentExprBound<20>();
+
+void memberFunctionPointer() {
+ Val V;
+ void (Val::*mfpArr[N])(void) = {&Val::g};
+ for (int I = 0; I < N; ++I)
+ (V.*mfpArr[I])();
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : mfpArr)
+ // CHECK-FIXES-NEXT: (V.*I)();
+
+ struct Foo {
+ int (Val::*f)();
+ } Foo[N];
+
+ for (int I = 0; I < N; ++I)
+ int R = (V.*(Foo[I].f))();
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : Foo)
+ // CHECK-FIXES-NEXT: int R = (V.*(I.f))();
+
+}
+
+} // namespace Array
+
+namespace Iterator {
+
+void f() {
+ /// begin()/end() - based for loops here:
+ T Tt;
+ for (T::iterator It = Tt.begin(), E = Tt.end(); It != E; ++It) {
+ printf("I found %d\n", *It);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & It : Tt)
+ // CHECK-FIXES-NEXT: printf("I found %d\n", It);
+
+ T *Pt;
+ for (T::iterator It = Pt->begin(), E = Pt->end(); It != E; ++It) {
+ printf("I found %d\n", *It);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & It : *Pt)
+ // CHECK-FIXES-NEXT: printf("I found %d\n", It);
+
+ S Ss;
+ for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
+ printf("s has value %d\n", (*It).X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : Ss)
+ // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+ S *Ps;
+ for (S::iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
+ printf("s has value %d\n", (*It).X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & P : *Ps)
+ // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
+
+ for (S::const_iterator It = Ss.cbegin(), E = Ss.cend(); It != E; ++It) {
+ printf("s has value %d\n", (*It).X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto It : Ss)
+ // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+ for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
+ printf("s has value %d\n", It->X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : Ss)
+ // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+ for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
+ It->X = 3;
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : Ss)
+ // CHECK-FIXES-NEXT: It.X = 3;
+
+ for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
+ (*It).X = 3;
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : Ss)
+ // CHECK-FIXES-NEXT: It.X = 3;
+
+ for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
+ It->nonConstFun(4, 5);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : Ss)
+ // CHECK-FIXES-NEXT: It.nonConstFun(4, 5);
+
+ U Uu;
+ for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
+ printf("s has value %d\n", It->X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : Uu)
+ // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+ for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
+ printf("s has value %d\n", (*It).X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : Uu)
+ // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+ for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
+ Val* a = It.operator->();
+ }
+
+ U::iterator A;
+ for (U::iterator I = Uu.begin(), E = Uu.end(); I != E; ++I)
+ int K = A->X + I->X;
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : Uu)
+ // CHECK-FIXES-NEXT: int K = A->X + I.X;
+
+ dependent<int> V;
+ for (dependent<int>::iterator It = V.begin(), E = V.end();
+ It != E; ++It) {
+ printf("Fibonacci number is %d\n", *It);
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & It : V)
+ // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
+
+ for (dependent<int>::iterator It(V.begin()), E = V.end();
+ It != E; ++It) {
+ printf("Fibonacci number is %d\n", *It);
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & It : V)
+ // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
+
+ doublyDependent<int, int> Intmap;
+ for (doublyDependent<int, int>::iterator It = Intmap.begin(), E = Intmap.end();
+ It != E; ++It) {
+ printf("Intmap[%d] = %d", It->first, It->second);
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : Intmap)
+ // CHECK-FIXES: printf("Intmap[%d] = %d", It.first, It.second);
+
+ // PtrSet's iterator dereferences by value so auto & can't be used.
+ {
+ PtrSet<int *> Val_int_ptrs;
+ for (PtrSet<int *>::iterator I = Val_int_ptrs.begin(),
+ E = Val_int_ptrs.end();
+ I != E; ++I) {
+ (void) *I;
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto Val_int_ptr : Val_int_ptrs)
+ }
+
+ // This container uses an iterator where the derefence type is a typedef of
+ // a reference type. Make sure non-const auto & is still used. A failure here
+ // means canonical types aren't being tested.
+ {
+ TypedefDerefContainer<int> Int_ptrs;
+ for (TypedefDerefContainer<int>::iterator I = Int_ptrs.begin(),
+ E = Int_ptrs.end();
+ I != E; ++I) {
+ (void) *I;
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & Int_ptr : Int_ptrs)
+ }
+
+ {
+ // Iterators returning an rvalue reference should disqualify the loop from
+ // transformation.
+ RValueDerefContainer<int> Container;
+ for (RValueDerefContainer<int>::iterator I = Container.begin(),
+ E = Container.end();
+ I != E; ++I) {
+ (void) *I;
+ }
+ }
+
+ dependent<Val *> Dpp;
+ for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {
+ printf("%d\n", (**I).X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : Dpp)
+ // CHECK-FIXES-NEXT: printf("%d\n", (*I).X);
+
+ for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {
+ printf("%d\n", (*I)->X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : Dpp)
+ // CHECK-FIXES-NEXT: printf("%d\n", I->X);
+}
+
+// Tests to verify the proper use of auto where the init variable type and the
+// initializer type differ or are mostly the same except for const qualifiers.
+void different_type() {
+ // Ss.begin() returns a type 'iterator' which is just a non-const pointer and
+ // differs from const_iterator only on the const qualification.
+ S Ss;
+ for (S::const_iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
+ printf("s has value %d\n", (*It).X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto It : Ss)
+ // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+ S *Ps;
+ for (S::const_iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
+ printf("s has value %d\n", (*It).X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto P : *Ps)
+ // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
+
+ // V.begin() returns a user-defined type 'iterator' which, since it's
+ // different from const_iterator, disqualifies these loops from
+ // transformation.
+ dependent<int> V;
+ for (dependent<int>::const_iterator It = V.begin(), E = V.end();
+ It != E; ++It) {
+ printf("Fibonacci number is %d\n", *It);
+ }
+
+ for (dependent<int>::const_iterator It(V.begin()), E = V.end();
+ It != E; ++It) {
+ printf("Fibonacci number is %d\n", *It);
+ }
+}
+
+// Tests to ensure that an implicit 'this' is picked up as the container.
+// If member calls are made to 'this' within the loop, the transform becomes
+// risky as these calls may affect state that affects the loop.
+class C {
+public:
+ typedef MutableVal *iterator;
+ typedef const MutableVal *const_iterator;
+
+ iterator begin();
+ iterator end();
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ void doSomething();
+ void doSomething() const;
+
+ void doLoop() {
+ for (iterator I = begin(), E = end(); I != E; ++I)
+ (void) *I;
+ // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : *this)
+
+ for (iterator I = C::begin(), E = C::end(); I != E; ++I)
+ (void) *I;
+ // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : *this)
+
+ for (iterator I = begin(), E = end(); I != E; ++I) {
+ (void) *I;
+ doSomething();
+ }
+
+ for (iterator I = begin(); I != end(); ++I)
+ (void) *I;
+ // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : *this)
+
+ for (iterator I = begin(); I != end(); ++I) {
+ (void) *I;
+ doSomething();
+ }
+ }
+
+ void doLoop() const {
+ for (const_iterator I = begin(), E = end(); I != E; ++I)
+ (void) *I;
+ // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto I : *this)
+
+ for (const_iterator I = C::begin(), E = C::end(); I != E; ++I)
+ (void) *I;
+ // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto I : *this)
+
+ for (const_iterator I = begin(), E = end(); I != E; ++I) {
+ (void) *I;
+ doSomething();
+ }
+ }
+};
+
+class C2 {
+public:
+ typedef MutableVal *iterator;
+
+ iterator begin() const;
+ iterator end() const;
+
+ void doLoop() {
+ // The implicit 'this' will have an Implicit cast to const C2* wrapped
+ // around it. Make sure the replacement still happens.
+ for (iterator I = begin(), E = end(); I != E; ++I)
+ (void) *I;
+ // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : *this)
+ }
+};
+
+} // namespace Iterator
+
+namespace PseudoArray {
+
+const int N = 6;
+dependent<int> V;
+dependent<int> *Pv;
+const dependent<NonTriviallyCopyable> Constv;
+const dependent<NonTriviallyCopyable> *Pconstv;
+
+transparent<dependent<int>> Cv;
+
+void f() {
+ int Sum = 0;
+ for (int I = 0, E = V.size(); I < E; ++I) {
+ printf("Fibonacci number is %d\n", V[I]);
+ Sum += V[I] + 2;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : V)
+ // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
+ // CHECK-FIXES-NEXT: Sum += I + 2;
+
+ for (int I = 0, E = V.size(); I < E; ++I) {
+ printf("Fibonacci number is %d\n", V.at(I));
+ Sum += V.at(I) + 2;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : V)
+ // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
+ // CHECK-FIXES-NEXT: Sum += I + 2;
+
+ for (int I = 0, E = Pv->size(); I < E; ++I) {
+ printf("Fibonacci number is %d\n", Pv->at(I));
+ Sum += Pv->at(I) + 2;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : *Pv)
+ // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
+ // CHECK-FIXES-NEXT: Sum += I + 2;
+
+ // This test will fail if size() isn't called repeatedly, since it
+ // returns unsigned int, and 0 is deduced to be signed int.
+ // FIXME: Insert the necessary explicit conversion, or write out the types
+ // explicitly.
+ for (int I = 0; I < Pv->size(); ++I) {
+ printf("Fibonacci number is %d\n", (*Pv).at(I));
+ Sum += (*Pv)[I] + 2;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : *Pv)
+ // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
+ // CHECK-FIXES-NEXT: Sum += I + 2;
+
+ for (int I = 0; I < Cv->size(); ++I) {
+ printf("Fibonacci number is %d\n", Cv->at(I));
+ Sum += Cv->at(I) + 2;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : *Cv)
+ // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
+ // CHECK-FIXES-NEXT: Sum += I + 2;
+}
+
+// Ensure that 'const auto &' is used with containers of non-trivial types.
+void constness() {
+ int Sum = 0;
+ for (int I = 0, E = Constv.size(); I < E; ++I) {
+ printf("Fibonacci number is %d\n", Constv[I].X);
+ Sum += Constv[I].X + 2;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (const auto & I : Constv)
+ // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
+ // CHECK-FIXES-NEXT: Sum += I.X + 2;
+
+ for (int I = 0, E = Constv.size(); I < E; ++I) {
+ printf("Fibonacci number is %d\n", Constv.at(I).X);
+ Sum += Constv.at(I).X + 2;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (const auto & I : Constv)
+ // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
+ // CHECK-FIXES-NEXT: Sum += I.X + 2;
+
+ for (int I = 0, E = Pconstv->size(); I < E; ++I) {
+ printf("Fibonacci number is %d\n", Pconstv->at(I).X);
+ Sum += Pconstv->at(I).X + 2;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (const auto & I : *Pconstv)
+ // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
+ // CHECK-FIXES-NEXT: Sum += I.X + 2;
+
+ // This test will fail if size() isn't called repeatedly, since it
+ // returns unsigned int, and 0 is deduced to be signed int.
+ // FIXME: Insert the necessary explicit conversion, or write out the types
+ // explicitly.
+ for (int I = 0; I < Pconstv->size(); ++I) {
+ printf("Fibonacci number is %d\n", (*Pconstv).at(I).X);
+ Sum += (*Pconstv)[I].X + 2;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (const auto & I : *Pconstv)
+ // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
+ // CHECK-FIXES-NEXT: Sum += I.X + 2;
+}
+
+void constRef(const dependent<int>& ConstVRef) {
+ int sum = 0;
+ // FIXME: This does not work with size_t (probably due to the implementation
+ // of dependent); make dependent work exactly like a std container type.
+ for (int I = 0; I < ConstVRef.size(); ++I) {
+ sum += ConstVRef[I];
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : ConstVRef)
+ // CHECK-FIXES-NEXT: sum += I;
+
+ for (auto I = ConstVRef.begin(), E = ConstVRef.end(); I != E; ++I) {
+ sum += *I;
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : ConstVRef)
+ // CHECK-FIXES-NEXT: sum += I;
+}
+
+// Check for loops that don't mention containers.
+void noContainer() {
+ for (auto I = 0; I < V.size(); ++I) {
+ }
+
+ for (auto I = 0; I < V.size(); ++I)
+ ;
+}
+
+struct NoBeginEnd {
+ unsigned size() const;
+ unsigned& operator[](int);
+ const unsigned& operator[](int) const;
+};
+
+struct NoConstBeginEnd {
+ NoConstBeginEnd();
+ unsigned size() const;
+ unsigned* begin();
+ unsigned* end();
+ unsigned& operator[](int);
+ const unsigned& operator[](int) const;
+};
+
+struct ConstBeginEnd {
+ ConstBeginEnd();
+ unsigned size() const;
+ unsigned* begin() const;
+ unsigned* end() const;
+ unsigned& operator[](int);
+ const unsigned& operator[](int) const;
+};
+
+// Shouldn't transform pseudo-array uses if the container doesn't provide
+// begin() and end() of the right const-ness.
+void NoBeginEndTest() {
+ NoBeginEnd NBE;
+ for (unsigned I = 0, E = NBE.size(); I < E; ++I)
+ printf("%d\n", NBE[I]);
+
+ const NoConstBeginEnd Const_NCBE;
+ for (unsigned I = 0, E = Const_NCBE.size(); I < E; ++I)
+ printf("%d\n", Const_NCBE[I]);
+
+ ConstBeginEnd CBE;
+ for (unsigned I = 0, E = CBE.size(); I < E; ++I)
+ printf("%d\n", CBE[I]);
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (unsigned int I : CBE)
+ // CHECK-FIXES-NEXT: printf("%d\n", I);
+
+ const ConstBeginEnd Const_CBE;
+ for (unsigned I = 0, E = Const_CBE.size(); I < E; ++I)
+ printf("%d\n", Const_CBE[I]);
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (unsigned int I : Const_CBE)
+ // CHECK-FIXES-NEXT: printf("%d\n", I);
+}
+
+struct DerefByValue {
+ DerefByValue();
+ struct iter { unsigned operator*(); };
+ unsigned size() const;
+ iter begin();
+ iter end();
+ unsigned operator[](int);
+};
+
+void derefByValueTest() {
+ DerefByValue DBV;
+ for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
+ printf("%d\n", DBV[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (unsigned int I : DBV)
+ // CHECK-FIXES-NEXT: printf("%d\n", I);
+
+ for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
+ auto f = [DBV, I]() {};
+ printf("%d\n", DBV[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (unsigned int I : DBV)
+ // CHECK-FIXES-NEXT: auto f = [DBV, &I]() {};
+ // CHECK-FIXES-NEXT: printf("%d\n", I);
+}
+
+void fundamentalTypesTest() {
+ const int N = 10;
+ bool Bools[N];
+ for (int i = 0; i < N; ++i)
+ printf("%d", Bools[i]);
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (bool Bool : Bools)
+
+ int Ints[N];
+ unsigned short int Shorts[N];
+ for (int i = 0; i < N; ++i)
+ printf("%d", Shorts[i]);
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (unsigned short Short : Shorts)
+
+ signed long Longs[N];
+ for (int i = 0; i < N; ++i)
+ printf("%d", Longs[i]);
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (long Long : Longs)
+
+ long long int LongLongs[N];
+ for (int i = 0; i < N; ++i)
+ printf("%d", LongLongs[i]);
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (long long LongLong : LongLongs)
+
+ char Chars[N];
+ for (int i = 0; i < N; ++i)
+ printf("%d", Chars[i]);
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (char Char : Chars)
+
+ wchar_t WChars[N];
+ for (int i = 0; i < N; ++i)
+ printf("%d", WChars[i]);
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (wchar_t WChar : WChars)
+
+ float Floats[N];
+ for (int i = 0; i < N; ++i)
+ printf("%d", Floats[i]);
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (float Float : Floats)
+
+ double Doubles[N];
+ for (int i = 0; i < N; ++i)
+ printf("%d", Doubles[i]);
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (double Double : Doubles)
+}
+
+} // namespace PseudoArray
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-camelback.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-camelback.cpp
new file mode 100644
index 0000000..50044de
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-camelback.cpp
@@ -0,0 +1,33 @@
+// RUN: %check_clang_tidy %s modernize-loop-convert %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-loop-convert.NamingStyle, value: 'camelBack'}]}" \
+// RUN: -- -std=c++11 -I %S/Inputs/modernize-loop-convert
+
+#include "structures.h"
+
+const int n = 10;
+int arr[n];
+int nums[n];
+
+void naming() {
+ for (int i = 0; i < n; ++i) {
+ printf("%d\n", arr[i]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]
+ // CHECK-FIXES: for (int i : arr)
+ // CHECK-FIXES-NEXT: printf("%d\n", i);
+
+ for (int i = 0; i < n; ++i) {
+ printf("%d\n", nums[i]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int num : nums)
+ // CHECK-FIXES-NEXT: printf("%d\n", num);
+
+ int num = 0;
+ for (int i = 0; i < n; ++i) {
+ printf("%d\n", nums[i] + num);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int i : nums)
+ // CHECK-FIXES-NEXT: printf("%d\n", i + num);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-const.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-const.cpp
new file mode 100644
index 0000000..806b6c1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-const.cpp
@@ -0,0 +1,360 @@
+// RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -std=c++11
+
+struct Str {
+ Str() = default;
+ Str(const Str &) = default;
+ void constMember(int) const;
+ void nonConstMember(int);
+ bool operator<(const Str &str) const; // const operator.
+ Str &operator=(const Str &str) = default; // non const operator.
+};
+
+// This class is non-trivially copyable because the copy-constructor and copy
+// assignment take non-const references.
+struct ModifiesRightSide {
+ ModifiesRightSide() = default;
+ ModifiesRightSide(ModifiesRightSide &) = default;
+ bool operator<(ModifiesRightSide &) const;
+ ModifiesRightSide &operator=(ModifiesRightSide &) = default;
+};
+
+template <typename T>
+void copyArg(T);
+
+template <typename T>
+void nonConstRefArg(T &);
+
+// If we define this as a template, the type is deduced to "T&",
+// and "const (T&) &" is the same as "T& &", and this collapses to "T&".
+void constRefArg(const Str &);
+void constRefArg(const ModifiesRightSide &);
+void constRefArg(const int &);
+
+void foo();
+
+const int N = 10;
+Str Array[N], OtherStr;
+ModifiesRightSide Right[N], OtherRight;
+int Ints[N], OtherInt;
+
+void memberFunctionsAndOperators() {
+ // Calling const member functions or operator is a const usage.
+ for (int I = 0; I < N; ++I) {
+ Array[I].constMember(0);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]
+ // CHECK-FIXES: for (auto I : Array)
+ // CHECK-FIXES-NEXT: I.constMember(0);
+
+ for (int I = 0; I < N; ++I) {
+ if (Array[I] < OtherStr)
+ foo();
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (auto I : Array)
+ // CHECK-FIXES-NEXT: if (I < OtherStr)
+ for (int I = 0; I < N; ++I) {
+ if (Right[I] < OtherRight)
+ foo();
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (const auto & I : Right)
+ // CHECK-FIXES-NEXT: if (I < OtherRight)
+
+ // Calling non-const member functions is not.
+ for (int I = 0; I < N; ++I) {
+ Array[I].nonConstMember(0);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (auto & I : Array)
+ // CHECK-FIXES-NEXT: I.nonConstMember(0);
+
+ for (int I = 0; I < N; ++I) {
+ Array[I] = OtherStr;
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (auto & I : Array)
+ // CHECK-FIXES-NEXT: I = OtherStr;
+
+ for (int I = 0; I < N; ++I) {
+ Right[I] = OtherRight;
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (auto & I : Right)
+ // CHECK-FIXES-NEXT: I = OtherRight;
+}
+
+void usedAsParameterToFunctionOrOperator() {
+ // Copying is OK, as long as the copy constructor takes a const-reference.
+ for (int I = 0; I < N; ++I) {
+ copyArg(Array[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (auto I : Array)
+ // CHECK-FIXES-NEXT: copyArg(I);
+
+ for (int I = 0; I < N; ++I) {
+ copyArg(Right[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (auto & I : Right)
+ // CHECK-FIXES-NEXT: copyArg(I);
+
+ // Using as a const reference argument is allowed.
+ for (int I = 0; I < N; ++I) {
+ constRefArg(Array[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (auto I : Array)
+ // CHECK-FIXES-NEXT: constRefArg(I);
+
+ for (int I = 0; I < N; ++I) {
+ if (OtherStr < Array[I])
+ foo();
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (auto I : Array)
+ // CHECK-FIXES-NEXT: if (OtherStr < I)
+
+ for (int I = 0; I < N; ++I) {
+ constRefArg(Right[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (const auto & I : Right)
+ // CHECK-FIXES-NEXT: constRefArg(I);
+
+ // Using as a non-const reference is not.
+ for (int I = 0; I < N; ++I) {
+ nonConstRefArg(Array[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (auto & I : Array)
+ // CHECK-FIXES-NEXT: nonConstRefArg(I);
+ for (int I = 0; I < N; ++I) {
+ nonConstRefArg(Right[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (auto & I : Right)
+ // CHECK-FIXES-NEXT: nonConstRefArg(I);
+ for (int I = 0; I < N; ++I) {
+ if (OtherRight < Right[I])
+ foo();
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (auto & I : Right)
+ // CHECK-FIXES-NEXT: if (OtherRight < I)
+}
+
+void primitiveTypes() {
+ // As argument to a function.
+ for (int I = 0; I < N; ++I) {
+ copyArg(Ints[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (int Int : Ints)
+ // CHECK-FIXES-NEXT: copyArg(Int);
+ for (int I = 0; I < N; ++I) {
+ constRefArg(Ints[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (int Int : Ints)
+ // CHECK-FIXES-NEXT: constRefArg(Int);
+ for (int I = 0; I < N; ++I) {
+ nonConstRefArg(Ints[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (int & Int : Ints)
+ // CHECK-FIXES-NEXT: nonConstRefArg(Int);
+
+ // Builtin operators.
+ // Comparisons.
+ for (int I = 0; I < N; ++I) {
+ if (Ints[I] < N)
+ foo();
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (int Int : Ints)
+ // CHECK-FIXES-NEXT: if (Int < N)
+
+ for (int I = 0; I < N; ++I) {
+ if (N == Ints[I])
+ foo();
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (int Int : Ints)
+ // CHECK-FIXES-NEXT: if (N == Int)
+
+ // Assignment.
+ for (int I = 0; I < N; ++I) {
+ Ints[I] = OtherInt;
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (int & Int : Ints)
+ // CHECK-FIXES-NEXT: Int = OtherInt;
+
+ for (int I = 0; I < N; ++I) {
+ OtherInt = Ints[I];
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (int Int : Ints)
+ // CHECK-FIXES-NEXT: OtherInt = Int;
+
+ for (int I = 0; I < N; ++I) {
+ OtherInt = Ints[I] = OtherInt;
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (int & Int : Ints)
+ // CHECK-FIXES-NEXT: OtherInt = Int = OtherInt;
+
+ // Arithmetic operations.
+ for (int I = 0; I < N; ++I) {
+ OtherInt += Ints[I];
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (int Int : Ints)
+ // CHECK-FIXES-NEXT: OtherInt += Int;
+
+ for (int I = 0; I < N; ++I) {
+ Ints[I] += Ints[I];
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (int & Int : Ints)
+ // CHECK-FIXES-NEXT: Int += Int;
+
+ for (int I = 0; I < N; ++I) {
+ int Res = 5 * (Ints[I] + 1) - Ints[I];
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (int Int : Ints)
+ // CHECK-FIXES-NEXT: int Res = 5 * (Int + 1) - Int;
+}
+
+void takingReferences() {
+ // We do it twice to prevent the check from thinking that they are aliases.
+
+ // Class type.
+ for (int I = 0; I < N; ++I) {
+ Str &J = Array[I];
+ Str &K = Array[I];
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (auto & I : Array)
+ // CHECK-FIXES-NEXT: Str &J = I;
+ // CHECK-FIXES-NEXT: Str &K = I;
+ for (int I = 0; I < N; ++I) {
+ const Str &J = Array[I];
+ const Str &K = Array[I];
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (auto I : Array)
+ // CHECK-FIXES-NEXT: const Str &J = I;
+ // CHECK-FIXES-NEXT: const Str &K = I;
+
+ // Primitive type.
+ for (int I = 0; I < N; ++I) {
+ int &J = Ints[I];
+ int &K = Ints[I];
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (int & Int : Ints)
+ // CHECK-FIXES-NEXT: int &J = Int;
+ // CHECK-FIXES-NEXT: int &K = Int;
+ for (int I = 0; I < N; ++I) {
+ const int &J = Ints[I];
+ const int &K = Ints[I];
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (int Int : Ints)
+ // CHECK-FIXES-NEXT: const int &J = Int;
+ // CHECK-FIXES-NEXT: const int &K = Int;
+
+ // Aliases.
+ for (int I = 0; I < N; ++I) {
+ const Str &J = Array[I];
+ (void)J;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (auto J : Array)
+ for (int I = 0; I < N; ++I) {
+ Str &J = Array[I];
+ (void)J;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (auto & J : Array)
+
+ for (int I = 0; I < N; ++I) {
+ const int &J = Ints[I];
+ (void)J;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (int J : Ints)
+
+ for (int I = 0; I < N; ++I) {
+ int &J = Ints[I];
+ (void)J;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (int & J : Ints)
+}
+
+template <class T>
+struct vector {
+ unsigned size() const;
+ const T &operator[](int) const;
+ T &operator[](int);
+ T *begin();
+ T *end();
+ const T *begin() const;
+ const T *end() const;
+};
+
+// If the elements are already constant, we won't do any ImplicitCast to const.
+void testContainerOfConstIents() {
+ const int Ints[N]{};
+ for (int I = 0; I < N; ++I) {
+ OtherInt -= Ints[I];
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (int Int : Ints)
+
+ vector<const Str> Strs;
+ for (int I = 0; I < Strs.size(); ++I) {
+ Strs[I].constMember(0);
+ constRefArg(Strs[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+ // CHECK-FIXES: for (auto Str : Strs)
+}
+
+// When we are inside a const-qualified member functions, all the data members
+// are implicitly set as const. As before, there won't be any ImplicitCast to
+// const in their usages.
+class TestInsideConstFunction {
+ const static int N = 10;
+ int Ints[N];
+ Str Array[N];
+ vector<int> V;
+
+ void foo() const {
+ for (int I = 0; I < N; ++I) {
+ if (Ints[I])
+ copyArg(Ints[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop
+ // CHECK-FIXES: for (int Int : Ints)
+
+ for (int I = 0; I < N; ++I) {
+ Array[I].constMember(0);
+ constRefArg(Array[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop
+ // CHECK-FIXES: for (auto I : Array)
+
+ for (int I = 0; I < V.size(); ++I) {
+ if (V[I])
+ copyArg(V[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop
+ // CHECK-FIXES: for (int I : V)
+ }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-extra.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-extra.cpp
new file mode 100644
index 0000000..b46ff25
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -0,0 +1,1074 @@
+// RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -std=c++11 -I %S/Inputs/modernize-loop-convert
+
+#include "structures.h"
+
+namespace Dependency {
+
+void f() {
+ const int N = 6;
+ const int M = 8;
+ int Arr[N][M];
+
+ for (int I = 0; I < N; ++I) {
+ int A = 0;
+ int B = Arr[I][A];
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : Arr)
+ // CHECK-FIXES-NEXT: int A = 0;
+ // CHECK-FIXES-NEXT: int B = I[A];
+
+ for (int J = 0; J < M; ++J) {
+ int A = 0;
+ int B = Arr[A][J];
+ }
+}
+
+} // namespace Dependency
+
+namespace NamingAlias {
+
+const int N = 10;
+
+Val Arr[N];
+dependent<Val> V;
+dependent<Val> *Pv;
+Val &func(Val &);
+void sideEffect(int);
+
+void aliasing() {
+ // If the loop container is only used for a declaration of a temporary
+ // variable to hold each element, we can name the new variable for the
+ // converted range-based loop as the temporary variable's name.
+
+ // In the following case, "T" is used as a temporary variable to hold each
+ // element, and thus we consider the name "T" aliased to the loop.
+ // The extra blank braces are left as a placeholder for after the variable
+ // declaration is deleted.
+ for (int I = 0; I < N; ++I) {
+ Val &T = Arr[I];
+ {}
+ int Y = T.X;
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & T : Arr)
+ // CHECK-FIXES-NOT: Val &{{[a-z_]+}} =
+ // CHECK-FIXES-NEXT: {}
+ // CHECK-FIXES-NEXT: int Y = T.X;
+
+ // The container was not only used to initialize a temporary loop variable for
+ // the container's elements, so we do not alias the new loop variable.
+ for (int I = 0; I < N; ++I) {
+ Val &T = Arr[I];
+ int Y = T.X;
+ int Z = Arr[I].X + T.X;
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : Arr)
+ // CHECK-FIXES-NEXT: Val &T = I;
+ // CHECK-FIXES-NEXT: int Y = T.X;
+ // CHECK-FIXES-NEXT: int Z = I.X + T.X;
+
+ for (int I = 0; I < N; ++I) {
+ Val T = Arr[I];
+ int Y = T.X;
+ int Z = Arr[I].X + T.X;
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : Arr)
+ // CHECK-FIXES-NEXT: Val T = I;
+ // CHECK-FIXES-NEXT: int Y = T.X;
+ // CHECK-FIXES-NEXT: int Z = I.X + T.X;
+
+ // The same for pseudo-arrays like std::vector<T> (or here dependent<Val>)
+ // which provide a subscript operator[].
+ for (int I = 0; I < V.size(); ++I) {
+ Val &T = V[I];
+ {}
+ int Y = T.X;
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & T : V)
+ // CHECK-FIXES-NEXT: {}
+ // CHECK-FIXES-NEXT: int Y = T.X;
+
+ // The same with a call to at()
+ for (int I = 0; I < Pv->size(); ++I) {
+ Val &T = Pv->at(I);
+ {}
+ int Y = T.X;
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & T : *Pv)
+ // CHECK-FIXES-NEXT: {}
+ // CHECK-FIXES-NEXT: int Y = T.X;
+
+ for (int I = 0; I < N; ++I) {
+ Val &T = func(Arr[I]);
+ int Y = T.X;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : Arr)
+ // CHECK-FIXES-NEXT: Val &T = func(I);
+ // CHECK-FIXES-NEXT: int Y = T.X;
+
+ int IntArr[N];
+ for (unsigned I = 0; I < N; ++I) {
+ if (int Alias = IntArr[I]) {
+ sideEffect(Alias);
+ }
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int Alias : IntArr)
+ // CHECK-FIXES-NEXT: if (Alias)
+
+ for (unsigned I = 0; I < N; ++I) {
+ while (int Alias = IntArr[I]) {
+ sideEffect(Alias);
+ }
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int Alias : IntArr)
+ // CHECK-FIXES-NEXT: while (Alias)
+
+ for (unsigned I = 0; I < N; ++I) {
+ switch (int Alias = IntArr[I]) {
+ default:
+ sideEffect(Alias);
+ }
+ }
+ // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int Alias : IntArr)
+ // CHECK-FIXES-NEXT: switch (Alias)
+
+ for (unsigned I = 0; I < N; ++I) {
+ for (int Alias = IntArr[I]; Alias < N; ++Alias) {
+ sideEffect(Alias);
+ }
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int Alias : IntArr)
+ // CHECK-FIXES-NEXT: for (; Alias < N; ++Alias)
+
+ for (unsigned I = 0; I < N; ++I) {
+ for (unsigned J = 0; int Alias = IntArr[I]; ++J) {
+ sideEffect(Alias);
+ }
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int Alias : IntArr)
+ // CHECK-FIXES-NEXT: for (unsigned J = 0; Alias; ++J)
+
+ struct IntRef { IntRef(); IntRef(const int& i); operator int*(); };
+ for (int I = 0; I < N; ++I) {
+ IntRef Int(IntArr[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : IntArr)
+ // CHECK-FIXES-NEXT: IntRef Int(I);
+
+ int *PtrArr[N];
+ for (unsigned I = 0; I < N; ++I) {
+ const int* const P = PtrArr[I];
+ printf("%d\n", *P);
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto P : PtrArr)
+ // CHECK-FIXES-NEXT: printf("%d\n", *P);
+
+ IntRef Refs[N];
+ for (unsigned I = 0; I < N; ++I) {
+ int *P = Refs[I];
+ printf("%d\n", *P);
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & Ref : Refs)
+ // CHECK-FIXES-NEXT: int *P = Ref;
+ // CHECK-FIXES-NEXT: printf("%d\n", *P);
+
+ // Ensure that removing the alias doesn't leave empty lines behind.
+ for (int I = 0; I < N; ++I) {
+ auto &X = IntArr[I];
+ X = 0;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & X : IntArr) {
+ // CHECK-FIXES-NEXT: {{^ X = 0;$}}
+ // CHECK-FIXES-NEXT: {{^ }$}}
+}
+
+void refs_and_vals() {
+ // The following tests check that the transform correctly preserves the
+ // reference or value qualifiers of the aliased variable. That is, if the
+ // variable was declared as a value, the loop variable will be declared as a
+ // value and vice versa for references.
+
+ S Ss;
+ const S S_const = Ss;
+
+ for (S::const_iterator It = S_const.begin(); It != S_const.end(); ++It) {
+ MutableVal Alias = *It;
+ {}
+ Alias.X = 0;
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto Alias : S_const)
+ // CHECK-FIXES-NOT: MutableVal {{[a-z_]+}} =
+ // CHECK-FIXES-NEXT: {}
+ // CHECK-FIXES-NEXT: Alias.X = 0;
+
+ for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
+ MutableVal Alias = *It;
+ {}
+ Alias.X = 0;
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto Alias : Ss)
+ // CHECK-FIXES-NOT: MutableVal {{[a-z_]+}} =
+ // CHECK-FIXES-NEXT: {}
+ // CHECK-FIXES-NEXT: Alias.X = 0;
+
+ for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
+ MutableVal &Alias = *It;
+ {}
+ Alias.X = 0;
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & Alias : Ss)
+ // CHECK-FIXES-NOT: MutableVal &{{[a-z_]+}} =
+ // CHECK-FIXES-NEXT: {}
+ // CHECK-FIXES-NEXT: Alias.X = 0;
+
+ dependent<int> Dep, Other;
+ for (dependent<int>::iterator It = Dep.begin(), E = Dep.end(); It != E; ++It) {
+ printf("%d\n", *It);
+ const int& Idx = Other[0];
+ unsigned Othersize = Other.size();
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & It : Dep)
+ // CHECK-FIXES-NEXT: printf("%d\n", It);
+ // CHECK-FIXES-NEXT: const int& Idx = Other[0];
+ // CHECK-FIXES-NEXT: unsigned Othersize = Other.size();
+
+ for (int i = 0; i < Other.size(); ++i) {
+ Other.at(i);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & i : Other)
+ // CHECK-FIXES: i;
+
+ for (int I = 0, E = Dep.size(); I != E; ++I) {
+ int Idx = Other.at(I);
+ Other.at(I, I); // Should not trigger assert failure.
+ }
+}
+
+struct MemberNaming {
+ const static int N = 10;
+ int Ints[N], Ints_[N];
+ dependent<int> DInts;
+ void loops() {
+ for (int I = 0; I < N; ++I) {
+ printf("%d\n", Ints[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int Int : Ints)
+ // CHECK-FIXES-NEXT: printf("%d\n", Int);
+
+ for (int I = 0; I < N; ++I) {
+ printf("%d\n", Ints_[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int Int : Ints_)
+ // CHECK-FIXES-NEXT: printf("%d\n", Int);
+
+ for (int I = 0; I < DInts.size(); ++I) {
+ printf("%d\n", DInts[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int DInt : DInts)
+ // CHECK-FIXES-NEXT: printf("%d\n", DInt);
+ }
+
+ void outOfLine();
+};
+void MemberNaming::outOfLine() {
+ for (int I = 0; I < N; ++I) {
+ printf("%d\n", Ints[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int Int : Ints)
+ // CHECK-FIXES-NEXT: printf("%d\n", Int);
+
+ for (int I = 0; I < N; ++I) {
+ printf("%d\n", Ints_[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int Int : Ints_)
+ // CHECK-FIXES-NEXT: printf("%d\n", Int);
+}
+
+} // namespace NamingAlias
+
+namespace NamingConlict {
+
+#define MAX(a, b) (a > b) ? a : b
+#define DEF 5
+
+const int N = 10;
+int Nums[N];
+int Sum = 0;
+
+namespace ns {
+struct St {
+ int X;
+};
+}
+
+void sameNames() {
+ int Num = 0;
+ for (int I = 0; I < N; ++I) {
+ printf("Fibonacci number is %d\n", Nums[I]);
+ Sum += Nums[I] + 2 + Num;
+ (void)Nums[I];
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & I : Nums)
+ // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
+ // CHECK-FIXES-NEXT: Sum += I + 2 + Num;
+ // CHECK-FIXES-NEXT: (void)I;
+
+ int Elem = 0;
+ for (int I = 0; I < N; ++I) {
+ printf("Fibonacci number is %d\n", Nums[I]);
+ Sum += Nums[I] + 2 + Num + Elem;
+ (void)Nums[I];
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & I : Nums)
+ // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
+ // CHECK-FIXES-NEXT: Sum += I + 2 + Num + Elem;
+ // CHECK-FIXES-NEXT: (void)I;
+}
+
+void oldIndexConflict() {
+ for (int Num = 0; Num < N; ++Num) {
+ printf("Num: %d\n", Nums[Num]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int Num : Nums)
+ // CHECK-FIXES-NEXT: printf("Num: %d\n", Num);
+
+ S Things;
+ for (S::iterator Thing = Things.begin(), End = Things.end(); Thing != End; ++Thing) {
+ printf("Thing: %d %d\n", Thing->X, (*Thing).X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & Thing : Things)
+ // CHECK-FIXES-NEXT: printf("Thing: %d %d\n", Thing.X, Thing.X);
+}
+
+void macroConflict() {
+ S MAXs;
+ for (S::iterator It = MAXs.begin(), E = MAXs.end(); It != E; ++It) {
+ printf("s has value %d\n", (*It).X);
+ printf("Max of 3 and 5: %d\n", MAX(3, 5));
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : MAXs)
+ // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+ // CHECK-FIXES-NEXT: printf("Max of 3 and 5: %d\n", MAX(3, 5));
+
+ for (S::const_iterator It = MAXs.begin(), E = MAXs.end(); It != E; ++It) {
+ printf("s has value %d\n", (*It).X);
+ printf("Max of 3 and 5: %d\n", MAX(3, 5));
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto It : MAXs)
+ // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+ // CHECK-FIXES-NEXT: printf("Max of 3 and 5: %d\n", MAX(3, 5));
+
+ T DEFs;
+ for (T::iterator It = DEFs.begin(), E = DEFs.end(); It != E; ++It) {
+ if (*It == DEF) {
+ printf("I found %d\n", *It);
+ }
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & It : DEFs)
+ // CHECK-FIXES-NEXT: if (It == DEF)
+ // CHECK-FIXES-NEXT: printf("I found %d\n", It);
+}
+
+void keywordConflict() {
+ T ints;
+ for (T::iterator It = ints.begin(), E = ints.end(); It != E; ++It) {
+ *It = 5;
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & It : ints)
+ // CHECK-FIXES-NEXT: It = 5;
+
+ U __FUNCTION__s;
+ for (U::iterator It = __FUNCTION__s.begin(), E = __FUNCTION__s.end();
+ It != E; ++It) {
+ int __FUNCTION__s_It = (*It).X + 2;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : __FUNCTION__s)
+ // CHECK-FIXES-NEXT: int __FUNCTION__s_It = It.X + 2;
+}
+
+void typeConflict() {
+ T Vals;
+ // Using the name "Val", although it is the name of an existing struct, is
+ // safe in this loop since it will only exist within this scope.
+ for (T::iterator It = Vals.begin(), E = Vals.end(); It != E; ++It)
+ (void) *It;
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & Val : Vals)
+
+ // We cannot use the name "Val" in this loop since there is a reference to
+ // it in the body of the loop.
+ for (T::iterator It = Vals.begin(), E = Vals.end(); It != E; ++It) {
+ *It = sizeof(Val);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & It : Vals)
+ // CHECK-FIXES-NEXT: It = sizeof(Val);
+
+ typedef struct Val TD;
+ U TDs;
+ // Naming the variable "TD" within this loop is safe because the typedef
+ // was never used within the loop.
+ for (U::iterator It = TDs.begin(), E = TDs.end(); It != E; ++It)
+ (void) *It;
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & TD : TDs)
+
+ // "TD" cannot be used in this loop since the typedef is being used.
+ for (U::iterator It = TDs.begin(), E = TDs.end(); It != E; ++It) {
+ TD V;
+ V.X = 5;
+ (void) *It;
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : TDs)
+ // CHECK-FIXES-NEXT: TD V;
+ // CHECK-FIXES-NEXT: V.X = 5;
+
+ using ns::St;
+ T Sts;
+ for (T::iterator It = Sts.begin(), E = Sts.end(); It != E; ++It) {
+ *It = sizeof(St);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & It : Sts)
+ // CHECK-FIXES-NEXT: It = sizeof(St);
+}
+
+} // namespace NamingConflict
+
+namespace FreeBeginEnd {
+
+// FIXME: Loop Convert should detect free begin()/end() functions.
+
+struct MyArray {
+ unsigned size();
+};
+
+template <typename T>
+struct MyContainer {
+};
+
+int *begin(const MyArray &Arr);
+int *end(const MyArray &Arr);
+
+template <typename T>
+T *begin(const MyContainer<T> &C);
+template <typename T>
+T *end(const MyContainer<T> &C);
+
+// The Loop Convert Transform doesn't detect free functions begin()/end() and
+// so fails to transform these cases which it should.
+void f() {
+ MyArray Arr;
+ for (unsigned I = 0, E = Arr.size(); I < E; ++I) {
+ }
+
+ MyContainer<int> C;
+ for (int *I = begin(C), *E = end(C); I != E; ++I) {
+ }
+}
+
+} // namespace FreeBeginEnd
+
+namespace Nesting {
+
+void g(S::iterator It);
+void const_g(S::const_iterator It);
+class Foo {
+ public:
+ void g(S::iterator It);
+ void const_g(S::const_iterator It);
+};
+
+void f() {
+ const int N = 10;
+ const int M = 15;
+ Val Arr[N];
+ for (int I = 0; I < N; ++I) {
+ for (int J = 0; J < N; ++J) {
+ int K = Arr[I].X + Arr[J].X;
+ // The repeat is there to allow FileCheck to make sure the two variable
+ // names aren't the same.
+ int L = Arr[I].X + Arr[J].X;
+ }
+ }
+ // CHECK-MESSAGES: :[[@LINE-8]]:3: warning: use range-based for loop instead
+ // CHECK-MESSAGES: :[[@LINE-8]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : Arr)
+ // CHECK-FIXES-NEXT: for (auto & J : Arr)
+ // CHECK-FIXES-NEXT: int K = I.X + J.X;
+ // CHECK-FIXES-NOT: int L = I.X + I.X;
+
+ // The inner loop is also convertible, but doesn't need to be converted
+ // immediately. FIXME: update this test when that changes.
+ Val Nest[N][M];
+ for (int I = 0; I < N; ++I) {
+ for (int J = 0; J < M; ++J) {
+ printf("Got item %d", Nest[I][J].X);
+ }
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : Nest)
+ // CHECK-FIXES-NEXT: for (int J = 0; J < M; ++J)
+ // CHECK-FIXES-NEXT: printf("Got item %d", I[J].X);
+
+ // Note that the order of M and N are switched for this test.
+ for (int J = 0; J < M; ++J) {
+ for (int I = 0; I < N; ++I) {
+ printf("Got item %d", Nest[I][J].X);
+ }
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop instead
+ // CHECK-FIXES-NOT: for (auto & {{[a-zA-Z_]+}} : Nest[I])
+ // CHECK-FIXES: for (int J = 0; J < M; ++J)
+ // CHECK-FIXES-NEXT: for (auto & I : Nest)
+ // CHECK-FIXES-NEXT: printf("Got item %d", I[J].X);
+
+ // The inner loop is also convertible.
+ Nested<T> NestT;
+ for (Nested<T>::iterator I = NestT.begin(), E = NestT.end(); I != E; ++I) {
+ for (T::iterator TI = (*I).begin(), TE = (*I).end(); TI != TE; ++TI) {
+ printf("%d", *TI);
+ }
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : NestT)
+ // CHECK-FIXES-NEXT: for (T::iterator TI = I.begin(), TE = I.end(); TI != TE; ++TI)
+ // CHECK-FIXES-NEXT: printf("%d", *TI);
+
+ // The inner loop is also convertible.
+ Nested<S> NestS;
+ for (Nested<S>::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
+ for (S::const_iterator SI = (*I).begin(), SE = (*I).end(); SI != SE; ++SI) {
+ printf("%d", *SI);
+ }
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto I : NestS)
+ // CHECK-FIXES-NEXT: for (S::const_iterator SI = I.begin(), SE = I.end(); SI != SE; ++SI)
+ // CHECK-FIXES-NEXT: printf("%d", *SI);
+
+ for (Nested<S>::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
+ const S &Ss = *I;
+ for (S::const_iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI) {
+ printf("%d", *SI);
+ const_g(SI);
+ }
+ }
+ // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto Ss : NestS)
+
+ for (Nested<S>::iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
+ S &Ss = *I;
+ for (S::iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI) {
+ printf("%d", *SI);
+ g(SI);
+ }
+ }
+ // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & Ss : NestS)
+
+ Foo foo;
+ for (Nested<S>::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
+ const S &Ss = *I;
+ for (S::const_iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI) {
+ printf("%d", *SI);
+ foo.const_g(SI);
+ }
+ }
+ // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto Ss : NestS)
+
+ for (Nested<S>::iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
+ S &Ss = *I;
+ for (S::iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI) {
+ printf("%d", *SI);
+ foo.g(SI);
+ }
+ }
+ // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & Ss : NestS)
+
+}
+
+} // namespace Nesting
+
+namespace SingleIterator {
+
+void complexContainer() {
+ X Exes[5];
+ int Index = 0;
+
+ for (S::iterator I = Exes[Index].getS().begin(), E = Exes[Index].getS().end(); I != E; ++I) {
+ MutableVal K = *I;
+ MutableVal J = *I;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : Exes[Index].getS())
+ // CHECK-FIXES-NEXT: MutableVal K = I;
+ // CHECK-FIXES-NEXT: MutableVal J = I;
+}
+
+void f() {
+ /// begin()/end() - based for loops here:
+ T Tt;
+ for (T::iterator It = Tt.begin(); It != Tt.end(); ++It) {
+ printf("I found %d\n", *It);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & It : Tt)
+ // CHECK-FIXES-NEXT: printf("I found %d\n", It);
+
+ T *Pt;
+ for (T::iterator It = Pt->begin(); It != Pt->end(); ++It) {
+ printf("I found %d\n", *It);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & It : *Pt)
+ // CHECK-FIXES-NEXT: printf("I found %d\n", It);
+
+ S Ss;
+ for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {
+ printf("s has value %d\n", (*It).X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : Ss)
+ // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+ S *Ps;
+ for (S::iterator It = Ps->begin(); It != Ps->end(); ++It) {
+ printf("s has value %d\n", (*It).X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & P : *Ps)
+ // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
+
+ for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {
+ printf("s has value %d\n", It->X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : Ss)
+ // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+ for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {
+ It->X = 3;
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : Ss)
+ // CHECK-FIXES-NEXT: It.X = 3;
+
+ for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {
+ (*It).X = 3;
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : Ss)
+ // CHECK-FIXES-NEXT: It.X = 3;
+
+ for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {
+ It->nonConstFun(4, 5);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : Ss)
+ // CHECK-FIXES-NEXT: It.nonConstFun(4, 5);
+
+ U Uu;
+ for (U::iterator It = Uu.begin(); It != Uu.end(); ++It) {
+ printf("s has value %d\n", It->X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : Uu)
+ // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+ for (U::iterator It = Uu.begin(); It != Uu.end(); ++It) {
+ printf("s has value %d\n", (*It).X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : Uu)
+ // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+ U::iterator A;
+ for (U::iterator I = Uu.begin(); I != Uu.end(); ++I)
+ int K = A->X + I->X;
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & I : Uu)
+ // CHECK-FIXES-NEXT: int K = A->X + I.X;
+
+ dependent<int> V;
+ for (dependent<int>::iterator It = V.begin();
+ It != V.end(); ++It) {
+ printf("Fibonacci number is %d\n", *It);
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & It : V)
+ // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
+
+ for (dependent<int>::iterator It(V.begin());
+ It != V.end(); ++It) {
+ printf("Fibonacci number is %d\n", *It);
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & It : V)
+ // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
+
+ doublyDependent<int, int> intmap;
+ for (doublyDependent<int, int>::iterator It = intmap.begin();
+ It != intmap.end(); ++It) {
+ printf("intmap[%d] = %d", It->first, It->second);
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & It : intmap)
+ // CHECK-FIXES-NEXT: printf("intmap[%d] = %d", It.first, It.second);
+}
+
+void different_type() {
+ // Tests to verify the proper use of auto where the init variable type and the
+ // initializer type differ or are mostly the same except for const qualifiers.
+
+ // Ss.begin() returns a type 'iterator' which is just a non-const pointer and
+ // differs from const_iterator only on the const qualification.
+ S Ss;
+ for (S::const_iterator It = Ss.begin(); It != Ss.end(); ++It) {
+ printf("s has value %d\n", (*It).X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto It : Ss)
+ // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+ S *Ps;
+ for (S::const_iterator It = Ps->begin(); It != Ps->end(); ++It) {
+ printf("s has value %d\n", (*It).X);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto P : *Ps)
+ // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
+
+ // V.begin() returns a user-defined type 'iterator' which, since it's
+ // different from const_iterator, disqualifies these loops from
+ // transformation.
+ dependent<int> V;
+ for (dependent<int>::const_iterator It = V.begin(); It != V.end(); ++It) {
+ printf("Fibonacci number is %d\n", *It);
+ }
+
+ for (dependent<int>::const_iterator It(V.begin()); It != V.end(); ++It) {
+ printf("Fibonacci number is %d\n", *It);
+ }
+}
+
+} // namespace SingleIterator
+
+
+namespace Macros {
+
+#define TWO_PARAM(x, y) if (x == y) {}
+#define THREE_PARAM(x, y, z) if (x == y) {z;}
+
+const int N = 10;
+int Arr[N];
+
+void messing_with_macros() {
+ for (int I = 0; I < N; ++I) {
+ printf("Value: %d\n", Arr[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : Arr)
+ // CHECK-FIXES-NEXT: printf("Value: %d\n", I);
+
+ for (int I = 0; I < N; ++I) {
+ printf("Value: %d\n", CONT Arr[I]);
+ }
+
+ // Multiple macro arguments.
+ for (int I = 0; I < N; ++I) {
+ TWO_PARAM(Arr[I], Arr[I]);
+ THREE_PARAM(Arr[I], Arr[I], Arr[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & I : Arr)
+ // CHECK-FIXES-NEXT: TWO_PARAM(I, I);
+ // CHECK-FIXES-NEXT: THREE_PARAM(I, I, I);
+}
+
+} // namespace Macros
+
+namespace Templates {
+
+template <class Container>
+void set_union(Container &container) {
+ for (typename Container::const_iterator SI = container.begin(),
+ SE = container.end(); SI != SE; ++SI) {
+ (void) *SI;
+ }
+
+ S Ss;
+ for (S::iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI)
+ (void) *SI;
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (auto & SI : Ss)
+}
+
+void template_instantiation() {
+ S Ss;
+ set_union(Ss);
+}
+
+} // namespace Templates
+
+namespace Lambdas {
+
+void capturesIndex() {
+ const int N = 10;
+ int Arr[N];
+ // FIXME: the next four loops could be convertible, if the capture list is
+ // also changed.
+
+ for (int I = 0; I < N; ++I)
+ auto F1 = [Arr, I]() { int R1 = Arr[I] + 1; };
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : Arr)
+ // CHECK-FIXES-NEXT: auto F1 = [Arr, &I]() { int R1 = I + 1; };
+
+ for (int I = 0; I < N; ++I)
+ auto F2 = [Arr, &I]() { int R2 = Arr[I] + 3; };
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : Arr)
+ // CHECK-FIXES-NEXT: auto F2 = [Arr, &I]() { int R2 = I + 3; };
+
+ // FIXME: alias don't work if the index is captured.
+ // Alias declared inside lambda (by value).
+ for (int I = 0; I < N; ++I)
+ auto F3 = [&Arr, I]() { int R3 = Arr[I]; };
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : Arr)
+ // CHECK-FIXES-NEXT: auto F3 = [&Arr, &I]() { int R3 = I; };
+
+
+ for (int I = 0; I < N; ++I)
+ auto F4 = [&Arr, &I]() { int R4 = Arr[I]; };
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : Arr)
+ // CHECK-FIXES-NEXT: auto F4 = [&Arr, &I]() { int R4 = I; };
+
+ // Alias declared inside lambda (by reference).
+ for (int I = 0; I < N; ++I)
+ auto F5 = [&Arr, I]() { int &R5 = Arr[I]; };
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & I : Arr)
+ // CHECK-FIXES-NEXT: auto F5 = [&Arr, &I]() { int &R5 = I; };
+
+
+ for (int I = 0; I < N; ++I)
+ auto F6 = [&Arr, &I]() { int &R6 = Arr[I]; };
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & I : Arr)
+ // CHECK-FIXES-NEXT: auto F6 = [&Arr, &I]() { int &R6 = I; };
+
+ for (int I = 0; I < N; ++I) {
+ auto F = [Arr, I](int k) {
+ printf("%d\n", Arr[I] + k);
+ };
+ F(Arr[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : Arr)
+ // CHECK-FIXES-NEXT: auto F = [Arr, &I](int k)
+ // CHECK-FIXES-NEXT: printf("%d\n", I + k);
+ // CHECK-FIXES: F(I);
+}
+
+void implicitCapture() {
+ const int N = 10;
+ int Arr[N];
+ // Index is used, not convertible.
+ for (int I = 0; I < N; ++I) {
+ auto G1 = [&]() {
+ int R = Arr[I];
+ int J = I;
+ };
+ }
+
+ for (int I = 0; I < N; ++I) {
+ auto G2 = [=]() {
+ int R = Arr[I];
+ int J = I;
+ };
+ }
+
+ // Convertible.
+ for (int I = 0; I < N; ++I) {
+ auto G3 = [&]() {
+ int R3 = Arr[I];
+ int J3 = Arr[I] + R3;
+ };
+ }
+ // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : Arr)
+ // CHECK-FIXES-NEXT: auto G3 = [&]()
+ // CHECK-FIXES-NEXT: int R3 = I;
+ // CHECK-FIXES-NEXT: int J3 = I + R3;
+
+ for (int I = 0; I < N; ++I) {
+ auto G4 = [=]() {
+ int R4 = Arr[I] + 5;
+ };
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : Arr)
+ // CHECK-FIXES-NEXT: auto G4 = [=]()
+ // CHECK-FIXES-NEXT: int R4 = I + 5;
+
+ // Alias by value.
+ for (int I = 0; I < N; ++I) {
+ auto G5 = [&]() {
+ int R5 = Arr[I];
+ int J5 = 8 + R5;
+ };
+ }
+ // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int R5 : Arr)
+ // CHECK-FIXES-NEXT: auto G5 = [&]()
+ // CHECK-FIXES-NEXT: int J5 = 8 + R5;
+
+ // Alias by reference.
+ for (int I = 0; I < N; ++I) {
+ auto G6 = [&]() {
+ int &R6 = Arr[I];
+ int J6 = -1 + R6;
+ };
+ }
+ // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & R6 : Arr)
+ // CHECK-FIXES-NEXT: auto G6 = [&]()
+ // CHECK-FIXES-NEXT: int J6 = -1 + R6;
+}
+
+void iterators() {
+ dependent<int> Dep;
+
+ for (dependent<int>::iterator I = Dep.begin(), E = Dep.end(); I != E; ++I)
+ auto H1 = [&I]() { int R = *I; };
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & I : Dep)
+ // CHECK-FIXES-NEXT: auto H1 = [&I]() { int R = I; };
+
+ for (dependent<int>::iterator I = Dep.begin(), E = Dep.end(); I != E; ++I)
+ auto H2 = [&]() { int R = *I + 2; };
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & I : Dep)
+ // CHECK-FIXES-NEXT: auto H2 = [&]() { int R = I + 2; };
+
+ // FIXME: It doesn't work with const iterators.
+ for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
+ I != E; ++I)
+ auto H3 = [I]() { int R = *I; };
+
+ for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
+ I != E; ++I)
+ auto H4 = [&]() { int R = *I + 1; };
+
+ for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
+ I != E; ++I)
+ auto H5 = [=]() { int R = *I; };
+}
+
+void captureByValue() {
+ // When the index is captured by value, we should replace this by a capture
+ // by reference. This avoids extra copies.
+ // FIXME: this could change semantics on array or pseudoarray loops if the
+ // container is captured by copy.
+ const int N = 10;
+ int Arr[N];
+ dependent<int> Dep;
+
+ for (int I = 0; I < N; ++I) {
+ auto C1 = [&Arr, I]() { if (Arr[I] == 1); };
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : Arr)
+ // CHECK-FIXES-NEXT: auto C1 = [&Arr, &I]() { if (I == 1); };
+
+ for (unsigned I = 0; I < Dep.size(); ++I) {
+ auto C2 = [&Dep, I]() { if (Dep[I] == 2); };
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : Dep)
+ // CHECK-FIXES-NEXT: auto C2 = [&Dep, &I]() { if (I == 2); };
+}
+
+} // namespace Lambdas
+
+namespace InitLists {
+
+struct D { int Ii; };
+struct E { D Dd; };
+int g(int B);
+
+void f() {
+ const unsigned N = 3;
+ int Array[N];
+
+ // Subtrees of InitListExpr are visited twice. Test that we do not do repeated
+ // replacements.
+ for (unsigned I = 0; I < N; ++I) {
+ int A{ Array[I] };
+ int B{ g(Array[I]) };
+ int C{ g( { Array[I] } ) };
+ D Dd{ { g( { Array[I] } ) } };
+ E Ee{ { { g( { Array[I] } ) } } };
+ }
+ // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : Array)
+ // CHECK-FIXES-NEXT: int A{ I };
+ // CHECK-FIXES-NEXT: int B{ g(I) };
+ // CHECK-FIXES-NEXT: int C{ g( { I } ) };
+ // CHECK-FIXES-NEXT: D Dd{ { g( { I } ) } };
+ // CHECK-FIXES-NEXT: E Ee{ { { g( { I } ) } } };
+}
+
+} // namespace InitLists
+
+void bug28341() {
+ char v[5];
+ for(int i = 0; i < 5; ++i) {
+ unsigned char value = v[i];
+ if (value > 127)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for(unsigned char value : v)
+ // CHECK-FIXES-NEXT: if (value > 127)
+ }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-lowercase.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-lowercase.cpp
new file mode 100644
index 0000000..c7bb221
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-lowercase.cpp
@@ -0,0 +1,41 @@
+// RUN: %check_clang_tidy %s modernize-loop-convert %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-loop-convert.NamingStyle, value: 'lower_case'}]}" \
+// RUN: -- -std=c++11 -I %S/Inputs/modernize-loop-convert
+
+#include "structures.h"
+
+const int n = 10;
+int arr[n];
+int nums[n];
+int nums_[n];
+
+void naming() {
+ for (int i = 0; i < n; ++i) {
+ printf("%d\n", arr[i]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]
+ // CHECK-FIXES: for (int i : arr)
+ // CHECK-FIXES-NEXT: printf("%d\n", i);
+
+ for (int i = 0; i < n; ++i) {
+ printf("%d\n", nums[i]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int num : nums)
+ // CHECK-FIXES-NEXT: printf("%d\n", num);
+
+ for (int i = 0; i < n; ++i) {
+ printf("%d\n", nums_[i]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int num : nums_)
+ // CHECK-FIXES-NEXT: printf("%d\n", num);
+
+ int num = 0;
+ for (int i = 0; i < n; ++i) {
+ printf("%d\n", nums[i] + num);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int i : nums)
+ // CHECK-FIXES-NEXT: printf("%d\n", i + num);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-negative.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-negative.cpp
new file mode 100644
index 0000000..c038437
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-negative.cpp
@@ -0,0 +1,485 @@
+// RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -std=c++11 -I %S/Inputs/modernize-loop-convert
+
+#include "structures.h"
+
+// CHECK-FIXES-NOT: for ({{.*[^:]:[^:].*}})
+// CHECK-MESSAGES-NOT: modernize-loop-convert
+
+namespace Negative {
+
+const int N = 6;
+int Arr[N] = {1, 2, 3, 4, 5, 6};
+int (*pArr)[N] = &Arr;
+int Sum = 0;
+
+// Checks for the Index start and end:
+void IndexStartAndEnd() {
+ for (int I = 0; I < N + 1; ++I)
+ Sum += Arr[I];
+
+ for (int I = 0; I < N - 1; ++I)
+ Sum += Arr[I];
+
+ for (int I = 1; I < N; ++I)
+ Sum += Arr[I];
+
+ for (int I = 1; I < N; ++I)
+ Sum += Arr[I];
+
+ for (int I = 0;; ++I)
+ Sum += (*pArr)[I];
+}
+
+// Checks for invalid increment steps:
+void increment() {
+ for (int I = 0; I < N; --I)
+ Sum += Arr[I];
+
+ for (int I = 0; I < N; I)
+ Sum += Arr[I];
+
+ for (int I = 0; I < N;)
+ Sum += Arr[I];
+
+ for (int I = 0; I < N; I += 2)
+ Sum++;
+}
+
+// Checks to make sure that the Index isn't used outside of the array:
+void IndexUse() {
+ for (int I = 0; I < N; ++I)
+ Arr[I] += 1 + I;
+}
+
+// Check for loops that don't mention arrays
+void noArray() {
+ for (int I = 0; I < N; ++I)
+ Sum += I;
+
+ for (int I = 0; I < N; ++I) {
+ }
+
+ for (int I = 0; I < N; ++I)
+ ;
+}
+
+// Checks for incorrect loop variables.
+void mixedVariables() {
+ int BadIndex;
+ for (int I = 0; BadIndex < N; ++I)
+ Sum += Arr[I];
+
+ for (int I = 0; I < N; ++BadIndex)
+ Sum += Arr[I];
+
+ for (int I = 0; BadIndex < N; ++BadIndex)
+ Sum += Arr[I];
+
+ for (int I = 0; BadIndex < N; ++BadIndex)
+ Sum += Arr[BadIndex];
+}
+
+// Checks for multiple arrays Indexed.
+void multipleArrays() {
+ int BadArr[N];
+
+ for (int I = 0; I < N; ++I)
+ Sum += Arr[I] + BadArr[I];
+
+ for (int I = 0; I < N; ++I) {
+ int K = BadArr[I];
+ Sum += Arr[I] + K;
+ }
+}
+
+}
+
+namespace NegativeIterator {
+
+S Ss;
+T Tt;
+U Tu;
+
+struct BadBeginEnd : T {
+ iterator notBegin();
+ iterator notEnd();
+};
+
+void notBeginOrEnd() {
+ BadBeginEnd Bad;
+ for (T::iterator I = Bad.notBegin(), E = Bad.end(); I != E; ++I)
+ int K = *I;
+
+ for (T::iterator I = Bad.begin(), E = Bad.notEnd(); I != E; ++I)
+ int K = *I;
+}
+
+void badLoopShapes() {
+ for (T::iterator I = Tt.begin(), E = Tt.end(), F = E; I != E; ++I)
+ int K = *I;
+
+ for (T::iterator I = Tt.begin(), E = Tt.end(); I != E;)
+ int K = *I;
+
+ for (T::iterator I = Tt.begin(), E = Tt.end();; ++I)
+ int K = *I;
+
+ T::iterator OutsideI;
+ T::iterator OutsideE;
+
+ for (; OutsideI != OutsideE; ++OutsideI)
+ int K = *OutsideI;
+}
+
+void iteratorArrayMix() {
+ int Lower;
+ const int N = 6;
+ for (T::iterator I = Tt.begin(), E = Tt.end(); Lower < N; ++I)
+ int K = *I;
+
+ for (T::iterator I = Tt.begin(), E = Tt.end(); Lower < N; ++Lower)
+ int K = *I;
+}
+
+struct ExtraConstructor : T::iterator {
+ ExtraConstructor(T::iterator, int);
+ explicit ExtraConstructor(T::iterator);
+};
+
+void badConstructor() {
+ for (T::iterator I = ExtraConstructor(Tt.begin(), 0), E = Tt.end();
+ I != E; ++I)
+ int K = *I;
+ for (T::iterator I = ExtraConstructor(Tt.begin()), E = Tt.end(); I != E; ++I)
+ int K = *I;
+}
+
+void foo(S::iterator It) {}
+class Foo {public: void bar(S::iterator It); };
+Foo Fo;
+
+void iteratorUsed() {
+ for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)
+ foo(I);
+
+ for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)
+ Fo.bar(I);
+
+ S::iterator Ret;
+ for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)
+ Ret = I;
+}
+
+void iteratorMemberUsed() {
+ for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)
+ I.X = *I;
+
+ for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)
+ int K = I.X + *I;
+
+ for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)
+ int K = E.X + *I;
+}
+
+void iteratorMethodCalled() {
+ for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)
+ I.insert(3);
+
+ for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)
+ if (I != I)
+ int K = 3;
+}
+
+void iteratorOperatorCalled() {
+ for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)
+ int K = *(++I);
+
+ for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)
+ MutableVal K = *(++I);
+}
+
+void differentContainers() {
+ T Other;
+ for (T::iterator I = Tt.begin(), E = Other.end(); I != E; ++I)
+ int K = *I;
+
+ for (T::iterator I = Other.begin(), E = Tt.end(); I != E; ++I)
+ int K = *I;
+
+ S OtherS;
+ for (S::iterator I = Ss.begin(), E = OtherS.end(); I != E; ++I)
+ MutableVal K = *I;
+
+ for (S::iterator I = OtherS.begin(), E = Ss.end(); I != E; ++I)
+ MutableVal K = *I;
+}
+
+void wrongIterators() {
+ T::iterator Other;
+ for (T::iterator I = Tt.begin(), E = Tt.end(); I != Other; ++I)
+ int K = *I;
+}
+
+struct EvilArrow : U {
+ // Please, no one ever write code like this.
+ U *operator->();
+};
+
+void differentMemberAccessTypes() {
+ EvilArrow A;
+ for (EvilArrow::iterator I = A.begin(), E = A->end(); I != E; ++I)
+ Val K = *I;
+ for (EvilArrow::iterator I = A->begin(), E = A.end(); I != E; ++I)
+ Val K = *I;
+}
+
+void f(const T::iterator &It, int);
+void f(const T &It, int);
+void g(T &It, int);
+
+void iteratorPassedToFunction() {
+ for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)
+ f(I, *I);
+}
+
+// FIXME: These tests can be removed if this tool ever does enough analysis to
+// decide that this is a safe transformation. Until then, we don't want it
+// applied.
+void iteratorDefinedOutside() {
+ T::iterator TheEnd = Tt.end();
+ for (T::iterator I = Tt.begin(); I != TheEnd; ++I)
+ int K = *I;
+
+ T::iterator TheBegin = Tt.begin();
+ for (T::iterator E = Tt.end(); TheBegin != E; ++TheBegin)
+ int K = *TheBegin;
+}
+
+} // namespace NegativeIterator
+
+namespace NegativePseudoArray {
+
+const int N = 6;
+dependent<int> V;
+dependent<int> *Pv;
+
+int Sum = 0;
+
+// Checks for the Index start and end:
+void IndexStartAndEnd() {
+ for (int I = 0; I < V.size() + 1; ++I)
+ Sum += V[I];
+
+ for (int I = 0; I < V.size() - 1; ++I)
+ Sum += V[I];
+
+ for (int I = 1; I < V.size(); ++I)
+ Sum += V[I];
+
+ for (int I = 1; I < V.size(); ++I)
+ Sum += V[I];
+
+ for (int I = 0;; ++I)
+ Sum += (*Pv)[I];
+}
+
+// Checks for invalid increment steps:
+void increment() {
+ for (int I = 0; I < V.size(); --I)
+ Sum += V[I];
+
+ for (int I = 0; I < V.size(); I)
+ Sum += V[I];
+
+ for (int I = 0; I < V.size();)
+ Sum += V[I];
+
+ for (int I = 0; I < V.size(); I += 2)
+ Sum++;
+}
+
+// Checks to make sure that the Index isn't used outside of the container:
+void IndexUse() {
+ for (int I = 0; I < V.size(); ++I)
+ V[I] += 1 + I;
+}
+
+// Checks for incorrect loop variables.
+void mixedVariables() {
+ int BadIndex;
+ for (int I = 0; BadIndex < V.size(); ++I)
+ Sum += V[I];
+
+ for (int I = 0; I < V.size(); ++BadIndex)
+ Sum += V[I];
+
+ for (int I = 0; BadIndex < V.size(); ++BadIndex)
+ Sum += V[I];
+
+ for (int I = 0; BadIndex < V.size(); ++BadIndex)
+ Sum += V[BadIndex];
+}
+
+// Checks for an array Indexed in addition to the container.
+void multipleArrays() {
+ int BadArr[N];
+
+ for (int I = 0; I < V.size(); ++I)
+ Sum += V[I] + BadArr[I];
+
+ for (int I = 0; I < V.size(); ++I)
+ Sum += BadArr[I];
+
+ for (int I = 0; I < V.size(); ++I) {
+ int K = BadArr[I];
+ Sum += K + 2;
+ }
+
+ for (int I = 0; I < V.size(); ++I) {
+ int K = BadArr[I];
+ Sum += V[I] + K;
+ }
+}
+
+// Checks for multiple containers being Indexed container.
+void multipleContainers() {
+ dependent<int> BadArr;
+
+ for (int I = 0; I < V.size(); ++I)
+ Sum += V[I] + BadArr[I];
+
+ for (int I = 0; I < V.size(); ++I)
+ Sum += BadArr[I];
+
+ for (int I = 0; I < V.size(); ++I) {
+ int K = BadArr[I];
+ Sum += K + 2;
+ }
+
+ for (int I = 0; I < V.size(); ++I) {
+ int K = BadArr[I];
+ Sum += V[I] + K;
+ }
+}
+
+// Check to make sure that dereferenced pointers-to-containers behave nicely.
+void derefContainer() {
+ // Note the dependent<T>::operator*() returns another dependent<T>.
+ // This test makes sure that we don't allow an arbitrary number of *'s.
+ for (int I = 0; I < Pv->size(); ++I)
+ Sum += (**Pv).at(I);
+
+ for (int I = 0; I < Pv->size(); ++I)
+ Sum += (**Pv)[I];
+}
+
+void wrongEnd() {
+ int Bad;
+ for (int I = 0, E = V.size(); I < Bad; ++I)
+ Sum += V[I];
+}
+
+// Checks to see that non-const member functions are not called on the container
+// object.
+// These could be conceivably allowed with a lower required confidence level.
+void memberFunctionCalled() {
+ for (int I = 0; I < V.size(); ++I) {
+ Sum += V[I];
+ V.foo();
+ }
+
+ for (int I = 0; I < V.size(); ++I) {
+ Sum += V[I];
+ dependent<int>::iterator It = V.begin();
+ }
+}
+
+} // namespace NegativePseudoArray
+
+namespace NegativeMultiEndCall {
+
+S Ss;
+T Tt;
+U Uu;
+
+void f(X);
+void f(S);
+void f(T);
+
+void complexContainer() {
+ X Xx;
+ for (S::iterator I = Xx.Ss.begin(), E = Xx.Ss.end(); I != E; ++I) {
+ f(Xx);
+ MutableVal K = *I;
+ }
+
+ for (T::iterator I = Xx.Tt.begin(), E = Xx.Tt.end(); I != E; ++I) {
+ f(Xx);
+ int K = *I;
+ }
+
+ for (S::iterator I = Xx.Ss.begin(), E = Xx.Ss.end(); I != E; ++I) {
+ f(Xx.Ss);
+ MutableVal K = *I;
+ }
+
+ for (T::iterator I = Xx.Tt.begin(), E = Xx.Tt.end(); I != E; ++I) {
+ f(Xx.Tt);
+ int K = *I;
+ }
+
+ for (S::iterator I = Xx.getS().begin(), E = Xx.getS().end(); I != E; ++I) {
+ f(Xx.getS());
+ MutableVal K = *I;
+ }
+
+ X Exes[5];
+ int Index = 0;
+
+ for (S::iterator I = Exes[Index].getS().begin(),
+ E = Exes[Index].getS().end();
+ I != E; ++I) {
+ Index++;
+ MutableVal K = *I;
+ }
+}
+
+} // namespace NegativeMultiEndCall
+
+namespace NoUsages {
+
+const int N = 6;
+int Arr[N] = {1, 2, 3, 4, 5, 6};
+S Ss;
+dependent<int> V;
+int Count = 0;
+
+void foo();
+
+void f() {
+ for (int I = 0; I < N; ++I) {}
+ for (int I = 0; I < N; ++I)
+ printf("Hello world\n");
+ for (int I = 0; I < N; ++I)
+ ++Count;
+ for (int I = 0; I < N; ++I)
+ foo();
+
+ for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I) {}
+ for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)
+ printf("Hello world\n");
+ for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)
+ ++Count;
+ for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)
+ foo();
+
+ for (int I = 0; I < V.size(); ++I) {}
+ for (int I = 0; I < V.size(); ++I)
+ printf("Hello world\n");
+ for (int I = 0; I < V.size(); ++I)
+ ++Count;
+ for (int I = 0; I < V.size(); ++I)
+ foo();
+}
+
+} // namespace NoUsages
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-uppercase.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-uppercase.cpp
new file mode 100644
index 0000000..4d1d5c2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-uppercase.cpp
@@ -0,0 +1,41 @@
+// RUN: %check_clang_tidy %s modernize-loop-convert %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-loop-convert.NamingStyle, value: 'UPPER_CASE'}]}" \
+// RUN: -- -std=c++11 -I %S/Inputs/modernize-loop-convert
+
+#include "structures.h"
+
+const int N = 10;
+int ARR[N];
+int NUMS[N];
+int NUMS_[N];
+
+void naming() {
+ for (int I = 0; I < N; ++I) {
+ printf("%d\n", ARR[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]
+ // CHECK-FIXES: for (int I : ARR)
+ // CHECK-FIXES-NEXT: printf("%d\n", I);
+
+ for (int I = 0; I < N; ++I) {
+ printf("%d\n", NUMS[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int NUM : NUMS)
+ // CHECK-FIXES-NEXT: printf("%d\n", NUM);
+
+ for (int I = 0; I < N; ++I) {
+ printf("%d\n", NUMS_[I]);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int NUM : NUMS_)
+ // CHECK-FIXES-NEXT: printf("%d\n", NUM);
+
+ int NUM = 0;
+ for (int I = 0; I < N; ++I) {
+ printf("%d\n", NUMS[I] + NUM);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int I : NUMS)
+ // CHECK-FIXES-NEXT: printf("%d\n", I + NUM);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert.c
new file mode 100644
index 0000000..4c7d956
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert.c
@@ -0,0 +1,12 @@
+// RUN: clang-tidy %s -checks=-*,modernize-loop-convert -- -std=c11 | count 0
+
+// Note: this test expects no diagnostics, but FileCheck cannot handle that,
+// hence the use of | count 0.
+
+int arr[6] = {1, 2, 3, 4, 5, 6};
+
+void f(void) {
+ for (int i = 0; i < 6; ++i) {
+ (void)arr[i];
+ }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-shared-header.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-shared-header.cpp
new file mode 100644
index 0000000..21b07ee
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-shared-header.cpp
@@ -0,0 +1,17 @@
+// RUN: %check_clang_tidy %s modernize-make-shared %t -- \
+// RUN: -config="{CheckOptions: \
+// RUN: [{key: modernize-make-shared.MakeSmartPtrFunction, \
+// RUN: value: 'my::MakeShared'}, \
+// RUN: {key: modernize-make-shared.MakeSmartPtrFunctionHeader, \
+// RUN: value: 'make_shared_util.h'} \
+// RUN: ]}" \
+// RUN: -- -std=c++11 -I%S/Inputs/modernize-smart-ptr
+
+#include "shared_ptr.h"
+// CHECK-FIXES: #include "make_shared_util.h"
+
+void f() {
+ std::shared_ptr<int> P1 = std::shared_ptr<int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use my::MakeShared instead
+ // CHECK-FIXES: std::shared_ptr<int> P1 = my::MakeShared<int>();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-shared.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-shared.cpp
new file mode 100644
index 0000000..ed4da99
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-shared.cpp
@@ -0,0 +1,286 @@
+// RUN: %check_clang_tidy %s modernize-make-shared %t -- -- -std=c++11 \
+// RUN: -I%S/Inputs/modernize-smart-ptr
+
+#include "shared_ptr.h"
+// CHECK-FIXES: #include <memory>
+
+struct Base {
+ Base();
+ Base(int, int);
+};
+
+struct Derived : public Base {
+ Derived();
+ Derived(int, int);
+};
+
+struct APair {
+ int a, b;
+};
+
+struct DPair {
+ DPair() : a(0), b(0) {}
+ DPair(int x, int y) : a(y), b(x) {}
+ int a, b;
+};
+
+struct Empty {};
+
+template <class T>
+using shared_ptr_ = std::shared_ptr<T>;
+
+void *operator new(__SIZE_TYPE__ Count, void *Ptr);
+
+int g(std::shared_ptr<int> P);
+
+std::shared_ptr<Base> getPointer() {
+ return std::shared_ptr<Base>(new Base);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use std::make_shared instead
+ // CHECK-FIXES: return std::make_shared<Base>();
+}
+
+void basic() {
+ std::shared_ptr<int> P1 = std::shared_ptr<int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_shared instead [modernize-make-shared]
+ // CHECK-FIXES: std::shared_ptr<int> P1 = std::make_shared<int>();
+
+ P1.reset(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_shared instead [modernize-make-shared]
+ // CHECK-FIXES: P1 = std::make_shared<int>();
+
+ P1 = std::shared_ptr<int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_shared instead [modernize-make-shared]
+ // CHECK-FIXES: P1 = std::make_shared<int>();
+
+ // Without parenthesis.
+ std::shared_ptr<int> P2 = std::shared_ptr<int>(new int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_shared instead [modernize-make-shared]
+ // CHECK-FIXES: std::shared_ptr<int> P2 = std::make_shared<int>();
+
+ P2.reset(new int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_shared instead [modernize-make-shared]
+ // CHECK-FIXES: P2 = std::make_shared<int>();
+
+ P2 = std::shared_ptr<int>(new int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_shared instead [modernize-make-shared]
+ // CHECK-FIXES: P2 = std::make_shared<int>();
+
+ // With auto.
+ auto P3 = std::shared_ptr<int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_shared instead
+ // CHECK-FIXES: auto P3 = std::make_shared<int>();
+
+ {
+ // No std.
+ using namespace std;
+ shared_ptr<int> Q = shared_ptr<int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use std::make_shared instead
+ // CHECK-FIXES: shared_ptr<int> Q = std::make_shared<int>();
+
+ Q = shared_ptr<int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_shared instead
+ // CHECK-FIXES: Q = std::make_shared<int>();
+ }
+
+ std::shared_ptr<int> R(new int());
+
+ // Create the shared_ptr as a parameter to a function.
+ int T = g(std::shared_ptr<int>(new int()));
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_shared instead
+ // CHECK-FIXES: int T = g(std::make_shared<int>());
+
+ // Only replace if the type in the template is the same as the type returned
+ // by the new operator.
+ auto Pderived = std::shared_ptr<Base>(new Derived());
+
+ // OK to replace for reset and assign
+ Pderived.reset(new Derived());
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use std::make_shared instead
+ // CHECK-FIXES: Pderived = std::make_shared<Derived>();
+
+ Pderived = std::shared_ptr<Derived>(new Derived());
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use std::make_shared instead
+ // CHECK-FIXES: Pderived = std::make_shared<Derived>();
+
+ // FIXME: OK to replace if assigned to shared_ptr<Base>
+ Pderived = std::shared_ptr<Base>(new Derived());
+
+ // FIXME: OK to replace when auto is not used
+ std::shared_ptr<Base> PBase = std::shared_ptr<Base>(new Derived());
+
+ // The pointer is returned by the function, nothing to do.
+ std::shared_ptr<Base> RetPtr = getPointer();
+
+ // This emulates std::move.
+ std::shared_ptr<int> Move = static_cast<std::shared_ptr<int> &&>(P1);
+
+ // Placement arguments should not be removed.
+ int *PInt = new int;
+ std::shared_ptr<int> Placement = std::shared_ptr<int>(new (PInt) int{3});
+ Placement.reset(new (PInt) int{3});
+ Placement = std::shared_ptr<int>(new (PInt) int{3});
+}
+
+// Calling make_smart_ptr from within a member function of a type with a
+// private or protected constructor would be ill-formed.
+class Private {
+private:
+ Private(int z) {}
+
+public:
+ Private() {}
+ void create() {
+ auto callsPublic = std::shared_ptr<Private>(new Private);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_shared instead
+ // CHECK-FIXES: auto callsPublic = std::make_shared<Private>();
+ auto ptr = std::shared_ptr<Private>(new Private(42));
+ ptr.reset(new Private(42));
+ ptr = std::shared_ptr<Private>(new Private(42));
+ }
+
+ virtual ~Private();
+};
+
+class Protected {
+protected:
+ Protected() {}
+
+public:
+ Protected(int, int) {}
+ void create() {
+ auto callsPublic = std::shared_ptr<Protected>(new Protected(1, 2));
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_shared instead
+ // CHECK-FIXES: auto callsPublic = std::make_shared<Protected>(1, 2);
+ auto ptr = std::shared_ptr<Protected>(new Protected);
+ ptr.reset(new Protected);
+ ptr = std::shared_ptr<Protected>(new Protected);
+ }
+};
+
+void initialization(int T, Base b) {
+ // Test different kinds of initialization of the pointee.
+
+ // Direct initialization with parenthesis.
+ std::shared_ptr<DPair> PDir1 = std::shared_ptr<DPair>(new DPair(1, T));
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
+ // CHECK-FIXES: std::shared_ptr<DPair> PDir1 = std::make_shared<DPair>(1, T);
+ PDir1.reset(new DPair(1, T));
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_shared instead
+ // CHECK-FIXES: PDir1 = std::make_shared<DPair>(1, T);
+
+ // Direct initialization with braces.
+ std::shared_ptr<DPair> PDir2 = std::shared_ptr<DPair>(new DPair{2, T});
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
+ // CHECK-FIXES: std::shared_ptr<DPair> PDir2 = std::make_shared<DPair>(2, T);
+ PDir2.reset(new DPair{2, T});
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_shared instead
+ // CHECK-FIXES: PDir2 = std::make_shared<DPair>(2, T);
+
+ // Aggregate initialization.
+ std::shared_ptr<APair> PAggr = std::shared_ptr<APair>(new APair{T, 1});
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
+ // CHECK-FIXES: std::shared_ptr<APair> PAggr = std::make_shared<APair>(APair{T, 1});
+ PAggr.reset(new APair{T, 1});
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_shared instead
+ // CHECK-FIXES: std::make_shared<APair>(APair{T, 1});
+
+ // Test different kinds of initialization of the pointee, when the shared_ptr
+ // is initialized with braces.
+
+ // Direct initialization with parenthesis.
+ std::shared_ptr<DPair> PDir3 = std::shared_ptr<DPair>{new DPair(3, T)};
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
+ // CHECK-FIXES: std::shared_ptr<DPair> PDir3 = std::make_shared<DPair>(3, T);
+
+ // Direct initialization with braces.
+ std::shared_ptr<DPair> PDir4 = std::shared_ptr<DPair>{new DPair{4, T}};
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
+ // CHECK-FIXES: std::shared_ptr<DPair> PDir4 = std::make_shared<DPair>(4, T);
+
+ // Aggregate initialization.
+ std::shared_ptr<APair> PAggr2 = std::shared_ptr<APair>{new APair{T, 2}};
+ // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use std::make_shared instead
+ // CHECK-FIXES: std::shared_ptr<APair> PAggr2 = std::make_shared<APair>(APair{T, 2});
+
+ // Direct initialization with parenthesis, without arguments.
+ std::shared_ptr<DPair> PDir5 = std::shared_ptr<DPair>(new DPair());
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
+ // CHECK-FIXES: std::shared_ptr<DPair> PDir5 = std::make_shared<DPair>();
+
+ // Direct initialization with braces, without arguments.
+ std::shared_ptr<DPair> PDir6 = std::shared_ptr<DPair>(new DPair{});
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
+ // CHECK-FIXES: std::shared_ptr<DPair> PDir6 = std::make_shared<DPair>();
+
+ // Aggregate initialization without arguments.
+ std::shared_ptr<Empty> PEmpty = std::shared_ptr<Empty>(new Empty{});
+ // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use std::make_shared instead
+ // CHECK-FIXES: std::shared_ptr<Empty> PEmpty = std::make_shared<Empty>(Empty{});
+}
+
+void aliases() {
+ typedef std::shared_ptr<int> IntPtr;
+ IntPtr Typedef = IntPtr(new int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use std::make_shared instead
+ // CHECK-FIXES: IntPtr Typedef = std::make_shared<int>();
+
+ // We use 'bool' instead of '_Bool'.
+ typedef std::shared_ptr<bool> BoolPtr;
+ BoolPtr BoolType = BoolPtr(new bool);
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use std::make_shared instead
+ // CHECK-FIXES: BoolPtr BoolType = std::make_shared<bool>();
+
+ // We use 'Base' instead of 'struct Base'.
+ typedef std::shared_ptr<Base> BasePtr;
+ BasePtr StructType = BasePtr(new Base);
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_shared instead
+// CHECK-FIXES: BasePtr StructType = std::make_shared<Base>();
+
+#define PTR shared_ptr<int>
+ std::shared_ptr<int> Macro = std::PTR(new int);
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_shared instead
+// CHECK-FIXES: std::shared_ptr<int> Macro = std::make_shared<int>();
+#undef PTR
+
+ std::shared_ptr<int> Using = shared_ptr_<int>(new int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_shared instead
+ // CHECK-FIXES: std::shared_ptr<int> Using = std::make_shared<int>();
+}
+
+void whitespaces() {
+ // clang-format off
+ auto Space = std::shared_ptr <int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use std::make_shared instead
+ // CHECK-FIXES: auto Space = std::make_shared<int>();
+
+ auto Spaces = std :: shared_ptr <int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use std::make_shared instead
+ // CHECK-FIXES: auto Spaces = std::make_shared<int>();
+ // clang-format on
+}
+
+void nesting() {
+ auto Nest = std::shared_ptr<std::shared_ptr<int>>(new std::shared_ptr<int>(new int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use std::make_shared instead
+ // CHECK-FIXES: auto Nest = std::make_shared<std::shared_ptr<int>>(new int);
+ Nest.reset(new std::shared_ptr<int>(new int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_shared instead
+ // CHECK-FIXES: Nest = std::make_shared<std::shared_ptr<int>>(new int);
+ Nest->reset(new int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_shared instead
+ // CHECK-FIXES: *Nest = std::make_shared<int>();
+}
+
+void reset() {
+ std::shared_ptr<int> P;
+ P.reset();
+ P.reset(nullptr);
+ P.reset(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use std::make_shared instead
+ // CHECK-FIXES: P = std::make_shared<int>();
+
+ auto Q = &P;
+ Q->reset(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_shared instead
+ // CHECK-FIXES: *Q = std::make_shared<int>();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-cxx11.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-cxx11.cpp
new file mode 100644
index 0000000..89beb08
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-cxx11.cpp
@@ -0,0 +1,10 @@
+// RUN: %check_clang_tidy %s modernize-make-unique %t -- -- -std=c++11 \
+// RUN: -I%S/Inputs/modernize-smart-ptr
+
+#include "unique_ptr.h"
+// CHECK-FIXES: #include "unique_ptr.h"
+
+void f() {
+ auto my_ptr = std::unique_ptr<int>(new int(1));
+ // CHECK-FIXES: auto my_ptr = std::unique_ptr<int>(new int(1));
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-cxx14.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-cxx14.cpp
new file mode 100644
index 0000000..cd35f75
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-cxx14.cpp
@@ -0,0 +1,11 @@
+// RUN: %check_clang_tidy %s modernize-make-unique %t -- -- -std=c++14 \
+// RUN: -I%S/Inputs/modernize-smart-ptr
+
+#include "unique_ptr.h"
+// CHECK-FIXES: #include <memory>
+
+void f() {
+ auto my_ptr = std::unique_ptr<int>(new int(1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use std::make_unique instead
+ // CHECK-FIXES: auto my_ptr = std::make_unique<int>(1);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-header.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-header.cpp
new file mode 100644
index 0000000..e6c2a61
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-header.cpp
@@ -0,0 +1,17 @@
+// RUN: %check_clang_tidy %s modernize-make-unique %t -- \
+// RUN: -config="{CheckOptions: \
+// RUN: [{key: modernize-make-unique.MakeSmartPtrFunction, \
+// RUN: value: 'my::MakeUnique'}, \
+// RUN: {key: modernize-make-unique.MakeSmartPtrFunctionHeader, \
+// RUN: value: 'make_unique_util.h'} \
+// RUN: ]}" \
+// RUN: -- -std=c++11 -I%S/Inputs/modernize-smart-ptr
+
+#include "unique_ptr.h"
+// CHECK-FIXES: #include "make_unique_util.h"
+
+void f() {
+ std::unique_ptr<int> P1 = std::unique_ptr<int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use my::MakeUnique instead
+ // CHECK-FIXES: std::unique_ptr<int> P1 = my::MakeUnique<int>();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-macros.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-macros.cpp
new file mode 100644
index 0000000..117a45c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-macros.cpp
@@ -0,0 +1,28 @@
+// RUN: %check_clang_tidy %s modernize-make-unique %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-make-unique.IgnoreMacros, value: 0}]}" \
+// RUN: -- -std=c++14 -I%S/Inputs/modernize-smart-ptr
+
+#include "unique_ptr.h"
+
+class Foo {};
+class Bar {};
+#define DEFINE(...) __VA_ARGS__
+// CHECK-FIXES: {{^}}#define DEFINE(...) __VA_ARGS__{{$}}
+template<typename T>
+void g2(std::unique_ptr<Foo> *t) {
+ DEFINE(
+ // CHECK-FIXES: {{^ *}}DEFINE({{$}}
+ auto p = std::unique_ptr<Foo>(new Foo);
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use std::make_unique instead
+ // CHECK-FIXES: {{^ *}}auto p = std::unique_ptr<Foo>(new Foo);{{$}}
+ t->reset(new Foo);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use std::make_unique instead
+ // CHECK-FIXES: {{^ *}}t->reset(new Foo);{{$}}
+ );
+ // CHECK-FIXES: {{^ *}});{{$}}
+}
+void macro() {
+ std::unique_ptr<Foo> *t;
+ g2<Bar>(t);
+}
+#undef DEFINE
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique.cpp
new file mode 100644
index 0000000..9685203
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique.cpp
@@ -0,0 +1,517 @@
+// RUN: %check_clang_tidy %s modernize-make-unique %t -- -- -std=c++14 \
+// RUN: -I%S/Inputs/modernize-smart-ptr
+
+#include "unique_ptr.h"
+#include "initializer_list.h"
+// CHECK-FIXES: #include <memory>
+
+struct Base {
+ Base();
+ Base(int, int);
+};
+
+struct Derived : public Base {
+ Derived();
+ Derived(int, int);
+};
+
+struct APair {
+ int a, b;
+};
+
+struct DPair {
+ DPair() : a(0), b(0) {}
+ DPair(int x, int y) : a(y), b(x) {}
+ int a, b;
+};
+
+template<typename T>
+struct MyVector {
+ MyVector(std::initializer_list<T>);
+};
+
+struct Empty {};
+
+struct E {
+ E(std::initializer_list<int>);
+ E();
+};
+
+struct F {
+ F(std::initializer_list<int>);
+ F();
+ int a;
+};
+
+struct G {
+ G(std::initializer_list<int>);
+ G(int);
+};
+
+struct H {
+ H(std::vector<int>);
+ H(std::vector<int> &, double);
+ H(MyVector<int>, int);
+};
+
+struct I {
+ I(G);
+};
+
+namespace {
+class Foo {};
+} // namespace
+
+namespace bar {
+class Bar {};
+} // namespace bar
+
+template <class T>
+using unique_ptr_ = std::unique_ptr<T>;
+
+void *operator new(__SIZE_TYPE__ Count, void *Ptr);
+
+int g(std::unique_ptr<int> P);
+
+std::unique_ptr<Base> getPointer() {
+ return std::unique_ptr<Base>(new Base);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use std::make_unique instead
+ // CHECK-FIXES: return std::make_unique<Base>();
+}
+
+void basic() {
+ std::unique_ptr<int> P1 = std::unique_ptr<int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]
+ // CHECK-FIXES: std::unique_ptr<int> P1 = std::make_unique<int>();
+
+ P1.reset(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead [modernize-make-unique]
+ // CHECK-FIXES: P1 = std::make_unique<int>();
+
+ P1 = std::unique_ptr<int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_unique instead [modernize-make-unique]
+ // CHECK-FIXES: P1 = std::make_unique<int>();
+
+ // Without parenthesis.
+ std::unique_ptr<int> P2 = std::unique_ptr<int>(new int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]
+ // CHECK-FIXES: std::unique_ptr<int> P2 = std::make_unique<int>();
+
+ P2.reset(new int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead [modernize-make-unique]
+ // CHECK-FIXES: P2 = std::make_unique<int>();
+
+ P2 = std::unique_ptr<int>(new int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_unique instead [modernize-make-unique]
+ // CHECK-FIXES: P2 = std::make_unique<int>();
+
+ // With auto.
+ auto P3 = std::unique_ptr<int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+ // CHECK-FIXES: auto P3 = std::make_unique<int>();
+
+ {
+ // No std.
+ using namespace std;
+ unique_ptr<int> Q = unique_ptr<int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use std::make_unique instead
+ // CHECK-FIXES: unique_ptr<int> Q = std::make_unique<int>();
+
+ Q = unique_ptr<int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_unique instead
+ // CHECK-FIXES: Q = std::make_unique<int>();
+ }
+
+ std::unique_ptr<int> R(new int());
+
+ // Create the unique_ptr as a parameter to a function.
+ int T = g(std::unique_ptr<int>(new int()));
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+ // CHECK-FIXES: int T = g(std::make_unique<int>());
+
+ // Only replace if the type in the template is the same as the type returned
+ // by the new operator.
+ auto Pderived = std::unique_ptr<Base>(new Derived());
+
+ // OK to replace for reset and assign
+ Pderived.reset(new Derived());
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use std::make_unique instead
+ // CHECK-FIXES: Pderived = std::make_unique<Derived>();
+
+ Pderived = std::unique_ptr<Derived>(new Derived());
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use std::make_unique instead
+ // CHECK-FIXES: Pderived = std::make_unique<Derived>();
+
+ // FIXME: OK to replace if assigned to unique_ptr<Base>
+ Pderived = std::unique_ptr<Base>(new Derived());
+
+ // FIXME: OK to replace when auto is not used
+ std::unique_ptr<Base> PBase = std::unique_ptr<Base>(new Derived());
+
+ // The pointer is returned by the function, nothing to do.
+ std::unique_ptr<Base> RetPtr = getPointer();
+
+ // This emulates std::move.
+ std::unique_ptr<int> Move = static_cast<std::unique_ptr<int> &&>(P1);
+
+ // Placement arguments should not be removed.
+ int *PInt = new int;
+ std::unique_ptr<int> Placement = std::unique_ptr<int>(new (PInt) int{3});
+ Placement.reset(new (PInt) int{3});
+ Placement = std::unique_ptr<int>(new (PInt) int{3});
+}
+
+// Calling make_smart_ptr from within a member function of a type with a
+// private or protected constructor would be ill-formed.
+class Private {
+private:
+ Private(int z) {}
+
+public:
+ Private() {}
+ void create() {
+ auto callsPublic = std::unique_ptr<Private>(new Private);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_unique instead
+ // CHECK-FIXES: auto callsPublic = std::make_unique<Private>();
+ auto ptr = std::unique_ptr<Private>(new Private(42));
+ ptr.reset(new Private(42));
+ ptr = std::unique_ptr<Private>(new Private(42));
+ }
+
+ virtual ~Private();
+};
+
+class Protected {
+protected:
+ Protected() {}
+
+public:
+ Protected(int, int) {}
+ void create() {
+ auto callsPublic = std::unique_ptr<Protected>(new Protected(1, 2));
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_unique instead
+ // CHECK-FIXES: auto callsPublic = std::make_unique<Protected>(1, 2);
+ auto ptr = std::unique_ptr<Protected>(new Protected);
+ ptr.reset(new Protected);
+ ptr = std::unique_ptr<Protected>(new Protected);
+ }
+};
+
+void initialization(int T, Base b) {
+ // Test different kinds of initialization of the pointee.
+
+ // Direct initialization with parenthesis.
+ std::unique_ptr<DPair> PDir1 = std::unique_ptr<DPair>(new DPair(1, T));
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<DPair> PDir1 = std::make_unique<DPair>(1, T);
+ PDir1.reset(new DPair(1, T));
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_unique instead
+ // CHECK-FIXES: PDir1 = std::make_unique<DPair>(1, T);
+
+ // Direct initialization with braces.
+ std::unique_ptr<DPair> PDir2 = std::unique_ptr<DPair>(new DPair{2, T});
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<DPair> PDir2 = std::make_unique<DPair>(2, T);
+ PDir2.reset(new DPair{2, T});
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_unique instead
+ // CHECK-FIXES: PDir2 = std::make_unique<DPair>(2, T);
+
+ // Aggregate initialization.
+ std::unique_ptr<APair> PAggr = std::unique_ptr<APair>(new APair{T, 1});
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<APair> PAggr = std::make_unique<APair>(APair{T, 1});
+ PAggr.reset(new APair{T, 1});
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_unique instead
+ // CHECK-FIXES: std::make_unique<APair>(APair{T, 1});
+
+ // Test different kinds of initialization of the pointee, when the unique_ptr
+ // is initialized with braces.
+
+ // Direct initialization with parenthesis.
+ std::unique_ptr<DPair> PDir3 = std::unique_ptr<DPair>{new DPair(3, T)};
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<DPair> PDir3 = std::make_unique<DPair>(3, T);
+
+ // Direct initialization with braces.
+ std::unique_ptr<DPair> PDir4 = std::unique_ptr<DPair>{new DPair{4, T}};
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<DPair> PDir4 = std::make_unique<DPair>(4, T);
+
+ // Aggregate initialization.
+ std::unique_ptr<APair> PAggr2 = std::unique_ptr<APair>{new APair{T, 2}};
+ // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<APair> PAggr2 = std::make_unique<APair>(APair{T, 2});
+
+ // Direct initialization with parenthesis, without arguments.
+ std::unique_ptr<DPair> PDir5 = std::unique_ptr<DPair>(new DPair());
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<DPair> PDir5 = std::make_unique<DPair>();
+
+ // Direct initialization with braces, without arguments.
+ std::unique_ptr<DPair> PDir6 = std::unique_ptr<DPair>(new DPair{});
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<DPair> PDir6 = std::make_unique<DPair>();
+
+ // Aggregate initialization without arguments.
+ std::unique_ptr<Empty> PEmpty = std::unique_ptr<Empty>(new Empty{});
+ // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<Empty> PEmpty = std::make_unique<Empty>(Empty{});
+
+ // Initialization with default constructor.
+ std::unique_ptr<E> PE1 = std::unique_ptr<E>(new E{});
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<E> PE1 = std::make_unique<E>();
+ PE1.reset(new E{});
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+ // CHECK-FIXES: PE1 = std::make_unique<E>();
+
+ //============================================================================
+ // NOTE: For initlializer-list constructors, the check only gives warnings,
+ // and no fixes are generated.
+ //============================================================================
+
+ // Initialization with the initializer-list constructor.
+ std::unique_ptr<E> PE2 = std::unique_ptr<E>(new E{1, 2});
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<E> PE2 = std::unique_ptr<E>(new E{1, 2});
+ PE2.reset(new E{1, 2});
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+ // CHECK-FIXES: PE2.reset(new E{1, 2});
+
+ // Initialization with default constructor.
+ std::unique_ptr<F> PF1 = std::unique_ptr<F>(new F());
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<F> PF1 = std::make_unique<F>();
+ PF1.reset(new F());
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+ // CHECK-FIXES: PF1 = std::make_unique<F>();
+
+ // Initialization with default constructor.
+ std::unique_ptr<F> PF2 = std::unique_ptr<F>(new F{});
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<F> PF2 = std::make_unique<F>();
+ PF2.reset(new F());
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+ // CHECK-FIXES: PF2 = std::make_unique<F>();
+
+ // Initialization with the initializer-list constructor.
+ std::unique_ptr<F> PF3 = std::unique_ptr<F>(new F{1});
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<F> PF3 = std::unique_ptr<F>(new F{1});
+ PF3.reset(new F{1});
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+ // CHECK-FIXES: PF3.reset(new F{1});
+
+ // Initialization with the initializer-list constructor.
+ std::unique_ptr<F> PF4 = std::unique_ptr<F>(new F{1, 2});
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<F> PF4 = std::unique_ptr<F>(new F{1, 2});
+
+ // Initialization with the initializer-list constructor.
+ std::unique_ptr<F> PF5 = std::unique_ptr<F>(new F({1, 2}));
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<F> PF5 = std::unique_ptr<F>(new F({1, 2}));
+
+ // Initialization with the initializer-list constructor as the default
+ // constructor is not present.
+ std::unique_ptr<G> PG1 = std::unique_ptr<G>(new G{});
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<G> PG1 = std::unique_ptr<G>(new G{});
+ PG1.reset(new G{});
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+ // CHECK-FIXES: PG1.reset(new G{});
+
+ // Initialization with the initializer-list constructor.
+ std::unique_ptr<G> PG2 = std::unique_ptr<G>(new G{1});
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<G> PG2 = std::unique_ptr<G>(new G{1});
+
+ // Initialization with the initializer-list constructor.
+ std::unique_ptr<G> PG3 = std::unique_ptr<G>(new G{1, 2});
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<G> PG3 = std::unique_ptr<G>(new G{1, 2});
+
+ std::unique_ptr<H> PH1 = std::unique_ptr<H>(new H({1, 2, 3}));
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<H> PH1 = std::unique_ptr<H>(new H({1, 2, 3}));
+ PH1.reset(new H({1, 2, 3}));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+ // CHECK-FIXES: PH1.reset(new H({1, 2, 3}));
+
+ std::unique_ptr<H> PH2 = std::unique_ptr<H>(new H({1, 2, 3}, 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<H> PH2 = std::unique_ptr<H>(new H({1, 2, 3}, 1));
+ PH2.reset(new H({1, 2, 3}, 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+ // CHECK-FIXES: PH2.reset(new H({1, 2, 3}, 1));
+
+ std::unique_ptr<H> PH3 = std::unique_ptr<H>(new H({1, 2, 3}, 1.0));
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<H> PH3 = std::unique_ptr<H>(new H({1, 2, 3}, 1.0));
+ PH3.reset(new H({1, 2, 3}, 1.0));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+ // CHECK-FIXES: PH3.reset(new H({1, 2, 3}, 1.0));
+
+ std::unique_ptr<I> PI1 = std::unique_ptr<I>(new I(G({1, 2, 3})));
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<I> PI1 = std::make_unique<I>(G({1, 2, 3}));
+ PI1.reset(new I(G({1, 2, 3})));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+ // CHECK-FIXES: PI1 = std::make_unique<I>(G({1, 2, 3}));
+
+ std::unique_ptr<Foo> FF = std::unique_ptr<Foo>(new Foo());
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning:
+ // CHECK-FIXES: std::unique_ptr<Foo> FF = std::make_unique<Foo>();
+ FF.reset(new Foo());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning:
+ // CHECK-FIXES: FF = std::make_unique<Foo>();
+
+ std::unique_ptr<bar::Bar> BB = std::unique_ptr<bar::Bar>(new bar::Bar());
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning:
+ // CHECK-FIXES: std::unique_ptr<bar::Bar> BB = std::make_unique<bar::Bar>();
+ BB.reset(new bar::Bar());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning:
+ // CHECK-FIXES: BB = std::make_unique<bar::Bar>();
+
+ std::unique_ptr<Foo[]> FFs;
+ FFs.reset(new Foo[5]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning:
+ // CHECK-FIXES: FFs = std::make_unique<Foo[]>(5);
+ FFs.reset(new Foo[5]());
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning:
+ // CHECK-FIXES: FFs = std::make_unique<Foo[]>(5);
+ const int Num = 1;
+ FFs.reset(new Foo[Num]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning:
+ // CHECK-FIXES: FFs = std::make_unique<Foo[]>(Num);
+ int Num2 = 1;
+ FFs.reset(new Foo[Num2]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning:
+ // CHECK-FIXES: FFs = std::make_unique<Foo[]>(Num2);
+
+ std::unique_ptr<int[]> FI;
+ FI.reset(new int[5]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning:
+ // CHECK-FIXES: FI = std::make_unique<int[]>(5);
+ FI.reset(new int[5]());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning:
+ // CHECK-FIXES: FI = std::make_unique<int[]>(5);
+ FI.reset(new int[Num]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning:
+ // CHECK-FIXES: FI = std::make_unique<int[]>(Num);
+ FI.reset(new int[Num2]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning:
+ // CHECK-FIXES: FI = std::make_unique<int[]>(Num2);
+}
+
+void aliases() {
+ typedef std::unique_ptr<int> IntPtr;
+ IntPtr Typedef = IntPtr(new int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use std::make_unique instead
+ // CHECK-FIXES: IntPtr Typedef = std::make_unique<int>();
+
+ // We use 'bool' instead of '_Bool'.
+ typedef std::unique_ptr<bool> BoolPtr;
+ BoolPtr BoolType = BoolPtr(new bool);
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use std::make_unique instead
+ // CHECK-FIXES: BoolPtr BoolType = std::make_unique<bool>();
+
+ // We use 'Base' instead of 'struct Base'.
+ typedef std::unique_ptr<Base> BasePtr;
+ BasePtr StructType = BasePtr(new Base);
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_unique instead
+// CHECK-FIXES: BasePtr StructType = std::make_unique<Base>();
+
+#define PTR unique_ptr<int>
+ std::unique_ptr<int> Macro = std::PTR(new int);
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_unique instead
+// CHECK-FIXES: std::unique_ptr<int> Macro = std::make_unique<int>();
+#undef PTR
+
+ std::unique_ptr<int> Using = unique_ptr_<int>(new int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<int> Using = std::make_unique<int>();
+}
+
+void whitespaces() {
+ // clang-format off
+ auto Space = std::unique_ptr <int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use std::make_unique instead
+ // CHECK-FIXES: auto Space = std::make_unique<int>();
+
+ auto Spaces = std :: unique_ptr <int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use std::make_unique instead
+ // CHECK-FIXES: auto Spaces = std::make_unique<int>();
+ // clang-format on
+}
+
+void nesting() {
+ auto Nest = std::unique_ptr<std::unique_ptr<int>>(new std::unique_ptr<int>(new int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use std::make_unique instead
+ // CHECK-FIXES: auto Nest = std::make_unique<std::unique_ptr<int>>(new int);
+ Nest.reset(new std::unique_ptr<int>(new int));
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_unique instead
+ // CHECK-FIXES: Nest = std::make_unique<std::unique_ptr<int>>(new int);
+ Nest->reset(new int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_unique instead
+ // CHECK-FIXES: *Nest = std::make_unique<int>();
+}
+
+void reset() {
+ std::unique_ptr<int> P;
+ P.reset();
+ P.reset(nullptr);
+ P.reset(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use std::make_unique instead
+ // CHECK-FIXES: P = std::make_unique<int>();
+
+ auto Q = &P;
+ Q->reset(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead
+ // CHECK-FIXES: *Q = std::make_unique<int>();
+}
+
+#define DEFINE(...) __VA_ARGS__
+template<typename T>
+void g2(std::unique_ptr<Foo> *t) {
+ DEFINE(auto p = std::unique_ptr<Foo>(new Foo); t->reset(new Foo););
+}
+void macro() {
+ std::unique_ptr<Foo> *t;
+ g2<bar::Bar>(t);
+}
+#undef DEFINE
+
+class UniqueFoo : public std::unique_ptr<Foo> {
+ public:
+ void foo() {
+ reset(new Foo);
+ this->reset(new Foo);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use std::make_unique instead
+ // CHECK-FIXES: *this = std::make_unique<Foo>();
+ (*this).reset(new Foo);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+ // CHECK-FIXES: (*this) = std::make_unique<Foo>();
+ }
+};
+
+// Ignore statements inside a template instantiation.
+template<typename T>
+void template_fun(T* t) {
+ std::unique_ptr<T> t2 = std::unique_ptr<T>(new T);
+ t2.reset(new T);
+}
+
+void invoke_template() {
+ Foo* foo;
+ template_fun(foo);
+}
+
+void no_fix_for_invalid_new_loc() {
+ // FIXME: Although the code is valid, the end location of `new struct Base` is
+ // invalid. Correct it once https://bugs.llvm.org/show_bug.cgi?id=35952 is
+ // fixed.
+ auto T = std::unique_ptr<Base>(new struct Base);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use std::make_unique instead
+ // CHECK-FIXES: auto T = std::unique_ptr<Base>(new struct Base);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value-header.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value-header.cpp
new file mode 100644
index 0000000..95ad623
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value-header.cpp
@@ -0,0 +1,8 @@
+// RUN: cp %S/Inputs/modernize-pass-by-value/header.h %T/pass-by-value-header.h
+// RUN: clang-tidy %s -checks='-*,modernize-pass-by-value' -header-filter='.*' -fix -- -std=c++11 -I %T | FileCheck %s -check-prefix=CHECK-MESSAGES -implicit-check-not="{{warning|error}}:"
+// RUN: FileCheck -input-file=%T/pass-by-value-header.h %s -check-prefix=CHECK-FIXES
+
+#include "pass-by-value-header.h"
+// CHECK-MESSAGES: :8:5: warning: pass by value and use std::move [modernize-pass-by-value]
+// CHECK-FIXES: #include <utility>
+// CHECK-FIXES: A(ThreadId tid) : threadid(std::move(tid)) {}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value-macro-header.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value-macro-header.cpp
new file mode 100644
index 0000000..543b7e4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value-macro-header.cpp
@@ -0,0 +1,18 @@
+// RUN: %check_clang_tidy %s modernize-pass-by-value %t -- -- -std=c++11 -isystem %S/Inputs/Headers
+
+// CHECK-FIXES: #include <utility>
+
+#define HEADER <./a.h>
+#include HEADER
+
+struct A {
+ A(const A &) {}
+ A(A &&) {}
+};
+
+struct B {
+ B(const A &a) : a(a) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move [modernize-pass-by-value]
+// CHECK-FIXES: B(A a) : a(std::move(a)) {}
+ A a;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value-multi-fixes.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value-multi-fixes.cpp
new file mode 100644
index 0000000..7980c30
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value-multi-fixes.cpp
@@ -0,0 +1,12 @@
+// RUN: cat %S/Inputs/modernize-pass-by-value/header-with-fix.h > %T/pass-by-value-header-with-fix.h
+// RUN: sed -e 's#//.*$##' %s > %t.cpp
+// RUN: clang-tidy %t.cpp -checks='-*,modernize-pass-by-value' -header-filter='.*' -fix -- -std=c++11 -I %T | FileCheck %s -check-prefix=CHECK-MESSAGES -implicit-check-not="{{warning|error}}:"
+// RUN: FileCheck -input-file=%t.cpp %s -check-prefix=CHECK-FIXES
+// RUN: FileCheck -input-file=%T/pass-by-value-header-with-fix.h %s -check-prefix=CHECK-HEADER-FIXES
+
+#include "pass-by-value-header-with-fix.h"
+// CHECK-HEADER-FIXES: Foo(S s);
+Foo::Foo(const S &s) : s(s) {}
+// CHECK-MESSAGES: :9:10: warning: pass by value and use std::move [modernize-pass-by-value]
+// CHECK-FIXES: #include <utility>
+// CHECK-FIXES: Foo::Foo(S s) : s(std::move(s)) {}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value.cpp
new file mode 100644
index 0000000..87e22ba
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value.cpp
@@ -0,0 +1,215 @@
+// RUN: %check_clang_tidy %s modernize-pass-by-value %t -- -- -std=c++11 -fno-delayed-template-parsing
+
+namespace {
+// POD types are trivially move constructible.
+struct POD {
+ int a, b, c;
+};
+
+struct Movable {
+ int a, b, c;
+ Movable() = default;
+ Movable(const Movable &) {}
+ Movable(Movable &&) {}
+};
+
+struct NotMovable {
+ NotMovable() = default;
+ NotMovable(const NotMovable &) = default;
+ NotMovable(NotMovable &&) = delete;
+ int a, b, c;
+};
+}
+
+struct A {
+ A(const Movable &M) : M(M) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move [modernize-pass-by-value]
+ // CHECK-FIXES: A(Movable M) : M(std::move(M)) {}
+ Movable M;
+};
+
+// Test that we aren't modifying other things than a parameter.
+Movable GlobalObj;
+struct B {
+ B(const Movable &M) : M(GlobalObj) {}
+ // CHECK-FIXES: B(const Movable &M) : M(GlobalObj) {}
+ Movable M;
+};
+
+// Test that a parameter with more than one reference to it won't be changed.
+struct C {
+ // Tests extra-reference in body.
+ C(const Movable &M) : M(M) { this->i = M.a; }
+ // CHECK-FIXES: C(const Movable &M) : M(M) { this->i = M.a; }
+
+ // Tests extra-reference in init-list.
+ C(const Movable &M, int) : M(M), i(M.a) {}
+ // CHECK-FIXES: C(const Movable &M, int) : M(M), i(M.a) {}
+ Movable M;
+ int i;
+};
+
+// Test that both declaration and definition are updated.
+struct D {
+ D(const Movable &M);
+ // CHECK-FIXES: D(Movable M);
+ Movable M;
+};
+D::D(const Movable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: D::D(Movable M) : M(std::move(M)) {}
+
+// Test with default parameter.
+struct E {
+ E(const Movable &M = Movable()) : M(M) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+ // CHECK-FIXES: E(Movable M = Movable()) : M(std::move(M)) {}
+ Movable M;
+};
+
+// Test with object that can't be moved.
+struct F {
+ F(const NotMovable &NM) : NM(NM) {}
+ // CHECK-FIXES: F(const NotMovable &NM) : NM(NM) {}
+ NotMovable NM;
+};
+
+// Test unnamed parameter in declaration.
+struct G {
+ G(const Movable &);
+ // CHECK-FIXES: G(Movable );
+ Movable M;
+};
+G::G(const Movable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: G::G(Movable M) : M(std::move(M)) {}
+
+// Test parameter with and without qualifier.
+namespace ns_H {
+typedef ::Movable HMovable;
+}
+struct H {
+ H(const ns_H::HMovable &M);
+ // CHECK-FIXES: H(ns_H::HMovable M);
+ ns_H::HMovable M;
+};
+using namespace ns_H;
+H::H(const HMovable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: H(HMovable M) : M(std::move(M)) {}
+
+// Try messing up with macros.
+#define MOVABLE_PARAM(Name) const Movable & Name
+// CHECK-FIXES: #define MOVABLE_PARAM(Name) const Movable & Name
+struct I {
+ I(MOVABLE_PARAM(M)) : M(M) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+ // CHECK-FIXES: I(MOVABLE_PARAM(M)) : M(M) {}
+ Movable M;
+};
+#undef MOVABLE_PARAM
+
+// Test that templates aren't modified.
+template <typename T> struct J {
+ J(const T &M) : M(M) {}
+ // CHECK-FIXES: J(const T &M) : M(M) {}
+ T M;
+};
+J<Movable> j1(Movable());
+J<NotMovable> j2(NotMovable());
+
+struct K_Movable {
+ K_Movable() = default;
+ K_Movable(const K_Movable &) = default;
+ K_Movable(K_Movable &&o) { dummy = o.dummy; }
+ int dummy;
+};
+
+// Test with movable type with an user defined move constructor.
+struct K {
+ K(const K_Movable &M) : M(M) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+ // CHECK-FIXES: K(K_Movable M) : M(std::move(M)) {}
+ K_Movable M;
+};
+
+template <typename T> struct L {
+ L(const Movable &M) : M(M) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+ // CHECK-FIXES: L(Movable M) : M(std::move(M)) {}
+ Movable M;
+};
+L<int> l(Movable());
+
+// Test with a non-instantiated template class.
+template <typename T> struct N {
+ N(const Movable &M) : M(M) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+ // CHECK-FIXES: N(Movable M) : M(std::move(M)) {}
+
+ Movable M;
+ T A;
+};
+
+// Test with value parameter.
+struct O {
+ O(Movable M) : M(M) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+ // CHECK-FIXES: O(Movable M) : M(std::move(M)) {}
+ Movable M;
+};
+
+// Test with a const-value parameter.
+struct P {
+ P(const Movable M) : M(M) {}
+ // CHECK-FIXES: P(const Movable M) : M(M) {}
+ Movable M;
+};
+
+// Test with multiples parameters where some need to be changed and some don't.
+// need to.
+struct Q {
+ Q(const Movable &A, const Movable &B, const Movable &C, double D)
+ : A(A), B(B), C(C), D(D) {}
+ // CHECK-MESSAGES: :[[@LINE-2]]:23: warning: pass by value and use std::move
+ // CHECK-MESSAGES: :[[@LINE-3]]:41: warning: pass by value and use std::move
+ // CHECK-FIXES: Q(const Movable &A, Movable B, Movable C, double D)
+ // CHECK-FIXES: : A(A), B(std::move(B)), C(std::move(C)), D(D) {}
+ const Movable &A;
+ Movable B;
+ Movable C;
+ double D;
+};
+
+// Test that value-parameters with a nested name specifier are left as-is.
+namespace ns_R {
+typedef ::Movable RMovable;
+}
+struct R {
+ R(ns_R::RMovable M) : M(M) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+ // CHECK-FIXES: R(ns_R::RMovable M) : M(std::move(M)) {}
+ ns_R::RMovable M;
+};
+
+// Test with rvalue parameter.
+struct S {
+ S(Movable &&M) : M(M) {}
+ // CHECK-FIXES: S(Movable &&M) : M(M) {}
+ Movable M;
+};
+
+template <typename T, int N> struct array { T A[N]; };
+
+// Test that types that are trivially copyable will not use std::move. This will
+// cause problems with performance-move-const-arg, as it will revert it.
+struct T {
+ T(array<int, 10> a) : a_(a) {}
+ // CHECK-FIXES: T(array<int, 10> a) : a_(a) {}
+ array<int, 10> a_;
+};
+
+struct U {
+ U(const POD &M) : M(M) {}
+ POD M;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-raw-string-literal-delimiter.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-raw-string-literal-delimiter.cpp
new file mode 100644
index 0000000..1dd3e13
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-raw-string-literal-delimiter.cpp
@@ -0,0 +1,9 @@
+// RUN: %check_clang_tidy %s modernize-raw-string-literal %t -- -config='{CheckOptions: [{key: "modernize-raw-string-literal.DelimiterStem", value: "str"}, {key: modernize-raw-string-literal.ReplaceShorterLiterals, value: 1}]}' -- -std=c++11
+
+char const *const ContainsSentinel{"who\\ops)\""};
+// CHECK-MESSAGES: :[[@LINE-1]]:36: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const ContainsSentinel{R"str(who\ops)")str"};{{$}}
+
+//char const *const ContainsDelim{"whoops)\")lit\""};
+// CHECK-XMESSAGES: :[[@LINE-1]]:33: warning: {{.*}} can be written as a raw string literal
+// CHECK-XFIXES: {{^}}char const *const ContainsDelim{R"lit1(whoops)")lit")lit1"};{{$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-raw-string-literal-replace-shorter.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-raw-string-literal-replace-shorter.cpp
new file mode 100644
index 0000000..673a8aa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-raw-string-literal-replace-shorter.cpp
@@ -0,0 +1,13 @@
+// RUN: %check_clang_tidy %s modernize-raw-string-literal %t
+
+// Don't replace these, because the raw literal would be longer.
+char const *const JustAQuote("quote:\'");
+char const *const NeedDelimiter("\":)\"");
+
+char const *const ManyQuotes("quotes:\'\'\'\'");
+// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const ManyQuotes(R"(quotes:'''')");{{$}}
+
+char const *const LongOctal("\042\072\051\042");
+// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const LongOctal(R"lit(":)")lit");{{$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-raw-string-literal.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-raw-string-literal.cpp
new file mode 100644
index 0000000..b6d4995
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-raw-string-literal.cpp
@@ -0,0 +1,131 @@
+// RUN: %check_clang_tidy %s modernize-raw-string-literal %t -- -config="{CheckOptions: [{key: modernize-raw-string-literal.ReplaceShorterLiterals, value: 1}]}" -- -std=c++11
+
+char const *const BackSlash("goink\\frob");
+// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: escaped string literal can be written as a raw string literal [modernize-raw-string-literal]
+// CHECK-FIXES: {{^}}char const *const BackSlash(R"(goink\frob)");{{$}}
+
+char const *const PlainLiteral("plain literal");
+
+// Non-printable ASCII characters.
+char const *const Nul("goink\\\000");
+char const *const Soh("goink\\\001");
+char const *const Stx("goink\\\002");
+char const *const Etx("goink\\\003");
+char const *const Enq("goink\\\004");
+char const *const Ack("goink\\\005");
+char const *const Bell("goink\\\afrob");
+char const *const BackSpace("goink\\\bfrob");
+char const *const HorizontalTab("goink\\\tfrob");
+char const *const NewLine("goink\nfrob");
+char const *const VerticalTab("goink\\\vfrob");
+char const *const FormFeed("goink\\\ffrob");
+char const *const CarraigeReturn("goink\\\rfrob");
+char const *const So("goink\\\016");
+char const *const Si("goink\\\017");
+char const *const Dle("goink\\\020");
+char const *const Dc1("goink\\\021");
+char const *const Dc2("goink\\\022");
+char const *const Dc3("goink\\\023");
+char const *const Dc4("goink\\\024");
+char const *const Nak("goink\\\025");
+char const *const Syn("goink\\\026");
+char const *const Etb("goink\\\027");
+char const *const Can("goink\\\030");
+char const *const Em("goink\\\031");
+char const *const Sub("goink\\\032");
+char const *const Esc("goink\\\033");
+char const *const Fs("goink\\\034");
+char const *const Gs("goink\\\035");
+char const *const Rs("goink\\\036");
+char const *const Us("goink\\\037");
+char const *const HexNonPrintable("\\\x03");
+char const *const Delete("\\\177");
+char const *const MultibyteSnowman("\xE2\x98\x83");
+// CHECK-FIXES: {{^}}char const *const MultibyteSnowman("\xE2\x98\x83");{{$}}
+
+char const *const TrailingSpace("A line \\with space. \n");
+char const *const TrailingNewLine("A single \\line.\n");
+char const *const AlreadyRaw(R"(foobie\\bletch)");
+char const *const UTF8Literal(u8"foobie\\bletch");
+char const *const UTF8RawLiteral(u8R"(foobie\\bletch)");
+// TODO: enable these tests once all supported compilers
+// support char16_t and char32_t (VS2013 does not)
+// char16_t const *const UTF16Literal(u"foobie\\bletch");
+// char16_t const *const UTF16RawLiteral(uR"(foobie\\bletch)");
+// char32_t const *const UTF32Literal(U"foobie\\bletch");
+// char32_t const *const UTF32RawLiteral(UR"(foobie\\bletch)");
+wchar_t const *const WideLiteral(L"foobie\\bletch");
+wchar_t const *const WideRawLiteral(LR"(foobie\\bletch)");
+
+char const *const SingleQuote("goink\'frob");
+// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: {{.*}} can be written as a raw string literal
+// CHECK-XFIXES: {{^}}char const *const SingleQuote(R"(goink'frob)");{{$}}
+
+char const *const DoubleQuote("goink\"frob");
+// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const DoubleQuote(R"(goink"frob)");{{$}}
+
+char const *const QuestionMark("goink\?frob");
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const QuestionMark(R"(goink?frob)");{{$}}
+
+char const *const RegEx("goink\\(one|two\\)\\\\\\?.*\\nfrob");
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const RegEx(R"(goink\(one|two\)\\\?.*\nfrob)");{{$}}
+
+char const *const Path("C:\\Program Files\\Vendor\\Application\\Application.exe");
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const Path(R"(C:\Program Files\Vendor\Application\Application.exe)");{{$}}
+
+char const *const ContainsSentinel("who\\ops)\"");
+// CHECK-MESSAGES: :[[@LINE-1]]:36: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const ContainsSentinel(R"lit(who\ops)")lit");{{$}}
+
+char const *const ContainsDelim("whoops)\")lit\"");
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const ContainsDelim(R"lit1(whoops)")lit")lit1");{{$}}
+
+char const *const OctalPrintable("\100\\");
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const OctalPrintable(R"(@\)");{{$}}
+
+char const *const HexPrintable("\x40\\");
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const HexPrintable(R"(@\)");{{$}}
+
+char const *const prettyFunction(__PRETTY_FUNCTION__);
+char const *const function(__FUNCTION__);
+char const *const func(__func__);
+
+#define TRICK(arg_) #arg_
+char const *const MacroBody = TRICK(foo\\bar);
+
+#define HAT(rabbit_) #rabbit_ "foo\\bar"
+char const *const StringizedMacroArgument = HAT(foo\\bar);
+
+#define SUBST(lit_) lit_
+char const *const MacroArgument = SUBST("foo\\bar");
+// FIXME: We should be able to replace this string literal macro argument
+
+template <typename T>
+void fn(char const *const Arg) {
+ char const *const Str("foo\\bar");
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: {{.*}} can be written as a raw string literal
+ // CHECK-FIXES: {{^}} char const *const Str(R"(foo\bar)");{{$}}
+}
+
+template <>
+void fn<int>(char const *const Arg) {
+ char const *const Str("foo\\bar");
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: {{.*}} can be written as a raw string literal
+ // CHECK-FIXES: {{^}} char const *const Str(R"(foo\bar)");{{$}}
+}
+
+void callFn() {
+ fn<int>("foo\\bar");
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} can be written as a raw string literal
+ // CHECK-FIXES: {{^}} fn<int>(R"(foo\bar)");{{$}}
+ fn<double>("foo\\bar");
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} can be written as a raw string literal
+ // CHECK-FIXES: {{^}} fn<double>(R"(foo\bar)");{{$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-redundant-void-arg-delayed.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-redundant-void-arg-delayed.cpp
new file mode 100644
index 0000000..dd88775
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-redundant-void-arg-delayed.cpp
@@ -0,0 +1,28 @@
+// RUN: %check_clang_tidy %s modernize-redundant-void-arg %t -- -- -fdelayed-template-parsing
+
+int foo(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant void argument list in function definition [modernize-redundant-void-arg]
+// CHECK-FIXES: {{^}}int foo() {{{$}}
+ return 0;
+}
+
+template <class T>
+struct MyFoo {
+ int foo(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant void argument list in function definition [modernize-redundant-void-arg]
+// CHECK-FIXES: {{^}} int foo() {{{$}}
+ return 0;
+ }
+};
+// Explicit instantiation.
+template class MyFoo<int>;
+
+template <class T>
+struct MyBar {
+ // This declaration isn't instantiated and won't be parsed 'delayed-template-parsing'.
+ int foo(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant void argument list in function definition [modernize-redundant-void-arg]
+// CHECK-FIXES: {{^}} int foo() {{{$}}
+ return 0;
+ }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-redundant-void-arg.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-redundant-void-arg.c
new file mode 100644
index 0000000..fdaf375
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-redundant-void-arg.c
@@ -0,0 +1,58 @@
+// RUN: clang-tidy -checks=-*,modernize-redundant-void-arg %s -- -x c | count 0
+
+#define NULL 0
+
+extern int i;
+
+int foo2() {
+ return 0;
+}
+
+int j = 1;
+
+int foo(void) {
+ return 0;
+}
+
+typedef unsigned int my_uint;
+
+typedef void my_void;
+
+// A function taking void and returning a pointer to function taking void
+// and returning int.
+int (*returns_fn_void_int(void))(void);
+
+typedef int (*returns_fn_void_int_t(void))(void);
+
+int (*returns_fn_void_int(void))(void) {
+ return NULL;
+}
+
+// A function taking void and returning a pointer to a function taking void
+// and returning a pointer to a function taking void and returning void.
+void (*(*returns_fn_returns_fn_void_void(void))(void))(void);
+
+typedef void (*(*returns_fn_returns_fn_void_void_t(void))(void))(void);
+
+void (*(*returns_fn_returns_fn_void_void(void))(void))(void) {
+ return NULL;
+}
+
+void bar() {
+ int i;
+ int *pi = NULL;
+ void *pv = (void *) pi;
+ float f;
+ float *fi;
+ double d;
+ double *pd;
+}
+
+void (*f1)(void);
+void (*f2)(void) = NULL;
+void (*f3)(void) = bar;
+void (*fa)();
+void (*fb)() = NULL;
+void (*fc)() = bar;
+
+typedef void (function_ptr)(void);
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-redundant-void-arg.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-redundant-void-arg.cpp
new file mode 100644
index 0000000..ea4b75f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-redundant-void-arg.cpp
@@ -0,0 +1,447 @@
+// RUN: %check_clang_tidy %s modernize-redundant-void-arg %t
+
+#define NULL 0
+
+int foo();
+
+void bar();
+
+void bar2();
+
+extern "C" void ecfoo(void);
+
+extern "C" void ecfoo(void) {
+}
+
+extern int i;
+
+int j = 1;
+
+int foo(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant void argument list in function definition [modernize-redundant-void-arg]
+// CHECK-FIXES: {{^}}int foo() {{{$}}
+ return 0;
+}
+
+typedef unsigned int my_uint;
+
+typedef void my_void;
+
+// A function taking void and returning a pointer to function taking void
+// and returning int.
+int (*returns_fn_void_int(void))(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: {{.*}} in function declaration
+// CHECK-MESSAGES: :[[@LINE-2]]:34: warning: {{.*}} in function declaration
+// CHECK-FIXES: {{^}}int (*returns_fn_void_int())();{{$}}
+
+typedef int (*returns_fn_void_int_t(void))(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: {{.*}} in typedef
+// CHECK-MESSAGES: :[[@LINE-2]]:44: warning: {{.*}} in typedef
+// CHECK-FIXES: {{^}}typedef int (*returns_fn_void_int_t())();{{$}}
+
+// Should work for type aliases as well as typedef.
+using returns_fn_void_int_t2 = int (*(void))(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: {{.*}} in type alias
+// CHECK-MESSAGES: :[[@LINE-2]]:46: warning: {{.*}} in type alias
+// CHECK-FIXES: {{^}}using returns_fn_void_int_t2 = int (*())();{{$}}
+
+int (*returns_fn_void_int(void))(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: {{.*}} in function definition
+// CHECK-MESSAGES: :[[@LINE-2]]:34: warning: {{.*}} in function definition
+// CHECK-FIXES: {{^}}int (*returns_fn_void_int())() {{{$}}
+ return nullptr;
+}
+
+// A function taking void and returning a pointer to a function taking void
+// and returning a pointer to a function taking void and returning void.
+void (*(*returns_fn_returns_fn_void_void(void))(void))(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:42: warning: {{.*}} in function declaration
+// CHECK-MESSAGES: :[[@LINE-2]]:49: warning: {{.*}} in function declaration
+// CHECK-MESSAGES: :[[@LINE-3]]:56: warning: {{.*}} in function declaration
+// CHECK-FIXES: {{^}}void (*(*returns_fn_returns_fn_void_void())())();{{$}}
+
+typedef void (*(*returns_fn_returns_fn_void_void_t(void))(void))(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:52: warning: {{.*}} in typedef
+// CHECK-MESSAGES: :[[@LINE-2]]:59: warning: {{.*}} in typedef
+// CHECK-MESSAGES: :[[@LINE-3]]:66: warning: {{.*}} in typedef
+// CHECK-FIXES: {{^}}typedef void (*(*returns_fn_returns_fn_void_void_t())())();{{$}}
+
+void (*(*returns_fn_returns_fn_void_void(void))(void))(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:42: warning: {{.*}} in function definition
+// CHECK-MESSAGES: :[[@LINE-2]]:49: warning: {{.*}} in function definition
+// CHECK-MESSAGES: :[[@LINE-3]]:56: warning: {{.*}} in function definition
+// CHECK-FIXES: {{^}}void (*(*returns_fn_returns_fn_void_void())())() {{{$}}
+ return nullptr;
+}
+
+void bar(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: {{.*}} in function definition
+// CHECK-FIXES: {{^}}void bar() {{{$}}
+}
+
+void op_fn(int i) {
+}
+
+class gronk {
+public:
+ gronk();
+ ~gronk();
+
+ void foo();
+ void bar();
+ void bar2
+ ();
+ void operation(int i) { }
+
+private:
+ int m_i;
+ int *m_pi;
+ float m_f;
+ float *m_pf;
+ double m_d;
+ double *m_pd;
+
+ void (*f1)(void);
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: {{.*}} in field declaration
+ // CHECK-FIXES: {{^ }}void (*f1)();{{$}}
+
+ void (*op)(int i);
+
+ void (gronk::*p1)(void);
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: {{.*}} in field declaration
+ // CHECK-FIXES: {{^ }}void (gronk::*p1)();{{$}}
+
+ int (gronk::*p_mi);
+
+ void (gronk::*p2)(int);
+
+ void (*(*returns_fn_returns_fn_void_void(void))(void))(void);
+ // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: {{.*}} in function declaration
+ // CHECK-MESSAGES: :[[@LINE-2]]:51: warning: {{.*}} in function declaration
+ // CHECK-MESSAGES: :[[@LINE-3]]:58: warning: {{.*}} in function declaration
+ // CHECK-FIXES: {{^}} void (*(*returns_fn_returns_fn_void_void())())();{{$}}
+
+ void (*(*(gronk::*returns_fn_returns_fn_void_void_mem)(void))(void))(void);
+ // CHECK-MESSAGES: :[[@LINE-1]]:58: warning: {{.*}} in field declaration
+ // CHECK-MESSAGES: :[[@LINE-2]]:65: warning: {{.*}} in field declaration
+ // CHECK-MESSAGES: :[[@LINE-3]]:72: warning: {{.*}} in field declaration
+ // CHECK-FIXES: {{^}} void (*(*(gronk::*returns_fn_returns_fn_void_void_mem)())())();{{$}}
+};
+
+int i;
+int *pi;
+void *pv = (void *) pi;
+float f;
+float *fi;
+double d;
+double *pd;
+
+void (*f1)(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: {{.*}} in variable declaration
+// CHECK-FIXES: {{^}}void (*f1)();{{$}}
+
+void (*f2)(void) = nullptr;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: {{.*}} in variable declaration with initializer
+// CHECK-FIXES: {{^}}void (*f2)() = nullptr;{{$}}
+
+void (*f2b)(void)(nullptr);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} in variable declaration with initializer
+// CHECK-FIXES: {{^}}void (*f2b)()(nullptr);{{$}}
+
+void (*f2c)(void){nullptr};
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} in variable declaration with initializer
+// CHECK-FIXES: {{^}}void (*f2c)(){nullptr};{{$}}
+
+void (*f2d)(void) = NULL;
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} in variable declaration with initializer
+// CHECK-FIXES: {{^}}void (*f2d)() = NULL;{{$}}
+
+void (*f2e)(void)(NULL);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} in variable declaration with initializer
+// CHECK-FIXES: {{^}}void (*f2e)()(NULL);{{$}}
+
+void (*f2f)(void){NULL};
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} in variable declaration with initializer
+// CHECK-FIXES: {{^}}void (*f2f)(){NULL};{{$}}
+
+void (*f3)(void) = bar;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: {{.*}} in variable declaration with initializer
+// CHECK-FIXES: {{^}}void (*f3)() = bar;{{$}}
+
+void (*o1)(int i);
+void (*o2)(int i) = nullptr;
+void (*o3)(int i)(nullptr);
+void (*o4)(int i){nullptr};
+void (*o5)(int i) = NULL;
+void (*o6)(int i)(NULL);
+void (*o7)(int i){NULL};
+void (*o8)(int i) = op_fn;
+
+void (*fa)();
+
+void (*fb)() = nullptr;
+
+void (*fc)() = bar;
+
+typedef void (function_ptr)(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: {{.*}} in typedef
+// CHECK-FIXES: {{^}}typedef void (function_ptr)();{{$}}
+
+// intentionally not LLVM style to check preservation of whitesapce
+typedef void (function_ptr2)
+ (
+ void
+ );
+// CHECK-MESSAGES: :[[@LINE-2]]:9: warning: {{.*}} in typedef
+// CHECK-FIXES: {{^typedef void \(function_ptr2\)$}}
+// CHECK-FIXES-NEXT: {{^ \($}}
+// CHECK-FIXES-NEXT: {{^ $}}
+// CHECK-FIXES-NEXT: {{^ \);$}}
+
+// intentionally not LLVM style to check preservation of whitesapce
+typedef
+void
+(
+*
+(
+*
+returns_fn_returns_fn_void_void_t2
+(
+void
+)
+)
+(
+void
+)
+)
+(
+void
+)
+;
+// CHECK-MESSAGES: :[[@LINE-11]]:1: warning: {{.*}} in typedef
+// CHECK-MESSAGES: :[[@LINE-8]]:1: warning: {{.*}} in typedef
+// CHECK-MESSAGES: :[[@LINE-5]]:1: warning: {{.*}} in typedef
+// CHECK-FIXES: {{^typedef$}}
+// CHECK-FIXES-NEXT: {{^void$}}
+// CHECK-FIXES-NEXT: {{^\($}}
+// CHECK-FIXES-NEXT: {{^\*$}}
+// CHECK-FIXES-NEXT: {{^\($}}
+// CHECK-FIXES-NEXT: {{^\*$}}
+// CHECK-FIXES-NEXT: {{^returns_fn_returns_fn_void_void_t2$}}
+// CHECK-FIXES-NEXT: {{^\($}}
+// CHECK-FIXES-NOT: {{[^ ]}}
+// CHECK-FIXES: {{^\)$}}
+// CHECK-FIXES-NEXT: {{^\)$}}
+// CHECK-FIXES-NEXT: {{^\($}}
+// CHECK-FIXES-NOT: {{[^ ]}}
+// CHECK-FIXES: {{^\)$}}
+// CHECK-FIXES-NEXT: {{^\)$}}
+// CHECK-FIXES-NEXT: {{^\($}}
+// CHECK-FIXES-NOT: {{[^ ]}}
+// CHECK-FIXES: {{^\)$}}
+// CHECK-FIXES-NEXT: {{^;$}}
+
+
+void (gronk::*p1)(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: {{.*}} in variable declaration
+// CHECK-FIXES: {{^}}void (gronk::*p1)();{{$}}
+
+void (gronk::*p2)(void) = &gronk::foo;
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: {{.*}} in variable declaration with initializer
+// CHECK-FIXES: {{^}}void (gronk::*p2)() = &gronk::foo;{{$}}
+
+typedef void (gronk::*member_function_ptr)(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:44: warning: {{.*}} in typedef
+// CHECK-FIXES: {{^}}typedef void (gronk::*member_function_ptr)();{{$}}
+
+// intentionally not LLVM style to check preservation of whitesapce
+typedef void (gronk::*member_function_ptr2)
+ (
+ void
+ );
+// CHECK-MESSAGES: :[[@LINE-2]]:9: warning: {{.*}} in typedef
+// CHECK-FIXES: {{^typedef void \(gronk::\*member_function_ptr2\)$}}
+// CHECK-FIXES-NEXT: {{^ \($}}
+// CHECK-FIXES-NEXT: {{^ $}}
+// CHECK-FIXES-NEXT: {{^ \);$}}
+
+void gronk::foo() {
+ void (*f1)(void) = &::bar;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} in variable declaration with initializer
+ // CHECK-FIXES: {{^ }}void (*f1)() = &::bar;{{$}}
+
+ void (*f2)(void);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} in variable declaration
+ // CHECK-FIXES: {{^ }}void (*f2)();{{$}}
+
+ // intentionally not LLVM style to check preservation of whitesapce
+ void (*f3)
+ (
+ void
+ );
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: {{.*}} in variable declaration
+ // CHECK-FIXES: {{^ }}void (*f3){{$}}
+ // CHECK-FIXES-NEXT: {{^ \($}}
+ // CHECK-FIXES-NEXT: {{^ $}}
+ // CHECK-FIXES-NEXT: {{^ \);$}}
+}
+
+void gronk::bar(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} in function definition
+// CHECK-FIXES: {{^}}void gronk::bar() {{{$}}
+ void (gronk::*p3)(void) = &gronk::foo;
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: {{.*}} in variable declaration with initializer
+ // CHECK-FIXES: {{^ }}void (gronk::*p3)() = &gronk::foo;{{$}}
+
+ void (gronk::*p4)(void);
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: {{.*}} in variable declaration
+ // CHECK-FIXES: {{^ }}void (gronk::*p4)();{{$}}
+
+ // intentionally not LLVM style to check preservation of whitesapce
+ void (gronk::*p5)
+ (
+ void
+ );
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: {{.*}} in variable declaration
+ // CHECK-FIXES: {{^ }}void (gronk::*p5){{$}}
+ // CHECK-FIXES-NEXT: {{^ \($}}
+ // CHECK-FIXES-NExT: {{^ $}}
+ // CHECK-FIXES-NExT: {{^ \);$}}
+}
+
+// intentionally not LLVM style to check preservation of whitesapce
+void gronk::bar2
+ (
+ void
+ )
+// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: {{.*}} in function definition
+// CHECK-FIXES: {{^void gronk::bar2$}}
+// CHECK-FIXES-NEXT: {{^ \($}}
+// CHECK-FIXES-NEXT: {{^ $}}
+// CHECK-FIXES-NEXT: {{^ \)$}}
+{
+}
+
+gronk::gronk(void)
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} in function definition
+// CHECK-FIXES: {{^}}gronk::gronk(){{$}}
+ : f1(nullptr),
+ p1(nullptr) {
+}
+
+gronk::~gronk(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} in function definition
+// CHECK-FIXES: {{^}}gronk::~gronk() {{{$}}
+}
+
+class nutter {
+public:
+ nutter();
+};
+
+nutter::nutter(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: {{.*}} in function definition
+// CHECK-FIXES: {{^}}nutter::nutter() {{{$}}
+ void (*f3)(void) = static_cast<void (*)(void)>(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} in variable declaration with initializer
+ // CHECK-MESSAGES: :[[@LINE-2]]:43: warning: {{.*}} in named cast
+ // CHECK-FIXES: void (*f3)() = static_cast<void (*)()>(0);{{$}}
+
+ void (*f4)(void) = (void (*)(void)) 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} in variable declaration with initializer
+ // CHECK-MESSAGES: :[[@LINE-2]]:32: warning: {{.*}} in cast expression
+ // CHECK-FIXES: void (*f4)() = (void (*)()) 0;{{$}}
+
+ void (*f5)(void) = reinterpret_cast<void (*)(void)>(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} in variable declaration with initializer
+ // CHECK-MESSAGES: :[[@LINE-2]]:48: warning: {{.*}} in named cast
+ // CHECK-FIXES: void (*f5)() = reinterpret_cast<void (*)()>(0);{{$}}
+
+ // intentionally not LLVM style to check preservation of whitesapce
+ void (*f6)(void) = static_cast<void (*)
+ (
+ void
+ )>(0);
+ // CHECK-MESSAGES: :[[@LINE-4]]:14: warning: {{.*}} in variable declaration with initializer
+ // CHECK-MESSAGES: :[[@LINE-3]]:11: warning: {{.*}} in named cast
+ // CHECK-FIXES: {{^ }}void (*f6)() = static_cast<void (*){{$}}
+ // CHECK-FIXES-NEXT: {{^ \($}}
+ // CHECK-FIXES-NEXT: {{^ $}}
+ // CHECK-FIXES-NEXT: {{^ }})>(0);{{$}}
+
+ // intentionally not LLVM style to check preservation of whitesapce
+ void (*f7)(void) = (void (*)
+ (
+ void
+ )) 0;
+ // CHECK-MESSAGES: :[[@LINE-4]]:14: warning: {{.*}} in variable declaration with initializer
+ // CHECK-MESSAGES: :[[@LINE-3]]:11: warning: {{.*}} in cast expression
+ // CHECK-FIXES: {{^ }}void (*f7)() = (void (*){{$}}
+ // CHECK-FIXES-NEXT: {{^ \($}}
+ // CHECK-FIXES-NEXT: {{^ $}}
+ // CHECK-FIXES-NEXT: {{^ \)\) 0;$}}
+
+ // intentionally not LLVM style to check preservation of whitesapce
+ void (*f8)(void) = reinterpret_cast<void (*)
+ (
+ void
+ )>(0);
+ // CHECK-MESSAGES: :[[@LINE-4]]:14: warning: {{.*}} in variable declaration with initializer
+ // CHECK-MESSAGES: :[[@LINE-3]]:11: warning: {{.*}} in named cast
+ // CHECK-FIXES: {{^ }}void (*f8)() = reinterpret_cast<void (*){{$}}
+ // CHECK-FIXES-NEXT: {{^ \($}}
+ // CHECK-FIXES-NEXT: {{^ $}}
+ // CHECK-FIXES-NEXT: {{^ \)>\(0\);$}}
+
+ void (*o1)(int) = static_cast<void (*)(int)>(0);
+ void (*o2)(int) = (void (*)(int)) 0;
+ void (*o3)(int) = reinterpret_cast<void (*)(int)>(0);
+}
+
+class generator {
+public:
+ int operator()(void) { return 1; }
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: {{.*}} in function definition
+ // CHECK-FIXES: {{^ }}int operator()() { return 1; }{{$}}
+};
+
+void test_lambda_functions() {
+ auto lamb_duh = [](void (*fn)(void)) { (*fn)(); };
+ // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: {{.*}} in variable declaration
+ // CHECK-FIXES: {{^ }}auto lamb_duh = [](void (*fn)()) { (*fn)(); };{{$}}
+
+ auto lambda_generator = [](void) { return 1; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: {{.*}} in lambda expression
+ // CHECK-FIXES: {{^ }}auto lambda_generator = []() { return 1; };{{$}}
+
+ auto gen2 = []() { return 1; };
+
+ auto gen3 = []{ return 1; };
+
+ auto void_returner = [](void) -> void (*)(void) { return f1; };
+ // CHECK-MESSAGES: [[@LINE-1]]:27: warning: {{.*}} in lambda expression
+ // CHECK-MESSAGES: [[@LINE-2]]:45: warning: {{.*}} in lambda expression
+ // CHECK-FIXES: {{^ }}auto void_returner = []() -> void (*)() { return f1; };{{$}}
+}
+
+#define M(x) x
+
+M(void inmacro(void) {})
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: {{.*}} in function definition
+// CHECK-FIXES: M(void inmacro() {})
+
+#define F(A, B) \
+ struct F_##A##_##B { \
+ F_##A##_##B(void); \
+ }; \
+ F_##A##_##B::F_##A##_##B(void)
+
+F(Foo, Bar) {
+
+}
+
+struct DefinitionWithNoBody {
+ DefinitionWithNoBody(void) = delete;
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: {{.*}} in function definition
+ // CHECK-FIXES: DefinitionWithNoBody() = delete;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-replace-auto-ptr.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-replace-auto-ptr.cpp
new file mode 100644
index 0000000..13405b2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-replace-auto-ptr.cpp
@@ -0,0 +1,304 @@
+// RUN: %check_clang_tidy %s modernize-replace-auto-ptr %t -- -- \
+// RUN: -std=c++11 -I %S/Inputs/modernize-replace-auto-ptr
+
+// CHECK-FIXES: #include <utility>
+
+#include "memory.h"
+
+// Instrumentation for auto_ptr_ref test.
+struct Base {};
+struct Derived : Base {};
+std::auto_ptr<Derived> create_derived_ptr();
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: auto_ptr is deprecated, use unique_ptr instead [modernize-replace-auto-ptr]
+// CHECK-FIXES: std::unique_ptr<Derived> create_derived_ptr();
+
+
+// Test function return values (declaration)
+std::auto_ptr<char> f_5();
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: auto_ptr is deprecated
+// CHECK-FIXES: std::unique_ptr<char> f_5()
+
+
+// Test function parameters.
+void f_6(std::auto_ptr<int>);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: auto_ptr is deprecated
+// CHECK-FIXES: void f_6(std::unique_ptr<int>);
+void f_7(const std::auto_ptr<int> &);
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: auto_ptr is deprecated
+// CHECK-FIXES: void f_7(const std::unique_ptr<int> &);
+
+
+// Test on record type fields.
+struct A {
+ std::auto_ptr<int> field;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+ // CHECK-FIXES: std::unique_ptr<int> field;
+
+ typedef std::auto_ptr<int> int_ptr_type;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: auto_ptr is deprecated
+ // CHECK-FIXES: typedef std::unique_ptr<int> int_ptr_type;
+};
+
+
+// FIXME: Test template WITH instantiation.
+template <typename T> struct B {
+ typedef typename std::auto_ptr<T> created_type;
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: auto_ptr is deprecated
+ // CHECK-FIXES: typedef typename std::unique_ptr<T> created_type;
+
+ created_type create() { return std::auto_ptr<T>(new T()); }
+ // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: auto_ptr is deprecated
+ // CHECK-FIXES: created_type create() { return std::unique_ptr<T>(new T()); }
+};
+
+
+// Test 'using' in a namespace (declaration)
+namespace ns_1 {
+// Test multiple using declarations.
+ using std::auto_ptr;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: auto_ptr is deprecated
+ // CHECK-FIXES: using std::unique_ptr;
+ using std::auto_ptr;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: auto_ptr is deprecated
+ // CHECK-FIXES: using std::unique_ptr;
+}
+
+
+namespace ns_2 {
+template <typename T> struct auto_ptr {};
+}
+
+void f_1() {
+ std::auto_ptr<int> a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+ // CHECK-FIXES: std::unique_ptr<int> a;
+
+ // Check that spaces aren't modified unnecessarily.
+ std:: auto_ptr <int> b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: auto_ptr is deprecated
+ // CHECK-FIXES: std:: unique_ptr <int> b;
+ std :: auto_ptr < char > c(new char());
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: auto_ptr is deprecated
+ // CHECK-FIXES: std :: unique_ptr < char > c(new char());
+
+ // Test construction from a temporary.
+ std::auto_ptr<char> d = std::auto_ptr<char>();
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+ // CHECK-MESSAGES: :[[@LINE-2]]:32: warning: auto_ptr is deprecated
+ // CHECK-FIXES: std::unique_ptr<char> d = std::unique_ptr<char>();
+
+ typedef std::auto_ptr<int> int_ptr_t;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: auto_ptr is deprecated
+ // CHECK-FIXES: typedef std::unique_ptr<int> int_ptr_t;
+ int_ptr_t e(new int());
+
+ // Test pointers.
+ std::auto_ptr<int> *f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+ // CHECK-FIXES: std::unique_ptr<int> *f;
+
+ // Test 'static' declarations.
+ static std::auto_ptr<int> g;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: auto_ptr is deprecated
+ // CHECK-FIXES: static std::unique_ptr<int> g;
+
+ // Test with cv-qualifiers.
+ const std::auto_ptr<int> h;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: auto_ptr is deprecated
+ // CHECK-FIXES: const std::unique_ptr<int> h;
+ volatile std::auto_ptr<int> i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: auto_ptr is deprecated
+ // CHECK-FIXES: volatile std::unique_ptr<int> i;
+ const volatile std::auto_ptr<int> j;
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: auto_ptr is deprecated
+ // CHECK-FIXES: const volatile std::unique_ptr<int> j;
+
+ // Test auto and initializer-list.
+ auto k = std::auto_ptr<int>{};
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: auto_ptr is deprecated
+ // CHECK-FIXES: auto k = std::unique_ptr<int>{};
+ std::auto_ptr<int> l{std::auto_ptr<int>()};
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+ // CHECK-MESSAGES: :[[@LINE-2]]:29: warning: auto_ptr is deprecated
+ // CHECK-FIXES: std::unique_ptr<int> l{std::unique_ptr<int>()};
+
+ // Test interlocked auto_ptr.
+ std::auto_ptr<std::auto_ptr<int> > m;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+ // CHECK-MESSAGES: :[[@LINE-2]]:22: warning: auto_ptr is deprecated
+ // CHECK-FIXES: std::unique_ptr<std::unique_ptr<int> > m;
+
+ // Test temporaries.
+ std::auto_ptr<char>();
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+ // CHECK-FIXES: std::unique_ptr<char>();
+
+ // Test void-specialization.
+ std::auto_ptr<void> n;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+ // CHECK-FIXES: std::unique_ptr<void> n;
+
+ // Test template WITH instantiation (instantiation).
+ B<double> o;
+ std::auto_ptr<double> p(o.create());
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+ // CHECK-FIXES: std::unique_ptr<double> p(o.create());
+
+ // Test 'using' in a namespace ("definition").
+ ns_1::auto_ptr<int> q;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: auto_ptr is deprecated
+ // CHECK-FIXES: ns_1::unique_ptr<int> q;
+
+ // Test construction with an 'auto_ptr_ref'.
+ std::auto_ptr<Base> r(create_derived_ptr());
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+ // CHECK-FIXES: std::unique_ptr<Base> r(create_derived_ptr());
+}
+
+// Test without the nested name specifiers.
+void f_2() {
+ using namespace std;
+
+ auto_ptr<int> a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: auto_ptr is deprecated
+ // CHECK-FIXES: unique_ptr<int> a;
+}
+
+// Test using declaration.
+void f_3() {
+ using std::auto_ptr;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: auto_ptr is deprecated
+ // CHECK-FIXES: using std::unique_ptr;
+
+ auto_ptr<int> a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: auto_ptr is deprecated
+ // CHECK-FIXES: unique_ptr<int> a;
+}
+
+// Test messing-up with macros.
+void f_4() {
+#define MACRO_1 <char>
+ std::auto_ptr MACRO_1 p(new char());
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+ // CHECK-FIXES: std::unique_ptr MACRO_1 p(new char());
+#define MACRO_2 auto_ptr
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: auto_ptr is deprecated
+ // CHECK-FIXES: #define MACRO_2 unique_ptr
+ std::MACRO_2<int> q;
+#define MACRO_3(Type) std::auto_ptr<Type>
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: auto_ptr is deprecated
+ // CHECK-FIXES: #define MACRO_3(Type) std::unique_ptr<Type>
+ MACRO_3(float)r(new float());
+#define MACRO_4 std::auto_ptr
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: auto_ptr is deprecated
+ // CHECK-FIXES: #define MACRO_4 std::unique_ptr
+ using MACRO_4;
+#undef MACRO_1
+#undef MACRO_2
+#undef MACRO_3
+#undef MACRO_4
+}
+
+// Test function return values (definition).
+std::auto_ptr<char> f_5()
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: auto_ptr is deprecated
+ // CHECK-FIXES: std::unique_ptr<char> f_5()
+{
+ // Test constructor.
+ return std::auto_ptr<char>(new char());
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: auto_ptr is deprecated
+ // CHECK-FIXES: return std::unique_ptr<char>(new char());
+}
+
+// Test that non-std auto_ptr aren't replaced.
+void f_8() {
+ ns_2::auto_ptr<char> a;
+ using namespace ns_2;
+ auto_ptr<int> b;
+}
+
+// Fail to modify when the template is never instantiated.
+//
+// This might not be an issue. If it's never used it doesn't really matter if
+// it's changed or not. If it's a header and one of the source use it, then it
+// will still be changed.
+template <typename X>
+void f() {
+ std::auto_ptr<X> p;
+}
+
+// FIXME: Alias template could be replaced if a matcher existed.
+namespace std {
+template <typename T> using aaaaaaaa = auto_ptr<T>;
+}
+
+// We want to avoid replacing 'aaaaaaaa' by unique_ptr here. It's better to
+// change the type alias directly.
+std::aaaaaaaa<int> d;
+
+
+void takes_ownership_fn(std::auto_ptr<int> x);
+// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: auto_ptr is deprecated
+// CHECK-FIXES: void takes_ownership_fn(std::unique_ptr<int> x);
+
+std::auto_ptr<int> get_by_value();
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: auto_ptr is deprecated
+// CHECK-FIXES: std::unique_ptr<int> get_by_value();
+
+class Wrapper {
+ public:
+ std::auto_ptr<int> &get_wrapped();
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+
+ private:
+ std::auto_ptr<int> wrapped;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+};
+
+void f() {
+ std::auto_ptr<int> a, b, c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+ // CHECK-FIXES: std::unique_ptr<int> a, b, c;
+ Wrapper wrapper_a, wrapper_b;
+
+ a = b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::move to transfer ownership
+ // CHECK-FIXES: a = std::move(b);
+
+ wrapper_a.get_wrapped() = wrapper_b.get_wrapped();
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::move to transfer ownership
+ // CHECK-FIXES: wrapper_a.get_wrapped() = std::move(wrapper_b.get_wrapped());
+
+ // Test that 'std::move()' is inserted when call to the
+ // copy-constructor are made.
+ takes_ownership_fn(c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use std::move to transfer ownership
+ // CHECK-FIXES: takes_ownership_fn(std::move(c));
+ takes_ownership_fn(wrapper_a.get_wrapped());
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use std::move to transfer ownership
+ // CHECK-FIXES: takes_ownership_fn(std::move(wrapper_a.get_wrapped()));
+
+ std::auto_ptr<int> d[] = { std::auto_ptr<int>(new int(1)),
+ std::auto_ptr<int>(new int(2)) };
+ // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: auto_ptr is deprecated
+ // CHECK-MESSAGES: :[[@LINE-3]]:35: warning: auto_ptr is deprecated
+ // CHECK-MESSAGES: :[[@LINE-3]]:35: warning: auto_ptr is deprecated
+ // CHECK-FIXES: std::unique_ptr<int> d[] = { std::unique_ptr<int>(new int(1)),
+ // CHECK-FIXES-NEXT: std::unique_ptr<int>(new int(2)) };
+ std::auto_ptr<int> e = d[0];
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+ // CHECK-MESSAGES: :[[@LINE-2]]:26: warning: use std::move to transfer ownership
+ // CHECK: std::unique_ptr<int> e = std::move(d[0]);
+
+ // Test that std::move() is not used when assigning an rvalue
+ std::auto_ptr<int> f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+ // CHECK-FIXES: std::unique_ptr<int> f;
+ f = std::auto_ptr<int>(new int(0));
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: auto_ptr is deprecated
+ // CHECK-NEXT: f = std::unique_ptr<int>(new int(0));
+
+ std::auto_ptr<int> g = get_by_value();
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+ // CHECK-FIXES: std::unique_ptr<int> g = get_by_value();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-replace-random-shuffle.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-replace-random-shuffle.cpp
new file mode 100644
index 0000000..019471e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-replace-random-shuffle.cpp
@@ -0,0 +1,57 @@
+// RUN: %check_clang_tidy %s modernize-replace-random-shuffle %t -- -- -std=c++11
+
+//CHECK-FIXES: #include <random>
+
+namespace std {
+template <typename T> struct vec_iterator {
+ T *ptr;
+ vec_iterator operator++(int);
+};
+
+template <typename T> struct vector {
+ typedef vec_iterator<T> iterator;
+
+ iterator begin();
+ iterator end();
+};
+
+template <typename FwIt>
+void random_shuffle(FwIt begin, FwIt end);
+
+template <typename FwIt, typename randomFunc>
+void random_shuffle(FwIt begin, FwIt end, randomFunc& randomfunc);
+
+template <typename FwIt>
+void shuffle(FwIt begin, FwIt end);
+} // namespace std
+
+// Random Func
+int myrandom (int i) { return i;}
+
+using namespace std;
+
+int main() {
+ std::vector<int> vec;
+
+ std::random_shuffle(vec.begin(), vec.end());
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::random_shuffle' has been removed in C++17; use 'std::shuffle' instead
+ // CHECK-FIXES: std::shuffle(vec.begin(), vec.end(), std::mt19937(std::random_device()()));
+
+ std::shuffle(vec.begin(), vec.end());
+
+ random_shuffle(vec.begin(), vec.end());
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::random_shuffle' has been removed in C++17; use 'std::shuffle' instead
+ // CHECK-FIXES: shuffle(vec.begin(), vec.end(), std::mt19937(std::random_device()()));
+
+ std::random_shuffle(vec.begin(), vec.end(), myrandom);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::random_shuffle' has been removed in C++17; use 'std::shuffle' and an alternative random mechanism instead
+ // CHECK-FIXES: std::shuffle(vec.begin(), vec.end(), std::mt19937(std::random_device()()));
+
+ random_shuffle(vec.begin(), vec.end(), myrandom);
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::random_shuffle' has been removed in C++17; use 'std::shuffle' and an alternative random mechanism instead
+ // CHECK-FIXES: shuffle(vec.begin(), vec.end(), std::mt19937(std::random_device()()));
+
+ shuffle(vec.begin(), vec.end());
+
+ return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-return-braced-init-list.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-return-braced-init-list.cpp
new file mode 100644
index 0000000..49a41ae
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-return-braced-init-list.cpp
@@ -0,0 +1,198 @@
+// RUN: %check_clang_tidy %s modernize-return-braced-init-list %t -- -- -std=c++14
+
+namespace std {
+typedef decltype(sizeof(int)) size_t;
+
+// libc++'s implementation
+template <class _E>
+class initializer_list {
+ const _E *__begin_;
+ size_t __size_;
+
+ initializer_list(const _E *__b, size_t __s)
+ : __begin_(__b),
+ __size_(__s) {}
+
+public:
+ typedef _E value_type;
+ typedef const _E &reference;
+ typedef const _E &const_reference;
+ typedef size_t size_type;
+
+ typedef const _E *iterator;
+ typedef const _E *const_iterator;
+
+ initializer_list() : __begin_(nullptr), __size_(0) {}
+
+ size_t size() const { return __size_; }
+ const _E *begin() const { return __begin_; }
+ const _E *end() const { return __begin_ + __size_; }
+};
+
+template <typename T>
+class vector {
+public:
+ vector(T) {}
+ vector(std::initializer_list<T>) {}
+};
+}
+
+class Bar {};
+
+Bar b0;
+
+class Foo {
+public:
+ Foo(Bar) {}
+ explicit Foo(Bar, unsigned int) {}
+ Foo(unsigned int) {}
+};
+
+class Baz {
+public:
+ Foo m() {
+ Bar bm;
+ return Foo(bm);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: avoid repeating the return type from the declaration; use a braced initializer list instead [modernize-return-braced-init-list]
+ // CHECK-FIXES: return {bm};
+ }
+};
+
+class Quux : public Foo {
+public:
+ Quux(Bar bar) : Foo(bar) {}
+ Quux(unsigned, unsigned, unsigned k = 0) : Foo(k) {}
+};
+
+Foo f() {
+ Bar b1;
+ return Foo(b1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+ // CHECK-FIXES: return {b1};
+}
+
+Foo f2() {
+ Bar b2;
+ return {b2};
+}
+
+auto f3() {
+ Bar b3;
+ return Foo(b3);
+}
+
+#define A(b) Foo(b)
+
+Foo f4() {
+ Bar b4;
+ return A(b4);
+}
+
+Foo f5() {
+ Bar b5;
+ return Quux(b5);
+}
+
+Foo f6() {
+ Bar b6;
+ return Foo(b6, 1);
+}
+
+std::vector<int> f7() {
+ int i7 = 1;
+ return std::vector<int>(i7);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+}
+
+Bar f8() {
+ return {};
+}
+
+Bar f9() {
+ return Bar();
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+}
+
+Bar f10() {
+ return Bar{};
+}
+
+Foo f11(Bar b11) {
+ return Foo(b11);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+ // CHECK-FIXES: return {b11};
+}
+
+Foo f12() {
+ return f11(Bar());
+}
+
+Foo f13() {
+ return Foo(Bar()); // 13
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+ // CHECK-FIXES: return {Bar()}; // 13
+}
+
+Foo f14() {
+ // FIXME: Type narrowing should not occur!
+ return Foo(-1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+ // CHECK-FIXES: return {-1};
+}
+
+Foo f15() {
+ return Foo(f10());
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+ // CHECK-FIXES: return {f10()};
+}
+
+Quux f16() {
+ return Quux(1, 2);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+ // CHECK-FIXES: return {1, 2};
+}
+
+Quux f17() {
+ return Quux(1, 2, 3);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+ // CHECK-FIXES: return {1, 2, 3};
+}
+
+template <typename T>
+T f19() {
+ return T();
+}
+
+Bar i1 = f19<Bar>();
+Baz i2 = f19<Baz>();
+
+template <typename T>
+Foo f20(T t) {
+ return Foo(t);
+}
+
+Foo i3 = f20(b0);
+
+template <typename T>
+class BazT {
+public:
+ T m() {
+ Bar b;
+ return T(b);
+ }
+
+ Foo m2(T t) {
+ return Foo(t);
+ }
+};
+
+BazT<Foo> bazFoo;
+Foo i4 = bazFoo.m();
+Foo i5 = bazFoo.m2(b0);
+
+BazT<Quux> bazQuux;
+Foo i6 = bazQuux.m();
+Foo i7 = bazQuux.m2(b0);
+
+auto v1 = []() { return std::vector<int>({1, 2}); }();
+auto v2 = []() -> std::vector<int> { return std::vector<int>({1, 2}); }();
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-shrink-to-fit.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-shrink-to-fit.cpp
new file mode 100644
index 0000000..6993d30
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-shrink-to-fit.cpp
@@ -0,0 +1,87 @@
+// RUN: %check_clang_tidy %s modernize-shrink-to-fit %t
+
+namespace std {
+template <typename T> struct vector { void swap(vector &other); };
+}
+
+void f() {
+ std::vector<int> v;
+
+ std::vector<int>(v).swap(v);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should be used to reduce the capacity of a shrinkable container [modernize-shrink-to-fit]
+ // CHECK-FIXES: {{^ }}v.shrink_to_fit();{{$}}
+
+ std::vector<int> &vref = v;
+ std::vector<int>(vref).swap(vref);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+ // CHECK-FIXES: {{^ }}vref.shrink_to_fit();{{$}}
+
+ std::vector<int> *vptr = &v;
+ std::vector<int>(*vptr).swap(*vptr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+ // CHECK-FIXES: {{^ }}vptr->shrink_to_fit();{{$}}
+}
+
+struct X {
+ std::vector<int> v;
+ void f() {
+ std::vector<int>(v).swap(v);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: the shrink_to_fit method should
+ // CHECK-FIXES: {{^ }}v.shrink_to_fit();{{$}}
+
+ std::vector<int> *vptr = &v;
+ std::vector<int>(*vptr).swap(*vptr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: the shrink_to_fit method should
+ // CHECK-FIXES: {{^ }}vptr->shrink_to_fit();{{$}}
+ }
+};
+
+template <typename T> void g() {
+ std::vector<int> v;
+ std::vector<int>(v).swap(v);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+ // CHECK-FIXES: {{^ }}v.shrink_to_fit();{{$}}
+
+ std::vector<T> v2;
+ std::vector<T>(v2).swap(v2);
+ // CHECK-FIXES: {{^ }}std::vector<T>(v2).swap(v2);{{$}}
+}
+
+template <typename T> void g2() {
+ std::vector<int> v;
+ std::vector<int>(v).swap(v);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+ // CHECK-FIXES: {{^ }}v.shrink_to_fit();{{$}}
+
+ T v3;
+ T(v3).swap(v3);
+ // CHECK-FIXES: {{^ }}T(v3).swap(v3);{{$}}
+}
+
+#define COPY_AND_SWAP_INT_VEC(x) std::vector<int>(x).swap(x)
+// CHECK-FIXES: #define COPY_AND_SWAP_INT_VEC(x) std::vector<int>(x).swap(x)
+
+void h() {
+ g<int>();
+ g<double>();
+ g<bool>();
+ g2<std::vector<int>>();
+ std::vector<int> v;
+ COPY_AND_SWAP_INT_VEC(v);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+ // CHECK-FIXES: {{^ }}COPY_AND_SWAP_INT_VEC(v);{{$}}
+}
+
+void PR38315() {
+ typedef std::vector<int> Vector;
+ Vector v;
+ Vector(v).swap(v);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+ // CHECK-FIXES: {{^ }}v.shrink_to_fit();{{$}}
+
+ using Vector2 = std::vector<int>;
+ Vector2 v2;
+ Vector2(v2).swap(v2);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+ // CHECK-FIXES: {{^ }}v2.shrink_to_fit();{{$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-unary-static-assert.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-unary-static-assert.cpp
new file mode 100644
index 0000000..fd39d5b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-unary-static-assert.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s modernize-unary-static-assert %t -- -- -std=c++1z
+
+#define FOO static_assert(sizeof(a) <= 15, "");
+#define MSG ""
+
+void f_textless(int a) {
+ static_assert(sizeof(a) <= 10, "");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use unary 'static_assert' when the string literal is an empty string [modernize-unary-static-assert]
+ // CHECK-FIXES: {{^}} static_assert(sizeof(a) <= 10 );{{$}}
+ static_assert(sizeof(a) <= 12, L"");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use unary 'static_assert' when
+ // CHECK-FIXES: {{^}} static_assert(sizeof(a) <= 12 );{{$}}
+ FOO
+ // CHECK-FIXES: {{^}} FOO{{$}}
+ static_assert(sizeof(a) <= 17, MSG);
+ // CHECK-FIXES: {{^}} static_assert(sizeof(a) <= 17, MSG);{{$}}
+}
+
+void f_with_tex(int a) {
+ static_assert(sizeof(a) <= 10, "Size of variable a is out of range!");
+}
+
+void f_unary(int a) { static_assert(sizeof(a) <= 10); }
+
+void f_incorrect_assert() { static_assert(""); }
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-cast-remove-stars.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-cast-remove-stars.cpp
new file mode 100644
index 0000000..97b87b8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-cast-remove-stars.cpp
@@ -0,0 +1,233 @@
+// RUN: %check_clang_tidy %s modernize-use-auto %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-auto.RemoveStars, value: '1'} , {key: modernize-use-auto.MinTypeNameLength, value: '0'}]}" \
+// RUN: -- -std=c++11 -frtti
+
+struct A {
+ virtual ~A() {}
+};
+
+struct B : public A {};
+
+struct C {};
+
+void f_static_cast() {
+ long l = 1;
+ int i1 = static_cast<int>(l);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto i1 = static_cast<int>(l);
+
+ const int i2 = static_cast<int>(l);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: const auto i2 = static_cast<int>(l);
+
+ long long ll = static_cast<long long>(l);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto ll = static_cast<long long>(l);
+ unsigned long long ull = static_cast<unsigned long long>(l);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto ull = static_cast<unsigned long long>(l);
+ unsigned int ui = static_cast<unsigned int>(l);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto ui = static_cast<unsigned int>(l);
+ long double ld = static_cast<long double>(l);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto ld = static_cast<long double>(l);
+
+ A *a = new B();
+ B *b1 = static_cast<B *>(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto b1 = static_cast<B *>(a);
+
+ B *const b2 = static_cast<B *>(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto const b2 = static_cast<B *>(a);
+
+ const B *b3 = static_cast<const B *>(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: const auto b3 = static_cast<const B *>(a);
+
+ B &b4 = static_cast<B &>(*a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto &b4 = static_cast<B &>(*a);
+
+ const B &b5 = static_cast<const B &>(*a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: const auto &b5 = static_cast<const B &>(*a);
+
+ B &b6 = static_cast<B &>(*a), &b7 = static_cast<B &>(*a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto &b6 = static_cast<B &>(*a), &b7 = static_cast<B &>(*a);
+
+ // Don't warn when non-cast involved
+ long double cast = static_cast<long double>(l), noncast = 5;
+
+ // Don't warn when auto is already being used.
+ auto i3 = static_cast<int>(l);
+ auto *b8 = static_cast<B *>(a);
+ auto &b9 = static_cast<B &>(*a);
+}
+
+void f_dynamic_cast() {
+ A *a = new B();
+ B *b1 = dynamic_cast<B *>(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto b1 = dynamic_cast<B *>(a);
+
+ B &b2 = dynamic_cast<B &>(*a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto &b2 = dynamic_cast<B &>(*a);
+}
+
+void f_reinterpret_cast() {
+ auto *a = new A();
+ C *c1 = reinterpret_cast<C *>(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto c1 = reinterpret_cast<C *>(a);
+
+ C &c2 = reinterpret_cast<C &>(*a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto &c2 = reinterpret_cast<C &>(*a);
+}
+
+void f_const_cast() {
+ const A *a1 = new A();
+ A *a2 = const_cast<A *>(a1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto a2 = const_cast<A *>(a1);
+ A &a3 = const_cast<A &>(*a1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto &a3 = const_cast<A &>(*a1);
+}
+
+typedef unsigned char xmlChar;
+#define BAD_CAST (xmlChar *)
+
+#define XMLCHAR_CAST(x) (xmlChar *)(x)
+
+#define CAST_IN_MACRO(x) \
+ do { \
+ xmlChar *s = (xmlChar *)(x); \
+ } while (false);
+// CHECK-FIXES: xmlChar *s = (xmlChar *)(x);
+
+void f_cstyle_cast() {
+ auto *a = new A();
+ C *c1 = (C *)a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto c1 = (C *)a;
+
+ C &c2 = (C &)*a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto &c2 = (C &)*a;
+
+ xmlChar *s = BAD_CAST "xml";
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto s = BAD_CAST "xml";
+ xmlChar *t = XMLCHAR_CAST("xml");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto t = XMLCHAR_CAST("xml");
+ CAST_IN_MACRO("xml");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+}
+
+void f_functional_cast() {
+ long l = 1;
+ int i1 = int(l);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto i1 = int(l);
+
+ B b;
+ A a = A(b);
+}
+
+class StringRef
+{
+public:
+ StringRef(const char *);
+ const char *begin() const;
+ const char *end() const;
+};
+
+template <typename T, typename U>
+T template_value_cast(const U &u);
+
+template <typename T, typename U>
+T *template_pointer_cast(U *u);
+
+template <typename T, typename U>
+T &template_reference_cast(U &u);
+
+template <typename T, typename U>
+const T *template_const_pointer_cast(const U *u);
+
+template <typename T, typename U>
+const T &template_const_reference_cast(const U &u);
+
+template <typename T>
+T template_value_get(StringRef s);
+
+struct S {
+ template <typename T>
+ const T *template_member_get();
+};
+
+template <typename T>
+T max(T t1, T t2);
+
+void f_template_cast()
+{
+ double d = 0;
+ int i1 = template_value_cast<int>(d);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: auto i1 = template_value_cast<int>(d);
+
+ A *a = new B();
+ B *b1 = template_value_cast<B *>(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: auto b1 = template_value_cast<B *>(a);
+ B &b2 = template_value_cast<B &>(*a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: auto &b2 = template_value_cast<B &>(*a);
+ B *b3 = template_pointer_cast<B>(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: auto b3 = template_pointer_cast<B>(a);
+ B &b4 = template_reference_cast<B>(*a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: auto &b4 = template_reference_cast<B>(*a);
+ const B *b5 = template_const_pointer_cast<B>(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: const auto b5 = template_const_pointer_cast<B>(a);
+ const B &b6 = template_const_reference_cast<B>(*a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: const auto &b6 = template_const_reference_cast<B>(*a);
+ B *b7 = template_value_get<B *>("foo");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: auto b7 = template_value_get<B *>("foo");
+ B *b8 = template_value_get<B *>("foo"), *b9 = template_value_get<B *>("bar");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: auto b8 = template_value_get<B *>("foo"), b9 = template_value_get<B *>("bar");
+
+ S s;
+ const B *b10 = s.template_member_get<B>();
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: const auto b10 = s.template_member_get<B>();
+
+ // Don't warn when auto is already being used.
+ auto i2 = template_value_cast<int>(d);
+ auto *i3 = template_value_cast<int *>(d);
+ auto **i4 = template_value_cast<int **>(d);
+ auto &i5 = template_reference_cast<int>(d);
+
+ // Don't warn for implicit template arguments.
+ int i6 = max(i1, i2);
+
+ // Don't warn for mismatched var and initializer types.
+ A *a1 = template_value_cast<B *>(a);
+
+ // Don't warn for mismatched var types.
+ B *b11 = template_value_get<B *>("foo"), b12 = template_value_get<B>("bar");
+
+ // Don't warn for implicit variables.
+ for (auto &c : template_reference_cast<StringRef>(*a)) {
+ }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-cast.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-cast.cpp
new file mode 100644
index 0000000..e07c9cb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-cast.cpp
@@ -0,0 +1,233 @@
+// RUN: %check_clang_tidy %s modernize-use-auto %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-auto.MinTypeNameLength, value: '0'}]}" \
+// RUN: -- -std=c++11 -I %S/Inputs/modernize-use-auto -frtti
+
+struct A {
+ virtual ~A() {}
+};
+
+struct B : public A {};
+
+struct C {};
+
+void f_static_cast() {
+ long l = 1;
+ int i1 = static_cast<int>(l);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto i1 = static_cast<int>(l);
+
+ const int i2 = static_cast<int>(l);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: const auto i2 = static_cast<int>(l);
+
+ long long ll = static_cast<long long>(l);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto ll = static_cast<long long>(l);
+ unsigned long long ull = static_cast<unsigned long long>(l);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto ull = static_cast<unsigned long long>(l);
+ unsigned int ui = static_cast<unsigned int>(l);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto ui = static_cast<unsigned int>(l);
+ long double ld = static_cast<long double>(l);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto ld = static_cast<long double>(l);
+
+ A *a = new B();
+ B *b1 = static_cast<B *>(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto *b1 = static_cast<B *>(a);
+
+ B *const b2 = static_cast<B *>(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto *const b2 = static_cast<B *>(a);
+
+ const B *b3 = static_cast<const B *>(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: const auto *b3 = static_cast<const B *>(a);
+
+ B &b4 = static_cast<B &>(*a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto &b4 = static_cast<B &>(*a);
+
+ const B &b5 = static_cast<const B &>(*a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: const auto &b5 = static_cast<const B &>(*a);
+
+ B &b6 = static_cast<B &>(*a), &b7 = static_cast<B &>(*a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto &b6 = static_cast<B &>(*a), &b7 = static_cast<B &>(*a);
+
+ // Don't warn when non-cast involved
+ long double cast = static_cast<long double>(l), noncast = 5;
+
+ // Don't warn when auto is already being used.
+ auto i3 = static_cast<int>(l);
+ auto *b8 = static_cast<B *>(a);
+ auto &b9 = static_cast<B &>(*a);
+}
+
+void f_dynamic_cast() {
+ A *a = new B();
+ B *b1 = dynamic_cast<B *>(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto *b1 = dynamic_cast<B *>(a);
+
+ B &b2 = dynamic_cast<B &>(*a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto &b2 = dynamic_cast<B &>(*a);
+}
+
+void f_reinterpret_cast() {
+ auto *a = new A();
+ C *c1 = reinterpret_cast<C *>(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto *c1 = reinterpret_cast<C *>(a);
+
+ C &c2 = reinterpret_cast<C &>(*a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto &c2 = reinterpret_cast<C &>(*a);
+}
+
+void f_const_cast() {
+ const A *a1 = new A();
+ A *a2 = const_cast<A *>(a1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto *a2 = const_cast<A *>(a1);
+ A &a3 = const_cast<A &>(*a1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto &a3 = const_cast<A &>(*a1);
+}
+
+typedef unsigned char xmlChar;
+#define BAD_CAST (xmlChar *)
+
+#define XMLCHAR_CAST(x) (xmlChar *)(x)
+
+#define CAST_IN_MACRO(x) \
+ do { \
+ xmlChar *s = (xmlChar *)(x); \
+ } while (false);
+// CHECK-FIXES: xmlChar *s = (xmlChar *)(x);
+
+void f_cstyle_cast() {
+ auto *a = new A();
+ C *c1 = (C *)a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto *c1 = (C *)a;
+
+ C &c2 = (C &)*a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto &c2 = (C &)*a;
+
+ xmlChar *s = BAD_CAST "xml";
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto *s = BAD_CAST "xml";
+ xmlChar *t = XMLCHAR_CAST("xml");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto *t = XMLCHAR_CAST("xml");
+ CAST_IN_MACRO("xml");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+}
+
+void f_functional_cast() {
+ long l = 1;
+ int i1 = int(l);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+ // CHECK-FIXES: auto i1 = int(l);
+
+ B b;
+ A a = A(b);
+}
+
+class StringRef
+{
+public:
+ StringRef(const char *);
+ const char *begin() const;
+ const char *end() const;
+};
+
+template <typename T, typename U>
+T template_value_cast(const U &u);
+
+template <typename T, typename U>
+T *template_pointer_cast(U *u);
+
+template <typename T, typename U>
+T &template_reference_cast(U &u);
+
+template <typename T, typename U>
+const T *template_const_pointer_cast(const U *u);
+
+template <typename T, typename U>
+const T &template_const_reference_cast(const U &u);
+
+template <typename T>
+T template_value_get(StringRef s);
+
+struct S {
+ template <typename T>
+ const T *template_member_get();
+};
+
+template <typename T>
+T max(T t1, T t2);
+
+void f_template_cast()
+{
+ double d = 0;
+ int i1 = template_value_cast<int>(d);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: auto i1 = template_value_cast<int>(d);
+
+ A *a = new B();
+ B *b1 = template_value_cast<B *>(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: auto *b1 = template_value_cast<B *>(a);
+ B &b2 = template_value_cast<B &>(*a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: auto &b2 = template_value_cast<B &>(*a);
+ B *b3 = template_pointer_cast<B>(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: auto *b3 = template_pointer_cast<B>(a);
+ B &b4 = template_reference_cast<B>(*a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: auto &b4 = template_reference_cast<B>(*a);
+ const B *b5 = template_const_pointer_cast<B>(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: const auto *b5 = template_const_pointer_cast<B>(a);
+ const B &b6 = template_const_reference_cast<B>(*a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: const auto &b6 = template_const_reference_cast<B>(*a);
+ B *b7 = template_value_get<B *>("foo");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: auto *b7 = template_value_get<B *>("foo");
+ B *b8 = template_value_get<B *>("foo"), *b9 = template_value_get<B *>("bar");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: auto *b8 = template_value_get<B *>("foo"), *b9 = template_value_get<B *>("bar");
+
+ S s;
+ const B *b10 = s.template_member_get<B>();
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a template cast to avoid duplicating the type name
+ // CHECK-FIXES: const auto *b10 = s.template_member_get<B>();
+
+ // Don't warn when auto is already being used.
+ auto i2 = template_value_cast<int>(d);
+ auto *i3 = template_value_cast<int *>(d);
+ auto **i4 = template_value_cast<int **>(d);
+ auto &i5 = template_reference_cast<int>(d);
+
+ // Don't warn for implicit template arguments.
+ int i6 = max(i1, i2);
+
+ // Don't warn for mismatched var and initializer types.
+ A *a1 = template_value_cast<B *>(a);
+
+ // Don't warn for mismatched var types.
+ B *b11 = template_value_get<B *>("foo"), b12 = template_value_get<B>("bar");
+
+ // Don't warn for implicit variables.
+ for (auto &c : template_reference_cast<StringRef>(*a)) {
+ }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-iterator.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-iterator.cpp
new file mode 100644
index 0000000..98117fc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-iterator.cpp
@@ -0,0 +1,320 @@
+// RUN: %check_clang_tidy %s modernize-use-auto %t -- -- \
+// RUN: -std=c++11 -I %S/Inputs/modernize-use-auto
+
+#include "containers.h"
+
+void f_array() {
+ std::array<int, 4> C;
+ std::array<int, 4>::iterator ArrayI1 = C.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators [modernize-use-auto]
+ // CHECK-FIXES: auto ArrayI1 = C.begin();
+
+ std::array<int, 5>::reverse_iterator ArrayI2 = C.rbegin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto ArrayI2 = C.rbegin();
+
+ const std::array<int, 3> D;
+ std::array<int, 3>::const_iterator ArrayI3 = D.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto ArrayI3 = D.begin();
+
+ std::array<int, 5>::const_reverse_iterator ArrayI4 = D.rbegin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto ArrayI4 = D.rbegin();
+}
+
+void f_deque() {
+ std::deque<int> C;
+ std::deque<int>::iterator DequeI1 = C.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto DequeI1 = C.begin();
+
+ std::deque<int>::reverse_iterator DequeI2 = C.rbegin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto DequeI2 = C.rbegin();
+
+ const std::deque<int> D;
+ std::deque<int>::const_iterator DequeI3 = D.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto DequeI3 = D.begin();
+
+ std::deque<int>::const_reverse_iterator DequeI4 = D.rbegin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto DequeI4 = D.rbegin();
+}
+
+void f_forward_list() {
+ std::forward_list<int> C;
+ std::forward_list<int>::iterator FListI1 = C.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto FListI1 = C.begin();
+
+ const std::forward_list<int> D;
+ std::forward_list<int>::const_iterator FListI2 = D.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto FListI2 = D.begin();
+}
+
+void f_list() {
+ std::list<int> C;
+ std::list<int>::iterator ListI1 = C.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto ListI1 = C.begin();
+ std::list<int>::reverse_iterator ListI2 = C.rbegin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto ListI2 = C.rbegin();
+
+ const std::list<int> D;
+ std::list<int>::const_iterator ListI3 = D.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto ListI3 = D.begin();
+ std::list<int>::const_reverse_iterator ListI4 = D.rbegin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto ListI4 = D.rbegin();
+}
+
+void f_vector() {
+ std::vector<int> C;
+ std::vector<int>::iterator VecI1 = C.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto VecI1 = C.begin();
+
+ std::vector<int>::reverse_iterator VecI2 = C.rbegin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto VecI2 = C.rbegin();
+
+ const std::vector<int> D;
+ std::vector<int>::const_iterator VecI3 = D.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto VecI3 = D.begin();
+
+ std::vector<int>::const_reverse_iterator VecI4 = D.rbegin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto VecI4 = D.rbegin();
+}
+
+void f_map() {
+ std::map<int, int> C;
+ std::map<int, int>::iterator MapI1 = C.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto MapI1 = C.begin();
+
+ std::map<int, int>::reverse_iterator MapI2 = C.rbegin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto MapI2 = C.rbegin();
+
+ const std::map<int, int> D;
+ std::map<int, int>::const_iterator MapI3 = D.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto MapI3 = D.begin();
+
+ std::map<int, int>::const_reverse_iterator MapI4 = D.rbegin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto MapI4 = D.rbegin();
+}
+
+void f_multimap() {
+ std::multimap<int, int> C;
+ std::multimap<int, int>::iterator MMapI1 = C.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto MMapI1 = C.begin();
+
+ std::multimap<int, int>::reverse_iterator MMapI2 = C.rbegin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto MMapI2 = C.rbegin();
+
+ const std::multimap<int, int> D;
+ std::multimap<int, int>::const_iterator MMapI3 = D.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto MMapI3 = D.begin();
+
+ std::multimap<int, int>::const_reverse_iterator MMapI4 = D.rbegin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto MMapI4 = D.rbegin();
+}
+
+void f_set() {
+ std::set<int> C;
+ std::set<int>::iterator SetI1 = C.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto SetI1 = C.begin();
+
+ std::set<int>::reverse_iterator SetI2 = C.rbegin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto SetI2 = C.rbegin();
+
+ const std::set<int> D;
+ std::set<int>::const_iterator SetI3 = D.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto SetI3 = D.begin();
+
+ std::set<int>::const_reverse_iterator SetI4 = D.rbegin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto SetI4 = D.rbegin();
+}
+
+void f_multiset() {
+ std::multiset<int> C;
+ std::multiset<int>::iterator MSetI1 = C.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto MSetI1 = C.begin();
+
+ std::multiset<int>::reverse_iterator MSetI2 = C.rbegin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto MSetI2 = C.rbegin();
+
+ const std::multiset<int> D;
+ std::multiset<int>::const_iterator MSetI3 = D.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto MSetI3 = D.begin();
+
+ std::multiset<int>::const_reverse_iterator MSetI4 = D.rbegin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto MSetI4 = D.rbegin();
+}
+
+void f_unordered_map() {
+ std::unordered_map<int, int> C;
+ std::unordered_map<int, int>::iterator UMapI1 = C.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto UMapI1 = C.begin();
+
+ const std::unordered_map<int, int> D;
+ std::unordered_map<int, int>::const_iterator UMapI2 = D.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto UMapI2 = D.begin();
+}
+
+void f_unordered_multimap() {
+ std::unordered_multimap<int, int> C;
+ std::unordered_multimap<int, int>::iterator UMMapI1 = C.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto UMMapI1 = C.begin();
+
+ const std::unordered_multimap<int, int> D;
+ std::unordered_multimap<int, int>::const_iterator UMMapI2 = D.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto UMMapI2 = D.begin();
+}
+
+void f_unordered_set() {
+ std::unordered_set<int> C;
+ std::unordered_set<int>::iterator USetI1 = C.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto USetI1 = C.begin();
+
+ const std::unordered_set<int> D;
+ std::unordered_set<int>::const_iterator USetI2 = D.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto USetI2 = D.begin();
+}
+
+void f_unordered_multiset() {
+ std::unordered_multiset<int> C;
+ std::unordered_multiset<int>::iterator UMSetI1 = C.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto UMSetI1 = C.begin();
+
+ const std::unordered_multiset<int> D;
+ std::unordered_multiset<int>::const_iterator UMSetI2 = D.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto UMSetI2 = D.begin();
+}
+
+typedef std::vector<int>::iterator int_iterator;
+
+std::vector<int> Vec;
+std::unordered_map<int, int> Map;
+
+void sugar() {
+ // Types with more sugar should work. Types with less should not.
+ int_iterator more_sugar = Vec.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto more_sugar = Vec.begin();
+}
+
+void initializer_list() {
+ // Initialization from initializer lists isn't allowed. Using 'auto' would
+ // result in std::initializer_list being deduced for the type.
+ std::unordered_map<int, int>::iterator I{Map.begin()};
+ std::unordered_map<int, int>::iterator I2 = {Map.begin()};
+}
+
+void construction() {
+ // Various forms of construction. Default constructors and constructors with
+ // all-default parameters shouldn't get transformed. Construction from other
+ // types is also not allowed.
+
+ std::unordered_map<int, int>::iterator copy(Map.begin());
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto copy(Map.begin());
+
+ std::unordered_map<int, int>::iterator def;
+ std::unordered_map<int, int>::const_iterator constI;
+
+ // Implicit conversion.
+ std::unordered_map<int, int>::const_iterator constI2 = def;
+ std::unordered_map<int, int>::const_iterator constI3(def);
+
+ // Explicit conversion
+ std::unordered_map<int, int>::const_iterator constI4
+ = std::unordered_map<int, int>::const_iterator(def);
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto constI4
+ // CHECK-FIXES-NEXT: = std::unordered_map<int, int>::const_iterator(def);
+}
+
+void pointer_to_iterator() {
+ int_iterator I = Vec.begin();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto I = Vec.begin();
+
+ // Pointers and references to iterators are not transformed.
+ int_iterator *IPtr = &I;
+ int_iterator &IRef = I;
+}
+
+void loop() {
+ for (std::vector<int>::iterator I = Vec.begin(); I != Vec.end(); ++I) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use auto when declaring iterators
+ // CHECK-FIXES: for (auto I = Vec.begin(); I != Vec.end(); ++I)
+ }
+
+ for (int_iterator I = Vec.begin(), E = Vec.end(); I != E; ++I) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use auto when declaring iterators
+ // CHECK-FIXES: for (auto I = Vec.begin(), E = Vec.end(); I != E; ++I)
+ }
+
+ std::vector<std::vector<int>::iterator> IterVec;
+ for (std::vector<int>::iterator I : IterVec) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use auto when declaring iterators
+ // CHECK-FIXES: for (auto I : IterVec)
+ }
+}
+
+void cv_qualifiers() {
+ // Make sure references and cv qualifiers don't get removed (i.e. replaced
+ // with just 'auto').
+ const auto & I = Vec.begin();
+ auto && I2 = Vec.begin();
+}
+
+void cleanup() {
+ // Passing a string as an argument to introduce a temporary object that will
+ // create an expression with cleanups.
+ std::map<std::string, int> MapFind;
+ std::map<std::string, int>::iterator I = MapFind.find("foo");
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto I = MapFind.find("foo");
+}
+
+void declaration_lists() {
+ // Declaration lists that match the declaration type with written no-list
+ // initializer are transformed.
+ std::vector<int>::iterator I = Vec.begin(), E = Vec.end();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+ // CHECK-FIXES: auto I = Vec.begin(), E = Vec.end();
+
+ // Declaration lists with non-initialized variables should not be transformed.
+ std::vector<int>::iterator J = Vec.begin(), K;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-min-type-name-length.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-min-type-name-length.cpp
new file mode 100644
index 0000000..1cd9158
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-min-type-name-length.cpp
@@ -0,0 +1,85 @@
+// RUN: %check_clang_tidy -check-suffix=0-0 %s modernize-use-auto %t -- -config="{CheckOptions: [{key: modernize-use-auto.RemoveStars, value: 0}, {key: modernize-use-auto.MinTypeNameLength, value: 0}]}" -- --std=c++11 -frtti
+// RUN: %check_clang_tidy -check-suffix=0-8 %s modernize-use-auto %t -- -config="{CheckOptions: [{key: modernize-use-auto.RemoveStars, value: 0}, {key: modernize-use-auto.MinTypeNameLength, value: 8}]}" -- --std=c++11 -frtti
+// RUN: %check_clang_tidy -check-suffix=1-0 %s modernize-use-auto %t -- -config="{CheckOptions: [{key: modernize-use-auto.RemoveStars, value: 1}, {key: modernize-use-auto.MinTypeNameLength, value: 0}]}" -- --std=c++11 -frtti
+// RUN: %check_clang_tidy -check-suffix=1-8 %s modernize-use-auto %t -- -config="{CheckOptions: [{key: modernize-use-auto.RemoveStars, value: 1}, {key: modernize-use-auto.MinTypeNameLength, value: 8}]}" -- --std=c++11 -frtti
+
+template <class T> extern T foo();
+template <class T> struct P { explicit P(T t) : t_(t) {} T t_;};
+template <class T> P<T> *foo_ptr();
+template <class T> P<T> &foo_ref();
+
+int bar() {
+ {
+ // Lenth(long) = 4
+ long i = static_cast<long>(foo<long>());
+ // CHECK-FIXES-0-0: auto i = {{.*}}
+ // CHECK-FIXES-0-8: long i = {{.*}}
+ // CHECK-FIXES-1-0: auto i = {{.*}}
+ // CHECK-FIXES-1-8: long i = {{.*}}
+ const long ci = static_cast<long>(foo<const long>());
+ // CHECK-FIXES-0-0: auto ci = {{.*}}
+ // CHECK-FIXES-0-8: long ci = {{.*}}
+ // CHECK-FIXES-1-0: auto ci = {{.*}}
+ // CHECK-FIXES-1-8: long ci = {{.*}}
+ long *pi = static_cast<long *>(foo<long *>());
+ // CHECK-FIXES-0-0: auto *pi = {{.*}}
+ // CHECK-FIXES-0-8: long *pi = {{.*}}
+ // CHECK-FIXES-1-0: auto pi = {{.*}}
+ // CHECK-FIXES-1-8: long *pi = {{.*}}
+
+ // Length(long *) is still 5
+ long * pi2 = static_cast<long *>(foo<long *>());
+ // CHECK-FIXES-0-0: auto * pi2 = {{.*}}
+ // CHECK-FIXES-0-8: long * pi2 = {{.*}}
+ // CHECK-FIXES-1-0: auto pi2 = {{.*}}
+ // CHECK-FIXES-1-8: long * pi2 = {{.*}}
+
+ // Length(long **) = 6
+ long **ppi = static_cast<long **>(foo<long **>());
+ // CHECK-FIXES-0-0: auto **ppi = {{.*}}
+ // CHECK-FIXES-0-8: long **ppi = {{.*}}
+ // CHECK-FIXES-1-0: auto ppi = {{.*}}
+ // CHECK-FIXES-1-8: long **ppi = {{.*}}
+ }
+
+ {
+ // Lenth(long int) = 4 + 1 + 3 = 8
+ // Lenth(long int) is still 8
+ long int i = static_cast<long int>(foo<long int>());
+ // CHECK-FIXES-0-0: auto i = {{.*}}
+ // CHECK-FIXES-0-8: auto i = {{.*}}
+ // CHECK-FIXES-1-0: auto i = {{.*}}
+ // CHECK-FIXES-1-8: auto i = {{.*}}
+
+ long int *pi = static_cast<long int *>(foo<long int *>());
+ // CHECK-FIXES-0-0: auto *pi = {{.*}}
+ // CHECK-FIXES-0-8: auto *pi = {{.*}}
+ // CHECK-FIXES-1-0: auto pi = {{.*}}
+ // CHECK-FIXES-1-8: auto pi = {{.*}}
+ }
+
+ // Templates
+ {
+ // Length(P<long>) = 7
+ P<long>& i = static_cast<P<long>&>(foo_ref<long>());
+ // CHECK-FIXES-0-0: auto& i = {{.*}}
+ // CHECK-FIXES-0-8: P<long>& i = {{.*}}
+ // CHECK-FIXES-1-0: auto & i = {{.*}}
+ // CHECK-FIXES-1-8: P<long>& i = {{.*}}
+
+ // Length(P<long*>) = 8
+ P<long*>& pi = static_cast<P<long*> &>(foo_ref<long*>());
+ // CHECK-FIXES-0-0: auto& pi = {{.*}}
+ // CHECK-FIXES-0-8: auto& pi = {{.*}}
+ // CHECK-FIXES-1-0: auto & pi = {{.*}}
+ // CHECK-FIXES-1-8: auto & pi = {{.*}}
+
+ P<long>* pi2 = static_cast<P<long>*>(foo_ptr<long>());
+ // CHECK-FIXES-0-0: auto* pi2 = {{.*}}
+ // CHECK-FIXES-0-8: P<long>* pi2 = {{.*}}
+ // CHECK-FIXES-1-0: auto pi2 = {{.*}}
+ // CHECK-FIXES-1-8: auto pi2 = {{.*}}
+ }
+
+ return 1;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-new-remove-stars.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-new-remove-stars.cpp
new file mode 100644
index 0000000..00e3c89
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-new-remove-stars.cpp
@@ -0,0 +1,106 @@
+// RUN: %check_clang_tidy %s modernize-use-auto %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-auto.RemoveStars, value: '1'}, {key: modernize-use-auto.MinTypeNameLength, value: '0'}]}" \
+// RUN: -- -std=c++11
+
+class MyType {};
+
+class MyDerivedType : public MyType {};
+
+// FIXME: the replacement sometimes results in two consecutive spaces after
+// the word 'auto' (due to the presence of spaces at both sides of '*').
+void auto_new() {
+ MyType *a_new = new MyType();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+ // CHECK-FIXES: auto a_new = new MyType();
+
+ static MyType *a_static = new MyType();
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use auto when initializing with new
+ // CHECK-FIXES: static auto a_static = new MyType();
+
+ MyType *derived = new MyDerivedType();
+
+ void *vd = new MyType();
+
+ // CV-qualifier tests.
+ //
+ // NOTE : the form "type const" is expected here because of a deficiency in
+ // TypeLoc where CV qualifiers are not considered part of the type location
+ // info. That is, all that is being replaced in each case is "MyType *" and
+ // not "MyType * const".
+ static MyType * const d_static = new MyType();
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use auto when initializing with new
+ // CHECK-FIXES: static auto const d_static = new MyType();
+
+ MyType * const a_const = new MyType();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+ // CHECK-FIXES: auto const a_const = new MyType();
+
+ MyType * volatile vol = new MyType();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+ // CHECK-FIXES: auto volatile vol = new MyType();
+
+ struct SType {} *stype = new SType;
+
+ int (**func)(int, int) = new (int(*[5])(int,int));
+
+ int *array = new int[5];
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+ // CHECK-FIXES: auto array = new int[5];
+
+ MyType *ptr(new MyType);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+ // CHECK-FIXES: auto ptr(new MyType);
+
+ MyType *ptr2{new MyType};
+
+ {
+ // Test for declaration lists.
+ MyType *a = new MyType(), *b = new MyType(), *c = new MyType();
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+ // CHECK-FIXES: auto a = new MyType(), b = new MyType(), c = new MyType();
+
+ // Non-initialized declaration should not be transformed.
+ MyType *d = new MyType(), *e;
+
+ MyType **f = new MyType*(), **g = new MyType*();
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+ // CHECK-FIXES: auto f = new MyType*(), g = new MyType*();
+
+ // Mismatching types in declaration lists should not be transformed.
+ MyType *h = new MyType(), **i = new MyType*();
+
+ // '*' shouldn't be removed in case of mismatching types with multiple
+ // declarations.
+ MyType *j = new MyType(), *k = new MyType(), **l = new MyType*();
+ }
+
+ {
+ // Test for typedefs.
+ typedef int * int_p;
+ // CHECK-FIXES: typedef int * int_p;
+
+ int_p a = new int;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+ // CHECK-FIXES: auto a = new int;
+ int_p *b = new int*;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+ // CHECK-FIXES: auto b = new int*;
+
+ // Test for typedefs in declarations lists.
+ int_p c = new int, d = new int;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+ // CHECK-FIXES: auto c = new int, d = new int;
+
+ // Different types should not be transformed.
+ int_p e = new int, *f = new int_p;
+
+ int_p *g = new int*, *h = new int_p;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+ // CHECK-FIXES: auto g = new int*, h = new int_p;
+ }
+
+ // Don't warn when 'auto' is already being used.
+ auto aut = new MyType();
+ auto *paut = new MyType();
+ const auto *pcaut = new MyType();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-new.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-new.cpp
new file mode 100644
index 0000000..3c872c9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-new.cpp
@@ -0,0 +1,110 @@
+// RUN: %check_clang_tidy %s modernize-use-auto %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-auto.MinTypeNameLength, value: '0'}]}" \
+// RUN: -- -std=c++11 -frtti
+
+class MyType {};
+
+class MyDerivedType : public MyType {};
+
+// FIXME: the replacement sometimes results in two consecutive spaces after
+// the word 'auto' (due to the presence of spaces at both sides of '*').
+void auto_new() {
+ MyType *a_new = new MyType();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+ // CHECK-FIXES: auto *a_new = new MyType();
+
+ static MyType *a_static = new MyType();
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use auto when initializing with new
+ // CHECK-FIXES: static auto *a_static = new MyType();
+
+ long long *ll = new long long();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+ // CHECK-FIXES: auto *ll = new long long();
+
+ MyType *derived = new MyDerivedType();
+
+ void *vd = new MyType();
+
+ // CV-qualifier tests.
+ //
+ // NOTE : the form "type const" is expected here because of a deficiency in
+ // TypeLoc where CV qualifiers are not considered part of the type location
+ // info. That is, all that is being replaced in each case is "MyType *" and
+ // not "MyType * const".
+ static MyType * const d_static = new MyType();
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use auto when initializing with new
+ // CHECK-FIXES: static auto * const d_static = new MyType();
+
+ MyType * const a_const = new MyType();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+ // CHECK-FIXES: auto * const a_const = new MyType();
+
+ MyType * volatile vol = new MyType();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+ // CHECK-FIXES: auto * volatile vol = new MyType();
+
+ struct SType {} *stype = new SType;
+
+ int (**func)(int, int) = new (int(*[5])(int,int));
+
+ int *array = new int[5];
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+ // CHECK-FIXES: auto *array = new int[5];
+
+ MyType *ptr(new MyType);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+ // CHECK-FIXES: auto *ptr(new MyType);
+
+ MyType *ptr2{new MyType};
+
+ {
+ // Test for declaration lists.
+ MyType *a = new MyType(), *b = new MyType(), *c = new MyType();
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+ // CHECK-FIXES: auto *a = new MyType(), *b = new MyType(), *c = new MyType();
+
+ // Non-initialized declaration should not be transformed.
+ MyType *d = new MyType(), *e;
+
+ MyType **f = new MyType*(), **g = new MyType*();
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+ // CHECK-FIXES: auto **f = new MyType*(), **g = new MyType*();
+
+ // Mismatching types in declaration lists should not be transformed.
+ MyType *h = new MyType(), **i = new MyType*();
+
+ // '*' shouldn't be removed in case of mismatching types with multiple
+ // declarations.
+ MyType *j = new MyType(), *k = new MyType(), **l = new MyType*();
+ }
+
+ {
+ // Test for typedefs.
+ typedef int * int_p;
+ // CHECK-FIXES: typedef int * int_p;
+
+ int_p a = new int;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+ // CHECK-FIXES: auto a = new int;
+ int_p *b = new int*;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+ // CHECK-FIXES: auto *b = new int*;
+
+ // Test for typedefs in declarations lists.
+ int_p c = new int, d = new int;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+ // CHECK-FIXES: auto c = new int, d = new int;
+
+ // Different types should not be transformed.
+ int_p e = new int, *f = new int_p;
+
+ int_p *g = new int*, *h = new int_p;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+ // CHECK-FIXES: auto *g = new int*, *h = new int_p;
+ }
+
+ // Don't warn when 'auto' is already being used.
+ auto aut = new MyType();
+ auto *paut = new MyType();
+ const auto *pcaut = new MyType();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-bool-literals-ignore-macros.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-bool-literals-ignore-macros.cpp
new file mode 100644
index 0000000..cf8f72c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-bool-literals-ignore-macros.cpp
@@ -0,0 +1,148 @@
+// RUN: %check_clang_tidy %s modernize-use-bool-literals %t -- \
+// RUN: -config="{CheckOptions: \
+// RUN: [{key: modernize-use-bool-literals.IgnoreMacros, \
+// RUN: value: 1}]}" \
+// RUN: -- -std=c++11
+
+bool IntToTrue = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: converting integer literal to bool, use bool literal instead [modernize-use-bool-literals]
+// CHECK-FIXES: {{^}}bool IntToTrue = true;{{$}}
+
+bool IntToFalse(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool IntToFalse(false);{{$}}
+
+bool LongLongToTrue{0x1LL};
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool LongLongToTrue{true};{{$}}
+
+bool ExplicitCStyleIntToFalse = (bool)0;
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool ExplicitCStyleIntToFalse = false;{{$}}
+
+bool ExplicitFunctionalIntToFalse = bool(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool ExplicitFunctionalIntToFalse = false;{{$}}
+
+bool ExplicitStaticIntToFalse = static_cast<bool>(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool ExplicitStaticIntToFalse = false;{{$}}
+
+#define TRUE_MACRO 1
+// CHECK-FIXES: {{^}}#define TRUE_MACRO 1{{$}}
+
+bool MacroIntToTrue = TRUE_MACRO;
+// CHECK-FIXES: {{^}}bool MacroIntToTrue = TRUE_MACRO;{{$}}
+
+#define FALSE_MACRO bool(0)
+// CHECK-FIXES: {{^}}#define FALSE_MACRO bool(0){{$}}
+
+bool TrueBool = true; // OK
+
+bool FalseBool = bool(FALSE_MACRO);
+// CHECK-FIXES: {{^}}bool FalseBool = bool(FALSE_MACRO);{{$}}
+
+void boolFunction(bool bar) {
+
+}
+
+char Character = 0; // OK
+
+unsigned long long LongInteger = 1; // OK
+
+#define MACRO_DEPENDENT_CAST(x) static_cast<bool>(x)
+// CHECK-FIXES: {{^}}#define MACRO_DEPENDENT_CAST(x) static_cast<bool>(x){{$}}
+
+bool MacroDependentBool = MACRO_DEPENDENT_CAST(0);
+// CHECK-FIXES: {{^}}bool MacroDependentBool = MACRO_DEPENDENT_CAST(0);{{$}}
+
+bool ManyMacrosDependent = MACRO_DEPENDENT_CAST(FALSE_MACRO);
+// CHECK-FIXES: {{^}}bool ManyMacrosDependent = MACRO_DEPENDENT_CAST(FALSE_MACRO);{{$}}
+
+class FooClass {
+ public:
+ FooClass() : JustBool(0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}FooClass() : JustBool(false) {}{{$}}
+ FooClass(int) : JustBool{0} {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}FooClass(int) : JustBool{false} {}{{$}}
+ private:
+ bool JustBool;
+ bool BoolWithBraces{0};
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}bool BoolWithBraces{false};{{$}}
+ bool BoolFromInt = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}bool BoolFromInt = false;{{$}}
+ bool SimpleBool = true; // OK
+};
+
+template<typename type>
+void templateFunction(type) {
+ type TemplateType = 0;
+ // CHECK-FIXES: {{^ *}}type TemplateType = 0;{{$}}
+}
+
+template<int c>
+void valueDependentTemplateFunction() {
+ bool Boolean = c;
+ // CHECK-FIXES: {{^ *}}bool Boolean = c;{{$}}
+}
+
+template<typename type>
+void anotherTemplateFunction(type) {
+ bool JustBool = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}bool JustBool = false;{{$}}
+}
+
+int main() {
+ boolFunction(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}boolFunction(true);{{$}}
+
+ boolFunction(false);
+
+ templateFunction(0);
+
+ templateFunction(false);
+
+ valueDependentTemplateFunction<1>();
+
+ anotherTemplateFunction(1);
+
+ IntToTrue = 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}IntToTrue = true;{{$}}
+}
+
+static int Value = 1;
+
+bool Function1() {
+ bool Result = Value == 1 ? 1 : 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: converting integer literal to bool
+ // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}bool Result = Value == 1 ? true : false;{{$}}
+ return Result;
+}
+
+bool Function2() {
+ return Value == 1 ? 1 : 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: converting integer literal to bool
+ // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}return Value == 1 ? true : false;{{$}}
+}
+
+void foo() {
+ bool Result;
+ Result = Value == 1 ? true : 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}Result = Value == 1 ? true : false;{{$}}
+ Result = Value == 1 ? false : bool(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}Result = Value == 1 ? false : false;{{$}}
+ Result = Value == 1 ? (bool)0 : false;
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}Result = Value == 1 ? false : false;{{$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-bool-literals.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-bool-literals.cpp
new file mode 100644
index 0000000..f2ab9ce
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-bool-literals.cpp
@@ -0,0 +1,152 @@
+// RUN: %check_clang_tidy %s modernize-use-bool-literals %t -- \
+// RUN: -config="{CheckOptions: \
+// RUN: [{key: modernize-use-bool-literals.IgnoreMacros, \
+// RUN: value: 0}]}" \
+// RUN: -- -std=c++11
+
+bool IntToTrue = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: converting integer literal to bool, use bool literal instead [modernize-use-bool-literals]
+// CHECK-FIXES: {{^}}bool IntToTrue = true;{{$}}
+
+bool IntToFalse(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool IntToFalse(false);{{$}}
+
+bool LongLongToTrue{0x1LL};
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool LongLongToTrue{true};{{$}}
+
+bool ExplicitCStyleIntToFalse = (bool)0;
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool ExplicitCStyleIntToFalse = false;{{$}}
+
+bool ExplicitFunctionalIntToFalse = bool(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool ExplicitFunctionalIntToFalse = false;{{$}}
+
+bool ExplicitStaticIntToFalse = static_cast<bool>(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool ExplicitStaticIntToFalse = false;{{$}}
+
+#define TRUE_MACRO 1
+// CHECK-FIXES: {{^}}#define TRUE_MACRO 1{{$}}
+
+bool MacroIntToTrue = TRUE_MACRO;
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool MacroIntToTrue = TRUE_MACRO;{{$}}
+
+#define FALSE_MACRO bool(0)
+// CHECK-FIXES: {{^}}#define FALSE_MACRO bool(0){{$}}
+
+bool TrueBool = true; // OK
+
+bool FalseBool = bool(FALSE_MACRO);
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool FalseBool = bool(FALSE_MACRO);{{$}}
+
+void boolFunction(bool bar) {
+
+}
+
+char Character = 0; // OK
+
+unsigned long long LongInteger = 1; // OK
+
+#define MACRO_DEPENDENT_CAST(x) static_cast<bool>(x)
+// CHECK-FIXES: {{^}}#define MACRO_DEPENDENT_CAST(x) static_cast<bool>(x){{$}}
+
+bool MacroDependentBool = MACRO_DEPENDENT_CAST(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool MacroDependentBool = MACRO_DEPENDENT_CAST(0);{{$}}
+
+bool ManyMacrosDependent = MACRO_DEPENDENT_CAST(FALSE_MACRO);
+// CHECK-MESSAGES: :[[@LINE-1]]:49: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool ManyMacrosDependent = MACRO_DEPENDENT_CAST(FALSE_MACRO);{{$}}
+
+class FooClass {
+ public:
+ FooClass() : JustBool(0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}FooClass() : JustBool(false) {}{{$}}
+ FooClass(int) : JustBool{0} {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}FooClass(int) : JustBool{false} {}{{$}}
+ private:
+ bool JustBool;
+ bool BoolWithBraces{0};
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}bool BoolWithBraces{false};{{$}}
+ bool BoolFromInt = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}bool BoolFromInt = false;{{$}}
+ bool SimpleBool = true; // OK
+};
+
+template<typename type>
+void templateFunction(type) {
+ type TemplateType = 0;
+ // CHECK-FIXES: {{^ *}}type TemplateType = 0;{{$}}
+}
+
+template<int c>
+void valueDependentTemplateFunction() {
+ bool Boolean = c;
+ // CHECK-FIXES: {{^ *}}bool Boolean = c;{{$}}
+}
+
+template<typename type>
+void anotherTemplateFunction(type) {
+ bool JustBool = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}bool JustBool = false;{{$}}
+}
+
+int main() {
+ boolFunction(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}boolFunction(true);{{$}}
+
+ boolFunction(false);
+
+ templateFunction(0);
+
+ templateFunction(false);
+
+ valueDependentTemplateFunction<1>();
+
+ anotherTemplateFunction(1);
+
+ IntToTrue = 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}IntToTrue = true;{{$}}
+}
+
+static int Value = 1;
+
+bool Function1() {
+ bool Result = Value == 1 ? 1 : 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: converting integer literal to bool
+ // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}bool Result = Value == 1 ? true : false;{{$}}
+ return Result;
+}
+
+bool Function2() {
+ return Value == 1 ? 1 : 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: converting integer literal to bool
+ // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}return Value == 1 ? true : false;{{$}}
+}
+
+void foo() {
+ bool Result;
+ Result = Value == 1 ? true : 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}Result = Value == 1 ? true : false;{{$}}
+ Result = Value == 1 ? false : bool(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}Result = Value == 1 ? false : false;{{$}}
+ Result = Value == 1 ? (bool)0 : false;
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: converting integer literal to bool
+ // CHECK-FIXES: {{^ *}}Result = Value == 1 ? false : false;{{$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init-assignment.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init-assignment.cpp
new file mode 100644
index 0000000..fdc0db1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init-assignment.cpp
@@ -0,0 +1,184 @@
+// RUN: %check_clang_tidy %s modernize-use-default-member-init %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-default-member-init.UseAssignment, value: 1}]}" -- -std=c++11
+
+struct S {
+};
+
+struct PositiveValueChar {
+ PositiveValueChar() : c0(), c1()/*, c2(), c3()*/ {}
+ // CHECK-FIXES: PositiveValueChar() {}
+ const char c0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use default member initializer for 'c0' [modernize-use-default-member-init]
+ // CHECK-FIXES: const char c0 = '\0';
+ wchar_t c1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use default member initializer for 'c1'
+ // CHECK-FIXES: wchar_t c1 = L'\0';
+ // FIXME: char16_t c2;
+ // C HECK-MESSAGES: :[[@LINE-1]]:12: warning: use default member initializer for 'c2'
+ // C HECK-FIXES: char16_t c2 = u'\0';
+ // FIXME: char32_t c3;
+ // C HECK-MESSAGES: :[[@LINE-1]]:12: warning: use default member initializer for 'c3'
+ // C HECK-FIXES: char32_t c3 = U'\0';
+};
+
+struct PositiveChar {
+ PositiveChar() : d('a') {}
+ // CHECK-FIXES: PositiveChar() {}
+ char d;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'd'
+ // CHECK-FIXES: char d = 'a';
+};
+
+struct PositiveValueInt {
+ PositiveValueInt() : i() {}
+ // CHECK-FIXES: PositiveValueInt() {}
+ const int i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use default member initializer for 'i'
+ // CHECK-FIXES: const int i = 0;
+};
+
+struct PositiveInt {
+ PositiveInt() : j(1) {}
+ // CHECK-FIXES: PositiveInt() {}
+ int j;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'j'
+ // CHECK-FIXES: int j = 1;
+};
+
+struct PositiveUnaryMinusInt {
+ PositiveUnaryMinusInt() : j(-1) {}
+ // CHECK-FIXES: PositiveUnaryMinusInt() {}
+ int j;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'j'
+ // CHECK-FIXES: int j = -1;
+};
+
+struct PositiveUnaryPlusInt {
+ PositiveUnaryPlusInt() : j(+1) {}
+ // CHECK-FIXES: PositiveUnaryPlusInt() {}
+ int j;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'j'
+ // CHECK-FIXES: int j = +1;
+};
+
+struct PositiveValueComplexInt {
+ PositiveValueComplexInt() : i() {}
+ // CHECK-FIXES: PositiveValueComplexInt() {}
+ _Complex int i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use default member initializer for 'i'
+ // CHECK-FIXES: _Complex int i = 0;
+};
+
+struct PositiveValueFloat {
+ PositiveValueFloat() : f() {}
+ // CHECK-FIXES: PositiveValueFloat() {}
+ float f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use default member initializer for 'f'
+ // CHECK-FIXES: float f = 0.0f;
+};
+
+struct PositiveValueDouble {
+ PositiveValueDouble() : d() {}
+ // CHECK-FIXES: PositiveValueDouble() {}
+ double d;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'd'
+ // CHECK-FIXES: double d = 0.0;
+};
+
+struct PositiveDouble {
+ PositiveDouble() : f(2.5463e43) {}
+ // CHECK-FIXES: PositiveDouble() {}
+ double f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'f'
+ // CHECK-FIXES: double f = 2.5463e43;
+};
+
+struct PositiveValueComplexFloat {
+ PositiveValueComplexFloat() : f() {}
+ // CHECK-FIXES: PositiveValueComplexFloat() {}
+ _Complex float f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use default member initializer for 'f'
+ // CHECK-FIXES: _Complex float f = 0.0f;
+};
+
+struct PositiveValueComplexDouble {
+ PositiveValueComplexDouble() : f() {}
+ // CHECK-FIXES: PositiveValueComplexDouble() {}
+ _Complex double f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use default member initializer for 'f'
+ // CHECK-FIXES: _Complex double f = 0.0;
+};
+
+struct PositiveUnaryMinusDouble {
+ PositiveUnaryMinusDouble() : f(-2.5463e43) {}
+ // CHECK-FIXES: PositiveUnaryMinusDouble() {}
+ double f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'f'
+ // CHECK-FIXES: double f = -2.5463e43;
+};
+
+struct PositiveUnaryPlusDouble {
+ PositiveUnaryPlusDouble() : f(+2.5463e43) {}
+ // CHECK-FIXES: PositiveUnaryPlusDouble() {}
+ double f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'f'
+ // CHECK-FIXES: double f = +2.5463e43;
+};
+
+struct PositiveValueBool {
+ PositiveValueBool() : b() {}
+ // CHECK-FIXES: PositiveValueBool() {}
+ bool b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'b'
+ // CHECK-FIXES: bool b = false;
+};
+
+struct PositiveBool {
+ PositiveBool() : a(true) {}
+ // CHECK-FIXES: PositiveBool() {}
+ bool a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'a'
+ // CHECK-FIXES: bool a = true;
+};
+
+struct PositiveValuePointer {
+ PositiveValuePointer() : p() {}
+ // CHECK-FIXES: PositiveValuePointer() {}
+ int *p;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'p'
+ // CHECK-FIXES: int *p = nullptr;
+};
+
+struct PositiveNullPointer {
+ PositiveNullPointer() : q(nullptr) {}
+ // CHECK-FIXES: PositiveNullPointer() {}
+ int *q;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'q'
+ // CHECK-FIXES: int *q = nullptr;
+};
+
+enum Enum { Foo };
+struct PositiveEnum {
+ PositiveEnum() : e(Foo) {}
+ // CHECK-FIXES: PositiveEnum() {}
+ Enum e;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'e'
+ // CHECK-FIXES: Enum e = Foo;
+};
+
+struct PositiveString {
+ PositiveString() : s("foo") {}
+ // CHECK-FIXES: PositiveString() {}
+ const char *s;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use default member initializer for 's'
+ // CHECK-FIXES: const char *s = "foo";
+};
+
+template <typename T>
+struct NegativeTemplate {
+ NegativeTemplate() : t() {}
+ T t;
+};
+
+NegativeTemplate<int> nti;
+NegativeTemplate<double> ntd;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init-bitfield.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init-bitfield.cpp
new file mode 100644
index 0000000..1ff08f9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init-bitfield.cpp
@@ -0,0 +1,10 @@
+// RUN: %check_clang_tidy %s modernize-use-default-member-init %t -- -- -std=c++2a
+
+struct PositiveBitField
+{
+ PositiveBitField() : i(6) {}
+ // CHECK-FIXES: PositiveBitField() {}
+ int i : 5;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'i' [modernize-use-default-member-init]
+ // CHECK-FIXES: int i : 5{6};
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init-macros.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init-macros.cpp
new file mode 100644
index 0000000..5b366b5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init-macros.cpp
@@ -0,0 +1,18 @@
+// RUN: %check_clang_tidy %s modernize-use-default-member-init %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-default-member-init.IgnoreMacros, value: 0}]}" \
+// RUN: -- -std=c++11
+
+#define MACRO() \
+ struct S { \
+ void *P; \
+ S() : P(nullptr) {} \
+ };
+
+MACRO();
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use default member initializer for 'P'
+
+struct S2 {
+ void *P;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use default member initializer for 'P'
+ S2() : P(nullptr) {}
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init.cpp
new file mode 100644
index 0000000..0ed65df
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init.cpp
@@ -0,0 +1,401 @@
+// RUN: %check_clang_tidy %s modernize-use-default-member-init %t -- -- -std=c++11
+
+struct S {
+};
+
+struct PositiveValueChar {
+ PositiveValueChar() : c0(), c1()/*, c2(), c3()*/ {}
+ // CHECK-FIXES: PositiveValueChar() {}
+ const char c0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use default member initializer for 'c0' [modernize-use-default-member-init]
+ // CHECK-FIXES: const char c0{};
+ wchar_t c1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use default member initializer for 'c1'
+ // CHECK-FIXES: wchar_t c1{};
+ // FIXME: char16_t c2;
+ // C HECK-MESSAGES: :[[@LINE-1]]:12: warning: use default member initializer for 'c2'
+ // C HECK-FIXES: char16_t c2{};
+ // FIXME: char32_t c3;
+ // C HECK-MESSAGES: :[[@LINE-1]]:12: warning: use default member initializer for 'c3'
+ // C HECK-FIXES: char32_t c3{};
+};
+
+struct PositiveChar {
+ PositiveChar() : d('a') {}
+ // CHECK-FIXES: PositiveChar() {}
+ char d;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'd'
+ // CHECK-FIXES: char d{'a'};
+};
+
+struct PositiveValueInt {
+ PositiveValueInt() : i() {}
+ // CHECK-FIXES: PositiveValueInt() {}
+ const int i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use default member initializer for 'i'
+ // CHECK-FIXES: const int i{};
+};
+
+struct PositiveInt {
+ PositiveInt() : j(1) {}
+ // CHECK-FIXES: PositiveInt() {}
+ int j;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'j'
+ // CHECK-FIXES: int j{1};
+};
+
+struct PositiveUnaryMinusInt {
+ PositiveUnaryMinusInt() : j(-1) {}
+ // CHECK-FIXES: PositiveUnaryMinusInt() {}
+ int j;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'j'
+ // CHECK-FIXES: int j{-1};
+};
+
+struct PositiveUnaryPlusInt {
+ PositiveUnaryPlusInt() : j(+1) {}
+ // CHECK-FIXES: PositiveUnaryPlusInt() {}
+ int j;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'j'
+ // CHECK-FIXES: int j{+1};
+};
+
+struct PositiveValueComplexInt {
+ PositiveValueComplexInt() : i() {}
+ // CHECK-FIXES: PositiveValueComplexInt() {}
+ _Complex int i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use default member initializer for 'i'
+ // CHECK-FIXES: _Complex int i{};
+};
+
+struct PositiveValueFloat {
+ PositiveValueFloat() : f() {}
+ // CHECK-FIXES: PositiveValueFloat() {}
+ float f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use default member initializer for 'f'
+ // CHECK-FIXES: float f{};
+};
+
+struct PositiveValueDouble {
+ PositiveValueDouble() : d() {}
+ // CHECK-FIXES: PositiveValueDouble() {}
+ double d;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'd'
+ // CHECK-FIXES: double d{};
+};
+
+struct PositiveDouble {
+ PositiveDouble() : f(2.5463e43) {}
+ // CHECK-FIXES: PositiveDouble() {}
+ double f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'f'
+ // CHECK-FIXES: double f{2.5463e43};
+};
+
+struct PositiveValueComplexFloat {
+ PositiveValueComplexFloat() : f() {}
+ // CHECK-FIXES: PositiveValueComplexFloat() {}
+ _Complex float f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use default member initializer for 'f'
+ // CHECK-FIXES: _Complex float f{};
+};
+
+struct PositiveValueComplexDouble {
+ PositiveValueComplexDouble() : f() {}
+ // CHECK-FIXES: PositiveValueComplexDouble() {}
+ _Complex double f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use default member initializer for 'f'
+ // CHECK-FIXES: _Complex double f{};
+};
+
+struct PositiveUnaryMinusDouble {
+ PositiveUnaryMinusDouble() : f(-2.5463e43) {}
+ // CHECK-FIXES: PositiveUnaryMinusDouble() {}
+ double f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'f'
+ // CHECK-FIXES: double f{-2.5463e43};
+};
+
+struct PositiveUnaryPlusDouble {
+ PositiveUnaryPlusDouble() : f(+2.5463e43) {}
+ // CHECK-FIXES: PositiveUnaryPlusDouble() {}
+ double f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'f'
+ // CHECK-FIXES: double f{+2.5463e43};
+};
+
+struct PositiveValueBool {
+ PositiveValueBool() : b() {}
+ // CHECK-FIXES: PositiveValueBool() {}
+ bool b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'b'
+ // CHECK-FIXES: bool b{};
+};
+
+struct PositiveBool {
+ PositiveBool() : a(true) {}
+ // CHECK-FIXES: PositiveBool() {}
+ bool a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'a'
+ // CHECK-FIXES: bool a{true};
+};
+
+struct PositiveValuePointer {
+ PositiveValuePointer() : p() {}
+ // CHECK-FIXES: PositiveValuePointer() {}
+ int *p;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'p'
+ // CHECK-FIXES: int *p{};
+};
+
+struct PositiveNullPointer {
+ PositiveNullPointer() : q(nullptr) {}
+ // CHECK-FIXES: PositiveNullPointer() {}
+ int *q;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'q'
+ // CHECK-FIXES: int *q{nullptr};
+};
+
+enum Enum { Foo, Bar };
+struct PositiveEnum {
+ PositiveEnum() : e(Foo) {}
+ // CHECK-FIXES: PositiveEnum() {}
+ Enum e;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'e'
+ // CHECK-FIXES: Enum e{Foo};
+};
+
+struct PositiveString {
+ PositiveString() : s("foo") {}
+ // CHECK-FIXES: PositiveString() {}
+ const char *s;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use default member initializer for 's'
+ // CHECK-FIXES: const char *s{"foo"};
+};
+
+struct PositiveStruct {
+ PositiveStruct() : s(7) {}
+ // CHECK-FIXES: PositiveStruct() {}
+ struct {
+ int s;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use default member initializer for 's'
+ // CHECK-FIXES: int s{7};
+ };
+};
+
+template <typename T>
+struct NegativeTemplate {
+ NegativeTemplate() : t() {}
+ T t;
+};
+
+NegativeTemplate<int> nti;
+NegativeTemplate<double> ntd;
+
+struct NegativeDefaultMember {
+ NegativeDefaultMember() {}
+ int i = 2;
+};
+
+struct NegativeClass : S {
+ NegativeClass() : s() {}
+ S s;
+};
+
+struct NegativeBase : S {
+ NegativeBase() : S() {}
+};
+
+struct NegativeDefaultOtherMember{
+ NegativeDefaultOtherMember() : i(3) {}
+ int i = 4;
+};
+
+struct NegativeUnion {
+ NegativeUnion() : d(5.0) {}
+ union {
+ int i;
+ double d;
+ };
+};
+
+struct NegativeBitField
+{
+ NegativeBitField() : i(6) {}
+ int i : 5;
+};
+
+struct NegativeNotDefaultInt
+{
+ NegativeNotDefaultInt(int) : i(7) {}
+ int i;
+};
+
+struct NegativeDefaultArg
+{
+ NegativeDefaultArg(int i = 4) : i(i) {}
+ int i;
+};
+
+struct ExistingChar {
+ ExistingChar(short) : e1(), e2(), e3(), e4() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: member initializer for 'e1' is redundant [modernize-use-default-member-init]
+ // CHECK-MESSAGES: :[[@LINE-2]]:31: warning: member initializer for 'e2' is redundant
+ // CHECK-MESSAGES: :[[@LINE-3]]:37: warning: member initializer for 'e3' is redundant
+ // CHECK-FIXES: ExistingChar(short) : e4() {}
+ ExistingChar(int) : e1(0), e2(0), e3(0), e4(0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:30: warning: member initializer for 'e2' is redundant
+ // CHECK-MESSAGES: :[[@LINE-3]]:37: warning: member initializer for 'e3' is redundant
+ // CHECK-FIXES: ExistingChar(int) : e4(0) {}
+ ExistingChar(long) : e1('\0'), e2('\0'), e3('\0'), e4('\0') {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: member initializer for 'e2' is redundant
+ // CHECK-MESSAGES: :[[@LINE-3]]:44: warning: member initializer for 'e3' is redundant
+ // CHECK-FIXES: ExistingChar(long) : e4('\0') {}
+ ExistingChar(char) : e1('a'), e2('a'), e3('a'), e4('a') {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:51: warning: member initializer for 'e4' is redundant
+ // CHECK-FIXES: ExistingChar(char) : e1('a'), e2('a'), e3('a') {}
+ char e1{};
+ char e2 = 0;
+ char e3 = '\0';
+ char e4 = 'a';
+};
+
+struct ExistingInt {
+ ExistingInt(short) : e1(), e2(), e3(), e4(), e5(), e6() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: member initializer for 'e1' is redundant [modernize-use-default-member-init]
+ // CHECK-MESSAGES: :[[@LINE-2]]:30: warning: member initializer for 'e2' is redundant
+ // CHECK-FIXES: ExistingInt(short) : e3(), e4(), e5(), e6() {}
+ ExistingInt(int) : e1(0), e2(0), e3(0), e4(0), e5(0), e6(0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:29: warning: member initializer for 'e2' is redundant
+ // CHECK-FIXES: ExistingInt(int) : e3(0), e4(0), e5(0), e6(0) {}
+ ExistingInt(long) : e1(5), e2(5), e3(5), e4(5), e5(5), e6(5) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: member initializer for 'e3' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:44: warning: member initializer for 'e4' is redundant
+ // CHECK-MESSAGES: :[[@LINE-3]]:58: warning: member initializer for 'e6' is redundant
+ // CHECK-FIXES: ExistingInt(long) : e1(5), e2(5), e5(5) {}
+ ExistingInt(char) : e1(-5), e2(-5), e3(-5), e4(-5), e5(-5), e6(-5) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:55: warning: member initializer for 'e5' is redundant
+ // CHECK-FIXES: ExistingInt(char) : e1(-5), e2(-5), e3(-5), e4(-5), e6(-5) {}
+ int e1{};
+ int e2 = 0;
+ int e3 = {5};
+ int e4 = 5;
+ int e5 = -5;
+ int e6 = +5;
+};
+
+struct ExistingDouble {
+ ExistingDouble(short) : e1(), e2(), e3(), e4(), e5() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:33: warning: member initializer for 'e2' is redundant
+ // CHECK-FIXES: ExistingDouble(short) : e3(), e4(), e5() {}
+ ExistingDouble(int) : e1(0.0), e2(0.0), e3(0.0), e4(0.0), e5(0.0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: member initializer for 'e2' is redundant
+ // CHECK-FIXES: ExistingDouble(int) : e3(0.0), e4(0.0), e5(0.0) {}
+ ExistingDouble(long) : e1(5.0), e2(5.0), e3(5.0), e4(5.0), e5(5.0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: member initializer for 'e3' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:62: warning: member initializer for 'e5' is redundant
+ // CHECK-FIXES: ExistingDouble(long) : e1(5.0), e2(5.0), e4(5.0) {}
+ ExistingDouble(char) : e1(-5.0), e2(-5.0), e3(-5.0), e4(-5.0), e5(-5.0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:56: warning: member initializer for 'e4' is redundant
+ // CHECK-FIXES: ExistingDouble(char) : e1(-5.0), e2(-5.0), e3(-5.0), e5(-5.0) {}
+ double e1{};
+ double e2 = 0.0;
+ double e3 = 5.0;
+ double e4 = -5.0;
+ double e5 = +5.0;
+};
+
+struct ExistingBool {
+ ExistingBool(short) : e1(), e2(), e3() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:31: warning: member initializer for 'e2' is redundant
+ // CHECK-FIXES: ExistingBool(short) : e3() {}
+ ExistingBool(int) : e1(false), e2(false), e3(false) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: member initializer for 'e2' is redundant
+ // CHECK-FIXES: ExistingBool(int) : e3(false) {}
+ ExistingBool(long) : e1(true), e2(true), e3(true) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: member initializer for 'e3' is redundant
+ // CHECK-FIXES: ExistingBool(long) : e1(true), e2(true) {}
+ bool e1{};
+ bool e2 = false;
+ bool e3 = true;
+};
+
+struct ExistingEnum {
+ ExistingEnum(short) : e1(Foo), e2(Foo) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: member initializer for 'e1' is redundant
+ // CHECK-FIXES: ExistingEnum(short) : e2(Foo) {}
+ ExistingEnum(int) : e1(Bar), e2(Bar) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: member initializer for 'e2' is redundant
+ // CHECK-FIXES: ExistingEnum(int) : e1(Bar) {}
+ Enum e1 = Foo;
+ Enum e2{Bar};
+};
+
+struct ExistingPointer {
+ ExistingPointer(short) : e1(), e2(), e3(), e4() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: member initializer for 'e2' is redundant
+ // CHECK-MESSAGES: :[[@LINE-3]]:40: warning: member initializer for 'e3' is redundant
+ // CHECK-FIXES: ExistingPointer(short) : e4() {}
+ ExistingPointer(int) : e1(0), e2(0), e3(0), e4(&e1) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:33: warning: member initializer for 'e2' is redundant
+ // CHECK-MESSAGES: :[[@LINE-3]]:40: warning: member initializer for 'e3' is redundant
+ // CHECK-FIXES: ExistingPointer(int) : e4(&e1) {}
+ ExistingPointer(long) : e1(nullptr), e2(nullptr), e3(nullptr), e4(&e2) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:40: warning: member initializer for 'e2' is redundant
+ // CHECK-MESSAGES: :[[@LINE-3]]:53: warning: member initializer for 'e3' is redundant
+ // CHECK-FIXES: ExistingPointer(long) : e4(&e2) {}
+ int *e1{};
+ int *e2 = 0;
+ int *e3 = nullptr;
+ int **e4 = &e1;
+};
+
+struct ExistingString {
+ ExistingString(short) : e1(), e2(), e3(), e4() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: member initializer for 'e1' is redundant [modernize-use-default-member-init]
+ // CHECK-MESSAGES: :[[@LINE-2]]:33: warning: member initializer for 'e2' is redundant
+ // CHECK-FIXES: ExistingString(short) : e3(), e4() {}
+ ExistingString(int) : e1(0), e2(0), e3(0), e4(0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:32: warning: member initializer for 'e2' is redundant
+ // CHECK-FIXES: ExistingString(int) : e3(0), e4(0) {}
+ ExistingString(long) : e1(nullptr), e2(nullptr), e3(nullptr), e4(nullptr) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:39: warning: member initializer for 'e2' is redundant
+ // CHECK-FIXES: ExistingString(long) : e3(nullptr), e4(nullptr) {}
+ ExistingString(char) : e1("foo"), e2("foo"), e3("foo"), e4("foo") {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: member initializer for 'e3' is redundant
+ // CHECK-FIXES: ExistingString(char) : e1("foo"), e2("foo"), e4("foo") {}
+ const char *e1{};
+ const char *e2 = nullptr;
+ const char *e3 = "foo";
+ const char *e4 = "bar";
+};
+
+template <typename T>
+struct NegativeTemplateExisting {
+ NegativeTemplateExisting(int) : t(0) {}
+ T t{};
+};
+
+NegativeTemplateExisting<int> ntei(0);
+NegativeTemplateExisting<double> nted(0);
+
+// This resulted in a warning by default.
+#define MACRO() \
+ struct MacroS { \
+ void *P; \
+ MacroS() : P(nullptr) {} \
+ };
+
+MACRO();
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-emplace-ignore-implicit-constructors.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-emplace-ignore-implicit-constructors.cpp
new file mode 100644
index 0000000..2f6b37f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-emplace-ignore-implicit-constructors.cpp
@@ -0,0 +1,123 @@
+// RUN: %check_clang_tidy %s modernize-use-emplace %t -- \
+// RUN: -config="{CheckOptions: \
+// RUN: [{key: modernize-use-emplace.IgnoreImplicitConstructors, \
+// RUN: value: 1}] \
+// RUN: }" -- -std=c++11
+
+namespace std {
+template <typename>
+class initializer_list
+{
+public:
+ initializer_list() noexcept {}
+};
+
+template <typename T>
+class vector {
+public:
+ vector() = default;
+ vector(initializer_list<T>) {}
+
+ void push_back(const T &) {}
+ void push_back(T &&) {}
+
+ template <typename... Args>
+ void emplace_back(Args &&... args){};
+ ~vector();
+};
+
+} // namespace std
+
+void testInts() {
+ std::vector<int> v;
+ v.push_back(42);
+ v.push_back(int(42));
+ v.push_back(int{42});
+ v.push_back(42.0);
+ int z;
+ v.push_back(z);
+}
+
+struct Something {
+ Something(int a, int b = 41) {}
+ Something() {}
+ void push_back(Something);
+ int getInt() { return 42; }
+};
+
+struct Convertable {
+ operator Something() { return Something{}; }
+};
+
+struct Zoz {
+ Zoz(Something, int = 42) {}
+};
+
+Zoz getZoz(Something s) { return Zoz(s); }
+
+void test_Something() {
+ std::vector<Something> v;
+
+ v.push_back(Something(1, 2));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back instead of push_back [modernize-use-emplace]
+ // CHECK-FIXES: v.emplace_back(1, 2);
+
+ v.push_back(Something{1, 2});
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(1, 2);
+
+ v.push_back(Something());
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back();
+
+ v.push_back(Something{});
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back();
+
+ Something Different;
+ v.push_back(Something(Different.getInt(), 42));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(Different.getInt(), 42);
+
+ v.push_back(Different.getInt());
+ v.push_back(42);
+
+ Something temporary(42, 42);
+ temporary.push_back(temporary);
+ v.push_back(temporary);
+
+ v.push_back(Convertable());
+ v.push_back(Convertable{});
+ Convertable s;
+ v.push_back(s);
+}
+
+template <typename ElemType>
+void dependOnElem() {
+ std::vector<ElemType> v;
+ v.push_back(ElemType(42));
+}
+
+template <typename ContainerType>
+void dependOnContainer() {
+ ContainerType v;
+ v.push_back(Something(42));
+}
+
+void callDependent() {
+ dependOnElem<Something>();
+ dependOnContainer<std::vector<Something>>();
+}
+
+void test2() {
+ std::vector<Zoz> v;
+ v.push_back(Zoz(Something(21, 37)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(Something(21, 37));
+
+ v.push_back(Zoz(Something(21, 37), 42));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(Something(21, 37), 42);
+
+ v.push_back(getZoz(Something(1, 2)));
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-emplace.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-emplace.cpp
new file mode 100644
index 0000000..c03d024
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-emplace.cpp
@@ -0,0 +1,607 @@
+// RUN: %check_clang_tidy %s modernize-use-emplace %t -- \
+// RUN: -config="{CheckOptions: \
+// RUN: [{key: modernize-use-emplace.ContainersWithPushBack, \
+// RUN: value: '::std::vector; ::std::list; ::std::deque; llvm::LikeASmallVector'}, \
+// RUN: {key: modernize-use-emplace.TupleTypes, \
+// RUN: value: '::std::pair; std::tuple; ::test::Single'}, \
+// RUN: {key: modernize-use-emplace.TupleMakeFunctions, \
+// RUN: value: '::std::make_pair; ::std::make_tuple; ::test::MakeSingle'}] \
+// RUN: }" -- -std=c++11
+
+namespace std {
+template <typename>
+class initializer_list
+{
+public:
+ initializer_list() noexcept {}
+};
+
+template <typename T>
+class vector {
+public:
+ vector() = default;
+ vector(initializer_list<T>) {}
+
+ void push_back(const T &) {}
+ void push_back(T &&) {}
+
+ template <typename... Args>
+ void emplace_back(Args &&... args){};
+ ~vector();
+};
+template <typename T>
+class list {
+public:
+ void push_back(const T &) {}
+ void push_back(T &&) {}
+
+ template <typename... Args>
+ void emplace_back(Args &&... args){};
+ ~list();
+};
+
+template <typename T>
+class deque {
+public:
+ void push_back(const T &) {}
+ void push_back(T &&) {}
+
+ template <typename... Args>
+ void emplace_back(Args &&... args){};
+ ~deque();
+};
+
+template <typename T> struct remove_reference { using type = T; };
+template <typename T> struct remove_reference<T &> { using type = T; };
+template <typename T> struct remove_reference<T &&> { using type = T; };
+
+template <typename T1, typename T2> class pair {
+public:
+ pair() = default;
+ pair(const pair &) = default;
+ pair(pair &&) = default;
+
+ pair(const T1 &, const T2 &) {}
+ pair(T1 &&, T2 &&) {}
+
+ template <typename U1, typename U2> pair(const pair<U1, U2> &){};
+ template <typename U1, typename U2> pair(pair<U1, U2> &&){};
+};
+
+template <typename T1, typename T2>
+pair<typename remove_reference<T1>::type, typename remove_reference<T2>::type>
+make_pair(T1 &&, T2 &&) {
+ return {};
+};
+
+template <typename... Ts> class tuple {
+public:
+ tuple() = default;
+ tuple(const tuple &) = default;
+ tuple(tuple &&) = default;
+
+ tuple(const Ts &...) {}
+ tuple(Ts &&...) {}
+
+ template <typename... Us> tuple(const tuple<Us...> &){};
+ template <typename... Us> tuple(tuple<Us...> &&) {}
+
+ template <typename U1, typename U2> tuple(const pair<U1, U2> &) {
+ static_assert(sizeof...(Ts) == 2, "Wrong tuple size");
+ };
+ template <typename U1, typename U2> tuple(pair<U1, U2> &&) {
+ static_assert(sizeof...(Ts) == 2, "Wrong tuple size");
+ };
+};
+
+template <typename... Ts>
+tuple<typename remove_reference<Ts>::type...> make_tuple(Ts &&...) {
+ return {};
+}
+
+template <typename T>
+class unique_ptr {
+public:
+ explicit unique_ptr(T *) {}
+ ~unique_ptr();
+};
+} // namespace std
+
+namespace llvm {
+template <typename T>
+class LikeASmallVector {
+public:
+ void push_back(const T &) {}
+ void push_back(T &&) {}
+
+ template <typename... Args>
+ void emplace_back(Args &&... args){};
+};
+
+} // llvm
+
+void testInts() {
+ std::vector<int> v;
+ v.push_back(42);
+ v.push_back(int(42));
+ v.push_back(int{42});
+ v.push_back(42.0);
+ int z;
+ v.push_back(z);
+}
+
+struct Something {
+ Something(int a, int b = 41) {}
+ Something() {}
+ void push_back(Something);
+ int getInt() { return 42; }
+};
+
+struct Convertable {
+ operator Something() { return Something{}; }
+};
+
+struct Zoz {
+ Zoz(Something, int = 42) {}
+};
+
+Zoz getZoz(Something s) { return Zoz(s); }
+
+void test_Something() {
+ std::vector<Something> v;
+
+ v.push_back(Something(1, 2));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back instead of push_back [modernize-use-emplace]
+ // CHECK-FIXES: v.emplace_back(1, 2);
+
+ v.push_back(Something{1, 2});
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(1, 2);
+
+ v.push_back(Something());
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back();
+
+ v.push_back(Something{});
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back();
+
+ Something Different;
+ v.push_back(Something(Different.getInt(), 42));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(Different.getInt(), 42);
+
+ v.push_back(Different.getInt());
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(Different.getInt());
+
+ v.push_back(42);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(42);
+
+ Something temporary(42, 42);
+ temporary.push_back(temporary);
+ v.push_back(temporary);
+
+ v.push_back(Convertable());
+ v.push_back(Convertable{});
+ Convertable s;
+ v.push_back(s);
+}
+
+template <typename ElemType>
+void dependOnElem() {
+ std::vector<ElemType> v;
+ v.push_back(ElemType(42));
+}
+
+template <typename ContainerType>
+void dependOnContainer() {
+ ContainerType v;
+ v.push_back(Something(42));
+}
+
+void callDependent() {
+ dependOnElem<Something>();
+ dependOnContainer<std::vector<Something>>();
+}
+
+void test2() {
+ std::vector<Zoz> v;
+ v.push_back(Zoz(Something(21, 37)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(Something(21, 37));
+
+ v.push_back(Zoz(Something(21, 37), 42));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(Something(21, 37), 42);
+
+ v.push_back(getZoz(Something(1, 2)));
+}
+
+struct GetPair {
+ std::pair<int, long> getPair();
+};
+void testPair() {
+ std::vector<std::pair<int, int>> v;
+ v.push_back(std::pair<int, int>(1, 2));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(1, 2);
+
+ GetPair g;
+ v.push_back(g.getPair());
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(g.getPair());
+
+ std::vector<std::pair<Something, Zoz>> v2;
+ v2.push_back(std::pair<Something, Zoz>(Something(42, 42), Zoz(Something(21, 37))));
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back
+ // CHECK-FIXES: v2.emplace_back(Something(42, 42), Zoz(Something(21, 37)));
+}
+
+void testTuple() {
+ std::vector<std::tuple<bool, char, int>> v;
+ v.push_back(std::tuple<bool, char, int>(false, 'x', 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(false, 'x', 1);
+
+ v.push_back(std::tuple<bool, char, int>{false, 'y', 2});
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(false, 'y', 2);
+
+ v.push_back({true, 'z', 3});
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(true, 'z', 3);
+
+ std::vector<std::tuple<int, bool>> x;
+ x.push_back(std::make_pair(1, false));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: x.emplace_back(1, false);
+
+ x.push_back(std::make_pair(2LL, 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: x.emplace_back(2LL, 1);
+}
+
+struct Base {
+ Base(int, int *, int = 42);
+};
+
+struct Derived : Base {
+ Derived(int *, Something) : Base(42, nullptr) {}
+};
+
+void testDerived() {
+ std::vector<Base> v;
+ v.push_back(Derived(nullptr, Something{}));
+}
+
+void testNewExpr() {
+ std::vector<Derived> v;
+ v.push_back(Derived(new int, Something{}));
+}
+
+void testSpaces() {
+ std::vector<Something> v;
+
+ // clang-format off
+
+ v.push_back(Something(1, //arg1
+ 2 // arg2
+ ) // Something
+ );
+ // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(1, //arg1
+ // CHECK-FIXES: 2 // arg2
+ // CHECK-FIXES: // Something
+ // CHECK-FIXES: );
+
+ v.push_back( Something (1, 2) );
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(1, 2 );
+
+ v.push_back( Something {1, 2} );
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(1, 2 );
+
+ v.push_back( Something {} );
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back( );
+
+ v.push_back(
+ Something(1, 2) );
+ // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(1, 2 );
+
+ std::vector<Base> v2;
+ v2.push_back(
+ Base(42, nullptr));
+ // CHECK-MESSAGES: :[[@LINE-2]]:6: warning: use emplace_back
+ // CHECK-FIXES: v2.emplace_back(42, nullptr);
+
+ // clang-format on
+}
+
+void testPointers() {
+ std::vector<int *> v;
+ v.push_back(new int(5));
+
+ std::vector<std::unique_ptr<int>> v2;
+ v2.push_back(std::unique_ptr<int>(new int(42)));
+ // This call can't be replaced with emplace_back.
+ // If emplacement will fail (not enough memory to add to vector)
+ // we will have leak of int because unique_ptr won't be constructed
+ // (and destructed) as in push_back case.
+
+ auto *ptr = new int;
+ v2.push_back(std::unique_ptr<int>(ptr));
+ // Same here
+}
+
+void testMakePair() {
+ std::vector<std::pair<int, int>> v;
+ v.push_back(std::make_pair(1, 2));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(1, 2);
+
+ v.push_back(std::make_pair(42LL, 13));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(42LL, 13);
+
+ v.push_back(std::make_pair<char, char>(0, 3));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(std::make_pair<char, char>(0, 3));
+ //
+ // Even though the call above could be turned into v.emplace_back(0, 3),
+ // we don't eliminate the make_pair call here, because of the explicit
+ // template parameters provided. make_pair's arguments can be convertible
+ // to its explicitly provided template parameter, but not to the pair's
+ // element type. The examples below illustrate the problem.
+ struct D {
+ D(...) {}
+ operator char() const { return 0; }
+ };
+ v.push_back(std::make_pair<D, int>(Something(), 2));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(std::make_pair<D, int>(Something(), 2));
+
+ struct X {
+ X(std::pair<int, int>) {}
+ };
+ std::vector<X> x;
+ x.push_back(std::make_pair(1, 2));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: x.emplace_back(std::make_pair(1, 2));
+ // make_pair cannot be removed here, as X is not constructible with two ints.
+
+ struct Y {
+ Y(std::pair<int, int>&&) {}
+ };
+ std::vector<Y> y;
+ y.push_back(std::make_pair(2, 3));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: y.emplace_back(std::make_pair(2, 3));
+ // make_pair cannot be removed here, as Y is not constructible with two ints.
+}
+
+void testMakeTuple() {
+ std::vector<std::tuple<int, bool, char>> v;
+ v.push_back(std::make_tuple(1, true, 'v'));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(1, true, 'v');
+
+ v.push_back(std::make_tuple(2ULL, 1, 0));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(2ULL, 1, 0);
+
+ v.push_back(std::make_tuple<long long, int, int>(3LL, 1, 0));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(std::make_tuple<long long, int, int>(3LL, 1, 0));
+ // make_tuple is not removed when there are explicit template
+ // arguments provided.
+}
+
+namespace test {
+template <typename T> struct Single {
+ Single() = default;
+ Single(const Single &) = default;
+ Single(Single &&) = default;
+
+ Single(const T &) {}
+ Single(T &&) {}
+
+ template <typename U> Single(const Single<U> &) {}
+ template <typename U> Single(Single<U> &&) {}
+
+ template <typename U> Single(const std::tuple<U> &) {}
+ template <typename U> Single(std::tuple<U> &&) {}
+};
+
+template <typename T>
+Single<typename std::remove_reference<T>::type> MakeSingle(T &&) {
+ return {};
+}
+} // namespace test
+
+void testOtherTuples() {
+ std::vector<test::Single<int>> v;
+ v.push_back(test::Single<int>(1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(1);
+
+ v.push_back({2});
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(2);
+
+ v.push_back(test::MakeSingle(3));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(3);
+
+ v.push_back(test::MakeSingle<long long>(4));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(test::MakeSingle<long long>(4));
+ // We don't remove make functions with explicit template parameters.
+
+ v.push_back(test::MakeSingle(5LL));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(5LL);
+
+ v.push_back(std::make_tuple(6));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(6);
+
+ v.push_back(std::make_tuple(7LL));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(7LL);
+}
+
+void testOtherContainers() {
+ std::list<Something> l;
+ l.push_back(Something(42, 41));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: l.emplace_back(42, 41);
+
+ std::deque<Something> d;
+ d.push_back(Something(42));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: d.emplace_back(42);
+
+ llvm::LikeASmallVector<Something> ls;
+ ls.push_back(Something(42));
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back
+ // CHECK-FIXES: ls.emplace_back(42);
+}
+
+class IntWrapper {
+public:
+ IntWrapper(int x) : value(x) {}
+ IntWrapper operator+(const IntWrapper other) const {
+ return IntWrapper(value + other.value);
+ }
+
+private:
+ int value;
+};
+
+void testMultipleOpsInPushBack() {
+ std::vector<IntWrapper> v;
+ v.push_back(IntWrapper(42) + IntWrapper(27));
+}
+
+// Macro tests.
+#define PUSH_BACK_WHOLE(c, x) c.push_back(x)
+#define PUSH_BACK_NAME push_back
+#define PUSH_BACK_ARG(x) (x)
+#define SOME_OBJ Something(10)
+#define MILLION 3
+#define SOME_WEIRD_PUSH(v) v.push_back(Something(
+#define OPEN (
+#define CLOSE )
+void macroTest() {
+ std::vector<Something> v;
+ Something s;
+
+ PUSH_BACK_WHOLE(v, Something(5, 6));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use emplace_back
+
+ v.PUSH_BACK_NAME(Something(5));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+
+ v.push_back PUSH_BACK_ARG(Something(5, 6));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+
+ v.push_back(SOME_OBJ);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+
+ v.push_back(Something(MILLION));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(MILLION);
+
+ // clang-format off
+ v.push_back( Something OPEN 3 CLOSE );
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // clang-format on
+ PUSH_BACK_WHOLE(s, Something(1));
+}
+
+struct A {
+ int value1, value2;
+};
+
+struct B {
+ B(A) {}
+};
+
+struct C {
+ int value1, value2, value3;
+};
+
+void testAggregation() {
+ // This should not be noticed or fixed; after the correction, the code won't
+ // compile.
+
+ std::vector<A> v;
+ v.push_back(A({1, 2}));
+
+ std::vector<B> vb;
+ vb.push_back(B({10, 42}));
+}
+
+struct Bitfield {
+ unsigned bitfield : 1;
+ unsigned notBitfield;
+};
+
+void testBitfields() {
+ std::vector<Something> v;
+ Bitfield b;
+ v.push_back(Something(42, b.bitfield));
+ v.push_back(Something(b.bitfield));
+
+ v.push_back(Something(42, b.notBitfield));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(42, b.notBitfield);
+ int var;
+ v.push_back(Something(42, var));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(42, var);
+}
+
+class PrivateCtor {
+ PrivateCtor(int z);
+
+public:
+ void doStuff() {
+ std::vector<PrivateCtor> v;
+ // This should not change it because emplace back doesn't have permission.
+ // Check currently doesn't support friend declarations because pretty much
+ // nobody would want to be friend with std::vector :(.
+ v.push_back(PrivateCtor(42));
+ }
+};
+
+struct WithDtor {
+ WithDtor(int) {}
+ ~WithDtor();
+};
+
+void testWithDtor() {
+ std::vector<WithDtor> v;
+
+ v.push_back(WithDtor(42));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+ // CHECK-FIXES: v.emplace_back(42);
+}
+
+void testInitializerList() {
+ std::vector<std::vector<int>> v;
+ v.push_back(std::vector<int>({1}));
+ // Test against the bug reported in PR32896.
+
+ v.push_back({{2}});
+
+ using PairIntVector = std::pair<int, std::vector<int>>;
+ std::vector<PairIntVector> x;
+ x.push_back(PairIntVector(3, {4}));
+ x.push_back({5, {6}});
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default-copy.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default-copy.cpp
new file mode 100644
index 0000000..39a864d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default-copy.cpp
@@ -0,0 +1,507 @@
+// RUN: %check_clang_tidy %s modernize-use-equals-default %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-equals-default.IgnoreMacros, value: 0}]}" \
+// RUN: -- -std=c++11 -fno-delayed-template-parsing -fexceptions
+
+// Out of line definition.
+struct OL {
+ OL(const OL &);
+ OL &operator=(const OL &);
+ int Field;
+};
+OL::OL(const OL &Other) : Field(Other.Field) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default' to define a trivial copy constructor [modernize-use-equals-default]
+// CHECK-FIXES: OL::OL(const OL &Other) = default;
+OL &OL::operator=(const OL &Other) {
+ Field = Other.Field;
+ return *this;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:9: warning: use '= default' to define a trivial copy-assignment operator [modernize-use-equals-default]
+// CHECK-FIXES: OL &OL::operator=(const OL &Other) = default;
+
+// Inline.
+struct IL {
+ IL(const IL &Other) : Field(Other.Field) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: IL(const IL &Other) = default;
+ IL &operator=(const IL &Other) {
+ Field = Other.Field;
+ return *this;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:7: warning: use '= default'
+ // CHECK-FIXES: IL &operator=(const IL &Other) = default;
+ int Field;
+};
+
+// Wrong type.
+struct WT {
+ WT(const IL &Other) {}
+ WT &operator=(const IL &);
+};
+WT &WT::operator=(const IL &Other) { return *this; }
+
+// Qualifiers.
+struct Qual {
+ Qual(const Qual &Other) : Field(Other.Field), Volatile(Other.Volatile),
+ Mutable(Other.Mutable), Reference(Other.Reference),
+ Const(Other.Const) {}
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use '= default'
+ // CHECK-FIXES: Qual(const Qual &Other)
+ // CHECK-FIXES: = default;
+
+ int Field;
+ volatile char Volatile;
+ mutable bool Mutable;
+ const OL &Reference; // This makes this class non-assignable.
+ const IL Const; // This also makes this class non-assignable.
+ static int Static;
+};
+
+// Wrong init arguments.
+struct WI {
+ WI(const WI &Other) : Field1(Other.Field1), Field2(Other.Field1) {}
+ WI &operator=(const WI &);
+ int Field1, Field2;
+};
+WI &WI::operator=(const WI &Other) {
+ Field1 = Other.Field1;
+ Field2 = Other.Field1;
+ return *this;
+}
+
+// Missing field.
+struct MF {
+ MF(const MF &Other) : Field1(Other.Field1), Field2(Other.Field2) {}
+ MF &operator=(const MF &);
+ int Field1, Field2, Field3;
+};
+MF &MF::operator=(const MF &Other) {
+ Field1 = Other.Field1;
+ Field2 = Other.Field2;
+ return *this;
+}
+
+struct Comments {
+ Comments(const Comments &Other)
+ /* don't delete */ : /* this comment */ Field(Other.Field) {}
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
+ // CHECK-FIXES: /* don't delete */ = default;
+ int Field;
+};
+
+struct MoreComments {
+ MoreComments(const MoreComments &Other) /* this comment is OK */
+ : Field(Other.Field) {}
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
+ // CHECK-FIXES: MoreComments(const MoreComments &Other) /* this comment is OK */
+ // CHECK-FIXES-NEXT: = default;
+ int Field;
+};
+
+struct ColonInComment {
+ ColonInComment(const ColonInComment &Other) /* : */ : Field(Other.Field) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: ColonInComment(const ColonInComment &Other) /* : */ = default;
+ int Field;
+};
+
+// No members or bases (in particular, no colon).
+struct Empty {
+ Empty(const Empty &Other) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: Empty(const Empty &Other) = default;
+ Empty &operator=(const Empty &);
+};
+Empty &Empty::operator=(const Empty &Other) { return *this; }
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use '= default'
+// CHECK-FIXES: Empty &Empty::operator=(const Empty &Other) = default;
+
+// Bit fields.
+struct BF {
+ BF() = default;
+ BF(const BF &Other) : Field1(Other.Field1), Field2(Other.Field2), Field3(Other.Field3),
+ Field4(Other.Field4) {}
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
+ // CHECK-FIXES: BF(const BF &Other) {{$}}
+ // CHECK-FIXES: = default;
+ BF &operator=(const BF &);
+
+ unsigned Field1 : 3;
+ int : 7;
+ char Field2 : 6;
+ int : 0;
+ int Field3 : 24;
+ unsigned char Field4;
+};
+BF &BF::operator=(const BF &Other) {
+ Field1 = Other.Field1;
+ Field2 = Other.Field2;
+ Field3 = Other.Field3;
+ Field4 = Other.Field4;
+ return *this;
+}
+// CHECK-MESSAGES: :[[@LINE-7]]:9: warning: use '= default'
+// CHECK-FIXES: BF &BF::operator=(const BF &Other) = default;
+
+// Base classes.
+struct BC : IL, OL, BF {
+ BC(const BC &Other) : IL(Other), OL(Other), BF(Other) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: BC(const BC &Other) = default;
+ BC &operator=(const BC &Other);
+};
+BC &BC::operator=(const BC &Other) {
+ IL::operator=(Other);
+ OL::operator=(Other);
+ BF::operator=(Other);
+ return *this;
+}
+// CHECK-MESSAGES: :[[@LINE-6]]:9: warning: use '= default'
+// CHECK-FIXES: BC &BC::operator=(const BC &Other) = default;
+
+// Base classes with member.
+struct BCWM : IL, OL {
+ BCWM(const BCWM &Other) : IL(Other), OL(Other), Bf(Other.Bf) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: BCWM(const BCWM &Other) = default;
+ BCWM &operator=(const BCWM &);
+ BF Bf;
+};
+BCWM &BCWM::operator=(const BCWM &Other) {
+ IL::operator=(Other);
+ OL::operator=(Other);
+ Bf = Other.Bf;
+ return *this;
+}
+// CHECK-MESSAGES: :[[@LINE-6]]:13: warning: use '= default'
+// CHECK-FIXES: BCWM &BCWM::operator=(const BCWM &Other) = default;
+
+// Missing base class.
+struct MBC : IL, OL, BF {
+ MBC(const MBC &Other) : IL(Other), OL(Other) {}
+ MBC &operator=(const MBC &);
+};
+MBC &MBC::operator=(const MBC &Other) {
+ IL::operator=(Other);
+ OL::operator=(Other);
+ return *this;
+}
+
+// Base classes, incorrect parameter.
+struct BCIP : BCWM, BF {
+ BCIP(const BCIP &Other) : BCWM(Other), BF(Other.Bf) {}
+ BCIP &operator=(const BCIP &);
+};
+BCIP &BCIP::operator=(const BCIP &Other) {
+ BCWM::operator=(Other);
+ BF::operator=(Other.Bf);
+ return *this;
+}
+
+// Virtual base classes.
+struct VA : virtual OL {};
+struct VB : virtual OL {};
+struct VBC : VA, VB, virtual OL {
+ // OL is the first thing that is going to be initialized, despite the fact
+ // that it is the last in the list of bases, because it is virtual and there
+ // is a virtual OL at the beginning of VA (which is the same).
+ VBC(const VBC &Other) : OL(Other), VA(Other), VB(Other) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: VBC(const VBC &Other) = default;
+ VBC &operator=(const VBC &Other);
+};
+VBC &VBC::operator=(const VBC &Other) {
+ OL::operator=(Other);
+ VA::operator=(Other);
+ VB::operator=(Other);
+ return *this;
+}
+// CHECK-MESSAGES: :[[@LINE-6]]:11: warning: use '= default'
+// CHECK-FIXES: VBC &VBC::operator=(const VBC &Other) = default;
+
+// Indirect base.
+struct IB : VBC {
+ IB(const IB &Other) : OL(Other), VBC(Other) {}
+ IB &operator=(const IB &);
+};
+IB &IB::operator=(const IB &Other) {
+ OL::operator=(Other);
+ VBC::operator=(Other);
+ return *this;
+}
+
+// Class template.
+template <class T>
+struct Template {
+ Template() = default;
+ Template(const Template &Other) : Field(Other.Field) {}
+ Template &operator=(const Template &Other);
+ void foo(const T &t);
+ int Field;
+};
+template <class T>
+Template<T> &Template<T>::operator=(const Template<T> &Other) {
+ Field = Other.Field;
+ return *this;
+}
+Template<int> T1;
+
+// Dependent types.
+template <class T>
+struct DT1 {
+ DT1() = default;
+ DT1(const DT1 &Other) : Field(Other.Field) {}
+ DT1 &operator=(const DT1 &);
+ T Field;
+};
+template <class T>
+DT1<T> &DT1<T>::operator=(const DT1<T> &Other) {
+ Field = Other.Field;
+ return *this;
+}
+DT1<int> Dt1;
+
+template <class T>
+struct DT2 {
+ DT2() = default;
+ DT2(const DT2 &Other) : Field(Other.Field), Dependent(Other.Dependent) {}
+ DT2 &operator=(const DT2 &);
+ T Field;
+ typename T::TT Dependent;
+};
+template <class T>
+DT2<T> &DT2<T>::operator=(const DT2<T> &Other) {
+ Field = Other.Field;
+ Dependent = Other.Dependent;
+ return *this;
+}
+struct T {
+ typedef int TT;
+};
+DT2<T> Dt2;
+
+// Default arguments.
+struct DA {
+ DA(int Int);
+ DA(const DA &Other = DA(0)) : Field1(Other.Field1), Field2(Other.Field2) {}
+ DA &operator=(const DA &);
+ int Field1;
+ char Field2;
+};
+// Overloaded operator= cannot have a default argument.
+DA &DA::operator=(const DA &Other) {
+ Field1 = Other.Field1;
+ Field2 = Other.Field2;
+ return *this;
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:9: warning: use '= default'
+// CHECK-FIXES: DA &DA::operator=(const DA &Other) = default;
+
+struct DA2 {
+ // Can be used as copy-constructor but cannot be explicitly defaulted.
+ DA2(const DA &Other, int Def = 0) {}
+};
+
+// Default initialization.
+struct DI {
+ DI(const DI &Other) : Field1(Other.Field1), Field2(Other.Field2) {}
+ int Field1;
+ int Field2 = 0;
+ int Fiedl3;
+};
+
+// Statement inside body.
+void foo();
+struct SIB {
+ SIB(const SIB &Other) : Field(Other.Field) { foo(); }
+ SIB &operator=(const SIB &);
+ int Field;
+};
+SIB &SIB::operator=(const SIB &Other) {
+ Field = Other.Field;
+ foo();
+ return *this;
+}
+
+// Comment inside body.
+struct CIB {
+ CIB(const CIB &Other) : Field(Other.Field) { /* Don't erase this */
+ }
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
+ CIB &operator=(const CIB &);
+ int Field;
+};
+CIB &CIB::operator=(const CIB &Other) {
+ Field = Other.Field;
+ // FIXME: don't erase this comment.
+ return *this;
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:11: warning: use '= default'
+// CHECK-FIXES: CIB &CIB::operator=(const CIB &Other) = default;
+
+// Take non-const reference as argument.
+struct NCRef {
+ NCRef(NCRef &Other) : Field1(Other.Field1), Field2(Other.Field2) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: NCRef(NCRef &Other) = default;
+ NCRef &operator=(NCRef &);
+ int Field1, Field2;
+};
+NCRef &NCRef::operator=(NCRef &Other) {
+ Field1 = Other.Field1;
+ Field2 = Other.Field2;
+ return *this;
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:15: warning: use '= default'
+// CHECK-FIXES: NCRef &NCRef::operator=(NCRef &Other) = default;
+
+// Already defaulted.
+struct IAD {
+ IAD(const IAD &Other) = default;
+ IAD &operator=(const IAD &Other) = default;
+};
+
+struct OAD {
+ OAD(const OAD &Other);
+ OAD &operator=(const OAD &);
+};
+OAD::OAD(const OAD &Other) = default;
+OAD &OAD::operator=(const OAD &Other) = default;
+
+// Deleted.
+struct ID {
+ ID(const ID &Other) = delete;
+ ID &operator=(const ID &Other) = delete;
+};
+
+// Non-reference parameter.
+struct NRef {
+ NRef &operator=(NRef Other);
+ int Field1;
+};
+NRef &NRef::operator=(NRef Other) {
+ Field1 = Other.Field1;
+ return *this;
+}
+
+// RValue reference parameter.
+struct RVR {
+ RVR(RVR &&Other) {}
+ RVR &operator=(RVR &&);
+};
+RVR &RVR::operator=(RVR &&Other) { return *this; }
+
+// Similar function.
+struct SF {
+ SF &foo(const SF &);
+ int Field1;
+};
+SF &SF::foo(const SF &Other) {
+ Field1 = Other.Field1;
+ return *this;
+}
+
+// No return.
+struct NR {
+ NR &operator=(const NR &);
+};
+NR &NR::operator=(const NR &Other) {}
+
+// Return misplaced.
+struct RM {
+ RM &operator=(const RM &);
+ int Field;
+};
+RM &RM::operator=(const RM &Other) {
+ return *this;
+ Field = Other.Field;
+}
+
+// Wrong return value.
+struct WRV {
+ WRV &operator=(WRV &);
+};
+WRV &WRV::operator=(WRV &Other) {
+ return Other;
+}
+
+// Wrong return type.
+struct WRT : IL {
+ IL &operator=(const WRT &);
+};
+IL &WRT::operator=(const WRT &Other) {
+ return *this;
+}
+
+// Try-catch.
+struct ITC {
+ ITC(const ITC &Other)
+ try : Field(Other.Field) {
+ } catch (...) {
+ }
+ ITC &operator=(const ITC &Other) try {
+ Field = Other.Field;
+ } catch (...) {
+ }
+ int Field;
+};
+
+struct OTC {
+ OTC(const OTC &);
+ OTC &operator=(const OTC &);
+ int Field;
+};
+OTC::OTC(const OTC &Other) try : Field(Other.Field) {
+} catch (...) {
+}
+OTC &OTC::operator=(const OTC &Other) try {
+ Field = Other.Field;
+} catch (...) {
+}
+
+// FIXME: the check is not able to detect exception specification.
+// noexcept(true).
+struct NET {
+ // This is the default.
+ //NET(const NET &Other) noexcept {}
+ NET &operator=(const NET &Other) noexcept;
+};
+//NET &NET::operator=(const NET &Other) noexcept { return *this; }
+
+// noexcept(false).
+struct NEF {
+ // This is the default.
+ //NEF(const NEF &Other) noexcept(false) {}
+ NEF &operator=(const NEF &Other) noexcept(false);
+};
+//NEF &NEF::operator=(const NEF &Other) noexcept(false) { return *this; }
+
+#define STRUCT_WITH_COPY_CONSTRUCT(_base, _type) \
+ struct _type { \
+ _type(const _type &v) : value(v.value) {} \
+ _base value; \
+ };
+
+STRUCT_WITH_COPY_CONSTRUCT(unsigned char, Hex8CopyConstruct)
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial copy constructor
+// CHECK-MESSAGES: :[[@LINE-6]]:44: note:
+
+#define STRUCT_WITH_COPY_ASSIGN(_base, _type) \
+ struct _type { \
+ _type &operator=(const _type &rhs) { \
+ value = rhs.value; \
+ return *this; \
+ } \
+ _base value; \
+ };
+
+STRUCT_WITH_COPY_ASSIGN(unsigned char, Hex8CopyAssign)
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial copy-assignment operator
+// CHECK-MESSAGES: :[[@LINE-9]]:40: note:
+
+// Use of braces
+struct UOB{
+ UOB(const UOB &Other):j{Other.j}{}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' to define a trivial copy constructor [modernize-use-equals-default]
+ // CHECK-FIXES: UOB(const UOB &Other)= default;
+ int j;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default-delayed.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default-delayed.cpp
new file mode 100644
index 0000000..953d88a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default-delayed.cpp
@@ -0,0 +1,8 @@
+// RUN: clang-tidy %s -checks=-*,modernize-use-equals-default -- -std=c++11 -fdelayed-template-parsing -fexceptions | count 0
+// Note: this test expects no diagnostics, but FileCheck cannot handle that,
+// hence the use of | count 0.
+
+template <typename Ty>
+struct S {
+ S<Ty>& operator=(const S<Ty>&) { return *this; }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default-macros.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default-macros.cpp
new file mode 100644
index 0000000..2277a86
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default-macros.cpp
@@ -0,0 +1,13 @@
+// RUN: %check_clang_tidy %s modernize-use-equals-default %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-equals-default.IgnoreMacros, value: 0}]}" \
+// RUN: -- -std=c++11
+
+#define STRUCT_WITH_DEFAULT(_base, _type) \
+ struct _type { \
+ _type() {} \
+ _base value; \
+ };
+
+STRUCT_WITH_DEFAULT(unsigned char, InMacro)
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial default constructor
+// CHECK-MESSAGES: :[[@LINE-6]]:13: note:
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default.cpp
new file mode 100644
index 0000000..8fa15ff
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default.cpp
@@ -0,0 +1,207 @@
+// RUN: %check_clang_tidy %s modernize-use-equals-default %t -- -- -std=c++11 -fno-delayed-template-parsing -fexceptions
+
+// Out of line definition.
+class OL {
+public:
+ OL();
+ ~OL();
+};
+
+OL::OL() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default' to define a trivial default constructor [modernize-use-equals-default]
+// CHECK-FIXES: OL::OL() = default;
+OL::~OL() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default' to define a trivial destructor [modernize-use-equals-default]
+// CHECK-FIXES: OL::~OL() = default;
+
+// Inline definitions.
+class IL {
+public:
+ IL() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: IL() = default;
+ ~IL() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: ~IL() = default;
+};
+
+// Non-empty body.
+void f();
+class NE {
+public:
+ NE() { f(); }
+ ~NE() { f(); }
+};
+
+// Initializer or arguments.
+class IA {
+public:
+ // Constructor with initializer.
+ IA() : Field(5) {}
+ // Constructor with arguments.
+ IA(int Arg1, int Arg2) {}
+ int Field;
+};
+
+// Default member initializer
+class DMI {
+public:
+ DMI() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: DMI() = default;
+ int Field = 5;
+};
+
+// Class member
+class CM {
+public:
+ CM() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: CM() = default;
+ OL o;
+};
+
+// Private constructor/destructor.
+class Priv {
+ Priv() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: Priv() = default;
+ ~Priv() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: ~Priv() = default;
+};
+
+// struct.
+struct ST {
+ ST() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: ST() = default;
+ ~ST() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: ST() = default;
+};
+
+// Deleted constructor/destructor.
+class Del {
+public:
+ Del() = delete;
+ ~Del() = delete;
+};
+
+// Do not remove other keywords.
+class KW {
+public:
+ explicit KW() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use '= default'
+ // CHECK-FIXES: explicit KW() = default;
+ virtual ~KW() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use '= default'
+ // CHECK-FIXES: virtual ~KW() = default;
+};
+
+// Nested class.
+struct N {
+ struct NN {
+ NN() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default'
+ // CHECK-FIXES: NN() = default;
+ ~NN() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default'
+ // CHECK-FIXES: ~NN() = default;
+ };
+ int Int;
+};
+
+// Class template.
+template <class T>
+class Temp {
+public:
+ Temp() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: Temp() = default;
+ ~Temp() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: ~Temp() = default;
+};
+
+// Class template out of line with explicit instantiation.
+template <class T>
+class TempODef {
+public:
+ TempODef();
+ ~TempODef();
+};
+
+template <class T>
+TempODef<T>::TempODef() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use '= default'
+// CHECK-FIXES: TempODef<T>::TempODef() = default;
+template <class T>
+TempODef<T>::~TempODef() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use '= default'
+// CHECK-FIXES: TempODef<T>::~TempODef() = default;
+
+template class TempODef<int>;
+template class TempODef<double>;
+
+// Non user-provided constructor/destructor.
+struct Imp {
+ int Int;
+};
+void g() {
+ Imp *PtrImp = new Imp();
+ PtrImp->~Imp();
+ delete PtrImp;
+}
+
+// Already using default.
+struct IDef {
+ IDef() = default;
+ ~IDef() = default;
+};
+struct ODef {
+ ODef();
+ ~ODef();
+};
+ODef::ODef() = default;
+ODef::~ODef() = default;
+
+// Delegating constructor and overriden destructor.
+struct DC : KW {
+ DC() : KW() {}
+ ~DC() override {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: ~DC() override = default;
+};
+
+struct Comments {
+ Comments() {
+ // Don't erase comments inside the body.
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use '= default'
+ ~Comments() {
+ // Don't erase comments inside the body.
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use '= default'
+};
+
+// Try-catch.
+struct ITC {
+ ITC() try {} catch(...) {}
+ ~ITC() try {} catch(...) {}
+};
+
+struct OTC {
+ OTC();
+ ~OTC();
+};
+OTC::OTC() try {} catch(...) {}
+OTC::~OTC() try {} catch(...) {}
+
+#define STRUCT_WITH_DEFAULT(_base, _type) \
+ struct _type { \
+ _type() {} \
+ _base value; \
+ };
+
+STRUCT_WITH_DEFAULT(unsigned char, InMacro)
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-delete.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-delete.cpp
new file mode 100644
index 0000000..6ab2ae4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-delete.cpp
@@ -0,0 +1,187 @@
+// RUN: %check_clang_tidy %s modernize-use-equals-delete %t
+
+struct PositivePrivate {
+private:
+ PositivePrivate();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+ // CHECK-FIXES: PositivePrivate() = delete;
+ PositivePrivate(const PositivePrivate &);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+ // CHECK-FIXES: PositivePrivate(const PositivePrivate &) = delete;
+ PositivePrivate &operator=(const PositivePrivate &);
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+ // CHECK-FIXES: PositivePrivate &operator=(const PositivePrivate &) = delete;
+ PositivePrivate(PositivePrivate &&);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+ // CHECK-FIXES: PositivePrivate(PositivePrivate &&) = delete;
+ PositivePrivate &operator=(PositivePrivate &&);
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+ // CHECK-FIXES: PositivePrivate &operator=(PositivePrivate &&) = delete;
+ ~PositivePrivate();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+ // CHECK-FIXES: ~PositivePrivate() = delete;
+};
+
+template<typename T>
+struct PositivePrivateTemplate {
+private:
+ PositivePrivateTemplate();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+ // CHECK-FIXES: PositivePrivateTemplate() = delete;
+ PositivePrivateTemplate(const PositivePrivateTemplate &);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+ // CHECK-FIXES: PositivePrivateTemplate(const PositivePrivateTemplate &) = delete;
+ PositivePrivateTemplate &operator=(const PositivePrivateTemplate &);
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+ // CHECK-FIXES: PositivePrivateTemplate &operator=(const PositivePrivateTemplate &) = delete;
+ PositivePrivateTemplate(PositivePrivateTemplate &&);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+ // CHECK-FIXES: PositivePrivateTemplate(PositivePrivateTemplate &&) = delete;
+ PositivePrivateTemplate &operator=(PositivePrivateTemplate &&);
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+ // CHECK-FIXES: PositivePrivateTemplate &operator=(PositivePrivateTemplate &&) = delete;
+ ~PositivePrivateTemplate();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+ // CHECK-FIXES: ~PositivePrivateTemplate() = delete;
+};
+
+template struct PositivePrivateTemplate<int>;
+template struct PositivePrivateTemplate<char>;
+
+struct NegativePublic {
+ NegativePublic(const NegativePublic &);
+};
+
+struct NegativeProtected {
+protected:
+ NegativeProtected(const NegativeProtected &);
+};
+
+struct PositiveInlineMember {
+ int foo() { return 0; }
+
+private:
+ PositiveInlineMember(const PositiveInlineMember &);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+ // CHECK-FIXES: PositiveInlineMember(const PositiveInlineMember &) = delete;
+};
+
+struct PositiveOutOfLineMember {
+ int foo();
+
+private:
+ PositiveOutOfLineMember(const PositiveOutOfLineMember &);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+ // CHECK-FIXES: PositiveOutOfLineMember(const PositiveOutOfLineMember &) = delete;
+};
+
+int PositiveOutOfLineMember::foo() { return 0; }
+
+struct PositiveAbstractMember {
+ virtual int foo() = 0;
+
+private:
+ PositiveAbstractMember(const PositiveAbstractMember &);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+ // CHECK-FIXES: PositiveAbstractMember(const PositiveAbstractMember &) = delete;
+};
+
+struct NegativeMemberNotImpl {
+ int foo();
+
+private:
+ NegativeMemberNotImpl(const NegativeMemberNotImpl &);
+};
+
+struct NegativeStaticMemberNotImpl {
+ static int foo();
+
+private:
+ NegativeStaticMemberNotImpl(const NegativeStaticMemberNotImpl &);
+};
+
+struct NegativeInline {
+private:
+ NegativeInline(const NegativeInline &) {}
+};
+
+struct NegativeOutOfLine {
+private:
+ NegativeOutOfLine(const NegativeOutOfLine &);
+};
+
+NegativeOutOfLine::NegativeOutOfLine(const NegativeOutOfLine &) {}
+
+struct NegativeConstructNotImpl {
+ NegativeConstructNotImpl();
+
+private:
+ NegativeConstructNotImpl(const NegativeConstructNotImpl &);
+};
+
+struct PositiveDefaultedConstruct {
+ PositiveDefaultedConstruct() = default;
+
+private:
+ PositiveDefaultedConstruct(const PositiveDefaultedConstruct &);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+ // CHECK-FIXES: PositiveDefaultedConstruct(const PositiveDefaultedConstruct &) = delete;
+};
+
+struct PositiveDeletedConstruct {
+ PositiveDeletedConstruct() = delete;
+
+private:
+ PositiveDeletedConstruct(const PositiveDeletedConstruct &);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+ // CHECK-FIXES: PositiveDeletedConstruct(const PositiveDeletedConstruct &) = delete;
+};
+
+struct NegativeDefaulted {
+private:
+ NegativeDefaulted(const NegativeDefaulted &) = default;
+};
+
+struct PrivateDeleted {
+private:
+ PrivateDeleted(const PrivateDeleted &) = delete;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: deleted member function should be public [modernize-use-equals-delete]
+};
+
+struct ProtectedDeleted {
+protected:
+ ProtectedDeleted(const ProtectedDeleted &) = delete;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: deleted member function should be public [modernize-use-equals-delete]
+};
+
+struct PublicDeleted {
+public:
+ PublicDeleted(const PublicDeleted &) = delete;
+};
+
+#define M1 \
+ struct PrivateDeletedMacro { \
+ private: \
+ PrivateDeletedMacro(const PrivateDeletedMacro &) = delete; \
+ }; \
+ struct ProtectedDeletedMacro { \
+ protected: \
+ ProtectedDeletedMacro(const ProtectedDeletedMacro &) = delete; \
+ }
+
+M1;
+
+#define DISALLOW_COPY_AND_ASSIGN(name) \
+ name(const name &) = delete; \
+ void operator=(const name &) = delete
+
+struct PrivateDeletedMacro2 {
+private:
+ DISALLOW_COPY_AND_ASSIGN(PrivateDeletedMacro2);
+};
+
+struct ProtectedDeletedMacro2 {
+protected:
+ DISALLOW_COPY_AND_ASSIGN(ProtectedDeletedMacro2);
+};
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-noexcept-macro.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-noexcept-macro.cpp
new file mode 100644
index 0000000..3948b66
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-noexcept-macro.cpp
@@ -0,0 +1,36 @@
+// RUN: %check_clang_tidy %s modernize-use-noexcept %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-noexcept.ReplacementString, value: 'NOEXCEPT'}]}" \
+// RUN: -- -std=c++11 -fexceptions
+
+// Example definition of NOEXCEPT -- simplified test to see if noexcept is supported.
+#if (__has_feature(cxx_noexcept))
+#define NOEXCEPT noexcept
+#else
+#define NOEXCEPT throw()
+#endif
+
+void bar() throw() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'NOEXCEPT' instead [modernize-use-noexcept]
+// CHECK-FIXES: void bar() NOEXCEPT {}
+
+// Should not trigger a FixItHint, since macros only support noexcept, and this
+// case throws.
+class A {};
+class B {};
+void foobar() throw(A, B);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: dynamic exception specification 'throw(A, B)' is deprecated; consider removing it instead [modernize-use-noexcept]
+
+// Should not trigger a replacement.
+void foo() noexcept(true);
+
+struct Z {
+ void operator delete(void *ptr) throw();
+ void operator delete[](void *ptr) throw(int);
+ ~Z() throw(int) {}
+};
+// CHECK-MESSAGES: :[[@LINE-4]]:35: warning: dynamic exception specification 'throw()' is deprecated; consider using 'NOEXCEPT' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-4]]:37: warning: dynamic exception specification 'throw(int)' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-4]]:8: warning: dynamic exception specification 'throw(int)' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-FIXES: void operator delete(void *ptr) NOEXCEPT;
+// CHECK-FIXES: void operator delete[](void *ptr) throw(int);
+// CHECK-FIXES: ~Z() throw(int) {}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-noexcept-opt.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-noexcept-opt.cpp
new file mode 100644
index 0000000..85a83c8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-noexcept-opt.cpp
@@ -0,0 +1,88 @@
+// RUN: %check_clang_tidy %s modernize-use-noexcept %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-noexcept.UseNoexceptFalse, value: 0}]}" \
+// RUN: -- -std=c++11 -fexceptions
+
+class A {};
+class B {};
+
+void foo() throw();
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void foo() noexcept;
+
+void bar() throw(...);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: dynamic exception specification 'throw(...)' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-FIXES: void bar() ;
+
+void k() throw(int(int));
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: dynamic exception specification 'throw(int(int))' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-FIXES: void k() ;
+
+void foobar() throw(A, B)
+{}
+// CHECK-MESSAGES: :[[@LINE-2]]:15: warning: dynamic exception specification 'throw(A, B)' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-FIXES: void foobar()
+
+void baz(int = (throw A(), 0)) throw(A, B) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: dynamic exception specification 'throw(A, B)' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-FIXES: void baz(int = (throw A(), 0)) {}
+
+void g(void (*fp)(void) throw());
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void g(void (*fp)(void) noexcept);
+
+void f(void (*fp)(void) throw(int)) throw(char);
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: dynamic exception specification 'throw(int)' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-2]]:37: warning: dynamic exception specification 'throw(char)' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-FIXES: void f(void (*fp)(void) ) ;
+
+#define THROW throw
+void h(void (*fp)(void) THROW(int)) THROW(char);
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: dynamic exception specification 'THROW(int)' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-2]]:37: warning: dynamic exception specification 'THROW(char)' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-FIXES: void h(void (*fp)(void) ) ;
+
+void j() throw(int(int) throw(void(void) throw(int)));
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: dynamic exception specification 'throw(int(int) throw(void(void) throw(int)))' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-FIXES: void j() ;
+
+class Y {
+ Y() throw() = default;
+};
+// CHECK-MESSAGES: :[[@LINE-2]]:7: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: Y() noexcept = default;
+
+struct Z {
+ void operator delete(void *ptr) throw();
+ void operator delete[](void *ptr) throw(int);
+ ~Z() throw(int) {}
+};
+// CHECK-MESSAGES: :[[@LINE-4]]:35: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-4]]:37: warning: dynamic exception specification 'throw(int)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-4]]:8: warning: dynamic exception specification 'throw(int)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void operator delete(void *ptr) noexcept;
+// CHECK-FIXES: void operator delete[](void *ptr) noexcept(false);
+// CHECK-FIXES: ~Z() noexcept(false) {}
+
+struct S {
+ void f() throw();
+};
+void f(void (S::*)() throw());
+// CHECK-MESSAGES: :[[@LINE-3]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-2]]:22: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void f() noexcept;
+// CHECK-FIXES: void f(void (S::*)() noexcept);
+
+typedef void (*fp)(void (*fp2)(int) throw());
+// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: typedef void (*fp)(void (*fp2)(int) noexcept);
+
+// Should not trigger a replacement.
+void titi() noexcept {}
+void toto() noexcept(true) {}
+
+// Should not trigger a replacement.
+void bad()
+#if !__has_feature(cxx_noexcept)
+ throw()
+#endif
+ ;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-noexcept.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-noexcept.cpp
new file mode 100644
index 0000000..58c764a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-noexcept.cpp
@@ -0,0 +1,104 @@
+// RUN: %check_clang_tidy %s modernize-use-noexcept %t -- \
+// RUN: -- -std=c++11 -fexceptions
+
+class A {};
+class B {};
+
+void foo() throw();
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void foo() noexcept;
+
+template <typename T>
+void foo() throw();
+void footest() { foo<int>(); foo<double>(); }
+// CHECK-MESSAGES: :[[@LINE-2]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void foo() noexcept;
+
+void bar() throw(...);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: dynamic exception specification 'throw(...)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void bar() noexcept(false);
+
+void k() throw(int(int));
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: dynamic exception specification 'throw(int(int))' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void k() noexcept(false);
+
+void foobar() throw(A, B)
+{}
+// CHECK-MESSAGES: :[[@LINE-2]]:15: warning: dynamic exception specification 'throw(A, B)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void foobar() noexcept(false)
+
+void baz(int = (throw A(), 0)) throw(A, B) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: dynamic exception specification 'throw(A, B)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void baz(int = (throw A(), 0)) noexcept(false) {}
+
+void g(void (*fp)(void) throw());
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void g(void (*fp)(void) noexcept);
+
+void f(void (*fp)(void) throw(int)) throw(char);
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: dynamic exception specification 'throw(int)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-2]]:37: warning: dynamic exception specification 'throw(char)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void f(void (*fp)(void) noexcept(false)) noexcept(false);
+
+#define THROW throw
+void h(void (*fp)(void) THROW(int)) THROW(char);
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: dynamic exception specification 'THROW(int)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-2]]:37: warning: dynamic exception specification 'THROW(char)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void h(void (*fp)(void) noexcept(false)) noexcept(false);
+
+void j() throw(int(int) throw(void(void) throw(int)));
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: dynamic exception specification 'throw(int(int) throw(void(void) throw(int)))' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void j() noexcept(false);
+
+class Y {
+ Y() throw() = default;
+};
+// CHECK-MESSAGES: :[[@LINE-2]]:7: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: Y() noexcept = default;
+
+struct Z {
+ void operator delete(void *ptr) throw();
+ void operator delete[](void *ptr) throw(int);
+ ~Z() throw(int) {}
+};
+// CHECK-MESSAGES: :[[@LINE-4]]:35: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-4]]:37: warning: dynamic exception specification 'throw(int)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-4]]:8: warning: dynamic exception specification 'throw(int)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void operator delete(void *ptr) noexcept;
+// CHECK-FIXES: void operator delete[](void *ptr) noexcept(false);
+// CHECK-FIXES: ~Z() noexcept(false) {}
+
+struct S {
+ void f() throw();
+};
+void f(void (S::*)() throw());
+// CHECK-MESSAGES: :[[@LINE-3]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-2]]:22: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void f() noexcept;
+// CHECK-FIXES: void f(void (S::*)() noexcept);
+
+template <typename T>
+struct ST {
+ void foo() throw();
+};
+template <typename T>
+void ft(void (ST<T>::*)() throw());
+// CHECK-MESSAGES: :[[@LINE-4]]:14: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-2]]:27: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void foo() noexcept;
+// CHECK-FIXES: void ft(void (ST<T>::*)() noexcept);
+
+typedef void (*fp)(void (*fp2)(int) throw());
+// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: typedef void (*fp)(void (*fp2)(int) noexcept);
+
+// Should not trigger a replacement.
+void titi() noexcept {}
+void toto() noexcept(true) {}
+
+// Should not trigger a replacement.
+void bad()
+#if !__has_feature(cxx_noexcept)
+ throw()
+#endif
+ ;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-nullptr-basic.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-nullptr-basic.cpp
new file mode 100644
index 0000000..7a953a7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-nullptr-basic.cpp
@@ -0,0 +1,361 @@
+// RUN: %check_clang_tidy %s modernize-use-nullptr %t -- -- \
+// RUN: -std=c++98 -Wno-non-literal-null-conversion
+//
+// Some parts of the test (e.g. assignment of `const int` to `int *`) fail in
+// C++11, so we need to run the test in C++98 mode.
+
+const unsigned int g_null = 0;
+#define NULL 0
+
+void test_assignment() {
+ int *p1 = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr [modernize-use-nullptr]
+ // CHECK-FIXES: int *p1 = nullptr;
+ p1 = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr
+ // CHECK-FIXES: p1 = nullptr;
+
+ int *p2 = NULL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr
+ // CHECK-FIXES: int *p2 = nullptr;
+
+ p2 = p1;
+ // CHECK-FIXES: p2 = p1;
+
+ const int null = 0;
+ int *p3 = null;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr
+ // CHECK-FIXES: int *p3 = nullptr;
+
+ p3 = NULL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr
+ // CHECK-FIXES: p3 = nullptr;
+
+ int *p4 = p3;
+ // CHECK-FIXES: int *p4 = p3;
+
+ p4 = null;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr
+ // CHECK-FIXES: p4 = nullptr;
+
+ int i1 = 0;
+
+ int i2 = NULL;
+
+ int i3 = null;
+
+ int *p5, *p6, *p7;
+ p5 = p6 = p7 = NULL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
+ // CHECK-FIXES: p5 = p6 = p7 = nullptr;
+}
+
+struct Foo {
+ Foo(int *p = NULL) : m_p1(p) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+ // CHECK-FIXES: Foo(int *p = nullptr) : m_p1(p) {}
+
+ void bar(int *p = 0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use nullptr
+ // CHECK-FIXES: void bar(int *p = nullptr) {}
+
+ void baz(int i = 0) {}
+
+ int *m_p1;
+ static int *m_p2;
+};
+
+int *Foo::m_p2 = NULL;
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
+// CHECK-FIXES: int *Foo::m_p2 = nullptr;
+
+template <typename T>
+struct Bar {
+ Bar(T *p) : m_p(p) {
+ m_p = static_cast<T*>(NULL);
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr
+ // CHECK-FIXES: m_p = static_cast<T*>(nullptr);
+
+ m_p = static_cast<T*>(reinterpret_cast<int*>((void*)NULL));
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr
+ // CHECK-FIXES: m_p = static_cast<T*>(nullptr);
+
+ m_p = static_cast<T*>(p ? p : static_cast<void*>(g_null));
+ // CHECK-MESSAGES: :[[@LINE-1]]:54: warning: use nullptr
+ // CHECK-FIXES: m_p = static_cast<T*>(p ? p : static_cast<void*>(nullptr));
+
+ T *p2 = static_cast<T*>(reinterpret_cast<int*>((void*)NULL));
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr
+ // CHECK-FIXES: T *p2 = static_cast<T*>(nullptr);
+
+ m_p = NULL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use nullptr
+ // CHECK-FIXES: m_p = nullptr;
+
+ int i = static_cast<int>(0.f);
+ T *i2 = static_cast<int>(0.f);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr
+ // CHECK-FIXES: T *i2 = nullptr;
+ }
+
+ T *m_p;
+};
+
+struct Baz {
+ Baz() : i(0) {}
+ int i;
+};
+
+void test_cxx_cases() {
+ Foo f(g_null);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+ // CHECK-FIXES: Foo f(nullptr);
+
+ f.bar(NULL);
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+ // CHECK-FIXES: f.bar(nullptr);
+
+ f.baz(g_null);
+
+ f.m_p1 = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
+ // CHECK-FIXES: f.m_p1 = nullptr;
+
+ Bar<int> b(g_null);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
+ // CHECK-FIXES: Bar<int> b(nullptr);
+
+ Baz b2;
+ int Baz::*memptr(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use nullptr
+ // CHECK-FIXES: int Baz::*memptr(nullptr);
+
+ memptr = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
+ // CHECK-FIXES: memptr = nullptr;
+}
+
+void test_function_default_param1(void *p = 0);
+// CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use nullptr
+// CHECK-FIXES: void test_function_default_param1(void *p = nullptr);
+
+void test_function_default_param2(void *p = NULL);
+// CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use nullptr
+// CHECK-FIXES: void test_function_default_param2(void *p = nullptr);
+
+void test_function_default_param3(void *p = g_null);
+// CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use nullptr
+// CHECK-FIXES: void test_function_default_param3(void *p = nullptr);
+
+void test_function(int *p) {}
+
+void test_function_no_ptr_param(int i) {}
+
+void test_function_call() {
+ test_function(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr
+ // CHECK-FIXES: test_function(nullptr);
+
+ test_function(NULL);
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr
+ // CHECK-FIXES: test_function(nullptr);
+
+ test_function(g_null);
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr
+ // CHECK-FIXES: test_function(nullptr);
+
+ test_function_no_ptr_param(0);
+}
+
+char *test_function_return1() {
+ return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr
+ // CHECK-FIXES: return nullptr;
+}
+
+void *test_function_return2() {
+ return NULL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr
+ // CHECK-FIXES: return nullptr;
+}
+
+long *test_function_return3() {
+ return g_null;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr
+ // CHECK-FIXES: return nullptr;
+}
+
+int test_function_return4() {
+ return 0;
+}
+
+int test_function_return5() {
+ return NULL;
+}
+
+int test_function_return6() {
+ return g_null;
+}
+
+int *test_function_return_cast1() {
+ return(int)0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+ // CHECK-FIXES: return nullptr;
+}
+
+int *test_function_return_cast2() {
+#define RET return
+ RET(int)0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use nullptr
+ // CHECK-FIXES: RET nullptr;
+#undef RET
+}
+
+// Test parentheses expressions resulting in a nullptr.
+int *test_parentheses_expression1() {
+ return(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr
+ // CHECK-FIXES: return(nullptr);
+}
+
+int *test_parentheses_expression2() {
+ return(int(0.f));
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr
+ // CHECK-FIXES: return(nullptr);
+}
+
+int *test_nested_parentheses_expression() {
+ return((((0))));
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr
+ // CHECK-FIXES: return((((nullptr))));
+}
+
+void *test_parentheses_explicit_cast() {
+ return(static_cast<void*>(0));
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr
+ // CHECK-FIXES: return(static_cast<void*>(nullptr));
+}
+
+void *test_parentheses_explicit_cast_sequence1() {
+ return(static_cast<void*>(static_cast<int*>((void*)NULL)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr
+ // CHECK-FIXES: return(static_cast<void*>(nullptr));
+}
+
+void *test_parentheses_explicit_cast_sequence2() {
+ return(static_cast<void*>(reinterpret_cast<int*>((float*)int(0.f))));
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr
+ // CHECK-FIXES: return(static_cast<void*>(nullptr));
+}
+
+// Test explicit cast expressions resulting in nullptr.
+struct Bam {
+ Bam(int *a) {}
+ Bam(float *a) {}
+ Bam operator=(int *a) { return Bam(a); }
+ Bam operator=(float *a) { return Bam(a); }
+};
+
+void ambiguous_function(int *a) {}
+void ambiguous_function(float *a) {}
+void const_ambiguous_function(const int *p) {}
+void const_ambiguous_function(const float *p) {}
+
+void test_explicit_cast_ambiguous1() {
+ ambiguous_function((int*)0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use nullptr
+ // CHECK-FIXES: ambiguous_function((int*)nullptr);
+}
+
+void test_explicit_cast_ambiguous2() {
+ ambiguous_function((int*)(0));
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use nullptr
+ // CHECK-FIXES: ambiguous_function((int*)nullptr);
+}
+
+void test_explicit_cast_ambiguous3() {
+ ambiguous_function(static_cast<int*>(reinterpret_cast<int*>((float*)0)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: use nullptr
+ // CHECK-FIXES: ambiguous_function(static_cast<int*>(nullptr));
+}
+
+Bam test_explicit_cast_ambiguous4() {
+ return(((int*)(0)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr
+ // CHECK-FIXES: return(((int*)nullptr));
+}
+
+void test_explicit_cast_ambiguous5() {
+ // Test for ambiguous overloaded constructors.
+ Bam k((int*)(0));
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use nullptr
+ // CHECK-FIXES: Bam k((int*)nullptr);
+
+ // Test for ambiguous overloaded operators.
+ k = (int*)0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr
+ // CHECK-FIXES: k = (int*)nullptr;
+}
+
+void test_const_pointers_abiguous() {
+ const_ambiguous_function((int*)0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use nullptr
+ // CHECK-FIXES: const_ambiguous_function((int*)nullptr);
+}
+
+// Test where the implicit cast to null is surrounded by another implict cast
+// with possible explict casts in-between.
+void test_const_pointers() {
+ const int *const_p1 = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr
+ // CHECK-FIXES: const int *const_p1 = nullptr;
+ const int *const_p2 = NULL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr
+ // CHECK-FIXES: const int *const_p2 = nullptr;
+ const int *const_p3 = (int)0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr
+ // CHECK-FIXES: const int *const_p3 = nullptr;
+ const int *const_p4 = (int)0.0f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr
+ // CHECK-FIXES: const int *const_p4 = nullptr;
+ const int *const_p5 = (int*)0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use nullptr
+ // CHECK-FIXES: const int *const_p5 = (int*)nullptr;
+ int *t;
+ const int *const_p6 = static_cast<int*>(t ? t : static_cast<int*>(0));
+ // CHECK-MESSAGES: :[[@LINE-1]]:69: warning: use nullptr
+ // CHECK-FIXES: const int *const_p6 = static_cast<int*>(t ? t : static_cast<int*>(nullptr));
+}
+
+void test_nested_implicit_cast_expr() {
+ int func0(void*, void*);
+ int func1(int, void*, void*);
+
+ (double)func1(0, 0, 0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use nullptr
+ // CHECK-MESSAGES: :[[@LINE-2]]:23: warning: use nullptr
+ // CHECK-FIXES: (double)func1(0, nullptr, nullptr);
+ (double)func1(func0(0, 0), 0, 0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use nullptr
+ // CHECK-MESSAGES: :[[@LINE-2]]:26: warning: use nullptr
+ // CHECK-MESSAGES: :[[@LINE-3]]:30: warning: use nullptr
+ // CHECK-MESSAGES: :[[@LINE-4]]:33: warning: use nullptr
+ // CHECK-FIXES: (double)func1(func0(nullptr, nullptr), nullptr, nullptr);
+}
+
+// FIXME: currently, the check doesn't work as it should with templates.
+template<typename T>
+class A {
+ public:
+ A(T *p = NULL) {}
+
+ void f() {
+ Ptr = NULL;
+ }
+ T *Ptr;
+};
+
+template<typename T>
+T *f2(T *a = NULL) {
+ return a ? a : NULL;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-nullptr.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-nullptr.c
new file mode 100644
index 0000000..c2ccbbd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-nullptr.c
@@ -0,0 +1,10 @@
+// RUN: clang-tidy %s -checks=-*,modernize-use-nullptr -- | count 0
+
+// Note: this test expects no diagnostics, but FileCheck cannot handle that,
+// hence the use of | count 0.
+
+#define NULL 0
+void f(void) {
+ char *str = NULL; // ok
+ (void)str;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-nullptr.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-nullptr.cpp
new file mode 100644
index 0000000..878c114
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-nullptr.cpp
@@ -0,0 +1,305 @@
+// RUN: %check_clang_tidy %s modernize-use-nullptr %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-nullptr.NullMacros, value: 'MY_NULL,NULL'}]}" \
+// RUN: -- -std=c++11
+
+#define NULL 0
+
+namespace std {
+
+typedef decltype(nullptr) nullptr_t;
+
+} // namespace std
+
+// Just to make sure make_null() could have side effects.
+void external();
+
+std::nullptr_t make_null() {
+ external();
+ return nullptr;
+}
+
+void func() {
+ void *CallTest = make_null();
+
+ int var = 1;
+ void *CommaTest = (var+=2, make_null());
+
+ int *CastTest = static_cast<int*>(make_null());
+}
+
+void dummy(int*) {}
+void side_effect() {}
+
+#define MACRO_EXPANSION_HAS_NULL \
+ void foo() { \
+ dummy(0); \
+ dummy(NULL); \
+ side_effect(); \
+ }
+
+MACRO_EXPANSION_HAS_NULL;
+#undef MACRO_EXPANSION_HAS_NULL
+
+
+void test_macro_expansion1() {
+#define MACRO_EXPANSION_HAS_NULL \
+ dummy(NULL); \
+ side_effect();
+
+ MACRO_EXPANSION_HAS_NULL;
+
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+// Test macro expansion with cast sequence, PR15572.
+void test_macro_expansion2() {
+#define MACRO_EXPANSION_HAS_NULL \
+ dummy((int*)0); \
+ side_effect();
+
+ MACRO_EXPANSION_HAS_NULL;
+
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+void test_macro_expansion3() {
+#define MACRO_EXPANSION_HAS_NULL \
+ dummy(NULL); \
+ side_effect();
+
+#define OUTER_MACRO \
+ MACRO_EXPANSION_HAS_NULL; \
+ side_effect();
+
+ OUTER_MACRO;
+
+#undef OUTER_MACRO
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+void test_macro_expansion4() {
+#define MY_NULL NULL
+ int *p = MY_NULL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr [modernize-use-nullptr]
+ // CHECK-FIXES: int *p = nullptr;
+#undef MY_NULL
+}
+
+#define IS_EQ(x, y) if (x != y) return;
+void test_macro_args() {
+ int i = 0;
+ int *Ptr;
+
+ IS_EQ(static_cast<int*>(0), Ptr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr
+ // CHECK-FIXES: IS_EQ(static_cast<int*>(nullptr), Ptr);
+
+ IS_EQ(0, Ptr); // literal
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+ // CHECK-FIXES: IS_EQ(nullptr, Ptr);
+
+ IS_EQ(NULL, Ptr); // macro
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+ // CHECK-FIXES: IS_EQ(nullptr, Ptr);
+
+ // These are ok since the null literal is not spelled within a macro.
+#define myassert(x) if (!(x)) return;
+ myassert(0 == Ptr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
+ // CHECK-FIXES: myassert(nullptr == Ptr);
+
+ myassert(NULL == Ptr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
+ // CHECK-FIXES: myassert(nullptr == Ptr);
+
+ // These are bad as the null literal is buried in a macro.
+#define BLAH(X) myassert(0 == (X));
+#define BLAH2(X) myassert(NULL == (X));
+ BLAH(Ptr);
+ BLAH2(Ptr);
+
+ // Same as above but testing extra macro expansion.
+#define EXPECT_NULL(X) IS_EQ(0, X);
+#define EXPECT_NULL2(X) IS_EQ(NULL, X);
+ EXPECT_NULL(Ptr);
+ EXPECT_NULL2(Ptr);
+
+ // Almost the same as above but now null literal is not in a macro so ok
+ // to transform.
+#define EQUALS_PTR(X) IS_EQ(X, Ptr);
+ EQUALS_PTR(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
+ // CHECK-FIXES: EQUALS_PTR(nullptr);
+ EQUALS_PTR(NULL);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
+ // CHECK-FIXES: EQUALS_PTR(nullptr);
+
+ // Same as above but testing extra macro expansion.
+#define EQUALS_PTR_I(X) EQUALS_PTR(X)
+ EQUALS_PTR_I(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+ // CHECK-FIXES: EQUALS_PTR_I(nullptr);
+ EQUALS_PTR_I(NULL);
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+ // CHECK-FIXES: EQUALS_PTR_I(nullptr);
+
+ // Ok since null literal not within macro. However, now testing macro
+ // used as arg to another macro.
+#define decorate(EXPR) side_effect(); EXPR;
+ decorate(IS_EQ(NULL, Ptr));
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
+ // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr));
+ decorate(IS_EQ(0, Ptr));
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
+ // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr));
+
+ // This macro causes a NullToPointer cast to happen where 0 is assigned to z
+ // but the 0 literal cannot be replaced because it is also used as an
+ // integer in the comparison.
+#define INT_AND_PTR_USE(X) do { int *z = X; if (X == 4) break; } while(false)
+ INT_AND_PTR_USE(0);
+
+ // Both uses of X in this case result in NullToPointer casts so replacement
+ // is possible.
+#define PTR_AND_PTR_USE(X) do { int *z = X; if (X != z) break; } while(false)
+ PTR_AND_PTR_USE(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
+ // CHECK-FIXES: PTR_AND_PTR_USE(nullptr);
+ PTR_AND_PTR_USE(NULL);
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
+ // CHECK-FIXES: PTR_AND_PTR_USE(nullptr);
+
+#define OPTIONAL_CODE(...) __VA_ARGS__
+#define NOT_NULL dummy(0)
+#define CALL(X) X
+ OPTIONAL_CODE(NOT_NULL);
+ CALL(NOT_NULL);
+
+#define ENTRY(X) {X}
+ struct A {
+ int *Ptr;
+ } a[2] = {ENTRY(0), {0}};
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
+ // CHECK-MESSAGES: :[[@LINE-2]]:24: warning: use nullptr
+ // CHECK-FIXES: a[2] = {ENTRY(nullptr), {nullptr}};
+#undef ENTRY
+
+#define assert1(expr) (expr) ? 0 : 1
+#define assert2 assert1
+ int *p;
+ assert2(p == 0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+ // CHECK-FIXES: assert2(p == nullptr);
+ assert2(p == NULL);
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+ // CHECK-FIXES: assert2(p == nullptr);
+#undef assert2
+#undef assert1
+
+#define ASSERT_EQ(a, b) a == b
+#define ASSERT_NULL(x) ASSERT_EQ(static_cast<void *>(NULL), x)
+ int *pp;
+ ASSERT_NULL(pp);
+ ASSERT_NULL(NULL);
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use nullptr
+ // CHECK-FIXES: ASSERT_NULL(nullptr);
+#undef ASSERT_NULL
+#undef ASSERT_EQ
+}
+
+// One of the ancestor of the cast is a NestedNameSpecifierLoc.
+class NoDef;
+char function(NoDef *p);
+#define F(x) (sizeof(function(x)) == 1)
+template<class T, T t>
+class C {};
+C<bool, F(0)> c;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use nullptr
+// CHECK-FIXES: C<bool, F(nullptr)> c;
+#undef F
+
+// Test default argument expression.
+struct D {
+ explicit D(void *t, int *c = NULL) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use nullptr
+ // CHECK-FIXES: explicit D(void *t, int *c = nullptr) {}
+};
+
+void test_default_argument() {
+ D(nullptr);
+}
+
+// Test on two neighbour CXXDefaultArgExprs nodes.
+typedef unsigned long long uint64;
+struct ZZ {
+ explicit ZZ(uint64, const uint64* = NULL) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: use nullptr
+// CHECK-FIXES: explicit ZZ(uint64, const uint64* = nullptr) {}
+ operator bool() { return true; }
+};
+
+uint64 Hash(uint64 seed = 0) { return 0; }
+
+void f() {
+ bool a;
+ a = ZZ(Hash());
+}
+
+// Test on ignoring substituted template types.
+template<typename T>
+class TemplateClass {
+ public:
+ explicit TemplateClass(int a, T default_value = 0) {}
+
+ void h(T *default_value = 0) {}
+
+ void f(int* p = 0) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
+// CHECK-FIXES: void f(int* p = nullptr) {}
+};
+
+void IgnoreSubstTemplateType() {
+ TemplateClass<int*> a(1);
+}
+
+// Test on casting nullptr.
+struct G {
+ explicit G(bool, const char * = NULL) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use nullptr
+ // CHECK-FIXES: explicit G(bool, const char * = nullptr) {}
+};
+bool g(const char*);
+void test_cast_nullptr() {
+ G(g(nullptr));
+ G(g((nullptr)));
+ G(g(static_cast<char*>(nullptr)));
+ G(g(static_cast<const char*>(nullptr)));
+}
+
+// Test on recognizing multiple NULLs.
+class H {
+public:
+ H(bool);
+};
+
+#define T(expression) H(expression);
+bool h(int *, int *, int * = nullptr);
+void test_multiple_nulls() {
+ T(h(NULL, NULL));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr
+// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use nullptr
+// CHECK-FIXES: T(h(nullptr, nullptr));
+ T(h(NULL, nullptr));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr
+// CHECK-FIXES: T(h(nullptr, nullptr));
+ T(h(nullptr, NULL));
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+// CHECK-FIXES: T(h(nullptr, nullptr));
+ T(h(nullptr, nullptr));
+ T(h(NULL, NULL, NULL));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr
+// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use nullptr
+// CHECK-MESSAGES: :[[@LINE-3]]:19: warning: use nullptr
+// CHECK-FIXES: T(h(nullptr, nullptr, nullptr));
+}
+#undef T
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-override-cxx98.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-override-cxx98.cpp
new file mode 100644
index 0000000..bc162d6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-override-cxx98.cpp
@@ -0,0 +1,19 @@
+// RUN: %check_clang_tidy %s modernize-use-override %t -- -- -std=c++98
+
+struct Base {
+ virtual ~Base() {}
+ virtual void a();
+ virtual void b();
+};
+
+struct SimpleCases : public Base {
+public:
+ virtual ~SimpleCases();
+ // CHECK-FIXES: {{^}} virtual ~SimpleCases();
+
+ void a();
+ // CHECK-FIXES: {{^}} void a();
+
+ virtual void b();
+ // CHECK-FIXES: {{^}} virtual void b();
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-override-ms.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-override-ms.cpp
new file mode 100644
index 0000000..0cee917
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-override-ms.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s modernize-use-override %t -- -- -fms-extensions -std=c++11
+
+// This test is designed to test ms-extension __declspec(dllexport) attributes.
+#define EXPORT __declspec(dllexport)
+
+class Base {
+ virtual EXPORT void a();
+};
+
+class EXPORT InheritedBase {
+ virtual void a();
+};
+
+class Derived : public Base {
+ virtual EXPORT void a();
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: prefer using 'override' or (rarely) 'final' instead of 'virtual' [modernize-use-override]
+ // CHECK-FIXES: {{^}} EXPORT void a() override;
+};
+
+class EXPORT InheritedDerived : public InheritedBase {
+ virtual void a();
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using 'override' or (rarely) 'final' instead of 'virtual' [modernize-use-override]
+ // CHECK-FIXES: {{^}} void a() override;
+};
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-override.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-override.cpp
new file mode 100644
index 0000000..24aafe5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-override.cpp
@@ -0,0 +1,318 @@
+// RUN: %check_clang_tidy %s modernize-use-override %t -- -- -std=c++11 -fexceptions
+
+#define ABSTRACT = 0
+
+#define OVERRIDE override
+#define VIRTUAL virtual
+#define NOT_VIRTUAL
+#define NOT_OVERRIDE
+
+#define MUST_USE_RESULT __attribute__((warn_unused_result))
+#define UNUSED __attribute__((unused))
+
+struct MUST_USE_RESULT MustUseResultObject {};
+
+struct IntPair {
+ int First, Second;
+};
+
+struct Base {
+ virtual ~Base() {}
+ virtual void a();
+ virtual void b();
+ virtual void c();
+ virtual void d();
+ virtual void d2();
+ virtual void e() = 0;
+ virtual void f() = 0;
+ virtual void f2() const = 0;
+ virtual void g() = 0;
+
+ virtual void j() const;
+ virtual MustUseResultObject k();
+ virtual bool l() MUST_USE_RESULT UNUSED;
+ virtual bool n() MUST_USE_RESULT UNUSED;
+
+ virtual void m();
+ virtual void m2();
+ virtual void o() __attribute__((unused));
+
+ virtual void r() &;
+ virtual void rr() &&;
+
+ virtual void cv() const volatile;
+ virtual void cv2() const volatile;
+
+ virtual void ne() noexcept(false);
+ virtual void t() throw();
+
+ virtual void il(IntPair);
+};
+
+struct SimpleCases : public Base {
+public:
+ virtual ~SimpleCases();
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: prefer using 'override' or (rarely) 'final' instead of 'virtual' [modernize-use-override]
+ // CHECK-FIXES: {{^}} ~SimpleCases() override;
+
+ void a();
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: annotate this
+ // CHECK-FIXES: {{^}} void a() override;
+
+ void b() override;
+ // CHECK-MESSAGES-NOT: warning:
+ // CHECK-FIXES: {{^}} void b() override;
+
+ virtual void c();
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void c() override;
+
+ virtual void d() override;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant since the function is already declared 'override'
+ // CHECK-FIXES: {{^}} void d() override;
+
+ virtual void d2() final;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant since the function is already declared 'final'
+ // CHECK-FIXES: {{^}} void d2() final;
+
+ virtual void e() = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void e() override = 0;
+
+ virtual void f()=0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void f() override =0;
+
+ virtual void f2() const=0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void f2() const override =0;
+
+ virtual void g() ABSTRACT;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void g() override ABSTRACT;
+
+ virtual void j() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void j() const override;
+
+ virtual MustUseResultObject k(); // Has an implicit attribute.
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: prefer using
+ // CHECK-FIXES: {{^}} MustUseResultObject k() override;
+
+ virtual bool l() MUST_USE_RESULT UNUSED;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} bool l() override MUST_USE_RESULT UNUSED;
+
+ virtual bool n() UNUSED MUST_USE_RESULT;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} bool n() override UNUSED MUST_USE_RESULT;
+
+ void m() override final;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'override' is redundant since the function is already declared 'final'
+ // CHECK-FIXES: {{^}} void m() final;
+
+ virtual void m2() override final;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' and 'override' are redundant since the function is already declared 'final'
+ // CHECK-FIXES: {{^}} void m2() final;
+
+ virtual void o() __attribute__((unused));
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void o() override __attribute__((unused));
+
+ virtual void ne() noexcept(false);
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void ne() noexcept(false) override;
+
+ virtual void t() throw();
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void t() throw() override;
+};
+
+// CHECK-MESSAGES-NOT: warning:
+
+void SimpleCases::c() {}
+// CHECK-FIXES: {{^}}void SimpleCases::c() {}
+
+SimpleCases::~SimpleCases() {}
+// CHECK-FIXES: {{^}}SimpleCases::~SimpleCases() {}
+
+struct DefaultedDestructor : public Base {
+ DefaultedDestructor() {}
+ virtual ~DefaultedDestructor() = default;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: prefer using
+ // CHECK-FIXES: {{^}} ~DefaultedDestructor() override = default;
+};
+
+struct FinalSpecified : public Base {
+public:
+ virtual ~FinalSpecified() final;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: 'virtual' is redundant since the function is already declared 'final'
+ // CHECK-FIXES: {{^}} ~FinalSpecified() final;
+
+ void b() final;
+ // CHECK-MESSAGES-NOT: warning:
+ // CHECK-FIXES: {{^}} void b() final;
+
+ virtual void d() final;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant
+ // CHECK-FIXES: {{^}} void d() final;
+
+ virtual void e() final = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant
+ // CHECK-FIXES: {{^}} void e() final = 0;
+
+ virtual void j() const final;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant
+ // CHECK-FIXES: {{^}} void j() const final;
+
+ virtual bool l() final MUST_USE_RESULT UNUSED;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant
+ // CHECK-FIXES: {{^}} bool l() final MUST_USE_RESULT UNUSED;
+};
+
+struct InlineDefinitions : public Base {
+public:
+ virtual ~InlineDefinitions() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: prefer using
+ // CHECK-FIXES: {{^}} ~InlineDefinitions() override {}
+
+ void a() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: annotate this
+ // CHECK-FIXES: {{^}} void a() override {}
+
+ void b() override {}
+ // CHECK-MESSAGES-NOT: warning:
+ // CHECK-FIXES: {{^}} void b() override {}
+
+ virtual void c()
+ {}
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void c() override
+
+ virtual void d() override {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant
+ // CHECK-FIXES: {{^}} void d() override {}
+
+ virtual void j() const
+ {}
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void j() const override
+
+ virtual MustUseResultObject k() {} // Has an implicit attribute.
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: prefer using
+ // CHECK-FIXES: {{^}} MustUseResultObject k() override {}
+
+ virtual bool l() MUST_USE_RESULT UNUSED {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} bool l() override MUST_USE_RESULT UNUSED {}
+
+ virtual void r() &
+ {}
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void r() & override
+
+ virtual void rr() &&
+ {}
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void rr() && override
+
+ virtual void cv() const volatile
+ {}
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void cv() const volatile override
+
+ virtual void cv2() const volatile // some comment
+ {}
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void cv2() const volatile override // some comment
+};
+
+struct DefaultArguments : public Base {
+ // Tests for default arguments (with initializer lists).
+ // Make sure the override fix is placed after the argument list.
+ void il(IntPair p = {1, (2 + (3))}) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: annotate this
+ // CHECK-FIXES: {{^}} void il(IntPair p = {1, (2 + (3))}) override {}
+};
+
+struct Macros : public Base {
+ // Tests for 'virtual' and 'override' being defined through macros. Basically
+ // give up for now.
+ NOT_VIRTUAL void a() NOT_OVERRIDE;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: annotate this
+ // CHECK-FIXES: {{^}} NOT_VIRTUAL void a() override NOT_OVERRIDE;
+
+ VIRTUAL void b() NOT_OVERRIDE;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} VIRTUAL void b() override NOT_OVERRIDE;
+
+ NOT_VIRTUAL void c() OVERRIDE;
+ // CHECK-MESSAGES-NOT: warning:
+ // CHECK-FIXES: {{^}} NOT_VIRTUAL void c() OVERRIDE;
+
+ VIRTUAL void d() OVERRIDE;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant
+ // CHECK-FIXES: {{^}} VIRTUAL void d() OVERRIDE;
+
+#define FUNC(return_type, name) return_type name()
+ FUNC(void, e);
+ // CHECK-FIXES: {{^}} FUNC(void, e);
+
+#define F virtual void f();
+ F
+ // CHECK-FIXES: {{^}} F
+
+ VIRTUAL void g() OVERRIDE final;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' and 'override' are redundant
+ // CHECK-FIXES: {{^}} VIRTUAL void g() final;
+};
+
+// Tests for templates.
+template <typename T> struct TemplateBase {
+ virtual void f(T t);
+};
+
+template <typename T> struct DerivedFromTemplate : public TemplateBase<T> {
+ virtual void f(T t);
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void f(T t) override;
+};
+void f() { DerivedFromTemplate<int>().f(2); }
+
+template <class C>
+struct UnusedMemberInstantiation : public C {
+ virtual ~UnusedMemberInstantiation() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: prefer using
+ // CHECK-FIXES: {{^}} ~UnusedMemberInstantiation() override {}
+};
+struct IntantiateWithoutUse : public UnusedMemberInstantiation<Base> {};
+
+struct Base2 {
+ virtual ~Base2() {}
+ virtual void a();
+};
+
+// The OverrideAttr isn't propagated to specializations in all cases. Make sure
+// we don't add "override" a second time.
+template <int I>
+struct MembersOfSpecializations : public Base2 {
+ void a() override;
+ // CHECK-MESSAGES-NOT: warning:
+ // CHECK-FIXES: {{^}} void a() override;
+};
+template <> void MembersOfSpecializations<3>::a() {}
+void ff() { MembersOfSpecializations<3>().a(); };
+
+// In case try statement is used as a method body,
+// make sure that override fix is placed before try keyword.
+struct TryStmtAsBody : public Base {
+ void a() try
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: annotate this
+ // CHECK-FIXES: {{^}} void a() override try
+ { b(); } catch(...) { c(); }
+
+ virtual void d() try
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void d() override try
+ { e(); } catch(...) { f(); }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-transparent-functors.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-transparent-functors.cpp
new file mode 100644
index 0000000..b700f54
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-transparent-functors.cpp
@@ -0,0 +1,107 @@
+// RUN: %check_clang_tidy %s modernize-use-transparent-functors %t -- -- -std=c++14
+
+namespace std {
+template<class T>
+struct remove_reference;
+
+template <class T>
+constexpr T &&forward(typename std::remove_reference<T>::type &t);
+
+template <class T>
+constexpr T &&forward(typename std::remove_reference<T>::type &&t);
+
+template <typename T = void>
+struct plus {
+ constexpr T operator()(const T &Lhs, const T &Rhs) const;
+};
+
+template <>
+struct plus<void> {
+ template <typename T, typename U>
+ constexpr auto operator()(T &&Lhs, U &&Rhs) const ->
+ decltype(forward<T>(Lhs) + forward<U>(Rhs));
+};
+
+template <typename T = void>
+struct less {
+ constexpr bool operator()(const T &Lhs, const T &Rhs) const;
+};
+
+template <>
+struct less<void> {
+ template <typename T, typename U>
+ constexpr bool operator()(T &&Lhs, U &&Rhs) const;
+};
+
+template <typename T = void>
+struct logical_not {
+ constexpr bool operator()(const T &Arg) const;
+};
+
+template <>
+struct logical_not<void> {
+ template <typename T>
+ constexpr bool operator()(T &&Arg) const;
+};
+
+template <typename T>
+class allocator;
+
+template <
+ class Key,
+ class Compare = std::less<>,
+ class Allocator = std::allocator<Key>>
+class set {};
+
+template <
+ class Key,
+ class Compare = std::less<Key>,
+ class Allocator = std::allocator<Key>>
+class set2 {};
+
+template <class InputIt, class UnaryPredicate>
+InputIt find_if(InputIt first, InputIt last,
+ UnaryPredicate p);
+
+template <class RandomIt, class Compare>
+void sort(RandomIt first, RandomIt last, Compare comp);
+
+class iterator {};
+class string {};
+}
+
+int main() {
+ using std::set;
+ using std::less;
+ std::set<int, std::less<int>> s;
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: prefer transparent functors 'less<>' [modernize-use-transparent-functors]
+ // CHECK-FIXES: {{^}} std::set<int, std::less<>> s;{{$}}
+ set<int, std::less<int>> s2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: prefer transparent functors
+ // CHECK-FIXES: {{^}} set<int, std::less<>> s2;{{$}}
+ set<int, less<int>> s3;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: prefer transparent functors
+ // CHECK-FIXES: {{^}} set<int, less<>> s3;{{$}}
+ std::set<int, std::less<>> s4;
+ std::set<char *, std::less<std::string>> s5;
+ std::set<set<int, less<int>>, std::less<>> s6;
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: prefer transparent functors
+ // CHECK-FIXES: {{^}} std::set<set<int, less<>>, std::less<>> s6;{{$}}
+ std::iterator begin, end;
+ sort(begin, end, std::less<int>());
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: prefer transparent functors
+ std::sort(begin, end, std::less<>());
+ find_if(begin, end, std::logical_not<bool>());
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: prefer transparent functors
+ std::find_if(begin, end, std::logical_not<>());
+ using my_set = std::set<int, std::less<int>>;
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: prefer transparent functors
+ // CHECK-FIXES: {{^}} using my_set = std::set<int, std::less<>>;{{$}}
+ using my_set2 = std::set<char*, std::less<std::string>>;
+ using my_less = std::less<std::string>;
+ find_if(begin, end, my_less());
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: prefer transparent functors
+ std::set2<int> control;
+}
+
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-uncaught-exceptions.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-uncaught-exceptions.cpp
new file mode 100644
index 0000000..e6bae2b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-uncaught-exceptions.cpp
@@ -0,0 +1,79 @@
+// RUN: %check_clang_tidy %s modernize-use-uncaught-exceptions %t -- -- -std=c++1z
+#define MACRO std::uncaught_exception
+// CHECK-FIXES: #define MACRO std::uncaught_exception
+
+bool uncaught_exception() {
+ return 0;
+}
+
+namespace std {
+ bool uncaught_exception() {
+ return false;
+ }
+
+ int uncaught_exceptions() {
+ return 0;
+ }
+}
+
+template <typename T>
+bool doSomething(T t) {
+ return t();
+ // CHECK-FIXES: return t();
+}
+
+template <bool (*T)()>
+bool doSomething2() {
+ return T();
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+ // CHECK-FIXES: return T();
+}
+
+void no_warn() {
+
+ uncaught_exception();
+ // CHECK-FIXES: uncaught_exception();
+
+ doSomething(uncaught_exception);
+ // CHECK-FIXES: doSomething(uncaught_exception);
+}
+
+void warn() {
+
+ std::uncaught_exception();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+ // CHECK-FIXES: std::uncaught_exceptions();
+
+ using std::uncaught_exception;
+ // CHECK-MESSAGES: [[@LINE-1]]:14: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+ // CHECK-FIXES: using std::uncaught_exceptions;
+
+ uncaught_exception();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+ // CHECK-FIXES: uncaught_exceptions();
+
+ bool b{uncaught_exception()};
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+ // CHECK-FIXES: bool b{std::uncaught_exceptions() > 0};
+
+ MACRO();
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+ // CHECK-FIXES: MACRO();
+
+ doSomething(std::uncaught_exception);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+ // CHECK-FIXES: doSomething(std::uncaught_exception);
+
+ doSomething(uncaught_exception);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+ // CHECK-FIXES: doSomething(uncaught_exception);
+
+ bool (*foo)();
+ foo = &uncaught_exception;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+ // CHECK-FIXES: foo = &uncaught_exception;
+
+ doSomething2<uncaught_exception>();
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+ // CHECK-FIXES: doSomething2<uncaught_exception>();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-using-macros.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-using-macros.cpp
new file mode 100644
index 0000000..5d88d1d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-using-macros.cpp
@@ -0,0 +1,23 @@
+// RUN: %check_clang_tidy %s modernize-use-using %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-using.IgnoreMacros, value: 0}]}" \
+// RUN: -- -std=c++11
+
+#define CODE typedef int INT
+
+CODE;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: #define CODE typedef int INT
+// CHECK-FIXES: CODE;
+
+struct Foo;
+#define Bar Baz
+typedef Foo Bar;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: #define Bar Baz
+// CHECK-FIXES: using Baz = Foo;
+
+#define TYPEDEF typedef
+TYPEDEF Foo Bak;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: #define TYPEDEF typedef
+// CHECK-FIXES: TYPEDEF Foo Bak;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-using.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-using.cpp
new file mode 100644
index 0000000..e8f4958
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-using.cpp
@@ -0,0 +1,164 @@
+// RUN: %check_clang_tidy %s modernize-use-using %t
+
+typedef int Type;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef' [modernize-use-using]
+// CHECK-FIXES: using Type = int;
+
+typedef long LL;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using LL = long;
+
+typedef int Bla;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Bla = int;
+
+typedef Bla Bla2;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Bla2 = Bla;
+
+typedef void (*type)(int, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using type = void (*)(int, int);
+
+typedef void (*type2)();
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using type2 = void (*)();
+
+class Class {
+ typedef long long Type;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef'
+ // CHECK-FIXES: using Type = long long;
+};
+
+typedef void (Class::*MyPtrType)(Bla) const;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using MyPtrType = void (Class::*)(Bla)[[ATTR:( __attribute__\(\(thiscall\)\))?]] const;
+
+class Iterable {
+public:
+ class Iterator {};
+};
+
+template <typename T>
+class Test {
+ typedef typename T::iterator Iter;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef'
+ // CHECK-FIXES: using Iter = typename T::iterator;
+};
+
+using balba = long long;
+
+union A {};
+
+typedef void (A::*PtrType)(int, int) const;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using PtrType = void (A::*)(int, int)[[ATTR]] const;
+
+typedef Class some_class;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using some_class = Class;
+
+typedef Class Cclass;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Cclass = Class;
+
+typedef Cclass cclass2;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using cclass2 = Cclass;
+
+class cclass {};
+
+typedef void (cclass::*MyPtrType3)(Bla);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using MyPtrType3 = void (cclass::*)(Bla)[[ATTR]];
+
+using my_class = int;
+
+typedef Test<my_class *> another;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using another = Test<my_class *>;
+
+typedef int* PInt;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using PInt = int *;
+
+typedef int bla1, bla2, bla3;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: typedef int bla1, bla2, bla3;
+
+#define CODE typedef int INT
+
+CODE;
+// CHECK-FIXES: #define CODE typedef int INT
+// CHECK-FIXES: CODE;
+
+struct Foo;
+#define Bar Baz
+typedef Foo Bar;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: #define Bar Baz
+// CHECK-FIXES: using Baz = Foo;
+
+#define TYPEDEF typedef
+TYPEDEF Foo Bak;
+// CHECK-FIXES: #define TYPEDEF typedef
+// CHECK-FIXES: TYPEDEF Foo Bak;
+
+#define FOO Foo
+typedef FOO Bam;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: #define FOO Foo
+// CHECK-FIXES: using Bam = Foo;
+
+typedef struct Foo Bap;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Bap = struct Foo;
+
+struct Foo typedef Bap2;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Bap2 = struct Foo;
+
+Foo typedef Bap3;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Bap3 = Foo;
+
+typedef struct Unknown Baq;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Baq = struct Unknown;
+
+struct Unknown2 typedef Baw;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Baw = struct Unknown2;
+
+int typedef Bax;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Bax = int;
+
+typedef struct Q1 { int a; } S1;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: typedef struct Q1 { int a; } S1;
+typedef struct { int b; } S2;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: typedef struct { int b; } S2;
+struct Q2 { int c; } typedef S3;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: struct Q2 { int c; } typedef S3;
+struct { int d; } typedef S4;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: struct { int d; } typedef S4;
+
+namespace my_space {
+ class my_cclass {};
+ typedef my_cclass FuncType;
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using FuncType = my_cclass;
+}
+
+#define lol 4
+typedef unsigned Map[lol];
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: typedef unsigned Map[lol];
+
+typedef void (*fun_type)();
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using fun_type = void (*)();
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/mpi-buffer-deref.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/mpi-buffer-deref.cpp
new file mode 100644
index 0000000..67304d2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/mpi-buffer-deref.cpp
@@ -0,0 +1,50 @@
+// RUN: %check_clang_tidy %s mpi-buffer-deref %t -- -- -I %S/Inputs/mpi-type-mismatch
+
+#include "mpimock.h"
+
+void negativeTests() {
+ char *buf;
+ MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer is insufficiently dereferenced: pointer->pointer [mpi-buffer-deref]
+
+ unsigned **buf2;
+ MPI_Send(buf2, 1, MPI_UNSIGNED, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer is insufficiently dereferenced: pointer->pointer
+
+ short buf3[1][1];
+ MPI_Send(buf3, 1, MPI_SHORT, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer is insufficiently dereferenced: array->array
+
+ long double _Complex *buf4[1];
+ MPI_Send(buf4, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer is insufficiently dereferenced: pointer->array
+
+ std::complex<float> *buf5[1][1];
+ MPI_Send(&buf5, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer is insufficiently dereferenced: pointer->array->array->pointer
+}
+
+void positiveTests() {
+ char buf;
+ MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+
+ unsigned *buf2;
+ MPI_Send(buf2, 1, MPI_UNSIGNED, 0, 0, MPI_COMM_WORLD);
+
+ short buf3[1][1];
+ MPI_Send(buf3[0], 1, MPI_SHORT, 0, 0, MPI_COMM_WORLD);
+
+ long double _Complex *buf4[1];
+ MPI_Send(*buf4, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+ long double _Complex buf5[1];
+ MPI_Send(buf5, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+ std::complex<float> *buf6[1][1];
+ MPI_Send(*buf6[0], 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+ // Referencing an array with '&' is valid, as this also points to the
+ // beginning of the array.
+ long double _Complex buf7[1];
+ MPI_Send(&buf7, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/mpi-type-mismatch.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/mpi-type-mismatch.cpp
new file mode 100644
index 0000000..5e230b8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/mpi-type-mismatch.cpp
@@ -0,0 +1,255 @@
+// RUN: %check_clang_tidy %s mpi-type-mismatch %t -- -- -I %S/Inputs/mpi-type-mismatch
+
+#include "mpimock.h"
+
+void charNegativeTest() {
+ int buf;
+ MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'int' does not match the MPI datatype 'MPI_CHAR'
+
+ short buf2;
+ MPI_Send(&buf2, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'short' does not match the MPI datatype 'MPI_CHAR'
+
+ long buf3;
+ MPI_Send(&buf3, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'long' does not match the MPI datatype 'MPI_CHAR'
+
+ int8_t buf4;
+ MPI_Send(&buf4, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'int8_t' does not match the MPI datatype 'MPI_CHAR'
+
+ uint16_t buf5;
+ MPI_Send(&buf5, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint16_t' does not match the MPI datatype 'MPI_CHAR'
+
+ long double _Complex buf6;
+ MPI_Send(&buf6, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'long double _Complex' does not match the MPI datatype 'MPI_CHAR'
+
+ std::complex<float> buf7;
+ MPI_Send(&buf7, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'complex<float>' does not match the MPI datatype 'MPI_CHAR'
+}
+
+void intNegativeTest() {
+ unsigned char buf;
+ MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned char' does not match the MPI datatype 'MPI_INT'
+
+ unsigned buf2;
+ MPI_Send(&buf2, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned int' does not match the MPI datatype 'MPI_INT'
+
+ short buf3;
+ MPI_Send(&buf3, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'short' does not match the MPI datatype 'MPI_INT'
+
+ long buf4;
+ MPI_Send(&buf4, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'long' does not match the MPI datatype 'MPI_INT'
+
+ int8_t buf5;
+ MPI_Send(&buf5, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'int8_t' does not match the MPI datatype 'MPI_INT'
+
+ uint16_t buf6;
+ MPI_Send(&buf6, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint16_t' does not match the MPI datatype 'MPI_INT'
+
+ long double _Complex buf7;
+ MPI_Send(&buf7, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'long double _Complex' does not match the MPI datatype 'MPI_INT'
+
+ std::complex<float> buf8;
+ MPI_Send(&buf8, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'complex<float>' does not match the MPI datatype 'MPI_INT'
+}
+
+void longNegativeTest() {
+ char buf;
+ MPI_Send(&buf, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'char' does not match the MPI datatype 'MPI_LONG'
+
+ unsigned buf2;
+ MPI_Send(&buf2, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned int' does not match the MPI datatype 'MPI_LONG'
+
+ unsigned short buf3;
+ MPI_Send(&buf3, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned short' does not match the MPI datatype 'MPI_LONG'
+
+ unsigned long buf4;
+ MPI_Send(&buf4, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned long' does not match the MPI datatype 'MPI_LONG'
+
+ int8_t buf5;
+ MPI_Send(&buf5, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'int8_t' does not match the MPI datatype 'MPI_LONG'
+
+ uint16_t buf6;
+ MPI_Send(&buf6, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint16_t' does not match the MPI datatype 'MPI_LONG'
+
+ long double _Complex buf7;
+ MPI_Send(&buf7, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'long double _Complex' does not match the MPI datatype 'MPI_LONG'
+
+ std::complex<float> buf8;
+ MPI_Send(&buf8, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'complex<float>' does not match the MPI datatype 'MPI_LONG'
+}
+
+void int8_tNegativeTest() {
+ char buf;
+ MPI_Send(&buf, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'char' does not match the MPI datatype 'MPI_INT8_T'
+
+ unsigned buf2;
+ MPI_Send(&buf2, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned int' does not match the MPI datatype 'MPI_INT8_T'
+
+ short buf3;
+ MPI_Send(&buf3, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'short' does not match the MPI datatype 'MPI_INT8_T'
+
+ unsigned long buf4;
+ MPI_Send(&buf4, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned long' does not match the MPI datatype 'MPI_INT8_T'
+
+ uint8_t buf5;
+ MPI_Send(&buf5, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint8_t' does not match the MPI datatype 'MPI_INT8_T'
+
+ uint16_t buf6;
+ MPI_Send(&buf6, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint16_t' does not match the MPI datatype 'MPI_INT8_T'
+
+ long double _Complex buf7;
+ MPI_Send(&buf7, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'long double _Complex' does not match the MPI datatype 'MPI_INT8_T'
+
+ std::complex<float> buf8;
+ MPI_Send(&buf8, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'complex<float>' does not match the MPI datatype 'MPI_INT8_T'
+}
+
+void complex_c_long_double_complexNegativeTest() {
+ char buf;
+ MPI_Send(&buf, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'char' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+ unsigned buf2;
+ MPI_Send(&buf2, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned int' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+ short buf3;
+ MPI_Send(&buf3, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'short' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+ unsigned long buf4;
+ MPI_Send(&buf4, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned long' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+ uint8_t buf5;
+ MPI_Send(&buf5, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint8_t' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+ uint16_t buf6;
+ MPI_Send(&buf6, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint16_t' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+ double _Complex buf7;
+ MPI_Send(&buf7, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'double _Complex' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+ std::complex<float> buf8;
+ MPI_Send(&buf8, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'complex<float>' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+}
+
+void complex_cxx_float_complexNegativeTest() {
+ char buf;
+ MPI_Send(&buf, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'char' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+ unsigned buf2;
+ MPI_Send(&buf2, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned int' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+ short buf3;
+ MPI_Send(&buf3, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'short' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+ unsigned long buf4;
+ MPI_Send(&buf4, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned long' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+ uint8_t buf5;
+ MPI_Send(&buf5, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint8_t' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+ uint16_t buf6;
+ MPI_Send(&buf6, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint16_t' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+ double _Complex buf7;
+ MPI_Send(&buf7, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'double _Complex' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+ std::complex<double> buf8;
+ MPI_Send(&buf8, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'complex<double>' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+}
+
+void skippedTypesTests() {
+ // typedefs, user defined MPI and nullptr types are skipped
+ typedef char CHAR;
+ CHAR buf;
+ MPI_Send(&buf, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+ typedef unsigned UNSIGNED;
+ UNSIGNED buf2;
+ MPI_Send(&buf2, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+#define _MPI_LONG MPI_LONG
+ int buf3;
+ MPI_Send(&buf3, 1, _MPI_LONG, 0, 0, MPI_COMM_WORLD);
+
+#define _MPI_CXX_FLOAT_COMPLEX MPI_CXX_FLOAT_COMPLEX
+ short buf4;
+ MPI_Send(&buf4, 1, _MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+ MPI_Send(NULL, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+}
+
+void positiveTests() {
+ char buf;
+ MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+
+ int buf2;
+ MPI_Send(&buf2, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+
+ long buf3;
+ MPI_Send(&buf3, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+
+ int8_t buf4;
+ MPI_Send(&buf4, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+
+ long double _Complex buf5;
+ MPI_Send(&buf5, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+ std::complex<float> buf6;
+ MPI_Send(&buf6, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+ uint8_t buf7;
+ MPI_Send(&buf7, 1, MPI_UINT8_T, 0, 0, MPI_COMM_WORLD);
+
+ uint16_t buf8;
+ MPI_Send(&buf8, 1, MPI_UINT16_T, 0, 0, MPI_COMM_WORLD);
+
+ // On some systems like PPC or ARM, 'char' is unsigned by default which is why
+ // distinct signedness for the buffer and MPI type is tolerated.
+ unsigned char buf9;
+ MPI_Send(&buf9, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/nolint.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/nolint.cpp
new file mode 100644
index 0000000..893e819
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/nolint.cpp
@@ -0,0 +1,49 @@
+// RUN: %check_clang_tidy %s google-explicit-constructor,clang-diagnostic-unused-variable,clang-analyzer-core.UndefinedBinaryOperatorResult %t -- -extra-arg=-Wunused-variable -- -I%S/Inputs/nolint
+
+#include "trigger_warning.h"
+void I(int& Out) {
+ int In;
+ A1(In, Out);
+}
+// CHECK-MESSAGES-NOT: trigger_warning.h:{{.*}} warning
+// CHECK-MESSAGES-NOT: :[[@LINE-4]]:{{.*}} note
+
+class A { A(int i); };
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: single-argument constructors must be marked explicit
+
+class B { B(int i); }; // NOLINT
+
+class C { C(int i); }; // NOLINT(for-some-other-check)
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: single-argument constructors must be marked explicit
+
+class C1 { C1(int i); }; // NOLINT(*)
+
+class C2 { C2(int i); }; // NOLINT(not-closed-bracket-is-treated-as-skip-all
+
+class C3 { C3(int i); }; // NOLINT(google-explicit-constructor)
+
+class C4 { C4(int i); }; // NOLINT(some-check, google-explicit-constructor)
+
+class C5 { C5(int i); }; // NOLINT without-brackets-skip-all, another-check
+
+void f() {
+ int i;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: unused variable 'i' [clang-diagnostic-unused-variable]
+ int j; // NOLINT
+}
+
+#define MACRO(X) class X { X(int i); };
+MACRO(D)
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: single-argument constructors must be marked explicit
+MACRO(E) // NOLINT
+
+#define MACRO_NOARG class F { F(int i); };
+MACRO_NOARG // NOLINT
+
+#define MACRO_NOLINT class G { G(int i); }; // NOLINT
+MACRO_NOLINT
+
+#define DOUBLE_MACRO MACRO(H) // NOLINT
+DOUBLE_MACRO
+
+// CHECK-MESSAGES: Suppressed 12 warnings (12 NOLINT)
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/nolintnextline.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/nolintnextline.cpp
new file mode 100644
index 0000000..a97928a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/nolintnextline.cpp
@@ -0,0 +1,49 @@
+class A { A(int i); };
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: single-argument constructors must be marked explicit
+
+// NOLINTNEXTLINE
+class B { B(int i); };
+
+// NOLINTNEXTLINE(for-some-other-check)
+class C { C(int i); };
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: single-argument constructors must be marked explicit
+
+// NOLINTNEXTLINE(*)
+class C1 { C1(int i); };
+
+// NOLINTNEXTLINE(not-closed-bracket-is-treated-as-skip-all
+class C2 { C2(int i); };
+
+// NOLINTNEXTLINE(google-explicit-constructor)
+class C3 { C3(int i); };
+
+// NOLINTNEXTLINE(some-check, google-explicit-constructor)
+class C4 { C4(int i); };
+
+// NOLINTNEXTLINE without-brackets-skip-all, another-check
+class C5 { C5(int i); };
+
+
+// NOLINTNEXTLINE
+
+class D { D(int i); };
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: single-argument constructors must be marked explicit
+
+// NOLINTNEXTLINE
+//
+class E { E(int i); };
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: single-argument constructors must be marked explicit
+
+#define MACRO(X) class X { X(int i); };
+MACRO(F)
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: single-argument constructors must be marked explicit
+// NOLINTNEXTLINE
+MACRO(G)
+
+#define MACRO_NOARG class H { H(int i); };
+// NOLINTNEXTLINE
+MACRO_NOARG
+
+// CHECK-MESSAGES: Suppressed 8 warnings (8 NOLINT)
+
+// RUN: %check_clang_tidy %s google-explicit-constructor %t --
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/nonstandard-file-extension.test b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/nonstandard-file-extension.test
new file mode 100644
index 0000000..4cb4d11
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/nonstandard-file-extension.test
@@ -0,0 +1,6 @@
+// RUN: %check_clang_tidy -assume-filename=const-cast.cpp %s cppcoreguidelines-pro-type-const-cast %t
+
+const int *i;
+int *j;
+void f() { j = const_cast<int *>(i); }
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not use const_cast [cppcoreguidelines-pro-type-const-cast]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-arc-and-properties.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-arc-and-properties.m
new file mode 100644
index 0000000..7fbd796
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-arc-and-properties.m
@@ -0,0 +1,21 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-semicolon %t
+
+// This test checks if Objective-C 2.0 (@properties) and
+// Automatic Reference Counting (ARC) are enabled for .m files
+// checked via check_clang_tidy.py.
+
+#if !__has_feature(objc_arc)
+#error Objective-C ARC not enabled as expected
+#endif
+
+@interface Foo
+@property (nonatomic, assign) int shouldDoStuff;
+- (void)nop;
+@end
+
+void fail(Foo *f)
+{
+ if(f.shouldDoStuff); [f nop];
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: potentially unintended semicolon [bugprone-suspicious-semicolon]
+ // CHECK-FIXES: if(f.shouldDoStuff) [f nop];
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-avoid-nserror-init.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-avoid-nserror-init.m
new file mode 100644
index 0000000..7794077
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-avoid-nserror-init.m
@@ -0,0 +1,12 @@
+// RUN: %check_clang_tidy %s objc-avoid-nserror-init %t
+@interface NSError
++ (instancetype)alloc;
+- (instancetype)init;
+@end
+
+@implementation foo
+- (void)bar {
+ NSError *error = [[NSError alloc] init];
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use errorWithDomain:code:userInfo: or initWithDomain:code:userInfo: to create a new NSError [objc-avoid-nserror-init]
+}
+@end
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-avoid-spinlock.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-avoid-spinlock.m
new file mode 100644
index 0000000..f9f05cb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-avoid-spinlock.m
@@ -0,0 +1,15 @@
+// RUN: %check_clang_tidy %s objc-avoid-spinlock %t
+
+typedef int OSSpinLock;
+
+@implementation Foo
+- (void)f {
+ int i = 1;
+ OSSpinlockLock(&i);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use os_unfair_lock_lock() or dispatch queue APIs instead of the deprecated OSSpinLock [objc-avoid-spinlock]
+ OSSpinlockTry(&i);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use os_unfair_lock_lock() or dispatch queue APIs instead of the deprecated OSSpinLock [objc-avoid-spinlock]
+ OSSpinlockUnlock(&i);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use os_unfair_lock_lock() or dispatch queue APIs instead of the deprecated OSSpinLock [objc-avoid-spinlock]
+}
+@end
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-forbidden-subclassing-custom.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-forbidden-subclassing-custom.m
new file mode 100644
index 0000000..59e6a88
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-forbidden-subclassing-custom.m
@@ -0,0 +1,39 @@
+// RUN: %check_clang_tidy %s objc-forbidden-subclassing %t \
+// RUN: -config='{CheckOptions: \
+// RUN: [{key: objc-forbidden-subclassing.ClassNames, value: "Foo;Quux"}]}' \
+// RUN: --
+
+@interface UIImagePickerController
+@end
+
+// Make sure custom config options replace (not add to) the default list.
+@interface Waldo : UIImagePickerController
+// CHECK-MESSAGES-NOT: :[[@LINE-1]]:12: warning: Objective-C interface 'Waldo' subclasses 'UIImagePickerController', which is not intended to be subclassed [objc-forbidden-subclassing]
+@end
+
+@interface Foo
+@end
+
+@interface Bar : Foo
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Objective-C interface 'Bar' subclasses 'Foo', which is not intended to be subclassed [objc-forbidden-subclassing]
+@end
+
+// Check subclasses of subclasses.
+@interface Baz : Bar
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Objective-C interface 'Baz' subclasses 'Foo', which is not intended to be subclassed [objc-forbidden-subclassing]
+@end
+
+@interface Quux
+@end
+
+// Check that more than one forbidden superclass can be specified.
+@interface Xyzzy : Quux
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Objective-C interface 'Xyzzy' subclasses 'Quux', which is not intended to be subclassed [objc-forbidden-subclassing]
+@end
+
+@interface Plugh
+@end
+
+@interface Corge : Plugh
+// CHECK-MESSAGES-NOT: :[[@LINE-1]]:12: warning: Objective-C interface 'Corge' subclasses 'Plugh', which is not intended to be subclassed [objc-forbidden-subclassing]
+@end
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-forbidden-subclassing.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-forbidden-subclassing.m
new file mode 100644
index 0000000..3ad38bf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-forbidden-subclassing.m
@@ -0,0 +1,21 @@
+// RUN: %check_clang_tidy %s objc-forbidden-subclassing %t
+
+@interface UIImagePickerController
+@end
+
+@interface Foo : UIImagePickerController
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Objective-C interface 'Foo' subclasses 'UIImagePickerController', which is not intended to be subclassed [objc-forbidden-subclassing]
+@end
+
+// Check subclasses of subclasses.
+@interface Bar : Foo
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Objective-C interface 'Bar' subclasses 'UIImagePickerController', which is not intended to be subclassed [objc-forbidden-subclassing]
+@end
+
+@interface Baz
+@end
+
+// Make sure innocent subclasses aren't caught by the check.
+@interface Blech : Baz
+// CHECK-MESSAGES-NOT: :[[@LINE-1]]:12: warning: Objective-C interface 'Blech' subclasses 'Baz', which is not intended to be subclassed [objc-forbidden-subclassing]
+@end
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-no-arc-or-properties.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-no-arc-or-properties.m
new file mode 100644
index 0000000..c1e73ed
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-no-arc-or-properties.m
@@ -0,0 +1,29 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-semicolon %t -- -- -fno-objc-arc -fobjc-abi-version=1
+
+// This test ensures check_clang_tidy.py allows disabling Objective-C ARC and
+// Objective-C 2.0 via passing arguments after -- on the command line.
+//
+// (We could include a test which doesn't pass any arguments after --
+// to check if ARC and ObjC 2.0 are disabled by default, but that test
+// could change behavior based on the default Objective-C runtime for
+// the platform, which would make this test flaky.)
+
+#if __has_feature(objc_arc)
+#error Objective-C ARC unexpectedly enabled even with -fno-objc-arc
+#endif
+
+#ifdef __OBJC2__
+#error Objective-C 2.0 unexpectedly enabled even with -fobjc-abi-version=1
+#endif
+
+@interface Foo
+- (int)shouldDoStuff;
+- (void)nop;
+@end
+
+void fail(Foo *f)
+{
+ if([f shouldDoStuff]); [f nop];
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: potentially unintended semicolon [bugprone-suspicious-semicolon]
+ // CHECK-FIXES: if([f shouldDoStuff]) [f nop];
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-property-declaration-additional.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-property-declaration-additional.m
new file mode 100644
index 0000000..bf836fa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-property-declaration-additional.m
@@ -0,0 +1,15 @@
+// RUN: %check_clang_tidy %s objc-property-declaration %t \
+// RUN: -config='{CheckOptions: \
+// RUN: [{key: objc-property-declaration.Acronyms, value: "ABC;TGIF"}]}' \
+// RUN: --
+@class NSString;
+
+@interface Foo
+@property(assign, nonatomic) int AbcNotRealPrefix;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: property name 'AbcNotRealPrefix' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+// CHECK-FIXES: @property(assign, nonatomic) int abcNotRealPrefix;
+@property(assign, nonatomic) int ABCCustomPrefix;
+@property(strong, nonatomic) NSString *ABC_custom_prefix;
+// CHECK-MESSAGES: :[[@LINE-1]]:40: warning: property name 'ABC_custom_prefix' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+@property(assign, nonatomic) int GIFShouldIncludeStandardAcronym;
+@end
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-property-declaration-custom.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-property-declaration-custom.m
new file mode 100644
index 0000000..68374ec
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-property-declaration-custom.m
@@ -0,0 +1,18 @@
+// RUN: %check_clang_tidy %s objc-property-declaration %t \
+// RUN: -config='{CheckOptions: \
+// RUN: [{key: objc-property-declaration.Acronyms, value: "ABC;TGIF"}, \
+// RUN: {key: objc-property-declaration.IncludeDefaultAcronyms, value: 0}]}' \
+// RUN: --
+@class NSString;
+
+@interface Foo
+@property(assign, nonatomic) int AbcNotRealPrefix;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: property name 'AbcNotRealPrefix' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+// CHECK-FIXES: @property(assign, nonatomic) int abcNotRealPrefix;
+@property(assign, nonatomic) int ABCCustomPrefix;
+@property(strong, nonatomic) NSString *ABC_custom_prefix;
+// CHECK-MESSAGES: :[[@LINE-1]]:40: warning: property name 'ABC_custom_prefix' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+@property(assign, nonatomic) int GIFIgnoreStandardAcronym;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: property name 'GIFIgnoreStandardAcronym' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+@property(strong, nonatomic) NSString *TGIF;
+@end
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-property-declaration.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-property-declaration.m
new file mode 100644
index 0000000..7f70784
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-property-declaration.m
@@ -0,0 +1,46 @@
+// RUN: %check_clang_tidy %s objc-property-declaration %t
+@class NSData;
+@class NSString;
+@class UIViewController;
+
+@interface Foo
+@property(assign, nonatomic) int NotCamelCase;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: property name 'NotCamelCase' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+// CHECK-FIXES: @property(assign, nonatomic) int notCamelCase;
+@property(assign, nonatomic) int camelCase;
+@property(strong, nonatomic) NSString *URLString;
+@property(strong, nonatomic) NSString *bundleID;
+@property(strong, nonatomic) NSData *RGBABytes;
+@property(strong, nonatomic) UIViewController *notificationsVC;
+@property(strong, nonatomic) NSString *URL_string;
+// CHECK-MESSAGES: :[[@LINE-1]]:40: warning: property name 'URL_string' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+@property(strong, nonatomic) NSString *supportURLsCamelCase;
+@property(strong, nonatomic) NSString *supportURLCamelCase;
+@property(strong, nonatomic) NSString *VCsPluralToAdd;
+@property(assign, nonatomic) int centerX;
+@property(assign, nonatomic) int enable2GBackgroundFetch;
+@property(assign, nonatomic) int shouldUseCFPreferences;
+@property(assign, nonatomic) int enableGLAcceleration;
+@property(assign, nonatomic) int ID;
+@property(assign, nonatomic) int hasADog;
+@end
+
+@interface Foo (Bar)
+@property(assign, nonatomic) int abc_NotCamelCase;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: property name 'abc_NotCamelCase' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+@property(assign, nonatomic) int abCD_camelCase;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: property name 'abCD_camelCase' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+// CHECK-FIXES: @property(assign, nonatomic) int abcd_camelCase;
+@property(assign, nonatomic) int abCD_NotCamelCase;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: property name 'abCD_NotCamelCase' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+// CHECK-FIXES: @property(assign, nonatomic) int abcd_notCamelCase;
+@property(assign, nonatomic) int wrongFormat_;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: property name 'wrongFormat_' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+@property(strong, nonatomic) NSString *URLStr;
+@property(assign, nonatomic) int abc_camelCase;
+@end
+
+@interface Foo ()
+@property(assign, nonatomic) int abc_inClassExtension;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: property name 'abc_inClassExtension' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+@end
\ No newline at end of file
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/overlapping.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/overlapping.cpp
new file mode 100644
index 0000000..f970a13
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/overlapping.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-tidy -checks=-*,llvm-include-order -header-filter=.* %s \
+// RUN: -- -isystem %S/Inputs/Headers -I %S/Inputs/overlapping | \
+// RUN: not grep "note: this fix will not be applied because it overlaps with another fix"
+
+#include <s.h>
+#include "o.h"
+
+// Test that clang-tidy takes into account in which file we are doing the
+// replacements to determine if they overlap or not. In the file "o.h" there is
+// a similar error at the same file offset, but they do not overlap.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-faster-string-find.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-faster-string-find.cpp
new file mode 100644
index 0000000..b36e323
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-faster-string-find.cpp
@@ -0,0 +1,110 @@
+// RUN: %check_clang_tidy %s performance-faster-string-find %t -- \
+// RUN: -config="{CheckOptions: \
+// RUN: [{key: performance-faster-string-find.StringLikeClasses, \
+// RUN: value: 'std::basic_string; ::llvm::StringRef;'}]}" --
+
+namespace std {
+template <typename Char>
+struct basic_string {
+ int find(const Char *, int = 0) const;
+ int find(const Char *, int, int) const;
+ int rfind(const Char *) const;
+ int find_first_of(const Char *) const;
+ int find_first_not_of(const Char *) const;
+ int find_last_of(const Char *) const;
+ int find_last_not_of(const Char *) const;
+};
+
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+} // namespace std
+
+namespace llvm {
+struct StringRef {
+ int find(const char *) const;
+};
+} // namespace llvm
+
+struct NotStringRef {
+ int find(const char *);
+};
+
+void StringFind() {
+ std::string Str;
+
+ Str.find("a");
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: 'find' called with a string literal consisting of a single character; consider using the more effective overload accepting a character [performance-faster-string-find]
+ // CHECK-FIXES: Str.find('a');
+
+ // Works with the pos argument.
+ Str.find("a", 1);
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: 'find' called with a string literal
+ // CHECK-FIXES: Str.find('a', 1);
+
+ // Doens't work with strings smaller or larger than 1 char.
+ Str.find("");
+ Str.find("ab");
+
+ // Doesn't do anything with the 3 argument overload.
+ Str.find("a", 1, 1);
+
+ // Other methods that can also be replaced
+ Str.rfind("a");
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: 'rfind' called with a string literal
+ // CHECK-FIXES: Str.rfind('a');
+ Str.find_first_of("a");
+ // CHECK-MESSAGES: [[@LINE-1]]:21: warning: 'find_first_of' called with a string
+ // CHECK-FIXES: Str.find_first_of('a');
+ Str.find_first_not_of("a");
+ // CHECK-MESSAGES: [[@LINE-1]]:25: warning: 'find_first_not_of' called with a
+ // CHECK-FIXES: Str.find_first_not_of('a');
+ Str.find_last_of("a");
+ // CHECK-MESSAGES: [[@LINE-1]]:20: warning: 'find_last_of' called with a string
+ // CHECK-FIXES: Str.find_last_of('a');
+ Str.find_last_not_of("a");
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: 'find_last_not_of' called with a
+ // CHECK-FIXES: Str.find_last_not_of('a');
+
+ // std::wstring should work.
+ std::wstring WStr;
+ WStr.find(L"n");
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: 'find' called with a string literal
+ // CHECK-FIXES: Str.find(L'n');
+ // Even with unicode that fits in one wide char.
+ WStr.find(L"\x3A9");
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: 'find' called with a string literal
+ // CHECK-FIXES: Str.find(L'\x3A9');
+
+ // Also with other types, but only if it was specified in the options.
+ llvm::StringRef sr;
+ sr.find("x");
+ // CHECK-MESSAGES: [[@LINE-1]]:11: warning: 'find' called with a string literal
+ // CHECK-FIXES: sr.find('x');
+ NotStringRef nsr;
+ nsr.find("x");
+}
+
+
+template <typename T>
+int FindTemplateDependant(T value) {
+ return value.find("A");
+}
+template <typename T>
+int FindTemplateNotDependant(T pos) {
+ return std::string().find("A", pos);
+ // CHECK-MESSAGES: [[@LINE-1]]:29: warning: 'find' called with a string literal
+ // CHECK-FIXES: return std::string().find('A', pos);
+}
+
+int FindStr() {
+ return FindTemplateDependant(std::string()) + FindTemplateNotDependant(1);
+}
+
+#define STR_MACRO(str) str.find("A")
+#define POS_MACRO(pos) std::string().find("A",pos)
+
+int Macros() {
+ return STR_MACRO(std::string()) + POS_MACRO(1);
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: 'find' called with a string literal
+ // CHECK-MESSAGES: [[@LINE-2]]:37: warning: 'find' called with a string literal
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-for-range-copy-warn-on-all-auto-copies.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-for-range-copy-warn-on-all-auto-copies.cpp
new file mode 100644
index 0000000..75655a6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-for-range-copy-warn-on-all-auto-copies.cpp
@@ -0,0 +1,39 @@
+// RUN: %check_clang_tidy %s performance-for-range-copy %t -config="{CheckOptions: [{key: "performance-for-range-copy.WarnOnAllAutoCopies", value: 1}]}" -- -std=c++11
+
+template <typename T>
+struct Iterator {
+ void operator++() {}
+ const T& operator*() {
+ static T* TT = new T();
+ return *TT;
+ }
+ bool operator!=(const Iterator &) { return false; }
+};
+template <typename T>
+struct View {
+ T begin() { return T(); }
+ T begin() const { return T(); }
+ T end() { return T(); }
+ T end() const { return T(); }
+};
+
+struct S {
+ S();
+ S(const S &);
+ ~S();
+ S &operator=(const S &);
+};
+
+void NegativeLoopVariableNotAuto() {
+ for (S S1 : View<Iterator<S>>()) {
+ S* S2 = &S1;
+ }
+}
+
+void PositiveTriggeredForAutoLoopVariable() {
+ for (auto S1 : View<Iterator<S>>()) {
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: the loop variable's type is not a reference type; this creates a copy in each iteration; consider making this a reference [performance-for-range-copy]
+ // CHECK-FIXES: for (const auto& S1 : View<Iterator<S>>()) {
+ S* S2 = &S1;
+ }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-for-range-copy.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-for-range-copy.cpp
new file mode 100644
index 0000000..1c77996
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-for-range-copy.cpp
@@ -0,0 +1,262 @@
+// RUN: %check_clang_tidy %s performance-for-range-copy %t -- -- -std=c++11 -fno-delayed-template-parsing
+
+namespace std {
+
+template <typename _Tp>
+struct remove_reference { typedef _Tp type; };
+
+template <typename _Tp>
+constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t) {
+ return static_cast<typename std::remove_reference<_Tp>::type &&>(__t);
+}
+
+} // std
+
+template <typename T>
+struct Iterator {
+ void operator++() {}
+ const T& operator*() {
+ static T* TT = new T();
+ return *TT;
+ }
+ bool operator!=(const Iterator &) { return false; }
+ typedef const T& const_reference;
+};
+template <typename T>
+struct View {
+ T begin() { return T(); }
+ T begin() const { return T(); }
+ T end() { return T(); }
+ T end() const { return T(); }
+ typedef typename T::const_reference const_reference;
+};
+
+struct ConstructorConvertible {
+};
+
+struct S {
+ S();
+ S(const S &);
+ S(const ConstructorConvertible&) {}
+ ~S();
+ S &operator=(const S &);
+};
+
+struct Convertible {
+ operator S() const {
+ return S();
+ }
+};
+
+void negativeConstReference() {
+ for (const S &S1 : View<Iterator<S>>()) {
+ }
+}
+
+void negativeUserDefinedConversion() {
+ Convertible C[0];
+ for (const S &S1 : C) {
+ }
+}
+
+void negativeImplicitConstructorConversion() {
+ ConstructorConvertible C[0];
+ for (const S &S1 : C) {
+ }
+}
+
+template <typename T>
+void uninstantiated() {
+ for (const S S1 : View<Iterator<S>>()) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: the loop variable's type is not a reference type; this creates a copy in each iteration; consider making this a reference [performance-for-range-copy]
+ // CHECK-FIXES: {{^}} for (const S& S1 : View<Iterator<S>>()) {}
+
+ // Don't warn on dependent types.
+ for (const T t1 : View<Iterator<T>>()) {
+ }
+}
+
+template <typename T>
+void instantiated() {
+ for (const S S2 : View<Iterator<S>>()) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: the loop variable's type is {{.*}}
+ // CHECK-FIXES: {{^}} for (const S& S2 : View<Iterator<S>>()) {}
+
+ for (const T T2 : View<Iterator<T>>()) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: the loop variable's type is {{.*}}
+ // CHECK-FIXES: {{^}} for (const T& T2 : View<Iterator<T>>()) {}
+}
+
+template <typename T>
+void instantiatedNegativeTypedefConstReference() {
+ for (typename T::const_reference T2 : T()) {
+ S S1 = T2;
+ }
+}
+
+void f() {
+ instantiated<int>();
+ instantiated<S>();
+ instantiatedNegativeTypedefConstReference<View<Iterator<S>>>();
+}
+
+struct Mutable {
+ Mutable() {}
+ Mutable(const Mutable &) = default;
+ Mutable(const Mutable &, const Mutable &) {}
+ void setBool(bool B) {}
+ bool constMethod() const {
+ return true;
+ }
+ Mutable& operator[](int I) {
+ return *this;
+ }
+ bool operator==(const Mutable &Other) const {
+ return true;
+ }
+ ~Mutable() {}
+};
+
+struct Point {
+ ~Point() {}
+ int x, y;
+};
+
+Mutable& operator<<(Mutable &Out, bool B) {
+ Out.setBool(B);
+ return Out;
+}
+
+bool operator!=(const Mutable& M1, const Mutable& M2) {
+ return false;
+}
+
+void use(const Mutable &M);
+void use(int I);
+void useTwice(const Mutable &M1, const Mutable &M2);
+void useByValue(Mutable M);
+void useByConstValue(const Mutable M);
+void mutate(Mutable *M);
+void mutate(Mutable &M);
+void onceConstOnceMutated(const Mutable &M1, Mutable &M2);
+
+void negativeVariableIsMutated() {
+ for (auto M : View<Iterator<Mutable>>()) {
+ mutate(M);
+ }
+ for (auto M : View<Iterator<Mutable>>()) {
+ mutate(&M);
+ }
+ for (auto M : View<Iterator<Mutable>>()) {
+ M.setBool(true);
+ }
+}
+
+void negativeOnceConstOnceMutated() {
+ for (auto M : View<Iterator<Mutable>>()) {
+ onceConstOnceMutated(M, M);
+ }
+}
+
+void negativeVarIsMoved() {
+ for (auto M : View<Iterator<Mutable>>()) {
+ auto Moved = std::move(M);
+ }
+}
+
+void negativeNonConstOperatorIsInvoked() {
+ for (auto NonConstOperatorInvokee : View<Iterator<Mutable>>()) {
+ auto& N = NonConstOperatorInvokee[0];
+ }
+}
+
+void negativeNonConstNonMemberOperatorInvoked() {
+ for (auto NonConstOperatorInvokee : View<Iterator<Mutable>>()) {
+ NonConstOperatorInvokee << true;
+ }
+}
+
+void negativeConstCheapToCopy() {
+ for (const int I : View<Iterator<int>>()) {
+ }
+}
+
+void negativeConstCheapToCopyTypedef() {
+ typedef const int ConstInt;
+ for (ConstInt C : View<Iterator<ConstInt>>()) {
+ }
+}
+
+void negativeCheapToCopy() {
+ for (int I : View<Iterator<int>>()) {
+ use(I);
+ }
+}
+
+void negativeCheapToCopyTypedef() {
+ typedef int Int;
+ for (Int I : View<Iterator<Int>>()) {
+ use(I);
+ }
+}
+
+void positiveOnlyConstMethodInvoked() {
+ for (auto M : View<Iterator<Mutable>>()) {
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+ // CHECK-FIXES: for (const auto& M : View<Iterator<Mutable>>()) {
+ M.constMethod();
+ }
+}
+
+void positiveOnlyUsedAsConstArguments() {
+ for (auto UsedAsConst : View<Iterator<Mutable>>()) {
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+ // CHECK-FIXES: for (const auto& UsedAsConst : View<Iterator<Mutable>>()) {
+ use(UsedAsConst);
+ useTwice(UsedAsConst, UsedAsConst);
+ useByValue(UsedAsConst);
+ useByConstValue(UsedAsConst);
+ }
+}
+
+void positiveOnlyAccessedFieldAsConst() {
+ for (auto UsedAsConst : View<Iterator<Point>>()) {
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+ // CHECK-FIXES: for (const auto& UsedAsConst : View<Iterator<Point>>()) {
+ use(UsedAsConst.x);
+ use(UsedAsConst.y);
+ }
+}
+
+void positiveOnlyUsedInCopyConstructor() {
+ for (auto A : View<Iterator<Mutable>>()) {
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+ // CHECK-FIXES: for (const auto& A : View<Iterator<Mutable>>()) {
+ Mutable Copy = A;
+ Mutable Copy2(A);
+ }
+}
+
+void positiveTwoConstConstructorArgs() {
+ for (auto A : View<Iterator<Mutable>>()) {
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+ // CHECK-FIXES: for (const auto& A : View<Iterator<Mutable>>()) {
+ Mutable Copy(A, A);
+ }
+}
+
+void PositiveConstMemberOperatorInvoked() {
+ for (auto ConstOperatorInvokee : View<Iterator<Mutable>>()) {
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+ // CHECK-FIXES: for (const auto& ConstOperatorInvokee : View<Iterator<Mutable>>()) {
+ bool result = ConstOperatorInvokee == Mutable();
+ }
+}
+
+void PositiveConstNonMemberOperatorInvoked() {
+ for (auto ConstOperatorInvokee : View<Iterator<Mutable>>()) {
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+ // CHECK-FIXES: for (const auto& ConstOperatorInvokee : View<Iterator<Mutable>>()) {
+ bool result = ConstOperatorInvokee != Mutable();
+ }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-implicit-conversion-in-loop.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-implicit-conversion-in-loop.cpp
new file mode 100644
index 0000000..72f9e52
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-implicit-conversion-in-loop.cpp
@@ -0,0 +1,197 @@
+// RUN: %check_clang_tidy %s performance-implicit-conversion-in-loop %t
+
+// ---------- Classes used in the tests ----------
+
+// Iterator returning by value.
+template <typename T>
+struct Iterator {
+ void operator++();
+ T operator*();
+ bool operator!=(const Iterator& other);
+};
+
+// Iterator returning by reference.
+template <typename T>
+struct RefIterator {
+ void operator++();
+ T& operator*();
+ bool operator!=(const RefIterator& other);
+};
+
+// The template argument is an iterator type, and a view is an object you can
+// run a for loop on.
+template <typename T>
+struct View {
+ T begin();
+ T end();
+};
+
+// With this class, the implicit conversion is a call to the (implicit)
+// constructor of the class.
+template <typename T>
+class ImplicitWrapper {
+ public:
+ // Implicit!
+ ImplicitWrapper(const T& t);
+};
+
+// With this class, the implicit conversion is a call to the conversion
+// operators of SimpleClass and ComplexClass.
+template <typename T>
+class OperatorWrapper {
+ public:
+ OperatorWrapper() = delete;
+};
+
+struct SimpleClass {
+ int foo;
+ operator OperatorWrapper<SimpleClass>();
+};
+
+// The materialize expression is not the same when the class has a destructor,
+// so we make sure we cover that case too.
+class ComplexClass {
+ public:
+ ComplexClass();
+ ~ComplexClass();
+ operator OperatorWrapper<ComplexClass>();
+};
+
+typedef View<Iterator<SimpleClass>> SimpleView;
+typedef View<RefIterator<SimpleClass>> SimpleRefView;
+typedef View<Iterator<ComplexClass>> ComplexView;
+typedef View<RefIterator<ComplexClass>> ComplexRefView;
+
+// ---------- The test themselves ----------
+// For each test we do, in the same order, const ref, non const ref, const
+// value, non const value.
+
+void SimpleClassIterator() {
+ for (const SimpleClass& foo : SimpleView()) {}
+ // This line does not compile because a temporary cannot be assigned to a non
+ // const reference.
+ // for (SimpleClass& foo : SimpleView()) {}
+ for (const SimpleClass foo : SimpleView()) {}
+ for (SimpleClass foo : SimpleView()) {}
+}
+
+void SimpleClassRefIterator() {
+ for (const SimpleClass& foo : SimpleRefView()) {}
+ for (SimpleClass& foo : SimpleRefView()) {}
+ for (const SimpleClass foo : SimpleRefView()) {}
+ for (SimpleClass foo : SimpleRefView()) {}
+}
+
+void ComplexClassIterator() {
+ for (const ComplexClass& foo : ComplexView()) {}
+ // for (ComplexClass& foo : ComplexView()) {}
+ for (const ComplexClass foo : ComplexView()) {}
+ for (ComplexClass foo : ComplexView()) {}
+}
+
+void ComplexClassRefIterator() {
+ for (const ComplexClass& foo : ComplexRefView()) {}
+ for (ComplexClass& foo : ComplexRefView()) {}
+ for (const ComplexClass foo : ComplexRefView()) {}
+ for (ComplexClass foo : ComplexRefView()) {}
+}
+
+void ImplicitSimpleClassIterator() {
+ for (const ImplicitWrapper<SimpleClass>& foo : SimpleView()) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the loop variable 'foo' is different from the one returned by the iterator and generates an implicit conversion; you can either change the type to the matching one ('const SimpleClass &' but 'const auto&' is always a valid option) or remove the reference to make it explicit that you are creating a new value [performance-implicit-conversion-in-loop]
+ // for (ImplicitWrapper<SimpleClass>& foo : SimpleView()) {}
+ for (const ImplicitWrapper<SimpleClass> foo : SimpleView()) {}
+ for (ImplicitWrapper<SimpleClass> foo : SimpleView()) {}
+}
+
+void ImplicitSimpleClassRefIterator() {
+ for (const ImplicitWrapper<SimpleClass>& foo : SimpleRefView()) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
+ // for (ImplicitWrapper<SimpleClass>& foo : SimpleRefView()) {}
+ for (const ImplicitWrapper<SimpleClass> foo : SimpleRefView()) {}
+ for (ImplicitWrapper<SimpleClass> foo : SimpleRefView()) {}
+}
+
+void ImplicitSimpleClassArray() {
+ SimpleClass array[5];
+ for (const ImplicitWrapper<SimpleClass>& foo : array) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
+ // for (ImplicitWrapper<SimpleClass>& foo : array) {}
+ for (const ImplicitWrapper<SimpleClass> foo : array) {}
+ for (ImplicitWrapper<SimpleClass> foo : array) {}
+}
+
+void ImplicitComplexClassIterator() {
+ for (const ImplicitWrapper<ComplexClass>& foo : ComplexView()) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
+ // for (ImplicitWrapper<ComplexClass>& foo : ComplexView()) {}
+ for (const ImplicitWrapper<ComplexClass> foo : ComplexView()) {}
+ for (ImplicitWrapper<ComplexClass> foo : ComplexView()) {}
+}
+
+void ImplicitComplexClassRefIterator() {
+ ComplexClass array[5];
+ for (const ImplicitWrapper<ComplexClass>& foo : array) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
+ // for (ImplicitWrapper<ComplexClass>& foo : array) {}
+ for (const ImplicitWrapper<ComplexClass> foo : array) {}
+ for (ImplicitWrapper<ComplexClass> foo : array) {}
+}
+
+void ImplicitComplexClassArray() {
+ for (const ImplicitWrapper<ComplexClass>& foo : ComplexRefView()) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
+ // for (ImplicitWrapper<ComplexClass>& foo : ComplexRefView()) {}
+ for (const ImplicitWrapper<ComplexClass> foo : ComplexRefView()) {}
+ for (ImplicitWrapper<ComplexClass> foo : ComplexRefView()) {}
+}
+
+void OperatorSimpleClassIterator() {
+ for (const OperatorWrapper<SimpleClass>& foo : SimpleView()) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
+ // for (OperatorWrapper<SimpleClass>& foo : SimpleView()) {}
+ for (const OperatorWrapper<SimpleClass> foo : SimpleView()) {}
+ for (OperatorWrapper<SimpleClass> foo : SimpleView()) {}
+}
+
+void OperatorSimpleClassRefIterator() {
+ for (const OperatorWrapper<SimpleClass>& foo : SimpleRefView()) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
+ // for (OperatorWrapper<SimpleClass>& foo : SimpleRefView()) {}
+ for (const OperatorWrapper<SimpleClass> foo : SimpleRefView()) {}
+ for (OperatorWrapper<SimpleClass> foo : SimpleRefView()) {}
+}
+
+void OperatorSimpleClassArray() {
+ SimpleClass array[5];
+ for (const OperatorWrapper<SimpleClass>& foo : array) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
+ // for (OperatorWrapper<SimpleClass>& foo : array) {}
+ for (const OperatorWrapper<SimpleClass> foo : array) {}
+ for (OperatorWrapper<SimpleClass> foo : array) {}
+}
+
+void OperatorComplexClassIterator() {
+ for (const OperatorWrapper<ComplexClass>& foo : ComplexView()) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
+ // for (OperatorWrapper<ComplexClass>& foo : ComplexView()) {}
+ for (const OperatorWrapper<ComplexClass> foo : ComplexView()) {}
+ for (OperatorWrapper<ComplexClass> foo : ComplexView()) {}
+}
+
+void OperatorComplexClassRefIterator() {
+ for (const OperatorWrapper<ComplexClass>& foo : ComplexRefView()) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
+ // for (OperatorWrapper<ComplexClass>& foo : ComplexRefView()) {}
+ for (const OperatorWrapper<ComplexClass> foo : ComplexRefView()) {}
+ for (OperatorWrapper<ComplexClass> foo : ComplexRefView()) {}
+}
+
+void OperatorComplexClassArray() {
+ ComplexClass array[5];
+ for (const OperatorWrapper<ComplexClass>& foo : array) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
+ // for (OperatorWrapper<ComplexClass>& foo : array) {}
+ for (const OperatorWrapper<ComplexClass> foo : array) {}
+ for (OperatorWrapper<ComplexClass> foo : array) {}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-inefficient-algorithm.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-inefficient-algorithm.cpp
new file mode 100644
index 0000000..19a6701
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-inefficient-algorithm.cpp
@@ -0,0 +1,166 @@
+// RUN: %check_clang_tidy %s performance-inefficient-algorithm %t
+
+namespace std {
+template <typename T> struct less {
+ bool operator()(const T &lhs, const T &rhs) { return lhs < rhs; }
+};
+
+template <typename T> struct greater {
+ bool operator()(const T &lhs, const T &rhs) { return lhs > rhs; }
+};
+
+struct iterator_type {};
+
+template <typename K, typename Cmp = less<K>> struct set {
+ typedef iterator_type iterator;
+ iterator find(const K &k);
+ unsigned count(const K &k);
+
+ iterator begin();
+ iterator end();
+ iterator begin() const;
+ iterator end() const;
+};
+
+struct other_iterator_type {};
+
+template <typename K, typename V, typename Cmp = less<K>> struct map {
+ typedef other_iterator_type iterator;
+ iterator find(const K &k);
+ unsigned count(const K &k);
+
+ iterator begin();
+ iterator end();
+ iterator begin() const;
+ iterator end() const;
+};
+
+template <typename K, typename V> struct multimap : map<K, V> {};
+template <typename K> struct unordered_set : set<K> {};
+template <typename K, typename V> struct unordered_map : map<K, V> {};
+template <typename K> struct unordered_multiset : set<K> {};
+template <typename K, typename V> struct unordered_multimap : map<K, V> {};
+
+template <typename K, typename Cmp = less<K>> struct multiset : set<K, Cmp> {};
+
+template <typename FwIt, typename K>
+FwIt find(FwIt, FwIt end, const K &) { return end; }
+
+template <typename FwIt, typename K, typename Cmp>
+FwIt find(FwIt, FwIt end, const K &, Cmp) { return end; }
+
+template <typename FwIt, typename Pred>
+FwIt find_if(FwIt, FwIt end, Pred) { return end; }
+
+template <typename FwIt, typename K>
+unsigned count(FwIt, FwIt, const K &) { return 0; }
+
+template <typename FwIt, typename K>
+FwIt lower_bound(FwIt, FwIt end, const K &) { return end; }
+
+template <typename FwIt, typename K, typename Ord>
+FwIt lower_bound(FwIt, FwIt end, const K &, Ord) { return end; }
+}
+
+#define FIND_IN_SET(x) find(x.begin(), x.end(), 10)
+// CHECK-FIXES: #define FIND_IN_SET(x) find(x.begin(), x.end(), 10)
+
+template <typename T> void f(const T &t) {
+ std::set<int> s;
+ find(s.begin(), s.end(), 46);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+ // CHECK-FIXES: {{^ }}s.find(46);{{$}}
+
+ find(t.begin(), t.end(), 46);
+ // CHECK-FIXES: {{^ }}find(t.begin(), t.end(), 46);{{$}}
+}
+
+int main() {
+ std::set<int> s;
+ auto it = std::find(s.begin(), s.end(), 43);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: this STL algorithm call should be replaced with a container method [performance-inefficient-algorithm]
+ // CHECK-FIXES: {{^ }}auto it = s.find(43);{{$}}
+ auto c = count(s.begin(), s.end(), 43);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: this STL algorithm call should be
+ // CHECK-FIXES: {{^ }}auto c = s.count(43);{{$}}
+
+#define SECOND(x, y, z) y
+ SECOND(q,std::count(s.begin(), s.end(), 22),w);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: this STL algorithm call should be
+ // CHECK-FIXES: {{^ }}SECOND(q,s.count(22),w);{{$}}
+
+ it = find_if(s.begin(), s.end(), [](int) { return false; });
+
+ std::multiset<int> ms;
+ find(ms.begin(), ms.end(), 46);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+ // CHECK-FIXES: {{^ }}ms.find(46);{{$}}
+
+ const std::multiset<int> &msref = ms;
+ find(msref.begin(), msref.end(), 46);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+ // CHECK-FIXES: {{^ }}msref.find(46);{{$}}
+
+ std::multiset<int> *msptr = &ms;
+ find(msptr->begin(), msptr->end(), 46);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+ // CHECK-FIXES: {{^ }}msptr->find(46);{{$}}
+
+ it = std::find(s.begin(), s.end(), 43, std::greater<int>());
+ // CHECK-MESSAGES: :[[@LINE-1]]:42: warning: different comparers used in the algorithm and the container [performance-inefficient-algorithm]
+
+ FIND_IN_SET(s);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+ // CHECK-FIXES: {{^ }}FIND_IN_SET(s);{{$}}
+
+ f(s);
+
+ std::unordered_set<int> us;
+ lower_bound(us.begin(), us.end(), 10);
+ // CHECK-FIXES: {{^ }}lower_bound(us.begin(), us.end(), 10);{{$}}
+ find(us.begin(), us.end(), 10);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+ // CHECK-FIXES: {{^ }}us.find(10);{{$}}
+
+ std::unordered_multiset<int> ums;
+ find(ums.begin(), ums.end(), 10);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+ // CHECK-FIXES: {{^ }}ums.find(10);{{$}}
+
+ std::map<int, int> intmap;
+ find(intmap.begin(), intmap.end(), 46);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+ // CHECK-FIXES: {{^ }}find(intmap.begin(), intmap.end(), 46);{{$}}
+
+ std::multimap<int, int> intmmap;
+ find(intmmap.begin(), intmmap.end(), 46);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+ // CHECK-FIXES: {{^ }}find(intmmap.begin(), intmmap.end(), 46);{{$}}
+
+ std::unordered_map<int, int> umap;
+ find(umap.begin(), umap.end(), 46);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+ // CHECK-FIXES: {{^ }}find(umap.begin(), umap.end(), 46);{{$}}
+
+ std::unordered_multimap<int, int> ummap;
+ find(ummap.begin(), ummap.end(), 46);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+ // CHECK-FIXES: {{^ }}find(ummap.begin(), ummap.end(), 46);{{$}}
+}
+
+struct Value {
+ int value;
+};
+
+struct Ordering {
+ bool operator()(const Value &lhs, const Value &rhs) const {
+ return lhs.value < rhs.value;
+ }
+ bool operator()(int lhs, const Value &rhs) const { return lhs < rhs.value; }
+};
+
+void g(std::set<Value, Ordering> container, int value) {
+ lower_bound(container.begin(), container.end(), value, Ordering());
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+ // CHECK-FIXES: {{^ }}lower_bound(container.begin(), container.end(), value, Ordering());{{$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-inefficient-string-concatenation.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-inefficient-string-concatenation.cpp
new file mode 100644
index 0000000..1dbd56b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-inefficient-string-concatenation.cpp
@@ -0,0 +1,48 @@
+// RUN: %check_clang_tidy %s performance-inefficient-string-concatenation %t
+
+namespace std {
+template <typename T>
+class basic_string {
+public:
+ basic_string() {}
+ ~basic_string() {}
+ basic_string<T> *operator+=(const basic_string<T> &) {}
+ friend basic_string<T> operator+(const basic_string<T> &, const basic_string<T> &) {}
+};
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+}
+
+void f(std::string) {}
+std::string g(std::string) {}
+
+int main() {
+ std::string mystr1, mystr2;
+ std::wstring mywstr1, mywstr2;
+ auto myautostr1 = mystr1;
+ auto myautostr2 = mystr2;
+
+ for (int i = 0; i < 10; ++i) {
+ f(mystr1 + mystr2 + mystr1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: string concatenation results in allocation of unnecessary temporary strings; consider using 'operator+=' or 'string::append()' instead
+ mystr1 = mystr1 + mystr2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: string concatenation
+ mystr1 = mystr2 + mystr2 + mystr2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: string concatenation
+ mystr1 = mystr2 + mystr1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: string concatenation
+ mywstr1 = mywstr2 + mywstr1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: string concatenation
+ mywstr1 = mywstr2 + mywstr2 + mywstr2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: string concatenation
+ myautostr1 = myautostr1 + myautostr2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: string concatenation
+
+ mywstr1 = mywstr2 + mywstr2;
+ mystr1 = mystr2 + mystr2;
+ mystr1 += mystr2;
+ f(mystr2 + mystr1);
+ mystr1 = g(mystr1);
+ }
+ return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-inefficient-vector-operation.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-inefficient-vector-operation.cpp
new file mode 100644
index 0000000..a04f66e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-inefficient-vector-operation.cpp
@@ -0,0 +1,277 @@
+// RUN: %check_clang_tidy %s performance-inefficient-vector-operation %t -- -format-style=llvm -- --std=c++11
+
+namespace std {
+
+typedef int size_t;
+
+template<class E> class initializer_list {
+public:
+ using value_type = E;
+ using reference = E&;
+ using const_reference = const E&;
+ using size_type = size_t;
+ using iterator = const E*;
+ using const_iterator = const E*;
+ initializer_list();
+ size_t size() const; // number of elements
+ const E* begin() const; // first element
+ const E* end() const; // one past the last element
+};
+
+// initializer list range access
+template<class E> const E* begin(initializer_list<E> il);
+template<class E> const E* end(initializer_list<E> il);
+
+template <class T>
+class vector {
+ public:
+ typedef T* iterator;
+ typedef const T* const_iterator;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef size_t size_type;
+
+ explicit vector();
+ explicit vector(size_type n);
+
+ void push_back(const T& val);
+
+ template <class... Args> void emplace_back(Args &&... args);
+
+ void reserve(size_t n);
+ void resize(size_t n);
+
+ size_t size();
+ const_reference operator[] (size_type) const;
+ reference operator[] (size_type);
+
+ const_iterator begin() const;
+ const_iterator end() const;
+};
+} // namespace std
+
+class Foo {
+ public:
+ explicit Foo(int);
+};
+
+class Bar {
+ public:
+ Bar(int);
+};
+
+int Op(int);
+
+void f(std::vector<int>& t) {
+ {
+ std::vector<int> v0;
+ // CHECK-FIXES: v0.reserve(10);
+ for (int i = 0; i < 10; ++i)
+ v0.push_back(i);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called inside a loop; consider pre-allocating the vector capacity before the loop
+ }
+ {
+ std::vector<int> v1;
+ // CHECK-FIXES: v1.reserve(10);
+ for (int i = 0; i < 10; i++)
+ v1.push_back(i);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+ }
+ {
+ std::vector<int> v2;
+ // CHECK-FIXES: v2.reserve(10);
+ for (int i = 0; i < 10; ++i)
+ v2.push_back(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+ }
+ {
+ std::vector<int> v3;
+ // CHECK-FIXES: v3.reserve(5);
+ for (int i = 0; i < 5; ++i) {
+ v3.push_back(i);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+ }
+ // CHECK-FIXES-NOT: v3.reserve(10);
+ for (int i = 0; i < 10; ++i) {
+ // No fix for this loop as we encounter the prior loops.
+ v3.push_back(i);
+ }
+ }
+ {
+ std::vector<int> v4;
+ std::vector<int> v5;
+ v5.reserve(3);
+ // CHECK-FIXES: v4.reserve(10);
+ for (int i = 0; i < 10; ++i)
+ v4.push_back(i);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+ }
+ {
+ std::vector<int> v6;
+ // CHECK-FIXES: v6.reserve(t.size());
+ for (std::size_t i = 0; i < t.size(); ++i) {
+ v6.push_back(t[i]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+ }
+ }
+ {
+ std::vector<int> v7;
+ // CHECK-FIXES: v7.reserve(t.size() - 1);
+ for (std::size_t i = 0; i < t.size() - 1; ++i) {
+ v7.push_back(t[i]);
+ } // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+ }
+ {
+ std::vector<int> v8;
+ // CHECK-FIXES: v8.reserve(t.size());
+ for (const auto &e : t) {
+ v8.push_back(e);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+ }
+ }
+ {
+ std::vector<int> v9;
+ // CHECK-FIXES: v9.reserve(t.size());
+ for (const auto &e : t) {
+ v9.push_back(Op(e));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+ }
+ }
+ {
+ std::vector<Foo> v10;
+ // CHECK-FIXES: v10.reserve(t.size());
+ for (const auto &e : t) {
+ v10.push_back(Foo(e));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+ }
+ }
+ {
+ std::vector<Bar> v11;
+ // CHECK-FIXES: v11.reserve(t.size());
+ for (const auto &e : t) {
+ v11.push_back(e);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+ }
+ }
+ {
+ std::vector<Foo> v12;
+ // CHECK-FIXES: v12.reserve(t.size());
+ for (const auto &e : t) {
+ v12.emplace_back(e);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'emplace_back' is called
+ }
+ }
+
+ // ---- Non-fixed Cases ----
+ {
+ std::vector<int> z0;
+ z0.reserve(20);
+ // CHECK-FIXES-NOT: z0.reserve(10);
+ // There is a "reserve" call already.
+ for (int i = 0; i < 10; ++i) {
+ z0.push_back(i);
+ }
+ }
+ {
+ std::vector<int> z1;
+ z1.reserve(5);
+ // CHECK-FIXES-NOT: z1.reserve(10);
+ // There is a "reserve" call already.
+ for (int i = 0; i < 10; ++i) {
+ z1.push_back(i);
+ }
+ }
+ {
+ std::vector<int> z2;
+ z2.resize(5);
+ // CHECK-FIXES-NOT: z2.reserve(10);
+ // There is a ref usage of v before the loop.
+ for (int i = 0; i < 10; ++i) {
+ z2.push_back(i);
+ }
+ }
+ {
+ std::vector<int> z3;
+ z3.push_back(0);
+ // CHECK-FIXES-NOT: z3.reserve(10);
+ // There is a ref usage of v before the loop.
+ for (int i = 0; i < 10; ++i) {
+ z3.push_back(i);
+ }
+ }
+ {
+ std::vector<int> z4;
+ f(z4);
+ // CHECK-FIXES-NOT: z4.reserve(10);
+ // There is a ref usage of z4 before the loop.
+ for (int i = 0; i < 10; ++i) {
+ z4.push_back(i);
+ }
+ }
+ {
+ std::vector<int> z5(20);
+ // CHECK-FIXES-NOT: z5.reserve(10);
+ // z5 is not constructed with default constructor.
+ for (int i = 0; i < 10; ++i) {
+ z5.push_back(i);
+ }
+ }
+ {
+ std::vector<int> z6;
+ // CHECK-FIXES-NOT: z6.reserve(10);
+ // For-loop is not started with 0.
+ for (int i = 1; i < 10; ++i) {
+ z6.push_back(i);
+ }
+ }
+ {
+ std::vector<int> z7;
+ // CHECK-FIXES-NOT: z7.reserve(t.size());
+ // z7 isn't referenced in for-loop body.
+ for (std::size_t i = 0; i < t.size(); ++i) {
+ t.push_back(i);
+ }
+ }
+ {
+ std::vector<int> z8;
+ int k;
+ // CHECK-FIXES-NOT: z8.reserve(10);
+ // For-loop isn't a fixable loop.
+ for (std::size_t i = 0; k < 10; ++i) {
+ z8.push_back(t[i]);
+ }
+ }
+ {
+ std::vector<int> z9;
+ // CHECK-FIXES-NOT: z9.reserve(i + 1);
+ // The loop end expression refers to the loop variable i.
+ for (int i = 0; i < i + 1; i++)
+ z9.push_back(i);
+ }
+ {
+ std::vector<int> z10;
+ int k;
+ // CHECK-FIXES-NOT: z10.reserve(10);
+ // For-loop isn't a fixable loop.
+ for (std::size_t i = 0; i < 10; ++k) {
+ z10.push_back(t[i]);
+ }
+ }
+ {
+ std::vector<int> z11;
+ // initializer_list should not trigger the check.
+ for (int e : {1, 2, 3, 4, 5}) {
+ z11.push_back(e);
+ }
+ }
+ {
+ std::vector<int> z12;
+ std::vector<int>* z13 = &t;
+ // We only support detecting the range init expression which references
+ // container directly.
+ // Complex range init expressions like `*z13` is not supported.
+ for (const auto &e : *z13) {
+ z12.push_back(e);
+ }
+ }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-move-const-arg-trivially-copyable.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-move-const-arg-trivially-copyable.cpp
new file mode 100644
index 0000000..ea0c2fc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-move-const-arg-trivially-copyable.cpp
@@ -0,0 +1,98 @@
+// RUN: %check_clang_tidy %s performance-move-const-arg %t \
+// RUN: -config='{CheckOptions: \
+// RUN: [{key: performance-move-const-arg.CheckTriviallyCopyableMove, value: 0}]}' \
+// RUN: -- -std=c++14
+
+namespace std {
+
+template <typename> struct remove_reference;
+template <typename _Tp> struct remove_reference { typedef _Tp type; };
+template <typename _Tp> struct remove_reference<_Tp &> { typedef _Tp type; };
+template <typename _Tp> struct remove_reference<_Tp &&> { typedef _Tp type; };
+
+template <typename _Tp>
+constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t) {
+ return static_cast<typename std::remove_reference<_Tp>::type &&>(__t);
+}
+
+template <typename _Tp>
+constexpr _Tp &&
+forward(typename remove_reference<_Tp>::type &__t) noexcept {
+ return static_cast<_Tp &&>(__t);
+}
+
+} // namespace std
+
+class NoMoveSemantics {
+ public:
+ NoMoveSemantics();
+ NoMoveSemantics(const NoMoveSemantics &);
+
+ NoMoveSemantics &operator=(const NoMoveSemantics &);
+};
+
+void callByConstRef(const NoMoveSemantics &);
+void callByConstRef(int i, const NoMoveSemantics &);
+
+void moveToConstReferencePositives() {
+ NoMoveSemantics obj;
+
+ // Basic case. It is here just to have a single "detected and fixed" case.
+ callByConstRef(std::move(obj));
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: passing result of std::move() as a const reference argument; no move will actually happen [performance-move-const-arg]
+ // CHECK-FIXES: callByConstRef(obj);
+}
+
+struct TriviallyCopyable {
+ int i;
+};
+
+void f(TriviallyCopyable) {}
+
+void g() {
+ TriviallyCopyable obj;
+ f(std::move(obj));
+}
+
+class MoveSemantics {
+ public:
+ MoveSemantics();
+ MoveSemantics(MoveSemantics &&);
+
+ MoveSemantics &operator=(MoveSemantics &&);
+};
+
+void fmovable(MoveSemantics);
+
+void lambda1() {
+ auto f = [](MoveSemantics m) {
+ fmovable(std::move(m));
+ };
+ f(MoveSemantics());
+}
+
+template<class T> struct function {};
+
+template<typename Result, typename... Args>
+class function<Result(Args...)> {
+public:
+ function() = default;
+ void operator()(Args... args) const {
+ fmovable(std::forward<Args>(args)...);
+ }
+};
+
+void functionInvocation() {
+ function<void(MoveSemantics)> callback;
+ MoveSemantics m;
+ callback(std::move(m));
+}
+
+void lambda2() {
+ function<void(MoveSemantics)> callback;
+
+ auto f = [callback = std::move(callback)](MoveSemantics m) mutable {
+ callback(std::move(m));
+ };
+ f(MoveSemantics());
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-move-const-arg.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-move-const-arg.cpp
new file mode 100644
index 0000000..06ed6e0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-move-const-arg.cpp
@@ -0,0 +1,248 @@
+// RUN: %check_clang_tidy %s performance-move-const-arg %t
+
+namespace std {
+template <typename>
+struct remove_reference;
+
+template <typename _Tp>
+struct remove_reference {
+ typedef _Tp type;
+};
+
+template <typename _Tp>
+struct remove_reference<_Tp &> {
+ typedef _Tp type;
+};
+
+template <typename _Tp>
+struct remove_reference<_Tp &&> {
+ typedef _Tp type;
+};
+
+template <typename _Tp>
+constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t) {
+ return static_cast<typename std::remove_reference<_Tp>::type &&>(__t);
+}
+
+template <typename _Tp>
+constexpr _Tp &&
+forward(typename remove_reference<_Tp>::type &__t) noexcept {
+ return static_cast<_Tp &&>(__t);
+}
+
+} // namespace std
+
+class A {
+public:
+ A() {}
+ A(const A &rhs) {}
+ A(A &&rhs) {}
+};
+
+struct TriviallyCopyable {
+ int i;
+};
+
+void f(TriviallyCopyable) {}
+
+void g() {
+ TriviallyCopyable obj;
+ f(std::move(obj));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: std::move of the variable 'obj' of the trivially-copyable type 'TriviallyCopyable' has no effect; remove std::move() [performance-move-const-arg]
+ // CHECK-FIXES: f(obj);
+}
+
+int f1() {
+ return std::move(42);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: std::move of the expression of the trivially-copyable type 'int' has no effect; remove std::move() [performance-move-const-arg]
+ // CHECK-FIXES: return 42;
+}
+
+int f2(int x2) {
+ return std::move(x2);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: std::move of the variable 'x2' of the trivially-copyable type 'int'
+ // CHECK-FIXES: return x2;
+}
+
+int *f3(int *x3) {
+ return std::move(x3);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: std::move of the variable 'x3' of the trivially-copyable type 'int *'
+ // CHECK-FIXES: return x3;
+}
+
+A f4(A x4) { return std::move(x4); }
+
+A f5(const A x5) {
+ return std::move(x5);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: std::move of the const variable 'x5' has no effect; remove std::move() or make the variable non-const [performance-move-const-arg]
+ // CHECK-FIXES: return x5;
+}
+
+template <typename T>
+T f6(const T x6) {
+ return std::move(x6);
+}
+
+void f7() { int a = f6(10); }
+
+#define M1(x) x
+void f8() {
+ const A a;
+ M1(A b = std::move(a);)
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: std::move of the const variable 'a' has no effect; remove std::move() or make the variable non-const
+ // CHECK-FIXES: M1(A b = a;)
+}
+
+#define M2(x) std::move(x)
+int f9() { return M2(1); }
+
+template <typename T>
+T f10(const int x10) {
+ return std::move(x10);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: std::move of the const variable 'x10' of the trivially-copyable type 'const int' has no effect; remove std::move() [performance-move-const-arg]
+ // CHECK-FIXES: return x10;
+}
+void f11() {
+ f10<int>(1);
+ f10<double>(1);
+}
+
+class NoMoveSemantics {
+public:
+ NoMoveSemantics();
+ NoMoveSemantics(const NoMoveSemantics &);
+
+ NoMoveSemantics &operator=(const NoMoveSemantics &);
+};
+
+void callByConstRef(const NoMoveSemantics &);
+void callByConstRef(int i, const NoMoveSemantics &);
+
+void moveToConstReferencePositives() {
+ NoMoveSemantics obj;
+
+ // Basic case.
+ callByConstRef(std::move(obj));
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: passing result of std::move() as
+ // CHECK-FIXES: callByConstRef(obj);
+
+ // Also works for second argument.
+ callByConstRef(1, std::move(obj));
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: passing result of std::move() as
+ // CHECK-FIXES: callByConstRef(1, obj);
+
+ // Works if std::move() applied to a temporary.
+ callByConstRef(std::move(NoMoveSemantics()));
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: passing result of std::move() as
+ // CHECK-FIXES: callByConstRef(NoMoveSemantics());
+
+ // Works if calling a copy constructor.
+ NoMoveSemantics other(std::move(obj));
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: passing result of std::move() as
+ // CHECK-FIXES: NoMoveSemantics other(obj);
+
+ // Works if calling assignment operator.
+ other = std::move(obj);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: passing result of std::move() as
+ // CHECK-FIXES: other = obj;
+}
+
+class MoveSemantics {
+public:
+ MoveSemantics();
+ MoveSemantics(MoveSemantics &&);
+
+ MoveSemantics &operator=(MoveSemantics &&);
+};
+
+void callByValue(MoveSemantics);
+
+void callByRValueRef(MoveSemantics &&);
+
+template <class T>
+void templateFunction(T obj) {
+ T other = std::move(obj);
+}
+
+#define M3(T, obj) \
+ do { \
+ T other = std::move(obj); \
+ } while (true)
+
+#define CALL(func) (func)()
+
+void moveToConstReferenceNegatives() {
+ // No warning when actual move takes place.
+ MoveSemantics move_semantics;
+ callByValue(std::move(move_semantics));
+ callByRValueRef(std::move(move_semantics));
+ MoveSemantics other(std::move(move_semantics));
+ other = std::move(move_semantics);
+
+ // No warning if std::move() not used.
+ NoMoveSemantics no_move_semantics;
+ callByConstRef(no_move_semantics);
+
+ // No warning if instantiating a template.
+ templateFunction(no_move_semantics);
+
+ // No warning inside of macro expansions.
+ M3(NoMoveSemantics, no_move_semantics);
+
+ // No warning inside of macro expansion, even if the macro expansion is inside
+ // a lambda that is, in turn, an argument to a macro.
+ CALL([no_move_semantics] { M3(NoMoveSemantics, no_move_semantics); });
+
+ auto lambda = [] {};
+ auto lambda2 = std::move(lambda);
+}
+
+class MoveOnly {
+public:
+ MoveOnly(const MoveOnly &other) = delete;
+ MoveOnly &operator=(const MoveOnly &other) = delete;
+ MoveOnly(MoveOnly &&other) = default;
+ MoveOnly &operator=(MoveOnly &&other) = default;
+};
+template <class T>
+void Q(T);
+void moveOnlyNegatives(MoveOnly val) {
+ Q(std::move(val));
+}
+
+void fmovable(MoveSemantics);
+
+void lambda1() {
+ auto f = [](MoveSemantics m) {
+ fmovable(std::move(m));
+ };
+ f(MoveSemantics());
+}
+
+template<class T> struct function {};
+
+template<typename Result, typename... Args>
+class function<Result(Args...)> {
+public:
+ function() = default;
+ void operator()(Args... args) const {
+ fmovable(std::forward<Args>(args)...);
+ }
+};
+
+void functionInvocation() {
+ function<void(MoveSemantics)> callback;
+ MoveSemantics m;
+ callback(std::move(m));
+}
+
+void lambda2() {
+ function<void(MoveSemantics)> callback;
+
+ auto f = [callback = std::move(callback)](MoveSemantics m) mutable {
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: std::move of the variable 'callback' of the trivially-copyable type 'function<void (MoveSemantics)>' has no effect; remove std::move()
+ // CHECK-FIXES: auto f = [callback = callback](MoveSemantics m) mutable {
+ callback(std::move(m));
+ };
+ f(MoveSemantics());
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-move-constructor-init.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-move-constructor-init.cpp
new file mode 100644
index 0000000..c9ed346
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-move-constructor-init.cpp
@@ -0,0 +1,154 @@
+// RUN: %check_clang_tidy %s performance-move-constructor-init,modernize-pass-by-value %t -- \
+// RUN: -config='{CheckOptions: \
+// RUN: [{key: modernize-pass-by-value.ValuesOnly, value: 1}]}' \
+// RUN: -- -std=c++11 -isystem %S/Inputs/Headers
+
+#include <s.h>
+
+// CHECK-FIXES: #include <utility>
+
+template <class T> struct remove_reference {typedef T type;};
+template <class T> struct remove_reference<T&> {typedef T type;};
+template <class T> struct remove_reference<T&&> {typedef T type;};
+
+template <typename T>
+typename remove_reference<T>::type&& move(T&& arg) {
+ return static_cast<typename remove_reference<T>::type&&>(arg);
+}
+
+struct C {
+ C() = default;
+ C(const C&) = default;
+};
+
+struct B {
+ B() {}
+ B(const B&) {}
+ B(B &&) {}
+};
+
+struct D : B {
+ D() : B() {}
+ D(const D &RHS) : B(RHS) {}
+ // CHECK-MESSAGES: :[[@LINE+3]]:16: warning: move constructor initializes base class by calling a copy constructor [performance-move-constructor-init]
+ // CHECK-MESSAGES: 26:3: note: copy constructor being called
+ // CHECK-MESSAGES: 27:3: note: candidate move constructor here
+ D(D &&RHS) : B(RHS) {}
+};
+
+struct E : B {
+ E() : B() {}
+ E(const E &RHS) : B(RHS) {}
+ E(E &&RHS) : B(move(RHS)) {} // ok
+};
+
+struct F {
+ C M;
+
+ F(F &&) : M(C()) {} // ok
+};
+
+struct G {
+ G() = default;
+ G(const G&) = default;
+ G(G&&) = delete;
+};
+
+struct H : G {
+ H() = default;
+ H(const H&) = default;
+ H(H &&RHS) : G(RHS) {} // ok
+};
+
+struct I {
+ I(const I &) = default; // suppresses move constructor creation
+};
+
+struct J : I {
+ J(J &&RHS) : I(RHS) {} // ok
+};
+
+struct K {}; // Has implicit copy and move constructors, is trivially copyable
+struct L : K {
+ L(L &&RHS) : K(RHS) {} // ok
+};
+
+struct M {
+ B Mem;
+ // CHECK-MESSAGES: :[[@LINE+1]]:16: warning: move constructor initializes class member by calling a copy constructor [performance-move-constructor-init]
+ M(M &&RHS) : Mem(RHS.Mem) {}
+};
+
+struct N {
+ B Mem;
+ N(N &&RHS) : Mem(move(RHS.Mem)) {}
+};
+
+struct O {
+ O(O&& other) : b(other.b) {} // ok
+ const B b;
+};
+
+struct P {
+ P(O&& other) : b(other.b) {} // ok
+ B b;
+};
+
+struct Movable {
+ Movable(Movable &&) = default;
+ Movable(const Movable &) = default;
+ Movable &operator=(const Movable &) = default;
+ ~Movable() {}
+};
+
+struct TriviallyCopyable {
+ TriviallyCopyable() = default;
+ TriviallyCopyable(TriviallyCopyable &&) = default;
+ TriviallyCopyable(const TriviallyCopyable &) = default;
+};
+
+struct Positive {
+ Positive(Movable M) : M_(M) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: pass by value and use std::move [modernize-pass-by-value]
+ // CHECK-FIXES: Positive(Movable M) : M_(std::move(M)) {}
+ Movable M_;
+};
+
+struct NegativeMultipleInitializerReferences {
+ NegativeMultipleInitializerReferences(Movable M) : M_(M), n_(M) {}
+ Movable M_;
+ Movable n_;
+};
+
+struct NegativeReferencedInConstructorBody {
+ NegativeReferencedInConstructorBody(Movable M) : M_(M) { M_ = M; }
+ Movable M_;
+};
+
+struct NegativeParamTriviallyCopyable {
+ NegativeParamTriviallyCopyable(TriviallyCopyable T) : T_(T) {}
+ NegativeParamTriviallyCopyable(int I) : I_(I) {}
+
+ TriviallyCopyable T_;
+ int I_;
+};
+
+struct NegativeNotPassedByValue {
+ // This const ref constructor isn't warned about because the ValuesOnly option is set.
+ NegativeNotPassedByValue(const Movable &M) : M_(M) {}
+ NegativeNotPassedByValue(const Movable M) : M_(M) {}
+ NegativeNotPassedByValue(Movable &M) : M_(M) {}
+ NegativeNotPassedByValue(Movable *M) : M_(*M) {}
+ NegativeNotPassedByValue(const Movable *M) : M_(*M) {}
+ Movable M_;
+};
+
+struct Immovable {
+ Immovable(const Immovable &) = default;
+ Immovable(Immovable &&) = delete;
+};
+
+struct NegativeImmovableParameter {
+ NegativeImmovableParameter(Immovable I) : I_(I) {}
+ Immovable I_;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-noexcept-move-constructor.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-noexcept-move-constructor.cpp
new file mode 100644
index 0000000..70d7065
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-noexcept-move-constructor.cpp
@@ -0,0 +1,54 @@
+// RUN: %check_clang_tidy %s performance-noexcept-move-constructor %t
+
+class A {
+ A(A &&);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor]
+ A &operator=(A &&);
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should
+};
+
+struct B {
+ static constexpr bool kFalse = false;
+ B(B &&) noexcept(kFalse);
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor]
+};
+
+class OK {};
+
+void f() {
+ OK a;
+ a = OK();
+}
+
+class OK1 {
+public:
+ OK1();
+ OK1(const OK1 &);
+ OK1(OK1 &&) noexcept;
+ OK1 &operator=(OK1 &&) noexcept;
+ void f();
+ void g() noexcept;
+};
+
+class OK2 {
+ static constexpr bool kTrue = true;
+
+public:
+ OK2(OK2 &&) noexcept(true) {}
+ OK2 &operator=(OK2 &&) noexcept(kTrue) { return *this; }
+};
+
+struct OK3 {
+ OK3(OK3 &&) noexcept(false) {}
+ OK3 &operator=(OK3 &&) = delete;
+};
+
+struct OK4 {
+ OK4(OK4 &&) noexcept = default;
+ OK4 &operator=(OK4 &&) noexcept = default;
+};
+
+struct OK5 {
+ OK5(OK5 &&) noexcept(true) = default;
+ OK5 &operator=(OK5 &&) noexcept(true) = default;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-type-promotion-in-math-fn.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-type-promotion-in-math-fn.cpp
new file mode 100644
index 0000000..b2da7cc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-type-promotion-in-math-fn.cpp
@@ -0,0 +1,316 @@
+// RUN: %check_clang_tidy %s performance-type-promotion-in-math-fn %t
+
+// CHECK-FIXES: #include <cmath>
+
+double acos(double);
+double acosh(double);
+double asin(double);
+double asinh(double);
+double atan2(double, double);
+double atan(double);
+double atanh(double);
+double cbrt(double);
+double ceil(double);
+double copysign(double, double);
+double cos(double);
+double cosh(double);
+double erfc(double);
+double erf(double);
+double exp2(double);
+double exp(double);
+double expm1(double);
+double fabs(double);
+double fdim(double, double);
+double floor(double);
+double fma(double, double, double);
+double fmax(double, double);
+double fmin(double, double);
+double fmod(double, double);
+double frexp(double, int *);
+double hypot(double, double);
+double ilogb(double);
+double ldexp(double, double);
+double lgamma(double);
+long long llrint(double);
+double log10(double);
+double log1p(double);
+double log2(double);
+double logb(double);
+double log(double);
+long lrint(double);
+double modf(double);
+double nearbyint(double);
+double nextafter(double, double);
+double nexttoward(double, long double);
+double pow(double, double);
+double remainder(double, double);
+double remquo(double, double, int *);
+double rint(double);
+double round(double);
+double scalbln(double, long);
+double scalbn(double, int);
+double sin(double);
+double sinh(double);
+double sqrt(double);
+double tan(double);
+double tanh(double);
+double tgamma(double);
+double trunc(double);
+long long llround(double);
+long lround(double);
+
+void check_all_fns() {
+ float a, b, c;
+ int i;
+ long l;
+ int *int_ptr;
+
+ acos(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'acos' promotes float to double [performance-type-promotion-in-math-fn]
+ // CHECK-FIXES: {{^}} std::acos(a);{{$}}
+ acosh(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'acosh'
+ // CHECK-FIXES: {{^}} std::acosh(a);{{$}}
+ asin(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'asin'
+ // CHECK-FIXES: {{^}} std::asin(a);{{$}}
+ asinh(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'asinh'
+ // CHECK-FIXES: {{^}} std::asinh(a);{{$}}
+ atan2(a, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'atan2'
+ // CHECK-FIXES: {{^}} std::atan2(a, b);{{$}}
+ atan(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'atan'
+ // CHECK-FIXES: {{^}} std::atan(a);{{$}}
+ atanh(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'atanh'
+ // CHECK-FIXES: {{^}} std::atanh(a);{{$}}
+ cbrt(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'cbrt'
+ // CHECK-FIXES: {{^}} std::cbrt(a);{{$}}
+ ceil(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'ceil'
+ // CHECK-FIXES: {{^}} std::ceil(a);{{$}}
+ copysign(a, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'copysign'
+ // CHECK-FIXES: {{^}} std::copysign(a, b);{{$}}
+ cos(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'cos'
+ // CHECK-FIXES: {{^}} std::cos(a);{{$}}
+ cosh(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'cosh'
+ // CHECK-FIXES: {{^}} std::cosh(a);{{$}}
+ erf(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'erf'
+ // CHECK-FIXES: {{^}} std::erf(a);{{$}}
+ erfc(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'erfc'
+ // CHECK-FIXES: {{^}} std::erfc(a);{{$}}
+ exp2(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'exp2'
+ // CHECK-FIXES: {{^}} std::exp2(a);{{$}}
+ exp(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'exp'
+ // CHECK-FIXES: {{^}} std::exp(a);{{$}}
+ expm1(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'expm1'
+ // CHECK-FIXES: {{^}} std::expm1(a);{{$}}
+ fabs(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fabs'
+ // CHECK-FIXES: {{^}} std::fabs(a);{{$}}
+ fdim(a, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fdim'
+ // CHECK-FIXES: {{^}} std::fdim(a, b);{{$}}
+ floor(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'floor'
+ // CHECK-FIXES: {{^}} std::floor(a);{{$}}
+ fma(a, b, c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fma'
+ // CHECK-FIXES: {{^}} std::fma(a, b, c);{{$}}
+ fmax(a, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fmax'
+ // CHECK-FIXES: {{^}} std::fmax(a, b);{{$}}
+ fmin(a, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fmin'
+ // CHECK-FIXES: {{^}} std::fmin(a, b);{{$}}
+ fmod(a, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fmod'
+ // CHECK-FIXES: {{^}} std::fmod(a, b);{{$}}
+ frexp(a, int_ptr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'frexp'
+ // CHECK-FIXES: {{^}} std::frexp(a, int_ptr);{{$}}
+ hypot(a, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'hypot'
+ // CHECK-FIXES: {{^}} std::hypot(a, b);{{$}}
+ ilogb(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'ilogb'
+ // CHECK-FIXES: {{^}} std::ilogb(a);{{$}}
+ ldexp(a, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'ldexp'
+ // CHECK-FIXES: {{^}} std::ldexp(a, b);{{$}}
+ lgamma(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'lgamma'
+ // CHECK-FIXES: {{^}} std::lgamma(a);{{$}}
+ llrint(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'llrint'
+ // CHECK-FIXES: {{^}} std::llrint(a);{{$}}
+ llround(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'llround'
+ // CHECK-FIXES: {{^}} std::llround(a);{{$}}
+ log10(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log10'
+ // CHECK-FIXES: {{^}} std::log10(a);{{$}}
+ log1p(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log1p'
+ // CHECK-FIXES: {{^}} std::log1p(a);{{$}}
+ log2(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log2'
+ // CHECK-FIXES: {{^}} std::log2(a);{{$}}
+ log(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log'
+ // CHECK-FIXES: {{^}} std::log(a);{{$}}
+ logb(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'logb'
+ // CHECK-FIXES: {{^}} std::logb(a);{{$}}
+ lrint(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'lrint'
+ // CHECK-FIXES: {{^}} std::lrint(a);{{$}}
+ lround(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'lround'
+ // CHECK-FIXES: {{^}} std::lround(a);{{$}}
+ nearbyint(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nearbyint'
+ // CHECK-FIXES: {{^}} std::nearbyint(a);{{$}}
+ nextafter(a, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nextafter'
+ // CHECK-FIXES: {{^}} std::nextafter(a, b);{{$}}
+ nexttoward(a, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
+ // CHECK-FIXES: {{^}} std::nexttoward(a, b);{{$}}
+ pow(a, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'pow'
+ // CHECK-FIXES: {{^}} std::pow(a, b);{{$}}
+ remainder(a, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'remainder'
+ // CHECK-FIXES: {{^}} std::remainder(a, b);{{$}}
+ remquo(a, b, int_ptr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'remquo'
+ // CHECK-FIXES: {{^}} std::remquo(a, b, int_ptr);{{$}}
+ rint(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'rint'
+ // CHECK-FIXES: {{^}} std::rint(a);{{$}}
+ round(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'round'
+ // CHECK-FIXES: {{^}} std::round(a);{{$}}
+ scalbln(a, l);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbln'
+ // CHECK-FIXES: {{^}} std::scalbln(a, l);{{$}}
+ scalbn(a, i);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbn'
+ // CHECK-FIXES: {{^}} std::scalbn(a, i);{{$}}
+ sin(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'sin'
+ // CHECK-FIXES: {{^}} std::sin(a);{{$}}
+ sinh(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'sinh'
+ // CHECK-FIXES: {{^}} std::sinh(a);{{$}}
+ sqrt(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'sqrt'
+ // CHECK-FIXES: {{^}} std::sqrt(a);{{$}}
+ tan(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'tan'
+ // CHECK-FIXES: {{^}} std::tan(a);{{$}}
+ tanh(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'tanh'
+ // CHECK-FIXES: {{^}} std::tanh(a);{{$}}
+ tgamma(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'tgamma'
+ // CHECK-FIXES: {{^}} std::tgamma(a);{{$}}
+ trunc(a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'trunc'
+ // CHECK-FIXES: {{^}} std::trunc(a);{{$}}
+}
+
+// nexttoward/nexttowardf are weird -- the second param is always long double.
+// So we warn if the first arg is a float, regardless of what the second arg is.
+void check_nexttoward() {
+ nexttoward(0.f, 0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
+ // CHECK-FIXES: {{^}} std::nexttoward(0.f, 0);{{$}}
+ nexttoward(0.f, 0l);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
+ // CHECK-FIXES: {{^}} std::nexttoward(0.f, 0l);{{$}}
+ nexttoward(0.f, 0.f);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
+ // CHECK-FIXES: {{^}} std::nexttoward(0.f, 0.f);{{$}}
+ nexttoward(0.f, 0.);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
+ // CHECK-FIXES: {{^}} std::nexttoward(0.f, 0.);{{$}}
+
+ // No warnings for these.
+ nexttoward(0., 0);
+ nexttoward(0., 0.f);
+ nexttoward(0., 0.);
+}
+
+// The second parameter to scalbn and scalbnf is an int, so we don't care what
+// type you pass as that argument; we warn iff the first argument is a float.
+void check_scalbn() {
+ scalbn(0.f, 0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbn'
+ // CHECK-FIXES: {{^}} std::scalbn(0.f, 0);{{$}}
+ scalbn(0.f, static_cast<char>(0));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbn'
+ // CHECK-FIXES: {{^}} std::scalbn(0.f, static_cast<char>(0));{{$}}
+
+ // No warnings for these.
+ scalbn(0., 0);
+ scalbn(0., static_cast<char>(0));
+}
+
+// scalbln/scalblnf are like scalbn/scalbnf except their second arg is a long.
+// Again, doesn't matter what we pass for the second arg; we warn iff the first
+// arg is a float.
+void check_scalbln() {
+ scalbln(0.f, 0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbln'
+ // CHECK-FIXES: {{^}} std::scalbln(0.f, 0);{{$}}
+ scalbln(0.f, 0l);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbln'
+ // CHECK-FIXES: {{^}} std::scalbln(0.f, 0l);{{$}}
+
+ // No warnings for these.
+ scalbln(0., 0);
+ scalbln(0., 0l);
+}
+
+float cosf(float);
+double foo(double); // not a math.h function
+float cos(float); // not a math.h function (wrong signature)
+double cos(double, double); // not a math.h function (wrong signature)
+
+namespace std {
+void cos(float);
+} // namespace std
+
+void check_no_warnings() {
+ foo(0.); // no warning because not a math.h function.
+
+ sin(0); // no warning because arg is an int
+ cos(0.); // no warning because arg is a double
+ std::cos(0.f); // no warning because not ::cos.
+ cosf(0.f); // no warning; we expect this to take a float
+ cos(0.f); // does not match the expected signature of ::cos
+ cos(0.f, 0.f); // does not match the expected signature of ::cos
+
+ // No warnings because all args are not floats.
+ remainder(0., 0.f);
+ remainder(0.f, 0.);
+ remainder(0, 0.f);
+ remainder(0.f, 0);
+ fma(0.f, 0.f, 0);
+ fma(0.f, 0.f, 0.);
+ fma(0.f, 0., 0.f);
+ fma(0., 0.f, 0.f);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-copy-initialization.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-copy-initialization.cpp
new file mode 100644
index 0000000..50dcfd8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-copy-initialization.cpp
@@ -0,0 +1,389 @@
+// RUN: %check_clang_tidy %s performance-unnecessary-copy-initialization %t
+
+struct ExpensiveToCopyType {
+ ExpensiveToCopyType();
+ virtual ~ExpensiveToCopyType();
+ const ExpensiveToCopyType &reference() const;
+ void nonConstMethod();
+ bool constMethod() const;
+};
+
+struct TrivialToCopyType {
+ const TrivialToCopyType &reference() const;
+};
+
+struct WeirdCopyCtorType {
+ WeirdCopyCtorType();
+ WeirdCopyCtorType(const WeirdCopyCtorType &w, bool oh_yes = true);
+
+ void nonConstMethod();
+ bool constMethod() const;
+};
+
+ExpensiveToCopyType global_expensive_to_copy_type;
+
+const ExpensiveToCopyType &ExpensiveTypeReference();
+const TrivialToCopyType &TrivialTypeReference();
+
+void mutate(ExpensiveToCopyType &);
+void mutate(ExpensiveToCopyType *);
+void useAsConstPointer(const ExpensiveToCopyType *);
+void useAsConstReference(const ExpensiveToCopyType &);
+void useByValue(ExpensiveToCopyType);
+
+void PositiveFunctionCall() {
+ const auto AutoAssigned = ExpensiveTypeReference();
+ // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned' is copy-constructed from a const reference; consider making it a const reference [performance-unnecessary-copy-initialization]
+ // CHECK-FIXES: const auto& AutoAssigned = ExpensiveTypeReference();
+ const auto AutoCopyConstructed(ExpensiveTypeReference());
+ // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
+ // CHECK-FIXES: const auto& AutoCopyConstructed(ExpensiveTypeReference());
+ const ExpensiveToCopyType VarAssigned = ExpensiveTypeReference();
+ // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
+ // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = ExpensiveTypeReference();
+ const ExpensiveToCopyType VarCopyConstructed(ExpensiveTypeReference());
+ // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
+ // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(ExpensiveTypeReference());
+}
+
+void PositiveMethodCallConstReferenceParam(const ExpensiveToCopyType &Obj) {
+ const auto AutoAssigned = Obj.reference();
+ // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
+ // CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
+ const auto AutoCopyConstructed(Obj.reference());
+ // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
+ // CHECK-FIXES: const auto& AutoCopyConstructed(Obj.reference());
+ const ExpensiveToCopyType VarAssigned = Obj.reference();
+ // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
+ // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = Obj.reference();
+ const ExpensiveToCopyType VarCopyConstructed(Obj.reference());
+ // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
+ // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(Obj.reference());
+}
+
+void PositiveMethodCallConstParam(const ExpensiveToCopyType Obj) {
+ const auto AutoAssigned = Obj.reference();
+ // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
+ // CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
+ const auto AutoCopyConstructed(Obj.reference());
+ // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
+ // CHECK-FIXES: const auto& AutoCopyConstructed(Obj.reference());
+ const ExpensiveToCopyType VarAssigned = Obj.reference();
+ // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
+ // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = Obj.reference();
+ const ExpensiveToCopyType VarCopyConstructed(Obj.reference());
+ // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
+ // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(Obj.reference());
+}
+
+void PositiveMethodCallConstPointerParam(const ExpensiveToCopyType *const Obj) {
+ const auto AutoAssigned = Obj->reference();
+ // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
+ // CHECK-FIXES: const auto& AutoAssigned = Obj->reference();
+ const auto AutoCopyConstructed(Obj->reference());
+ // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
+ // CHECK-FIXES: const auto& AutoCopyConstructed(Obj->reference());
+ const ExpensiveToCopyType VarAssigned = Obj->reference();
+ // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
+ // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = Obj->reference();
+ const ExpensiveToCopyType VarCopyConstructed(Obj->reference());
+ // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
+ // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(Obj->reference());
+}
+
+void PositiveLocalConstValue() {
+ const ExpensiveToCopyType Obj;
+ const auto UnnecessaryCopy = Obj.reference();
+ // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy'
+ // CHECK-FIXES: const auto& UnnecessaryCopy = Obj.reference();
+}
+
+void PositiveLocalConstRef() {
+ const ExpensiveToCopyType Obj;
+ const ExpensiveToCopyType &ConstReference = Obj.reference();
+ const auto UnnecessaryCopy = ConstReference.reference();
+ // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy'
+ // CHECK-FIXES: const auto& UnnecessaryCopy = ConstReference.reference();
+}
+
+void PositiveLocalConstPointer() {
+ const ExpensiveToCopyType Obj;
+ const ExpensiveToCopyType *const ConstPointer = &Obj;
+ const auto UnnecessaryCopy = ConstPointer->reference();
+ // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy'
+ // CHECK-FIXES: const auto& UnnecessaryCopy = ConstPointer->reference();
+}
+
+void NegativeFunctionCallTrivialType() {
+ const auto AutoAssigned = TrivialTypeReference();
+ const auto AutoCopyConstructed(TrivialTypeReference());
+ const TrivialToCopyType VarAssigned = TrivialTypeReference();
+ const TrivialToCopyType VarCopyConstructed(TrivialTypeReference());
+}
+
+void NegativeStaticLocalVar(const ExpensiveToCopyType &Obj) {
+ static const auto StaticVar = Obj.reference();
+}
+
+void PositiveFunctionCallExpensiveTypeNonConstVariable() {
+ auto AutoAssigned = ExpensiveTypeReference();
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'AutoAssigned' is copy-constructed from a const reference but is only used as const reference; consider making it a const reference [performance-unnecessary-copy-initialization]
+ // CHECK-FIXES: const auto& AutoAssigned = ExpensiveTypeReference();
+ auto AutoCopyConstructed(ExpensiveTypeReference());
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'AutoCopyConstructed'
+ // CHECK-FIXES: const auto& AutoCopyConstructed(ExpensiveTypeReference());
+ ExpensiveToCopyType VarAssigned = ExpensiveTypeReference();
+ // CHECK-MESSAGES: [[@LINE-1]]:23: warning: the variable 'VarAssigned'
+ // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = ExpensiveTypeReference();
+ ExpensiveToCopyType VarCopyConstructed(ExpensiveTypeReference());
+ // CHECK-MESSAGES: [[@LINE-1]]:23: warning: the variable 'VarCopyConstructed'
+ // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(ExpensiveTypeReference());
+}
+
+void positiveNonConstVarInCodeBlock(const ExpensiveToCopyType &Obj) {
+ {
+ auto Assigned = Obj.reference();
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: the variable 'Assigned'
+ // CHECK-FIXES: const auto& Assigned = Obj.reference();
+ Assigned.reference();
+ useAsConstReference(Assigned);
+ useByValue(Assigned);
+ }
+}
+
+void negativeNonConstVarWithNonConstUse(const ExpensiveToCopyType &Obj) {
+ {
+ auto NonConstInvoked = Obj.reference();
+ // CHECK-FIXES: auto NonConstInvoked = Obj.reference();
+ NonConstInvoked.nonConstMethod();
+ }
+ {
+ auto Reassigned = Obj.reference();
+ // CHECK-FIXES: auto Reassigned = Obj.reference();
+ Reassigned = ExpensiveToCopyType();
+ }
+ {
+ auto MutatedByReference = Obj.reference();
+ // CHECK-FIXES: auto MutatedByReference = Obj.reference();
+ mutate(MutatedByReference);
+ }
+ {
+ auto MutatedByPointer = Obj.reference();
+ // CHECK-FIXES: auto MutatedByPointer = Obj.reference();
+ mutate(&MutatedByPointer);
+ }
+}
+
+void PositiveMethodCallNonConstRefNotModified(ExpensiveToCopyType &Obj) {
+ const auto AutoAssigned = Obj.reference();
+ // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
+ // CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
+}
+
+void NegativeMethodCallNonConstRefIsModified(ExpensiveToCopyType &Obj) {
+ const auto AutoAssigned = Obj.reference();
+ const auto AutoCopyConstructed(Obj.reference());
+ const ExpensiveToCopyType VarAssigned = Obj.reference();
+ const ExpensiveToCopyType VarCopyConstructed(Obj.reference());
+ mutate(&Obj);
+}
+
+void PositiveMethodCallNonConstNotModified(ExpensiveToCopyType Obj) {
+ const auto AutoAssigned = Obj.reference();
+ // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
+ // CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
+}
+
+void NegativeMethodCallNonConstValueArgumentIsModified(ExpensiveToCopyType Obj) {
+ Obj.nonConstMethod();
+ const auto AutoAssigned = Obj.reference();
+}
+
+void PositiveMethodCallNonConstPointerNotModified(ExpensiveToCopyType *const Obj) {
+ const auto AutoAssigned = Obj->reference();
+ // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
+ // CHECK-FIXES: const auto& AutoAssigned = Obj->reference();
+ Obj->constMethod();
+}
+
+void NegativeMethodCallNonConstPointerIsModified(ExpensiveToCopyType *const Obj) {
+ const auto AutoAssigned = Obj->reference();
+ const auto AutoCopyConstructed(Obj->reference());
+ const ExpensiveToCopyType VarAssigned = Obj->reference();
+ const ExpensiveToCopyType VarCopyConstructed(Obj->reference());
+ mutate(Obj);
+}
+
+void PositiveLocalVarIsNotModified() {
+ ExpensiveToCopyType LocalVar;
+ const auto AutoAssigned = LocalVar.reference();
+ // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
+ // CHECK-FIXES: const auto& AutoAssigned = LocalVar.reference();
+}
+
+void NegativeLocalVarIsModified() {
+ ExpensiveToCopyType Obj;
+ const auto AutoAssigned = Obj.reference();
+ Obj = AutoAssigned;
+}
+
+struct NegativeConstructor {
+ NegativeConstructor(const ExpensiveToCopyType &Obj) : Obj(Obj) {}
+ ExpensiveToCopyType Obj;
+};
+
+#define UNNECESSARY_COPY_INIT_IN_MACRO_BODY(TYPE) \
+ void functionWith##TYPE(const TYPE &T) { \
+ auto AssignedInMacro = T.reference(); \
+ } \
+// Ensure fix is not applied.
+// CHECK-FIXES: auto AssignedInMacro = T.reference();
+
+UNNECESSARY_COPY_INIT_IN_MACRO_BODY(ExpensiveToCopyType)
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: the variable 'AssignedInMacro' is copy-constructed
+
+#define UNNECESSARY_COPY_INIT_IN_MACRO_ARGUMENT(ARGUMENT) ARGUMENT
+
+void PositiveMacroArgument(const ExpensiveToCopyType &Obj) {
+ UNNECESSARY_COPY_INIT_IN_MACRO_ARGUMENT(auto CopyInMacroArg = Obj.reference());
+ // CHECK-MESSAGES: [[@LINE-1]]:48: warning: the variable 'CopyInMacroArg' is copy-constructed
+ // Ensure fix is not applied.
+ // CHECK-FIXES: auto CopyInMacroArg = Obj.reference()
+}
+
+void PositiveLocalCopyConstMethodInvoked() {
+ ExpensiveToCopyType orig;
+ ExpensiveToCopyType copy_1 = orig;
+ // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_1' of the variable 'orig' is never modified; consider avoiding the copy [performance-unnecessary-copy-initialization]
+ // CHECK-FIXES: const ExpensiveToCopyType& copy_1 = orig;
+ copy_1.constMethod();
+ orig.constMethod();
+}
+
+void PositiveLocalCopyUsingExplicitCopyCtor() {
+ ExpensiveToCopyType orig;
+ ExpensiveToCopyType copy_2(orig);
+ // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_2'
+ // CHECK-FIXES: const ExpensiveToCopyType& copy_2(orig);
+ copy_2.constMethod();
+ orig.constMethod();
+}
+
+void PositiveLocalCopyCopyIsArgument(const ExpensiveToCopyType &orig) {
+ ExpensiveToCopyType copy_3 = orig;
+ // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_3'
+ // CHECK-FIXES: const ExpensiveToCopyType& copy_3 = orig;
+ copy_3.constMethod();
+}
+
+void PositiveLocalCopyUsedAsConstRef() {
+ ExpensiveToCopyType orig;
+ ExpensiveToCopyType copy_4 = orig;
+ // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_4'
+ // CHECK-FIXES: const ExpensiveToCopyType& copy_4 = orig;
+ useAsConstReference(orig);
+}
+
+void PositiveLocalCopyTwice() {
+ ExpensiveToCopyType orig;
+ ExpensiveToCopyType copy_5 = orig;
+ // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_5'
+ // CHECK-FIXES: const ExpensiveToCopyType& copy_5 = orig;
+ ExpensiveToCopyType copy_6 = copy_5;
+ // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_6'
+ // CHECK-FIXES: const ExpensiveToCopyType& copy_6 = copy_5;
+ copy_5.constMethod();
+ copy_6.constMethod();
+ orig.constMethod();
+}
+
+
+void PositiveLocalCopyWeirdCopy() {
+ WeirdCopyCtorType orig;
+ WeirdCopyCtorType weird_1(orig);
+ // CHECK-MESSAGES: [[@LINE-1]]:21: warning: local copy 'weird_1'
+ // CHECK-FIXES: const WeirdCopyCtorType& weird_1(orig);
+ weird_1.constMethod();
+
+ WeirdCopyCtorType weird_2 = orig;
+ // CHECK-MESSAGES: [[@LINE-1]]:21: warning: local copy 'weird_2'
+ // CHECK-FIXES: const WeirdCopyCtorType& weird_2 = orig;
+ weird_2.constMethod();
+}
+
+void NegativeLocalCopySimpleTypes() {
+ int i1 = 0;
+ int i2 = i1;
+}
+
+void NegativeLocalCopyCopyIsModified() {
+ ExpensiveToCopyType orig;
+ ExpensiveToCopyType neg_copy_1 = orig;
+ neg_copy_1.nonConstMethod();
+}
+
+void NegativeLocalCopyOriginalIsModified() {
+ ExpensiveToCopyType orig;
+ ExpensiveToCopyType neg_copy_2 = orig;
+ orig.nonConstMethod();
+}
+
+void NegativeLocalCopyUsedAsRefArg() {
+ ExpensiveToCopyType orig;
+ ExpensiveToCopyType neg_copy_3 = orig;
+ mutate(neg_copy_3);
+}
+
+void NegativeLocalCopyUsedAsPointerArg() {
+ ExpensiveToCopyType orig;
+ ExpensiveToCopyType neg_copy_4 = orig;
+ mutate(&neg_copy_4);
+}
+
+void NegativeLocalCopyCopyFromGlobal() {
+ ExpensiveToCopyType neg_copy_5 = global_expensive_to_copy_type;
+}
+
+void NegativeLocalCopyCopyToStatic() {
+ ExpensiveToCopyType orig;
+ static ExpensiveToCopyType neg_copy_6 = orig;
+}
+
+void NegativeLocalCopyNonConstInForLoop() {
+ ExpensiveToCopyType orig;
+ for (ExpensiveToCopyType neg_copy_7 = orig; orig.constMethod();
+ orig.nonConstMethod()) {
+ orig.constMethod();
+ }
+}
+
+void NegativeLocalCopyWeirdNonCopy() {
+ WeirdCopyCtorType orig;
+ WeirdCopyCtorType neg_weird_1(orig, false);
+ WeirdCopyCtorType neg_weird_2(orig, true);
+}
+void WarningOnlyMultiDeclStmt() {
+ ExpensiveToCopyType orig;
+ ExpensiveToCopyType copy = orig, copy2;
+ // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy' of the variable 'orig' is never modified; consider avoiding the copy [performance-unnecessary-copy-initialization]
+ // CHECK-FIXES: ExpensiveToCopyType copy = orig, copy2;
+}
+
+class Element {};
+class Container {
+public:
+ class Iterator {
+ public:
+ void operator++();
+ Element operator*();
+ bool operator!=(const Iterator &);
+ WeirdCopyCtorType c;
+ };
+ const Iterator &begin() const;
+ const Iterator &end() const;
+};
+
+void implicitVarFalsePositive() {
+ for (const Element &E : Container()) {
+ }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-arc.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-arc.m
new file mode 100644
index 0000000..0a9ea06
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-arc.m
@@ -0,0 +1,16 @@
+// RUN: clang-tidy %s -checks=-*,performance-unnecessary-value-param -- \
+// RUN: -xobjective-c -fobjc-abi-version=2 -fobjc-arc | count 0
+
+#if !__has_feature(objc_arc)
+#error Objective-C ARC not enabled as expected
+#endif
+
+// Passing an Objective-C ARC-managed object to a C function should
+// not raise performance-unnecessary-value-param.
+void foo(id object) { }
+
+// Same for explcitly non-ARC-managed Objective-C objects.
+void bar(__unsafe_unretained id object) { }
+
+// Same for Objective-c classes.
+void baz(Class c) { }
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-arc.mm b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-arc.mm
new file mode 100644
index 0000000..4ed0506
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-arc.mm
@@ -0,0 +1,16 @@
+// RUN: clang-tidy %s -checks=-*,performance-unnecessary-value-param -- \
+// RUN: -xobjective-c++ -fobjc-abi-version=2 -fobjc-arc | count 0
+
+#if !__has_feature(objc_arc)
+#error Objective-C ARC not enabled as expected
+#endif
+
+// Passing an Objective-C ARC-managed object to a C function should
+// not raise performance-unnecessary-value-param.
+void foo(id object) { }
+
+// Same for explcitly non-ARC-managed Objective-C objects.
+void bar(__unsafe_unretained id object) { }
+
+// Same for Objective-c classes.
+void baz(Class c) { }
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-delayed.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-delayed.cpp
new file mode 100644
index 0000000..623bf8b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-delayed.cpp
@@ -0,0 +1,181 @@
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- -- -fdelayed-template-parsing
+
+struct ExpensiveToCopyType {
+ const ExpensiveToCopyType & constReference() const {
+ return *this;
+ }
+ void nonConstMethod();
+ virtual ~ExpensiveToCopyType();
+};
+
+void mutate(ExpensiveToCopyType &);
+void mutate(ExpensiveToCopyType *);
+void useAsConstReference(const ExpensiveToCopyType &);
+void useByValue(ExpensiveToCopyType);
+
+// This class simulates std::pair<>. It is trivially copy constructible
+// and trivially destructible, but not trivially copy assignable.
+class SomewhatTrivial {
+ public:
+ SomewhatTrivial();
+ SomewhatTrivial(const SomewhatTrivial&) = default;
+ ~SomewhatTrivial() = default;
+ SomewhatTrivial& operator=(const SomewhatTrivial&);
+};
+
+void positiveExpensiveConstValue(const ExpensiveToCopyType Obj);
+// CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj);
+void positiveExpensiveConstValue(const ExpensiveToCopyType Obj) {
+ // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'Obj' is copied for each invocation; consider making it a reference [performance-unnecessary-value-param]
+ // CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj) {
+}
+
+void positiveExpensiveValue(ExpensiveToCopyType Obj);
+// CHECK-FIXES: void positiveExpensiveValue(const ExpensiveToCopyType& Obj);
+void positiveExpensiveValue(ExpensiveToCopyType Obj) {
+ // CHECK-MESSAGES: [[@LINE-1]]:49: warning: the parameter 'Obj' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
+ // CHECK-FIXES: void positiveExpensiveValue(const ExpensiveToCopyType& Obj) {
+ Obj.constReference();
+ useAsConstReference(Obj);
+ auto Copy = Obj;
+ useByValue(Obj);
+}
+
+void positiveWithComment(const ExpensiveToCopyType /* important */ S);
+// CHECK-FIXES: void positiveWithComment(const ExpensiveToCopyType& /* important */ S);
+void positiveWithComment(const ExpensiveToCopyType /* important */ S) {
+ // CHECK-MESSAGES: [[@LINE-1]]:68: warning: the const qualified
+ // CHECK-FIXES: void positiveWithComment(const ExpensiveToCopyType& /* important */ S) {
+}
+
+void positiveUnnamedParam(const ExpensiveToCopyType) {
+ // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the const qualified parameter #1
+ // CHECK-FIXES: void positiveUnnamedParam(const ExpensiveToCopyType&) {
+}
+
+void positiveAndNegative(const ExpensiveToCopyType ConstCopy, const ExpensiveToCopyType& ConstRef, ExpensiveToCopyType Copy);
+// CHECK-FIXES: void positiveAndNegative(const ExpensiveToCopyType& ConstCopy, const ExpensiveToCopyType& ConstRef, const ExpensiveToCopyType& Copy);
+void positiveAndNegative(const ExpensiveToCopyType ConstCopy, const ExpensiveToCopyType& ConstRef, ExpensiveToCopyType Copy) {
+ // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the const qualified parameter 'ConstCopy'
+ // CHECK-MESSAGES: [[@LINE-2]]:120: warning: the parameter 'Copy'
+ // CHECK-FIXES: void positiveAndNegative(const ExpensiveToCopyType& ConstCopy, const ExpensiveToCopyType& ConstRef, const ExpensiveToCopyType& Copy) {
+}
+
+struct PositiveConstValueConstructor {
+ PositiveConstValueConstructor(const ExpensiveToCopyType ConstCopy) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:59: warning: the const qualified parameter 'ConstCopy'
+ // CHECK-FIXES: PositiveConstValueConstructor(const ExpensiveToCopyType& ConstCopy) {}
+};
+
+template <typename T> void templateWithNonTemplatizedParameter(const ExpensiveToCopyType S, T V) {
+ // CHECK-MESSAGES: [[@LINE-1]]:90: warning: the const qualified parameter 'S'
+ // CHECK-FIXES: template <typename T> void templateWithNonTemplatizedParameter(const ExpensiveToCopyType& S, T V) {
+}
+
+void instantiated() {
+ templateWithNonTemplatizedParameter(ExpensiveToCopyType(), ExpensiveToCopyType());
+ templateWithNonTemplatizedParameter(ExpensiveToCopyType(), 5);
+}
+
+template <typename T> void negativeTemplateType(const T V) {
+}
+
+void negativeArray(const ExpensiveToCopyType[]) {
+}
+
+void negativePointer(ExpensiveToCopyType* Obj) {
+}
+
+void negativeConstPointer(const ExpensiveToCopyType* Obj) {
+}
+
+void negativeConstReference(const ExpensiveToCopyType& Obj) {
+}
+
+void negativeReference(ExpensiveToCopyType& Obj) {
+}
+
+void negativeUniversalReference(ExpensiveToCopyType&& Obj) {
+}
+
+void negativeSomewhatTrivialConstValue(const SomewhatTrivial Somewhat) {
+}
+
+void negativeSomewhatTrivialValue(SomewhatTrivial Somewhat) {
+}
+
+void negativeConstBuiltIn(const int I) {
+}
+
+void negativeValueBuiltIn(int I) {
+}
+
+void negativeValueIsMutatedByReference(ExpensiveToCopyType Obj) {
+ mutate(Obj);
+}
+
+void negativeValueIsMutatatedByPointer(ExpensiveToCopyType Obj) {
+ mutate(&Obj);
+}
+
+void negativeValueIsReassigned(ExpensiveToCopyType Obj) {
+ Obj = ExpensiveToCopyType();
+}
+
+void negativeValueNonConstMethodIsCalled(ExpensiveToCopyType Obj) {
+ Obj.nonConstMethod();
+}
+
+struct PositiveValueUnusedConstructor {
+ PositiveValueUnusedConstructor(ExpensiveToCopyType Copy) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy'
+ // CHECK-FIXES: PositiveValueUnusedConstructor(const ExpensiveToCopyType& Copy) {}
+};
+
+struct PositiveValueCopiedConstructor {
+ PositiveValueCopiedConstructor(ExpensiveToCopyType Copy) : Field(Copy) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy'
+ // CHECK-FIXES: PositiveValueCopiedConstructor(const ExpensiveToCopyType& Copy) : Field(Copy) {}
+ ExpensiveToCopyType Field;
+};
+
+template <typename T>
+struct Container {
+ typedef const T & const_reference;
+};
+
+void NegativeTypedefParam(const Container<ExpensiveToCopyType>::const_reference Param) {
+}
+
+#define UNNECESSARY_VALUE_PARAM_IN_MACRO_BODY() \
+ void inMacro(const ExpensiveToCopyType T) { \
+ } \
+// Ensure fix is not applied.
+// CHECK-FIXES: void inMacro(const ExpensiveToCopyType T) {
+
+UNNECESSARY_VALUE_PARAM_IN_MACRO_BODY()
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: the const qualified parameter 'T'
+
+#define UNNECESSARY_VALUE_PARAM_IN_MACRO_ARGUMENT(ARGUMENT) \
+ ARGUMENT
+
+UNNECESSARY_VALUE_PARAM_IN_MACRO_ARGUMENT(void inMacroArgument(const ExpensiveToCopyType InMacroArg) {})
+// CHECK-MESSAGES: [[@LINE-1]]:90: warning: the const qualified parameter 'InMacroArg'
+// CHECK-FIXES: void inMacroArgument(const ExpensiveToCopyType InMacroArg) {}
+
+struct VirtualMethod {
+ virtual ~VirtualMethod() {}
+ virtual void handle(ExpensiveToCopyType T) const = 0;
+};
+
+struct NegativeOverriddenMethod : public VirtualMethod {
+ void handle(ExpensiveToCopyType Overridden) const {
+ // CHECK-FIXES: handle(ExpensiveToCopyType Overridden) const {
+ }
+};
+
+struct NegativeDeletedMethod {
+ ~NegativeDeletedMethod() {}
+ NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete;
+ // CHECK-FIXES: NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-header.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-header.cpp
new file mode 100644
index 0000000..9e4c246
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-header.cpp
@@ -0,0 +1,20 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: cp %S/Inputs/performance-unnecessary-value-param/header.h %t/header.h
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t/temp -- -- -std=c++11 -I %t
+// RUN: diff %t/header.h %S/Inputs/performance-unnecessary-value-param/header-fixed.h
+
+#include "header.h"
+
+
+
+int f1(int n, ABC v1, ABC v2) {
+ // CHECK-MESSAGES: [[@LINE-1]]:19: warning: the parameter 'v1' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
+ // CHECK-MESSAGES: [[@LINE-2]]:27: warning: the parameter 'v2' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
+ // CHECK-FIXES: int f1(int n, const ABC& v1, const ABC& v2) {
+ return v1.get(n) + v2.get(n);
+}
+int f2(int n, ABC v2) {
+ // CHECK-MESSAGES: [[@LINE-1]]:19: warning: the parameter 'v2' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
+ // CHECK-FIXES: int f2(int n, const ABC& v2) {
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
new file mode 100644
index 0000000..cd8c4da
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
@@ -0,0 +1,9 @@
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- -fix-errors -- --std=c++11
+
+// Ensure that incomplete types result in an error from the frontend and not a
+// clang-tidy diagnostic about IncompleteType being expensive to copy.
+struct IncompleteType;
+void NegativeForIncompleteType(IncompleteType I) {
+ // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 'IncompleteType' [clang-diagnostic-error]
+}
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param.cpp
new file mode 100644
index 0000000..dcf82df
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -0,0 +1,361 @@
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t
+
+// CHECK-FIXES: #include <utility>
+
+struct ExpensiveToCopyType {
+ const ExpensiveToCopyType & constReference() const {
+ return *this;
+ }
+ void nonConstMethod();
+ virtual ~ExpensiveToCopyType();
+};
+
+void mutate(ExpensiveToCopyType &);
+void mutate(ExpensiveToCopyType *);
+void useAsConstReference(const ExpensiveToCopyType &);
+void useByValue(ExpensiveToCopyType);
+
+// This class simulates std::pair<>. It is trivially copy constructible
+// and trivially destructible, but not trivially copy assignable.
+class SomewhatTrivial {
+ public:
+ SomewhatTrivial();
+ SomewhatTrivial(const SomewhatTrivial&) = default;
+ ~SomewhatTrivial() = default;
+ SomewhatTrivial& operator=(const SomewhatTrivial&);
+};
+
+struct MoveOnlyType {
+ MoveOnlyType(const MoveOnlyType &) = delete;
+ MoveOnlyType(MoveOnlyType &&) = default;
+ ~MoveOnlyType();
+ void constMethod() const;
+};
+
+struct ExpensiveMovableType {
+ ExpensiveMovableType();
+ ExpensiveMovableType(ExpensiveMovableType &&);
+ ExpensiveMovableType(const ExpensiveMovableType &) = default;
+ ExpensiveMovableType &operator=(const ExpensiveMovableType &) = default;
+ ExpensiveMovableType &operator=(ExpensiveMovableType &&);
+ ~ExpensiveMovableType();
+};
+
+void positiveExpensiveConstValue(const ExpensiveToCopyType Obj);
+// CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj);
+void positiveExpensiveConstValue(const ExpensiveToCopyType Obj) {
+ // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'Obj' is copied for each invocation; consider making it a reference [performance-unnecessary-value-param]
+ // CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj) {
+}
+
+void positiveExpensiveValue(ExpensiveToCopyType Obj);
+// CHECK-FIXES: void positiveExpensiveValue(const ExpensiveToCopyType& Obj);
+void positiveExpensiveValue(ExpensiveToCopyType Obj) {
+ // CHECK-MESSAGES: [[@LINE-1]]:49: warning: the parameter 'Obj' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
+ // CHECK-FIXES: void positiveExpensiveValue(const ExpensiveToCopyType& Obj) {
+ Obj.constReference();
+ useAsConstReference(Obj);
+ auto Copy = Obj;
+ useByValue(Obj);
+}
+
+void positiveWithComment(const ExpensiveToCopyType /* important */ S);
+// CHECK-FIXES: void positiveWithComment(const ExpensiveToCopyType& /* important */ S);
+void positiveWithComment(const ExpensiveToCopyType /* important */ S) {
+ // CHECK-MESSAGES: [[@LINE-1]]:68: warning: the const qualified
+ // CHECK-FIXES: void positiveWithComment(const ExpensiveToCopyType& /* important */ S) {
+}
+
+void positiveUnnamedParam(const ExpensiveToCopyType) {
+ // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the const qualified parameter #1
+ // CHECK-FIXES: void positiveUnnamedParam(const ExpensiveToCopyType&) {
+}
+
+void positiveAndNegative(const ExpensiveToCopyType ConstCopy, const ExpensiveToCopyType& ConstRef, ExpensiveToCopyType Copy);
+// CHECK-FIXES: void positiveAndNegative(const ExpensiveToCopyType& ConstCopy, const ExpensiveToCopyType& ConstRef, const ExpensiveToCopyType& Copy);
+void positiveAndNegative(const ExpensiveToCopyType ConstCopy, const ExpensiveToCopyType& ConstRef, ExpensiveToCopyType Copy) {
+ // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the const qualified parameter 'ConstCopy'
+ // CHECK-MESSAGES: [[@LINE-2]]:120: warning: the parameter 'Copy'
+ // CHECK-FIXES: void positiveAndNegative(const ExpensiveToCopyType& ConstCopy, const ExpensiveToCopyType& ConstRef, const ExpensiveToCopyType& Copy) {
+}
+
+struct PositiveConstValueConstructor {
+ PositiveConstValueConstructor(const ExpensiveToCopyType ConstCopy) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:59: warning: the const qualified parameter 'ConstCopy'
+ // CHECK-FIXES: PositiveConstValueConstructor(const ExpensiveToCopyType& ConstCopy) {}
+};
+
+template <typename T> void templateWithNonTemplatizedParameter(const ExpensiveToCopyType S, T V) {
+ // CHECK-MESSAGES: [[@LINE-1]]:90: warning: the const qualified parameter 'S'
+ // CHECK-FIXES: template <typename T> void templateWithNonTemplatizedParameter(const ExpensiveToCopyType& S, T V) {
+}
+
+void instantiated() {
+ templateWithNonTemplatizedParameter(ExpensiveToCopyType(), ExpensiveToCopyType());
+ templateWithNonTemplatizedParameter(ExpensiveToCopyType(), 5);
+}
+
+template <typename T> void negativeTemplateType(const T V) {
+}
+
+void negativeArray(const ExpensiveToCopyType[]) {
+}
+
+void negativePointer(ExpensiveToCopyType* Obj) {
+}
+
+void negativeConstPointer(const ExpensiveToCopyType* Obj) {
+}
+
+void negativeConstReference(const ExpensiveToCopyType& Obj) {
+}
+
+void negativeReference(ExpensiveToCopyType& Obj) {
+}
+
+void negativeUniversalReference(ExpensiveToCopyType&& Obj) {
+}
+
+void negativeSomewhatTrivialConstValue(const SomewhatTrivial Somewhat) {
+}
+
+void negativeSomewhatTrivialValue(SomewhatTrivial Somewhat) {
+}
+
+void negativeConstBuiltIn(const int I) {
+}
+
+void negativeValueBuiltIn(int I) {
+}
+
+void negativeValueIsMutatedByReference(ExpensiveToCopyType Obj) {
+ mutate(Obj);
+}
+
+void negativeValueIsMutatatedByPointer(ExpensiveToCopyType Obj) {
+ mutate(&Obj);
+}
+
+void negativeValueIsReassigned(ExpensiveToCopyType Obj) {
+ Obj = ExpensiveToCopyType();
+}
+
+void negativeValueNonConstMethodIsCalled(ExpensiveToCopyType Obj) {
+ Obj.nonConstMethod();
+}
+
+struct PositiveValueUnusedConstructor {
+ PositiveValueUnusedConstructor(ExpensiveToCopyType Copy) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy'
+ // CHECK-FIXES: PositiveValueUnusedConstructor(const ExpensiveToCopyType& Copy) {}
+};
+
+struct PositiveValueCopiedConstructor {
+ PositiveValueCopiedConstructor(ExpensiveToCopyType Copy) : Field(Copy) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy'
+ // CHECK-FIXES: PositiveValueCopiedConstructor(const ExpensiveToCopyType& Copy) : Field(Copy) {}
+ ExpensiveToCopyType Field;
+};
+
+struct PositiveValueMovableConstructor {
+ PositiveValueMovableConstructor(ExpensiveMovableType Copy) : Field(Copy) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:70: warning: parameter 'Copy'
+ // CHECK-FIXES: PositiveValueMovableConstructor(ExpensiveMovableType Copy) : Field(std::move(Copy)) {}
+ ExpensiveMovableType Field;
+};
+
+struct NegativeValueMovedConstructor {
+ NegativeValueMovedConstructor(ExpensiveMovableType Copy) : Field(static_cast<ExpensiveMovableType &&>(Copy)) {}
+ ExpensiveMovableType Field;
+};
+
+template <typename T>
+struct Container {
+ typedef const T & const_reference;
+};
+
+void NegativeTypedefParam(const Container<ExpensiveToCopyType>::const_reference Param) {
+}
+
+#define UNNECESSARY_VALUE_PARAM_IN_MACRO_BODY() \
+ void inMacro(const ExpensiveToCopyType T) { \
+ } \
+// Ensure fix is not applied.
+// CHECK-FIXES: void inMacro(const ExpensiveToCopyType T) {
+
+UNNECESSARY_VALUE_PARAM_IN_MACRO_BODY()
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: the const qualified parameter 'T'
+
+#define UNNECESSARY_VALUE_PARAM_IN_MACRO_ARGUMENT(ARGUMENT) \
+ ARGUMENT
+
+UNNECESSARY_VALUE_PARAM_IN_MACRO_ARGUMENT(void inMacroArgument(const ExpensiveToCopyType InMacroArg) {})
+// CHECK-MESSAGES: [[@LINE-1]]:90: warning: the const qualified parameter 'InMacroArg'
+// CHECK-FIXES: void inMacroArgument(const ExpensiveToCopyType InMacroArg) {}
+
+struct VirtualMethod {
+ virtual ~VirtualMethod() {}
+ virtual void handle(ExpensiveToCopyType T) const = 0;
+};
+
+struct NegativeOverriddenMethod : public VirtualMethod {
+ void handle(ExpensiveToCopyType Overridden) const {
+ // CHECK-FIXES: handle(ExpensiveToCopyType Overridden) const {
+ }
+};
+
+struct VirtualMethodWarningOnly {
+ virtual void methodWithExpensiveValueParam(ExpensiveToCopyType T) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:66: warning: the parameter 'T' is copied
+ // CHECK-FIXES: virtual void methodWithExpensiveValueParam(ExpensiveToCopyType T) {}
+ virtual ~VirtualMethodWarningOnly() {}
+};
+
+struct PositiveNonVirualMethod {
+ void method(const ExpensiveToCopyType T) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:41: warning: the const qualified parameter 'T' is copied
+ // CHECK-FIXES: void method(const ExpensiveToCopyType& T) {}
+};
+
+struct NegativeDeletedMethod {
+ ~NegativeDeletedMethod() {}
+ NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete;
+ // CHECK-FIXES: NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete;
+};
+
+void NegativeMoveOnlyTypePassedByValue(MoveOnlyType M) {
+ M.constMethod();
+}
+
+void PositiveMoveOnCopyConstruction(ExpensiveMovableType E) {
+ auto F = E;
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: parameter 'E' is passed by value and only copied once; consider moving it to avoid unnecessary copies [performance-unnecessary-value-param]
+ // CHECK-FIXES: auto F = std::move(E);
+}
+
+void PositiveConstRefNotMoveSinceReferencedMultipleTimes(ExpensiveMovableType E) {
+ // CHECK-MESSAGES: [[@LINE-1]]:79: warning: the parameter 'E' is copied
+ // CHECK-FIXES: void PositiveConstRefNotMoveSinceReferencedMultipleTimes(const ExpensiveMovableType& E) {
+ auto F = E;
+ auto G = E;
+}
+
+void PositiveMoveOnCopyAssignment(ExpensiveMovableType E) {
+ ExpensiveMovableType F;
+ F = E;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: parameter 'E' is passed by value
+ // CHECK-FIXES: F = std::move(E);
+}
+
+struct NotCopyAssigned {
+ NotCopyAssigned &operator=(const ExpensiveMovableType &);
+};
+
+void PositiveNoMoveForNonCopyAssigmentOperator(ExpensiveMovableType E) {
+ // CHECK-MESSAGES: [[@LINE-1]]:69: warning: the parameter 'E' is copied
+ // CHECK-FIXES: void PositiveNoMoveForNonCopyAssigmentOperator(const ExpensiveMovableType& E) {
+ NotCopyAssigned N;
+ N = E;
+}
+
+// The argument could be moved but is not since copy statement is inside a loop.
+void PositiveNoMoveInsideLoop(ExpensiveMovableType E) {
+ // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the parameter 'E' is copied
+ // CHECK-FIXES: void PositiveNoMoveInsideLoop(const ExpensiveMovableType& E) {
+ for (;;) {
+ auto F = E;
+ }
+}
+
+void PositiveConstRefNotMoveConstructible(ExpensiveToCopyType T) {
+ // CHECK-MESSAGES: [[@LINE-1]]:63: warning: the parameter 'T' is copied
+ // CHECK-FIXES: void PositiveConstRefNotMoveConstructible(const ExpensiveToCopyType& T) {
+ auto U = T;
+}
+
+void PositiveConstRefNotMoveAssignable(ExpensiveToCopyType A) {
+ // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the parameter 'A' is copied
+ // CHECK-FIXES: void PositiveConstRefNotMoveAssignable(const ExpensiveToCopyType& A) {
+ ExpensiveToCopyType B;
+ B = A;
+}
+
+// Case where parameter in declaration is already const-qualified but not in
+// implementation. Make sure a second 'const' is not added to the declaration.
+void PositiveConstDeclaration(const ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveConstDeclaration(ExpensiveToCopyType A) {
+ // CHECK-MESSAGES: [[@LINE-1]]:51: warning: the parameter 'A' is copied
+ // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A) {
+}
+
+void PositiveNonConstDeclaration(ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveNonConstDeclaration(const ExpensiveToCopyType A) {
+ // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A'
+ // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A) {
+}
+
+void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
+ // CHECK-MESSAGES: [[@LINE-1]]:75: warning: the parameter 'A' is copied
+ // CHECK-FIXES: void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
+}
+
+void ReferenceFunctionOutsideOfCallExpr() {
+ void (*ptr)(ExpensiveToCopyType) = &PositiveOnlyMessageAsReferencedInCompilationUnit;
+}
+
+void PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType A) {
+ // CHECK-MESSAGES: [[@LINE-1]]:66: warning: the parameter 'A' is copied
+ // CHECK-FIXES: void PositiveMessageAndFixAsFunctionIsCalled(const ExpensiveToCopyType& A) {
+}
+
+void ReferenceFunctionByCallingIt() {
+ PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType());
+}
+
+// Virtual method overrides of dependent types cannot be recognized unless they
+// are marked as override or final. Test that check is not triggered on methods
+// marked with override or final.
+template <typename T>
+struct NegativeDependentTypeInterface {
+ virtual void Method(ExpensiveToCopyType E) = 0;
+};
+
+template <typename T>
+struct NegativeOverrideImpl : public NegativeDependentTypeInterface<T> {
+ void Method(ExpensiveToCopyType E) override {}
+};
+
+template <typename T>
+struct NegativeFinalImpl : public NegativeDependentTypeInterface<T> {
+ void Method(ExpensiveToCopyType E) final {}
+};
+
+struct PositiveConstructor {
+ PositiveConstructor(ExpensiveToCopyType E) : E(E) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:43: warning: the parameter 'E' is copied
+ // CHECK-FIXES: PositiveConstructor(const ExpensiveToCopyType& E) : E(E) {}
+
+ ExpensiveToCopyType E;
+};
+
+struct NegativeUsingConstructor : public PositiveConstructor {
+ using PositiveConstructor::PositiveConstructor;
+};
+
+void fun() {
+ ExpensiveToCopyType E;
+ NegativeUsingConstructor S(E);
+}
+
+template<typename T>
+void templateFunction(T) {
+}
+
+template<>
+void templateFunction<ExpensiveToCopyType>(ExpensiveToCopyType E) {
+ // CHECK-MESSAGES: [[@LINE-1]]:64: warning: the parameter 'E' is copied
+ // CHECK-FIXES: void templateFunction<ExpensiveToCopyType>(ExpensiveToCopyType E) {
+ E.constReference();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/portability-simd-intrinsics-ppc.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/portability-simd-intrinsics-ppc.cpp
new file mode 100644
index 0000000..be0ef76
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/portability-simd-intrinsics-ppc.cpp
@@ -0,0 +1,13 @@
+// RUN: %check_clang_tidy %s portability-simd-intrinsics %t -- \
+// RUN: -config='{CheckOptions: [ \
+// RUN: {key: portability-simd-intrinsics.Suggest, value: 1} \
+// RUN: ]}' -- -target ppc64le -maltivec -std=c++11
+
+vector int vec_add(vector int, vector int);
+
+void PPC() {
+ vector int i0, i1;
+
+ vec_add(i0, i1);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'vec_add' can be replaced by operator+ on std::experimental::simd objects [portability-simd-intrinsics]
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/portability-simd-intrinsics-x86.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/portability-simd-intrinsics-x86.cpp
new file mode 100644
index 0000000..1fb2289
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/portability-simd-intrinsics-x86.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s portability-simd-intrinsics %t -- \
+// RUN: -config='{CheckOptions: [ \
+// RUN: {key: portability-simd-intrinsics.Suggest, value: 1} \
+// RUN: ]}' -- -target x86_64 -std=c++11
+
+typedef long long __m128i __attribute__((vector_size(16)));
+typedef double __m256 __attribute__((vector_size(32)));
+
+__m128i _mm_add_epi32(__m128i, __m128i);
+__m256 _mm256_load_pd(double const *);
+void _mm256_store_pd(double *, __m256);
+
+int _mm_add_fake(int, int);
+
+void X86() {
+ __m128i i0, i1;
+ __m256 d0;
+
+ _mm_add_epi32(i0, i1);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: '_mm_add_epi32' can be replaced by operator+ on std::experimental::simd objects [portability-simd-intrinsics]
+ d0 = _mm256_load_pd(0);
+ _mm256_store_pd(0, d0);
+
+ _mm_add_fake(0, 1);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/pr37091.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/pr37091.cpp
new file mode 100644
index 0000000..e56115a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/pr37091.cpp
@@ -0,0 +1,10 @@
+// REQUIRES: shell
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+
+// This is a reproducer for PR37091.
+//
+// Verify that no temporary files are left behind by the clang-tidy invocation.
+
+// RUN: env TMPDIR=%t TEMP=%t TMP=%t clang-tidy %s -- --target=mips64
+// RUN: rmdir %t
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/read_file_config.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/read_file_config.cpp
new file mode 100644
index 0000000..3635c21
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/read_file_config.cpp
@@ -0,0 +1,12 @@
+// RUN: mkdir -p %T/read-file-config/
+// RUN: cp %s %T/read-file-config/test.cpp
+// RUN: echo 'Checks: "-*,modernize-use-nullptr"' > %T/read-file-config/.clang-tidy
+// RUN: echo '[{"command": "cc -c -o test.o test.cpp", "directory": "%/T/read-file-config", "file": "%/T/read-file-config/test.cpp"}]' > %T/read-file-config/compile_commands.json
+// RUN: clang-tidy %T/read-file-config/test.cpp | not grep "warning: .*\[clang-analyzer-deadcode.DeadStores\]$"
+// RUN: clang-tidy -checks="-*,clang-analyzer-*" %T/read-file-config/test.cpp | grep "warning: .*\[clang-analyzer-deadcode.DeadStores\]$"
+
+void f() {
+ int x;
+ x = 1;
+ x = 2;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-avoid-const-params-in-decls.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-avoid-const-params-in-decls.cpp
new file mode 100644
index 0000000..c2c12a4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-avoid-const-params-in-decls.cpp
@@ -0,0 +1,133 @@
+// RUN: %check_clang_tidy %s readability-avoid-const-params-in-decls %t
+
+using alias_type = bool;
+using alias_const_type = const bool;
+
+
+void F1(const int i);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'i' is const-qualified in the function declaration; const-qualification of parameters only has an effect in function definitions [readability-avoid-const-params-in-decls]
+// CHECK-FIXES: void F1(int i);
+
+void F2(const int *const i);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'i' is const-qualified
+// CHECK-FIXES: void F2(const int *i);
+
+void F3(int const i);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'i' is const-qualified
+// CHECK-FIXES: void F3(int i);
+
+void F4(alias_type const i);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'i' is const-qualified
+// CHECK-FIXES: void F4(alias_type i);
+
+void F5(const int);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 1 is const-qualified
+// CHECK-FIXES: void F5(int);
+
+void F6(const int *const);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 1 is const-qualified
+// CHECK-FIXES: void F6(const int *);
+
+void F7(int, const int);
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: parameter 2 is const-qualified
+// CHECK-FIXES: void F7(int, int);
+
+void F8(const int, const int);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 1 is const-qualified
+// CHECK-MESSAGES: :[[@LINE-2]]:20: warning: parameter 2 is const-qualified
+// CHECK-FIXES: void F8(int, int);
+
+void F9(const int long_name);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'long_name'
+// CHECK-FIXES: void F9(int long_name);
+
+void F10(const int *const *const long_name);
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: parameter 'long_name'
+// CHECK-FIXES: void F10(const int *const *long_name);
+
+void F11(const unsigned int /*v*/);
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: parameter 1
+// CHECK-FIXES: void F11(unsigned int /*v*/);
+
+void F12(const bool b = true);
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: parameter 'b'
+// CHECK-FIXES: void F12(bool b = true);
+
+template<class T>
+int F13(const bool b = true);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'b'
+// CHECK-FIXES: int F13(bool b = true);
+int f13 = F13<int>();
+
+struct Foo {
+ Foo(const int i);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: parameter 'i'
+ // CHECK-FIXES: Foo(int i);
+
+ void operator()(const int i);
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: parameter 'i'
+ // CHECK-FIXES: void operator()(int i);
+};
+
+template <class T>
+struct FooT {
+ FooT(const int i);
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: parameter 'i'
+ // CHECK-FIXES: FooT(int i);
+
+ void operator()(const int i);
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: parameter 'i'
+ // CHECK-FIXES: void operator()(int i);
+};
+FooT<int> f(1);
+
+// Do not match on definitions
+void NF1(const int i) {}
+void NF2(const int *const i) {}
+void NF3(int const i) {}
+void NF4(alias_type const i) {}
+void NF5(const int) {}
+void NF6(const int *const) {}
+void NF7(int, const int) {}
+void NF8(const int, const int) {}
+template <class T>
+int NF9(const int, const int) { return 0; }
+int nf9 = NF9<int>(1, 2);
+
+// Do not match on inline member functions
+struct Bar {
+ Bar(const int i) {}
+
+ void operator()(const int i) {}
+};
+
+// Do not match on inline member functions of a templated class
+template <class T>
+struct BarT {
+ BarT(const int i) {}
+
+ void operator()(const int i) {}
+};
+BarT<int> b(1);
+
+// Do not match on other stuff
+void NF(const alias_type& i);
+void NF(const int &i);
+void NF(const int *i);
+void NF(alias_const_type i);
+void NF(const alias_type&);
+void NF(const int&);
+void NF(const int*);
+void NF(const int* const*);
+void NF(alias_const_type);
+
+// Regression test for when the 'const' token is not in the code.
+#define CONCAT(a, b) a##b
+void ConstNotVisible(CONCAT(cons, t) int i);
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: parameter 'i'
+// We warn, but we can't give a fix
+// CHECK-FIXES: void ConstNotVisible(CONCAT(cons, t) int i);
+
+// Regression test. We should not warn (or crash) on lambda expressions
+auto lambda_with_name = [](const int n) {};
+auto lambda_without_name = [](const int) {};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-assert-failure.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-assert-failure.cpp
new file mode 100644
index 0000000..7d619c0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-assert-failure.cpp
@@ -0,0 +1,12 @@
+// RUN: not clang-tidy -checks='-*,readability-braces-around-statements' %s --
+
+// Note: this test expects no assert failure happened in clang-tidy.
+
+int test_failure() {
+ if (std::rand()) {
+ }
+}
+
+void test_failure2() {
+ for (a b c;;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-few-lines.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-few-lines.cpp
new file mode 100644
index 0000000..00d253a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-few-lines.cpp
@@ -0,0 +1,30 @@
+// RUN: %check_clang_tidy %s readability-braces-around-statements %t -- -config="{CheckOptions: [{key: readability-braces-around-statements.ShortStatementLines, value: 4}]}" --
+
+void do_something(const char *) {}
+
+bool cond(const char *) {
+ return false;
+}
+
+void test() {
+ if (cond("if1") /*comment*/) do_something("same-line");
+
+ if (cond("if2"))
+ do_something("single-line");
+
+ if (cond("if3") /*comment*/)
+ // some comment
+ do_something("three"
+ "lines");
+
+ if (cond("if4") /*comment*/)
+ // some comment
+ do_something("many"
+ "many"
+ "many"
+ "many"
+ "lines");
+ // CHECK-MESSAGES: :[[@LINE-7]]:31: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("if4") /*comment*/) {
+ // CHECK-FIXES: }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-format.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-format.cpp
new file mode 100644
index 0000000..81f832d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-format.cpp
@@ -0,0 +1,33 @@
+// RUN: %check_clang_tidy %s readability-braces-around-statements %t -- -format-style="{IndentWidth: 3}" --
+
+void do_something(const char *) {}
+
+bool cond(const char *) {
+ return false;
+}
+
+void test() {
+ if (cond("if0") /*comment*/) do_something("same-line");
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: statement should be inside braces
+ // CHECK-FIXES: {{^}} if (cond("if0") /*comment*/) {{{$}}
+ // CHECK-FIXES-NEXT: {{^}} do_something("same-line");{{$}}
+ // CHECK-FIXES-NEXT: {{^}} }{{$}}
+
+ if (1) while (2) if (3) for (;;) do ; while(false) /**/;/**/
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: statement should be inside braces
+ // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: statement should be inside braces
+ // CHECK-MESSAGES: :[[@LINE-3]]:26: warning: statement should be inside braces
+ // CHECK-MESSAGES: :[[@LINE-4]]:35: warning: statement should be inside braces
+ // CHECK-MESSAGES: :[[@LINE-5]]:38: warning: statement should be inside braces
+ // CHECK-FIXES: {{^}} if (1) {{{$}}
+ // CHECK-FIXES-NEXT: {{^}} while (2) {
+ // CHECK-FIXES-NEXT: {{^}} if (3) {
+ // CHECK-FIXES-NEXT: {{^}} for (;;) {
+ // CHECK-FIXES-NEXT: {{^}} do {
+ // CHECK-FIXES-NEXT: {{^}} ;
+ // CHECK-FIXES-NEXT: {{^}} } while (false) /**/; /**/
+ // CHECK-FIXES-NEXT: {{^}} }
+ // CHECK-FIXES-NEXT: {{^}} }
+ // CHECK-FIXES-NEXT: {{^}} }
+ // CHECK-FIXES-NEXT: {{^}} }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-same-line.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-same-line.cpp
new file mode 100644
index 0000000..504043f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-same-line.cpp
@@ -0,0 +1,36 @@
+// RUN: %check_clang_tidy %s readability-braces-around-statements %t -- -config="{CheckOptions: [{key: readability-braces-around-statements.ShortStatementLines, value: 1}]}" --
+
+void do_something(const char *) {}
+
+bool cond(const char *) {
+ return false;
+}
+
+void test() {
+ if (cond("if1") /*comment*/) do_something("same-line");
+
+ if (cond("if2"))
+ do_something("single-line");
+ // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("if2")) {
+ // CHECK-FIXES: }
+
+ if (cond("if3") /*comment*/)
+ // some comment
+ do_something("three"
+ "lines");
+ // CHECK-MESSAGES: :[[@LINE-4]]:31: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("if3") /*comment*/) {
+ // CHECK-FIXES: }
+
+ if (cond("if4") /*comment*/)
+ // some comment
+ do_something("many"
+ "many"
+ "many"
+ "many"
+ "lines");
+ // CHECK-MESSAGES: :[[@LINE-7]]:31: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("if4") /*comment*/) {
+ // CHECK-FIXES: }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-single-line.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-single-line.cpp
new file mode 100644
index 0000000..3edbd4b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-single-line.cpp
@@ -0,0 +1,33 @@
+// RUN: %check_clang_tidy %s readability-braces-around-statements %t -- -config="{CheckOptions: [{key: readability-braces-around-statements.ShortStatementLines, value: 2}]}" --
+
+void do_something(const char *) {}
+
+bool cond(const char *) {
+ return false;
+}
+
+void test() {
+ if (cond("if1") /*comment*/) do_something("same-line");
+
+ if (cond("if2"))
+ do_something("single-line");
+
+ if (cond("if3") /*comment*/)
+ // some comment
+ do_something("three"
+ "lines");
+ // CHECK-MESSAGES: :[[@LINE-4]]:31: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("if3") /*comment*/) {
+ // CHECK-FIXES: }
+
+ if (cond("if4") /*comment*/)
+ // some comment
+ do_something("many"
+ "many"
+ "many"
+ "many"
+ "lines");
+ // CHECK-MESSAGES: :[[@LINE-7]]:31: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("if4") /*comment*/) {
+ // CHECK-FIXES: }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements.cpp
new file mode 100644
index 0000000..8dc5bf1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements.cpp
@@ -0,0 +1,206 @@
+// RUN: %check_clang_tidy %s readability-braces-around-statements %t
+
+void do_something(const char *) {}
+
+bool cond(const char *) {
+ return false;
+}
+
+#define EMPTY_MACRO
+#define EMPTY_MACRO_FUN()
+
+void test() {
+ if (cond("if0") /*comment*/) do_something("same-line");
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("if0") /*comment*/) { do_something("same-line");
+ // CHECK-FIXES: }
+
+ if (cond("if0.1"))
+ do_something("single-line");
+ // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("if0.1")) {
+ // CHECK-FIXES: }
+
+ if (cond("if1") /*comment*/)
+ // some comment
+ do_something("if1");
+ // CHECK-MESSAGES: :[[@LINE-3]]:31: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("if1") /*comment*/) {
+ // CHECK-FIXES: }
+ if (cond("if2")) {
+ do_something("if2");
+ }
+ if (cond("if3"))
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("if3")) {
+ // CHECK-FIXES: }
+
+ if (cond("if-else1"))
+ do_something("if-else1");
+ // CHECK-MESSAGES: :[[@LINE-2]]:24: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("if-else1")) {
+ // CHECK-FIXES: } else {
+ else
+ do_something("if-else1 else");
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: statement should be inside braces
+ // CHECK-FIXES: }
+ if (cond("if-else2")) {
+ do_something("if-else2");
+ } else {
+ do_something("if-else2 else");
+ }
+
+ if (cond("if-else if-else1"))
+ do_something("if");
+ // CHECK-MESSAGES: :[[@LINE-2]]:32: warning: statement should be inside braces
+ // CHECK-FIXES: } else if (cond("else if1")) {
+ else if (cond("else if1"))
+ do_something("else if");
+ // CHECK-MESSAGES: :[[@LINE-2]]:29: warning: statement should be inside braces
+ else
+ do_something("else");
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: statement should be inside braces
+ // CHECK-FIXES: }
+ if (cond("if-else if-else2")) {
+ do_something("if");
+ } else if (cond("else if2")) {
+ do_something("else if");
+ } else {
+ do_something("else");
+ }
+
+ for (;;)
+ do_something("for");
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: statement should be inside braces
+ // CHECK-FIXES: for (;;) {
+ // CHECK-FIXES: }
+ for (;;) {
+ do_something("for");
+ }
+ for (;;)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: statement should be inside braces
+ // CHECK-FIXES: for (;;) {
+ // CHECK-FIXES: }
+
+ int arr[4] = {1, 2, 3, 4};
+ for (int a : arr)
+ do_something("for-range");
+ // CHECK-MESSAGES: :[[@LINE-2]]:20: warning: statement should be inside braces
+ // CHECK-FIXES: for (int a : arr) {
+ // CHECK-FIXES: }
+ for (int a : arr) {
+ do_something("for-range");
+ }
+ for (int a : arr)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:20: warning: statement should be inside braces
+ // CHECK-FIXES: for (int a : arr) {
+ // CHECK-FIXES: }
+
+ while (cond("while1"))
+ do_something("while");
+ // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: statement should be inside braces
+ // CHECK-FIXES: while (cond("while1")) {
+ // CHECK-FIXES: }
+ while (cond("while2")) {
+ do_something("while");
+ }
+ while (false)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: statement should be inside braces
+ // CHECK-FIXES: while (false) {
+ // CHECK-FIXES: }
+
+ do
+ do_something("do1");
+ while (cond("do1"));
+ // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: statement should be inside braces
+ // CHECK-FIXES: do {
+ // CHECK-FIXES: } while (cond("do1"));
+ do {
+ do_something("do2");
+ } while (cond("do2"));
+
+ do
+ ;
+ while (false);
+ // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: statement should be inside braces
+ // CHECK-FIXES: do {
+ // CHECK-FIXES: } while (false);
+
+ if (cond("ifif1"))
+ // comment
+ if (cond("ifif2"))
+ // comment
+ /*comment*/ ; // comment
+ // CHECK-MESSAGES: :[[@LINE-5]]:21: warning: statement should be inside braces
+ // CHECK-MESSAGES: :[[@LINE-4]]:23: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("ifif1")) {
+ // CHECK-FIXES: if (cond("ifif2")) {
+ // CHECK-FIXES: }
+ // CHECK-FIXES-NEXT: }
+
+ if (cond("ifif3"))
+ // comment
+ if (cond("ifif4")) {
+ // comment
+ /*comment*/; // comment
+ }
+ // CHECK-MESSAGES: :[[@LINE-6]]:21: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("ifif3")) {
+ // CHECK-FIXES: }
+
+ if (cond("ifif5"))
+ ; /* multi-line
+ comment */
+ // CHECK-MESSAGES: :[[@LINE-3]]:21: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("ifif5")) {
+ // CHECK-FIXES: }/* multi-line
+
+ if (1) while (2) if (3) for (;;) do ; while(false) /**/;/**/
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: statement should be inside braces
+ // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: statement should be inside braces
+ // CHECK-MESSAGES: :[[@LINE-3]]:26: warning: statement should be inside braces
+ // CHECK-MESSAGES: :[[@LINE-4]]:35: warning: statement should be inside braces
+ // CHECK-MESSAGES: :[[@LINE-5]]:38: warning: statement should be inside braces
+ // CHECK-FIXES: if (1) { while (2) { if (3) { for (;;) { do { ; } while(false) /**/;/**/
+ // CHECK-FIXES-NEXT: }
+ // CHECK-FIXES-NEXT: }
+ // CHECK-FIXES-NEXT: }
+ // CHECK-FIXES-NEXT: }
+}
+
+void f(const char *p) {
+ if (!p)
+ f("\
+");
+} // end of f
+// CHECK-MESSAGES: :[[@LINE-4]]:10: warning: statement should be inside braces
+// CHECK-FIXES: {{^}} if (!p) {{{$}}
+// CHECK-FIXES-NEXT: {{^}} f("\{{$}}
+// CHECK-FIXES-NEXT: {{^}}");{{$}}
+// CHECK-FIXES-NEXT: {{^}}}{{$}}
+// CHECK-FIXES-NEXT: {{^}}} // end of f{{$}}
+
+#define M(x) x
+
+int test_macros(bool b) {
+ if (b) {
+ return 1;
+ } else
+ M(return 2);
+ // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: statement should be inside braces
+ // CHECK-FIXES: } else {
+ // CHECK-FIXES-NEXT: M(return 2);
+ // CHECK-FIXES-NEXT: }
+ M(
+ for (;;)
+ ;
+ );
+ // CHECK-MESSAGES: :[[@LINE-3]]:13: warning: statement should be inside braces
+ // CHECK-FIXES: {{^}} for (;;) {{{$}}
+ // CHECK-FIXES-NEXT: {{^ ;$}}
+ // CHECK-FIXES-NEXT: {{^}$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-container-size-empty.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-container-size-empty.cpp
new file mode 100644
index 0000000..3c3c9a6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-container-size-empty.cpp
@@ -0,0 +1,439 @@
+// RUN: %check_clang_tidy %s readability-container-size-empty %t
+
+namespace std {
+template <typename T> struct vector {
+ vector();
+ bool operator==(const vector<T>& other) const;
+ bool operator!=(const vector<T>& other) const;
+ unsigned long size() const;
+ bool empty() const;
+};
+
+template <typename T> struct basic_string {
+ basic_string();
+ bool operator==(const basic_string<T>& other) const;
+ bool operator!=(const basic_string<T>& other) const;
+ bool operator==(const char *) const;
+ bool operator!=(const char *) const;
+ basic_string<T> operator+(const basic_string<T>& other) const;
+ unsigned long size() const;
+ bool empty() const;
+};
+
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+
+inline namespace __v2 {
+template <typename T> struct set {
+ set();
+ bool operator==(const set<T>& other) const;
+ bool operator!=(const set<T>& other) const;
+ unsigned long size() const;
+ bool empty() const;
+};
+}
+
+}
+
+template <typename T>
+class TemplatedContainer {
+public:
+ bool operator==(const TemplatedContainer<T>& other) const;
+ bool operator!=(const TemplatedContainer<T>& other) const;
+ int size() const;
+ bool empty() const;
+};
+
+template <typename T>
+class PrivateEmpty {
+public:
+ bool operator==(const PrivateEmpty<T>& other) const;
+ bool operator!=(const PrivateEmpty<T>& other) const;
+ int size() const;
+private:
+ bool empty() const;
+};
+
+struct BoolSize {
+ bool size() const;
+ bool empty() const;
+};
+
+struct EnumSize {
+ enum E { one };
+ enum E size() const;
+ bool empty() const;
+};
+
+class Container {
+public:
+ bool operator==(const Container& other) const;
+ int size() const;
+ bool empty() const;
+};
+
+class Derived : public Container {
+};
+
+class Container2 {
+public:
+ int size() const;
+ bool empty() const { return size() == 0; }
+};
+
+class Container3 {
+public:
+ int size() const;
+ bool empty() const;
+};
+
+bool Container3::empty() const { return this->size() == 0; }
+
+class Container4 {
+public:
+ bool operator==(const Container4& rhs) const;
+ int size() const;
+ bool empty() const { return *this == Container4(); }
+};
+
+std::string s_func() {
+ return std::string();
+}
+
+int main() {
+ std::set<int> intSet;
+ std::string str;
+ std::string str2;
+ std::wstring wstr;
+ str.size() + 0;
+ str.size() - 0;
+ 0 + str.size();
+ 0 - str.size();
+ if (intSet.size() == 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
+ // CHECK-FIXES: {{^ }}if (intSet.empty()){{$}}
+ // CHECK-MESSAGES: :32:8: note: method 'set<int>'::empty() defined here
+ if (intSet == std::set<int>())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness
+ // CHECK-FIXES: {{^ }}if (intSet.empty()){{$}}
+ // CHECK-MESSAGES: :32:8: note: method 'set<int>'::empty() defined here
+ if (s_func() == "")
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (s_func().empty()){{$}}
+ if (str.size() == 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (str.empty()){{$}}
+ if ((str + str2).size() == 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if ((str + str2).empty()){{$}}
+ if (str == "")
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (str.empty()){{$}}
+ if (str + str2 == "")
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if ((str + str2).empty()){{$}}
+ if (wstr.size() == 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (wstr.empty()){{$}}
+ if (wstr == "")
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (wstr.empty()){{$}}
+ std::vector<int> vect;
+ if (vect.size() == 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (vect.empty()){{$}}
+ if (vect == std::vector<int>())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (vect.empty()){{$}}
+ if (vect.size() != 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!vect.empty()){{$}}
+ if (vect != std::vector<int>())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!vect.empty()){{$}}
+ if (0 == vect.size())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (vect.empty()){{$}}
+ if (0 != vect.size())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!vect.empty()){{$}}
+ if (std::vector<int>() == vect)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (vect.empty()){{$}}
+ if (std::vector<int>() != vect)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!vect.empty()){{$}}
+ if (vect.size() > 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!vect.empty()){{$}}
+ if (0 < vect.size())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!vect.empty()){{$}}
+ if (vect.size() < 1)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (vect.empty()){{$}}
+ if (1 > vect.size())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (vect.empty()){{$}}
+ if (vect.size() >= 1)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!vect.empty()){{$}}
+ if (1 <= vect.size())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!vect.empty()){{$}}
+ if (vect.size() > 1) // no warning
+ ;
+ if (1 < vect.size()) // no warning
+ ;
+ if (vect.size() <= 1) // no warning
+ ;
+ if (1 >= vect.size()) // no warning
+ ;
+ if (!vect.size())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (vect.empty()){{$}}
+ if (vect.size())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!vect.empty()){{$}}
+
+ if (vect.empty())
+ ;
+
+ const std::vector<int> vect2;
+ if (vect2.size() != 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!vect2.empty()){{$}}
+
+ std::vector<int> *vect3 = new std::vector<int>();
+ if (vect3->size() == 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (vect3->empty()){{$}}
+ if ((*vect3).size() == 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if ((*vect3).empty()){{$}}
+ if ((*vect3) == std::vector<int>())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (vect3->empty()){{$}}
+ if (*vect3 == std::vector<int>())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (vect3->empty()){{$}}
+
+ delete vect3;
+
+ const std::vector<int> &vect4 = vect2;
+ if (vect4.size() == 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (vect4.empty()){{$}}
+ if (vect4 == std::vector<int>())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (vect4.empty()){{$}}
+
+ TemplatedContainer<void> templated_container;
+ if (templated_container.size() == 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (templated_container.empty()){{$}}
+ if (templated_container == TemplatedContainer<void>())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (templated_container.empty()){{$}}
+ if (templated_container.size() != 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
+ if (templated_container != TemplatedContainer<void>())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
+ if (0 == templated_container.size())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (templated_container.empty()){{$}}
+ if (TemplatedContainer<void>() == templated_container)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (templated_container.empty()){{$}}
+ if (0 != templated_container.size())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
+ if (TemplatedContainer<void>() != templated_container)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
+ if (templated_container.size() > 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
+ if (0 < templated_container.size())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
+ if (templated_container.size() < 1)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (templated_container.empty()){{$}}
+ if (1 > templated_container.size())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (templated_container.empty()){{$}}
+ if (templated_container.size() >= 1)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
+ if (1 <= templated_container.size())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
+ if (templated_container.size() > 1) // no warning
+ ;
+ if (1 < templated_container.size()) // no warning
+ ;
+ if (templated_container.size() <= 1) // no warning
+ ;
+ if (1 >= templated_container.size()) // no warning
+ ;
+ if (!templated_container.size())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (templated_container.empty()){{$}}
+ if (templated_container.size())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
+
+ if (templated_container.empty())
+ ;
+
+ // No warnings expected.
+ PrivateEmpty<void> private_empty;
+ if (private_empty.size() == 0)
+ ;
+ if (private_empty == PrivateEmpty<void>())
+ ;
+ if (private_empty.size() != 0)
+ ;
+ if (private_empty != PrivateEmpty<void>())
+ ;
+ if (0 == private_empty.size())
+ ;
+ if (PrivateEmpty<void>() == private_empty)
+ ;
+ if (0 != private_empty.size())
+ ;
+ if (PrivateEmpty<void>() != private_empty)
+ ;
+ if (private_empty.size() > 0)
+ ;
+ if (0 < private_empty.size())
+ ;
+ if (private_empty.size() < 1)
+ ;
+ if (1 > private_empty.size())
+ ;
+ if (private_empty.size() >= 1)
+ ;
+ if (1 <= private_empty.size())
+ ;
+ if (private_empty.size() > 1)
+ ;
+ if (1 < private_empty.size())
+ ;
+ if (private_empty.size() <= 1)
+ ;
+ if (1 >= private_empty.size())
+ ;
+ if (!private_empty.size())
+ ;
+ if (private_empty.size())
+ ;
+
+ // Types with weird size() return type.
+ BoolSize bs;
+ if (bs.size() == 0)
+ ;
+ EnumSize es;
+ if (es.size() == 0)
+ ;
+
+ Derived derived;
+ if (derived.size() == 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (derived.empty()){{$}}
+ if (derived == Derived())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (derived.empty()){{$}}
+}
+
+#define CHECKSIZE(x) if (x.size())
+// CHECK-FIXES: #define CHECKSIZE(x) if (x.size())
+
+template <typename T> void f() {
+ std::vector<T> v;
+ if (v.size())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
+ // CHECK-FIXES: {{^ }}if (!v.empty()){{$}}
+ if (v == std::vector<T>())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of comparing to an empty object [readability-container-size-empty]
+ // CHECK-FIXES: {{^ }}if (v.empty()){{$}}
+ // CHECK-FIXES-NEXT: ;
+ CHECKSIZE(v);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: the 'empty' method should be used
+ // CHECK-MESSAGES: CHECKSIZE(v);
+
+ TemplatedContainer<T> templated_container;
+ if (templated_container.size())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
+ if (templated_container != TemplatedContainer<T>())
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+ // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
+ // CHECK-FIXES-NEXT: ;
+ CHECKSIZE(templated_container);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: the 'empty' method should be used
+ // CHECK-MESSAGES: CHECKSIZE(templated_container);
+}
+
+void g() {
+ f<int>();
+ f<double>();
+ f<char *>();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-delete-null-pointer.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-delete-null-pointer.cpp
new file mode 100644
index 0000000..b46e52a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-delete-null-pointer.cpp
@@ -0,0 +1,86 @@
+// RUN: %check_clang_tidy %s readability-delete-null-pointer %t
+
+#define NULL 0
+
+void f() {
+ int *p = 0;
+
+ // #1
+ if (p) { // #2
+ delete p;
+ } // #3
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: 'if' statement is unnecessary; deleting null pointer has no effect [readability-delete-null-pointer]
+
+ // CHECK-FIXES: {{^ }}// #1
+ // CHECK-FIXES-NEXT: {{^ }}// #2
+ // CHECK-FIXES-NEXT: delete p;
+ // CHECK-FIXES-NEXT: {{^ }}// #3
+
+ int *p2 = new int[3];
+ // #4
+ if (p2) // #5
+ delete[] p2;
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: 'if' statement is unnecessary;
+
+ // CHECK-FIXES: // #4
+ // CHECK-FIXES-NEXT: {{^ }}// #5
+ // CHECK-FIXES-NEXT: delete[] p2;
+
+ int *p3 = 0;
+ if (NULL != p3) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'if' statement is unnecessary;
+ delete p3;
+ }
+ // CHECK-FIXES-NOT: if (NULL != p3) {
+ // CHECK-FIXES: delete p3;
+
+ int *p4 = nullptr;
+ if (p4 != nullptr) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'if' statement is unnecessary;
+ delete p4;
+ }
+ // CHECK-FIXES-NOT: if (p4 != nullptr) {
+ // CHECK-FIXES: delete p4;
+
+ char *c;
+ if (c != 0) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'if' statement is unnecessary;
+ delete c;
+ }
+ // CHECK-FIXES-NOT: if (c != 0) {
+ // CHECK-FIXES: delete c;
+
+ char *c2;
+ if (c2) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'if' statement is unnecessary;
+ // CHECK-FIXES: } else {
+ // CHECK-FIXES: c2 = c;
+ delete c2;
+ } else {
+ c2 = c;
+ }
+ struct A {
+ void foo() {
+ if (mp) // #6
+ delete mp;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: 'if' statement is unnecessary; deleting null pointer has no effect [readability-delete-null-pointer]
+ // CHECK-FIXES: {{^ }}// #6
+ // CHECK-FIXES-NEXT: delete mp;
+ }
+ int *mp;
+ };
+}
+
+void g() {
+ int *p5, *p6;
+ if (p5)
+ delete p6;
+
+ if (p5 && p6)
+ delete p5;
+
+ if (p6) {
+ int x = 5;
+ delete p6;
+ }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-deleted-default.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-deleted-default.cpp
new file mode 100644
index 0000000..bf27e00
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-deleted-default.cpp
@@ -0,0 +1,127 @@
+// RUN: %check_clang_tidy %s readability-deleted-default %t -- -- -std=c++11 -fno-ms-compatibility
+
+class NoDefault {
+public:
+ NoDefault() = delete;
+ NoDefault(NoDefault &&Other) = delete;
+ NoDefault(const NoDefault &Other) = delete;
+};
+
+class MissingEverything {
+public:
+ MissingEverything() = default;
+ // CHECK-MESSAGES: warning: default constructor is explicitly defaulted but implicitly deleted, probably because a non-static data member or a base class is lacking a default constructor; definition can either be removed or explicitly deleted [readability-deleted-default]
+ MissingEverything(MissingEverything &&Other) = default;
+ // CHECK-MESSAGES: warning: move constructor is explicitly defaulted but implicitly deleted, probably because a non-static data member or a base class is neither copyable nor movable; definition can either be removed or explicitly deleted [readability-deleted-default]
+ MissingEverything(const MissingEverything &Other) = default;
+ // CHECK-MESSAGES: warning: copy constructor is explicitly defaulted but implicitly deleted, probably because a non-static data member or a base class is not copyable; definition can either be removed or explicitly deleted [readability-deleted-default]
+ MissingEverything &operator=(MissingEverything &&Other) = default;
+ // CHECK-MESSAGES: warning: move assignment operator is explicitly defaulted but implicitly deleted, probably because a base class or a non-static data member is not assignable, e.g. because the latter is marked 'const'; definition can either be removed or explicitly deleted [readability-deleted-default]
+ MissingEverything &operator=(const MissingEverything &Other) = default;
+ // CHECK-MESSAGES: warning: copy assignment operator is explicitly defaulted but implicitly deleted, probably because a base class or a non-static data member is not assignable, e.g. because the latter is marked 'const'; definition can either be removed or explicitly deleted [readability-deleted-default]
+
+private:
+ NoDefault ND;
+};
+
+class NotAssignable {
+public:
+ NotAssignable(NotAssignable &&Other) = default;
+ NotAssignable(const NotAssignable &Other) = default;
+ NotAssignable &operator=(NotAssignable &&Other) = default;
+ // CHECK-MESSAGES: warning: move assignment operator is explicitly defaulted but implicitly deleted
+ NotAssignable &operator=(const NotAssignable &Other) = default;
+ // CHECK-MESSAGES: warning: copy assignment operator is explicitly defaulted but implicitly deleted
+
+private:
+ const int I = 0;
+};
+
+class Movable {
+public:
+ Movable() = default;
+ Movable(Movable &&Other) = default;
+ Movable(const Movable &Other) = delete;
+ Movable &operator=(Movable &&Other) = default;
+ Movable &operator=(const Movable &Other) = delete;
+};
+
+class NotCopyable {
+public:
+ NotCopyable(NotCopyable &&Other) = default;
+ NotCopyable(const NotCopyable &Other) = default;
+ // CHECK-MESSAGES: warning: copy constructor is explicitly defaulted but implicitly deleted
+ NotCopyable &operator=(NotCopyable &&Other) = default;
+ NotCopyable &operator=(const NotCopyable &Other) = default;
+ // CHECK-MESSAGES: warning: copy assignment operator is explicitly defaulted but implicitly deleted
+private:
+ Movable M;
+};
+
+template <typename T> class Templated {
+public:
+ // No warning here, it is a templated class.
+ Templated() = default;
+ Templated(Templated &&Other) = default;
+ Templated(const Templated &Other) = default;
+ Templated &operator=(Templated &&Other) = default;
+ Templated &operator=(const Templated &Other) = default;
+
+ class InnerTemplated {
+ public:
+ // This class is not in itself templated, but we still don't have warning.
+ InnerTemplated() = default;
+ InnerTemplated(InnerTemplated &&Other) = default;
+ InnerTemplated(const InnerTemplated &Other) = default;
+ InnerTemplated &operator=(InnerTemplated &&Other) = default;
+ InnerTemplated &operator=(const InnerTemplated &Other) = default;
+
+ private:
+ T TVar;
+ };
+
+ class InnerNotTemplated {
+ public:
+ // This one could technically have warnings, but currently doesn't.
+ InnerNotTemplated() = default;
+ InnerNotTemplated(InnerNotTemplated &&Other) = default;
+ InnerNotTemplated(const InnerNotTemplated &Other) = default;
+ InnerNotTemplated &operator=(InnerNotTemplated &&Other) = default;
+ InnerNotTemplated &operator=(const InnerNotTemplated &Other) = default;
+
+ private:
+ int I;
+ };
+
+private:
+ const T TVar{};
+};
+
+int FunctionWithInnerClass() {
+ class InnerNotAssignable {
+ public:
+ InnerNotAssignable &operator=(InnerNotAssignable &&Other) = default;
+ // CHECK-MESSAGES: warning: move assignment operator is explicitly defaulted but implicitly deleted
+ private:
+ const int I = 0;
+ };
+ return 1;
+};
+
+template <typename T>
+int TemplateFunctionWithInnerClass() {
+ class InnerNotAssignable {
+ public:
+ InnerNotAssignable &operator=(InnerNotAssignable &&Other) = default;
+ private:
+ const T TVar{};
+ };
+ return 1;
+};
+
+void Foo() {
+ Templated<const int> V1;
+ Templated<int>::InnerTemplated V2;
+ Templated<float>::InnerNotTemplated V3;
+ TemplateFunctionWithInnerClass<int>();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-else-after-return.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-else-after-return.cpp
new file mode 100644
index 0000000..7e95092
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-else-after-return.cpp
@@ -0,0 +1,107 @@
+// RUN: %check_clang_tidy %s readability-else-after-return %t -- -- -std=c++11 -fexceptions
+
+namespace std {
+struct string {
+ string(const char *);
+ ~string();
+};
+} // namespace std
+
+struct my_exception {
+ my_exception(const std::string &s);
+};
+
+void f(int a) {
+ if (a > 0)
+ return;
+ else // comment-0
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'else' after 'return'
+ // CHECK-FIXES: {{^}} // comment-0
+ return;
+
+ if (a > 0) {
+ return;
+ } else { // comment-1
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return'
+ // CHECK-FIXES: {{^}} } // comment-1
+ return;
+ }
+
+ if (a > 0) {
+ f(0);
+ if (a > 10)
+ return;
+ } else {
+ return;
+ }
+
+ if (a > 0)
+ f(0);
+ else if (a > 10)
+ return;
+ else // comment-2
+ // CHECK-FIXES-NOT: {{^}} // comment-2
+ f(0);
+
+ if (a > 0)
+ if (a < 10)
+ return;
+ else // comment-3
+ // CHECK-FIXES-NOT: {{^}} // comment-3
+ f(0);
+ else
+ if (a > 10)
+ return;
+ else // comment-4
+ // CHECK-FIXES-NOT: {{^}} // comment-4
+ f(0);
+
+ if (a > 0) {
+ if (a < 10)
+ return;
+ else // comment-5
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return'
+ // CHECK-FIXES: {{^}} // comment-5
+ f(0);
+ } else {
+ if (a > 10)
+ return;
+ else // comment-6
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return'
+ // CHECK-FIXES: {{^}} // comment-6
+ f(0);
+ }
+}
+
+void foo() {
+ for (unsigned x = 0; x < 42; ++x) {
+ if (x) {
+ continue;
+ } else { // comment-7
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use 'else' after 'continue'
+ // CHECK-FIXES: {{^}} } // comment-7
+ x++;
+ }
+ if (x) {
+ break;
+ } else { // comment-8
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use 'else' after 'break'
+ // CHECK-FIXES: {{^}} } // comment-8
+ x++;
+ }
+ if (x) {
+ throw 42;
+ } else { // comment-9
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use 'else' after 'throw'
+ // CHECK-FIXES: {{^}} } // comment-9
+ x++;
+ }
+ if (x) {
+ throw my_exception("foo");
+ } else { // comment-10
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use 'else' after 'throw'
+ // CHECK-FIXES: {{^}} } // comment-10
+ x++;
+ }
+ }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-function-size-variables-c++17.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-function-size-variables-c++17.cpp
new file mode 100644
index 0000000..8af0d96
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-function-size-variables-c++17.cpp
@@ -0,0 +1,21 @@
+// RUN: %check_clang_tidy %s readability-function-size %t -- -config='{CheckOptions: [{key: readability-function-size.LineThreshold, value: 0}, {key: readability-function-size.StatementThreshold, value: 0}, {key: readability-function-size.BranchThreshold, value: 0}, {key: readability-function-size.ParameterThreshold, value: 5}, {key: readability-function-size.NestingThreshold, value: 2}, {key: readability-function-size.VariableThreshold, value: 1}]}' -- -std=c++17
+
+void structured_bindings() {
+ int a[2] = {1, 2};
+ auto [x, y] = a;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:6: warning: function 'structured_bindings' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 3 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 2 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 3 variables (threshold 1)
+
+#define SWAP(x, y) ({auto& [x0, x1] = x; __typeof__(x) t = {x0, x1}; auto& [y0, y1] = y; auto& [t0, t1] = t; x0 = y0; x1 = y1; y0 = t0; y1 = t1; })
+void variables_13() {
+ int a[2] = {1, 2};
+ int b[2] = {3, 4};
+ SWAP(a, b);
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:6: warning: function 'variables_13' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 4 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 11 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-8]]:6: note: 2 variables (threshold 1)
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-function-size.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-function-size.cpp
new file mode 100644
index 0000000..efb41a1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-function-size.cpp
@@ -0,0 +1,301 @@
+// RUN: %check_clang_tidy %s readability-function-size %t -- -config='{CheckOptions: [{key: readability-function-size.LineThreshold, value: 0}, {key: readability-function-size.StatementThreshold, value: 0}, {key: readability-function-size.BranchThreshold, value: 0}, {key: readability-function-size.ParameterThreshold, value: 5}, {key: readability-function-size.NestingThreshold, value: 2}, {key: readability-function-size.VariableThreshold, value: 1}]}' -- -std=c++11
+
+// Bad formatting is intentional, don't run clang-format over the whole file!
+
+void foo1() {
+}
+
+void foo2() {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'foo2' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-2]]:6: note: 1 statements (threshold 0)
+
+void foo3() {
+;
+
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:6: warning: function 'foo3' exceeds recommended size/complexity
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 3 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 1 statements (threshold 0)
+
+void foo4(int i) { if (i) {} else; {}
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:6: warning: function 'foo4' exceeds recommended size/complexity
+// CHECK-MESSAGES: :[[@LINE-3]]:6: note: 1 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: 3 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 1 branches (threshold 0)
+
+void foo5(int i) {for(;i;)while(i)
+do;while(i);
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:6: warning: function 'foo5' exceeds recommended size/complexity
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: 2 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 7 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 3 branches (threshold 0)
+
+template <typename T> T foo6(T i) {return i;
+}
+int x = foo6(0);
+// CHECK-MESSAGES: :[[@LINE-3]]:25: warning: function 'foo6' exceeds recommended size/complexity
+// CHECK-MESSAGES: :[[@LINE-4]]:25: note: 1 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-5]]:25: note: 1 statements (threshold 0)
+
+void foo7(int p1, int p2, int p3, int p4, int p5, int p6) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'foo7' exceeds recommended size/complexity
+// CHECK-MESSAGES: :[[@LINE-2]]:6: note: 1 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-3]]:6: note: 6 parameters (threshold 5)
+
+void bar1() { [](){;;;;;;;;;;;if(1){}}();
+
+
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:6: warning: function 'bar1' exceeds recommended size/complexity
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 3 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 14 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 1 branches (threshold 0)
+
+void bar2() { class A { void barx() {;;} }; }
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'bar2' exceeds recommended size/complexity
+// CHECK-MESSAGES: :[[@LINE-2]]:6: note: 3 statements (threshold 0)
+//
+// CHECK-MESSAGES: :[[@LINE-4]]:30: warning: function 'barx' exceeds recommended size/complexity
+// CHECK-MESSAGES: :[[@LINE-5]]:30: note: 2 statements (threshold 0)
+
+#define macro() {int x; {int y; {int z;}}}
+
+void baz0() { // 1
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'baz0' exceeds recommended size/complexity
+ // CHECK-MESSAGES: :[[@LINE-2]]:6: note: 28 lines including whitespace and comments (threshold 0)
+ // CHECK-MESSAGES: :[[@LINE-3]]:6: note: 9 statements (threshold 0)
+ int a;
+ { // 2
+ int b;
+ { // 3
+// CHECK-MESSAGES: :[[@LINE-1]]:5: note: nesting level 3 starts here (threshold 2)
+ int c;
+ { // 4
+ int d;
+ }
+ }
+ }
+ { // 2
+ int e;
+ }
+ { // 2
+ { // 3
+// CHECK-MESSAGES: :[[@LINE-1]]:5: note: nesting level 3 starts here (threshold 2)
+ int j;
+ }
+ }
+ macro()
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: note: nesting level 3 starts here (threshold 2)
+ // CHECK-MESSAGES: :[[@LINE-28]]:25: note: expanded from macro 'macro'
+ // CHECK-MESSAGES: :[[@LINE-27]]:6: note: 9 variables (threshold 1)
+}
+
+// check that nested if's are not reported. this was broken initially
+void nesting_if() { // 1
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'nesting_if' exceeds recommended size/complexity
+ // CHECK-MESSAGES: :[[@LINE-2]]:6: note: 23 lines including whitespace and comments (threshold 0)
+ // CHECK-MESSAGES: :[[@LINE-3]]:6: note: 18 statements (threshold 0)
+ // CHECK-MESSAGES: :[[@LINE-4]]:6: note: 6 branches (threshold 0)
+ if (true) { // 2
+ int j;
+ } else if (true) { // 2
+ int j;
+ if (true) { // 3
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: note: nesting level 3 starts here (threshold 2)
+ int j;
+ }
+ } else if (true) { // 2
+ int j;
+ if (true) { // 3
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: note: nesting level 3 starts here (threshold 2)
+ int j;
+ }
+ } else if (true) { // 2
+ int j;
+ }
+ // CHECK-MESSAGES: :[[@LINE-22]]:6: note: 6 variables (threshold 1)
+}
+
+// however this should warn
+void bad_if_nesting() { // 1
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'bad_if_nesting' exceeds recommended size/complexity
+// CHECK-MESSAGES: :[[@LINE-2]]:6: note: 23 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-3]]:6: note: 12 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: 4 branches (threshold 0)
+ if (true) { // 2
+ int j;
+ } else { // 2
+ if (true) { // 3
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: note: nesting level 3 starts here (threshold 2)
+ int j;
+ } else { // 3
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: note: nesting level 3 starts here (threshold 2)
+ if (true) { // 4
+ int j;
+ } else { // 4
+ if (true) { // 5
+ int j;
+ }
+ }
+ }
+ }
+ // CHECK-MESSAGES: :[[@LINE-22]]:6: note: 4 variables (threshold 1)
+}
+
+void variables_0() {
+ int i;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:6: warning: function 'variables_0' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: 2 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 1 statements (threshold 0)
+void variables_1(int i) {
+ int j;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:6: warning: function 'variables_1' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: 2 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 1 statements (threshold 0)
+void variables_2(int i, int j) {
+ ;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:6: warning: function 'variables_2' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: 2 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 1 statements (threshold 0)
+void variables_3() {
+ int i[2];
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:6: warning: function 'variables_3' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: 2 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 1 statements (threshold 0)
+void variables_4() {
+ int i;
+ int j;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:6: warning: function 'variables_4' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 3 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 2 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 2 variables (threshold 1)
+void variables_5() {
+ int i, j;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:6: warning: function 'variables_5' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: 2 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 1 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 2 variables (threshold 1)
+void variables_6() {
+ for (int i;;)
+ for (int j;;)
+ ;
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:6: warning: function 'variables_6' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 4 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 5 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-8]]:6: note: 2 branches (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-9]]:6: note: 2 variables (threshold 1)
+void variables_7() {
+ if (int a = 1)
+ if (int b = 2)
+ ;
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:6: warning: function 'variables_7' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 4 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 7 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-8]]:6: note: 2 branches (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-9]]:6: note: 2 variables (threshold 1)
+void variables_8() {
+ int a[2];
+ for (auto i : a)
+ for (auto j : a)
+ ;
+}
+// CHECK-MESSAGES: :[[@LINE-6]]:6: warning: function 'variables_8' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 5 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-8]]:6: note: 8 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-9]]:6: note: 2 branches (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-10]]:6: note: 3 variables (threshold 1)
+void variables_9() {
+ int a, b;
+ struct A {
+ A(int c, int d) {
+ int e, f;
+ }
+ };
+}
+// CHECK-MESSAGES: :[[@LINE-8]]:6: warning: function 'variables_9' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-9]]:6: note: 7 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-10]]:6: note: 3 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-11]]:6: note: 2 variables (threshold 1)
+// CHECK-MESSAGES: :[[@LINE-9]]:5: warning: function 'A' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-10]]:5: note: 2 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-11]]:5: note: 1 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-12]]:5: note: 2 variables (threshold 1)
+void variables_10() {
+ int a, b;
+ struct A {
+ int c;
+ int d;
+ };
+}
+// CHECK-MESSAGES: :[[@LINE-7]]:6: warning: function 'variables_10' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-8]]:6: note: 6 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-9]]:6: note: 2 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-10]]:6: note: 2 variables (threshold 1)
+void variables_11() {
+ struct S {
+ void bar() {
+ int a, b;
+ }
+ };
+}
+// CHECK-MESSAGES: :[[@LINE-7]]:6: warning: function 'variables_11' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-8]]:6: note: 6 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:10: warning: function 'bar' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-8]]:10: note: 2 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-9]]:10: note: 2 variables (threshold 1)
+void variables_12() {
+ int v;
+ auto test = [](int a, int b) -> void {};
+ test({}, {});
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:6: warning: function 'variables_12' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 4 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 3 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-8]]:6: note: 2 variables (threshold 1)
+void variables_13() {
+ int v;
+ auto test = []() -> void {
+ int a;
+ int b;
+ };
+ test();
+}
+// CHECK-MESSAGES: :[[@LINE-8]]:6: warning: function 'variables_13' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-9]]:6: note: 7 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-10]]:6: note: 5 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-11]]:6: note: 2 variables (threshold 1)
+void variables_14() {
+ (void)({int a = 12; a; });
+ (void)({int a = 12; a; });
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:6: warning: function 'variables_14' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 3 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 6 statements (threshold 0)
+#define SWAP(x, y) ({__typeof__(x) temp = x; x = y; y = temp; })
+void variables_15() {
+ int a = 10, b = 12;
+ SWAP(a, b);
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:6: warning: function 'variables_15' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 3 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 5 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 2 variables (threshold 1)
+#define vardecl(type, name) type name;
+void variables_16() {
+ vardecl(int, a);
+ vardecl(int, b);
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:6: warning: function 'variables_16' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 3 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 4 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 2 variables (threshold 1)
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-identifier-naming-objc.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-identifier-naming-objc.m
new file mode 100644
index 0000000..ab123c2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-identifier-naming-objc.m
@@ -0,0 +1,12 @@
+// RUN: %check_clang_tidy %s readability-identifier-naming %t \
+// RUN: -config='{CheckOptions: \
+// RUN: [{key: readability-identifier-naming.ObjcIvarPrefix, value: '_'}]}' \
+// RUN: --
+
+@interface Foo {
+ int _bar;
+ int barWithoutPrefix;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for objc ivar 'barWithoutPrefix' [readability-identifier-naming]
+ // CHECK-FIXES: int _barWithoutPrefix;
+}
+@end
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-identifier-naming.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-identifier-naming.cpp
new file mode 100644
index 0000000..436e844
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-identifier-naming.cpp
@@ -0,0 +1,476 @@
+// Remove UNSUPPORTED for powerpc64le when the problem introduced by
+// r288563 is resolved.
+// UNSUPPORTED: powerpc64le
+// RUN: %check_clang_tidy %s readability-identifier-naming %t -- \
+// RUN: -config='{CheckOptions: [ \
+// RUN: {key: readability-identifier-naming.AbstractClassCase, value: CamelCase}, \
+// RUN: {key: readability-identifier-naming.AbstractClassPrefix, value: 'A'}, \
+// RUN: {key: readability-identifier-naming.ClassCase, value: CamelCase}, \
+// RUN: {key: readability-identifier-naming.ClassPrefix, value: 'C'}, \
+// RUN: {key: readability-identifier-naming.ClassConstantCase, value: CamelCase}, \
+// RUN: {key: readability-identifier-naming.ClassConstantPrefix, value: 'k'}, \
+// RUN: {key: readability-identifier-naming.ClassMemberCase, value: CamelCase}, \
+// RUN: {key: readability-identifier-naming.ClassMethodCase, value: camelBack}, \
+// RUN: {key: readability-identifier-naming.ConstantCase, value: UPPER_CASE}, \
+// RUN: {key: readability-identifier-naming.ConstantSuffix, value: '_CST'}, \
+// RUN: {key: readability-identifier-naming.ConstexprFunctionCase, value: lower_case}, \
+// RUN: {key: readability-identifier-naming.ConstexprMethodCase, value: lower_case}, \
+// RUN: {key: readability-identifier-naming.ConstexprVariableCase, value: lower_case}, \
+// RUN: {key: readability-identifier-naming.EnumCase, value: CamelCase}, \
+// RUN: {key: readability-identifier-naming.EnumPrefix, value: 'E'}, \
+// RUN: {key: readability-identifier-naming.EnumConstantCase, value: UPPER_CASE}, \
+// RUN: {key: readability-identifier-naming.FunctionCase, value: camelBack}, \
+// RUN: {key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE}, \
+// RUN: {key: readability-identifier-naming.GlobalFunctionCase, value: CamelCase}, \
+// RUN: {key: readability-identifier-naming.GlobalVariableCase, value: lower_case}, \
+// RUN: {key: readability-identifier-naming.GlobalVariablePrefix, value: 'g_'}, \
+// RUN: {key: readability-identifier-naming.InlineNamespaceCase, value: lower_case}, \
+// RUN: {key: readability-identifier-naming.LocalConstantCase, value: CamelCase}, \
+// RUN: {key: readability-identifier-naming.LocalConstantPrefix, value: 'k'}, \
+// RUN: {key: readability-identifier-naming.LocalVariableCase, value: lower_case}, \
+// RUN: {key: readability-identifier-naming.MemberCase, value: CamelCase}, \
+// RUN: {key: readability-identifier-naming.MemberPrefix, value: 'm_'}, \
+// RUN: {key: readability-identifier-naming.ConstantMemberCase, value: lower_case}, \
+// RUN: {key: readability-identifier-naming.PrivateMemberPrefix, value: '__'}, \
+// RUN: {key: readability-identifier-naming.ProtectedMemberPrefix, value: '_'}, \
+// RUN: {key: readability-identifier-naming.PublicMemberCase, value: lower_case}, \
+// RUN: {key: readability-identifier-naming.MethodCase, value: camelBack}, \
+// RUN: {key: readability-identifier-naming.PrivateMethodPrefix, value: '__'}, \
+// RUN: {key: readability-identifier-naming.ProtectedMethodPrefix, value: '_'}, \
+// RUN: {key: readability-identifier-naming.NamespaceCase, value: lower_case}, \
+// RUN: {key: readability-identifier-naming.ParameterCase, value: camelBack}, \
+// RUN: {key: readability-identifier-naming.ParameterPrefix, value: 'a_'}, \
+// RUN: {key: readability-identifier-naming.ConstantParameterCase, value: camelBack}, \
+// RUN: {key: readability-identifier-naming.ConstantParameterPrefix, value: 'i_'}, \
+// RUN: {key: readability-identifier-naming.ParameterPackCase, value: camelBack}, \
+// RUN: {key: readability-identifier-naming.PureFunctionCase, value: lower_case}, \
+// RUN: {key: readability-identifier-naming.PureMethodCase, value: camelBack}, \
+// RUN: {key: readability-identifier-naming.StaticConstantCase, value: UPPER_CASE}, \
+// RUN: {key: readability-identifier-naming.StaticVariableCase, value: camelBack}, \
+// RUN: {key: readability-identifier-naming.StaticVariablePrefix, value: 's_'}, \
+// RUN: {key: readability-identifier-naming.StructCase, value: lower_case}, \
+// RUN: {key: readability-identifier-naming.TemplateParameterCase, value: UPPER_CASE}, \
+// RUN: {key: readability-identifier-naming.TemplateTemplateParameterCase, value: CamelCase}, \
+// RUN: {key: readability-identifier-naming.TemplateUsingCase, value: lower_case}, \
+// RUN: {key: readability-identifier-naming.TemplateUsingPrefix, value: 'u_'}, \
+// RUN: {key: readability-identifier-naming.TypeTemplateParameterCase, value: camelBack}, \
+// RUN: {key: readability-identifier-naming.TypeTemplateParameterSuffix, value: '_t'}, \
+// RUN: {key: readability-identifier-naming.TypedefCase, value: lower_case}, \
+// RUN: {key: readability-identifier-naming.TypedefSuffix, value: '_t'}, \
+// RUN: {key: readability-identifier-naming.UnionCase, value: CamelCase}, \
+// RUN: {key: readability-identifier-naming.UnionPrefix, value: 'U'}, \
+// RUN: {key: readability-identifier-naming.UsingCase, value: lower_case}, \
+// RUN: {key: readability-identifier-naming.ValueTemplateParameterCase, value: camelBack}, \
+// RUN: {key: readability-identifier-naming.VariableCase, value: lower_case}, \
+// RUN: {key: readability-identifier-naming.VirtualMethodCase, value: Camel_Snake_Case}, \
+// RUN: {key: readability-identifier-naming.VirtualMethodPrefix, value: 'v_'}, \
+// RUN: {key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE}, \
+// RUN: {key: readability-identifier-naming.TypeAliasCase, value: camel_Snake_Back}, \
+// RUN: {key: readability-identifier-naming.TypeAliasSuffix, value: '_t'}, \
+// RUN: {key: readability-identifier-naming.IgnoreFailedSplit, value: 0} \
+// RUN: ]}' -- -std=c++11 -fno-delayed-template-parsing \
+// RUN: -I%S/Inputs/readability-identifier-naming \
+// RUN: -isystem %S/Inputs/readability-identifier-naming/system
+
+// clang-format off
+
+#include <system-header.h>
+#include "user-header.h"
+// NO warnings or fixes expected from declarations within header files without
+// the -header-filter= option
+
+namespace FOO_NS {
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: invalid case style for namespace 'FOO_NS' [readability-identifier-naming]
+// CHECK-FIXES: {{^}}namespace foo_ns {{{$}}
+inline namespace InlineNamespace {
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: invalid case style for inline namespace 'InlineNamespace'
+// CHECK-FIXES: {{^}}inline namespace inline_namespace {{{$}}
+
+SYSTEM_NS::structure g_s1;
+// NO warnings or fixes expected as SYSTEM_NS and structure are declared in a header file
+
+USER_NS::object g_s2;
+// NO warnings or fixes expected as USER_NS and object are declared in a header file
+
+SYSTEM_MACRO(var1);
+// NO warnings or fixes expected as var1 is from macro expansion
+
+USER_MACRO(var2);
+// NO warnings or fixes expected as var2 is declared in a macro expansion
+
+#define BLA int FOO_bar
+BLA;
+// NO warnings or fixes expected as FOO_bar is from macro expansion
+
+int global0;
+#define USE_NUMBERED_GLOBAL(number) auto use_global##number = global##number
+USE_NUMBERED_GLOBAL(0);
+// NO warnings or fixes expected as global0 is pieced together in a macro
+// expansion.
+
+int global1;
+#define USE_NUMBERED_BAL(prefix, number) \
+ auto use_##prefix##bal##number = prefix##bal##number
+USE_NUMBERED_BAL(glo, 1);
+// NO warnings or fixes expected as global1 is pieced together in a macro
+// expansion.
+
+int global2;
+#define USE_RECONSTRUCTED(glo, bal) auto use_##glo##bal = glo##bal
+USE_RECONSTRUCTED(glo, bal2);
+// NO warnings or fixes expected as global2 is pieced together in a macro
+// expansion.
+
+int global;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'global'
+// CHECK-FIXES: {{^}}int g_global;{{$}}
+#define USE_IN_MACRO(m) auto use_##m = m
+USE_IN_MACRO(global);
+
+int global3;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'global3'
+// CHECK-FIXES: {{^}}int g_global3;{{$}}
+#define ADD_TO_SELF(m) (m) + (m)
+int g_twice_global3 = ADD_TO_SELF(global3);
+// CHECK-FIXES: {{^}}int g_twice_global3 = ADD_TO_SELF(g_global3);{{$}}
+
+enum my_enumeration {
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for enum 'my_enumeration'
+// CHECK-FIXES: {{^}}enum EMyEnumeration {{{$}}
+ MyConstant = 1,
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for enum constant 'MyConstant'
+// CHECK-FIXES: {{^}} MY_CONSTANT = 1,{{$}}
+ your_CONST = 1,
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for enum constant 'your_CONST'
+// CHECK-FIXES: {{^}} YOUR_CONST = 1,{{$}}
+ THIS_ConstValue = 1,
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for enum constant 'THIS_ConstValue'
+// CHECK-FIXES: {{^}} THIS_CONST_VALUE = 1,{{$}}
+};
+
+constexpr int ConstExpr_variable = MyConstant;
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: invalid case style for constexpr variable 'ConstExpr_variable'
+// CHECK-FIXES: {{^}}constexpr int const_expr_variable = MY_CONSTANT;{{$}}
+
+class my_class {
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for class 'my_class'
+// CHECK-FIXES: {{^}}class CMyClass {{{$}}
+public:
+ my_class();
+// CHECK-FIXES: {{^}} CMyClass();{{$}}
+
+ my_class(void*) : my_class() {}
+// CHECK-FIXES: {{^}} CMyClass(void*) : CMyClass() {}{{$}}
+
+ ~
+ my_class();
+// (space in destructor token test, we could check trigraph but they will be deprecated)
+// CHECK-FIXES: {{^}} ~{{$}}
+// CHECK-FIXES: {{^}} CMyClass();{{$}}
+
+private:
+ const int MEMBER_one_1 = ConstExpr_variable;
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: invalid case style for constant member 'MEMBER_one_1'
+// CHECK-FIXES: {{^}} const int member_one_1 = const_expr_variable;{{$}}
+ int member2 = 2;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for private member 'member2'
+// CHECK-FIXES: {{^}} int __member2 = 2;{{$}}
+ int _memberWithExtraUnderscores_ = 42;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for private member '_memberWithExtraUnderscores_'
+// CHECK-FIXES: {{^}} int __memberWithExtraUnderscores = 42;{{$}}
+
+private:
+ int private_member = 3;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for private member 'private_member'
+// CHECK-FIXES: {{^}} int __private_member = 3;{{$}}
+
+protected:
+ int ProtMember;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for protected member 'ProtMember'
+// CHECK-FIXES: {{^}} int _ProtMember;{{$}}
+
+public:
+ int PubMem;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for public member 'PubMem'
+// CHECK-FIXES: {{^}} int pub_mem;{{$}}
+
+ static const int classConstant;
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: invalid case style for class constant 'classConstant'
+// CHECK-FIXES: {{^}} static const int kClassConstant;{{$}}
+ static int ClassMember_2;
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: invalid case style for class member 'ClassMember_2'
+// CHECK-FIXES: {{^}} static int ClassMember2;{{$}}
+};
+class my_class;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for class 'my_class'
+// CHECK-FIXES: {{^}}class CMyClass;{{$}}
+
+class my_forward_declared_class; // No warning should be triggered.
+
+const int my_class::classConstant = 4;
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: invalid case style for class constant 'classConstant'
+// CHECK-FIXES: {{^}}const int CMyClass::kClassConstant = 4;{{$}}
+
+int my_class::ClassMember_2 = 5;
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: invalid case style for class member 'ClassMember_2'
+// CHECK-FIXES: {{^}}int CMyClass::ClassMember2 = 5;{{$}}
+
+class my_derived_class : public virtual my_class {};
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for class 'my_derived_class'
+// CHECK-FIXES: {{^}}class CMyDerivedClass : public virtual CMyClass {};{{$}}
+
+class CMyWellNamedClass {};
+// No warning expected as this class is well named.
+
+template <typename t_t>
+class CMyWellNamedClass2 : public my_class {
+ // CHECK-FIXES: {{^}}class CMyWellNamedClass2 : public CMyClass {{{$}}
+ t_t my_Bad_Member;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for private member 'my_Bad_Member'
+ // CHECK-FIXES: {{^}} t_t __my_Bad_Member;{{$}}
+ int my_Other_Bad_Member = 42;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for private member 'my_Other_Bad_Member'
+ // CHECK-FIXES: {{^}} int __my_Other_Bad_Member = 42;{{$}}
+public:
+ CMyWellNamedClass2() = default;
+ CMyWellNamedClass2(CMyWellNamedClass2 const&) = default;
+ CMyWellNamedClass2(CMyWellNamedClass2 &&) = default;
+ CMyWellNamedClass2(t_t a_v, void *a_p) : my_class(a_p), my_Bad_Member(a_v) {}
+ // CHECK-FIXES: {{^}} CMyWellNamedClass2(t_t a_v, void *a_p) : CMyClass(a_p), __my_Bad_Member(a_v) {}{{$}}
+
+ CMyWellNamedClass2(t_t a_v) : my_class(), my_Bad_Member(a_v), my_Other_Bad_Member(11) {}
+ // CHECK-FIXES: {{^}} CMyWellNamedClass2(t_t a_v) : CMyClass(), __my_Bad_Member(a_v), __my_Other_Bad_Member(11) {}{{$}}
+};
+void InstantiateClassMethods() {
+ // Ensure we trigger the instantiation of each constructor
+ CMyWellNamedClass2<int> x;
+ CMyWellNamedClass2<int> x2 = x;
+ CMyWellNamedClass2<int> x3 = static_cast<CMyWellNamedClass2<int>&&>(x2);
+ CMyWellNamedClass2<int> x4(42);
+ CMyWellNamedClass2<int> x5(42, nullptr);
+}
+
+template<typename T>
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: invalid case style for type template parameter 'T'
+// CHECK-FIXES: {{^}}template<typename t_t>{{$}}
+class my_templated_class : CMyWellNamedClass {};
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for class 'my_templated_class'
+// CHECK-FIXES: {{^}}class CMyTemplatedClass : CMyWellNamedClass {};{{$}}
+
+template<typename T>
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: invalid case style for type template parameter 'T'
+// CHECK-FIXES: {{^}}template<typename t_t>{{$}}
+class my_other_templated_class : my_templated_class< my_class>, private my_derived_class {};
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for class 'my_other_templated_class'
+// CHECK-FIXES: {{^}}class CMyOtherTemplatedClass : CMyTemplatedClass< CMyClass>, private CMyDerivedClass {};{{$}}
+
+template<typename t_t>
+using mysuper_tpl_t = my_other_templated_class <:: FOO_NS ::my_class>;
+// CHECK-FIXES: {{^}}using mysuper_tpl_t = CMyOtherTemplatedClass <:: foo_ns ::CMyClass>;{{$}}
+
+const int global_Constant = 6;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: invalid case style for global constant 'global_Constant'
+// CHECK-FIXES: {{^}}const int GLOBAL_CONSTANT = 6;{{$}}
+int Global_variable = 7;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'Global_variable'
+// CHECK-FIXES: {{^}}int g_global_variable = 7;{{$}}
+
+void global_function(int PARAMETER_1, int const CONST_parameter) {
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global function 'global_function'
+// CHECK-MESSAGES: :[[@LINE-2]]:26: warning: invalid case style for parameter 'PARAMETER_1'
+// CHECK-MESSAGES: :[[@LINE-3]]:49: warning: invalid case style for constant parameter 'CONST_parameter'
+// CHECK-FIXES: {{^}}void GlobalFunction(int a_parameter1, int const i_constParameter) {{{$}}
+ static const int THIS_static_ConsTant = 4;
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: invalid case style for static constant 'THIS_static_ConsTant'
+// CHECK-FIXES: {{^}} static const int THIS_STATIC_CONS_TANT = 4;{{$}}
+ static int THIS_static_variable;
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: invalid case style for static variable 'THIS_static_variable'
+// CHECK-FIXES: {{^}} static int s_thisStaticVariable;{{$}}
+ int const local_Constant = 3;
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: invalid case style for local constant 'local_Constant'
+// CHECK-FIXES: {{^}} int const kLocalConstant = 3;{{$}}
+ int LOCAL_VARIABLE;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for local variable 'LOCAL_VARIABLE'
+// CHECK-FIXES: {{^}} int local_variable;{{$}}
+
+ int LOCAL_Array__[] = {0, 1, 2};
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for local variable 'LOCAL_Array__'
+// CHECK-FIXES: {{^}} int local_array[] = {0, 1, 2};{{$}}
+
+ for (auto _ : LOCAL_Array__) {
+ }
+}
+
+template<typename ... TYPE_parameters>
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: invalid case style for type template parameter 'TYPE_parameters'
+// CHECK-FIXES: {{^}}template<typename ... typeParameters_t>{{$}}
+void Global_Fun(TYPE_parameters... PARAMETER_PACK) {
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global function 'Global_Fun'
+// CHECK-MESSAGES: :[[@LINE-2]]:36: warning: invalid case style for parameter pack 'PARAMETER_PACK'
+// CHECK-FIXES: {{^}}void GlobalFun(typeParameters_t... parameterPack) {{{$}}
+ global_function(1, 2);
+// CHECK-FIXES: {{^}} GlobalFunction(1, 2);{{$}}
+ FOO_bar = Global_variable;
+// CHECK-FIXES: {{^}} FOO_bar = g_global_variable;{{$}}
+// NO fix expected for FOO_bar declared in macro expansion
+}
+
+template<template<typename> class TPL_parameter, int COUNT_params, typename ... TYPE_parameters>
+// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: invalid case style for template template parameter 'TPL_parameter'
+// CHECK-MESSAGES: :[[@LINE-2]]:54: warning: invalid case style for value template parameter 'COUNT_params'
+// CHECK-MESSAGES: :[[@LINE-3]]:81: warning: invalid case style for type template parameter 'TYPE_parameters'
+// CHECK-FIXES: {{^}}template<template<typename> class TplParameter, int countParams, typename ... typeParameters_t>{{$}}
+class test_CLASS {
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for class 'test_CLASS'
+// CHECK-FIXES: {{^}}class CTestClass {{{$}}
+};
+
+class abstract_class {
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for abstract class 'abstract_class'
+// CHECK-FIXES: {{^}}class AAbstractClass {{{$}}
+ virtual ~abstract_class() = 0;
+// CHECK-FIXES: {{^}} virtual ~AAbstractClass() = 0;{{$}}
+ virtual void VIRTUAL_METHOD();
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: invalid case style for virtual method 'VIRTUAL_METHOD'
+// CHECK-FIXES: {{^}} virtual void v_Virtual_Method();{{$}}
+ void non_Virtual_METHOD() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for private method 'non_Virtual_METHOD'
+// CHECK-FIXES: {{^}} void __non_Virtual_METHOD() {}{{$}}
+
+public:
+ static void CLASS_METHOD() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: invalid case style for class method 'CLASS_METHOD'
+// CHECK-FIXES: {{^}} static void classMethod() {}{{$}}
+
+ constexpr int CST_expr_Method() { return 2; }
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: invalid case style for constexpr method 'CST_expr_Method'
+// CHECK-FIXES: {{^}} constexpr int cst_expr_method() { return 2; }{{$}}
+
+private:
+ void PRIVate_Method();
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for private method 'PRIVate_Method'
+// CHECK-FIXES: {{^}} void __PRIVate_Method();{{$}}
+protected:
+ void protected_Method();
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for protected method 'protected_Method'
+// CHECK-FIXES: {{^}} void _protected_Method();{{$}}
+public:
+ void public_Method();
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for method 'public_Method'
+// CHECK-FIXES: {{^}} void publicMethod();{{$}}
+};
+
+constexpr int CE_function() { return 3; }
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: invalid case style for constexpr function 'CE_function'
+// CHECK-FIXES: {{^}}constexpr int ce_function() { return 3; }{{$}}
+
+struct THIS___Structure {
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for struct 'THIS___Structure'
+// CHECK-FIXES: {{^}}struct this_structure {{{$}}
+ THIS___Structure();
+// CHECK-FIXES: {{^}} this_structure();{{$}}
+
+ union __MyUnion_is_wonderful__ {};
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for union '__MyUnion_is_wonderful__'
+// CHECK-FIXES: {{^}} union UMyUnionIsWonderful {};{{$}}
+};
+
+typedef THIS___Structure struct_type;
+// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: invalid case style for typedef 'struct_type'
+// CHECK-FIXES: {{^}}typedef this_structure struct_type_t;{{$}}
+
+struct_type GlobalTypedefTestFunction(struct_type a_argument1) {
+// CHECK-FIXES: {{^}}struct_type_t GlobalTypedefTestFunction(struct_type_t a_argument1) {
+ struct_type typedef_test_1;
+// CHECK-FIXES: {{^}} struct_type_t typedef_test_1;
+}
+
+using my_struct_type = THIS___Structure;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for type alias 'my_struct_type'
+// CHECK-FIXES: {{^}}using my_Struct_Type_t = this_structure;{{$}}
+
+template<typename t_t>
+using SomeOtherTemplate = my_other_templated_class <:: FOO_NS ::my_class>;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for type alias 'SomeOtherTemplate'
+// CHECK-FIXES: {{^}}using some_Other_Template_t = CMyOtherTemplatedClass <:: foo_ns ::CMyClass>;{{$}}
+
+static void static_Function() {
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: invalid case style for function 'static_Function'
+// CHECK-FIXES: {{^}}static void staticFunction() {{{$}}
+
+ ::FOO_NS::InlineNamespace::abstract_class::CLASS_METHOD();
+// CHECK-FIXES: {{^}} ::foo_ns::inline_namespace::AAbstractClass::classMethod();{{$}}
+ ::FOO_NS::InlineNamespace::static_Function();
+// CHECK-FIXES: {{^}} ::foo_ns::inline_namespace::staticFunction();{{$}}
+
+ using ::FOO_NS::InlineNamespace::CE_function;
+// CHECK-FIXES: {{^}} using ::foo_ns::inline_namespace::ce_function;{{$}}
+
+ unsigned MY_LOCAL_array[] = {1,2,3};
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: invalid case style for local variable 'MY_LOCAL_array'
+// CHECK-FIXES: {{^}} unsigned my_local_array[] = {1,2,3};{{$}}
+
+ unsigned const MyConstLocal_array[] = {1,2,3};
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: invalid case style for local constant 'MyConstLocal_array'
+// CHECK-FIXES: {{^}} unsigned const kMyConstLocalArray[] = {1,2,3};{{$}}
+
+ static unsigned MY_STATIC_array[] = {1,2,3};
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: invalid case style for static variable 'MY_STATIC_array'
+// CHECK-FIXES: {{^}} static unsigned s_myStaticArray[] = {1,2,3};{{$}}
+
+ static unsigned const MyConstStatic_array[] = {1,2,3};
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: invalid case style for static constant 'MyConstStatic_array'
+// CHECK-FIXES: {{^}} static unsigned const MY_CONST_STATIC_ARRAY[] = {1,2,3};{{$}}
+
+ char MY_LOCAL_string[] = "123";
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for local variable 'MY_LOCAL_string'
+// CHECK-FIXES: {{^}} char my_local_string[] = "123";{{$}}
+
+ char const MyConstLocal_string[] = "123";
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: invalid case style for local constant 'MyConstLocal_string'
+// CHECK-FIXES: {{^}} char const kMyConstLocalString[] = "123";{{$}}
+
+ static char MY_STATIC_string[] = "123";
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: invalid case style for static variable 'MY_STATIC_string'
+// CHECK-FIXES: {{^}} static char s_myStaticString[] = "123";{{$}}
+
+ static char const MyConstStatic_string[] = "123";
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: invalid case style for static constant 'MyConstStatic_string'
+// CHECK-FIXES: {{^}} static char const MY_CONST_STATIC_STRING[] = "123";{{$}}
+}
+
+#define MY_TEST_Macro(X) X()
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for macro definition 'MY_TEST_Macro'
+// CHECK-FIXES: {{^}}#define MY_TEST_MACRO(X) X()
+
+void MY_TEST_Macro(function) {}
+// CHECK-FIXES: {{^}}void MY_TEST_MACRO(function) {}
+}
+}
+
+template <typename t_t> struct a {
+ typename t_t::template b<> c;
+
+ char const MY_ConstMember_string[4] = "123";
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: invalid case style for constant member 'MY_ConstMember_string'
+// CHECK-FIXES: {{^}} char const my_const_member_string[4] = "123";{{$}}
+
+ static char const MyConstClass_string[];
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: invalid case style for class constant 'MyConstClass_string'
+// CHECK-FIXES: {{^}} static char const kMyConstClassString[];{{$}}
+};
+
+template<typename t_t>
+char const a<t_t>::MyConstClass_string[] = "123";
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: invalid case style for class constant 'MyConstClass_string'
+// CHECK-FIXES: {{^}}char const a<t_t>::kMyConstClassString[] = "123";{{$}}
+
+template <template <typename> class A> struct b { A<int> c; };
+
+unsigned MY_GLOBAL_array[] = {1,2,3};
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for global variable 'MY_GLOBAL_array'
+// CHECK-FIXES: {{^}}unsigned g_my_global_array[] = {1,2,3};{{$}}
+
+unsigned const MyConstGlobal_array[] = {1,2,3};
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: invalid case style for global constant 'MyConstGlobal_array'
+// CHECK-FIXES: {{^}}unsigned const MY_CONST_GLOBAL_ARRAY[] = {1,2,3};{{$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-implicit-bool-conversion-allow-in-conditions.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-implicit-bool-conversion-allow-in-conditions.cpp
new file mode 100644
index 0000000..c50b798
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-implicit-bool-conversion-allow-in-conditions.cpp
@@ -0,0 +1,72 @@
+// RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t \
+// RUN: -config='{CheckOptions: \
+// RUN: [{key: readability-implicit-bool-conversion.AllowIntegerConditions, value: 1}, \
+// RUN: {key: readability-implicit-bool-conversion.AllowPointerConditions, value: 1}]}' \
+// RUN: -- -std=c++11
+
+template<typename T>
+void functionTaking(T);
+
+int functionReturningInt();
+int* functionReturningPointer();
+
+struct Struct {
+ int member;
+ unsigned bitfield : 1;
+};
+
+
+void regularImplicitConversionIntegerToBoolIsNotIgnored() {
+ int integer = 0;
+ functionTaking<bool>(integer);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool [readability-implicit-bool-conversion]
+ // CHECK-FIXES: functionTaking<bool>(integer != 0);
+}
+
+void implicitConversionIntegerToBoolInConditionalsIsAllowed() {
+ Struct s = {};
+ if (s.member) {}
+ if (!s.member) {}
+ if (s.bitfield) {}
+ if (!s.bitfield) {}
+ if (functionReturningInt()) {}
+ if (!functionReturningInt()) {}
+ if (functionReturningInt() && functionReturningPointer()) {}
+ if (!functionReturningInt() && !functionReturningPointer()) {}
+ for (; functionReturningInt(); ) {}
+ for (; functionReturningPointer(); ) {}
+ for (; functionReturningInt() && !functionReturningPointer() || (!functionReturningInt() && functionReturningPointer()); ) {}
+ while (functionReturningInt()) {}
+ while (functionReturningPointer()) {}
+ while (functionReturningInt() && !functionReturningPointer() || (!functionReturningInt() && functionReturningPointer())) {}
+ int value1 = functionReturningInt() ? 1 : 2;
+ int value2 = !functionReturningInt() ? 1 : 2;
+ int value3 = (functionReturningInt() && functionReturningPointer() || !functionReturningInt()) ? 1 : 2;
+ int value4 = functionReturningInt() ?: value3;
+ int *p1 = functionReturningPointer() ?: &value3;
+}
+
+void regularImplicitConversionPointerToBoolIsNotIgnored() {
+ int* pointer = nullptr;
+ functionTaking<bool>(pointer);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int *' -> bool
+ // CHECK-FIXES: functionTaking<bool>(pointer != nullptr);
+
+ int Struct::* memberPointer = &Struct::member;
+ functionTaking<bool>(memberPointer);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int Struct::*' -> bool
+ // CHECK-FIXES: functionTaking<bool>(memberPointer != nullptr);
+}
+
+void implicitConversionPointerToBoolInConditionalsIsAllowed() {
+ if (functionReturningPointer()) {}
+ if (not functionReturningPointer()) {}
+ int value1 = functionReturningPointer() ? 1 : 2;
+ int value2 = (not functionReturningPointer()) ? 1 : 2;
+
+ int Struct::* memberPointer = &Struct::member;
+ if (memberPointer) {}
+ if (memberPointer) {}
+ int value3 = memberPointer ? 1 : 2;
+ int value4 = (not memberPointer) ? 1 : 2;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-implicit-bool-conversion-cxx98.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-implicit-bool-conversion-cxx98.cpp
new file mode 100644
index 0000000..587f7e2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-implicit-bool-conversion-cxx98.cpp
@@ -0,0 +1,45 @@
+// RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t -- -- -std=c++98
+
+// We need NULL macro, but some buildbots don't like including <cstddef> header
+// This is a portable way of getting it to work
+#undef NULL
+#define NULL 0L
+
+template<typename T>
+void functionTaking(T);
+
+struct Struct {
+ int member;
+};
+
+void useOldNullMacroInReplacements() {
+ int* pointer = NULL;
+ functionTaking<bool>(pointer);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int *' -> bool [readability-implicit-bool-conversion]
+ // CHECK-FIXES: functionTaking<bool>(pointer != 0);
+
+ int Struct::* memberPointer = NULL;
+ functionTaking<bool>(!memberPointer);
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit conversion 'int Struct::*' -> bool
+ // CHECK-FIXES: functionTaking<bool>(memberPointer == 0);
+}
+
+void fixFalseLiteralConvertingToNullPointer() {
+ functionTaking<int*>(false);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion bool -> 'int *'
+ // CHECK-FIXES: functionTaking<int*>(0);
+
+ int* pointer = NULL;
+ if (pointer == false) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: implicit conversion bool -> 'int *'
+ // CHECK-FIXES: if (pointer == 0) {}
+
+ functionTaking<int Struct::*>(false);
+ // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion bool -> 'int Struct::*'
+ // CHECK-FIXES: functionTaking<int Struct::*>(0);
+
+ int Struct::* memberPointer = NULL;
+ if (memberPointer != false) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion bool -> 'int Struct::*'
+ // CHECK-FIXES: if (memberPointer != 0) {}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-implicit-bool-conversion.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-implicit-bool-conversion.cpp
new file mode 100644
index 0000000..0bdd670
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-implicit-bool-conversion.cpp
@@ -0,0 +1,439 @@
+// RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t
+
+// We need NULL macro, but some buildbots don't like including <cstddef> header
+// This is a portable way of getting it to work
+#undef NULL
+#define NULL 0L
+
+template<typename T>
+void functionTaking(T);
+
+struct Struct {
+ int member;
+};
+
+
+////////// Implicit conversion from bool.
+
+void implicitConversionFromBoolSimpleCases() {
+ bool boolean = true;
+
+ functionTaking<bool>(boolean);
+
+ functionTaking<int>(boolean);
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit conversion bool -> 'int' [readability-implicit-bool-conversion]
+ // CHECK-FIXES: functionTaking<int>(static_cast<int>(boolean));
+
+ functionTaking<unsigned long>(boolean);
+ // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion bool -> 'unsigned long'
+ // CHECK-FIXES: functionTaking<unsigned long>(static_cast<unsigned long>(boolean));
+
+ functionTaking<char>(boolean);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion bool -> 'char'
+ // CHECK-FIXES: functionTaking<char>(static_cast<char>(boolean));
+
+ functionTaking<float>(boolean);
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit conversion bool -> 'float'
+ // CHECK-FIXES: functionTaking<float>(static_cast<float>(boolean));
+
+ functionTaking<double>(boolean);
+ // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: implicit conversion bool -> 'double'
+ // CHECK-FIXES: functionTaking<double>(static_cast<double>(boolean));
+}
+
+float implicitConversionFromBoolInReturnValue() {
+ bool boolean = false;
+ return boolean;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit conversion bool -> 'float'
+ // CHECK-FIXES: return static_cast<float>(boolean);
+}
+
+void implicitConversionFromBoolInSingleBoolExpressions(bool b1, bool b2) {
+ bool boolean = true;
+ boolean = b1 ^ b2;
+ boolean = b1 && b2;
+ boolean |= !b1 || !b2;
+ boolean &= b1;
+ boolean = b1 == true;
+ boolean = b2 != false;
+
+ int integer = boolean - 3;
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: implicit conversion bool -> 'int'
+ // CHECK-FIXES: int integer = static_cast<int>(boolean) - 3;
+
+ float floating = boolean / 0.3f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit conversion bool -> 'float'
+ // CHECK-FIXES: float floating = static_cast<float>(boolean) / 0.3f;
+
+ char character = boolean;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit conversion bool -> 'char'
+ // CHECK-FIXES: char character = static_cast<char>(boolean);
+}
+
+void implicitConversionFromBoollInComplexBoolExpressions() {
+ bool boolean = true;
+ bool anotherBoolean = false;
+
+ int integer = boolean && anotherBoolean;
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: implicit conversion bool -> 'int'
+ // CHECK-FIXES: int integer = static_cast<int>(boolean && anotherBoolean);
+
+ unsigned long unsignedLong = (! boolean) + 4ul;
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit conversion bool -> 'unsigned long'
+ // CHECK-FIXES: unsigned long unsignedLong = static_cast<unsigned long>(! boolean) + 4ul;
+
+ float floating = (boolean || anotherBoolean) * 0.3f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit conversion bool -> 'float'
+ // CHECK-FIXES: float floating = static_cast<float>(boolean || anotherBoolean) * 0.3f;
+
+ double doubleFloating = (boolean && (anotherBoolean || boolean)) * 0.3;
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: implicit conversion bool -> 'double'
+ // CHECK-FIXES: double doubleFloating = static_cast<double>(boolean && (anotherBoolean || boolean)) * 0.3;
+}
+
+void implicitConversionFromBoolLiterals() {
+ functionTaking<int>(true);
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit conversion bool -> 'int'
+ // CHECK-FIXES: functionTaking<int>(1);
+
+ functionTaking<unsigned long>(false);
+ // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion bool -> 'unsigned long'
+ // CHECK-FIXES: functionTaking<unsigned long>(0u);
+
+ functionTaking<signed char>(true);
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: implicit conversion bool -> 'signed char'
+ // CHECK-FIXES: functionTaking<signed char>(1);
+
+ functionTaking<float>(false);
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit conversion bool -> 'float'
+ // CHECK-FIXES: functionTaking<float>(0.0f);
+
+ functionTaking<double>(true);
+ // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: implicit conversion bool -> 'double'
+ // CHECK-FIXES: functionTaking<double>(1.0);
+}
+
+void implicitConversionFromBoolInComparisons() {
+ bool boolean = true;
+ int integer = 0;
+
+ functionTaking<bool>(boolean == integer);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion bool -> 'int'
+ // CHECK-FIXES: functionTaking<bool>(static_cast<int>(boolean) == integer);
+
+ functionTaking<bool>(integer != boolean);
+ // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: implicit conversion bool -> 'int'
+ // CHECK-FIXES: functionTaking<bool>(integer != static_cast<int>(boolean));
+}
+
+void ignoreBoolComparisons() {
+ bool boolean = true;
+ bool anotherBoolean = false;
+
+ functionTaking<bool>(boolean == anotherBoolean);
+ functionTaking<bool>(boolean != anotherBoolean);
+}
+
+void ignoreExplicitCastsFromBool() {
+ bool boolean = true;
+
+ int integer = static_cast<int>(boolean) + 3;
+ float floating = static_cast<float>(boolean) * 0.3f;
+ char character = static_cast<char>(boolean);
+}
+
+void ignoreImplicitConversionFromBoolInMacroExpansions() {
+ bool boolean = true;
+
+ #define CAST_FROM_BOOL_IN_MACRO_BODY boolean + 3
+ int integerFromMacroBody = CAST_FROM_BOOL_IN_MACRO_BODY;
+
+ #define CAST_FROM_BOOL_IN_MACRO_ARGUMENT(x) x + 3
+ int integerFromMacroArgument = CAST_FROM_BOOL_IN_MACRO_ARGUMENT(boolean);
+}
+
+namespace ignoreImplicitConversionFromBoolInTemplateInstantiations {
+
+template<typename T>
+void templateFunction() {
+ bool boolean = true;
+ T uknownType = boolean + 3;
+}
+
+void useOfTemplateFunction() {
+ templateFunction<int>();
+}
+
+} // namespace ignoreImplicitConversionFromBoolInTemplateInstantiations
+
+////////// Implicit conversions to bool.
+
+void implicitConversionToBoolSimpleCases() {
+ int integer = 10;
+ functionTaking<bool>(integer);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
+ // CHECK-FIXES: functionTaking<bool>(integer != 0);
+
+ unsigned long unsignedLong = 10;
+ functionTaking<bool>(unsignedLong);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'unsigned long' -> bool
+ // CHECK-FIXES: functionTaking<bool>(unsignedLong != 0u);
+
+ float floating = 0.0f;
+ functionTaking<bool>(floating);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> bool
+ // CHECK-FIXES: functionTaking<bool>(floating != 0.0f);
+
+ double doubleFloating = 1.0f;
+ functionTaking<bool>(doubleFloating);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'double' -> bool
+ // CHECK-FIXES: functionTaking<bool>(doubleFloating != 0.0);
+
+ signed char character = 'a';
+ functionTaking<bool>(character);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'signed char' -> bool
+ // CHECK-FIXES: functionTaking<bool>(character != 0);
+
+ int* pointer = nullptr;
+ functionTaking<bool>(pointer);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int *' -> bool
+ // CHECK-FIXES: functionTaking<bool>(pointer != nullptr);
+
+ auto pointerToMember = &Struct::member;
+ functionTaking<bool>(pointerToMember);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int Struct::*' -> bool
+ // CHECK-FIXES: functionTaking<bool>(pointerToMember != nullptr);
+}
+
+void implicitConversionToBoolInSingleExpressions() {
+ int integer = 10;
+ bool boolComingFromInt = integer;
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: implicit conversion 'int' -> bool
+ // CHECK-FIXES: bool boolComingFromInt = integer != 0;
+
+ float floating = 10.0f;
+ bool boolComingFromFloat = floating;
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: implicit conversion 'float' -> bool
+ // CHECK-FIXES: bool boolComingFromFloat = floating != 0.0f;
+
+ signed char character = 'a';
+ bool boolComingFromChar = character;
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: implicit conversion 'signed char' -> bool
+ // CHECK-FIXES: bool boolComingFromChar = character != 0;
+
+ int* pointer = nullptr;
+ bool boolComingFromPointer = pointer;
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit conversion 'int *' -> bool
+ // CHECK-FIXES: bool boolComingFromPointer = pointer != nullptr;
+}
+
+void implicitConversionToBoolInComplexExpressions() {
+ bool boolean = true;
+
+ int integer = 10;
+ int anotherInteger = 20;
+ bool boolComingFromInteger = integer + anotherInteger;
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit conversion 'int' -> bool
+ // CHECK-FIXES: bool boolComingFromInteger = (integer + anotherInteger) != 0;
+
+ float floating = 0.2f;
+ bool boolComingFromFloating = floating - 0.3f || boolean;
+ // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion 'float' -> bool
+ // CHECK-FIXES: bool boolComingFromFloating = ((floating - 0.3f) != 0.0f) || boolean;
+
+ double doubleFloating = 0.3;
+ bool boolComingFromDoubleFloating = (doubleFloating - 0.4) && boolean;
+ // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit conversion 'double' -> bool
+ // CHECK-FIXES: bool boolComingFromDoubleFloating = ((doubleFloating - 0.4) != 0.0) && boolean;
+}
+
+void implicitConversionInNegationExpressions() {
+ int integer = 10;
+ bool boolComingFromNegatedInt = !integer;
+ // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: implicit conversion 'int' -> bool
+ // CHECK-FIXES: bool boolComingFromNegatedInt = integer == 0;
+
+ float floating = 10.0f;
+ bool boolComingFromNegatedFloat = ! floating;
+ // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit conversion 'float' -> bool
+ // CHECK-FIXES: bool boolComingFromNegatedFloat = floating == 0.0f;
+
+ signed char character = 'a';
+ bool boolComingFromNegatedChar = (! character);
+ // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit conversion 'signed char' -> bool
+ // CHECK-FIXES: bool boolComingFromNegatedChar = (character == 0);
+
+ int* pointer = nullptr;
+ bool boolComingFromNegatedPointer = not pointer;
+ // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: implicit conversion 'int *' -> bool
+ // CHECK-FIXES: bool boolComingFromNegatedPointer = pointer == nullptr;
+}
+
+void implicitConversionToBoolInControlStatements() {
+ int integer = 10;
+ if (integer) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: implicit conversion 'int' -> bool
+ // CHECK-FIXES: if (integer != 0) {}
+
+ long int longInteger = 0.2f;
+ for (;longInteger;) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: implicit conversion 'long' -> bool
+ // CHECK-FIXES: for (;longInteger != 0;) {}
+
+ float floating = 0.3f;
+ while (floating) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit conversion 'float' -> bool
+ // CHECK-FIXES: while (floating != 0.0f) {}
+
+ double doubleFloating = 0.4;
+ do {} while (doubleFloating);
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: implicit conversion 'double' -> bool
+ // CHECK-FIXES: do {} while (doubleFloating != 0.0);
+}
+
+bool implicitConversionToBoolInReturnValue() {
+ float floating = 1.0f;
+ return floating;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit conversion 'float' -> bool
+ // CHECK-FIXES: return floating != 0.0f;
+}
+
+void implicitConversionToBoolFromLiterals() {
+ functionTaking<bool>(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
+ // CHECK-FIXES: functionTaking<bool>(false);
+
+ functionTaking<bool>(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
+ // CHECK-FIXES: functionTaking<bool>(true);
+
+ functionTaking<bool>(2ul);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'unsigned long' -> bool
+ // CHECK-FIXES: functionTaking<bool>(true);
+
+
+ functionTaking<bool>(0.0f);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> bool
+ // CHECK-FIXES: functionTaking<bool>(false);
+
+ functionTaking<bool>(1.0f);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> bool
+ // CHECK-FIXES: functionTaking<bool>(true);
+
+ functionTaking<bool>(2.0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'double' -> bool
+ // CHECK-FIXES: functionTaking<bool>(true);
+
+
+ functionTaking<bool>('\0');
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'char' -> bool
+ // CHECK-FIXES: functionTaking<bool>(false);
+
+ functionTaking<bool>('a');
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'char' -> bool
+ // CHECK-FIXES: functionTaking<bool>(true);
+
+
+ functionTaking<bool>("");
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'const char *' -> bool
+ // CHECK-FIXES: functionTaking<bool>(true);
+
+ functionTaking<bool>("abc");
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'const char *' -> bool
+ // CHECK-FIXES: functionTaking<bool>(true);
+
+ functionTaking<bool>(NULL);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'long' -> bool
+ // CHECK-FIXES: functionTaking<bool>(false);
+}
+
+void implicitConversionToBoolFromUnaryMinusAndZeroLiterals() {
+ functionTaking<bool>(-0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
+ // CHECK-FIXES: functionTaking<bool>((-0) != 0);
+
+ functionTaking<bool>(-0.0f);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> bool
+ // CHECK-FIXES: functionTaking<bool>((-0.0f) != 0.0f);
+
+ functionTaking<bool>(-0.0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'double' -> bool
+ // CHECK-FIXES: functionTaking<bool>((-0.0) != 0.0);
+}
+
+void implicitConversionToBoolInWithOverloadedOperators() {
+ struct UserStruct {
+ int operator()(int x) { return x; }
+ int operator+(int y) { return y; }
+ };
+
+ UserStruct s;
+
+ functionTaking<bool>(s(0));
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
+ // CHECK-FIXES: functionTaking<bool>(s(0) != 0);
+
+ functionTaking<bool>(s + 2);
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
+ // CHECK-FIXES: functionTaking<bool>((s + 2) != 0);
+}
+
+int functionReturningInt();
+int* functionReturningPointer();
+
+void ignoreImplicitConversionToBoolWhenDeclaringVariableInControlStatements() {
+ if (int integer = functionReturningInt()) {}
+
+ while (int* pointer = functionReturningPointer()) {}
+}
+
+void ignoreExplicitCastsToBool() {
+ int integer = 10;
+ bool boolComingFromInt = static_cast<bool>(integer);
+
+ float floating = 10.0f;
+ bool boolComingFromFloat = static_cast<bool>(floating);
+
+ char character = 'a';
+ bool boolComingFromChar = static_cast<bool>(character);
+
+ int* pointer = nullptr;
+ bool booleanComingFromPointer = static_cast<bool>(pointer);
+}
+
+void ignoreImplicitConversionToBoolInMacroExpansions() {
+ int integer = 3;
+
+ #define CAST_TO_BOOL_IN_MACRO_BODY integer && false
+ bool boolFromMacroBody = CAST_TO_BOOL_IN_MACRO_BODY;
+
+ #define CAST_TO_BOOL_IN_MACRO_ARGUMENT(x) x || true
+ bool boolFromMacroArgument = CAST_TO_BOOL_IN_MACRO_ARGUMENT(integer);
+}
+
+namespace ignoreImplicitConversionToBoolInTemplateInstantiations {
+
+template<typename T>
+void templateFunction() {
+ T unknownType = 0;
+ bool boolean = unknownType;
+}
+
+void useOfTemplateFunction() {
+ templateFunction<int>();
+}
+
+} // namespace ignoreImplicitConversionToBoolInTemplateInstantiations
+
+namespace ignoreUserDefinedConversionOperator {
+
+struct StructWithUserConversion {
+ operator bool();
+};
+
+void useOfUserConversion() {
+ StructWithUserConversion structure;
+ functionTaking<bool>(structure);
+}
+
+} // namespace ignoreUserDefinedConversionOperator
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-inconsistent-declaration-parameter-name-macros.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-inconsistent-declaration-parameter-name-macros.cpp
new file mode 100644
index 0000000..c06bbfb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-inconsistent-declaration-parameter-name-macros.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s readability-inconsistent-declaration-parameter-name %t -- \
+// RUN: -config="{CheckOptions: [{key: readability-inconsistent-declaration-parameter-name.IgnoreMacros, value: 0}]}" \
+// RUN: -- -std=c++11
+
+#define MACRO() \
+ void f(int x);
+
+struct S {
+ MACRO();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: function 'S::f' has a definition with different parameter names
+};
+
+void S::f(int y) {
+}
+
+//////////////////////////////////////////////////////
+
+#define DECLARE_FUNCTION_WITH_PARAM_NAME(function_name, param_name) \
+ void function_name(int param_name)
+
+// CHECK-MESSAGES: :[[@LINE+1]]:34: warning: function 'macroFunction' has 1 other declaration with different parameter names [readability-inconsistent-declaration-parameter-name]
+DECLARE_FUNCTION_WITH_PARAM_NAME(macroFunction, a);
+// CHECK-MESSAGES: :[[@LINE+2]]:34: note: the 1st inconsistent declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:34: note: differing parameters are named here: ('b'), in the other declaration: ('a')
+DECLARE_FUNCTION_WITH_PARAM_NAME(macroFunction, b);
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-inconsistent-declaration-parameter-name-strict.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-inconsistent-declaration-parameter-name-strict.cpp
new file mode 100644
index 0000000..90ac45f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-inconsistent-declaration-parameter-name-strict.cpp
@@ -0,0 +1,11 @@
+// RUN: %check_clang_tidy %s readability-inconsistent-declaration-parameter-name %t -- \
+// RUN: -config="{CheckOptions: [{key: readability-inconsistent-declaration-parameter-name.Strict, value: 1}]}" \
+// RUN: -- -std=c++11
+
+void inconsistentFunction(int a, int b, int c);
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'inconsistentFunction' has 1 other declaration with different parameter names
+void inconsistentFunction(int prefixA, int b, int cSuffix);
+// CHECK-MESSAGES: :[[@LINE-1]]:6: note: the 1st inconsistent declaration seen here
+// CHECK-MESSAGES: :[[@LINE-2]]:6: note: differing parameters are named here: ('prefixA', 'cSuffix'), in the other declaration: ('a', 'c')
+void inconsistentFunction(int a, int b, int c);
+void inconsistentFunction(int /*c*/, int /*c*/, int /*c*/);
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-inconsistent-declaration-parameter-name.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-inconsistent-declaration-parameter-name.cpp
new file mode 100644
index 0000000..c98258b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-inconsistent-declaration-parameter-name.cpp
@@ -0,0 +1,193 @@
+// RUN: %check_clang_tidy %s readability-inconsistent-declaration-parameter-name %t -- -- -std=c++11 -fno-delayed-template-parsing
+
+void consistentFunction(int a, int b, int c);
+void consistentFunction(int a, int b, int c);
+void consistentFunction(int prefixA, int b, int cSuffix);
+void consistentFunction(int a, int b, int c);
+void consistentFunction(int a, int b, int /*c*/);
+void consistentFunction(int /*c*/, int /*c*/, int /*c*/);
+
+//////////////////////////////////////////////////////
+
+// CHECK-MESSAGES: :[[@LINE+1]]:6: warning: function 'inconsistentFunction' has 2 other declarations with different parameter names [readability-inconsistent-declaration-parameter-name]
+void inconsistentFunction(int a, int b, int c);
+// CHECK-MESSAGES: :[[@LINE+2]]:6: note: the 1st inconsistent declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('d', 'e', 'f'), in the other declaration: ('a', 'b', 'c')
+void inconsistentFunction(int d, int e, int f);
+// CHECK-MESSAGES: :[[@LINE+2]]:6: note: the 2nd inconsistent declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('x', 'y', 'z'), in the other declaration: ('a', 'b', 'c')
+void inconsistentFunction(int x, int y, int z);
+
+//////////////////////////////////////////////////////
+
+// CHECK-MESSAGES: :[[@LINE+4]]:6: warning: function 'inconsistentFunctionWithVisibleDefinition' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name]
+// CHECK-MESSAGES: :[[@LINE+9]]:6: note: the definition seen here
+// CHECK-MESSAGES: :[[@LINE+2]]:6: note: differing parameters are named here: ('a'), in definition: ('c')
+// CHECK-FIXES: void inconsistentFunctionWithVisibleDefinition(int c);
+void inconsistentFunctionWithVisibleDefinition(int a);
+// CHECK-MESSAGES: :[[@LINE+4]]:6: warning: function 'inconsistentFunctionWithVisibleDefinition' has a definition
+// CHECK-MESSAGES: :[[@LINE+4]]:6: note: the definition seen here
+// CHECK-MESSAGES: :[[@LINE+2]]:6: note: differing parameters are named here: ('b'), in definition: ('c')
+// CHECK-FIXES: void inconsistentFunctionWithVisibleDefinition(int c);
+void inconsistentFunctionWithVisibleDefinition(int b);
+void inconsistentFunctionWithVisibleDefinition(int c) { c; }
+
+// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function 'inconsidentFunctionWithUnreferencedParameterInDefinition' has a definition
+// CHECK-MESSAGES: :[[@LINE+3]]:6: note: the definition seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('a'), in definition: ('b')
+void inconsidentFunctionWithUnreferencedParameterInDefinition(int a);
+void inconsidentFunctionWithUnreferencedParameterInDefinition(int b) {}
+
+//////////////////////////////////////////////////////
+
+struct Struct {
+// CHECK-MESSAGES: :[[@LINE+4]]:8: warning: function 'Struct::inconsistentFunction' has a definition
+// CHECK-MESSAGES: :[[@LINE+6]]:14: note: the definition seen here
+// CHECK-MESSAGES: :[[@LINE+2]]:8: note: differing parameters are named here: ('a'), in definition: ('b')
+// CHECK-FIXES: void inconsistentFunction(int b);
+ void inconsistentFunction(int a);
+};
+
+void Struct::inconsistentFunction(int b) { b = 0; }
+
+//////////////////////////////////////////////////////
+
+struct SpecialFunctions {
+// CHECK-MESSAGES: :[[@LINE+4]]:3: warning: function 'SpecialFunctions::SpecialFunctions' has a definition
+// CHECK-MESSAGES: :[[@LINE+12]]:19: note: the definition seen here
+// CHECK-MESSAGES: :[[@LINE+2]]:3: note: differing parameters are named here: ('a'), in definition: ('b')
+// CHECK-FIXES: SpecialFunctions(int b);
+ SpecialFunctions(int a);
+
+// CHECK-MESSAGES: :[[@LINE+4]]:21: warning: function 'SpecialFunctions::operator=' has a definition
+// CHECK-MESSAGES: :[[@LINE+8]]:37: note: the definition seen here
+// CHECK-MESSAGES: :[[@LINE+2]]:21: note: differing parameters are named here: ('a'), in definition: ('b')
+// CHECK-FIXES: SpecialFunctions& operator=(const SpecialFunctions& b);
+ SpecialFunctions& operator=(const SpecialFunctions& a);
+};
+
+SpecialFunctions::SpecialFunctions(int b) { b; }
+
+SpecialFunctions& SpecialFunctions::operator=(const SpecialFunctions& b) { b; return *this; }
+
+//////////////////////////////////////////////////////
+
+// CHECK-MESSAGES: :[[@LINE+5]]:6: warning: function 'templateFunctionWithSeparateDeclarationAndDefinition' has a definition
+// CHECK-MESSAGES: :[[@LINE+7]]:6: note: the definition seen here
+// CHECK-MESSAGES: :[[@LINE+3]]:6: note: differing parameters are named here: ('a'), in definition: ('b')
+// CHECK-FIXES: void templateFunctionWithSeparateDeclarationAndDefinition(T b);
+template<typename T>
+void templateFunctionWithSeparateDeclarationAndDefinition(T a);
+
+template<typename T>
+void templateFunctionWithSeparateDeclarationAndDefinition(T b) { b; }
+
+//////////////////////////////////////////////////////
+
+template<typename T>
+void templateFunctionWithSpecializations(T a) { a; }
+
+template<>
+// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function template specialization 'templateFunctionWithSpecializations<int>' has a primary template declaration with different parameter names [readability-inconsistent-declaration-parameter-name]
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: the primary template declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('b'), in primary template declaration: ('a')
+void templateFunctionWithSpecializations(int b) { b; }
+
+template<>
+// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function template specialization 'templateFunctionWithSpecializations<float>' has a primary template
+// CHECK-MESSAGES: :[[@LINE-10]]:6: note: the primary template declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('c'), in primary template declaration: ('a')
+void templateFunctionWithSpecializations(float c) { c; }
+
+//////////////////////////////////////////////////////
+
+template<typename T>
+void templateFunctionWithoutDefinitionButWithSpecialization(T a);
+
+template<>
+// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function template specialization 'templateFunctionWithoutDefinitionButWithSpecialization<int>' has a primary template
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: the primary template declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('b'), in primary template declaration: ('a')
+void templateFunctionWithoutDefinitionButWithSpecialization(int b) { b; }
+
+//////////////////////////////////////////////////////
+
+template<typename T>
+void templateFunctionWithSeparateSpecializationDeclarationAndDefinition(T a);
+
+template<>
+// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function template specialization 'templateFunctionWithSeparateSpecializationDeclarationAndDefinition<int>' has a primary template
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: the primary template declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('b'), in primary template declaration: ('a')
+void templateFunctionWithSeparateSpecializationDeclarationAndDefinition(int b);
+
+template<>
+// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function template specialization 'templateFunctionWithSeparateSpecializationDeclarationAndDefinition<int>' has a primary template
+// CHECK-MESSAGES: :[[@LINE-10]]:6: note: the primary template declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('c'), in primary template declaration: ('a')
+void templateFunctionWithSeparateSpecializationDeclarationAndDefinition(int c) { c; }
+
+//////////////////////////////////////////////////////
+
+template<typename T>
+class ClassTemplate
+{
+public:
+// CHECK-MESSAGES: :[[@LINE+4]]:10: warning: function 'ClassTemplate::functionInClassTemplateWithSeparateDeclarationAndDefinition' has a definition
+// CHECK-MESSAGES: :[[@LINE+7]]:24: note: the definition seen here
+// CHECK-MESSAGES: :[[@LINE+2]]:10: note: differing parameters are named here: ('a'), in definition: ('b')
+// CHECK-FIXES: void functionInClassTemplateWithSeparateDeclarationAndDefinition(int b);
+ void functionInClassTemplateWithSeparateDeclarationAndDefinition(int a);
+};
+
+template<typename T>
+void ClassTemplate<T>::functionInClassTemplateWithSeparateDeclarationAndDefinition(int b) { b; }
+
+//////////////////////////////////////////////////////
+
+class Class
+{
+public:
+ template<typename T>
+// CHECK-MESSAGES: :[[@LINE+4]]:8: warning: function 'Class::memberFunctionTemplateWithSeparateDeclarationAndDefinition' has a definition
+// CHECK-MESSAGES: :[[@LINE+12]]:13: note: the definition seen here
+// CHECK-MESSAGES: :[[@LINE+2]]:8: note: differing parameters are named here: ('a'), in definition: ('b')
+// CHECK-FIXES: void memberFunctionTemplateWithSeparateDeclarationAndDefinition(T b);
+ void memberFunctionTemplateWithSeparateDeclarationAndDefinition(T a);
+
+ template<typename T>
+ void memberFunctionTemplateWithSpecializations(T a) { a; }
+};
+
+//////////////////////////////////////////////////////
+
+template<typename T>
+void Class::memberFunctionTemplateWithSeparateDeclarationAndDefinition(T b) { b; }
+
+//////////////////////////////////////////////////////
+
+template<>
+// CHECK-MESSAGES: :[[@LINE+3]]:13: warning: function template specialization 'Class::memberFunctionTemplateWithSpecializations<int>' has a primary template
+// CHECK-MESSAGES: :[[@LINE-12]]:8: note: the primary template declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:13: note: differing parameters are named here: ('b'), in primary template declaration: ('a')
+void Class::memberFunctionTemplateWithSpecializations(int b) { b; }
+
+template<>
+// CHECK-MESSAGES: :[[@LINE+3]]:13: warning: function template specialization 'Class::memberFunctionTemplateWithSpecializations<float>' has a primary template
+// CHECK-MESSAGES: :[[@LINE-18]]:8: note: the primary template declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:13: note: differing parameters are named here: ('c'), in primary template declaration: ('a')
+void Class::memberFunctionTemplateWithSpecializations(float c) { c; }
+
+//////////////////////////////////////////////////////
+
+// This resulted in a warning by default.
+#define MACRO() \
+ void f(int x);
+
+struct S {
+ MACRO();
+};
+
+void S::f(int y)
+{
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-misleading-indentation.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-misleading-indentation.cpp
new file mode 100644
index 0000000..59d5f40
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-misleading-indentation.cpp
@@ -0,0 +1,111 @@
+// RUN: %check_clang_tidy %s readability-misleading-indentation %t
+
+void foo1();
+void foo2();
+
+#define BLOCK \
+ if (cond1) \
+ foo1(); \
+ foo2();
+
+int main()
+{
+ bool cond1 = true;
+ bool cond2 = true;
+
+ if (cond1)
+ if (cond2)
+ foo1();
+ else
+ foo2();
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: different indentation for 'if' and corresponding 'else' [readability-misleading-indentation]
+
+ if (cond1) {
+ if (cond2)
+ foo1();
+ }
+ else
+ foo2();
+
+ if (cond1)
+ if (cond2)
+ foo1();
+ else
+ foo2();
+
+ if (cond2)
+ foo1();
+ foo2();
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: misleading indentation: statement is indented too deeply [readability-misleading-indentation]
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: note: did you mean this line to be inside this 'if'
+ foo2(); // No redundant warning.
+
+ if (cond1)
+ {
+ foo1();
+ }
+ foo2();
+
+ if (cond1)
+ foo1();
+ foo2();
+
+ if (cond2)
+ if (cond1) foo1(); else foo2();
+
+ if (cond1) {
+ } else {
+ }
+
+ if (cond1) {
+ }
+ else {
+ }
+
+ if (cond1)
+ {
+ }
+ else
+ {
+ }
+
+ if (cond1)
+ {
+ }
+ else
+ {
+ }
+
+ if(cond1) {
+ }
+ else if (cond2) {
+ }
+ else {
+ }
+
+ if(cond1) {
+ }
+ else if (cond2) {
+ }
+ else {
+ }
+ // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: different indentation for 'if' and corresponding 'else' [readability-misleading-indentation]
+
+ if (cond1) {
+ if (cond1) {
+ }
+ else if (cond2) {
+ }
+ else {
+ }
+ if (cond1) {
+ } else if (cond2) {
+ } else if (!cond2) {
+ } else {
+ }
+ }
+ else if (cond2) {
+ }
+
+ BLOCK
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-misplaced-array-index.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-misplaced-array-index.cpp
new file mode 100644
index 0000000..43dd458
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-misplaced-array-index.cpp
@@ -0,0 +1,34 @@
+// RUN: %check_clang_tidy %s readability-misplaced-array-index %t
+
+#define ABC "abc"
+
+struct XY { int *X; int *Y; };
+
+void dostuff(int);
+
+void unusualSyntax(int *P1, struct XY *P2) {
+ 10[P1] = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: confusing array subscript expression, usually the index is inside the []
+ // CHECK-FIXES: P1[10] = 0;
+
+ 10[P2->X] = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: confusing array subscript expression
+ // CHECK-FIXES: P2->X[10] = 0;
+
+ dostuff(1["abc"]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: confusing array subscript expression
+ // CHECK-FIXES: dostuff("abc"[1]);
+
+ dostuff(1[ABC]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: confusing array subscript expression
+ // CHECK-FIXES: dostuff(ABC[1]);
+
+ dostuff(0[0 + ABC]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: confusing array subscript expression
+ // CHECK-FIXES: dostuff(0[0 + ABC]);
+ // No fixit. Probably the code should be ABC[0]
+}
+
+void normalSyntax(int *X) {
+ X[10] = 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-named-parameter.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-named-parameter.cpp
new file mode 100644
index 0000000..af2c195
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-named-parameter.cpp
@@ -0,0 +1,133 @@
+// RUN: %check_clang_tidy %s readability-named-parameter %t
+
+void Method(char *) { /* */ }
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: all parameters should be named in a function
+// CHECK-FIXES: void Method(char * /*unused*/) { /* */ }
+void Method2(char *) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: all parameters should be named in a function
+// CHECK-FIXES: void Method2(char * /*unused*/) {}
+void Method3(char *, void *) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: all parameters should be named in a function
+// CHECK-FIXES: void Method3(char * /*unused*/, void * /*unused*/) {}
+void Method4(char *, int /*unused*/) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: all parameters should be named in a function
+// CHECK-FIXES: void Method4(char * /*unused*/, int /*unused*/) {}
+void operator delete[](void *) throw() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: all parameters should be named in a function
+// CHECK-FIXES: void operator delete[](void * /*unused*/) throw() {}
+int Method5(int) { return 0; }
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: all parameters should be named in a function
+// CHECK-FIXES: int Method5(int /*unused*/) { return 0; }
+void Method6(void (*)(void *)) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: all parameters should be named in a function
+// CHECK-FIXES: void Method6(void (* /*unused*/)(void *)) {}
+template <typename T> void Method7(T) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: all parameters should be named in a function
+// CHECK-FIXES: template <typename T> void Method7(T /*unused*/) {}
+
+// Don't warn in macros.
+#define M void MethodM(int) {}
+M
+
+void operator delete(void *x) throw() {}
+void Method7(char * /*x*/) {}
+void Method8(char *x) {}
+typedef void (*TypeM)(int x);
+void operator delete[](void *x) throw();
+void operator delete[](void * /*x*/) throw();
+
+struct X {
+ X operator++(int) {}
+ X operator--(int) {}
+
+ X(X&) = delete;
+ X &operator=(X&) = default;
+
+ const int &i;
+};
+
+void (*Func1)(void *);
+void Func2(void (*func)(void *)) {}
+template <void Func(void *)> void Func3() {}
+
+template <typename T>
+struct Y {
+ void foo(T) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: all parameters should be named in a function
+// CHECK-FIXES: void foo(T /*unused*/) {}
+};
+
+Y<int> y;
+Y<float> z;
+
+struct Base {
+ virtual void foo(bool notThisOne);
+ virtual void foo(int argname);
+};
+
+struct Derived : public Base {
+ void foo(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: all parameters should be named in a function
+// CHECK-FIXES: void foo(int /*argname*/);
+};
+
+void FDef(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: all parameters should be named in a function
+// CHECK-FIXES: void FDef(int /*n*/);
+void FDef(int n) {}
+
+void FDef2(int, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: all parameters should be named in a function
+// CHECK-FIXES: void FDef2(int /*n*/, int /*unused*/);
+void FDef2(int n, int) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: all parameters should be named in a function
+// CHECK-FIXES: void FDef2(int n, int /*unused*/) {}
+
+void FNoDef(int);
+
+class Z {};
+
+Z &operator++(Z&) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: all parameters should be named in a function
+// CHECK-FIXES: Z &operator++(Z& /*unused*/) {}
+
+Z &operator++(Z&, int) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: all parameters should be named in a function
+// CHECK-FIXES: Z &operator++(Z& /*unused*/, int) {}
+
+Z &operator--(Z&) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: all parameters should be named in a function
+// CHECK-FIXES: Z &operator--(Z& /*unused*/) {}
+
+Z &operator--(Z&, int) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: all parameters should be named in a function
+// CHECK-FIXES: Z &operator--(Z& /*unused*/, int) {}
+
+namespace testing {
+namespace internal {
+class IgnoredValue {
+ public:
+ template <typename T>
+ IgnoredValue(const T& /* ignored */) {}
+};
+}
+typedef internal::IgnoredValue Unused;
+}
+
+using ::testing::Unused;
+
+void MockFunction(Unused, int q, Unused) {
+ ++q;
+ ++q;
+ ++q;
+}
+
+namespace std {
+typedef decltype(nullptr) nullptr_t;
+}
+
+void f(std::nullptr_t) {}
+
+typedef void (F)(int);
+F f;
+void f(int x) {}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-non-const-parameter.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-non-const-parameter.cpp
new file mode 100644
index 0000000..6cd1f91
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-non-const-parameter.cpp
@@ -0,0 +1,289 @@
+// RUN: %check_clang_tidy %s readability-non-const-parameter %t
+
+// Currently the checker only warns about pointer arguments.
+//
+// It can be defined both that the data is const and that the pointer is const,
+// the checker only checks if the data can be const-specified.
+//
+// It does not warn about pointers to records or function pointers.
+
+// Some external function where first argument is nonconst and second is const.
+char *strcpy1(char *dest, const char *src);
+unsigned my_strcpy(char *buf, const char *s);
+unsigned my_strlen(const char *buf);
+
+// CHECK-MESSAGES: :[[@LINE+1]]:29: warning: pointer parameter 'last' can be pointer to const [readability-non-const-parameter]
+void warn1(int *first, int *last) {
+ // CHECK-FIXES: {{^}}void warn1(int *first, const int *last) {{{$}}
+ *first = 0;
+ if (first < last) {
+ } // <- last can be const
+}
+
+// TODO: warning should be written here
+void warn2(char *p) {
+ char buf[10];
+ strcpy1(buf, p);
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:19: warning: pointer parameter 'p' can be
+void assign1(int *p) {
+ // CHECK-FIXES: {{^}}void assign1(const int *p) {{{$}}
+ const int *q;
+ q = p;
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:19: warning: pointer parameter 'p' can be
+void assign2(int *p) {
+ // CHECK-FIXES: {{^}}void assign2(const int *p) {{{$}}
+ const int *q;
+ q = p + 1;
+}
+
+void assign3(int *p) {
+ *p = 0;
+}
+
+void assign4(int *p) {
+ *p += 2;
+}
+
+void assign5(char *p) {
+ p[0] = 0;
+}
+
+void assign6(int *p) {
+ int *q;
+ q = p++;
+}
+
+void assign7(char *p) {
+ char *a, *b;
+ a = b = p;
+}
+
+void assign8(char *a, char *b) {
+ char *x;
+ x = (a ? a : b);
+}
+
+void assign9(unsigned char *str, const unsigned int i) {
+ unsigned char *p;
+ for (p = str + i; *p;) {
+ }
+}
+
+void assign10(int *buf) {
+ int i, *p;
+ for (i = 0, p = buf; i < 10; i++, p++) {
+ *p = 1;
+ }
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:17: warning: pointer parameter 'p' can be
+void init1(int *p) {
+ // CHECK-FIXES: {{^}}void init1(const int *p) {{{$}}
+ const int *q = p;
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:17: warning: pointer parameter 'p' can be
+void init2(int *p) {
+ // CHECK-FIXES: {{^}}void init2(const int *p) {{{$}}
+ const int *q = p + 1;
+}
+
+void init3(int *p) {
+ int *q = p;
+}
+
+void init4(float *p) {
+ int *q = (int *)p;
+}
+
+void init5(int *p) {
+ int *i = p ? p : 0;
+}
+
+void init6(int *p) {
+ int *a[] = {p, p, 0};
+}
+
+void init7(int *p, int x) {
+ for (int *q = p + x - 1; 0; q++)
+ ;
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:18: warning: pointer parameter 'p' can be
+int return1(int *p) {
+ // CHECK-FIXES: {{^}}int return1(const int *p) {{{$}}
+ return *p;
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:25: warning: pointer parameter 'p' can be
+const int *return2(int *p) {
+ // CHECK-FIXES: {{^}}const int *return2(const int *p) {{{$}}
+ return p;
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:25: warning: pointer parameter 'p' can be
+const int *return3(int *p) {
+ // CHECK-FIXES: {{^}}const int *return3(const int *p) {{{$}}
+ return p + 1;
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:27: warning: pointer parameter 'p' can be
+const char *return4(char *p) {
+ // CHECK-FIXES: {{^}}const char *return4(const char *p) {{{$}}
+ return p ? p : "";
+}
+
+char *return5(char *s) {
+ return s;
+}
+
+char *return6(char *s) {
+ return s + 1;
+}
+
+char *return7(char *a, char *b) {
+ return a ? a : b;
+}
+
+char return8(int *p) {
+ return ++(*p);
+}
+
+void dontwarn1(int *p) {
+ ++(*p);
+}
+
+void dontwarn2(int *p) {
+ (*p)++;
+}
+
+int dontwarn3(_Atomic(int) * p) {
+ return *p;
+}
+
+void callFunction1(char *p) {
+ strcpy1(p, "abc");
+}
+
+void callFunction2(char *p) {
+ strcpy1(&p[0], "abc");
+}
+
+void callFunction3(char *p) {
+ strcpy1(p + 2, "abc");
+}
+
+char *callFunction4(char *p) {
+ return strcpy1(p, "abc");
+}
+
+unsigned callFunction5(char *buf) {
+ unsigned len = my_strlen(buf);
+ return len + my_strcpy(buf, "abc");
+}
+
+void f6(int **p);
+void callFunction6(int *p) { f6(&p); }
+
+typedef union { void *v; } t;
+void f7(t obj);
+void callFunction7(int *p) {
+ f7((t){p});
+}
+
+void f8(int &x);
+void callFunction8(int *p) {
+ f8(*p);
+}
+
+// Don't warn about nonconst function pointers that can be const.
+void functionpointer(double f(double), int x) {
+ f(x);
+}
+
+// TODO: This is a false positive.
+// CHECK-MESSAGES: :[[@LINE+1]]:27: warning: pointer parameter 'p' can be
+int functionpointer2(int *p) {
+ return *p;
+}
+void use_functionpointer2() {
+ int (*fp)(int *) = functionpointer2; // <- the parameter 'p' can't be const
+}
+
+// Don't warn about nonconst record pointers that can be const.
+struct XY {
+ int *x;
+ int *y;
+};
+void recordpointer(struct XY *xy) {
+ *(xy->x) = 0;
+}
+
+class C {
+public:
+ C(int *p) : p(p) {}
+
+private:
+ int *p;
+};
+
+class C2 {
+public:
+ // CHECK-MESSAGES: :[[@LINE+1]]:11: warning: pointer parameter 'p' can be
+ C2(int *p) : p(p) {}
+ // CHECK-FIXES: {{^}} C2(const int *p) : p(p) {}{{$}}
+
+private:
+ const int *p;
+};
+
+void tempObject(int *p) {
+ C c(p);
+}
+
+// avoid fp for const pointer array
+void constPointerArray(const char *remapped[][2]) {
+ const char *name = remapped[0][0];
+}
+
+class Warn {
+public:
+ // CHECK-MESSAGES: :[[@LINE+1]]:21: warning: pointer parameter 'p' can be
+ void doStuff(int *p) {
+ // CHECK-FIXES: {{^}} void doStuff(const int *p) {{{$}}
+ x = *p;
+ }
+
+private:
+ int x;
+};
+
+class Base {
+public:
+ // Ensure there is no false positive for this method. It is virtual.
+ virtual void doStuff(int *p) {
+ int x = *p;
+ }
+};
+
+class Derived : public Base {
+public:
+ // Ensure there is no false positive for this method. It overrides a method.
+ void doStuff(int *p) override {
+ int x = *p;
+ }
+};
+
+extern char foo(char *s); // 1
+// CHECK-FIXES: {{^}}extern char foo(const char *s); // 1{{$}}
+// CHECK-MESSAGES: :[[@LINE+1]]:16: warning: pointer parameter 's' can be
+char foo(char *s) {
+ // CHECK-FIXES: {{^}}char foo(const char *s) {{{$}}
+ return *s;
+}
+char foo(char *s); // 2
+// CHECK-FIXES: {{^}}char foo(const char *s); // 2{{$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-control-flow.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-control-flow.cpp
new file mode 100644
index 0000000..0352e3a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-control-flow.cpp
@@ -0,0 +1,224 @@
+// RUN: %check_clang_tidy %s readability-redundant-control-flow %t
+
+void g(int i);
+void j();
+
+void f() {
+ return;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement at the end of a function with a void return type [readability-redundant-control-flow]
+// CHECK-FIXES: {{^}}void f() {{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+void g() {
+ f();
+ return;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement
+// CHECK-FIXES: {{^ }}f();{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+void g(int i) {
+ if (i < 0) {
+ return;
+ }
+ if (i < 10) {
+ f();
+ }
+}
+
+int h() {
+ return 1;
+}
+
+void j() {
+}
+
+void k() {
+ for (int i = 0; i < 10; ++i) {
+ continue;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement at the end of loop statement
+// CHECK-FIXES: {{^}} for (int i = 0; i < 10; ++i) {{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+void k2() {
+ int v[10] = { 0 };
+ for (auto i : v) {
+ continue;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
+// CHECK-FIXES: {{^}} for (auto i : v) {{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+void m() {
+ int i = 0;
+ do {
+ ++i;
+ continue;
+ } while (i < 10);
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
+// CHECK-FIXES: {{^ do {$}}
+// CHECK-FIXES-NEXT: {{^}} ++i;{{$}}
+// CHECK-FIXES-NEXT: {{^ *}}} while (i < 10);{{$}}
+
+void p() {
+ int i = 0;
+ while (i < 10) {
+ ++i;
+ continue;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
+// CHECK-FIXES: {{^}} while (i < 10) {{{$}}
+// CHECK-FIXES-NEXT: {{^}} ++i;{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+void im_not_dead(int i) {
+ if (i > 0) {
+ return;
+ }
+ g();
+}
+
+void im_still_not_dead(int i) {
+ for (int j = 0; j < 10; ++j) {
+ if (i < 10) {
+ continue;
+ }
+ g();
+ }
+}
+
+void im_dead(int i) {
+ if (i > 0) {
+ return;
+ g();
+ }
+ g();
+}
+
+void im_still_dead(int i) {
+ for (int j = 0; j < 10; ++j) {
+ if (i < 10) {
+ continue;
+ g();
+ }
+ g();
+ }
+}
+
+void void_return() {
+ return g();
+}
+
+void nested_return_unmolested() {
+ g();
+ {
+ g();
+ return;
+ }
+}
+
+void nested_continue_unmolested() {
+ for (int i = 0; i < 10; ++i) {
+ if (i < 5) {
+ continue;
+ }
+ }
+}
+
+#define MACRO_RETURN_UNMOLESTED(fn_) \
+ (fn_)(); \
+ return
+
+#define MACRO_CONTINUE_UNMOLESTED(x_) \
+ do { \
+ for (int i = 0; i < (x_); ++i) { \
+ continue; \
+ } \
+ } while (false)
+
+void macro_return() {
+ MACRO_RETURN_UNMOLESTED(g);
+}
+
+void macro_continue() {
+ MACRO_CONTINUE_UNMOLESTED(10);
+}
+
+#define MACRO_RETURN_ARG(stmt_) \
+ stmt_
+
+#define MACRO_CONTINUE_ARG(stmt_) \
+ do { \
+ for (int i = 0; i < 10; ++i) { \
+ stmt_; \
+ } \
+ } while (false)
+
+void macro_arg_return() {
+ MACRO_RETURN_ARG(return);
+}
+
+void macro_arg_continue() {
+ MACRO_CONTINUE_ARG(continue);
+}
+
+template <typename T>
+void template_return(T check) {
+ if (check < T(0)) {
+ return;
+ }
+ return;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement
+// CHECK-FIXES: {{^}} if (check < T(0)) {{{$}}
+// CHECK-FIXES-NEXT: {{^ return;$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+template <>
+void template_return(int check) {
+ if (check < 0) {
+ return;
+ }
+ return;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement
+// CHECK-FIXES: {{^}} if (check < 0) {{{$}}
+// CHECK-FIXES-NEXT: {{^ return;$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+template <typename T>
+void template_loop(T end) {
+ for (T i = 0; i < end; ++i) {
+ continue;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
+// CHECK-FIXES: {{^}} for (T i = 0; i < end; ++i) {{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+template <>
+void template_loop(int end) {
+ for (int i = 0; i < end; ++i) {
+ continue;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
+// CHECK-FIXES: {{^}} for (int i = 0; i < end; ++i) {{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+void call_templates() {
+ template_return(10);
+ template_return(10.0f);
+ template_return(10.0);
+ template_loop(10);
+ template_loop(10L);
+ template_loop(10U);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-declaration-ignore-macros.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-declaration-ignore-macros.cpp
new file mode 100644
index 0000000..2dc8618
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-declaration-ignore-macros.cpp
@@ -0,0 +1,22 @@
+// RUN: %check_clang_tidy %s readability-redundant-declaration %t -- \
+// RUN: -config="{CheckOptions: \
+// RUN: [{key: readability-redundant-declaration.IgnoreMacros, \
+// RUN: value: 1}]}" \
+// RUN: -- -std=c++11
+
+extern int Xyz;
+extern int Xyz; // Xyz
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'Xyz' declaration [readability-redundant-declaration]
+// CHECK-FIXES: {{^}}// Xyz{{$}}
+
+namespace macros {
+#define DECLARE(x) extern int x
+#define DEFINE(x) extern int x; int x = 42
+DECLARE(test);
+DEFINE(test);
+// CHECK-FIXES: {{^}}#define DECLARE(x) extern int x{{$}}
+// CHECK-FIXES: {{^}}#define DEFINE(x) extern int x; int x = 42{{$}}
+// CHECK-FIXES: {{^}}DECLARE(test);{{$}}
+// CHECK-FIXES: {{^}}DEFINE(test);{{$}}
+
+} // namespace macros
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-declaration.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-declaration.cpp
new file mode 100644
index 0000000..83d1b5b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-declaration.cpp
@@ -0,0 +1,70 @@
+// RUN: %check_clang_tidy %s readability-redundant-declaration %t -- \
+// RUN: -config="{CheckOptions: \
+// RUN: [{key: readability-redundant-declaration.IgnoreMacros, \
+// RUN: value: 0}]}" \
+// RUN: -- -std=c++11
+
+extern int Xyz;
+extern int Xyz; // Xyz
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'Xyz' declaration [readability-redundant-declaration]
+// CHECK-FIXES: {{^}}// Xyz{{$}}
+int Xyz = 123;
+
+extern int A;
+extern int A, B;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'A' declaration
+// CHECK-FIXES: {{^}}extern int A, B;{{$}}
+
+extern int Buf[10];
+extern int Buf[10]; // Buf[10]
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'Buf' declaration
+// CHECK-FIXES: {{^}}// Buf[10]{{$}}
+
+static int f();
+static int f(); // f
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'f' declaration
+// CHECK-FIXES: {{^}}// f{{$}}
+static int f() {}
+
+// Original check crashed for the code below.
+namespace std {
+typedef decltype(sizeof(0)) size_t;
+}
+void *operator new(std::size_t) __attribute__((__externally_visible__));
+void *operator new[](std::size_t) __attribute__((__externally_visible__));
+
+// Don't warn about static member definition.
+struct C {
+ static int I;
+};
+int C::I;
+
+template <class T>
+struct C2 {
+ C2();
+};
+
+template <class T>
+C2<T>::C2() = default;
+
+void best_friend();
+
+struct Friendly {
+ friend void best_friend();
+ friend void enemy();
+};
+
+void enemy();
+
+namespace macros {
+#define DECLARE(x) extern int x
+#define DEFINE(x) extern int x; int x = 42
+DECLARE(test);
+DEFINE(test);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant 'test' declaration
+// CHECK-FIXES: {{^}}#define DECLARE(x) extern int x{{$}}
+// CHECK-FIXES: {{^}}#define DEFINE(x) extern int x; int x = 42{{$}}
+// CHECK-FIXES: {{^}}DECLARE(test);{{$}}
+// CHECK-FIXES: {{^}}DEFINE(test);{{$}}
+
+} // namespace macros
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-function-ptr-dereference.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-function-ptr-dereference.cpp
new file mode 100644
index 0000000..2b34ce1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-function-ptr-dereference.cpp
@@ -0,0 +1,45 @@
+// RUN: %check_clang_tidy %s readability-redundant-function-ptr-dereference %t
+
+void f(int i);
+
+void positive() {
+ void (*p)(int) = f;
+
+ (**p)(1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: redundant repeated dereference of function pointer [readability-redundant-function-ptr-dereference]
+ // CHECK-FIXES: (*p)(1);
+ (*****p)(2);
+ // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: redundant repeated
+ // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: redundant repeated
+ // CHECK-MESSAGES: :[[@LINE-3]]:6: warning: redundant repeated
+ // CHECK-MESSAGES: :[[@LINE-4]]:7: warning: redundant repeated
+ // CHECK-FIXES: (*p)(2);
+}
+
+template<typename T>
+void invoke(const T& fn) {
+ fn(0); // 1
+ (*fn)(0); // 2
+ // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: redundant repeated
+ // CHECK-FIXES: fn(0); // 1
+ // CHECK-FIXES: (fn)(0); // 2
+ // FIXME: Remove unnecessary parentheses.
+}
+
+void f1(int);
+void f2(double);
+void f3(char);
+
+void instantiate() {
+ invoke(f1);
+ invoke(f2);
+ invoke(f3);
+ invoke([](unsigned) {});
+}
+
+void negative() {
+ void (*q)(int) = &f;
+
+ q(1);
+ (*q)(2);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-member-init.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-member-init.cpp
new file mode 100644
index 0000000..90b52fd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-member-init.cpp
@@ -0,0 +1,219 @@
+// RUN: %check_clang_tidy %s readability-redundant-member-init %t
+
+struct S {
+ S() = default;
+ S(int i) : i(i) {}
+ int i = 1;
+};
+
+struct T {
+ T(int i = 1) : i(i) {}
+ int i;
+};
+
+struct U {
+ int i;
+};
+
+union V {
+ int i;
+ double f;
+};
+
+// Initializer calls default constructor
+struct F1 {
+ F1() : f() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 'f' is redundant
+ // CHECK-FIXES: F1() {}
+ S f;
+};
+
+// Initializer calls default constructor with default argument
+struct F2 {
+ F2() : f() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 'f' is redundant
+ // CHECK-FIXES: F2() {}
+ T f;
+};
+
+// Multiple redundant initializers for same constructor
+struct F3 {
+ F3() : f(), g(1), h() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 'f' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: initializer for member 'h' is redundant
+ // CHECK-FIXES: F3() : g(1) {}
+ S f, g, h;
+};
+
+// Templated class independent type
+template <class V>
+struct F4 {
+ F4() : f() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 'f' is redundant
+ // CHECK-FIXES: F4() {}
+ S f;
+};
+F4<int> f4i;
+F4<S> f4s;
+
+// Base class
+struct F5 : S {
+ F5() : S() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for base class 'S' is redundant
+ // CHECK-FIXES: F5() {}
+};
+
+// Constructor call requires cleanup
+struct Cleanup {
+ ~Cleanup() {}
+};
+
+struct UsesCleanup {
+ UsesCleanup(const Cleanup &c = Cleanup()) {}
+};
+
+struct F6 {
+ F6() : uc() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 'uc' is redundant
+ // CHECK-FIXES: F6() {}
+ UsesCleanup uc;
+};
+
+// Multiple inheritance
+struct F7 : S, T {
+ F7() : S(), T() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for base class 'S' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: initializer for base class 'T' is redundant
+ // CHECK-FIXES: F7() {}
+};
+
+namespace Foo {
+inline namespace Bar {
+template <int N>
+struct Template {
+ Template() = default;
+ int i = N;
+};
+}
+}
+
+enum { N_THINGS = 5 };
+
+struct F8 : Foo::Template<N_THINGS> {
+ F8() : Template() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for base class 'Foo::Template<N_THINGS>' is redundant
+ // CHECK-FIXES: F8() {}
+};
+
+// Anonymous struct
+struct F9 {
+ F9() : s1() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 's1' is redundant
+ // CHECK-FIXES: F9() {}
+ struct {
+ S s1;
+ S s2;
+ };
+};
+
+// Initializer not written
+struct NF1 {
+ NF1() {}
+ S f;
+};
+
+// Initializer doesn't call default constructor
+struct NF2 {
+ NF2() : f(1) {}
+ S f;
+};
+
+// Initializer calls default constructor without using default argument
+struct NF3 {
+ NF3() : f(1) {}
+ T f;
+};
+
+// Initializer calls default constructor without using default argument
+struct NF4 {
+ NF4() : f(2) {}
+ T f;
+};
+
+// Initializer is zero-initialization
+struct NF5 {
+ NF5() : i() {}
+ int i;
+};
+
+// Initializer is direct-initialization
+struct NF6 {
+ NF6() : i(1) {}
+ int i;
+};
+
+// Initializer is aggregate initialization of struct
+struct NF7 {
+ NF7() : f{} {}
+ U f;
+};
+
+// Initializer is zero-initialization of struct
+struct NF7b {
+ NF7b() : f() {}
+ U f;
+};
+
+// Initializer is aggregate initialization of array
+struct NF8 {
+ NF8() : f{} {}
+ int f[2];
+};
+
+struct NF9 {
+ NF9() : f{} {}
+ S f[2];
+};
+
+// Initializing member of union
+union NF10 {
+ NF10() : s() {}
+ int i;
+ S s;
+};
+
+// Templated class dependent type
+template <class V>
+struct NF11 {
+ NF11() : f() {}
+ V f;
+};
+NF11<int> nf11i;
+NF11<S> nf11s;
+
+// Delegating constructor
+class NF12 {
+ NF12() = default;
+ NF12(int) : NF12() {}
+};
+
+// Const member
+struct NF13 {
+ NF13() : f() {}
+ const S f;
+};
+
+// Union member
+struct NF14 {
+ NF14() : f() {}
+ V f;
+};
+
+// Anonymous union member
+struct NF15 {
+ NF15() : s1() {}
+ union {
+ S s1;
+ S s2;
+ };
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-smartptr-get.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-smartptr-get.cpp
new file mode 100644
index 0000000..685a57c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-smartptr-get.cpp
@@ -0,0 +1,196 @@
+// RUN: %check_clang_tidy %s readability-redundant-smartptr-get %t
+
+#define NULL __null
+
+namespace std {
+
+template <typename T>
+struct unique_ptr {
+ T& operator*() const;
+ T* operator->() const;
+ T* get() const;
+ explicit operator bool() const noexcept;
+};
+
+template <typename T>
+struct shared_ptr {
+ T& operator*() const;
+ T* operator->() const;
+ T* get() const;
+ explicit operator bool() const noexcept;
+};
+
+} // namespace std
+
+struct Bar {
+ void Do();
+ void ConstDo() const;
+};
+struct BarPtr {
+ Bar* operator->();
+ Bar& operator*();
+ Bar* get();
+ explicit operator bool() const;
+};
+struct int_ptr {
+ int* get();
+ int* operator->();
+ int& operator*();
+};
+
+struct Fail1 {
+ Bar* get();
+};
+struct Fail2 {
+ Bar* get();
+ int* operator->();
+ int& operator*();
+};
+
+struct PointerWithOverloadedGet {
+ int* get();
+ template <typename T>
+ T* get();
+ int* operator->();
+ int& operator*();
+};
+
+void Positive() {
+ BarPtr u;
+ // CHECK-FIXES: BarPtr u;
+ BarPtr().get()->Do();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant get() call on smart pointer [readability-redundant-smartptr-get]
+ // CHECK-MESSAGES: BarPtr().get()->Do();
+ // CHECK-FIXES: BarPtr()->Do();
+
+ u.get()->ConstDo();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant get() call
+ // CHECK-MESSAGES: u.get()->ConstDo();
+ // CHECK-FIXES: u->ConstDo();
+
+ Bar& b = *BarPtr().get();
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant get() call
+ // CHECK-MESSAGES: Bar& b = *BarPtr().get();
+ // CHECK-FIXES: Bar& b = *BarPtr();
+
+ Bar& b2 = *std::unique_ptr<Bar>().get();
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant get() call
+ // CHECK-MESSAGES: Bar& b2 = *std::unique_ptr<Bar>().get();
+ // CHECK-FIXES: Bar& b2 = *std::unique_ptr<Bar>();
+
+ (*BarPtr().get()).ConstDo();
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant get() call
+ // CHECK-MESSAGES: (*BarPtr().get()).ConstDo();
+ // CHECK-FIXES: (*BarPtr()).ConstDo();
+
+ (*std::unique_ptr<Bar>().get()).ConstDo();
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant get() call
+ // CHECK-MESSAGES: (*std::unique_ptr<Bar>().get()).ConstDo();
+ // CHECK-FIXES: (*std::unique_ptr<Bar>()).ConstDo();
+
+ std::unique_ptr<Bar>* up;
+ (*up->get()).Do();
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant get() call
+ // CHECK-MESSAGES: (*up->get()).Do();
+ // CHECK-FIXES: (**up).Do();
+
+ int_ptr ip;
+ int i = *ip.get();
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant get() call
+ // CHECK-MESSAGES: int i = *ip.get();
+ // CHECK-FIXES: int i = *ip;
+
+ auto ip2 = ip;
+ i = *ip2.get();
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call
+ // CHECK-MESSAGES: i = *ip2.get();
+ // CHECK-FIXES: i = *ip2;
+
+ std::unique_ptr<int> uu;
+ std::shared_ptr<double> *ss;
+ bool bb = uu.get() == nullptr;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant get() call
+ // CHECK-MESSAGES: uu.get() == nullptr;
+ // CHECK-FIXES: bool bb = uu == nullptr;
+
+ if (up->get());
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call
+ // CHECK-MESSAGES: if (up->get());
+ // CHECK-FIXES: if (*up);
+ if ((uu.get()));
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call
+ // CHECK-MESSAGES: if ((uu.get()));
+ // CHECK-FIXES: if ((uu));
+ bb = !ss->get();
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant get() call
+ // CHECK-MESSAGES: bb = !ss->get();
+ // CHECK-FIXES: bb = !*ss;
+ bb = u.get() ? true : false;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call
+ // CHECK-MESSAGES: bb = u.get() ? true : false;
+ // CHECK-FIXES: bb = u ? true : false;
+
+ bb = nullptr != ss->get();
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: redundant get() call
+ // CHECK-MESSAGES: nullptr != ss->get();
+ // CHECK-FIXES: bb = nullptr != *ss;
+
+ i = *PointerWithOverloadedGet().get();
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call
+ // CHECK-MESSAGES: i = *PointerWithOverloadedGet().get();
+ // CHECK-FIXES: i = *PointerWithOverloadedGet();
+
+ bb = std::unique_ptr<int>().get() == NULL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call
+ // CHECK-MESSAGES: bb = std::unique_ptr<int>().get() == NULL;
+ // CHECK-FIXES: bb = std::unique_ptr<int>() == NULL;
+ bb = ss->get() == NULL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call
+ // CHECK-MESSAGES: bb = ss->get() == NULL;
+ // CHECK-FIXES: bb = *ss == NULL;
+
+ std::unique_ptr<int> x, y;
+ if (x.get() == nullptr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call
+ // CHECK-MESSAGES: if (x.get() == nullptr);
+ // CHECK-FIXES: if (x == nullptr);
+ if (nullptr == y.get());
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: redundant get() call
+ // CHECK-MESSAGES: if (nullptr == y.get());
+ // CHECK-FIXES: if (nullptr == y);
+ if (x.get() == NULL);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call
+ // CHECK-MESSAGES: if (x.get() == NULL);
+ // CHECK-FIXES: if (x == NULL);
+ if (NULL == x.get());
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: redundant get() call
+ // CHECK-MESSAGES: if (NULL == x.get());
+ // CHECK-FIXES: if (NULL == x);
+}
+
+void Negative() {
+ struct NegPtr {
+ int* get();
+ int* operator->() {
+ return &*this->get();
+ }
+ int& operator*() {
+ return *get();
+ }
+ };
+
+ long l = *PointerWithOverloadedGet().get<long>();
+
+ std::unique_ptr<Bar>* u;
+ u->get()->Do();
+
+ Fail1().get()->Do();
+ Fail2().get()->Do();
+ const Bar& b = *Fail1().get();
+ (*Fail2().get()).Do();
+
+ int_ptr ip;
+ bool bb = ip.get() == nullptr;
+ bb = !ip.get();
+ bb = ip.get() ? true : false;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-cstr-msvc.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-cstr-msvc.cpp
new file mode 100644
index 0000000..a6b6b20
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-cstr-msvc.cpp
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s readability-redundant-string-cstr %t
+
+namespace std {
+template <typename T>
+class allocator {};
+template <typename T>
+class char_traits {};
+template <typename C, typename T, typename A>
+struct basic_string {
+ basic_string();
+ // MSVC headers define two constructors instead of using optional arguments.
+ basic_string(const C *p);
+ basic_string(const C *p, const A &a);
+ const C *c_str() const;
+ const C *data() const;
+};
+typedef basic_string<char, std::char_traits<char>, std::allocator<char>> string;
+}
+namespace llvm {
+struct StringRef {
+ StringRef(const char *p);
+ StringRef(const std::string &);
+};
+}
+
+void f1(const std::string &s) {
+ f1(s.c_str());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+ // CHECK-FIXES: {{^ }}f1(s);{{$}}
+ f1(s.data());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'data' [readability-redundant-string-cstr]
+ // CHECK-FIXES: {{^ }}f1(s);{{$}}
+}
+void f2(const llvm::StringRef r) {
+ std::string s;
+ f2(s.c_str());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call {{.*}}
+ // CHECK-FIXES: {{^ }}std::string s;{{$}}
+ // CHECK-FIXES-NEXT: {{^ }}f2(s);{{$}}
+}
+void f3(const llvm::StringRef &r) {
+ std::string s;
+ f3(s.c_str());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call {{.*}}
+ // CHECK-FIXES: {{^ }}std::string s;{{$}}
+ // CHECK-FIXES-NEXT: {{^ }}f3(s);{{$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-cstr.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-cstr.cpp
new file mode 100644
index 0000000..976a54f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-cstr.cpp
@@ -0,0 +1,207 @@
+// RUN: %check_clang_tidy %s readability-redundant-string-cstr %t -- -- -std=c++11
+
+typedef unsigned __INT16_TYPE__ char16;
+typedef unsigned __INT32_TYPE__ char32;
+typedef __SIZE_TYPE__ size;
+
+namespace std {
+template <typename T>
+class allocator {};
+template <typename T>
+class char_traits {};
+template <typename C, typename T, typename A>
+struct basic_string {
+ typedef basic_string<C, T, A> _Type;
+ basic_string();
+ basic_string(const C *p, const A &a = A());
+
+ const C *c_str() const;
+ const C *data() const;
+
+ _Type& append(const C *s);
+ _Type& append(const C *s, size n);
+ _Type& assign(const C *s);
+ _Type& assign(const C *s, size n);
+
+ int compare(const _Type&) const;
+ int compare(const C* s) const;
+ int compare(size pos, size len, const _Type&) const;
+ int compare(size pos, size len, const C* s) const;
+
+ size find(const _Type& str, size pos = 0) const;
+ size find(const C* s, size pos = 0) const;
+ size find(const C* s, size pos, size n) const;
+
+ _Type& insert(size pos, const _Type& str);
+ _Type& insert(size pos, const C* s);
+ _Type& insert(size pos, const C* s, size n);
+
+ _Type& operator+=(const _Type& str);
+ _Type& operator+=(const C* s);
+ _Type& operator=(const _Type& str);
+ _Type& operator=(const C* s);
+};
+
+typedef basic_string<char, std::char_traits<char>, std::allocator<char>> string;
+typedef basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>> wstring;
+typedef basic_string<char16, std::char_traits<char16>, std::allocator<char16>> u16string;
+typedef basic_string<char32, std::char_traits<char32>, std::allocator<char32>> u32string;
+}
+
+std::string operator+(const std::string&, const std::string&);
+std::string operator+(const std::string&, const char*);
+std::string operator+(const char*, const std::string&);
+
+bool operator==(const std::string&, const std::string&);
+bool operator==(const std::string&, const char*);
+bool operator==(const char*, const std::string&);
+
+namespace llvm {
+struct StringRef {
+ StringRef(const char *p);
+ StringRef(const std::string &);
+};
+}
+
+// Tests for std::string.
+
+void f1(const std::string &s) {
+ f1(s.c_str());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+ // CHECK-FIXES: {{^ }}f1(s);{{$}}
+ f1(s.data());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'data' [readability-redundant-string-cstr]
+ // CHECK-FIXES: {{^ }}f1(s);{{$}}
+}
+void f2(const llvm::StringRef r) {
+ std::string s;
+ f2(s.c_str());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call {{.*}}
+ // CHECK-FIXES: {{^ }}std::string s;{{$}}
+ // CHECK-FIXES-NEXT: {{^ }}f2(s);{{$}}
+}
+void f3(const llvm::StringRef &r) {
+ std::string s;
+ f3(s.c_str());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call {{.*}}
+ // CHECK-FIXES: {{^ }}std::string s;{{$}}
+ // CHECK-FIXES-NEXT: {{^ }}f3(s);{{$}}
+}
+void f4(const std::string &s) {
+ const std::string* ptr = &s;
+ f1(ptr->c_str());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+ // CHECK-FIXES: {{^ }}f1(*ptr);{{$}}
+}
+void f5(const std::string &s) {
+ std::string tmp;
+ tmp.append(s.c_str());
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant call {{.*}}
+ // CHECK-FIXES: {{^ }}tmp.append(s);{{$}}
+ tmp.assign(s.c_str());
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant call {{.*}}
+ // CHECK-FIXES: {{^ }}tmp.assign(s);{{$}}
+
+ if (tmp.compare(s.c_str()) == 0) return;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: redundant call {{.*}}
+ // CHECK-FIXES: {{^ }}if (tmp.compare(s) == 0) return;{{$}}
+
+ if (tmp.compare(1, 2, s.c_str()) == 0) return;
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: redundant call {{.*}}
+ // CHECK-FIXES: {{^ }}if (tmp.compare(1, 2, s) == 0) return;{{$}}
+
+ if (tmp.find(s.c_str()) == 0) return;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: redundant call {{.*}}
+ // CHECK-FIXES: {{^ }}if (tmp.find(s) == 0) return;{{$}}
+
+ if (tmp.find(s.c_str(), 2) == 0) return;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: redundant call {{.*}}
+ // CHECK-FIXES: {{^ }}if (tmp.find(s, 2) == 0) return;{{$}}
+
+ if (tmp.find(s.c_str(), 2) == 0) return;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: redundant call {{.*}}
+ // CHECK-FIXES: {{^ }}if (tmp.find(s, 2) == 0) return;{{$}}
+
+ tmp.insert(1, s.c_str());
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: redundant call {{.*}}
+ // CHECK-FIXES: {{^ }}tmp.insert(1, s);{{$}}
+
+ tmp = s.c_str();
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant call {{.*}}
+ // CHECK-FIXES: {{^ }}tmp = s;{{$}}
+
+ tmp += s.c_str();
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: redundant call {{.*}}
+ // CHECK-FIXES: {{^ }}tmp += s;{{$}}
+
+ if (tmp == s.c_str()) return;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant call {{.*}}
+ // CHECK-FIXES: {{^ }}if (tmp == s) return;{{$}}
+
+ tmp = s + s.c_str();
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant call {{.*}}
+ // CHECK-FIXES: {{^ }}tmp = s + s;{{$}}
+
+ tmp = s.c_str() + s;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant call {{.*}}
+ // CHECK-FIXES: {{^ }}tmp = s + s;{{$}}
+}
+void f6(const std::string &s) {
+ std::string tmp;
+ tmp.append(s.c_str(), 2);
+ tmp.assign(s.c_str(), 2);
+
+ if (tmp.compare(s) == 0) return;
+ if (tmp.compare(1, 2, s) == 0) return;
+
+ tmp = s;
+ tmp += s;
+
+ if (tmp == s)
+ return;
+
+ tmp = s + s;
+
+ if (tmp.find(s.c_str(), 2, 4) == 0) return;
+
+ tmp.insert(1, s);
+ tmp.insert(1, s.c_str(), 2);
+}
+
+// Tests for std::wstring.
+
+void g1(const std::wstring &s) {
+ g1(s.c_str());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+ // CHECK-FIXES: {{^ }}g1(s);{{$}}
+}
+
+// Tests for std::u16string.
+
+void h1(const std::u16string &s) {
+ h1(s.c_str());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+ // CHECK-FIXES: {{^ }}h1(s);{{$}}
+}
+
+// Tests for std::u32string.
+
+void k1(const std::u32string &s) {
+ k1(s.c_str());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+ // CHECK-FIXES: {{^ }}k1(s);{{$}}
+}
+
+// Tests on similar classes that aren't good candidates for this checker.
+
+struct NotAString {
+ NotAString();
+ NotAString(const NotAString&);
+ const char *c_str() const;
+};
+
+void dummy(const char*) {}
+
+void invalid(const NotAString &s) {
+ dummy(s.c_str());
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-init-msvc.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-init-msvc.cpp
new file mode 100644
index 0000000..0299519
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-init-msvc.cpp
@@ -0,0 +1,61 @@
+// RUN: %check_clang_tidy %s readability-redundant-string-init %t
+
+namespace std {
+template <typename T>
+class allocator {};
+template <typename T>
+class char_traits {};
+template <typename C, typename T = std::char_traits<C>, typename A = std::allocator<C>>
+struct basic_string {
+ basic_string();
+ basic_string(const basic_string&);
+ // MSVC headers define two constructors instead of using optional arguments.
+ basic_string(const C *);
+ basic_string(const C *, const A &);
+ ~basic_string();
+};
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+}
+
+void f() {
+ std::string a = "";
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization [readability-redundant-string-init]
+ // CHECK-FIXES: std::string a;
+ std::string b("");
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+ // CHECK-FIXES: std::string b;
+ std::string c = R"()";
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+ // CHECK-FIXES: std::string c;
+ std::string d(R"()");
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+ // CHECK-FIXES: std::string d;
+
+ std::string u = "u";
+ std::string w("w");
+ std::string x = R"(x)";
+ std::string y(R"(y)");
+ std::string z;
+}
+
+void g() {
+ std::wstring a = L"";
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization
+ // CHECK-FIXES: std::wstring a;
+ std::wstring b(L"");
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization
+ // CHECK-FIXES: std::wstring b;
+ std::wstring c = LR"()";
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization
+ // CHECK-FIXES: std::wstring c;
+ std::wstring d(LR"()");
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization
+ // CHECK-FIXES: std::wstring d;
+
+ std::wstring u = L"u";
+ std::wstring w(L"w");
+ std::wstring x = LR"(x)";
+ std::wstring y(LR"(y)");
+ std::wstring z;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-init.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-init.cpp
new file mode 100644
index 0000000..4455ad4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-init.cpp
@@ -0,0 +1,140 @@
+// RUN: %check_clang_tidy %s readability-redundant-string-init %t
+
+namespace std {
+template <typename T>
+class allocator {};
+template <typename T>
+class char_traits {};
+template <typename C, typename T = std::char_traits<C>, typename A = std::allocator<C>>
+struct basic_string {
+ basic_string();
+ basic_string(const basic_string&);
+ basic_string(const C *, const A &a = A());
+ ~basic_string();
+};
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+}
+
+void f() {
+ std::string a = "";
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization [readability-redundant-string-init]
+ // CHECK-FIXES: std::string a;
+ std::string b("");
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+ // CHECK-FIXES: std::string b;
+ std::string c = R"()";
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+ // CHECK-FIXES: std::string c;
+ std::string d(R"()");
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+ // CHECK-FIXES: std::string d;
+
+ std::string u = "u";
+ std::string w("w");
+ std::string x = R"(x)";
+ std::string y(R"(y)");
+ std::string z;
+}
+
+void g() {
+ std::wstring a = L"";
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization
+ // CHECK-FIXES: std::wstring a;
+ std::wstring b(L"");
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization
+ // CHECK-FIXES: std::wstring b;
+ std::wstring c = LR"()";
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization
+ // CHECK-FIXES: std::wstring c;
+ std::wstring d(LR"()");
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization
+ // CHECK-FIXES: std::wstring d;
+
+ std::wstring u = L"u";
+ std::wstring w(L"w");
+ std::wstring x = LR"(x)";
+ std::wstring y(LR"(y)");
+ std::wstring z;
+}
+
+template <typename T>
+void templ() {
+ std::string s = "";
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+ // CHECK-FIXES: std::string s;
+}
+
+#define M(x) x
+#define N { std::string s = ""; }
+// CHECK-FIXES: #define N { std::string s = ""; }
+
+void h() {
+ templ<int>();
+ templ<double>();
+
+ M({ std::string s = ""; })
+ // CHECK-MESSAGES: [[@LINE-1]]:19: warning: redundant string initialization
+ // CHECK-FIXES: M({ std::string s; })
+
+ N
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: redundant string initialization
+ // CHECK-FIXES: N
+ N
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: redundant string initialization
+ // CHECK-FIXES: N
+}
+
+typedef std::string MyString;
+#define STRING MyString
+#define DECL_STRING(name, val) STRING name = val
+
+void i() {
+ MyString a = "";
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant string initialization
+ // CHECK-FIXES: MyString a;
+ STRING b = "";
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: redundant string initialization
+ // CHECK-FIXES: STRING b;
+ MyString c = "" "" "";
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant string initialization
+ // CHECK-FIXES: MyString c;
+ STRING d = "" "" "";
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: redundant string initialization
+ // CHECK-FIXES: STRING d;
+ DECL_STRING(e, "");
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+
+ MyString f = "u";
+ STRING g = "u";
+ DECL_STRING(h, "u");
+}
+
+#define EMPTY_STR ""
+void j() {
+ std::string a(EMPTY_STR);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+ // CHECK-FIXES: std::string a;
+ std::string b = (EMPTY_STR);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+ // CHECK-FIXES: std::string b;
+
+ std::string c(EMPTY_STR "u" EMPTY_STR);
+}
+
+void k() {
+ std::string a = "", b = "", c = "";
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+ // CHECK-MESSAGES: [[@LINE-2]]:23: warning: redundant string initialization
+ // CHECK-MESSAGES: [[@LINE-3]]:31: warning: redundant string initialization
+ // CHECK-FIXES: std::string a, b, c;
+
+ std::string d = "u", e = "u", f = "u";
+}
+
+// These cases should not generate warnings.
+extern void Param1(std::string param = "");
+extern void Param2(const std::string& param = "");
+void Param3(std::string param = "") {}
+void Param4(STRING param = "") {}
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-bool-expr-chained-conditional-assignment.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-bool-expr-chained-conditional-assignment.cpp
new file mode 100644
index 0000000..65b86c3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-bool-expr-chained-conditional-assignment.cpp
@@ -0,0 +1,34 @@
+// RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t -- -config="{CheckOptions: [{key: "readability-simplify-boolean-expr.ChainedConditionalAssignment", value: 1}]}" --
+
+void chained_conditional_compound_assignment(int i) {
+ bool b;
+ if (i < 0) {
+ b = true;
+ } else if (i < 10) {
+ b = false;
+ } else if (i > 20) {
+ b = true;
+ } else {
+ b = false;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:9: warning: redundant boolean literal in conditional assignment [readability-simplify-boolean-expr]
+ // CHECK-FIXES: {{^}} } else if (i < 10) {{{$}}
+ // CHECK-FIXES-NEXT: {{^}} b = false;{{$}}
+ // CHECK-FIXES-NEXT: {{^}} } else b = i > 20;{{$}}
+}
+
+void chained_conditional_assignment(int i) {
+ bool b;
+ if (i < 0)
+ b = true;
+ else if (i < 10)
+ b = false;
+ else if (i > 20)
+ b = true;
+ else
+ b = false;
+ // CHECK-MESSAGES: :[[@LINE-3]]:9: warning: {{.*}} in conditional assignment
+ // CHECK-FIXES: {{^}} else if (i < 10)
+ // CHECK-FIXES-NEXT: {{^}} b = false;
+ // CHECK-FIXES-NEXT: {{^}} else b = i > 20;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-bool-expr-chained-conditional-return.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-bool-expr-chained-conditional-return.cpp
new file mode 100644
index 0000000..fb8759c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-bool-expr-chained-conditional-return.cpp
@@ -0,0 +1,94 @@
+// RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t -- -config="{CheckOptions: [{key: "readability-simplify-boolean-expr.ChainedConditionalReturn", value: 1}]}" --
+
+bool chained_conditional_compound_return(int i) {
+ if (i < 0) {
+ return true;
+ } else if (i < 10) {
+ return false;
+ } else if (i > 20) {
+ return true;
+ } else {
+ return false;
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:12: warning: redundant boolean literal in conditional return statement [readability-simplify-boolean-expr]
+ // CHECK-FIXES: {{^}} } else if (i < 10) {{{$}}
+ // CHECK-FIXES-NEXT: {{^}} return false;{{$}}
+ // CHECK-FIXES-NEXT: {{^}} } else return i > 20;{{$}}
+}
+
+bool chained_conditional_return(int i) {
+ if (i < 0)
+ return true;
+ else if (i < 10)
+ return false;
+ else if (i > 20)
+ return true;
+ else
+ return false;
+ // CHECK-MESSAGES: :[[@LINE-3]]:12: warning: {{.*}} in conditional return statement
+ // CHECK-FIXES: {{^}} else if (i < 10)
+ // CHECK-FIXES-NEXT: {{^}} return false;
+ // CHECK-FIXES-NEXT: {{^}} else return i > 20;
+}
+
+bool chained_simple_if_return(int i) {
+ if (i < 5)
+ return true;
+ if (i > 10)
+ return true;
+ return false;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool chained_simple_if_return(int i) {{{$}}
+// CHECK-FIXES: {{^}} if (i < 5){{$}}
+// CHECK-FIXES: {{^ return true;$}}
+// CHECK-FIXES: {{^ return i > 10;$}}
+// CHECK-FIXES: {{^}$}}
+
+bool chained_simple_if_return_negated(int i) {
+ if (i < 5)
+ return false;
+ if (i > 10)
+ return false;
+ return true;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool chained_simple_if_return_negated(int i) {{{$}}
+// CHECK-FIXES: {{^}} if (i < 5){{$}}
+// CHECK-FIXES: {{^ return false;$}}
+// CHECK-FIXES: {{^ return i <= 10;$}}
+// CHECK-FIXES: {{^}$}}
+
+bool complex_chained_if_return_return(int i) {
+ if (i < 5) {
+ return true;
+ }
+ if (i > 10) {
+ return true;
+ }
+ return false;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool complex_chained_if_return_return(int i) {{{$}}
+// CHECK-FIXES: {{^}} if (i < 5) {{{$}}
+// CHECK-FIXES: {{^}} return true;{{$}}
+// CHECK-FIXES: {{^}} }{{$}}
+// CHECK-FIXES: {{^ return i > 10;$}}
+// CHECK-FIXES: {{^}$}}
+
+bool complex_chained_if_return_return_negated(int i) {
+ if (i < 5) {
+ return false;
+ }
+ if (i > 10) {
+ return false;
+ }
+ return true;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool complex_chained_if_return_return_negated(int i) {{{$}}
+// CHECK-FIXES: {{^}} if (i < 5) {{{$}}
+// CHECK-FIXES: {{^}} return false;{{$}}
+// CHECK-FIXES: {{^}} }{{$}}
+// CHECK-FIXES: {{^ return i <= 10;$}}
+// CHECK-FIXES: {{^}$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-bool-expr.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-bool-expr.cpp
new file mode 100644
index 0000000..cd93c5d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-bool-expr.cpp
@@ -0,0 +1,950 @@
+// RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t
+
+bool a1 = false;
+
+//=-=-=-=-=-=-= operator ==
+bool aa = false == a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant boolean literal supplied to boolean operator [readability-simplify-boolean-expr]
+// CHECK-FIXES: {{^bool aa = !a1;$}}
+bool ab = true == a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool ab = a1;$}}
+bool a2 = a1 == false;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a2 = !a1;$}}
+bool a3 = a1 == true;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a3 = a1;$}}
+
+//=-=-=-=-=-=-= operator !=
+bool n1 = a1 != false;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool n1 = a1;$}}
+bool n2 = a1 != true;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool n2 = !a1;$}}
+bool n3 = false != a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool n3 = a1;$}}
+bool n4 = true != a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool n4 = !a1;$}}
+
+//=-=-=-=-=-=-= operator ||
+bool a4 = a1 || false;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a4 = a1;$}}
+bool a5 = a1 || true;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a5 = true;$}}
+bool a6 = false || a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a6 = a1;$}}
+bool a7 = true || a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a7 = true;$}}
+
+//=-=-=-=-=-=-= operator &&
+bool a8 = a1 && false;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a8 = false;$}}
+bool a9 = a1 && true;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a9 = a1;$}}
+bool ac = false && a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool ac = false;$}}
+bool ad = true && a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool ad = a1;$}}
+
+void if_with_bool_literal_condition() {
+ int i = 0;
+ if (false) {
+ i = 1;
+ } else {
+ i = 2;
+ }
+ i = 3;
+ // CHECK-MESSAGES: :[[@LINE-6]]:7: warning: {{.*}} in if statement condition
+ // CHECK-FIXES: {{^ int i = 0;$}}
+ // CHECK-FIXES-NEXT: {{^ {$}}
+ // CHECK-FIXES-NEXT: {{^ i = 2;$}}
+ // CHECK-FIXES-NEXT: {{^ }$}}
+ // CHECK-FIXES-NEXT: {{^ i = 3;$}}
+
+ i = 4;
+ if (true) {
+ i = 5;
+ } else {
+ i = 6;
+ }
+ i = 7;
+ // CHECK-MESSAGES: :[[@LINE-6]]:7: warning: {{.*}} in if statement condition
+ // CHECK-FIXES: {{^ i = 4;$}}
+ // CHECK-FIXES-NEXT: {{^ {$}}
+ // CHECK-FIXES-NEXT: {{^ i = 5;$}}
+ // CHECK-FIXES-NEXT: {{^ }$}}
+ // CHECK-FIXES-NEXT: {{^ i = 7;$}}
+
+ i = 8;
+ if (false) {
+ i = 9;
+ }
+ i = 11;
+ // CHECK-MESSAGES: :[[@LINE-4]]:7: warning: {{.*}} in if statement condition
+ // CHECK-FIXES: {{^ i = 8;$}}
+ // CHECK-FIXES-NEXT: {{^ $}}
+ // CHECK-FIXES-NEXT: {{^ i = 11;$}}
+}
+
+void operator_equals() {
+ int i = 0;
+ bool b1 = (i > 2);
+ if (b1 == true) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(b1\) {$}}
+ i = 5;
+ } else {
+ i = 6;
+ }
+ bool b2 = (i > 4);
+ if (b2 == false) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(!b2\) {$}}
+ i = 7;
+ } else {
+ i = 9;
+ }
+ bool b3 = (i > 6);
+ if (true == b3) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(b3\) {$}}
+ i = 10;
+ } else {
+ i = 11;
+ }
+ bool b4 = (i > 8);
+ if (false == b4) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(!b4\) {$}}
+ i = 12;
+ } else {
+ i = 13;
+ }
+}
+
+void operator_or() {
+ int i = 0;
+ bool b5 = (i > 10);
+ if (b5 || false) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(b5\) {$}}
+ i = 14;
+ } else {
+ i = 15;
+ }
+ bool b6 = (i > 10);
+ if (b6 || true) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(true\) {$}}
+ i = 16;
+ } else {
+ i = 17;
+ }
+ bool b7 = (i > 10);
+ if (false || b7) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(b7\) {$}}
+ i = 18;
+ } else {
+ i = 19;
+ }
+ bool b8 = (i > 10);
+ if (true || b8) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(true\) {$}}
+ i = 20;
+ } else {
+ i = 21;
+ }
+}
+
+void operator_and() {
+ int i = 0;
+ bool b9 = (i > 20);
+ if (b9 && false) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(false\) {$}}
+ i = 22;
+ } else {
+ i = 23;
+ }
+ bool ba = (i > 20);
+ if (ba && true) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(ba\) {$}}
+ i = 24;
+ } else {
+ i = 25;
+ }
+ bool bb = (i > 20);
+ if (false && bb) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(false\) {$}}
+ i = 26;
+ } else {
+ i = 27;
+ }
+ bool bc = (i > 20);
+ if (true && bc) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(bc\) {$}}
+ i = 28;
+ } else {
+ i = 29;
+ }
+}
+
+void ternary_operator() {
+ int i = 0;
+ bool bd = (i > 20) ? true : false;
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: {{.*}} in ternary expression result
+ // CHECK-FIXES: {{^ bool bd = i > 20;$}}
+
+ bool be = (i > 20) ? false : true;
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: {{.*}} in ternary expression result
+ // CHECK-FIXES: {{^ bool be = i <= 20;$}}
+
+ bool bf = ((i > 20)) ? false : true;
+ // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: {{.*}} in ternary expression result
+ // CHECK-FIXES: {{^ bool bf = i <= 20;$}}
+}
+
+void operator_not_equal() {
+ int i = 0;
+ bool bf = (i > 20);
+ if (false != bf) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(bf\) {$}}
+ i = 30;
+ } else {
+ i = 31;
+ }
+ bool bg = (i > 20);
+ if (true != bg) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(!bg\) {$}}
+ i = 32;
+ } else {
+ i = 33;
+ }
+ bool bh = (i > 20);
+ if (bh != false) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(bh\) {$}}
+ i = 34;
+ } else {
+ i = 35;
+ }
+ bool bi = (i > 20);
+ if (bi != true) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(!bi\) {$}}
+ i = 36;
+ } else {
+ i = 37;
+ }
+}
+
+void nested_booleans() {
+ if (false || (true || false)) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(false \|\| \(true\)\) {$}}
+ }
+ if (true && (true || false)) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(true && \(true\)\) {$}}
+ }
+ if (false || (true && false)) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(false \|\| \(false\)\) {$}}
+ }
+ if (true && (true && false)) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(true && \(false\)\) {$}}
+ }
+}
+
+static constexpr bool truthy() {
+ return true;
+}
+
+#define HAS_XYZ_FEATURE true
+#define M1(what) M2(true, what)
+#define M2(condition, what) if (condition) what
+
+void macros_and_constexprs(int i = 0) {
+ bool b = (i == 1);
+ if (b && truthy()) {
+ // leave this alone; if you want it simplified, then you should
+ // inline the constexpr function first.
+ i = 1;
+ }
+ i = 2;
+ if (b && HAS_XYZ_FEATURE) {
+ // leave this alone; if you want it simplified, then you should
+ // inline the macro first.
+ i = 3;
+ }
+ if (HAS_XYZ_FEATURE) {
+ i = 5;
+ }
+ i = 4;
+ M1(i = 7);
+}
+
+#undef HAS_XYZ_FEATURE
+
+bool conditional_return_statements(int i) {
+ if (i == 0) return true; else return false;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:22: warning: {{.*}} in conditional return statement
+// CHECK-FIXES: {{^}} return i == 0;{{$}}
+// CHECK-FIXES-NEXT: {{^}$}}
+
+bool conditional_return_statements_then_expr(int i, int j) {
+ if (i == j) return (i == 0); else return false;
+}
+
+bool conditional_return_statements_else_expr(int i, int j) {
+ if (i == j) return true; else return (i == 0);
+}
+
+bool negated_conditional_return_statements(int i) {
+ if (i == 0) return false; else return true;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:22: warning: {{.*}} in conditional return statement
+// CHECK-FIXES: {{^}} return i != 0;{{$}}
+// CHECK-FIXES-NEXT: {{^}$}}
+
+bool negative_condition_conditional_return_statement(int i) {
+ if (!(i == 0)) return false; else return true;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:25: warning: {{.*}} in conditional return statement
+// CHECK-FIXES: {{^}} return i == 0;{{$}}
+// CHECK-FIXES-NEXT: {{^}$}}
+
+bool conditional_compound_return_statements(int i) {
+ if (i == 1) {
+ return true;
+ } else {
+ return false;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return statement
+// CHECK-FIXES: {{^}}bool conditional_compound_return_statements(int i) {{{$}}
+// CHECK-FIXES-NEXT: {{^}} return i == 1;{{$}}
+// CHECK-FIXES-NEXT: {{^}$}}
+
+bool negated_conditional_compound_return_statements(int i) {
+ if (i == 1) {
+ return false;
+ } else {
+ return true;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return statement
+// CHECK-FIXES: {{^}}bool negated_conditional_compound_return_statements(int i) {{{$}}
+// CHECK-FIXES-NEXT: {{^}} return i != 1;{{$}}
+// CHECK-FIXES-NEXT: {{^}$}}
+
+bool conditional_return_statements_side_effects_then(int i) {
+ if (i == 2) {
+ macros_and_constexprs();
+ return true;
+ } else
+ return false;
+}
+
+bool negated_conditional_return_statements_side_effects_then(int i) {
+ if (i == 2) {
+ macros_and_constexprs();
+ return false;
+ } else
+ return true;
+}
+
+bool conditional_return_statements_side_effects_else(int i) {
+ if (i == 2)
+ return true;
+ else {
+ macros_and_constexprs();
+ return false;
+ }
+}
+
+bool negated_conditional_return_statements_side_effects_else(int i) {
+ if (i == 2)
+ return false;
+ else {
+ macros_and_constexprs();
+ return true;
+ }
+}
+
+void lambda_conditional_return_statements() {
+ auto lambda = [](int n) -> bool { if (n > 0) return true; else return false; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:55: warning: {{.*}} in conditional return statement
+ // CHECK-FIXES: {{^}} auto lambda = [](int n) -> bool { return n > 0; };{{$}}
+
+ auto lambda2 = [](int n) -> bool {
+ if (n > 0) {
+ return true;
+ } else {
+ return false;
+ }
+ };
+ // CHECK-MESSAGES: :[[@LINE-5]]:16: warning: {{.*}} in conditional return statement
+ // CHECK-FIXES: {{^}} auto lambda2 = [](int n) -> bool {{{$}}
+ // CHECK-FIXES-NEXT: {{^}} return n > 0;{{$}}
+ // CHECK-FIXES-NEXT: {{^}} };{{$}}
+
+ auto lambda3 = [](int n) -> bool { if (n > 0) {macros_and_constexprs(); return true; } else return false; };
+
+ auto lambda4 = [](int n) -> bool {
+ if (n > 0)
+ return true;
+ else {
+ macros_and_constexprs();
+ return false;
+ }
+ };
+
+ auto lambda5 = [](int n) -> bool { if (n > 0) return false; else return true; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:56: warning: {{.*}} in conditional return statement
+ // CHECK-FIXES: {{^}} auto lambda5 = [](int n) -> bool { return n <= 0; };{{$}}
+
+ auto lambda6 = [](int n) -> bool {
+ if (n > 0) {
+ return false;
+ } else {
+ return true;
+ }
+ };
+ // CHECK-MESSAGES: :[[@LINE-5]]:16: warning: {{.*}} in conditional return statement
+ // CHECK-FIXES: {{^}} auto lambda6 = [](int n) -> bool {{{$}}
+ // CHECK-FIXES-NEXT: {{^}} return n <= 0;{{$}}
+ // CHECK-FIXES-NEXT: {{^}} };{{$}}
+}
+
+void simple_conditional_assignment_statements(int i) {
+ bool b;
+ if (i > 10)
+ b = true;
+ else
+ b = false;
+ bool bb = false;
+ // CHECK-MESSAGES: :[[@LINE-4]]:9: warning: {{.*}} in conditional assignment
+ // CHECK-FIXES: bool b;
+ // CHECK-FIXES: {{^ }}b = i > 10;{{$}}
+ // CHECK-FIXES: bool bb = false;
+
+ bool c;
+ if (i > 20)
+ c = false;
+ else
+ c = true;
+ bool c2 = false;
+ // CHECK-MESSAGES: :[[@LINE-4]]:9: warning: {{.*}} in conditional assignment
+ // CHECK-FIXES: bool c;
+ // CHECK-FIXES: {{^ }}c = i <= 20;{{$}}
+ // CHECK-FIXES: bool c2 = false;
+
+ // Unchanged: different variables.
+ bool b2;
+ if (i > 12)
+ b = true;
+ else
+ b2 = false;
+
+ // Unchanged: no else statement.
+ bool b3;
+ if (i > 15)
+ b3 = true;
+
+ // Unchanged: not boolean assignment.
+ int j;
+ if (i > 17)
+ j = 10;
+ else
+ j = 20;
+
+ // Unchanged: different variables assigned.
+ int k = 0;
+ bool b4 = false;
+ if (i > 10)
+ b4 = true;
+ else
+ k = 10;
+}
+
+void complex_conditional_assignment_statements(int i) {
+ bool d;
+ if (i > 30) {
+ d = true;
+ } else {
+ d = false;
+ }
+ d = false;
+ // CHECK-MESSAGES: :[[@LINE-5]]:9: warning: {{.*}} in conditional assignment
+ // CHECK-FIXES: bool d;
+ // CHECK-FIXES: {{^ }}d = i > 30;{{$}}
+ // CHECK-FIXES: d = false;
+
+ bool e;
+ if (i > 40) {
+ e = false;
+ } else {
+ e = true;
+ }
+ e = false;
+ // CHECK-MESSAGES: :[[@LINE-5]]:9: warning: {{.*}} in conditional assignment
+ // CHECK-FIXES: bool e;
+ // CHECK-FIXES: {{^ }}e = i <= 40;{{$}}
+ // CHECK-FIXES: e = false;
+
+ // Unchanged: no else statement.
+ bool b3;
+ if (i > 15) {
+ b3 = true;
+ }
+
+ // Unchanged: not a boolean assignment.
+ int j;
+ if (i > 17) {
+ j = 10;
+ } else {
+ j = 20;
+ }
+
+ // Unchanged: multiple statements.
+ bool f;
+ if (j > 10) {
+ j = 10;
+ f = true;
+ } else {
+ j = 20;
+ f = false;
+ }
+
+ // Unchanged: multiple statements.
+ bool g;
+ if (j > 10)
+ f = true;
+ else {
+ j = 20;
+ f = false;
+ }
+
+ // Unchanged: multiple statements.
+ bool h;
+ if (j > 10) {
+ j = 10;
+ f = true;
+ } else
+ f = false;
+}
+
+// Unchanged: chained return statements, but ChainedConditionalReturn not set.
+bool chained_conditional_compound_return(int i) {
+ if (i < 0) {
+ return true;
+ } else if (i < 10) {
+ return false;
+ } else if (i > 20) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+// Unchanged: chained return statements, but ChainedConditionalReturn not set.
+bool chained_conditional_return(int i) {
+ if (i < 0)
+ return true;
+ else if (i < 10)
+ return false;
+ else if (i > 20)
+ return true;
+ else
+ return false;
+}
+
+// Unchanged: chained assignments, but ChainedConditionalAssignment not set.
+void chained_conditional_compound_assignment(int i) {
+ bool b;
+ if (i < 0) {
+ b = true;
+ } else if (i < 10) {
+ b = false;
+ } else if (i > 20) {
+ b = true;
+ } else {
+ b = false;
+ }
+}
+
+// Unchanged: chained return statements, but ChainedConditionalReturn not set.
+void chained_conditional_assignment(int i) {
+ bool b;
+ if (i < 0)
+ b = true;
+ else if (i < 10)
+ b = false;
+ else if (i > 20)
+ b = true;
+ else
+ b = false;
+}
+
+// Unchanged: chained return statements, but ChainedConditionalReturn not set.
+bool chained_simple_if_return_negated(int i) {
+ if (i < 5)
+ return false;
+ if (i > 10)
+ return false;
+ return true;
+}
+
+// Unchanged: chained return statements, but ChainedConditionalReturn not set.
+bool complex_chained_if_return_return(int i) {
+ if (i < 5) {
+ return true;
+ }
+ if (i > 10) {
+ return true;
+ }
+ return false;
+}
+
+// Unchanged: chained return statements, but ChainedConditionalReturn not set.
+bool complex_chained_if_return_return_negated(int i) {
+ if (i < 5) {
+ return false;
+ }
+ if (i > 10) {
+ return false;
+ }
+ return true;
+}
+
+// Unchanged: chained return statements, but ChainedConditionalReturn not set.
+bool chained_simple_if_return(int i) {
+ if (i < 5)
+ return true;
+ if (i > 10)
+ return true;
+ return false;
+}
+
+bool simple_if_return_return(int i) {
+ if (i > 10)
+ return true;
+ return false;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool simple_if_return_return(int i) {{{$}}
+// CHECK-FIXES: {{^ return i > 10;$}}
+// CHECK-FIXES: {{^}$}}
+
+bool simple_if_return_return_negated(int i) {
+ if (i > 10)
+ return false;
+ return true;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool simple_if_return_return_negated(int i) {{{$}}
+// CHECK-FIXES: {{^ return i <= 10;$}}
+// CHECK-FIXES: {{^}$}}
+
+bool complex_if_return_return(int i) {
+ if (i > 10) {
+ return true;
+ }
+ return false;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool complex_if_return_return(int i) {{{$}}
+// CHECK-FIXES: {{^ return i > 10;$}}
+// CHECK-FIXES: {{^}$}}
+
+bool complex_if_return_return_negated(int i) {
+ if (i > 10) {
+ return false;
+ }
+ return true;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool complex_if_return_return_negated(int i) {{{$}}
+// CHECK-FIXES: {{^ return i <= 10;$}}
+// CHECK-FIXES: {{^}$}}
+
+bool if_implicit_bool_expr(int i) {
+ if (i & 1) {
+ return true;
+ } else {
+ return false;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}} return (i & 1) != 0;{{$}}
+
+bool negated_if_implicit_bool_expr(int i) {
+ if (i - 1) {
+ return false;
+ } else {
+ return true;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}} return (i - 1) == 0;{{$}}
+
+bool implicit_int(int i) {
+ if (i) {
+ return true;
+ } else {
+ return false;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}} return i != 0;{{$}}
+
+bool explicit_bool(bool b) {
+ if (b) {
+ return true;
+ } else {
+ return false;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}} return b;{{$}}
+
+class Implicit {
+public:
+ operator bool() {
+ return true;
+ }
+};
+
+bool object_bool_implicit_conversion(Implicit O) {
+ if (O) {
+ return true;
+ } else {
+ return false;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}} return O;{{$}}
+
+bool negated_explicit_bool(bool b) {
+ if (!b) {
+ return true;
+ } else {
+ return false;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}} return !b;{{$}}
+
+bool bitwise_complement_conversion(int i) {
+ if (~i) {
+ return true;
+ } else {
+ return false;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}} return ~i != 0;{{$}}
+
+bool logical_or(bool a, bool b) {
+ if (a || b) {
+ return true;
+ } else {
+ return false;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}} return a || b;{{$}}
+
+bool logical_and(bool a, bool b) {
+ if (a && b) {
+ return true;
+ } else {
+ return false;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}} return a && b;{{$}}
+
+class Comparable
+{
+public:
+ bool operator==(Comparable const &rhs) { return true; }
+ bool operator!=(Comparable const &rhs) { return false; }
+};
+
+bool comparable_objects() {
+ Comparable c;
+ Comparable d;
+ if (c == d) {
+ return true;
+ } else {
+ return false;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}} return c == d;{{$}}
+
+bool negated_comparable_objects() {
+ Comparable c;
+ Comparable d;
+ if (c == d) {
+ return false;
+ } else {
+ return true;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}} return c != d;{{$}}
+
+struct X {
+ explicit operator bool();
+};
+
+void explicit_conversion_assignment(X x) {
+ bool y;
+ if (x) {
+ y = true;
+ } else {
+ y = false;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:9: warning: {{.*}} in conditional assignment
+// CHECK-FIXES: {{^ bool y;$}}
+// CHECK-FIXES: {{^}} y = static_cast<bool>(x);{{$}}
+
+void ternary_integer_condition(int i) {
+ bool b = i ? true : false;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:16: warning: {{.*}} in ternary expression result
+// CHECK-FIXES: bool b = i != 0;{{$}}
+
+bool non_null_pointer_condition(int *p1) {
+ if (p1) {
+ return true;
+ } else {
+ return false;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: return p1 != nullptr;{{$}}
+
+bool null_pointer_condition(int *p2) {
+ if (!p2) {
+ return true;
+ } else {
+ return false;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: return p2 == nullptr;{{$}}
+
+bool negated_non_null_pointer_condition(int *p3) {
+ if (p3) {
+ return false;
+ } else {
+ return true;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: return p3 == nullptr;{{$}}
+
+bool negated_null_pointer_condition(int *p4) {
+ if (!p4) {
+ return false;
+ } else {
+ return true;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: return p4 != nullptr;{{$}}
+
+bool comments_in_the_middle(bool b) {
+ if (b) {
+ return true;
+ } else {
+ // something wicked this way comes
+ return false;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-6]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}} if (b) {
+// CHECK-FIXES: // something wicked this way comes{{$}}
+
+bool preprocessor_in_the_middle(bool b) {
+ if (b) {
+ return true;
+ } else {
+#define SOMETHING_WICKED false
+ return false;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-6]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}} if (b) {
+// CHECK-FIXES: {{^}}#define SOMETHING_WICKED false
+
+bool integer_not_zero(int i) {
+ if (i) {
+ return false;
+ } else {
+ return true;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}} return i == 0;{{$}}
+
+class A {
+public:
+ int m;
+};
+
+bool member_pointer_nullptr(int A::*p) {
+ if (p) {
+ return true;
+ } else {
+ return false;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: return p != nullptr;{{$}}
+
+bool integer_member_implicit_cast(A *p) {
+ if (p->m) {
+ return true;
+ } else {
+ return false;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: return p->m != 0;{{$}}
+
+bool operator!=(const A&, const A&) { return false; }
+bool expr_with_cleanups(A &S) {
+ if (S != (A)S)
+ return false;
+
+ return true;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: S == (A)S;{{$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-subscript-expr.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-subscript-expr.cpp
new file mode 100644
index 0000000..16197dc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-subscript-expr.cpp
@@ -0,0 +1,108 @@
+// RUN: %check_clang_tidy %s readability-simplify-subscript-expr %t \
+// RUN: -config="{CheckOptions: \
+// RUN: [{key: readability-simplify-subscript-expr.Types, \
+// RUN: value: '::std::basic_string;::std::basic_string_view;MyVector'}]}" --
+
+namespace std {
+
+template <class T>
+class basic_string {
+ public:
+ using size_type = unsigned;
+ using value_type = T;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+
+ reference operator[](size_type);
+ const_reference operator[](size_type) const;
+ T* data();
+ const T* data() const;
+};
+
+using string = basic_string<char>;
+
+template <class T>
+class basic_string_view {
+ public:
+ using size_type = unsigned;
+ using const_reference = const T&;
+ using const_pointer = const T*;
+
+ constexpr const_reference operator[](size_type) const;
+ constexpr const_pointer data() const noexcept;
+};
+
+using string_view = basic_string_view<char>;
+
+}
+
+template <class T>
+class MyVector {
+ public:
+ using size_type = unsigned;
+ using const_reference = const T&;
+ using const_pointer = const T*;
+
+ const_reference operator[](size_type) const;
+ const T* data() const noexcept;
+};
+
+#define DO(x) do { x; } while (false)
+#define ACCESS(x) (x)
+#define GET(x, i) (x).data()[i]
+
+template <class T>
+class Foo {
+ public:
+ char bar(int i) {
+ return x.data()[i];
+ }
+ private:
+ T x;
+};
+
+void f(int i) {
+ MyVector<int> v;
+ int x = v.data()[i];
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: accessing an element of the container does not require a call to 'data()'; did you mean to use 'operator[]'? [readability-simplify-subscript-expr]
+ // CHECK-FIXES: int x = v[i];
+
+ std::string s;
+ char c1 = s.data()[i];
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: accessing an element
+ // CHECK-FIXES: char c1 = s[i];
+
+ std::string_view sv;
+ char c2 = sv.data()[i];
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: accessing an element
+ // CHECK-FIXES: char c2 = sv[i];
+
+ std::string* ps = &s;
+ char c3 = ps->data()[i];
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: accessing an element
+ // CHECK-FIXES: char c3 = (*ps)[i];
+
+ char c4 = (*ps).data()[i];
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: accessing an element
+ // CHECK-FIXES: char c4 = (*ps)[i];
+
+ DO(char c5 = s.data()[i]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: accessing an element
+ // CHECK-FIXES: DO(char c5 = s[i]);
+
+ char c6 = ACCESS(s).data()[i];
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: accessing an element
+ // CHECK-FIXES: char c6 = ACCESS(s)[i];
+
+ char c7 = ACCESS(s.data())[i];
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: accessing an element
+ // CHECK-FIXES: char c7 = ACCESS(s)[i];
+
+ char c8 = ACCESS(s.data()[i]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: accessing an element
+ // CHECK-FIXES: char c8 = ACCESS(s[i]);
+
+ char c9 = GET(s, i);
+
+ char c10 = Foo<std::string>{}.bar(i);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance-nesting-threshold.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance-nesting-threshold.cpp
new file mode 100644
index 0000000..0375249
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance-nesting-threshold.cpp
@@ -0,0 +1,33 @@
+// RUN: %check_clang_tidy %s readability-static-accessed-through-instance %t -- -config="{CheckOptions: [{key: readability-static-accessed-through-instance.NameSpecifierNestingThreshold, value: 4}]}" --
+
+// Nested specifiers
+namespace M {
+namespace N {
+struct V {
+ static int v;
+ struct T {
+ static int t;
+ struct U {
+ static int u;
+ };
+ };
+};
+}
+}
+
+void f(M::N::V::T::U u) {
+ M::N::V v;
+ v.v = 12;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+ // CHECK-FIXES: {{^}} M::N::V::v = 12;{{$}}
+
+ M::N::V::T w;
+ w.t = 12;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+ // CHECK-FIXES: {{^}} M::N::V::T::t = 12;{{$}}
+
+ // u.u is not changed, because the nesting level is over 4
+ u.u = 12;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+ // CHECK-FIXES: {{^}} u.u = 12;{{$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance.cpp
new file mode 100644
index 0000000..fc42a1d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance.cpp
@@ -0,0 +1,222 @@
+// RUN: %check_clang_tidy %s readability-static-accessed-through-instance %t
+
+struct C {
+ static void foo();
+ static int x;
+ int nsx;
+ void mf() {
+ (void)&x; // OK, x is accessed inside the struct.
+ (void)&C::x; // OK, x is accessed using a qualified-id.
+ foo(); // OK, foo() is accessed inside the struct.
+ }
+ void ns() const;
+};
+
+int C::x = 0;
+
+struct CC {
+ void foo();
+ int x;
+};
+
+template <typename T> struct CT {
+ static T foo();
+ static T x;
+ int nsx;
+ void mf() {
+ (void)&x; // OK, x is accessed inside the struct.
+ (void)&C::x; // OK, x is accessed using a qualified-id.
+ foo(); // OK, foo() is accessed inside the struct.
+ }
+};
+
+// Expressions with side effects
+C &f(int, int, int, int);
+void g() {
+ f(1, 2, 3, 4).x;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through instance [readability-static-accessed-through-instance]
+ // CHECK-FIXES: {{^}} f(1, 2, 3, 4).x;{{$}}
+}
+
+int i(int &);
+void j(int);
+C h();
+bool a();
+int k(bool);
+
+void f(C c) {
+ j(i(h().x));
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: static member
+ // CHECK-FIXES: {{^}} j(i(h().x));{{$}}
+
+ // The execution of h() depends on the return value of a().
+ j(k(a() && h().x));
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: static member
+ // CHECK-FIXES: {{^}} j(k(a() && h().x));{{$}}
+
+ if ([c]() {
+ c.ns();
+ return c;
+ }().x == 15)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-5]]:7: warning: static member
+ // CHECK-FIXES: {{^}} if ([c]() {{{$}}
+}
+
+// Nested specifiers
+namespace N {
+struct V {
+ static int v;
+ struct T {
+ static int t;
+ struct U {
+ static int u;
+ };
+ };
+};
+}
+
+void f(N::V::T::U u) {
+ N::V v;
+ v.v = 12;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+ // CHECK-FIXES: {{^}} N::V::v = 12;{{$}}
+
+ N::V::T w;
+ w.t = 12;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+ // CHECK-FIXES: {{^}} N::V::T::t = 12;{{$}}
+
+ // u.u is not changed to N::V::T::U::u; because the nesting level is over 3.
+ u.u = 12;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+ // CHECK-FIXES: {{^}} u.u = 12;{{$}}
+
+ using B = N::V::T::U;
+ B b;
+ b.u;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+ // CHECK-FIXES: {{^}} B::u;{{$}}
+}
+
+// Templates
+template <typename T> T CT<T>::x;
+
+template <typename T> struct CCT {
+ T foo();
+ T x;
+};
+
+typedef C D;
+
+using E = D;
+
+#define FOO(c) c.foo()
+#define X(c) c.x
+
+template <typename T> void f(T t, C c) {
+ t.x; // OK, t is a template parameter.
+ c.x;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+ // CHECK-FIXES: {{^}} C::x;{{$}}
+}
+
+template <int N> struct S { static int x; };
+
+template <> struct S<0> { int x; };
+
+template <int N> void h() {
+ S<N> sN;
+ sN.x; // OK, value of N affects whether x is static or not.
+
+ S<2> s2;
+ s2.x;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+ // CHECK-FIXES: {{^}} S<2>::x;{{$}}
+}
+
+void static_through_instance() {
+ C *c1 = new C();
+ c1->foo(); // 1
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+ // CHECK-FIXES: {{^}} C::foo(); // 1{{$}}
+ c1->x; // 2
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+ // CHECK-FIXES: {{^}} C::x; // 2{{$}}
+ c1->nsx; // OK, nsx is a non-static member.
+
+ const C *c2 = new C();
+ c2->foo(); // 2
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+ // CHECK-FIXES: {{^}} C::foo(); // 2{{$}}
+
+ C::foo(); // OK, foo() is accessed using a qualified-id.
+ C::x; // OK, x is accessed using a qualified-id.
+
+ D d;
+ d.foo();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+ // CHECK-FIXES: {{^}} D::foo();{{$}}
+ d.x;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+ // CHECK-FIXES: {{^}} D::x;{{$}}
+
+ E e;
+ e.foo();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+ // CHECK-FIXES: {{^}} E::foo();{{$}}
+ e.x;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+ // CHECK-FIXES: {{^}} E::x;{{$}}
+
+ CC *cc = new CC;
+
+ f(*c1, *c1);
+ f(*cc, *c1);
+
+ // Macros: OK, macros are not checked.
+ FOO((*c1));
+ X((*c1));
+ FOO((*cc));
+ X((*cc));
+
+ // Templates
+ CT<int> ct;
+ ct.foo();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+ // CHECK-FIXES: {{^}} CT<int>::foo();{{$}}
+ ct.x;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+ // CHECK-FIXES: {{^}} CT<int>::x;{{$}}
+ ct.nsx; // OK, nsx is a non-static member
+
+ CCT<int> cct;
+ cct.foo(); // OK, CCT has no static members.
+ cct.x; // OK, CCT has no static members.
+
+ h<4>();
+}
+
+// Overloaded member access operator
+struct Q {
+ static int K;
+ int y = 0;
+};
+
+int Q::K = 0;
+
+struct Qptr {
+ Q *q;
+
+ explicit Qptr(Q *qq) : q(qq) {}
+
+ Q *operator->() {
+ ++q->y;
+ return q;
+ }
+};
+
+int func(Qptr qp) {
+ qp->y = 10; // OK, the overloaded operator might have side-effects.
+ qp->K = 10; //
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-static-definition-in-anonymous-namespace.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-static-definition-in-anonymous-namespace.cpp
new file mode 100644
index 0000000..5c3c8c1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-static-definition-in-anonymous-namespace.cpp
@@ -0,0 +1,49 @@
+// RUN: %check_clang_tidy %s readability-static-definition-in-anonymous-namespace %t
+
+namespace {
+
+int a = 1;
+const int b = 1;
+static int c = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: 'c' is a static definition in anonymous namespace; static is redundant here [readability-static-definition-in-anonymous-namespace]
+// CHECK-FIXES: {{^}}int c = 1;
+static const int d = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'd' is a static definition in anonymous namespace
+// CHECK-FIXES: {{^}}const int d = 1;
+const static int e = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'e' is a static definition in anonymous namespace
+// CHECK-FIXES: {{^}}const int e = 1;
+
+void f() {
+ int a = 1;
+ static int b = 1;
+}
+
+static int g() {
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: 'g' is a static definition in anonymous namespace
+// CHECK-FIXES: {{^}}int g() {
+ return 1;
+}
+
+#define DEFINE_STATIC static
+// CHECK-FIXES: {{^}}#define DEFINE_STATIC static
+DEFINE_STATIC int h = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: 'h' is a static definition in anonymous namespace
+// CHECK-FIXES: {{^}}DEFINE_STATIC int h = 1;
+
+#define DEFINE_STATIC_VAR(x) static int x = 2
+// CHECK-FIXES: {{^}}#define DEFINE_STATIC_VAR(x) static int x = 2
+DEFINE_STATIC_VAR(i);
+// CHECK-FIXES: {{^}}DEFINE_STATIC_VAR(i);
+
+} // namespace
+
+namespace N {
+
+int a = 1;
+const int b = 1;
+static int c = 1;
+static const int d = 1;
+const static int e = 1;
+
+} // namespace N
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-string-compare.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-string-compare.cpp
new file mode 100644
index 0000000..9bd11da
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-string-compare.cpp
@@ -0,0 +1,119 @@
+// RUN: %check_clang_tidy %s readability-string-compare %t -- -- -std=c++11
+
+namespace std {
+template <typename T>
+class allocator {};
+template <typename T>
+class char_traits {};
+template <typename C, typename T = std::char_traits<C>, typename A = std::allocator<C>>
+class basic_string {
+public:
+ basic_string();
+ basic_string(const C *, unsigned int size);
+ int compare(const basic_string<char> &str) const;
+ int compare(const C *) const;
+ int compare(int, int, const basic_string<char> &str) const;
+ bool empty();
+};
+bool operator==(const basic_string<char> &lhs, const basic_string<char> &rhs);
+bool operator!=(const basic_string<char> &lhs, const basic_string<char> &rhs);
+bool operator==(const basic_string<char> &lhs, const char *&rhs);
+typedef basic_string<char> string;
+}
+
+void func(bool b);
+
+std::string comp() {
+ std::string str("a", 1);
+ return str;
+}
+
+void Test() {
+ std::string str1("a", 1);
+ std::string str2("b", 1);
+
+ if (str1.compare(str2)) {
+ }
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings; use the string equality operator instead [readability-string-compare]
+ if (!str1.compare(str2)) {
+ }
+ // CHECK-MESSAGES: [[@LINE-2]]:8: warning: do not use 'compare' to test equality of strings; use the string equality operator instead [readability-string-compare]
+ if (str1.compare(str2) == 0) {
+ }
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+ // CHECK-FIXES: if (str1 == str2) {
+ if (str1.compare(str2) != 0) {
+ }
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+ // CHECK-FIXES: if (str1 != str2) {
+ if (str1.compare("foo") == 0) {
+ }
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+ // CHECK-FIXES: if (str1 == "foo") {
+ if (0 == str1.compare(str2)) {
+ }
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+ // CHECK-FIXES: if (str2 == str1) {
+ if (0 != str1.compare(str2)) {
+ }
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+ // CHECK-FIXES: if (str2 != str1) {
+ func(str1.compare(str2));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: do not use 'compare' to test equality of strings;
+ if (str2.empty() || str1.compare(str2) != 0) {
+ }
+ // CHECK-MESSAGES: [[@LINE-2]]:23: warning: do not use 'compare' to test equality of strings;
+ // CHECK-FIXES: if (str2.empty() || str1 != str2) {
+ std::string *str3 = &str1;
+ if (str3->compare(str2)) {
+ }
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+ if (str3->compare(str2) == 0) {
+ }
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+ // CHECK-FIXES: if (*str3 == str2) {
+ if (str2.compare(*str3) == 0) {
+ }
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+ // CHECK-FIXES: if (str2 == *str3) {
+ if (comp().compare(str1) == 0) {
+ }
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+ // CHECK-FIXES: if (comp() == str1) {
+ if (str1.compare(comp()) == 0) {
+ }
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+ // CHECK-FIXES: if (str1 == comp()) {
+ if (str1.compare(comp())) {
+ }
+ // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+}
+
+void Valid() {
+ std::string str1("a", 1);
+ std::string str2("b", 1);
+ if (str1 == str2) {
+ }
+ if (str1 != str2) {
+ }
+ if (str1.compare(str2) == str1.compare(str2)) {
+ }
+ if (0 == 0) {
+ }
+ if (str1.compare(str2) > 0) {
+ }
+ if (str1.compare(1, 3, str2)) {
+ }
+ if (str1.compare(str2) > 0) {
+ }
+ if (str1.compare(str2) < 0) {
+ }
+ if (str1.compare(str2) == 2) {
+ }
+ if (str1.compare(str2) == -3) {
+ }
+ if (str1.compare(str2) == 1) {
+ }
+ if (str1.compare(str2) == -1) {
+ }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-uniqueptr-delete-release.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-uniqueptr-delete-release.cpp
new file mode 100644
index 0000000..bd51bc6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-uniqueptr-delete-release.cpp
@@ -0,0 +1,76 @@
+// RUN: %check_clang_tidy %s readability-uniqueptr-delete-release %t
+
+namespace std {
+template <typename T>
+struct default_delete {};
+
+template <typename T, typename D = default_delete<T>>
+class unique_ptr {
+ public:
+ unique_ptr();
+ ~unique_ptr();
+ explicit unique_ptr(T*);
+ template <typename U, typename E>
+ unique_ptr(unique_ptr<U, E>&&);
+ T* release();
+};
+} // namespace std
+
+std::unique_ptr<int>& ReturnsAUnique();
+
+void Positives() {
+ std::unique_ptr<int> P;
+ delete P.release();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer '= nullptr' to 'delete x.release()' to reset unique_ptr<> objects [readability-uniqueptr-delete-release]
+ // CHECK-FIXES: {{^}} P = nullptr;
+
+ auto P2 = P;
+ delete P2.release();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer '= nullptr' to 'delete x.release()' to reset unique_ptr<> objects [readability-uniqueptr-delete-release]
+ // CHECK-FIXES: {{^}} P2 = nullptr;
+
+ std::unique_ptr<int> Array[20];
+ delete Array[4].release();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer '= nullptr' to 'delete
+ // CHECK-FIXES: {{^}} Array[4] = nullptr;
+
+ delete ReturnsAUnique().release();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer '= nullptr' to 'delete
+ // CHECK-FIXES: {{^}} ReturnsAUnique() = nullptr;
+}
+
+struct NotDefaultDeleter {};
+
+struct NotUniquePtr {
+ int* release();
+};
+
+void Negatives() {
+ std::unique_ptr<int, NotDefaultDeleter> P;
+ delete P.release();
+
+ NotUniquePtr P2;
+ delete P2.release();
+}
+
+template <typename T, typename D>
+void NegativeDeleterT() {
+ // Ideally this would trigger a warning, but we have all dependent types
+ // disabled for now.
+ std::unique_ptr<T> P;
+ delete P.release();
+
+ // We ignore this one because the deleter is a template argument.
+ // Not all instantiations will use the default deleter.
+ std::unique_ptr<int, D> P2;
+ delete P2.release();
+}
+template void NegativeDeleterT<int, std::default_delete<int>>();
+
+// Test some macros
+
+#define DELETE_RELEASE(x) delete (x).release()
+void NegativesWithTemplate() {
+ std::unique_ptr<int> P;
+ DELETE_RELEASE(P);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/run-clang-tidy.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/run-clang-tidy.cpp
new file mode 100644
index 0000000..2207e43
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/run-clang-tidy.cpp
@@ -0,0 +1,17 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "[{\"directory\":\".\",\"command\":\"clang++ -c %/t/test.cpp\",\"file\":\"%/t/test.cpp\"}]" | sed -e 's/\\/\\\\/g' > %t/compile_commands.json
+// RUN: echo "Checks: '-*,modernize-use-auto'" > %t/.clang-tidy
+// RUN: echo "WarningsAsErrors: '*'" >> %t/.clang-tidy
+// RUN: echo "CheckOptions:" >> %t/.clang-tidy
+// RUN: echo " - key: modernize-use-auto.MinTypeNameLength" >> %t/.clang-tidy
+// RUN: echo " value: '0'" >> %t/.clang-tidy
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: cd "%t"
+// RUN: not %run_clang_tidy "%t/test.cpp"
+
+int main()
+{
+ int* x = new int();
+ delete x;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/select-checks.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/select-checks.cpp
new file mode 100644
index 0000000..791def7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/select-checks.cpp
@@ -0,0 +1,11 @@
+// RUN: clang-tidy %s -checks='-*,llvm-namespace-*' -- 2>&1 | FileCheck -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy %s -checks='-*,an-unknown-check' -- 2>&1 | FileCheck -implicit-check-not='{{warning:|error:}}' -check-prefix=CHECK2 %s
+
+// CHECK2: Error: no checks enabled.
+
+namespace i {
+}
+// CHECK: :[[@LINE-1]]:2: warning: namespace 'i' not terminated with a closing comment [llvm-namespace-comment]
+
+// Expect no warnings from the google-explicit-constructor check:
+class A { A(int i); };
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/serialize-diagnostics.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/serialize-diagnostics.cpp
new file mode 100644
index 0000000..8b0895a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/serialize-diagnostics.cpp
@@ -0,0 +1,3 @@
+// RUN: not clang-tidy -checks=-*,llvm-namespace-comment %s -- -serialize-diagnostics %t | FileCheck %s
+// CHECK: :[[@LINE+1]]:12: error: expected ';' after struct [clang-diagnostic-error]
+struct A {}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/static-analyzer-config.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/static-analyzer-config.cpp
new file mode 100644
index 0000000..cee0a4c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/static-analyzer-config.cpp
@@ -0,0 +1,19 @@
+// RUN: clang-tidy %s -checks='-*,clang-analyzer-unix.Malloc' -config='{CheckOptions: [{ key: "clang-analyzer-unix.Malloc:Optimistic", value: true}]}' -- | FileCheck %s
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
+void free(void *);
+void __attribute((ownership_returns(malloc))) *my_malloc(size_t);
+void __attribute((ownership_takes(malloc, 1))) my_free(void *);
+
+void f1() {
+ void *p = malloc(12);
+ return;
+ // CHECK: warning: Potential leak of memory pointed to by 'p' [clang-analyzer-unix.Malloc]
+}
+
+void af2() {
+ void *p = my_malloc(12);
+ my_free(p);
+ free(p);
+ // CHECK: warning: Attempt to free released memory [clang-analyzer-unix.Malloc]
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/static-analyzer.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/static-analyzer.cpp
new file mode 100644
index 0000000..b0015aa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/static-analyzer.cpp
@@ -0,0 +1,17 @@
+// RUN: clang-tidy %s -checks='-*,clang-analyzer-*' -- | FileCheck %s
+extern void *malloc(unsigned long);
+extern void free(void *);
+
+void f() {
+ int *p = new int(42);
+ delete p;
+ delete p;
+ // CHECK: warning: Attempt to free released memory [clang-analyzer-cplusplus.NewDelete]
+}
+
+void g() {
+ void *q = malloc(132);
+ free(q);
+ free(q);
+ // CHECK: warning: Attempt to free released memory [clang-analyzer-unix.Malloc]
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/temporaries.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/temporaries.cpp
new file mode 100644
index 0000000..3df4c60
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/temporaries.cpp
@@ -0,0 +1,24 @@
+// RUN: clang-tidy -checks='-*,clang-analyzer-core.NullDereference' %s -- | FileCheck %s
+
+struct NoReturnDtor {
+ ~NoReturnDtor() __attribute__((noreturn));
+};
+
+extern bool check(const NoReturnDtor &);
+
+// CHECK-NOT: warning
+void testNullPointerDereferencePositive() {
+ int *value = 0;
+ // CHECK: [[@LINE+1]]:10: warning: Dereference of null pointer (loaded from variable 'value') [clang-analyzer-core.NullDereference]
+ *value = 1;
+}
+
+// CHECK-NOT: warning
+void testNullPointerDereference() {
+ int *value = 0;
+ if (check(NoReturnDtor())) {
+ // This unreachable code causes a warning if analysis of temporary
+ // destructors is not enabled.
+ *value = 1;
+ }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/validate-check-names.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/validate-check-names.cpp
new file mode 100644
index 0000000..35bfb09
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/validate-check-names.cpp
@@ -0,0 +1,2 @@
+// Check names may only contain alphanumeric characters, '-', '_', and '.'.
+// RUN: clang-tidy -checks=* -list-checks | grep '^ ' | cut -b5- | not grep -v '^[a-zA-Z0-9_.\-]\+$'
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/vfsoverlay.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/vfsoverlay.cpp
new file mode 100644
index 0000000..5704b71
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/vfsoverlay.cpp
@@ -0,0 +1,8 @@
+// RUN: sed -e "s:INPUT_DIR:%S/Inputs/vfsoverlay:g" -e "s:OUT_DIR:%t:g" %S/Inputs/vfsoverlay/vfsoverlay.yaml > %t.yaml
+// RUN: clang-tidy %s -checks='-*,modernize-use-nullptr' -vfsoverlay %t.yaml -- -I %t | FileCheck %s
+// REQUIRES: shell
+
+#include "not_real.h"
+
+X *ptr = 0;
+// CHECK: warning: use nullptr [modernize-use-nullptr]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/warnings-as-errors-diagnostics.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/warnings-as-errors-diagnostics.cpp
new file mode 100644
index 0000000..9f90b62
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/warnings-as-errors-diagnostics.cpp
@@ -0,0 +1,18 @@
+// RUN: clang-tidy %s -checks='-*,llvm-namespace-comment,clang-diagnostic*' \
+// RUN: -- -Wunused-variable 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-WARN -implicit-check-not='{{warning|error}}:'
+// RUN: not clang-tidy %s -checks='-*,llvm-namespace-comment,clang-diagnostic*' \
+// RUN: -warnings-as-errors='clang-diagnostic*' -- -Wunused-variable 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-WERR -implicit-check-not='{{warning|error}}:'
+// RUN: not clang-tidy %s -checks='-*,llvm-namespace-comment,clang-diagnostic*' \
+// RUN: -warnings-as-errors='clang-diagnostic*' -quiet -- -Wunused-variable 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-WERR-QUIET -implicit-check-not='{{warning|error}}:'
+
+void f() { int i; }
+// CHECK-WARN: warning: unused variable 'i' [clang-diagnostic-unused-variable]
+// CHECK-WERR: error: unused variable 'i' [clang-diagnostic-unused-variable,-warnings-as-errors]
+// CHECK-WERR-QUIET: error: unused variable 'i' [clang-diagnostic-unused-variable,-warnings-as-errors]
+
+// CHECK-WARN-NOT: treated as
+// CHECK-WERR: 1 warning treated as error
+// CHECK-WERR-QUIET-NOT: treated as
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/warnings-as-errors-plural.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/warnings-as-errors-plural.cpp
new file mode 100644
index 0000000..a14759d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/warnings-as-errors-plural.cpp
@@ -0,0 +1,24 @@
+// RUN: clang-tidy %s -checks='-*,llvm-namespace-comment,clang-diagnostic*' -- 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-WARN -implicit-check-not='{{warning|error}}:'
+// RUN: not clang-tidy %s -checks='-*,llvm-namespace-comment,clang-diagnostic*' \
+// RUN: -warnings-as-errors='llvm-namespace-comment' -- 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-WERR -implicit-check-not='{{warning|error}}:'
+// RUN: not clang-tidy %s -checks='-*,llvm-namespace-comment,clang-diagnostic*' \
+// RUN: -warnings-as-errors='llvm-namespace-comment' -quiet -- 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-WERR-QUIET -implicit-check-not='{{warning|error}}:'
+
+namespace j {
+}
+// CHECK-WARN: warning: namespace 'j' not terminated with a closing comment [llvm-namespace-comment]
+// CHECK-WERR: error: namespace 'j' not terminated with a closing comment [llvm-namespace-comment,-warnings-as-errors]
+// CHECK-WERR-QUIET: error: namespace 'j' not terminated with a closing comment [llvm-namespace-comment,-warnings-as-errors]
+
+namespace k {
+}
+// CHECK-WARN: warning: namespace 'k' not terminated with a closing comment [llvm-namespace-comment]
+// CHECK-WERR: error: namespace 'k' not terminated with a closing comment [llvm-namespace-comment,-warnings-as-errors]
+// CHECK-WERR-QUIET: error: namespace 'k' not terminated with a closing comment [llvm-namespace-comment,-warnings-as-errors]
+
+// CHECK-WARN-NOT: treated as
+// CHECK-WERR: 2 warnings treated as errors
+// CHECK-WERR-QUIET-NOT: treated as
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/warnings-as-errors.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/warnings-as-errors.cpp
new file mode 100644
index 0000000..44afb83
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/warnings-as-errors.cpp
@@ -0,0 +1,13 @@
+// RUN: clang-tidy %s -checks='-*,llvm-namespace-comment' -- 2>&1 | FileCheck %s --check-prefix=CHECK-WARN -implicit-check-not='{{warning|error}}:'
+// RUN: not clang-tidy %s -checks='-*,llvm-namespace-comment' -warnings-as-errors='llvm-namespace-comment' -- 2>&1 | FileCheck %s --check-prefix=CHECK-WERR -implicit-check-not='{{warning|error}}:'
+// RUN: not clang-tidy %s -checks='-*,llvm-namespace-comment' -warnings-as-errors='llvm-namespace-comment' -quiet -- 2>&1 | FileCheck %s --check-prefix=CHECK-WERR-QUIET -implicit-check-not='{{warning|error}}:'
+
+namespace i {
+}
+// CHECK-WARN: warning: namespace 'i' not terminated with a closing comment [llvm-namespace-comment]
+// CHECK-WERR: error: namespace 'i' not terminated with a closing comment [llvm-namespace-comment,-warnings-as-errors]
+// CHECK-WERR-QUIET: error: namespace 'i' not terminated with a closing comment [llvm-namespace-comment,-warnings-as-errors]
+
+// CHECK-WARN-NOT: treated as
+// CHECK-WERR: 1 warning treated as error
+// CHECK-WERR-QUIET-NOT: treated as
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/zircon-temporary-objects.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/zircon-temporary-objects.cpp
new file mode 100644
index 0000000..b29b482
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/zircon-temporary-objects.cpp
@@ -0,0 +1,109 @@
+// RUN: %check_clang_tidy %s zircon-temporary-objects %t -- \
+// RUN: -config="{CheckOptions: [{key: zircon-temporary-objects.Names, value: 'Foo;NS::Bar'}]}" \
+// RUN: -header-filter=.* \
+// RUN: -- -std=c++11
+
+// Should flag instances of Foo, NS::Bar.
+
+class Foo {
+public:
+ Foo() = default;
+ Foo(int Val) : Val(Val){};
+
+private:
+ int Val;
+};
+
+namespace NS {
+
+class Bar {
+public:
+ Bar() = default;
+ Bar(int Val) : Val(Val){};
+
+private:
+ int Val;
+};
+
+} // namespace NS
+
+class Bar {
+public:
+ Bar() = default;
+ Bar(int Val) : Val(Val){};
+
+private:
+ int Val;
+};
+
+int func(Foo F) { return 1; };
+
+int main() {
+ Foo F;
+ Foo *F2 = new Foo();
+ new Foo();
+ Foo();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: creating a temporary object of type 'Foo' is prohibited
+ Foo F3 = Foo();
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: creating a temporary object of type 'Foo' is prohibited
+
+ Bar();
+ NS::Bar();
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: creating a temporary object of type 'NS::Bar' is prohibited
+
+ int A = func(Foo());
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: creating a temporary object of type 'Foo' is prohibited
+
+ Foo F4(0);
+ Foo *F5 = new Foo(0);
+ new Foo(0);
+ Foo(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: creating a temporary object of type 'Foo' is prohibited
+ Foo F6 = Foo(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: creating a temporary object of type 'Foo' is prohibited
+
+ Bar(0);
+ NS::Bar(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: creating a temporary object of type 'NS::Bar' is prohibited
+
+ int B = func(Foo(0));
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: creating a temporary object of type 'Foo' is prohibited
+}
+
+namespace NS {
+
+void f() {
+ Bar();
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: creating a temporary object of type 'NS::Bar' is prohibited
+ Bar(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: creating a temporary object of type 'NS::Bar' is prohibited
+}
+
+} // namespace NS
+
+template <typename Ty>
+Ty make_ty() { return Ty(); }
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: creating a temporary object of type 'Foo' is prohibited
+// CHECK-MESSAGES: :[[@LINE-2]]:23: warning: creating a temporary object of type 'NS::Bar' is prohibited
+
+void ty_func() {
+ make_ty<Bar>();
+ make_ty<NS::Bar>();
+ make_ty<Foo>();
+}
+
+// Inheriting the disallowed class does not trigger the check.
+
+class Bingo : NS::Bar {}; // Not explicitly disallowed
+
+void f2() {
+ Bingo();
+}
+
+template <typename Ty>
+class Quux : Ty {};
+
+void f3() {
+ Quux<NS::Bar>();
+ Quux<Bar>();
+}