Mercurial > hg > CbC > CbC_llvm
view clang/test/Analysis/uninit-structured-binding-tuple.cpp @ 236:c4bab56944e8 llvm-original
LLVM 16
author | kono |
---|---|
date | Wed, 09 Nov 2022 17:45:10 +0900 |
parents | |
children |
line wrap: on
line source
// RUN: %clang_analyze_cc1 -Wno-ignored-reference-qualifiers -analyzer-checker=core,debug.ExprInspection -std=c++17 -verify %s #include "Inputs/system-header-simulator-cxx.h" void clang_analyzer_eval(bool); namespace std { template <typename T> struct tuple_size { }; template <std::size_t I, typename T> struct tuple_element { }; // The std::pair in our system header simulator is not tuple-like, so a tuple-like mock is created here template <typename T1, typename T2> struct mock_pair { T1 first; T2 second; }; template <typename T1, typename T2> struct tuple_size<mock_pair<T1, T2>> { static const std::size_t value = 2; }; template <typename T1, typename T2> struct tuple_element<0, mock_pair<T1, T2>> { using type = T1; }; template <typename T1, typename T2> struct tuple_element<1, mock_pair<T1, T2>> { using type = T2; }; template <std::size_t I, class T> using tuple_element_t = typename tuple_element<I, T>::type; template <std::size_t I, class T1, class T2> constexpr std::tuple_element_t<I, std::mock_pair<T1, T2>> & get(std::mock_pair<T1, T2> &p) noexcept { if (I == 0) return p.first; else return p.second; } template <std::size_t I, class T1, class T2> constexpr const std::tuple_element_t<I, std::mock_pair<T1, T2>> & get(const std::mock_pair<T1, T2> &p) noexcept { if (I == 0) return p.first; else return p.second; } template <std::size_t I, class T1, class T2> constexpr std::tuple_element_t<I, std::mock_pair<T1, T2>> && get(std::mock_pair<T1, T2> &&p) noexcept { if (I == 0) return static_cast<std::tuple_element_t<I, std::mock_pair<T1, T2>> &&>(p.first); else return static_cast<std::tuple_element_t<I, std::mock_pair<T1, T2>> &&>(p.second); } template <std::size_t I, class T1, class T2> constexpr const std::tuple_element_t<I, std::mock_pair<T1, T2>> && get(const std::mock_pair<T1, T2> &&p) noexcept { if (I == 0) return static_cast<std::tuple_element_t<I, std::mock_pair<T1, T2>> &&>(p.first); else return static_cast<std::tuple_element_t<I, std::mock_pair<T1, T2>> &&>(p.second); } } // namespace std // A utility that generates a tuple-like struct with 2 fields // of the same type. The fields are 'first' and 'second' #define GENERATE_TUPLE_LIKE_STRUCT(name, element_type) \ struct name { \ element_type first; \ element_type second; \ }; \ \ namespace std { \ template <> \ struct tuple_size<name> { \ static const std::size_t value = 2; \ }; \ \ template <std::size_t I> \ struct tuple_element<I, name> { \ using type = element_type; \ }; \ } void non_user_defined_by_value(void) { std::mock_pair<int, int> p = {1, 2}; auto [u, v] = p; clang_analyzer_eval(u == 1); // expected-warning{{TRUE}} clang_analyzer_eval(v == 2); // expected-warning{{TRUE}} int x = u; u = 10; int y = u; clang_analyzer_eval(x == 1); // expected-warning{{TRUE}} clang_analyzer_eval(u == 10); // expected-warning{{TRUE}} clang_analyzer_eval(y == 10); // expected-warning{{TRUE}} clang_analyzer_eval(p.first == 1); // expected-warning{{TRUE}} p.first = 5; clang_analyzer_eval(u == 10); // expected-warning{{TRUE}} } void non_user_defined_by_lref(void) { std::mock_pair<int, int> p = {1, 2}; auto &[u, v] = p; int x = u; u = 10; int y = u; clang_analyzer_eval(x == 1); // expected-warning{{TRUE}} clang_analyzer_eval(u == 10); // expected-warning{{TRUE}} clang_analyzer_eval(y == 10); // expected-warning{{TRUE}} clang_analyzer_eval(p.first == 10); // expected-warning{{TRUE}} clang_analyzer_eval(v == 2); // expected-warning{{TRUE}} clang_analyzer_eval(p.second == 2); // expected-warning{{TRUE}} p.first = 5; clang_analyzer_eval(u == 5); // expected-warning{{TRUE}} } void non_user_defined_by_rref(void) { std::mock_pair<int, int> p = {1, 2}; auto &&[u, v] = p; int x = u; u = 10; int y = u; clang_analyzer_eval(x == 1); // expected-warning{{TRUE}} clang_analyzer_eval(u == 10); // expected-warning{{TRUE}} clang_analyzer_eval(y == 10); // expected-warning{{TRUE}} clang_analyzer_eval(p.first == 10); // expected-warning{{TRUE}} clang_analyzer_eval(v == 2); // expected-warning{{TRUE}} clang_analyzer_eval(p.second == 2); // expected-warning{{TRUE}} p.first = 5; clang_analyzer_eval(u == 5); // expected-warning{{TRUE}} } GENERATE_TUPLE_LIKE_STRUCT(Test, int); template <std::size_t I> int get(Test t) { if (I == 0) { t.second = 10; return t.first; } else { t.first = 20; return t.second; } } void user_defined_get_val_by_val(void) { Test p{1, 2}; auto [u, v] = p; clang_analyzer_eval(u == 1); // expected-warning{{TRUE}} u = 8; int x = u; clang_analyzer_eval(x == 8); // expected-warning{{TRUE}} clang_analyzer_eval(u == 8); // expected-warning{{TRUE}} clang_analyzer_eval(v == 2); // expected-warning{{TRUE}} clang_analyzer_eval(p.first == 1); // expected-warning{{TRUE}} clang_analyzer_eval(p.second == 2); // expected-warning{{TRUE}} p.first = 5; clang_analyzer_eval(u == 8); // expected-warning{{TRUE}} clang_analyzer_eval(p.first == 5); // expected-warning{{TRUE}} } GENERATE_TUPLE_LIKE_STRUCT(Test2, int); template <std::size_t I> int get(Test2 &t) { if (I == 0) { t.second = 10; return t.first; } else { t.first = 20; return t.second; } } void user_defined_get_val_by_lref(void) { Test2 p{1, 2}; auto &[u, v] = p; clang_analyzer_eval(u == 1); // expected-warning{{TRUE}} clang_analyzer_eval(v == 10); // expected-warning{{TRUE}} u = 8; int x = u; clang_analyzer_eval(x == 8); // expected-warning{{TRUE}} clang_analyzer_eval(u == 8); // expected-warning{{TRUE}} clang_analyzer_eval(v == 10); // expected-warning{{TRUE}} clang_analyzer_eval(p.first == 20); // expected-warning{{TRUE}} clang_analyzer_eval(p.second == 10); // expected-warning{{TRUE}} p.first = 5; clang_analyzer_eval(u == 8); // expected-warning{{TRUE}} clang_analyzer_eval(p.first == 5); // expected-warning{{TRUE}} } void user_defined_get_val_by_rref(void) { Test2 p{1, 2}; auto &&[u, v] = p; clang_analyzer_eval(u == 1); // expected-warning{{TRUE}} clang_analyzer_eval(v == 10); // expected-warning{{TRUE}} u = 8; int x = u; clang_analyzer_eval(x == 8); // expected-warning{{TRUE}} clang_analyzer_eval(u == 8); // expected-warning{{TRUE}} clang_analyzer_eval(v == 10); // expected-warning{{TRUE}} clang_analyzer_eval(p.first == 20); // expected-warning{{TRUE}} clang_analyzer_eval(p.second == 10); // expected-warning{{TRUE}} p.first = 5; clang_analyzer_eval(u == 8); // expected-warning{{TRUE}} clang_analyzer_eval(p.first == 5); // expected-warning{{TRUE}} } struct MixedTest { int x; char &&y; int &z; }; namespace std { template <> struct tuple_size<MixedTest> { static const std::size_t value = 3; }; template <> struct tuple_element<0, MixedTest> { using type = int; }; template <> struct tuple_element<1, MixedTest> { using type = char &&; }; template <> struct tuple_element<2, MixedTest> { using type = int &; }; template <std::size_t I, typename T> using tuple_element_t = typename tuple_element<I, T>::type; } // namespace std template <std::size_t I> const std::tuple_element_t<I, MixedTest> &get(const MixedTest &t) {} template <> const std::tuple_element_t<0, MixedTest> &get<0>(const MixedTest &t) { return t.x; } template <> const std::tuple_element_t<1, MixedTest> &get<1>(const MixedTest &t) { return t.y; } template <> const std::tuple_element_t<2, MixedTest> &get<2>(const MixedTest &t) { return t.z; } void mixed_type_cref(void) { int x = 1; char y = 2; int z = 3; MixedTest m{x, std::move(y), z}; const auto &[a, b, c] = m; clang_analyzer_eval(a == 1); // expected-warning{{TRUE}} clang_analyzer_eval(b == 2); // expected-warning{{TRUE}} clang_analyzer_eval(c == 3); // expected-warning{{TRUE}} clang_analyzer_eval(a == 1); // expected-warning{{TRUE}} clang_analyzer_eval(b == 2); // expected-warning{{TRUE}} clang_analyzer_eval(c == 3); // expected-warning{{TRUE}} } template <std::size_t I> std::tuple_element_t<I, MixedTest> &get(MixedTest &t) {} template <> std::tuple_element_t<0, MixedTest> &get<0>(MixedTest &t) { return t.x; } template <> std::tuple_element_t<1, MixedTest> &get<1>(MixedTest &t) { return t.y; } template <> std::tuple_element_t<2, MixedTest> &get<2>(MixedTest &t) { return t.z; } void mixed_type_lref(void) { int x = 1; char y = 2; int z = 3; MixedTest m{x, std::move(y), z}; auto &[a, b, c] = m; a = 4; b = 5; c = 6; clang_analyzer_eval(get<0>(m) == 4); // expected-warning{{TRUE}} clang_analyzer_eval(get<1>(m) == 5); // expected-warning{{TRUE}} clang_analyzer_eval(get<2>(m) == 6); // expected-warning{{TRUE}} clang_analyzer_eval(get<0>(m) == 4); // expected-warning{{TRUE}} clang_analyzer_eval(get<1>(m) == 5); // expected-warning{{TRUE}} clang_analyzer_eval(get<2>(m) == 6); // expected-warning{{TRUE}} clang_analyzer_eval(z == 6); // expected-warning{{TRUE}} } void mixed_type_rref(void) { int x = 1; char y = 2; int z = 3; MixedTest m{x, std::move(y), z}; auto &&[a, b, c] = m; a = 4; b = 5; c = 6; clang_analyzer_eval(get<0>(m) == 4); // expected-warning{{TRUE}} clang_analyzer_eval(get<1>(m) == 5); // expected-warning{{TRUE}} clang_analyzer_eval(get<2>(m) == 6); // expected-warning{{TRUE}} clang_analyzer_eval(get<0>(m) == 4); // expected-warning{{TRUE}} clang_analyzer_eval(get<1>(m) == 5); // expected-warning{{TRUE}} clang_analyzer_eval(get<2>(m) == 6); // expected-warning{{TRUE}} clang_analyzer_eval(z == 6); // expected-warning{{TRUE}} } void ref_val(void) { int i = 1, j = 2; std::mock_pair<int &, int &> p{i, j}; auto [a, b] = p; clang_analyzer_eval(a == 1); // expected-warning{{TRUE}} clang_analyzer_eval(b == 2); // expected-warning{{TRUE}} a = 3; b = 4; clang_analyzer_eval(p.first == 3); // expected-warning{{TRUE}} clang_analyzer_eval(p.second == 4); // expected-warning{{TRUE}} clang_analyzer_eval(a == 3); // expected-warning{{TRUE}} clang_analyzer_eval(b == 4); // expected-warning{{TRUE}} } struct Small_Non_POD { int i; int j; }; void non_user_defined_small_non_pod_by_value(void) { std::mock_pair<Small_Non_POD, Small_Non_POD> p{{1, 2}, {1, 2}}; auto [a, b] = p; clang_analyzer_eval(a.i == 1); // expected-warning{{TRUE}} clang_analyzer_eval(a.j == 2); // expected-warning{{TRUE}} clang_analyzer_eval(b.i == 1); // expected-warning{{TRUE}} clang_analyzer_eval(b.j == 2); // expected-warning{{TRUE}} a.i = 3; a.j = 4; b.i = 5; b.j = 6; clang_analyzer_eval(a.i == 3); // expected-warning{{TRUE}} clang_analyzer_eval(a.j == 4); // expected-warning{{TRUE}} clang_analyzer_eval(b.i == 5); // expected-warning{{TRUE}} clang_analyzer_eval(b.j == 6); // expected-warning{{TRUE}} clang_analyzer_eval(p.first.i == 1); // expected-warning{{TRUE}} clang_analyzer_eval(p.first.j == 2); // expected-warning{{TRUE}} clang_analyzer_eval(p.second.i == 1); // expected-warning{{TRUE}} clang_analyzer_eval(p.second.j == 2); // expected-warning{{TRUE}} } void non_user_defined_small_non_pod_by_lref(void) { std::mock_pair<Small_Non_POD, Small_Non_POD> p{{1, 2}, {1, 2}}; auto &[a, b] = p; clang_analyzer_eval(a.i == 1); // expected-warning{{TRUE}} clang_analyzer_eval(a.j == 2); // expected-warning{{TRUE}} clang_analyzer_eval(b.i == 1); // expected-warning{{TRUE}} clang_analyzer_eval(b.j == 2); // expected-warning{{TRUE}} a.i = 3; a.j = 4; b.i = 5; b.j = 6; clang_analyzer_eval(a.i == 3); // expected-warning{{TRUE}} clang_analyzer_eval(a.j == 4); // expected-warning{{TRUE}} clang_analyzer_eval(b.i == 5); // expected-warning{{TRUE}} clang_analyzer_eval(b.j == 6); // expected-warning{{TRUE}} clang_analyzer_eval(p.first.i == 3); // expected-warning{{TRUE}} clang_analyzer_eval(p.first.j == 4); // expected-warning{{TRUE}} clang_analyzer_eval(p.second.i == 5); // expected-warning{{TRUE}} clang_analyzer_eval(p.second.j == 6); // expected-warning{{TRUE}} } void non_user_defined_small_non_pod_by_rref(void) { std::mock_pair<Small_Non_POD, Small_Non_POD> p{{1, 2}, {1, 2}}; auto &&[a, b] = p; clang_analyzer_eval(a.i == 1); // expected-warning{{TRUE}} clang_analyzer_eval(a.j == 2); // expected-warning{{TRUE}} clang_analyzer_eval(b.i == 1); // expected-warning{{TRUE}} clang_analyzer_eval(b.j == 2); // expected-warning{{TRUE}} a.i = 3; a.j = 4; b.i = 5; b.j = 6; clang_analyzer_eval(a.i == 3); // expected-warning{{TRUE}} clang_analyzer_eval(a.j == 4); // expected-warning{{TRUE}} clang_analyzer_eval(b.i == 5); // expected-warning{{TRUE}} clang_analyzer_eval(b.j == 6); // expected-warning{{TRUE}} clang_analyzer_eval(p.first.i == 3); // expected-warning{{TRUE}} clang_analyzer_eval(p.first.j == 4); // expected-warning{{TRUE}} clang_analyzer_eval(p.second.i == 5); // expected-warning{{TRUE}} clang_analyzer_eval(p.second.j == 6); // expected-warning{{TRUE}} } GENERATE_TUPLE_LIKE_STRUCT(Uninit, int); template <std::size_t I> int &get(Uninit &&t) { if (I == 0) { return t.first; } else { return t.second; } } void uninit_a(void) { Uninit u; auto [a, b] = u; int x = a; // expected-warning{{Assigned value is garbage or undefined}} } void uninit_b(void) { Uninit u; auto [a, b] = u; int x = b; // expected-warning{{Assigned value is garbage or undefined}} } GENERATE_TUPLE_LIKE_STRUCT(UninitCall, int); template <std::size_t I> int get(UninitCall t) { if (I == 0) { return t.first; } else { return t.second; } } void uninit_call(void) { UninitCall u; auto [a, b] = u; int x = a; // expected-warning@543{{Undefined or garbage value returned to caller}} } void syntax_2() { std::mock_pair<Small_Non_POD, Small_Non_POD> p{{1, 2}, {3, 4}}; auto [a, b]{p}; clang_analyzer_eval(a.i == 1); // expected-warning{{TRUE}} clang_analyzer_eval(a.j == 2); // expected-warning{{TRUE}} clang_analyzer_eval(b.i == 3); // expected-warning{{TRUE}} clang_analyzer_eval(b.j == 4); // expected-warning{{TRUE}} } void syntax_3() { std::mock_pair<Small_Non_POD, Small_Non_POD> p{{1, 2}, {3, 4}}; auto [a, b](p); clang_analyzer_eval(a.i == 1); // expected-warning{{TRUE}} clang_analyzer_eval(a.j == 2); // expected-warning{{TRUE}} clang_analyzer_eval(b.i == 3); // expected-warning{{TRUE}} clang_analyzer_eval(b.j == 4); // expected-warning{{TRUE}} }