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).
247 lines
8.6 KiB
C
247 lines
8.6 KiB
C
// RUN: %clang_cc1 %s -verify=expected,access -fsyntax-only
|
|
// RUN: %clang_cc1 %s -std=c2x -verify=expected,access -fsyntax-only
|
|
// RUN: %clang_cc1 %s -std=c2x -pedantic -verify=expected,access -fsyntax-only
|
|
// RUN: %clang_cc1 %s -verify -fsyntax-only -Wno-atomic-access
|
|
// RUN: %clang_cc1 %s -verify=expected,access -fsyntax-only -fexperimental-new-constant-interpreter
|
|
// RUN: %clang_cc1 %s -std=c2x -verify=expected,access -fsyntax-only -fexperimental-new-constant-interpreter
|
|
// RUN: %clang_cc1 %s -std=c2x -pedantic -verify=expected,access -fsyntax-only -fexperimental-new-constant-interpreter
|
|
// RUN: %clang_cc1 %s -verify -fsyntax-only -Wno-atomic-access -fexperimental-new-constant-interpreter
|
|
|
|
|
|
_Atomic(unsigned int) data1;
|
|
int _Atomic data2;
|
|
|
|
// Shift operations
|
|
|
|
int func_01 (int x) {
|
|
return data1 << x;
|
|
}
|
|
|
|
int func_02 (int x) {
|
|
return x << data1;
|
|
}
|
|
|
|
int func_03 (int x) {
|
|
return data2 << x;
|
|
}
|
|
|
|
int func_04 (int x) {
|
|
return x << data2;
|
|
}
|
|
|
|
int func_05 (void) {
|
|
return data2 << data1;
|
|
}
|
|
|
|
int func_06 (void) {
|
|
return data1 << data2;
|
|
}
|
|
|
|
void func_07 (int x) {
|
|
data1 <<= x;
|
|
}
|
|
|
|
void func_08 (int x) {
|
|
data2 <<= x;
|
|
}
|
|
|
|
void func_09 (int* xp) {
|
|
*xp <<= data1;
|
|
}
|
|
|
|
void func_10 (int* xp) {
|
|
*xp <<= data2;
|
|
}
|
|
|
|
int func_11 (int x) {
|
|
return data1 == x;
|
|
}
|
|
|
|
int func_12 (void) {
|
|
return data1 < data2;
|
|
}
|
|
|
|
int func_13 (int x, unsigned y) {
|
|
return x ? data1 : y;
|
|
}
|
|
|
|
int func_14 (void) {
|
|
return data1 == 0;
|
|
}
|
|
|
|
void func_15(void) {
|
|
// Ensure that the result of an assignment expression properly strips the
|
|
// _Atomic qualifier; Issue 48742.
|
|
_Atomic int x;
|
|
int y = (x = 2);
|
|
int z = (int)(x = 2);
|
|
y = (x = 2);
|
|
z = (int)(x = 2);
|
|
y = (x += 2);
|
|
|
|
_Static_assert(__builtin_types_compatible_p(__typeof__(x = 2), int), "incorrect");
|
|
_Static_assert(__builtin_types_compatible_p(__typeof__(x += 2), int), "incorrect");
|
|
}
|
|
|
|
// Ensure that member access of an atomic structure or union type is properly
|
|
// diagnosed as being undefined behavior; Issue 54563.
|
|
void func_16(void) {
|
|
// LHS member access.
|
|
_Atomic struct { int val; } x, *xp;
|
|
x.val = 12; // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
|
|
xp->val = 12; // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
|
|
|
|
_Atomic union {
|
|
int ival;
|
|
float fval;
|
|
} y, *yp;
|
|
y.ival = 12; // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
|
|
yp->fval = 1.2f; // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
|
|
|
|
// RHS member access.
|
|
int xval = x.val; // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
|
|
xval = xp->val; // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
|
|
int yval = y.ival; // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
|
|
yval = yp->ival; // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
|
|
|
|
// Using the type specifier instead of the type qualifier.
|
|
_Atomic(struct { int val; }) z;
|
|
z.val = 12; // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
|
|
int zval = z.val; // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
|
|
|
|
// Don't diagnose in an unevaluated context, however.
|
|
(void)sizeof(x.val);
|
|
(void)sizeof(xp->val);
|
|
(void)sizeof(y.ival);
|
|
(void)sizeof(yp->ival);
|
|
|
|
// Also, do not diagnose in unreachable code paths.
|
|
{
|
|
if (0) {
|
|
x.val = 12;
|
|
xp->val = 12;
|
|
(void)y.ival;
|
|
(void)yp->ival;
|
|
}
|
|
|
|
return;
|
|
|
|
x.val = 12;
|
|
xp->val = 12;
|
|
(void)y.ival;
|
|
(void)yp->ival;
|
|
}
|
|
}
|
|
|
|
// Ensure that we correctly implement assignment constraints from C2x 6.5.16.1.
|
|
void func_17(void) {
|
|
// The left operand has atomic ... arithmetic type, and the right operand has
|
|
// arithmetic type;
|
|
_Atomic int i = 0;
|
|
_Atomic float f = 0.0f;
|
|
|
|
// the left operand has an atomic ... version of a structure or union type
|
|
// compatible with the type of the right operand;
|
|
struct S { int i; } non_atomic_s;
|
|
_Atomic struct S s = non_atomic_s;
|
|
|
|
union U { int i; float f; } non_atomic_u;
|
|
_Atomic union U u = non_atomic_u;
|
|
|
|
// the left operand has atomic ... pointer type, and (considering the type
|
|
// the left operand would have after lvalue conversion) both operands are
|
|
// pointers to qualified or unqualified versions of compatible types, and the
|
|
// type pointed to by the left operand has all the qualifiers of the type
|
|
// pointed to by the right operand;
|
|
const int *cip = 0;
|
|
volatile const int *vcip = 0;
|
|
const int * const cicp = 0;
|
|
_Atomic(const int *) acip = cip;
|
|
_Atomic(const int *) bad_acip = vcip; // expected-warning {{initializing '_Atomic(const int *)' with an expression of type 'const volatile int *' discards qualifiers}}
|
|
_Atomic(const int *) acip2 = cicp;
|
|
_Atomic(int *) aip = &i; // expected-warning {{incompatible pointer types initializing '_Atomic(int *)' with an expression of type '_Atomic(int) *'}} \
|
|
|
|
// the left operand has atomic ... pointer type, and (considering the type
|
|
// the left operand would have after lvalue conversion) one operand is a
|
|
// pointer to an object type, and the other is a pointer to a qualified or
|
|
// unqualified version of void, and the type pointed to by the left operand
|
|
// has all the qualifiers of the type pointed to by the right operand;
|
|
const void *cvp = 0;
|
|
_Atomic(const int *) acip3 = cvp;
|
|
_Atomic(const void *) acvip = cip;
|
|
_Atomic(const int *) acip4 = vcip; // expected-warning {{initializing '_Atomic(const int *)' with an expression of type 'const volatile int *' discards qualifiers}}
|
|
_Atomic(const void *) acvip2 = vcip; // expected-warning {{initializing '_Atomic(const void *)' with an expression of type 'const volatile int *' discards qualifiers}}
|
|
_Atomic(const int *) acip5 = cicp;
|
|
_Atomic(const void *) acvip3 = cicp;
|
|
|
|
#if __STDC_VERSION__ >= 202311L
|
|
// the left operand has an atomic ... version of the nullptr_t type and the
|
|
// right operand is a null pointer constant or its type is nullptr_t
|
|
typedef typeof(nullptr) nullptr_t;
|
|
nullptr_t n;
|
|
_Atomic nullptr_t cn2 = n;
|
|
_Atomic nullptr_t cn3 = nullptr;
|
|
#endif // __STDC_VERSION__ >= 202311L
|
|
|
|
// the left operand is an atomic ... pointer, and the right operand is a null
|
|
// pointer constant or its type is nullptr_t;
|
|
_Atomic(int *) aip2 = 0;
|
|
#if __STDC_VERSION__ >= 202311L
|
|
_Atomic(int *) ip2 = n;
|
|
_Atomic(int *) ip3 = nullptr;
|
|
_Atomic(const int *) ip4 = nullptr;
|
|
#endif // __STDC_VERSION__ >= 202311L
|
|
}
|
|
|
|
// Ensure that the assignment constraints also work at file scope.
|
|
_Atomic int ai = 0;
|
|
_Atomic float af = 0.0f;
|
|
_Atomic(int *) aip1 = 0;
|
|
|
|
struct S { int a; } non_atomic_s;
|
|
_Atomic struct S as = non_atomic_s; // expected-error {{initializer element is not a compile-time constant}}
|
|
|
|
const int *cip = 0;
|
|
_Atomic(const int *) acip1 = cip; // expected-error {{initializer element is not a compile-time constant}}
|
|
|
|
const void *cvp = 0;
|
|
_Atomic(const int *) acip2 = cvp; // expected-error {{initializer element is not a compile-time constant}}
|
|
|
|
#if __STDC_VERSION__ >= 202311L
|
|
// the left operand has an atomic ... version of the nullptr_t type and the
|
|
// right operand is a null pointer constant or its type is nullptr_t
|
|
typedef typeof(nullptr) nullptr_t;
|
|
nullptr_t n;
|
|
_Atomic nullptr_t cn2 = n; // expected-error {{initializer element is not a compile-time constant}}
|
|
_Atomic(int *) aip2 = nullptr;
|
|
#endif // __STDC_VERSION__ >= 202311L
|
|
|
|
// FIXME: &ai is an address constant, so this should be accepted as an
|
|
// initializer, but the bit-cast inserted due to the pointer conversion is
|
|
// tripping up the test for whether the initializer is a constant expression.
|
|
// The warning is correct but the error is not.
|
|
_Atomic(int *) aip3 = &ai; /* expected-warning {{incompatible pointer types initializing '_Atomic(int *)' with an expression of type '_Atomic(int) *'}}
|
|
expected-error {{initializer element is not a compile-time constant}}
|
|
*/
|
|
|
|
// Test the behavior when converting the null pointer constant to an atomic
|
|
// function pointer.
|
|
_Atomic(int (*)(char)) afp = (void *)0;
|
|
|
|
void func_18(void) {
|
|
// Ensure we can cast to atomic scalar types.
|
|
data2 = (_Atomic int)0;
|
|
(void)(_Atomic(int *))0;
|
|
|
|
// But that we correctly reject casts to atomic aggregate types.
|
|
struct S { int a; } s;
|
|
struct T { int a; };
|
|
(void)(_Atomic struct T)s; // expected-error {{used type 'struct T' where arithmetic or pointer type is required}}
|
|
}
|
|
|
|
// Test if we can handle an _Atomic qualified integer in a switch statement.
|
|
void func_19(void) {
|
|
_Atomic int a = 0;
|
|
switch (a) { }
|
|
}
|