Files
RedBear-OS/local/recipes/dev/libclc/source/clang/test/Parser/cxx1z-fold-expressions.cpp
T
vasilito cb424d7448 build: static patch-sanity linter (shift-left the malformed-patch class)
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).
2026-08-01 05:13:02 +03:00

97 lines
4.9 KiB
C++

// RUN: %clang_cc1 -std=c++1z -verify %s
template<typename ...T> constexpr auto sum(T ...t) { return (... + t); }
template<typename ...T> constexpr auto product(T ...t) { return (t * ...); }
template<typename ...T> constexpr auto all(T ...t) { return (true && ... && t); }
template<typename ...T> constexpr auto all2(T ...t) { return (t && ... && true); }
int k1 = (1 + ... + 2); // expected-error {{does not contain any unexpanded parameter packs}}
int k2 = (1 + ...); // expected-error {{does not contain any unexpanded parameter packs}}
int k3 = (... + 2); // expected-error {{does not contain any unexpanded parameter packs}}
struct A { A(int); friend A operator+(A, A); A operator-(A); A operator()(A); A operator[](A); };
A operator*(A, A);
template<int ...N> void bad1() { (N + ... + N); } // expected-error {{unexpanded parameter packs in both operands}}
// FIXME: it would be reasonable to support this as an extension.
template<int ...N> void bad2() { (2 * N + ... + 1); } // expected-error {{expression not permitted as operand}}
template<int ...N> void bad3() { (2 + N * ... * 1); } // expected-error {{expression not permitted as operand}}
template<int ...N, int ...M> void bad4(int (&...x)[N]) { (N + M * ... * 1); } // expected-error {{expression not permitted as operand}}
template<int ...N, int ...M> void fixed4(int (&...x)[N]) { ((N + M) * ... * 1); }
template<typename ...T> void bad4a(T ...t) { (t * 2 + ... + 1); } // expected-error {{expression not permitted as operand}}
template<int ...N> void bad4b() { (A(0) + A(N) + ...); } // expected-error {{expression not permitted as operand}}
template<int ...N> void bad4c() { (A(0) - A(N) + ...); } // expected-error {{expression not permitted as operand}}
template<int ...N> void bad4d() { (A(0)(A(0)) + ... + A(0)[A(N)]); }
// Parens are mandatory.
template<int ...N> void bad5() { N + ...; } // expected-error {{expected expression}} expected-error +{{}}
template<int ...N> void bad6() { ... + N; } // expected-error {{expected expression}}
template<int ...N> void bad7() { N + ... + N; } // expected-error {{expected expression}} expected-error +{{}}
// Must have a fold-operator in the relevant places.
template<int ...N> int bad8() { return (N + ... * 3); } // expected-error {{operators in fold expression must be the same}}
template<int ...N> int bad9() { return (3 + ... * N); } // expected-error {{operators in fold expression must be the same}}
template<int ...N> int bad10() { return (3 ? ... : N); } // expected-error +{{}} expected-note {{to match}}
template<int ...N> int bad11() { return (N + ... 0); } // expected-error {{expected a foldable binary operator}} expected-error {{expected expression}}
template<int ...N> int bad12() { return (... N); } // expected-error {{expected expression}}
template<typename ...T> void as_operand_of_cast(int a, T ...t) {
return
(int)(a + ... + undeclared_junk) + // expected-error {{undeclared}}
(int)(t + ... + undeclared_junk) + // expected-error {{undeclared}}
(int)(... + undeclared_junk) + // expected-error {{undeclared}}
(int)(undeclared_junk + ...) + // expected-error {{undeclared}}
(int)(a + ...) + // expected-error {{does not contain any unexpanded}}
(int)(a, ...) + // expected-error {{does not contain any unexpanded}}
(int)(..., a) + // expected-error {{does not contain any unexpanded}}
(int)(a, ..., undeclared_junk) + // expected-error {{undeclared}}
(int)(t, ...) +
(int)(..., t) +
(int)(t, ..., a);
}
// fold-operator can be '>' or '>>'.
template <int... N> constexpr bool greaterThan() { return (N > ...); }
// expected-error@-1 {{comparison in fold expression}}
template <int... N> constexpr int rightShift() { return (N >> ...); }
static_assert(greaterThan<2, 1>()); // expected-note {{in instantiation}}
static_assert(rightShift<10, 1>() == 5);
template <auto V> constexpr auto Identity = V;
// Support fold operators within templates.
template <int... N> constexpr int nestedFoldOperator() {
return Identity<(Identity<0> >> ... >> N)> +
Identity<(N >> ... >> Identity<0>)>;
}
static_assert(nestedFoldOperator<3, 1>() == 1);
// A fold-expression is a primary-expression.
template <typename T, typename... Ts>
constexpr auto castSum(Ts... Args) {
return (T)(Args + ...).Value; // expected-error{{member reference base type 'int' is not a structure or union}}
}
template <typename... Ts>
constexpr auto simpleSum(Ts... Args) {
return (... + Args).Value; // expected-error{{member reference base type 'int' is not a structure or union}}
}
void prim() {
castSum<int>(1, 2);
// expected-note@-1{{in instantiation of function template specialization}}
simpleSum(1, 2);
// expected-note@-1{{in instantiation of function template specialization}}
struct Number {
int Value;
constexpr Number operator+(Number Rhs) const { return {Rhs.Value + Value}; }
};
static_assert(castSum<long>(Number{1}, Number{2}) == 3);
static_assert(simpleSum(Number{1}, Number{2}) == 3);
}