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).
218 lines
8.3 KiB
C++
218 lines
8.3 KiB
C++
// RUN: %clang_cc1 %s -ast-dump -fblocks | FileCheck %s
|
|
|
|
// Make sure that the attribute gets parsed and attached to the correct AST elements.
|
|
|
|
#pragma clang diagnostic ignored "-Wunused-variable"
|
|
#pragma clang diagnostic ignored "-Wperf-constraint-implies-noexcept"
|
|
|
|
// =========================================================================================
|
|
// Square brackets, true
|
|
|
|
namespace square_brackets {
|
|
|
|
// 1. On the type of the FunctionDecl
|
|
void nl_function() [[clang::nonblocking]];
|
|
// CHECK: FunctionDecl {{.*}} nl_function 'void () __attribute__((nonblocking))'
|
|
|
|
// 2. On the type of the VarDecl holding a function pointer
|
|
void (*nl_func_a)() [[clang::nonblocking]];
|
|
// CHECK: VarDecl {{.*}} nl_func_a 'void (*)() __attribute__((nonblocking))'
|
|
|
|
// 3. On the type of the ParmVarDecl of a function parameter
|
|
static void nlReceiver(void (*nl_func)() [[clang::nonblocking]]);
|
|
// CHECK: ParmVarDecl {{.*}} nl_func 'void (*)() __attribute__((nonblocking))'
|
|
|
|
// 4. As an AttributedType within the nested types of a typedef
|
|
typedef void (*nl_fp_type)() [[clang::nonblocking]];
|
|
// CHECK: TypedefDecl {{.*}} nl_fp_type 'void (*)() __attribute__((nonblocking))'
|
|
using nl_fp_talias = void (*)() [[clang::nonblocking]];
|
|
// CHECK: TypeAliasDecl {{.*}} nl_fp_talias 'void (*)() __attribute__((nonblocking))'
|
|
|
|
// 5. From a typedef or typealias, on a VarDecl
|
|
nl_fp_type nl_fp_var1;
|
|
// CHECK: VarDecl {{.*}} nl_fp_var1 'nl_fp_type':'void (*)() __attribute__((nonblocking))'
|
|
nl_fp_talias nl_fp_var2;
|
|
// CHECK: VarDecl {{.*}} nl_fp_var2 'nl_fp_talias':'void (*)() __attribute__((nonblocking))'
|
|
|
|
// 6. On type of a FieldDecl
|
|
struct Struct {
|
|
void (*nl_func_field)() [[clang::nonblocking]];
|
|
// CHECK: FieldDecl {{.*}} nl_func_field 'void (*)() __attribute__((nonblocking))'
|
|
};
|
|
|
|
// nonallocating should NOT be subsumed into nonblocking
|
|
void nl1() [[clang::nonblocking]] [[clang::nonallocating]];
|
|
// CHECK: FunctionDecl {{.*}} nl1 'void () __attribute__((nonblocking)) __attribute__((nonallocating))'
|
|
|
|
void nl2() [[clang::nonallocating]] [[clang::nonblocking]];
|
|
// CHECK: FunctionDecl {{.*}} nl2 'void () __attribute__((nonblocking)) __attribute__((nonallocating))'
|
|
|
|
decltype(nl1) nl3;
|
|
// CHECK: FunctionDecl {{.*}} nl3 'decltype(nl1)':'void () __attribute__((nonblocking)) __attribute__((nonallocating))'
|
|
|
|
// Attribute propagates from base class virtual method to overrides.
|
|
struct Base {
|
|
virtual void nb_method() [[clang::nonblocking]];
|
|
};
|
|
struct Derived : public Base {
|
|
void nb_method() override;
|
|
// CHECK: CXXMethodDecl {{.*}} nb_method 'void () __attribute__((nonblocking))'
|
|
};
|
|
|
|
// Dependent expression
|
|
template <bool V>
|
|
struct Dependent {
|
|
void nb_method2() [[clang::nonblocking(V)]];
|
|
// CHECK: CXXMethodDecl {{.*}} nb_method2 'void () __attribute__((nonblocking(V)))'
|
|
};
|
|
|
|
// --- Blocks ---
|
|
|
|
// On the type of the VarDecl holding a BlockDecl
|
|
void (^nl_block1)() [[clang::nonblocking]] = ^() [[clang::nonblocking]] {};
|
|
// CHECK: VarDecl {{.*}} nl_block1 'void (^)() __attribute__((nonblocking))'
|
|
|
|
int (^nl_block2)() [[clang::nonblocking]] = ^() [[clang::nonblocking]] { return 0; };
|
|
// CHECK: VarDecl {{.*}} nl_block2 'int (^)() __attribute__((nonblocking))'
|
|
|
|
// The operand of the CallExpr is an ImplicitCastExpr of a DeclRefExpr -> nl_block which hold the attribute
|
|
static void blockCaller() { nl_block1(); }
|
|
// CHECK: DeclRefExpr {{.*}} 'nl_block1' 'void (^)() __attribute__((nonblocking))'
|
|
|
|
// --- Lambdas ---
|
|
|
|
// On the operator() of a lambda's CXXMethodDecl
|
|
auto nl_lambda = []() [[clang::nonblocking]] {};
|
|
// CHECK: CXXMethodDecl {{.*}} operator() 'void () const __attribute__((nonblocking))' inline
|
|
|
|
// =========================================================================================
|
|
// Square brackets, false
|
|
|
|
void nl_func_false() [[clang::blocking]];
|
|
// CHECK: FunctionDecl {{.*}} nl_func_false 'void () __attribute__((blocking))'
|
|
|
|
auto nl_lambda_false = []() [[clang::blocking]] {};
|
|
// CHECK: CXXMethodDecl {{.*}} operator() 'void () const __attribute__((blocking))'
|
|
|
|
} // namespace square_brackets
|
|
|
|
// =========================================================================================
|
|
// GNU-style attribute, true
|
|
|
|
namespace gnu_style {
|
|
|
|
// 1. On the type of the FunctionDecl
|
|
void nl_function() __attribute__((nonblocking));
|
|
// CHECK: FunctionDecl {{.*}} nl_function 'void () __attribute__((nonblocking))'
|
|
|
|
// 1a. Alternate placement on the FunctionDecl
|
|
__attribute__((nonblocking)) void nl_function();
|
|
// CHECK: FunctionDecl {{.*}} nl_function 'void () __attribute__((nonblocking))'
|
|
|
|
// 2. On the type of the VarDecl holding a function pointer
|
|
void (*nl_func_a)() __attribute__((nonblocking));
|
|
// CHECK: VarDecl {{.*}} nl_func_a 'void (*)() __attribute__((nonblocking))'
|
|
|
|
// 2a. Alternate attribute placement on VarDecl
|
|
__attribute__((nonblocking)) void (*nl_func_b)();
|
|
// CHECK: VarDecl {{.*}} nl_func_b 'void (*)() __attribute__((nonblocking))'
|
|
|
|
// 3. On the type of the ParmVarDecl of a function parameter
|
|
static void nlReceiver(void (*nl_func)() __attribute__((nonblocking)));
|
|
// CHECK: ParmVarDecl {{.*}} nl_func 'void (*)() __attribute__((nonblocking))'
|
|
|
|
// 4. As an AttributedType within the nested types of a typedef
|
|
// Note different placement from square brackets for the typealias.
|
|
typedef void (*nl_fp_type)() __attribute__((nonblocking));
|
|
// CHECK: TypedefDecl {{.*}} nl_fp_type 'void (*)() __attribute__((nonblocking))'
|
|
using nl_fp_talias = __attribute__((nonblocking)) void (*)();
|
|
// CHECK: TypeAliasDecl {{.*}} nl_fp_talias 'void (*)() __attribute__((nonblocking))'
|
|
|
|
// 5. From a typedef or typealias, on a VarDecl
|
|
nl_fp_type nl_fp_var1;
|
|
// CHECK: VarDecl {{.*}} nl_fp_var1 'nl_fp_type':'void (*)() __attribute__((nonblocking))'
|
|
nl_fp_talias nl_fp_var2;
|
|
// CHECK: VarDecl {{.*}} nl_fp_var2 'nl_fp_talias':'void (*)() __attribute__((nonblocking))'
|
|
|
|
// 6. On type of a FieldDecl
|
|
struct Struct {
|
|
void (*nl_func_field)() __attribute__((nonblocking));
|
|
// CHECK: FieldDecl {{.*}} nl_func_field 'void (*)() __attribute__((nonblocking))'
|
|
};
|
|
|
|
} // namespace gnu_style
|
|
|
|
// =========================================================================================
|
|
// nonallocating and allocating - quick checks because the code paths are generally
|
|
// identical after parsing.
|
|
|
|
void na_function() [[clang::nonallocating]];
|
|
// CHECK: FunctionDecl {{.*}} na_function 'void () __attribute__((nonallocating))'
|
|
|
|
void na_true_function() [[clang::nonallocating(true)]];
|
|
// CHECK: FunctionDecl {{.*}} na_true_function 'void () __attribute__((nonallocating))'
|
|
|
|
void na_false_function() [[clang::nonallocating(false)]];
|
|
// CHECK: FunctionDecl {{.*}} na_false_function 'void () __attribute__((allocating))'
|
|
|
|
void alloc_function() [[clang::allocating]];
|
|
// CHECK: FunctionDecl {{.*}} alloc_function 'void () __attribute__((allocating))'
|
|
|
|
|
|
// =========================================================================================
|
|
// Non-blocking with an expression parameter
|
|
|
|
void t0() [[clang::nonblocking(1 - 1)]];
|
|
// CHECK: FunctionDecl {{.*}} t0 'void () __attribute__((blocking))'
|
|
void t1() [[clang::nonblocking(1 + 1)]];
|
|
// CHECK: FunctionDecl {{.*}} t1 'void () __attribute__((nonblocking))'
|
|
|
|
template <bool V>
|
|
struct ValueDependent {
|
|
void nb_method() [[clang::nonblocking(V)]];
|
|
};
|
|
|
|
void t3() [[clang::nonblocking]]
|
|
{
|
|
ValueDependent<false> x1;
|
|
x1.nb_method();
|
|
// CHECK: ClassTemplateSpecializationDecl {{.*}} ValueDependent
|
|
// CHECK: TemplateArgument integral 'false'
|
|
// CHECK: CXXMethodDecl {{.*}} nb_method 'void () __attribute__((blocking))'
|
|
|
|
ValueDependent<true> x2;
|
|
x2.nb_method();
|
|
// CHECK: ClassTemplateSpecializationDecl {{.*}} ValueDependent
|
|
// CHECK: TemplateArgument integral 'true'
|
|
// CHECK: CXXMethodDecl {{.*}} nb_method 'void () __attribute__((nonblocking))'
|
|
}
|
|
|
|
template <typename X>
|
|
struct TypeDependent {
|
|
void td_method() [[clang::nonblocking(X::is_nb)]];
|
|
};
|
|
|
|
struct NBPolicyTrue {
|
|
static constexpr bool is_nb = true;
|
|
};
|
|
|
|
struct NBPolicyFalse {
|
|
static constexpr bool is_nb = false;
|
|
};
|
|
|
|
void t4()
|
|
{
|
|
TypeDependent<NBPolicyFalse> x1;
|
|
x1.td_method();
|
|
// CHECK: ClassTemplateSpecializationDecl {{.*}} TypeDependent
|
|
// CHECK: TemplateArgument type 'NBPolicyFalse'
|
|
// CHECK: CXXMethodDecl {{.*}} td_method 'void () __attribute__((blocking))'
|
|
|
|
TypeDependent<NBPolicyTrue> x2;
|
|
x2.td_method();
|
|
// CHECK: ClassTemplateSpecializationDecl {{.*}} TypeDependent
|
|
// CHECK: TemplateArgument type 'NBPolicyTrue'
|
|
// CHECK: CXXMethodDecl {{.*}} td_method 'void () __attribute__((nonblocking))'
|
|
}
|
|
|