cb424d7448
verify-patch-sanity.py validates every active recipe .patch has internally- consistent hunk line counts — catching the 'malformed patch at line N' failure at commit/CI/preflight time instead of hours into a cook. This cycle hit that class three times (qtwaylandscanner, sddm, xwayland), each only discovered when cookbook tried to apply the patch. Running it across the repo found 29 latent malformed patches (validated against GNU patch: e.g. relibc/P3-sysv-ipc reproduces 'malformed patch at line 22'). They were harmless only because they sit in vendored recipes (baked, not re- applied) — but would fail on any version-bump re-derivation. --fix recounts the hunk headers (body untouched) and repaired all 29. Wired into build-preflight.sh (Phase 1.0D) and redbear-ci.yml, with a unit test (test-patch-sanity.sh). Skips archived/legacy trees and unvalidatable formats (empty placeholders, bare-@@ git hunks).
581 lines
15 KiB
C++
581 lines
15 KiB
C++
// 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 uninitialized}}
|
|
}
|
|
|
|
void uninit_b(void) {
|
|
Uninit u;
|
|
|
|
auto [a, b] = u;
|
|
|
|
int x = b; // expected-warning{{Assigned value is uninitialized}}
|
|
}
|
|
|
|
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}}
|
|
}
|