diff options
Diffstat (limited to 'test/clang-tidy')
55 files changed, 2050 insertions, 63 deletions
diff --git a/test/clang-tidy/Inputs/Headers/stdio.h b/test/clang-tidy/Inputs/Headers/stdio.h new file mode 100644 index 00000000..eebe9fd9 --- /dev/null +++ b/test/clang-tidy/Inputs/Headers/stdio.h @@ -0,0 +1,18 @@ +//===--- stdio.h - Stub header for tests ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _STDIO_H_ +#define _STDIO_H_ + +// A header intended to contain C standard input and output library +// declarations. + +int printf(const char *, ...); + +#endif // _STDIO_H_ + diff --git a/test/clang-tidy/Inputs/absl/time/time.h b/test/clang-tidy/Inputs/absl/time/time.h index 9d136a5d..5454f978 100644 --- a/test/clang-tidy/Inputs/absl/time/time.h +++ b/test/clang-tidy/Inputs/absl/time/time.h @@ -14,11 +14,14 @@ public: Duration &operator/=(float r); Duration &operator/=(double r); template <typename T> Duration &operator/=(T r); + + Duration &operator+(Duration d); }; template <typename T> Duration operator*(Duration lhs, T rhs); template <typename T> Duration operator*(T lhs, Duration rhs); template <typename T> Duration operator/(Duration lhs, T rhs); +int64_t operator/(Duration lhs, Duration rhs); class Time{}; @@ -55,6 +58,21 @@ int64_t ToInt64Milliseconds(Duration d); int64_t ToInt64Microseconds(Duration d); int64_t ToInt64Nanoseconds(Duration d); +int64_t ToUnixHours(Time t); +int64_t ToUnixMinutes(Time t); +int64_t ToUnixSeconds(Time t); +int64_t ToUnixMillis(Time t); +int64_t ToUnixMicros(Time t); +int64_t ToUnixNanos(Time t); +Time FromUnixHours(int64_t); +Time FromUnixMinutes(int64_t); +Time FromUnixSeconds(int64_t); +Time FromUnixMillis(int64_t); +Time FromUnixMicros(int64_t); +Time FromUnixNanos(int64_t); + +Time Now(); + // Relational Operators constexpr bool operator<(Duration lhs, Duration rhs); constexpr bool operator>(Duration lhs, Duration rhs); @@ -69,4 +87,6 @@ inline Time operator+(Duration lhs, Time rhs); inline Time operator-(Time lhs, Duration rhs); inline Duration operator-(Time lhs, Time rhs); +double FDivDuration(Duration num, Duration den); + } // namespace absl diff --git a/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/a.h b/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/a.h new file mode 100644 index 00000000..6651b4fa --- /dev/null +++ b/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/a.h @@ -0,0 +1 @@ +#define a diff --git a/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/b.h b/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/b.h new file mode 100644 index 00000000..446eda1a --- /dev/null +++ b/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/b.h @@ -0,0 +1,2 @@ +#include "a.h" +#define b diff --git a/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/c.h b/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/c.h new file mode 100644 index 00000000..0d4c60df --- /dev/null +++ b/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/c.h @@ -0,0 +1,2 @@ +#include "b.h" +#define c diff --git a/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/module.modulemap b/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/module.modulemap new file mode 100644 index 00000000..d04240af --- /dev/null +++ b/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/module.modulemap @@ -0,0 +1,3 @@ +module a { header "a.h" export * } +module b { header "b.h" export * use a } +module c { header "c.h" export * use b } diff --git a/test/clang-tidy/abseil-duration-addition.cpp b/test/clang-tidy/abseil-duration-addition.cpp new file mode 100644 index 00000000..33cfc58f --- /dev/null +++ b/test/clang-tidy/abseil-duration-addition.cpp @@ -0,0 +1,98 @@ +// RUN: %check_clang_tidy %s abseil-duration-addition %t -- -- -I%S/Inputs + +#include "absl/time/time.h" + +void f() { + absl::Time t; + int i; + + i = absl::ToUnixHours(t) + 5; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition] + // CHECK-FIXES: absl::ToUnixHours(t + absl::Hours(5)) + i = absl::ToUnixMinutes(t) + 5; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition] + // CHECK-FIXES: absl::ToUnixMinutes(t + absl::Minutes(5)) + i = absl::ToUnixSeconds(t) + 5; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition] + // CHECK-FIXES: absl::ToUnixSeconds(t + absl::Seconds(5)) + i = absl::ToUnixMillis(t) + 5; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition] + // CHECK-FIXES: absl::ToUnixMillis(t + absl::Milliseconds(5)) + i = absl::ToUnixMicros(t) + 5; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition] + // CHECK-FIXES: absl::ToUnixMicros(t + absl::Microseconds(5)) + i = absl::ToUnixNanos(t) + 5; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition] + // CHECK-FIXES: absl::ToUnixNanos(t + absl::Nanoseconds(5)) + + i = 3 + absl::ToUnixHours(t); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition] + // CHECK-FIXES: absl::ToUnixHours(absl::Hours(3) + t) + i = 3 + absl::ToUnixMinutes(t); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition] + // CHECK-FIXES: absl::ToUnixMinutes(absl::Minutes(3) + t) + i = 3 + absl::ToUnixSeconds(t); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition] + // CHECK-FIXES: absl::ToUnixSeconds(absl::Seconds(3) + t) + i = 3 + absl::ToUnixMillis(t); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition] + // CHECK-FIXES: absl::ToUnixMillis(absl::Milliseconds(3) + t) + i = 3 + absl::ToUnixMicros(t); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition] + // CHECK-FIXES: absl::ToUnixMicros(absl::Microseconds(3) + t) + i = 3 + absl::ToUnixNanos(t); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition] + // CHECK-FIXES: absl::ToUnixNanos(absl::Nanoseconds(3) + t) + + // Undoing inverse conversions + i = absl::ToUnixMicros(t) + absl::ToInt64Microseconds(absl::Seconds(1)); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition] + // CHECK-FIXES: absl::ToUnixMicros(t + absl::Seconds(1)) + + // Parens + i = 3 + (absl::ToUnixHours(t)); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition] + // CHECK-FIXES: absl::ToUnixHours(absl::Hours(3) + t) + + // Float folding + i = absl::ToUnixSeconds(t) + 5.0; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition] + // CHECK-FIXES: absl::ToUnixSeconds(t + absl::Seconds(5)) + + // We can rewrite the argument of the duration conversion +#define THIRTY absl::FromUnixSeconds(30) + i = absl::ToUnixSeconds(THIRTY) + 1; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition] + // CHECK-FIXES: absl::ToUnixSeconds(THIRTY + absl::Seconds(1)) +#undef THIRTY + + // Some other contexts + if (absl::ToUnixSeconds(t) + 1.0 > 10) {} + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition] + // CHECK-FIXES: absl::ToUnixSeconds(t + absl::Seconds(1)) + + // These should not match + i = 5 + 6; + i = absl::ToUnixSeconds(t) - 1.0; + i = absl::ToUnixSeconds(t) * 1.0; + i = absl::ToUnixSeconds(t) / 1.0; + i += absl::ToInt64Microseconds(absl::Seconds(1)); + +#define PLUS_FIVE(z) absl::ToUnixSeconds(z) + 5 + i = PLUS_FIVE(t); +#undef PLUS_FIVE +} + +// Within a templated function +template<typename T> +void foo(absl::Time t) { + int i = absl::ToUnixNanos(t) + T{}; + // CHECK-MESSAGES: [[@LINE-1]]:11: warning: perform addition in the duration domain [abseil-duration-addition] + // CHECK-FIXES: absl::ToUnixNanos(t + absl::Nanoseconds(T{})) +} + +void g() { + absl::Time t; + foo<int>(t); + foo<double>(t); +} diff --git a/test/clang-tidy/abseil-duration-conversion-cast.cpp b/test/clang-tidy/abseil-duration-conversion-cast.cpp new file mode 100644 index 00000000..260aa327 --- /dev/null +++ b/test/clang-tidy/abseil-duration-conversion-cast.cpp @@ -0,0 +1,95 @@ +// RUN: %check_clang_tidy %s abseil-duration-conversion-cast %t -- -- -I%S/Inputs + +#include "absl/time/time.h" + +void f() { + absl::Duration d1; + double x; + int i; + + i = static_cast<int>(absl::ToDoubleHours(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: absl::ToInt64Hours(d1); + x = static_cast<float>(absl::ToInt64Hours(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: absl::ToDoubleHours(d1); + i = static_cast<int>(absl::ToDoubleMinutes(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: absl::ToInt64Minutes(d1); + x = static_cast<float>(absl::ToInt64Minutes(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: absl::ToDoubleMinutes(d1); + i = static_cast<int>(absl::ToDoubleSeconds(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: absl::ToInt64Seconds(d1); + x = static_cast<float>(absl::ToInt64Seconds(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: absl::ToDoubleSeconds(d1); + i = static_cast<int>(absl::ToDoubleMilliseconds(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: absl::ToInt64Milliseconds(d1); + x = static_cast<float>(absl::ToInt64Milliseconds(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: absl::ToDoubleMilliseconds(d1); + i = static_cast<int>(absl::ToDoubleMicroseconds(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: absl::ToInt64Microseconds(d1); + x = static_cast<float>(absl::ToInt64Microseconds(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: absl::ToDoubleMicroseconds(d1); + i = static_cast<int>(absl::ToDoubleNanoseconds(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: absl::ToInt64Nanoseconds(d1); + x = static_cast<float>(absl::ToInt64Nanoseconds(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: absl::ToDoubleNanoseconds(d1); + + // Functional-style casts + i = int(absl::ToDoubleHours(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: absl::ToInt64Hours(d1); + x = float(absl::ToInt64Microseconds(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: absl::ToDoubleMicroseconds(d1); + + // C-style casts + i = (int) absl::ToDoubleHours(d1); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: absl::ToInt64Hours(d1); + x = (float) absl::ToInt64Microseconds(d1); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: absl::ToDoubleMicroseconds(d1); + + // Type aliasing + typedef int FancyInt; + typedef float FancyFloat; + + FancyInt j = static_cast<FancyInt>(absl::ToDoubleHours(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: absl::ToInt64Hours(d1); + FancyFloat k = static_cast<FancyFloat>(absl::ToInt64Microseconds(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:18: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: absl::ToDoubleMicroseconds(d1); + + // Macro handling + // We want to transform things in macro arguments +#define EXTERNAL(x) (x) + 5 + i = EXTERNAL(static_cast<int>(absl::ToDoubleSeconds(d1))); + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast] + // CHECK-FIXES: EXTERNAL(absl::ToInt64Seconds(d1)); +#undef EXTERNAL + + // We don't want to transform this which get split across macro boundaries +#define SPLIT(x) static_cast<int>((x)) + 5 + i = SPLIT(absl::ToDoubleSeconds(d1)); +#undef SPLIT + + // We also don't want to transform things inside of a macro definition +#define INTERNAL(x) static_cast<int>(absl::ToDoubleSeconds((x))) + 5 + i = INTERNAL(d1); +#undef INTERNAL + + // These shouldn't be converted + i = static_cast<int>(absl::ToInt64Seconds(d1)); + i = static_cast<float>(absl::ToDoubleSeconds(d1)); +} diff --git a/test/clang-tidy/abseil-duration-unnecessary-conversion.cpp b/test/clang-tidy/abseil-duration-unnecessary-conversion.cpp new file mode 100644 index 00000000..d32837f8 --- /dev/null +++ b/test/clang-tidy/abseil-duration-unnecessary-conversion.cpp @@ -0,0 +1,111 @@ +// RUN: %check_clang_tidy %s abseil-duration-unnecessary-conversion %t -- -- -I%S/Inputs + +#include "absl/time/time.h" + +void f() { + absl::Duration d1, d2; + + // Floating point + d2 = absl::Hours(absl::ToDoubleHours(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Minutes(absl::ToDoubleMinutes(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Seconds(absl::ToDoubleSeconds(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Milliseconds(absl::ToDoubleMilliseconds(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Microseconds(absl::ToDoubleMicroseconds(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Nanoseconds(absl::ToDoubleNanoseconds(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + + // Integer point + d2 = absl::Hours(absl::ToInt64Hours(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Minutes(absl::ToInt64Minutes(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Seconds(absl::ToInt64Seconds(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Milliseconds(absl::ToInt64Milliseconds(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Microseconds(absl::ToInt64Microseconds(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Nanoseconds(absl::ToInt64Nanoseconds(d1)); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + + d2 = absl::Hours(d1 / absl::Hours(1)); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Minutes(d1 / absl::Minutes(1)); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Seconds(d1 / absl::Seconds(1)); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Milliseconds(d1 / absl::Milliseconds(1)); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Microseconds(d1 / absl::Microseconds(1)); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Nanoseconds(d1 / absl::Nanoseconds(1)); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + + d2 = absl::Hours(absl::FDivDuration(d1, absl::Hours(1))); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Minutes(absl::FDivDuration(d1, absl::Minutes(1))); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Seconds(absl::FDivDuration(d1, absl::Seconds(1))); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Milliseconds(absl::FDivDuration(d1, absl::Milliseconds(1))); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Microseconds(absl::FDivDuration(d1, absl::Microseconds(1))); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + d2 = absl::Nanoseconds(absl::FDivDuration(d1, absl::Nanoseconds(1))); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: d2 = d1 + + // As macro argument +#define PLUS_FIVE_S(x) x + absl::Seconds(5) + d2 = PLUS_FIVE_S(absl::Seconds(absl::ToInt64Seconds(d1))); + // CHECK-MESSAGES: [[@LINE-1]]:20: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion] + // CHECK-FIXES: PLUS_FIVE_S(d1) +#undef PLUS_FIVE_S + + // Split by macro: should not change +#define TOSECONDS(x) absl::Seconds(x) + d2 = TOSECONDS(absl::ToInt64Seconds(d1)); +#undef TOSECONDS + + // Don't change something inside a macro definition +#define VALUE(x) absl::Hours(absl::ToInt64Hours(x)); + d2 = VALUE(d1); +#undef VALUE + + // These should not match + d2 = absl::Seconds(absl::ToDoubleMilliseconds(d1)); + d2 = absl::Seconds(4); + int i = absl::ToInt64Milliseconds(d1); + d2 = absl::Hours(d1 / absl::Minutes(1)); + d2 = absl::Seconds(d1 / absl::Seconds(30)); + d2 = absl::Hours(absl::FDivDuration(d1, absl::Minutes(1))); + d2 = absl::Milliseconds(absl::FDivDuration(d1, absl::Milliseconds(20))); +} diff --git a/test/clang-tidy/abseil-time-comparison.cpp b/test/clang-tidy/abseil-time-comparison.cpp new file mode 100644 index 00000000..ab03020c --- /dev/null +++ b/test/clang-tidy/abseil-time-comparison.cpp @@ -0,0 +1,129 @@ +// RUN: %check_clang_tidy %s abseil-time-comparison %t -- -- -I%S/Inputs + +#include "absl/time/time.h" + +void f() { + double x; + absl::Duration d1, d2; + bool b; + absl::Time t1, t2; + + // Check against the RHS + b = x > absl::ToUnixSeconds(t1); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: absl::FromUnixSeconds(x) > t1; + b = x >= absl::ToUnixSeconds(t1); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: absl::FromUnixSeconds(x) >= t1; + b = x == absl::ToUnixSeconds(t1); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: absl::FromUnixSeconds(x) == t1; + b = x <= absl::ToUnixSeconds(t1); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: absl::FromUnixSeconds(x) <= t1; + b = x < absl::ToUnixSeconds(t1); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: absl::FromUnixSeconds(x) < t1; + b = x == absl::ToUnixSeconds(t1 - d2); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: absl::FromUnixSeconds(x) == t1 - d2; + b = absl::ToUnixSeconds(t1) > absl::ToUnixSeconds(t2); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: t1 > t2; + + // Check against the LHS + b = absl::ToUnixSeconds(t1) < x; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: t1 < absl::FromUnixSeconds(x); + b = absl::ToUnixSeconds(t1) <= x; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: t1 <= absl::FromUnixSeconds(x); + b = absl::ToUnixSeconds(t1) == x; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: t1 == absl::FromUnixSeconds(x); + b = absl::ToUnixSeconds(t1) >= x; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: t1 >= absl::FromUnixSeconds(x); + b = absl::ToUnixSeconds(t1) > x; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: t1 > absl::FromUnixSeconds(x); + + // Comparison against zero + b = absl::ToUnixSeconds(t1) < 0.0; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: t1 < absl::UnixEpoch(); + b = absl::ToUnixSeconds(t1) < 0; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: t1 < absl::UnixEpoch(); + + // Scales other than Seconds + b = x > absl::ToUnixMicros(t1); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: absl::FromUnixMicros(x) > t1; + b = x >= absl::ToUnixMillis(t1); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: absl::FromUnixMillis(x) >= t1; + b = x == absl::ToUnixNanos(t1); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: absl::FromUnixNanos(x) == t1; + b = x <= absl::ToUnixMinutes(t1); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: absl::FromUnixMinutes(x) <= t1; + b = x < absl::ToUnixHours(t1); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: absl::FromUnixHours(x) < t1; + + // A long expression + bool some_condition; + int very_very_very_very_long_variable_name; + absl::Time SomeTime; + if (some_condition && very_very_very_very_long_variable_name + < absl::ToUnixSeconds(SomeTime)) { + // CHECK-MESSAGES: [[@LINE-2]]:25: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: if (some_condition && absl::FromUnixSeconds(very_very_very_very_long_variable_name) < SomeTime) { + return; + } + + // A complex expression + int y; + b = (y + 5) * 10 > absl::ToUnixMillis(t1); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: absl::FromUnixMillis((y + 5) * 10) > t1; + + // We should still transform the expression inside this macro invocation +#define VALUE_IF(v, e) v ? (e) : 0 + int a = VALUE_IF(1, 5 > absl::ToUnixSeconds(t1)); + // CHECK-MESSAGES: [[@LINE-1]]:23: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: VALUE_IF(1, absl::FromUnixSeconds(5) > t1); +#undef VALUE_IF + +#define VALUE_IF_2(e) (e) +#define VALUE_IF(v, e) v ? VALUE_IF_2(e) : VALUE_IF_2(0) + int a2 = VALUE_IF(1, 5 > absl::ToUnixSeconds(t1)); + // CHECK-MESSAGES: [[@LINE-1]]:24: warning: perform comparison in the time domain [abseil-time-comparison] + // CHECK-FIXES: VALUE_IF(1, absl::FromUnixSeconds(5) > t1); +#undef VALUE_IF +#undef VALUE_IF_2 + +#define VALUE_IF_2(e) (e) +#define VALUE_IF(v, e, type) (v ? VALUE_IF_2(absl::To##type##Seconds(e)) : 0) + int a3 = VALUE_IF(1, t1, Unix); +#undef VALUE_IF +#undef VALUE_IF_2 + +#define VALUE_IF_2(e) (e) +#define VALUE_IF(v, e, type) (v ? (5 > VALUE_IF_2(absl::To##type##Seconds(e))) : 0) + int a4 = VALUE_IF(1, t1, Unix); +#undef VALUE_IF +#undef VALUE_IF_2 + + // These should not match + b = 6 < 4; + +#define TODOUBLE(x) absl::ToUnixSeconds(x) + b = 5.0 > TODOUBLE(t1); +#undef TODOUBLE +#define THIRTY 30.0 + b = THIRTY > absl::ToUnixSeconds(t1); +#undef THIRTY +} diff --git a/test/clang-tidy/abseil-time-subtraction.cpp b/test/clang-tidy/abseil-time-subtraction.cpp new file mode 100644 index 00000000..6f5d4b45 --- /dev/null +++ b/test/clang-tidy/abseil-time-subtraction.cpp @@ -0,0 +1,117 @@ +// RUN: %check_clang_tidy %s abseil-time-subtraction %t -- -- -I%S/Inputs + +#include "absl/time/time.h" + +void g(absl::Duration d); + +void f() { + absl::Time t; + int x, y; + absl::Duration d; + + d = absl::Hours(absl::ToUnixHours(t) - x); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: d = (t - absl::FromUnixHours(x)); + d = absl::Minutes(absl::ToUnixMinutes(t) - x); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: d = (t - absl::FromUnixMinutes(x)); + d = absl::Seconds(absl::ToUnixSeconds(t) - x); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: d = (t - absl::FromUnixSeconds(x)); + d = absl::Milliseconds(absl::ToUnixMillis(t) - x); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: d = (t - absl::FromUnixMillis(x)); + d = absl::Microseconds(absl::ToUnixMicros(t) - x); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: d = (t - absl::FromUnixMicros(x)); + d = absl::Nanoseconds(absl::ToUnixNanos(t) - x); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: d = (t - absl::FromUnixNanos(x)); + + y = x - absl::ToUnixHours(t); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: y = absl::ToInt64Hours(absl::FromUnixHours(x) - t); + y = x - absl::ToUnixMinutes(t); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: y = absl::ToInt64Minutes(absl::FromUnixMinutes(x) - t); + y = x - absl::ToUnixSeconds(t); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: y = absl::ToInt64Seconds(absl::FromUnixSeconds(x) - t); + y = x - absl::ToUnixMillis(t); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: y = absl::ToInt64Milliseconds(absl::FromUnixMillis(x) - t); + y = x - absl::ToUnixMicros(t); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: y = absl::ToInt64Microseconds(absl::FromUnixMicros(x) - t); + y = x - absl::ToUnixNanos(t); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: y = absl::ToInt64Nanoseconds(absl::FromUnixNanos(x) - t); + + // Check parenthesis placement + d = 5 * absl::Seconds(absl::ToUnixSeconds(t) - x); + // CHECK-MESSAGES: [[@LINE-1]]:11: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: d = 5 * (t - absl::FromUnixSeconds(x)); + d = absl::Seconds(absl::ToUnixSeconds(t) - x) / 5; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: d = (t - absl::FromUnixSeconds(x)) / 5; + + // No extra parens around arguments + g(absl::Seconds(absl::ToUnixSeconds(t) - x)); + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: g(t - absl::FromUnixSeconds(x)); + g(absl::Seconds(x - absl::ToUnixSeconds(t))); + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: g(absl::FromUnixSeconds(x) - t); + + // More complex subexpressions + d = absl::Hours(absl::ToUnixHours(t) - 5 * x); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: d = (t - absl::FromUnixHours(5 * x)); + + // These should not trigger; they are likely bugs + d = absl::Milliseconds(absl::ToUnixSeconds(t) - x); + d = absl::Seconds(absl::ToUnixMicros(t) - x); + + // Various macro scenarios +#define SUB(z, t1) z - absl::ToUnixSeconds(t1) + y = SUB(x, t); +#undef SUB + +#define MILLIS(t1) absl::ToUnixMillis(t1) + y = x - MILLIS(t); +#undef MILLIS + +#define HOURS(z) absl::Hours(z) + d = HOURS(absl::ToUnixHours(t) - x); +#undef HOURS + + // This should match the expression inside the macro invocation. +#define SECONDS(z) absl::Seconds(z) + d = SECONDS(x - absl::ToUnixSeconds(t)); + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: SECONDS(absl::ToInt64Seconds(absl::FromUnixSeconds(x) - t)) +#undef SECONDS +} + +template<typename T> +void func(absl::Time t, T x) { + absl::Duration d = absl::Seconds(absl::ToUnixSeconds(t) - x); + // CHECK-MESSAGES: [[@LINE-1]]:22: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: absl::Duration d = t - absl::FromUnixSeconds(x); +} + +void g() { + func(absl::Now(), 5); +} + +absl::Duration parens_in_return() { + absl::Time t; + int x; + + return absl::Seconds(absl::ToUnixSeconds(t) - x); + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: return t - absl::FromUnixSeconds(x); + return absl::Seconds(x - absl::ToUnixSeconds(t)); + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: perform subtraction in the time domain [abseil-time-subtraction] + // CHECK-FIXES: return absl::FromUnixSeconds(x) - t; +} diff --git a/test/clang-tidy/abseil-upgrade-duration-conversions.cpp b/test/clang-tidy/abseil-upgrade-duration-conversions.cpp index 7d8ad43e..fed0f8bd 100644 --- a/test/clang-tidy/abseil-upgrade-duration-conversions.cpp +++ b/test/clang-tidy/abseil-upgrade-duration-conversions.cpp @@ -430,3 +430,36 @@ void factoryInMacros() { factoryTemplateAndMacro<ConvertibleTo<int>>(); TemplateFactoryInMacro(ConvertibleTo<int>()); } + +// This is a reduced test-case for PR39949 and manifested in this check. +namespace std { +template <typename _Tp> +_Tp declval(); + +template <typename _Functor, typename... _ArgTypes> +struct __res { + template <typename... _Args> + static decltype(declval<_Functor>()(_Args()...)) _S_test(int); + + template <typename...> + static void _S_test(...); + + typedef decltype(_S_test<_ArgTypes...>(0)) type; +}; + +template <typename> +struct function; + +template <typename... _ArgTypes> +struct function<void(_ArgTypes...)> { + template <typename _Functor, + typename = typename __res<_Functor, _ArgTypes...>::type> + function(_Functor) {} +}; +} // namespace std + +typedef std::function<void(void)> F; + +F foo() { + return F([] {}); +} diff --git a/test/clang-tidy/alternative-fixes.cpp b/test/clang-tidy/alternative-fixes.cpp new file mode 100644 index 00000000..d5cee68d --- /dev/null +++ b/test/clang-tidy/alternative-fixes.cpp @@ -0,0 +1,9 @@ +// RUN: %check_clang_tidy %s "llvm-namespace-comment,clang-diagnostic-*" %t +void foo(int a) { + if (a = 1) { + // CHECK-NOTES: [[@LINE-1]]:9: warning: using the result of an assignment as a condition without parentheses [clang-diagnostic-parentheses] + // CHECK-NOTES: [[@LINE-2]]:9: note: place parentheses around the assignment to silence this warning + // CHECK-NOTES: [[@LINE-3]]:9: note: use '==' to turn this assignment into an equality comparison + // CHECK-FIXES: if ((a = 1)) { + } +} diff --git a/test/clang-tidy/bugprone-argument-comment-literals.cpp b/test/clang-tidy/bugprone-argument-comment-literals.cpp new file mode 100644 index 00000000..739c9a59 --- /dev/null +++ b/test/clang-tidy/bugprone-argument-comment-literals.cpp @@ -0,0 +1,124 @@ +// RUN: %check_clang_tidy %s bugprone-argument-comment %t -- \ +// RUN: -config="{CheckOptions: [{key: CommentBoolLiterals, value: 1},{key: CommentIntegerLiterals, value: 1}, {key: CommentFloatLiterals, value: 1}, {key: CommentUserDefinedLiterals, value: 1}, {key: CommentStringLiterals, value: 1}, {key: CommentNullPtrs, value: 1}, {key: CommentCharacterLiterals, value: 1}]}" -- + +struct A { + void foo(bool abc); + void foo(bool abc, bool cde); + void foo(const char *, bool abc); + void foo(int iabc); + void foo(float fabc); + void foo(double dabc); + void foo(const char *strabc); + void fooW(const wchar_t *wstrabc); + void fooPtr(A *ptrabc); + void foo(char chabc); +}; + +#define FOO 1 + +void g(int a); +void h(double b); +void i(const char *c); + +double operator"" _km(long double); + +void test() { + A a; + + a.foo(true); + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'abc' [bugprone-argument-comment] + // CHECK-FIXES: a.foo(/*abc=*/true); + + a.foo(false); + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'abc' [bugprone-argument-comment] + // CHECK-FIXES: a.foo(/*abc=*/false); + + a.foo(true, false); + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'abc' [bugprone-argument-comment] + // CHECK-MESSAGES: [[@LINE-2]]:15: warning: argument comment missing for literal argument 'cde' [bugprone-argument-comment] + // CHECK-FIXES: a.foo(/*abc=*/true, /*cde=*/false); + + a.foo(false, true); + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'abc' [bugprone-argument-comment] + // CHECK-MESSAGES: [[@LINE-2]]:16: warning: argument comment missing for literal argument 'cde' [bugprone-argument-comment] + // CHECK-FIXES: a.foo(/*abc=*/false, /*cde=*/true); + + a.foo(/*abc=*/false, true); + // CHECK-MESSAGES: [[@LINE-1]]:24: warning: argument comment missing for literal argument 'cde' [bugprone-argument-comment] + // CHECK-FIXES: a.foo(/*abc=*/false, /*cde=*/true); + + a.foo(false, /*cde=*/true); + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'abc' [bugprone-argument-comment] + // CHECK-FIXES: a.foo(/*abc=*/false, /*cde=*/true); + + bool val1 = true; + bool val2 = false; + a.foo(val1, val2); + + a.foo("", true); + // CHECK-MESSAGES: [[@LINE-1]]:13: warning: argument comment missing for literal argument 'abc' [bugprone-argument-comment] + // CHECK-FIXES: a.foo("", /*abc=*/true); + + a.foo(0); + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'iabc' [bugprone-argument-comment] + // CHECK-FIXES: a.foo(/*iabc=*/0); + + a.foo(1.0f); + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'fabc' [bugprone-argument-comment] + // CHECK-FIXES: a.foo(/*fabc=*/1.0f); + + a.foo(1.0); + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'dabc' [bugprone-argument-comment] + // CHECK-FIXES: a.foo(/*dabc=*/1.0); + + int val3 = 10; + a.foo(val3); + + float val4 = 10.0; + a.foo(val4); + + double val5 = 10.0; + a.foo(val5); + + a.foo("Hello World"); + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'strabc' [bugprone-argument-comment] + // CHECK-FIXES: a.foo(/*strabc=*/"Hello World"); + // + a.fooW(L"Hello World"); + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: argument comment missing for literal argument 'wstrabc' [bugprone-argument-comment] + // CHECK-FIXES: a.fooW(/*wstrabc=*/L"Hello World"); + + a.fooPtr(nullptr); + // CHECK-MESSAGES: [[@LINE-1]]:12: warning: argument comment missing for literal argument 'ptrabc' [bugprone-argument-comment] + // CHECK-FIXES: a.fooPtr(/*ptrabc=*/nullptr); + + a.foo(402.0_km); + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'dabc' [bugprone-argument-comment] + // CHECK-FIXES: a.foo(/*dabc=*/402.0_km); + + a.foo('A'); + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'chabc' [bugprone-argument-comment] + // CHECK-FIXES: a.foo(/*chabc=*/'A'); + + g(FOO); + h(1.0f); + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: argument comment missing for literal argument 'b' [bugprone-argument-comment] + // CHECK-FIXES: h(/*b=*/1.0f); + i(__FILE__); + + // FIXME Would like the below to add argument comments. + g((1)); + // FIXME But we should not add argument comments here. + g(_Generic(0, int : 0)); +} + +void f(bool _with_underscores_); +void ignores_underscores() { + f(false); + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: argument comment missing for literal argument '_with_underscores_' [bugprone-argument-comment] + // CHECK-FIXES: f(/*_with_underscores_=*/false); + + f(true); + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: argument comment missing for literal argument + // CHECK-FIXES: f(/*_with_underscores_=*/true); +} diff --git a/test/clang-tidy/bugprone-exception-escape-openmp.cpp b/test/clang-tidy/bugprone-exception-escape-openmp.cpp new file mode 100644 index 00000000..101c339b --- /dev/null +++ b/test/clang-tidy/bugprone-exception-escape-openmp.cpp @@ -0,0 +1,29 @@ +// RUN: %check_clang_tidy %s bugprone-exception-escape %t -- -extra-arg=-fopenmp=libomp -extra-arg=-fexceptions -- + +int thrower() { + throw 42; +} + +void ok_parallel() { +#pragma omp parallel + thrower(); +} + +void bad_for_header_XFAIL(const int a) noexcept { +#pragma omp for + for (int i = 0; i < thrower(); i++) + ; + // FIXME: this really should be caught by bugprone-exception-escape. + // https://bugs.llvm.org/show_bug.cgi?id=41102 +} + +void ok_forloop(const int a) { +#pragma omp for + for (int i = 0; i < a; i++) + thrower(); +} + +void some_exception_just_so_that_check_clang_tidy_shuts_up() noexcept { + thrower(); +} +// CHECK-MESSAGES: :[[@LINE-3]]:6: warning: an exception may be thrown in function 'some_exception_just_so_that_check_clang_tidy_shuts_up' which should not throw exceptions diff --git a/test/clang-tidy/bugprone-parent-virtual-call.cpp b/test/clang-tidy/bugprone-parent-virtual-call.cpp index ad845886..ad845886 100755..100644 --- a/test/clang-tidy/bugprone-parent-virtual-call.cpp +++ b/test/clang-tidy/bugprone-parent-virtual-call.cpp diff --git a/test/clang-tidy/bugprone-sizeof-expression.cpp b/test/clang-tidy/bugprone-sizeof-expression.cpp index 683ad083..57b73ea4 100644 --- a/test/clang-tidy/bugprone-sizeof-expression.cpp +++ b/test/clang-tidy/bugprone-sizeof-expression.cpp @@ -231,6 +231,35 @@ int Test5() { return sum; } +int Test6() { + int sum = 0; + + struct S A = AsStruct(), B = AsStruct(); + struct S *P = &A, *Q = &B; + sum += sizeof(struct S) == P - Q; + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic + sum += 5 * sizeof(S) != P - Q; + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic + sum += sizeof(S) < P - Q; + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic + sum += 5 * sizeof(S) <= P - Q; + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic + sum += 5 * sizeof(*P) >= P - Q; + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic + sum += Q - P > 3 * sizeof(*P); + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic + sum += sizeof(S) + (P - Q); + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic + sum += 5 * sizeof(S) - (P - Q); + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic + sum += (P - Q) / sizeof(S); + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic + sum += (P - Q) / sizeof(*Q); + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic + + return sum; +} + int ValidExpressions() { int A[] = {1, 2, 3, 4}; static const char str[] = "hello"; diff --git a/test/clang-tidy/bugprone-string-constructor.cpp b/test/clang-tidy/bugprone-string-constructor.cpp index 3ab4f424..9e11a32a 100644 --- a/test/clang-tidy/bugprone-string-constructor.cpp +++ b/test/clang-tidy/bugprone-string-constructor.cpp @@ -65,3 +65,11 @@ void Valid() { std::string s2("test", 3); std::string s3("test"); } + +namespace instantiation_dependent_exprs { +template<typename T> +struct S { + bool x; + std::string f() { return x ? "a" : "b"; } +}; +} diff --git a/test/clang-tidy/bugprone-string-integer-assignment.cpp b/test/clang-tidy/bugprone-string-integer-assignment.cpp index c4e13fc4..18fe5ef4 100644 --- a/test/clang-tidy/bugprone-string-integer-assignment.cpp +++ b/test/clang-tidy/bugprone-string-integer-assignment.cpp @@ -7,18 +7,29 @@ struct basic_string { basic_string& operator=(basic_string); basic_string& operator+=(T); basic_string& operator+=(basic_string); + const T &operator[](int i) const; + T &operator[](int i); }; typedef basic_string<char> string; typedef basic_string<wchar_t> wstring; + +int tolower(int i); +int toupper(int i); } +int tolower(int i); +int toupper(int i); + typedef int MyArcaneChar; +constexpr char kCharConstant = 'a'; + int main() { std::string s; std::wstring ws; int x = 5; + const char c = 'c'; s = 6; // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: an integer is interpreted as a character code when assigning {{.*}} [bugprone-string-integer-assignment] @@ -47,7 +58,52 @@ int main() { std::basic_string<MyArcaneChar> as; as = 6; -// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: an integer is interpreted as a chara -// CHECK-FIXES: {{^}} as = 6;{{$}} + as = static_cast<MyArcaneChar>(6); + as = 'a'; + + s += toupper(x); + s += tolower(x); + s += (std::tolower(x)); + + s += c & s[1]; + s += c ^ s[1]; + s += c | s[1]; + + s[x] += 1; + s += s[x]; + as += as[x]; + + // Likely character expressions. + s += x & 0xff; + s += 0xff & x; + s += x % 26; + s += 26 % x; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: an integer is interpreted as a chara + // CHECK-FIXES: {{^}} s += std::to_string(26 % x);{{$}} + s += c | 0x80; + s += c | 0x8000; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: an integer is interpreted as a chara + // CHECK-FIXES: {{^}} s += std::to_string(c | 0x8000);{{$}} + as += c | 0x8000; + + s += 'a' + (x % 26); + s += kCharConstant + (x % 26); + s += 'a' + (s[x] & 0xf); + s += (x % 10) + 'b'; + + s += x > 255 ? c : x; + s += x > 255 ? 12 : x; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: an integer is interpreted as a chara + // CHECK-FIXES: {{^}} s += std::to_string(x > 255 ? 12 : x);{{$}} +} + +namespace instantiation_dependent_exprs { +template<typename T> +struct S { + static constexpr T t = 0x8000; + std::string s; + void f(char c) { s += c | static_cast<int>(t); } +}; +template S<int>; } diff --git a/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp b/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp new file mode 100644 index 00000000..d602a1d0 --- /dev/null +++ b/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp @@ -0,0 +1,23 @@ +// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- -- --target=x86_64-linux + +// MagnitudeBitsUpperLimit = 16 (default value) + +unsigned long size() { return 294967296l; } + +void voidFilteredOutForLoop1() { + for (long i = 0; i < size(); ++i) { + // no warning + } +} + +void voidCaughtForLoop1() { + for (int i = 0; i < size(); ++i) { + // no warning + } +} + +void voidCaughtForLoop2() { + for (short i = 0; i < size(); ++i) { + // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'unsigned long' [bugprone-too-small-loop-variable] + } +} diff --git a/test/clang-tidy/bugprone-too-small-loop-variable.cpp b/test/clang-tidy/bugprone-too-small-loop-variable.cpp index f11dd499..5a633559 100644 --- a/test/clang-tidy/bugprone-too-small-loop-variable.cpp +++ b/test/clang-tidy/bugprone-too-small-loop-variable.cpp @@ -1,4 +1,8 @@ -// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- -- --target=x86_64-linux +// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- \ +// RUN: -config="{CheckOptions: \ +// RUN: [{key: bugprone-too-small-loop-variable.MagnitudeBitsUpperLimit, \ +// RUN: value: 1024}]}" \ +// RUN: -- --target=x86_64-linux long size() { return 294967296l; } diff --git a/test/clang-tidy/check_clang_tidy.py b/test/clang-tidy/check_clang_tidy.py index 9768011a..5d808f40 100755 --- a/test/clang-tidy/check_clang_tidy.py +++ b/test/clang-tidy/check_clang_tidy.py @@ -2,10 +2,9 @@ # #===- 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. +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # #===------------------------------------------------------------------------===# diff --git a/test/clang-tidy/clang-tidy-diff.cpp b/test/clang-tidy/clang-tidy-diff.cpp index 146287bf..2e18a43c 100644 --- a/test/clang-tidy/clang-tidy-diff.cpp +++ b/test/clang-tidy/clang-tidy-diff.cpp @@ -23,5 +23,4 @@ struct B : public A { // CHECK-QUIET-NOT: warning: }; // CHECK-SANITY-NOT: Suppressed -// CHECK: Suppressed 1 warnings (1 due to line filter). // CHECK-QUIET-NOT: Suppressed diff --git a/test/clang-tidy/clang-tidy-mac-libcxx.cpp b/test/clang-tidy/clang-tidy-mac-libcxx.cpp index 153a5d6e..d124a344 100644 --- a/test/clang-tidy/clang-tidy-mac-libcxx.cpp +++ b/test/clang-tidy/clang-tidy-mac-libcxx.cpp @@ -8,7 +8,7 @@ // RUN: cp -r %S/Inputs/mock-libcxx %t/ // // Pretend clang is installed beside the mock library that we provided. -// RUN: echo '[{"directory":"%t","command":"%t/mock-libcxx/bin/clang++ -stdlib=libc++ -target x86_64-apple-darwin -c test.cpp","file":"test.cpp"}]' | sed -e 's/\\/\//g' > %t/compile_commands.json +// RUN: echo '[{"directory":"%t","command":"%t/mock-libcxx/bin/clang++ -stdlib=libc++ -std=c++11 -target x86_64-apple-darwin -c test.cpp","file":"test.cpp"}]' | sed -e 's/\\/\//g' > %t/compile_commands.json // RUN: cp "%s" "%t/test.cpp" // RUN: clang-tidy -header-filter='.*' -system-headers -checks='-*,modernize-use-using' "%t/test.cpp" | FileCheck %s // CHECK: mock_vector:{{[0-9]+}}:{{[0-9]+}}: warning: use 'using' instead of 'typedef' diff --git a/test/clang-tidy/cppcoreguidelines-macro-usage.cpp b/test/clang-tidy/cppcoreguidelines-macro-usage.cpp index a4948f5b..edce328e 100644 --- a/test/clang-tidy/cppcoreguidelines-macro-usage.cpp +++ b/test/clang-tidy/cppcoreguidelines-macro-usage.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s cppcoreguidelines-macro-usage %t +// RUN: %check_clang_tidy %s cppcoreguidelines-macro-usage %t -- -header-filter=.* -system-headers -- #ifndef INCLUDE_GUARD #define INCLUDE_GUARD diff --git a/test/clang-tidy/expand-modular-headers-ppcallbacks.cpp b/test/clang-tidy/expand-modular-headers-ppcallbacks.cpp new file mode 100644 index 00000000..d191922d --- /dev/null +++ b/test/clang-tidy/expand-modular-headers-ppcallbacks.cpp @@ -0,0 +1,35 @@ +// Sanity-check. Run without modules: +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: cp %S/Inputs/expand-modular-headers-ppcallbacks/* %t/ +// RUN: %check_clang_tidy %s readability-identifier-naming %t/without-modules -- \ +// RUN: -config="CheckOptions: [{ \ +// RUN: key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE }]" \ +// RUN: -header-filter=.* \ +// RUN: -- -x c++ -std=c++11 -I%t/ +// +// Run clang-tidy on a file with modular includes: +// +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: cp %S/Inputs/expand-modular-headers-ppcallbacks/* %t/ +// RUN: %check_clang_tidy %s readability-identifier-naming %t/with-modules -- \ +// RUN: -config="CheckOptions: [{ \ +// RUN: key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE }]" \ +// RUN: -header-filter=.* \ +// RUN: -- -x c++ -std=c++11 -I%t/ \ +// RUN: -fmodules -fimplicit-modules -fno-implicit-module-maps \ +// RUN: -fmodule-map-file=%t/module.modulemap \ +// RUN: -fmodules-cache-path=%t/module-cache/ +#include "c.h" + +// CHECK-MESSAGES: a.h:1:9: warning: invalid case style for macro definition 'a' [readability-identifier-naming] +// CHECK-MESSAGES: a.h:1:9: note: FIX-IT applied suggested code changes +// CHECK-MESSAGES: b.h:2:9: warning: invalid case style for macro definition 'b' +// CHECK-MESSAGES: b.h:2:9: note: FIX-IT applied suggested code changes +// CHECK-MESSAGES: c.h:2:9: warning: invalid case style for macro definition 'c' +// CHECK-MESSAGES: c.h:2:9: note: FIX-IT applied suggested code changes + +#define m +// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for macro definition 'm' +// CHECK-MESSAGES: :[[@LINE-2]]:9: note: FIX-IT applied suggested code changes diff --git a/test/clang-tidy/export-diagnostics.cpp b/test/clang-tidy/export-diagnostics.cpp index 5eda2042..14a6a40d 100644 --- a/test/clang-tidy/export-diagnostics.cpp +++ b/test/clang-tidy/export-diagnostics.cpp @@ -13,16 +13,19 @@ X(f) // CHECK-YAML-NEXT: MainSourceFile: '{{.*}}-input.cpp' // CHECK-YAML-NEXT: Diagnostics: // CHECK-YAML-NEXT: - DiagnosticName: clang-diagnostic-missing-prototypes -// CHECK-YAML-NEXT: Message: 'no previous prototype for function ''ff''' -// CHECK-YAML-NEXT: FileOffset: 30 -// CHECK-YAML-NEXT: FilePath: '{{.*}}-input.cpp' +// CHECK-YAML-NEXT: DiagnosticMessage: +// CHECK-YAML-NEXT: Message: 'no previous prototype for function +// ''ff''' +// CHECK-YAML-NEXT: FilePath: '{{.*}}-input.cpp' +// CHECK-YAML-NEXT: FileOffset: 30 +// CHECK-YAML-NEXT: Replacements: [] // CHECK-YAML-NEXT: Notes: // CHECK-YAML-NEXT: - Message: 'expanded from macro ''X''' // CHECK-YAML-NEXT: FilePath: '{{.*}}-input.cpp' // CHECK-YAML-NEXT: FileOffset: 18 +// CHECK-YAML-NEXT: Replacements: [] // CHECK-YAML-NEXT: - Message: expanded from here // CHECK-YAML-NEXT: FilePath: '' // CHECK-YAML-NEXT: FileOffset: 0 -// CHECK-YAML-NEXT: Replacements: [] +// CHECK-YAML-NEXT: Replacements: [] // CHECK-YAML-NEXT: ... - diff --git a/test/clang-tidy/google-objc-function-naming.m b/test/clang-tidy/google-objc-function-naming.m index d0336d26..01433d9f 100644 --- a/test/clang-tidy/google-objc-function-naming.m +++ b/test/clang-tidy/google-objc-function-naming.m @@ -1,4 +1,12 @@ -// RUN: %check_clang_tidy %s google-objc-function-naming %t +// RUN: %check_clang_tidy %s google-objc-function-naming %t -- -- -isystem %S/Inputs/Headers + +#include <stdio.h> + +static void TestImplicitFunctionDeclaration(int a) { + // Call a builtin function so that the compiler generates an implicit + // function declaration. + printf("%d", a); +} typedef _Bool bool; diff --git a/test/clang-tidy/google-objc-global-variable-declaration.mm b/test/clang-tidy/google-objc-global-variable-declaration.mm new file mode 100644 index 00000000..a6b0f6ee --- /dev/null +++ b/test/clang-tidy/google-objc-global-variable-declaration.mm @@ -0,0 +1,10 @@ +// 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"; + +class MyTest { + static int not_objc_style; +}; diff --git a/test/clang-tidy/google-runtime-int.m b/test/clang-tidy/google-runtime-int.m new file mode 100644 index 00000000..dd1225c9 --- /dev/null +++ b/test/clang-tidy/google-runtime-int.m @@ -0,0 +1,32 @@ +// RUN: clang-tidy -checks=-*,google-runtime-int %s 2>&1 -- | count 0 +// RUN: clang-tidy -checks=-*,google-runtime-int %s 2>&1 -- -x objective-c++ | count 0 + +typedef long NSInteger; +typedef unsigned long NSUInteger; + +@interface NSString +@property(readonly) NSInteger integerValue; +@property(readonly) long long longLongValue; +@property(readonly) NSUInteger length; +@end + +NSInteger Foo(NSString *s) { + return [s integerValue]; +} + +long long Bar(NSString *s) { + return [s longLongValue]; +} + +NSUInteger Baz(NSString *s) { + return [s length]; +} + +unsigned short NSSwapShort(unsigned short inv); + +long DoSomeMath(long a, short b) { + short c = NSSwapShort(b); + long a2 = a * 5L; + return a2 + c; +} + diff --git a/test/clang-tidy/llvm-prefer-isa-or-dyn-cast-in-conditionals.cpp b/test/clang-tidy/llvm-prefer-isa-or-dyn-cast-in-conditionals.cpp new file mode 100644 index 00000000..48652d52 --- /dev/null +++ b/test/clang-tidy/llvm-prefer-isa-or-dyn-cast-in-conditionals.cpp @@ -0,0 +1,132 @@ +// RUN: %check_clang_tidy %s llvm-prefer-isa-or-dyn-cast-in-conditionals %t + +struct X; +struct Y; +struct Z { + int foo(); + X *bar(); + X *cast(Y*); + bool baz(Y*); +}; + +template <class X, class Y> +bool isa(Y *); +template <class X, class Y> +X *cast(Y *); +template <class X, class Y> +X *dyn_cast(Y *); +template <class X, class Y> +X *dyn_cast_or_null(Y *); + +bool foo(Y *y, Z *z) { + if (auto x = cast<X>(y)) + return true; + // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: cast<> in conditional will assert rather than return a null pointer [llvm-prefer-isa-or-dyn-cast-in-conditionals] + // CHECK-FIXES: if (auto x = dyn_cast<X>(y)) + + while (auto x = cast<X>(y)) + break; + // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: cast<> in conditional + // CHECK-FIXES: while (auto x = dyn_cast<X>(y)) + + if (cast<X>(y)) + return true; + // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: cast<> in conditional + // CHECK-FIXES: if (isa<X>(y)) + + while (cast<X>(y)) + break; + // CHECK-MESSAGES: :[[@LINE-2]]:10: warning: cast<> in conditional + // CHECK-FIXES: while (isa<X>(y)) + + do { + break; + } while (cast<X>(y)); + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: cast<> in conditional + // CHECK-FIXES: while (isa<X>(y)); + + if (dyn_cast<X>(y)) + return true; + // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: return value from dyn_cast<> not used [llvm-prefer-isa-or-dyn-cast-in-conditionals] + // CHECK-FIXES: if (isa<X>(y)) + + while (dyn_cast<X>(y)) + break; + // CHECK-MESSAGES: :[[@LINE-2]]:10: warning: return value from dyn_cast<> not used + // CHECK-FIXES: while (isa<X>(y)) + + do { + break; + } while (dyn_cast<X>(y)); + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: return value from dyn_cast<> not used + // CHECK-FIXES: while (isa<X>(y)); + + if (y && isa<X>(y)) + return true; + // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred over an explicit test for null followed by calling isa<> [llvm-prefer-isa-or-dyn-cast-in-conditionals] + // CHECK-FIXES: if (isa_and_nonnull<X>(y)) + + if (z->bar() && isa<Y>(z->bar())) + return true; + // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred + // CHECK-FIXES: if (isa_and_nonnull<Y>(z->bar())) + + if (z->bar() && cast<Y>(z->bar())) + return true; + // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred + // CHECK-FIXES: if (isa_and_nonnull<Y>(z->bar())) + + if (z->bar() && dyn_cast<Y>(z->bar())) + return true; + // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred + // CHECK-FIXES: if (isa_and_nonnull<Y>(z->bar())) + + if (z->bar() && dyn_cast_or_null<Y>(z->bar())) + return true; + // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred + // CHECK-FIXES: if (isa_and_nonnull<Y>(z->bar())) + + bool b = z->bar() && cast<Y>(z->bar()); + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: isa_and_nonnull<> is preferred + // CHECK-FIXES: bool b = isa_and_nonnull<Y>(z->bar()); + + // These don't trigger a warning. + if (auto x = cast<Z>(y)->foo()) + return true; + if (auto x = z->cast(y)) + return true; + while (auto x = cast<Z>(y)->foo()) + break; + if (cast<Z>(y)->foo()) + return true; + if (z->cast(y)) + return true; + while (cast<Z>(y)->foo()) + break; + if (y && cast<X>(z->bar())) + return true; + if (z && cast<Z>(y)->foo()) + return true; + bool b2 = y && cast<X>(z); + if(z->cast(y)) + return true; + if (z->baz(cast<Y>(z))) + return true; + +#define CAST(T, Obj) cast<T>(Obj) +#define AUTO_VAR_CAST(X, Y, Z) auto X = cast<Y>(Z) +#define ISA(T, Obj) isa<T>(Obj) +#define ISA_OR_NULL(T, Obj) Obj &&isa<T>(Obj) + + // Macros don't trigger warning. + if (auto x = CAST(X, y)) + return true; + if (AUTO_VAR_CAST(x, X, z)) + return true; + if (z->bar() && ISA(Y, z->bar())) + return true; + if (ISA_OR_NULL(Y, z->bar())) + return true; + + return false; +} diff --git a/test/clang-tidy/misc-non-private-member-variables-in-classes.cpp b/test/clang-tidy/misc-non-private-member-variables-in-classes.cpp index 31052716..2a93ff6a 100644 --- a/test/clang-tidy/misc-non-private-member-variables-in-classes.cpp +++ b/test/clang-tidy/misc-non-private-member-variables-in-classes.cpp @@ -35,6 +35,23 @@ private: int S1_v3; }; +// Only data and implicit or static methods, do not warn + +class C { +public: + C() {} + ~C() {} +}; + +struct S1Implicit { + C S1Implicit_v0; +}; + +struct S1ImplicitAndStatic { + C S1Implicit_v0; + static void s() {} +}; + //----------------------------------------------------------------------------// // All functions are static, do not warn. diff --git a/test/clang-tidy/modernize-avoid-bind.cpp b/test/clang-tidy/modernize-avoid-bind.cpp index 1c78b9e6..721801be 100644 --- a/test/clang-tidy/modernize-avoid-bind.cpp +++ b/test/clang-tidy/modernize-avoid-bind.cpp @@ -77,3 +77,47 @@ void n() { // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: prefer a lambda to std::bind // CHECK-FIXES: auto clj = [] { return C::add(1, 1); }; } + +// Let's fake a minimal std::function-like facility. +namespace std { +template <typename _Tp> +_Tp declval(); + +template <typename _Functor, typename... _ArgTypes> +struct __res { + template <typename... _Args> + static decltype(declval<_Functor>()(_Args()...)) _S_test(int); + + template <typename...> + static void _S_test(...); + + using type = decltype(_S_test<_ArgTypes...>(0)); +}; + +template <typename> +struct function; + +template <typename... _ArgTypes> +struct function<void(_ArgTypes...)> { + template <typename _Functor, + typename = typename __res<_Functor, _ArgTypes...>::type> + function(_Functor) {} +}; +} // namespace std + +struct Thing {}; +void UseThing(Thing *); + +struct Callback { + Callback(); + Callback(std::function<void()>); + void Reset(std::function<void()>); +}; + +void test(Thing *t) { + Callback cb; + if (t) + cb.Reset(std::bind(UseThing, t)); + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: prefer a lambda to std::bind + // CHECK-FIXES: cb.Reset([=] { return UseThing(t); }); +} diff --git a/test/clang-tidy/modernize-avoid-c-arrays-ignores-main.cpp b/test/clang-tidy/modernize-avoid-c-arrays-ignores-main.cpp new file mode 100644 index 00000000..6549422f --- /dev/null +++ b/test/clang-tidy/modernize-avoid-c-arrays-ignores-main.cpp @@ -0,0 +1,18 @@ +// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t + +int not_main(int argc, char *argv[]) { + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not declare C-style arrays, use std::array<> instead + int f4[] = {1, 2}; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead +} + +int main(int argc, char *argv[]) { + int f5[] = {1, 2}; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead + + auto not_main = [](int argc, char *argv[]) { + // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: do not declare C-style arrays, use std::array<> instead + int f6[] = {1, 2}; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not declare C-style arrays, use std::array<> instead + }; +} diff --git a/test/clang-tidy/modernize-avoid-c-arrays-ignores-three-arg-main.cpp b/test/clang-tidy/modernize-avoid-c-arrays-ignores-three-arg-main.cpp new file mode 100644 index 00000000..22a4016f --- /dev/null +++ b/test/clang-tidy/modernize-avoid-c-arrays-ignores-three-arg-main.cpp @@ -0,0 +1,20 @@ +// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t + +int not_main(int argc, char *argv[], char *argw[]) { + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not declare C-style arrays, use std::array<> instead + // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: do not declare C-style arrays, use std::array<> instead + int f4[] = {1, 2}; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead +} + +int main(int argc, char *argv[], char *argw[]) { + int f5[] = {1, 2}; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead + + auto not_main = [](int argc, char *argv[], char *argw[]) { + // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: do not declare C-style arrays, use std::array<> instead + // CHECK-MESSAGES: :[[@LINE-2]]:46: warning: do not declare C-style arrays, use std::array<> instead + int f6[] = {1, 2}; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not declare C-style arrays, use std::array<> instead + }; +} diff --git a/test/clang-tidy/modernize-redundant-void-arg.cpp b/test/clang-tidy/modernize-redundant-void-arg.cpp index 44a726b5..0fad5d55 100644 --- a/test/clang-tidy/modernize-redundant-void-arg.cpp +++ b/test/clang-tidy/modernize-redundant-void-arg.cpp @@ -489,6 +489,13 @@ void lambda_expression_with_macro_test(){ // CHECK-FIXES: []() BODY; } +namespace qqq { +void foo() BODY +void bar(void) BODY; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: redundant void argument list in function definition +// CHECK-FIXES: void bar() BODY; +} + struct S_1 { void g_1(void) const { // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant void argument list in function definition [modernize-redundant-void-arg] diff --git a/test/clang-tidy/modernize-use-default-member-init-assignment.cpp b/test/clang-tidy/modernize-use-default-member-init-assignment.cpp index fdc0db18..b98055c9 100644 --- a/test/clang-tidy/modernize-use-default-member-init-assignment.cpp +++ b/test/clang-tidy/modernize-use-default-member-init-assignment.cpp @@ -166,6 +166,14 @@ struct PositiveEnum { // CHECK-FIXES: Enum e = Foo; }; +struct PositiveValueEnum { + PositiveValueEnum() : e() {} + // CHECK-FIXES: PositiveValueEnum() {} + Enum e; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'e' + // CHECK-FIXES: Enum e{}; +}; + struct PositiveString { PositiveString() : s("foo") {} // CHECK-FIXES: PositiveString() {} diff --git a/test/clang-tidy/modernize-use-default-member-init.cpp b/test/clang-tidy/modernize-use-default-member-init.cpp index 0ed65df3..825bfa0b 100644 --- a/test/clang-tidy/modernize-use-default-member-init.cpp +++ b/test/clang-tidy/modernize-use-default-member-init.cpp @@ -165,6 +165,14 @@ struct PositiveEnum { // CHECK-FIXES: Enum e{Foo}; }; +struct PositiveValueEnum { + PositiveValueEnum() : e() {} + // CHECK-FIXES: PositiveValueEnum() {} + Enum e; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'e' + // CHECK-FIXES: Enum e{}; +}; + struct PositiveString { PositiveString() : s("foo") {} // CHECK-FIXES: PositiveString() {} @@ -382,6 +390,16 @@ struct ExistingString { const char *e4 = "bar"; }; +struct UnionExisting { + UnionExisting() : e(5.0) {} + // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: member initializer for 'e' is redundant + // CHECK-FIXES: UnionExisting() {} + union { + int i; + double e = 5.0; + }; +}; + template <typename T> struct NegativeTemplateExisting { NegativeTemplateExisting(int) : t(0) {} diff --git a/test/clang-tidy/modernize-use-override-no-destructors.cpp b/test/clang-tidy/modernize-use-override-no-destructors.cpp new file mode 100644 index 00000000..eaadb07b --- /dev/null +++ b/test/clang-tidy/modernize-use-override-no-destructors.cpp @@ -0,0 +1,16 @@ +// RUN: %check_clang_tidy %s modernize-use-override %t -- \ +// RUN: -config="{CheckOptions: [{key: modernize-use-override.IgnoreDestructors, value: 1}]}" \ +// RUN: -- -std=c++11 + +struct Base { + virtual ~Base(); + virtual void f(); +}; + +struct Simple : public Base { + virtual ~Simple(); + // CHECK-MESSAGES-NOT: warning: + virtual void f(); + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using + // CHECK-FIXES: {{^}} void f() override; +}; diff --git a/test/clang-tidy/modernize-use-override-with-macro.cpp b/test/clang-tidy/modernize-use-override-with-macro.cpp new file mode 100644 index 00000000..ad682f15 --- /dev/null +++ b/test/clang-tidy/modernize-use-override-with-macro.cpp @@ -0,0 +1,70 @@ +// RUN: %check_clang_tidy %s modernize-use-override %t -- \ +// RUN: -config="{CheckOptions: [{key: modernize-use-override.OverrideSpelling, value: 'OVERRIDE'},{key: modernize-use-override.FinalSpelling, value: 'FINAL'}]}" \ +// RUN: -- -std=c++11 + +#define ABSTRACT = 0 + +#define OVERRIDE override +#define FINAL final +#define VIRTUAL virtual +#define NOT_VIRTUAL +#define NOT_OVERRIDE + +#define MUST_USE_RESULT __attribute__((warn_unused_result)) +#define UNUSED __attribute__((unused)) + +struct Base { + virtual ~Base() {} + virtual void a(); + virtual void b(); + virtual void c(); + virtual void e() = 0; + virtual void f2() const = 0; + virtual void g() = 0; + virtual void j() const; + virtual void k() = 0; + virtual void l() const; +}; + +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 function with 'OVERRIDE' or (rarely) 'FINAL' [modernize-use-override] + // CHECK-FIXES: {{^}} void a() OVERRIDE; + + virtual void b(); + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using 'OVERRIDE' or (rarely) 'FINAL' instead of 'virtual' [modernize-use-override] + // CHECK-FIXES: {{^}} void b() OVERRIDE; + + virtual void c(); + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using + // CHECK-FIXES: {{^}} void c() OVERRIDE; + + virtual void e() = 0; + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using + // CHECK-FIXES: {{^}} void e() 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 void k() OVERRIDE; + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant since the function is already declared 'OVERRIDE' [modernize-use-override] + // CHECK-FIXES: {{^}} void k() OVERRIDE; + + virtual void l() const OVERRIDE; + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant since the function is already declared 'OVERRIDE' [modernize-use-override] + // CHECK-FIXES: {{^}} void l() const OVERRIDE; +}; diff --git a/test/clang-tidy/modernize-use-override-with-no-macro-inscope.cpp b/test/clang-tidy/modernize-use-override-with-no-macro-inscope.cpp new file mode 100644 index 00000000..97b71053 --- /dev/null +++ b/test/clang-tidy/modernize-use-override-with-no-macro-inscope.cpp @@ -0,0 +1,28 @@ +// RUN: %check_clang_tidy %s modernize-use-override %t -- \ +// RUN: -config="{CheckOptions: [{key: modernize-use-override.OverrideSpelling, value: 'CUSTOM_OVERRIDE'},{key: modernize-use-override.FinalSpelling, value: 'CUSTOM_FINAL'}]}" \ +// RUN: -- -std=c++11 + +// As if the macro was not defined. +//#define CUSTOM_OVERRIDE override +//#define CUSTOM_FINAL override + +struct Base { + virtual ~Base() {} + virtual void a(); + virtual void b(); +}; + +struct SimpleCases : public Base { +public: + virtual ~SimpleCases(); + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: prefer using 'CUSTOM_OVERRIDE' or (rarely) 'CUSTOM_FINAL' instead of 'virtual' [modernize-use-override] + // CHECK-FIXES: {{^}} virtual ~SimpleCases(); + + void a(); + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: annotate this function with 'CUSTOM_OVERRIDE' or (rarely) 'CUSTOM_FINAL' [modernize-use-override] + // CHECK-FIXES: {{^}} void a(); + + virtual void b(); + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using 'CUSTOM_OVERRIDE' or (rarely) 'CUSTOM_FINAL' instead of 'virtual' [modernize-use-override] + // CHECK-FIXES: {{^}} virtual void b(); +}; diff --git a/test/clang-tidy/nolint.cpp b/test/clang-tidy/nolint.cpp index 24c37228..a2d2c10a 100644 --- a/test/clang-tidy/nolint.cpp +++ b/test/clang-tidy/nolint.cpp @@ -31,6 +31,7 @@ void f() { int i; // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: unused variable 'i' [clang-diagnostic-unused-variable] int j; // NOLINT + int k; // NOLINT(clang-diagnostic-unused-variable) } #define MACRO(X) class X { X(int i); }; @@ -47,4 +48,4 @@ MACRO_NOLINT #define DOUBLE_MACRO MACRO(H) // NOLINT DOUBLE_MACRO -// CHECK-MESSAGES: Suppressed 12 warnings (12 NOLINT) +// CHECK-MESSAGES: Suppressed 13 warnings (13 NOLINT) diff --git a/test/clang-tidy/objc-property-declaration.m b/test/clang-tidy/objc-property-declaration.m index 07a06205..b56bdcd1 100644 --- a/test/clang-tidy/objc-property-declaration.m +++ b/test/clang-tidy/objc-property-declaration.m @@ -46,6 +46,7 @@ typedef void *CGColorRef; @property(strong, nonatomic) NSString *URLStr; @property(assign, nonatomic) int abc_camelCase; @property(strong, nonatomic) NSString *abc_URL; +@property(strong, nonatomic) NSString *opac2_sourceComponent; @end @interface Foo () diff --git a/test/clang-tidy/objc-super-self.m b/test/clang-tidy/objc-super-self.m new file mode 100644 index 00000000..9653cd22 --- /dev/null +++ b/test/clang-tidy/objc-super-self.m @@ -0,0 +1,86 @@ +// RUN: %check_clang_tidy %s objc-super-self %t + +@interface NSObject +- (instancetype)init; +- (instancetype)self; +@end + +@interface NSObjectDerivedClass : NSObject +@end + +@implementation NSObjectDerivedClass + +- (instancetype)init { + return [super self]; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious invocation of 'self' in initializer; did you mean to invoke a superclass initializer? [objc-super-self] +// CHECK-FIXES: return [super init]; +} + +- (instancetype)initWithObject:(NSObject *)obj { + self = [super self]; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious invocation of 'self' in initializer; did you mean to invoke a superclass initializer? [objc-super-self] +// CHECK-FIXES: self = [super init]; + if (self) { + // ... + } + return self; +} + +#define INITIALIZE() [super self] + +- (instancetype)initWithObject:(NSObject *)objc a:(int)a { + return INITIALIZE(); +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious invocation of 'self' in initializer; did you mean to invoke a superclass initializer? [objc-super-self] +// CHECK-FIXES: return INITIALIZE(); +} + +#define INITIALIZER_IMPL() return [super self] + +- (instancetype)initWithObject:(NSObject *)objc b:(int)b { + INITIALIZER_IMPL(); +// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: suspicious invocation of 'self' in initializer; did you mean to invoke a superclass initializer? [objc-super-self] +// CHECK-FIXES: INITIALIZER_IMPL(); +} + +#define INITIALIZER_METHOD self + +- (instancetype)initWithObject:(NSObject *)objc c:(int)c { + return [super INITIALIZER_METHOD]; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious invocation of 'self' in initializer; did you mean to invoke a superclass initializer? [objc-super-self] +// CHECK-FIXES: return [super INITIALIZER_METHOD]; +} + +#define RECEIVER super + +- (instancetype)initWithObject:(NSObject *)objc d:(int)d { + return [RECEIVER self]; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious invocation of 'self' in initializer; did you mean to invoke a superclass initializer? [objc-super-self] +// CHECK-FIXES: return [RECEIVER self]; +} + +- (instancetype)foo { + return [super self]; +} + +- (instancetype)bar { + return [self self]; +} + +@end + +@interface RootClass +- (instancetype)init; +- (instancetype)self; +@end + +@interface NotNSObjectDerivedClass : RootClass +@end + +@implementation NotNSObjectDerivedClass + +- (instancetype)init { + return [super self]; +} + +@end + diff --git a/test/clang-tidy/openmp-exception-escape.cpp b/test/clang-tidy/openmp-exception-escape.cpp new file mode 100644 index 00000000..73345836 --- /dev/null +++ b/test/clang-tidy/openmp-exception-escape.cpp @@ -0,0 +1,132 @@ +// RUN: %check_clang_tidy %s openmp-exception-escape %t -- -extra-arg=-fopenmp=libomp -extra-arg=-fexceptions -config="{CheckOptions: [{key: openmp-exception-escape.IgnoredExceptions, value: 'ignored, ignored2'}]}" -- + +int thrower() { + throw 42; +} + +class ignored {}; +class ignored2 {}; +namespace std { +class bad_alloc {}; +} // namespace std + +void parallel() { +#pragma omp parallel + thrower(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception thrown inside of the OpenMP 'parallel' region is not caught in that same region +} + +void ignore() { +#pragma omp parallel + throw ignored(); +} + +void ignore2() { +#pragma omp parallel + throw ignored2(); +} + +void standalone_directive() { +#pragma omp taskwait + throw ignored(); // not structured block +} + +void ignore_alloc() { +#pragma omp parallel + throw std::bad_alloc(); +} + +void parallel_caught() { +#pragma omp parallel + { + try { + thrower(); + } catch (...) { + } + } +} + +void for_header(const int a) { + // Only the body of the loop counts. +#pragma omp for + for (int i = 0; i < thrower(); i++) + ; +} + +void forloop(const int a) { +#pragma omp for + for (int i = 0; i < a; i++) + thrower(); + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception thrown inside of the OpenMP 'for' region is not caught in that same region +} + +void parallel_forloop(const int a) { +#pragma omp parallel + { +#pragma omp for + for (int i = 0; i < a; i++) + thrower(); + thrower(); + // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: an exception thrown inside of the OpenMP 'parallel' region is not caught in that same region + // CHECK-MESSAGES: :[[@LINE-3]]:7: warning: an exception thrown inside of the OpenMP 'for' region is not caught in that same region + } +} + +void parallel_forloop_caught(const int a) { +#pragma omp parallel + { +#pragma omp for + for (int i = 0; i < a; i++) { + try { + thrower(); + } catch (...) { + } + } + thrower(); + // CHECK-MESSAGES: :[[@LINE-9]]:3: warning: an exception thrown inside of the OpenMP 'parallel' region is not caught in that same region + } +} + +void parallel_caught_forloop(const int a) { +#pragma omp parallel + { +#pragma omp for + for (int i = 0; i < a; i++) + thrower(); + try { + thrower(); + } catch (...) { + } + // CHECK-MESSAGES: :[[@LINE-5]]:7: warning: an exception thrown inside of the OpenMP 'for' region is not caught in that same region + } +} + +void parallel_outercaught_forloop(const int a) { +#pragma omp parallel + { + try { +#pragma omp for + for (int i = 0; i < a; i++) + thrower(); + thrower(); + } catch (...) { + } + // CHECK-MESSAGES: :[[@LINE-4]]:9: warning: an exception thrown inside of the OpenMP 'for' region is not caught in that same region + } +} + +void parallel_outercaught_forloop_caught(const int a) { +#pragma omp parallel + { + try { +#pragma omp for + for (int i = 0; i < a; i++) { + try { + thrower(); + } catch (...) { + } + } + } catch (...) { + } + } +} diff --git a/test/clang-tidy/openmp-use-default-none.cpp b/test/clang-tidy/openmp-use-default-none.cpp new file mode 100644 index 00000000..1a374bde --- /dev/null +++ b/test/clang-tidy/openmp-use-default-none.cpp @@ -0,0 +1,160 @@ +// RUN: %check_clang_tidy %s openmp-use-default-none %t -- -- -x c++ -fopenmp=libomp -fopenmp-version=40 +// RUN: %check_clang_tidy %s openmp-use-default-none %t -- -- -x c -fopenmp=libomp -fopenmp-version=40 + +//----------------------------------------------------------------------------// +// Null cases. +//----------------------------------------------------------------------------// + +// 'for' directive can not have 'default' clause, no diagnostics. +void n0(const int a) { +#pragma omp for + for (int b = 0; b < a; b++) + ; +} + +//----------------------------------------------------------------------------// +// Single-directive positive cases. +//----------------------------------------------------------------------------// + +// 'parallel' directive. + +// 'parallel' directive can have 'default' clause, but said clause is not +// specified, diagnosed. +void p0_0() { +#pragma omp parallel + ; + // CHECK-NOTES: :[[@LINE-2]]:9: warning: OpenMP directive 'parallel' does not specify 'default' clause, consider specifying 'default(none)' clause +} + +// 'parallel' directive can have 'default' clause, and said clause specified, +// with 'none' kind, all good. +void p0_1() { +#pragma omp parallel default(none) + ; +} + +// 'parallel' directive can have 'default' clause, and said clause specified, +// but with 'shared' kind, which is not 'none', diagnose. +void p0_2() { +#pragma omp parallel default(shared) + ; + // CHECK-NOTES: :[[@LINE-2]]:9: warning: OpenMP directive 'parallel' specifies 'default(shared)' clause, consider using 'default(none)' clause instead + // CHECK-NOTES: :[[@LINE-3]]:22: note: existing 'default' clause specified here +} + +// 'task' directive. + +// 'task' directive can have 'default' clause, but said clause is not +// specified, diagnosed. +void p1_0() { +#pragma omp task + ; + // CHECK-NOTES: :[[@LINE-2]]:9: warning: OpenMP directive 'task' does not specify 'default' clause, consider specifying 'default(none)' clause +} + +// 'task' directive can have 'default' clause, and said clause specified, +// with 'none' kind, all good. +void p1_1() { +#pragma omp task default(none) + ; +} + +// 'task' directive can have 'default' clause, and said clause specified, +// but with 'shared' kind, which is not 'none', diagnose. +void p1_2() { +#pragma omp task default(shared) + ; + // CHECK-NOTES: :[[@LINE-2]]:9: warning: OpenMP directive 'task' specifies 'default(shared)' clause, consider using 'default(none)' clause instead + // CHECK-NOTES: :[[@LINE-3]]:18: note: existing 'default' clause specified here +} + +// 'teams' directive. (has to be inside of 'target' directive) + +// 'teams' directive can have 'default' clause, but said clause is not +// specified, diagnosed. +void p2_0() { +#pragma omp target +#pragma omp teams + ; + // CHECK-NOTES: :[[@LINE-2]]:9: warning: OpenMP directive 'teams' does not specify 'default' clause, consider specifying 'default(none)' clause +} + +// 'teams' directive can have 'default' clause, and said clause specified, +// with 'none' kind, all good. +void p2_1() { +#pragma omp target +#pragma omp teams default(none) + ; +} + +// 'teams' directive can have 'default' clause, and said clause specified, +// but with 'shared' kind, which is not 'none', diagnose. +void p2_2() { +#pragma omp target +#pragma omp teams default(shared) + ; + // CHECK-NOTES: :[[@LINE-2]]:9: warning: OpenMP directive 'teams' specifies 'default(shared)' clause, consider using 'default(none)' clause instead + // CHECK-NOTES: :[[@LINE-3]]:19: note: existing 'default' clause specified here +} + +// 'taskloop' directive. + +// 'taskloop' directive can have 'default' clause, but said clause is not +// specified, diagnosed. +void p3_0(const int a) { +#pragma omp taskloop + for (int b = 0; b < a; b++) + ; + // CHECK-NOTES: :[[@LINE-3]]:9: warning: OpenMP directive 'taskloop' does not specify 'default' clause, consider specifying 'default(none)' clause +} + +// 'taskloop' directive can have 'default' clause, and said clause specified, +// with 'none' kind, all good. +void p3_1(const int a) { +#pragma omp taskloop default(none) shared(a) + for (int b = 0; b < a; b++) + ; +} + +// 'taskloop' directive can have 'default' clause, and said clause specified, +// but with 'shared' kind, which is not 'none', diagnose. +void p3_2(const int a) { +#pragma omp taskloop default(shared) + for (int b = 0; b < a; b++) + ; + // CHECK-NOTES: :[[@LINE-3]]:9: warning: OpenMP directive 'taskloop' specifies 'default(shared)' clause, consider using 'default(none)' clause instead + // CHECK-NOTES: :[[@LINE-4]]:22: note: existing 'default' clause specified here +} + +//----------------------------------------------------------------------------// +// Combined directives. +// Let's not test every single possible permutation/combination of directives, +// but just *one* combined directive. The rest will be the same. +//----------------------------------------------------------------------------// + +// 'parallel' directive can have 'default' clause, but said clause is not +// specified, diagnosed. +void p4_0(const int a) { +#pragma omp parallel for + for (int b = 0; b < a; b++) + ; + // CHECK-NOTES: :[[@LINE-3]]:9: warning: OpenMP directive 'parallel for' does not specify 'default' clause, consider specifying 'default(none)' clause +} + +// 'parallel' directive can have 'default' clause, and said clause specified, +// with 'none' kind, all good. +void p4_1(const int a) { +#pragma omp parallel for default(none) shared(a) + for (int b = 0; b < a; b++) + ; +} + +// 'parallel' directive can have 'default' clause, and said clause specified, +// but with 'shared' kind, which is not 'none', diagnose. +void p4_2(const int a) { +#pragma omp parallel for default(shared) + for (int b = 0; b < a; b++) + ; + // CHECK-NOTES: :[[@LINE-3]]:9: warning: OpenMP directive 'parallel for' specifies 'default(shared)' clause, consider using 'default(none)' clause instead + // CHECK-NOTES: :[[@LINE-4]]:26: note: existing 'default' clause specified here +} diff --git a/test/clang-tidy/readability-avoid-underscore-in-googletest-name.cpp b/test/clang-tidy/readability-avoid-underscore-in-googletest-name.cpp new file mode 100644 index 00000000..6e8a5c2d --- /dev/null +++ b/test/clang-tidy/readability-avoid-underscore-in-googletest-name.cpp @@ -0,0 +1,108 @@ +// RUN: %check_clang_tidy %s google-readability-avoid-underscore-in-googletest-name %t + +#define TEST(test_case_name, test_name) void test_case_name##test_name() +#define TEST_F(test_case_name, test_name) void test_case_name##test_name() +#define TEST_P(test_case_name, test_name) void test_case_name##test_name() +#define TYPED_TEST(test_case_name, test_name) void test_case_name##test_name() +#define TYPED_TEST_P(test_case_name, test_name) void test_case_name##test_name() +#define FRIEND_TEST(test_case_name, test_name) void test_case_name##test_name() + +TEST(TestCaseName, Illegal_TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] + +TEST(TestCaseName, DISABLED_Illegal_TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +TEST(TestCaseName, Illegal_Test_Name) {} +// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: avoid using "_" in test name "Illegal_Test_Name" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +TEST(Illegal_TestCaseName, TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: avoid using "_" in test case name "Illegal_TestCaseName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +TEST(Illegal_Test_CaseName, TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: avoid using "_" in test case name "Illegal_Test_CaseName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +TEST(Illegal_TestCaseName, Illegal_TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: avoid using "_" in test case name "Illegal_TestCaseName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +// CHECK-MESSAGES: :[[@LINE-2]]:28: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] + +TEST_F(TestCaseFixtureName, Illegal_TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +TEST_F(TestCaseFixtureName, DISABLED_Illegal_Test_Name) {} +// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: avoid using "_" in test name "Illegal_Test_Name" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +TEST_F(TestCaseFixtureName, Illegal_Test_Name) {} +// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: avoid using "_" in test name "Illegal_Test_Name" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] + +TEST_F(Illegal_TestCaseFixtureName, TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: avoid using "_" in test case name "Illegal_TestCaseFixtureName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +TEST_F(Illegal_TestCaseFixtureName, Illegal_TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: avoid using "_" in test case name "Illegal_TestCaseFixtureName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +// CHECK-MESSAGES: :[[@LINE-2]]:37: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] + +TEST_F(Illegal_Test_CaseFixtureName, TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: avoid using "_" in test case name "Illegal_Test_CaseFixtureName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] + +TEST_P(ParameterizedTestCaseFixtureName, Illegal_TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:42: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +TEST_P(ParameterizedTestCaseFixtureName, DISABLED_Illegal_TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:42: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +TEST_P(ParameterizedTestCaseFixtureName, Illegal_Test_Name) {} +// CHECK-MESSAGES: :[[@LINE-1]]:42: warning: avoid using "_" in test name "Illegal_Test_Name" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] + +TEST_P(Illegal_ParameterizedTestCaseFixtureName, TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: avoid using "_" in test case name "Illegal_ParameterizedTestCaseFixtureName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +TEST_P(Illegal_ParameterizedTestCaseFixtureName, Illegal_TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: avoid using "_" in test case name "Illegal_ParameterizedTestCaseFixtureName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +// CHECK-MESSAGES: :[[@LINE-2]]:50: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] + +TEST_P(Illegal_Parameterized_TestCaseFixtureName, TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: avoid using "_" in test case name "Illegal_Parameterized_TestCaseFixtureName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] + +TYPED_TEST(TypedTestCaseName, Illegal_TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +TYPED_TEST(TypedTestCaseName, DISABLED_Illegal_TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +TYPED_TEST(TypedTestCaseName, Illegal_Test_Name) {} +// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: avoid using "_" in test name "Illegal_Test_Name" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] + +TYPED_TEST(Illegal_TypedTestCaseName, TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: avoid using "_" in test case name "Illegal_TypedTestCaseName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +TYPED_TEST(Illegal_TypedTestCaseName, Illegal_TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: avoid using "_" in test case name "Illegal_TypedTestCaseName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +// CHECK-MESSAGES: :[[@LINE-2]]:39: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] + +TYPED_TEST(Illegal_Typed_TestCaseName, TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: avoid using "_" in test case name "Illegal_Typed_TestCaseName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] + +TYPED_TEST_P(TypeParameterizedTestCaseName, Illegal_TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:45: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +TYPED_TEST_P(TypeParameterizedTestCaseName, DISABLED_Illegal_TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:45: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +TYPED_TEST_P(TypeParameterizedTestCaseName, Illegal_Test_Name) {} +// CHECK-MESSAGES: :[[@LINE-1]]:45: warning: avoid using "_" in test name "Illegal_Test_Name" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] + +TYPED_TEST_P(Illegal_TypeParameterizedTestCaseName, TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: avoid using "_" in test case name "Illegal_TypeParameterizedTestCaseName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +TYPED_TEST_P(Illegal_TypeParameterizedTestCaseName, Illegal_TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: avoid using "_" in test case name "Illegal_TypeParameterizedTestCaseName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] +// CHECK-MESSAGES: :[[@LINE-2]]:53: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] + +TYPED_TEST_P(Illegal_Type_ParameterizedTestCaseName, TestName) {} +// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: avoid using "_" in test case name "Illegal_Type_ParameterizedTestCaseName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name] + +// Underscores are allowed to disable a test with the DISABLED_ prefix. +// https://github.com/google/googletest/blob/master/googletest/docs/faq.md#why-should-test-suite-names-and-test-names-not-contain-underscore +TEST(TestCaseName, TestName) {} +TEST(TestCaseName, DISABLED_TestName) {} + +TEST_F(TestCaseFixtureName, TestName) {} +TEST_F(TestCaseFixtureName, DISABLED_TestName) {} + +TEST_P(ParameterizedTestCaseFixtureName, TestName) {} +TEST_P(ParameterizedTestCaseFixtureName, DISABLED_TestName) {} + +TYPED_TEST(TypedTestName, TestName) {} +TYPED_TEST(TypedTestName, DISABLED_TestName) {} + +TYPED_TEST_P(TypeParameterizedTestName, TestName) {} +TYPED_TEST_P(TypeParameterizedTestName, DISABLED_TestName) {} + +FRIEND_TEST(FriendTest, Is_NotChecked) {} +FRIEND_TEST(Friend_Test, IsNotChecked) {} +FRIEND_TEST(Friend_Test, Is_NotChecked) {} diff --git a/test/clang-tidy/readability-else-after-return.cpp b/test/clang-tidy/readability-else-after-return.cpp index 7e950928..b06c02c9 100644 --- a/test/clang-tidy/readability-else-after-return.cpp +++ b/test/clang-tidy/readability-else-after-return.cpp @@ -105,3 +105,15 @@ void foo() { } } } + +extern int *g(); +extern void h(int **x); + +int *decl_in_condition() { + if (int *x = g()) { + return x; + } else { + h(&x); + return x; + } +} diff --git a/test/clang-tidy/readability-misleading-indentation.cpp b/test/clang-tidy/readability-misleading-indentation.cpp index 59d5f406..40399492 100644 --- a/test/clang-tidy/readability-misleading-indentation.cpp +++ b/test/clang-tidy/readability-misleading-indentation.cpp @@ -8,7 +8,7 @@ void foo2(); foo1(); \ foo2(); -int main() +void f() { bool cond1 = true; bool cond2 = true; @@ -90,7 +90,7 @@ int main() else { } // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: different indentation for 'if' and corresponding 'else' [readability-misleading-indentation] - + if (cond1) { if (cond1) { } @@ -109,3 +109,12 @@ int main() BLOCK } + +void g(bool x) { + if (x) + #pragma unroll + for (int k = 0; k < 1; ++k) {} + + #pragma unroll + for (int k = 0; k < 1; ++k) {} +} diff --git a/test/clang-tidy/readability-redundant-smartptr-get-msvc.cpp b/test/clang-tidy/readability-redundant-smartptr-get-msvc.cpp new file mode 100644 index 00000000..bd8990a2 --- /dev/null +++ b/test/clang-tidy/readability-redundant-smartptr-get-msvc.cpp @@ -0,0 +1,94 @@ +// RUN: %check_clang_tidy %s readability-redundant-smartptr-get %t + +#define NULL __null + +namespace std { + +// MSVC headers define operator templates instead of plain operators. + +template <typename T> +struct unique_ptr { + template <typename T2 = T> + T2& operator*() const; + template <typename T2 = T> + T2* operator->() const; + T* get() const; + explicit operator bool() const noexcept; +}; + +template <typename T> +struct shared_ptr { + template <typename T2 = T> + T2& operator*() const; + template <typename T2 = T> + T2* operator->() const; + T* get() const; + explicit operator bool() const noexcept; +}; + +} // namespace std + +struct Bar { + void Do(); + void ConstDo() const; +}; + +void Positive() { + 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(); + + 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 = nullptr != ss->get(); + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: redundant get() call + // CHECK-MESSAGES: nullptr != ss->get(); + // CHECK-FIXES: bb = nullptr != *ss; + + 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); +} diff --git a/test/clang-tidy/readability-uppercase-literal-suffix-float16.cpp b/test/clang-tidy/readability-uppercase-literal-suffix-float16.cpp new file mode 100644 index 00000000..b2b858f9 --- /dev/null +++ b/test/clang-tidy/readability-uppercase-literal-suffix-float16.cpp @@ -0,0 +1,51 @@ +// RUN: %check_clang_tidy %s readability-uppercase-literal-suffix %t -- -- -target aarch64-linux-gnu -I %S + +#include "readability-uppercase-literal-suffix.h" + +void float16_normal_literals() { + // _Float16 + + static constexpr auto v14 = 1.f16; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v14 = 1.f16; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}} + // CHECK-FIXES: static constexpr auto v14 = 1.F16; + static_assert(is_same<decltype(v14), const _Float16>::value, ""); + static_assert(v14 == 1.F16, ""); + + static constexpr auto v15 = 1.e0f16; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v15 = 1.e0f16; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}} + // CHECK-FIXES: static constexpr auto v15 = 1.e0F16; + static_assert(is_same<decltype(v15), const _Float16>::value, ""); + static_assert(v15 == 1.F16, ""); + + static constexpr auto v16 = 1.F16; // OK. + static_assert(is_same<decltype(v16), const _Float16>::value, ""); + static_assert(v16 == 1.F16, ""); + + static constexpr auto v17 = 1.e0F16; // OK. + static_assert(is_same<decltype(v17), const _Float16>::value, ""); + static_assert(v17 == 1.F16, ""); +} + +void float16_hexadecimal_literals() { +// _Float16 + + static constexpr auto v13 = 0xfp0f16; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v13 = 0xfp0f16; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}} + // CHECK-FIXES: static constexpr auto v13 = 0xfp0F16; + static_assert(is_same<decltype(v13), const _Float16>::value, ""); + static_assert(v13 == 0xfp0F16, ""); + + static constexpr auto v14 = 0xfp0F16; // OK. + static_assert(is_same<decltype(v14), const _Float16>::value, ""); + static_assert(v14 == 0xfp0F16, ""); + +} diff --git a/test/clang-tidy/readability-uppercase-literal-suffix-floating-point.cpp b/test/clang-tidy/readability-uppercase-literal-suffix-floating-point.cpp index 4d41db7a..50e75fae 100644 --- a/test/clang-tidy/readability-uppercase-literal-suffix-floating-point.cpp +++ b/test/clang-tidy/readability-uppercase-literal-suffix-floating-point.cpp @@ -97,34 +97,6 @@ void floating_point_suffix() { static constexpr auto v13 = 1.e0Q; // OK. static_assert(is_same<decltype(v13), const __float128>::value, ""); static_assert(v13 == 1., ""); - - // _Float16 - - static constexpr auto v14 = 1.f16; - // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase - // CHECK-MESSAGES-NEXT: static constexpr auto v14 = 1.f16; - // CHECK-MESSAGES-NEXT: ^ ~ - // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}} - // CHECK-FIXES: static constexpr auto v14 = 1.F16; - static_assert(is_same<decltype(v14), const _Float16>::value, ""); - static_assert(v14 == 1.F16, ""); - - static constexpr auto v15 = 1.e0f16; - // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase - // CHECK-MESSAGES-NEXT: static constexpr auto v15 = 1.e0f16; - // CHECK-MESSAGES-NEXT: ^ ~ - // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}} - // CHECK-FIXES: static constexpr auto v15 = 1.e0F16; - static_assert(is_same<decltype(v15), const _Float16>::value, ""); - static_assert(v15 == 1.F16, ""); - - static constexpr auto v16 = 1.F16; // OK. - static_assert(is_same<decltype(v16), const _Float16>::value, ""); - static_assert(v16 == 1.F16, ""); - - static constexpr auto v17 = 1.e0F16; // OK. - static_assert(is_same<decltype(v17), const _Float16>::value, ""); - static_assert(v17 == 1.F16, ""); } void floating_point_complex_suffix() { diff --git a/test/clang-tidy/readability-uppercase-literal-suffix-hexadecimal-floating-point.cpp b/test/clang-tidy/readability-uppercase-literal-suffix-hexadecimal-floating-point.cpp index 4cc9d6d2..415c6d8e 100644 --- a/test/clang-tidy/readability-uppercase-literal-suffix-hexadecimal-floating-point.cpp +++ b/test/clang-tidy/readability-uppercase-literal-suffix-hexadecimal-floating-point.cpp @@ -93,21 +93,6 @@ void floating_point_suffix() { static constexpr auto v12 = 0xfp0Q; // OK. static_assert(is_same<decltype(v12), const __float128>::value, ""); static_assert(v12 == 0xfp0, ""); - - // _Float16 - - static constexpr auto v13 = 0xfp0f16; - // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase - // CHECK-MESSAGES-NEXT: static constexpr auto v13 = 0xfp0f16; - // CHECK-MESSAGES-NEXT: ^ ~ - // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}} - // CHECK-FIXES: static constexpr auto v13 = 0xfp0F16; - static_assert(is_same<decltype(v13), const _Float16>::value, ""); - static_assert(v13 == 0xfp0F16, ""); - - static constexpr auto v14 = 0xfp0F16; // OK. - static_assert(is_same<decltype(v14), const _Float16>::value, ""); - static_assert(v14 == 0xfp0F16, ""); } void floating_point_complex_suffix() { diff --git a/test/clang-tidy/run-clang-tidy.cpp b/test/clang-tidy/run-clang-tidy.cpp index 2207e430..31c4d681 100644 --- a/test/clang-tidy/run-clang-tidy.cpp +++ b/test/clang-tidy/run-clang-tidy.cpp @@ -1,3 +1,4 @@ +// RUN: %run_clang_tidy --help // 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 diff --git a/test/clang-tidy/static-analyzer-config.cpp b/test/clang-tidy/static-analyzer-config.cpp index 9ca87cf8..d07c0c3a 100644 --- a/test/clang-tidy/static-analyzer-config.cpp +++ b/test/clang-tidy/static-analyzer-config.cpp @@ -1,5 +1,5 @@ // REQUIRES: static-analyzer -// RUN: clang-tidy %s -checks='-*,clang-analyzer-unix.Malloc' -config='{CheckOptions: [{ key: "clang-analyzer-unix.Malloc:Optimistic", value: true}]}' -- | FileCheck %s +// RUN: clang-tidy %s -checks='-*,clang-analyzer-unix.Malloc' -config='{CheckOptions: [{ key: "clang-analyzer-unix.DynamicMemoryModeling:Optimistic", value: true}]}' -- | FileCheck %s typedef __typeof(sizeof(int)) size_t; void *malloc(size_t); void free(void *); |