| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| // RUN: %check_clang_tidy -check-suffixes=,MACROS %s readability-simplify-boolean-expr %t | ||
|
|
||
| // Ignore expressions in macros. | ||
| // RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t \ | ||
| // RUN: -- -config="{CheckOptions: {readability-simplify-boolean-expr.IgnoreMacros: true}}" \ | ||
| // RUN: -- | ||
|
|
||
| #define NEGATE(expr) !(expr) | ||
|
|
||
| bool without_macro(bool a, bool b) { | ||
| return !(!a && b); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: boolean expression can be simplified by DeMorgan's theorem | ||
| // CHECK-FIXES: return a || !b; | ||
| } | ||
|
|
||
| bool macro(bool a, bool b) { | ||
| return NEGATE(!a && b); | ||
| // CHECK-MESSAGES-MACROS: :[[@LINE-1]]:12: warning: boolean expression can be simplified by DeMorgan's theorem | ||
| // CHECK-FIXES: return NEGATE(!a && b); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| // RUN: %clang_cc1 -std=c++98 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors | ||
| // RUN: %clang_cc1 -std=c++11 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors | ||
| // RUN: %clang_cc1 -std=c++14 %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors | ||
| // RUN: %clang_cc1 -std=c++17 %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors | ||
| // RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors | ||
| // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors | ||
| // RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors | ||
|
|
||
| #if __cplusplus <= 201103L | ||
| // expected-no-diagnostics | ||
| #endif | ||
|
|
||
| namespace dr2335 { // dr2335: no drafting | ||
| // FIXME: current consensus is that the examples are well-formed. | ||
| #if __cplusplus >= 201402L | ||
| namespace ex1 { | ||
| template <class...> struct partition_indices { | ||
| static auto compute_right() {} | ||
| static constexpr auto right = compute_right; | ||
| }; | ||
| template struct partition_indices<int>; | ||
| } // namespace ex1 | ||
|
|
||
| namespace ex2 { | ||
| template <int> struct X {}; | ||
| template <class T> struct partition_indices { | ||
| static auto compute_right() { return X<I>(); } | ||
| // since-cxx14-error@-1 {{no member 'I' in 'dr2335::ex2::partition_indices<int>'; it has not yet been instantiated}} | ||
| // since-cxx14-note@#dr2335-ex2-right {{in instantiation of member function 'dr2335::ex2::partition_indices<int>::compute_right' requested here}} | ||
| // since-cxx14-note@#dr2335-ex2-inst {{in instantiation of template class 'dr2335::ex2::partition_indices<int>' requested here}} | ||
| // since-cxx14-note@#dr2335-ex2-I {{not-yet-instantiated member is declared here}} | ||
| static constexpr auto right = compute_right; // #dr2335-ex2-right | ||
| static constexpr int I = sizeof(T); // #dr2335-ex2-I | ||
| }; | ||
| template struct partition_indices<int>; // #dr2335-ex2-inst | ||
| } // namespace ex2 | ||
|
|
||
| namespace ex3 { | ||
| struct partition_indices { | ||
| static auto compute_right() {} // #dr2335-compute_right | ||
| static constexpr auto right = compute_right; // #dr2335-ex3-right | ||
| // since-cxx14-error@-1 {{function 'compute_right' with deduced return type cannot be used before it is defined}} | ||
| // since-cxx14-note@#dr2335-compute_right {{'compute_right' declared here}} | ||
| // since-cxx14-error@#dr2335-ex3-right {{declaration of variable 'right' with deduced type 'const auto' requires an initializer}} | ||
| }; | ||
| } // namespace ex3 | ||
| #endif | ||
| } // namespace dr2335 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++03, c++11, c++14, c++17 | ||
|
|
||
| // Concept helpers for the internal type traits for the fundamental types. | ||
|
|
||
| // template <class _Tp> | ||
| // concept __libcpp_integer; | ||
|
|
||
| #include <concepts> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| struct SomeObject {}; | ||
|
|
||
| enum SomeEnum {}; | ||
|
|
||
| enum class SomeScopedEnum {}; | ||
|
|
||
| // Unsigned | ||
| static_assert(std::__libcpp_integer<unsigned char>); | ||
| static_assert(std::__libcpp_integer<unsigned short int>); | ||
| static_assert(std::__libcpp_integer<unsigned int>); | ||
| static_assert(std::__libcpp_integer<unsigned long int>); | ||
| static_assert(std::__libcpp_integer<unsigned long long int>); | ||
| static_assert(std::__libcpp_integer<unsigned short int>); | ||
| #ifndef _LIBCPP_HAS_NO_INT128 | ||
| static_assert(std::__libcpp_integer<__uint128_t>); | ||
| #endif | ||
| // Signed | ||
| static_assert(std::__libcpp_integer<signed char>); | ||
| static_assert(std::__libcpp_integer<short int>); | ||
| static_assert(std::__libcpp_integer<int>); | ||
| static_assert(std::__libcpp_integer<long int>); | ||
| static_assert(std::__libcpp_integer<long long int>); | ||
| static_assert(std::__libcpp_integer<short int>); | ||
| #ifndef _LIBCPP_HAS_NO_INT128 | ||
| static_assert(std::__libcpp_integer<__int128_t>); | ||
| #endif | ||
| // Non-integer | ||
| static_assert(!std::__libcpp_integer<bool>); | ||
| static_assert(!std::__libcpp_integer<char>); | ||
| #ifndef TEST_HAS_NO_WIDE_CHARACTERS | ||
| static_assert(!std::__libcpp_integer<wchar_t>); | ||
| #endif | ||
| static_assert(!std::__libcpp_integer<char8_t>); | ||
| static_assert(!std::__libcpp_integer<char16_t>); | ||
| static_assert(!std::__libcpp_integer<char32_t>); | ||
| static_assert(!std::__libcpp_integer<float>); | ||
| static_assert(!std::__libcpp_integer<double>); | ||
| static_assert(!std::__libcpp_integer<long double>); | ||
| static_assert(!std::__libcpp_integer<void>); | ||
| static_assert(!std::__libcpp_integer<int*>); | ||
| static_assert(!std::__libcpp_integer<unsigned int*>); | ||
| static_assert(!std::__libcpp_integer<SomeObject>); | ||
| static_assert(!std::__libcpp_integer<SomeEnum>); | ||
| static_assert(!std::__libcpp_integer<SomeScopedEnum>); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++03, c++11, c++14, c++17 | ||
|
|
||
| // Concept helpers for the internal type traits for the fundamental types. | ||
|
|
||
| // template <class _Tp> | ||
| // concept __libcpp_signed_integer; | ||
|
|
||
| #include <concepts> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| struct SomeObject {}; | ||
|
|
||
| enum SomeEnum {}; | ||
|
|
||
| enum class SomeScopedEnum {}; | ||
|
|
||
| // Unsigned | ||
| static_assert(!std::__libcpp_signed_integer<unsigned char>); | ||
| static_assert(!std::__libcpp_signed_integer<unsigned short int>); | ||
| static_assert(!std::__libcpp_signed_integer<unsigned int>); | ||
| static_assert(!std::__libcpp_signed_integer<unsigned long int>); | ||
| static_assert(!std::__libcpp_signed_integer<unsigned long long int>); | ||
| static_assert(!std::__libcpp_signed_integer<unsigned short int>); | ||
| #ifndef _LIBCPP_HAS_NO_INT128 | ||
| static_assert(!std::__libcpp_signed_integer<__uint128_t>); | ||
| #endif | ||
| // Signed | ||
| static_assert(std::__libcpp_signed_integer<signed char>); | ||
| static_assert(std::__libcpp_signed_integer<short int>); | ||
| static_assert(std::__libcpp_signed_integer<int>); | ||
| static_assert(std::__libcpp_signed_integer<long int>); | ||
| static_assert(std::__libcpp_signed_integer<long long int>); | ||
| static_assert(std::__libcpp_signed_integer<short int>); | ||
| #ifndef _LIBCPP_HAS_NO_INT128 | ||
| static_assert(std::__libcpp_signed_integer<__int128_t>); | ||
| #endif | ||
| // Non-integer | ||
| static_assert(!std::__libcpp_signed_integer<bool>); | ||
| static_assert(!std::__libcpp_signed_integer<char>); | ||
| #ifndef TEST_HAS_NO_WIDE_CHARACTERS | ||
| static_assert(!std::__libcpp_signed_integer<wchar_t>); | ||
| #endif | ||
| static_assert(!std::__libcpp_signed_integer<char8_t>); | ||
| static_assert(!std::__libcpp_signed_integer<char16_t>); | ||
| static_assert(!std::__libcpp_signed_integer<char32_t>); | ||
| static_assert(!std::__libcpp_signed_integer<float>); | ||
| static_assert(!std::__libcpp_signed_integer<double>); | ||
| static_assert(!std::__libcpp_signed_integer<long double>); | ||
| static_assert(!std::__libcpp_signed_integer<void>); | ||
| static_assert(!std::__libcpp_signed_integer<int*>); | ||
| static_assert(!std::__libcpp_signed_integer<unsigned int*>); | ||
| static_assert(!std::__libcpp_signed_integer<SomeObject>); | ||
| static_assert(!std::__libcpp_signed_integer<SomeEnum>); | ||
| static_assert(!std::__libcpp_signed_integer<SomeScopedEnum>); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++03, c++11, c++14, c++17 | ||
|
|
||
| // Concept helpers for the internal type traits for the fundamental types. | ||
|
|
||
| // template <class _Tp> | ||
| // concept __libcpp_unsigned_integer; | ||
|
|
||
| #include <concepts> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| struct SomeObject {}; | ||
|
|
||
| enum SomeEnum {}; | ||
|
|
||
| enum class SomeScopedEnum {}; | ||
|
|
||
| // Unsigned | ||
| static_assert(std::__libcpp_unsigned_integer<unsigned char>); | ||
| static_assert(std::__libcpp_unsigned_integer<unsigned short int>); | ||
| static_assert(std::__libcpp_unsigned_integer<unsigned int>); | ||
| static_assert(std::__libcpp_unsigned_integer<unsigned long int>); | ||
| static_assert(std::__libcpp_unsigned_integer<unsigned long long int>); | ||
| static_assert(std::__libcpp_unsigned_integer<unsigned short int>); | ||
| #ifndef _LIBCPP_HAS_NO_INT128 | ||
| static_assert(std::__libcpp_unsigned_integer<__uint128_t>); | ||
| #endif | ||
| // Signed | ||
| static_assert(!std::__libcpp_unsigned_integer<signed char>); | ||
| static_assert(!std::__libcpp_unsigned_integer<short int>); | ||
| static_assert(!std::__libcpp_unsigned_integer<int>); | ||
| static_assert(!std::__libcpp_unsigned_integer<long int>); | ||
| static_assert(!std::__libcpp_unsigned_integer<long long int>); | ||
| static_assert(!std::__libcpp_unsigned_integer<short int>); | ||
| #ifndef _LIBCPP_HAS_NO_INT128 | ||
| static_assert(!std::__libcpp_unsigned_integer<__int128_t>); | ||
| #endif | ||
| // Non-integer | ||
| static_assert(!std::__libcpp_unsigned_integer<bool>); | ||
| static_assert(!std::__libcpp_unsigned_integer<char>); | ||
| #ifndef TEST_HAS_NO_WIDE_CHARACTERS | ||
| static_assert(!std::__libcpp_unsigned_integer<wchar_t>); | ||
| #endif | ||
| static_assert(!std::__libcpp_unsigned_integer<char8_t>); | ||
| static_assert(!std::__libcpp_unsigned_integer<char16_t>); | ||
| static_assert(!std::__libcpp_unsigned_integer<char32_t>); | ||
| static_assert(!std::__libcpp_unsigned_integer<float>); | ||
| static_assert(!std::__libcpp_unsigned_integer<double>); | ||
| static_assert(!std::__libcpp_unsigned_integer<long double>); | ||
| static_assert(!std::__libcpp_unsigned_integer<void>); | ||
| static_assert(!std::__libcpp_unsigned_integer<int*>); | ||
| static_assert(!std::__libcpp_unsigned_integer<unsigned int*>); | ||
| static_assert(!std::__libcpp_unsigned_integer<SomeObject>); | ||
| static_assert(!std::__libcpp_unsigned_integer<SomeEnum>); | ||
| static_assert(!std::__libcpp_unsigned_integer<SomeScopedEnum>); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // REQUIRES: asan | ||
| // UNSUPPORTED: c++03 | ||
|
|
||
| // Basic test if ASan annotations work for basic_string. | ||
|
|
||
| #include <string> | ||
| #include <cassert> | ||
| #include <cstdlib> | ||
|
|
||
| #include "asan_testing.h" | ||
| #include "min_allocator.h" | ||
| #include "test_iterators.h" | ||
| #include "test_macros.h" | ||
|
|
||
| extern "C" void __sanitizer_set_death_callback(void (*callback)(void)); | ||
|
|
||
| void do_exit() { exit(0); } | ||
|
|
||
| int main(int, char**) { | ||
| { | ||
| typedef cpp17_input_iterator<char*> MyInputIter; | ||
| // Should not trigger ASan. | ||
| std::basic_string<char, std::char_traits<char>, safe_allocator<char>> v; | ||
| char i[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'a', 'b', 'c', 'd', 'e', | ||
| 'f', 'g', 'h', 'i', 'j', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}; | ||
|
|
||
| v.insert(v.begin(), MyInputIter(i), MyInputIter(i + 29)); | ||
| assert(v[0] == 'a'); | ||
| assert(is_string_asan_correct(v)); | ||
| } | ||
|
|
||
| __sanitizer_set_death_callback(do_exit); | ||
| { | ||
| using T = char; | ||
| using C = std::basic_string<T, std::char_traits<T>, safe_allocator<T>>; | ||
| const T t[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'a', 'b', 'c', 'd', 'e', | ||
| 'f', 'g', 'h', 'i', 'j', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}; | ||
| C c(std::begin(t), std::end(t)); | ||
| assert(is_string_asan_correct(c)); | ||
| assert(__sanitizer_verify_contiguous_container(c.data(), c.data() + c.size() + 1, c.data() + c.capacity() + 1) != | ||
| 0); | ||
| T foo = c[c.size() + 1]; // should trigger ASAN and call do_exit(). | ||
| assert(false); // if we got here, ASAN didn't trigger | ||
| ((void)foo); | ||
|
|
||
| return 0; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // REQUIRES: asan | ||
| // UNSUPPORTED: c++03 | ||
|
|
||
| // Test based on: https://bugs.chromium.org/p/chromium/issues/detail?id=1419798#c5 | ||
| // Some allocators during deallocation may not call destructors and just reuse memory. | ||
| // In those situations, one may want to deactivate annotations for a specific allocator. | ||
| // It's possible with __asan_annotate_container_with_allocator template class. | ||
| // This test confirms that those allocators work after turning off annotations. | ||
| // | ||
| // A context to this test is a situations when memory is repurposed and destructors are not called. | ||
| // Related issue: https://github.com/llvm/llvm-project/issues/60384 | ||
| // | ||
| // That issue appeared in the past and was addressed here: https://reviews.llvm.org/D145628 | ||
| // | ||
| // There was also a discussion, if it's UB. | ||
| // Related discussion: https://reviews.llvm.org/D136765#4155262 | ||
| // Related notes: https://eel.is/c++draft/basic.life#6 | ||
| // Probably it's no longer UB due a change in CWG2523. | ||
| // https://cplusplus.github.io/CWG/issues/2523.html | ||
| // | ||
| // Therefore we make sure that it works that way, also because people rely on this behavior. | ||
| // Annotations are turned off only, if a user explicitly turns off annotations for a specific allocator. | ||
|
|
||
| #include <assert.h> | ||
| #include <stdlib.h> | ||
| #include <string> | ||
| #include <new> | ||
|
|
||
| // Allocator with pre-allocated (with malloc in constructor) buffers. | ||
| // Memory may be freed without calling destructors. | ||
| struct reuse_allocator { | ||
| static size_t const N = 100; | ||
| reuse_allocator() { | ||
| for (size_t i = 0; i < N; ++i) | ||
| __buffers[i] = malloc(8 * 1024); | ||
| } | ||
| ~reuse_allocator() { | ||
| for (size_t i = 0; i < N; ++i) | ||
| free(__buffers[i]); | ||
| } | ||
| void* alloc() { | ||
| assert(__next_id < N); | ||
| return __buffers[__next_id++]; | ||
| } | ||
| void reset() { __next_id = 0; } | ||
| void* __buffers[N]; | ||
| size_t __next_id = 0; | ||
| } reuse_buffers; | ||
|
|
||
| template <typename T> | ||
| struct user_allocator { | ||
| using value_type = T; | ||
| user_allocator() = default; | ||
| template <class U> | ||
| user_allocator(user_allocator<U>) {} | ||
| friend bool operator==(user_allocator, user_allocator) { return true; } | ||
| friend bool operator!=(user_allocator x, user_allocator y) { return !(x == y); } | ||
|
|
||
| T* allocate(size_t n) { | ||
| if (n * sizeof(T) > 8 * 1024) | ||
| throw std::bad_array_new_length(); | ||
| return (T*)reuse_buffers.alloc(); | ||
| } | ||
| void deallocate(T*, size_t) noexcept {} | ||
| }; | ||
|
|
||
| // Turn off annotations for user_allocator: | ||
| template <class T> | ||
| struct std::__asan_annotate_container_with_allocator<user_allocator<T>> { | ||
| static bool const value = false; | ||
| }; | ||
|
|
||
| int main(int, char**) { | ||
| using S = std::basic_string<char, std::char_traits<char>, user_allocator<char>>; | ||
|
|
||
| { | ||
| // Create a string with a buffer from reuse allocator object: | ||
| S* s = new (reuse_buffers.alloc()) S(); | ||
| // Use string, so it's poisoned, if container annotations for that allocator are not turned off: | ||
| for (int i = 0; i < 40; i++) | ||
| s->push_back('a'); | ||
| } | ||
| // Reset the state of the allocator, don't call destructors, allow memory to be reused: | ||
| reuse_buffers.reset(); | ||
| { | ||
| // Create a next string with the same allocator, so the same buffer due to the reset: | ||
| S s; | ||
| // Use memory inside the string again, if it's poisoned, an error will be raised: | ||
| for (int i = 0; i < 60; i++) | ||
| s.push_back('a'); | ||
| } | ||
|
|
||
| return 0; | ||
| } |