218 lines · cpp
1// RUN: %clang_cc1 %s -ast-dump -fblocks | FileCheck %s2 3// Make sure that the attribute gets parsed and attached to the correct AST elements.4 5#pragma clang diagnostic ignored "-Wunused-variable"6#pragma clang diagnostic ignored "-Wperf-constraint-implies-noexcept"7 8// =========================================================================================9// Square brackets, true10 11namespace square_brackets {12 13// 1. On the type of the FunctionDecl14void nl_function() [[clang::nonblocking]];15// CHECK: FunctionDecl {{.*}} nl_function 'void () __attribute__((nonblocking))'16 17// 2. On the type of the VarDecl holding a function pointer18void (*nl_func_a)() [[clang::nonblocking]];19// CHECK: VarDecl {{.*}} nl_func_a 'void (*)() __attribute__((nonblocking))'20 21// 3. On the type of the ParmVarDecl of a function parameter22static void nlReceiver(void (*nl_func)() [[clang::nonblocking]]);23// CHECK: ParmVarDecl {{.*}} nl_func 'void (*)() __attribute__((nonblocking))'24 25// 4. As an AttributedType within the nested types of a typedef26typedef void (*nl_fp_type)() [[clang::nonblocking]];27// CHECK: TypedefDecl {{.*}} nl_fp_type 'void (*)() __attribute__((nonblocking))'28using nl_fp_talias = void (*)() [[clang::nonblocking]];29// CHECK: TypeAliasDecl {{.*}} nl_fp_talias 'void (*)() __attribute__((nonblocking))'30 31// 5. From a typedef or typealias, on a VarDecl32nl_fp_type nl_fp_var1;33// CHECK: VarDecl {{.*}} nl_fp_var1 'nl_fp_type':'void (*)() __attribute__((nonblocking))'34nl_fp_talias nl_fp_var2;35// CHECK: VarDecl {{.*}} nl_fp_var2 'nl_fp_talias':'void (*)() __attribute__((nonblocking))'36 37// 6. On type of a FieldDecl38struct Struct {39 void (*nl_func_field)() [[clang::nonblocking]];40// CHECK: FieldDecl {{.*}} nl_func_field 'void (*)() __attribute__((nonblocking))'41};42 43// nonallocating should NOT be subsumed into nonblocking44void nl1() [[clang::nonblocking]] [[clang::nonallocating]];45// CHECK: FunctionDecl {{.*}} nl1 'void () __attribute__((nonblocking)) __attribute__((nonallocating))'46 47void nl2() [[clang::nonallocating]] [[clang::nonblocking]];48// CHECK: FunctionDecl {{.*}} nl2 'void () __attribute__((nonblocking)) __attribute__((nonallocating))'49 50decltype(nl1) nl3;51// CHECK: FunctionDecl {{.*}} nl3 'decltype(nl1)':'void () __attribute__((nonblocking)) __attribute__((nonallocating))'52 53// Attribute propagates from base class virtual method to overrides.54struct Base {55 virtual void nb_method() [[clang::nonblocking]];56};57struct Derived : public Base {58 void nb_method() override;59 // CHECK: CXXMethodDecl {{.*}} nb_method 'void () __attribute__((nonblocking))'60};61 62// Dependent expression63template <bool V>64struct Dependent {65 void nb_method2() [[clang::nonblocking(V)]];66 // CHECK: CXXMethodDecl {{.*}} nb_method2 'void () __attribute__((nonblocking(V)))'67};68 69// --- Blocks ---70 71// On the type of the VarDecl holding a BlockDecl72void (^nl_block1)() [[clang::nonblocking]] = ^() [[clang::nonblocking]] {};73// CHECK: VarDecl {{.*}} nl_block1 'void (^)() __attribute__((nonblocking))'74 75int (^nl_block2)() [[clang::nonblocking]] = ^() [[clang::nonblocking]] { return 0; };76// CHECK: VarDecl {{.*}} nl_block2 'int (^)() __attribute__((nonblocking))'77 78// The operand of the CallExpr is an ImplicitCastExpr of a DeclRefExpr -> nl_block which hold the attribute79static void blockCaller() { nl_block1(); }80// CHECK: DeclRefExpr {{.*}} 'nl_block1' 'void (^)() __attribute__((nonblocking))'81 82// --- Lambdas ---83 84// On the operator() of a lambda's CXXMethodDecl85auto nl_lambda = []() [[clang::nonblocking]] {};86// CHECK: CXXMethodDecl {{.*}} operator() 'void () const __attribute__((nonblocking))' inline87 88// =========================================================================================89// Square brackets, false90 91void nl_func_false() [[clang::blocking]];92// CHECK: FunctionDecl {{.*}} nl_func_false 'void () __attribute__((blocking))'93 94auto nl_lambda_false = []() [[clang::blocking]] {};95// CHECK: CXXMethodDecl {{.*}} operator() 'void () const __attribute__((blocking))'96 97} // namespace square_brackets98 99// =========================================================================================100// GNU-style attribute, true101 102namespace gnu_style {103 104// 1. On the type of the FunctionDecl105void nl_function() __attribute__((nonblocking));106// CHECK: FunctionDecl {{.*}} nl_function 'void () __attribute__((nonblocking))'107 108// 1a. Alternate placement on the FunctionDecl109__attribute__((nonblocking)) void nl_function();110// CHECK: FunctionDecl {{.*}} nl_function 'void () __attribute__((nonblocking))'111 112// 2. On the type of the VarDecl holding a function pointer113void (*nl_func_a)() __attribute__((nonblocking));114// CHECK: VarDecl {{.*}} nl_func_a 'void (*)() __attribute__((nonblocking))'115 116// 2a. Alternate attribute placement on VarDecl117__attribute__((nonblocking)) void (*nl_func_b)();118// CHECK: VarDecl {{.*}} nl_func_b 'void (*)() __attribute__((nonblocking))'119 120// 3. On the type of the ParmVarDecl of a function parameter121static void nlReceiver(void (*nl_func)() __attribute__((nonblocking)));122// CHECK: ParmVarDecl {{.*}} nl_func 'void (*)() __attribute__((nonblocking))'123 124// 4. As an AttributedType within the nested types of a typedef125// Note different placement from square brackets for the typealias.126typedef void (*nl_fp_type)() __attribute__((nonblocking));127// CHECK: TypedefDecl {{.*}} nl_fp_type 'void (*)() __attribute__((nonblocking))'128using nl_fp_talias = __attribute__((nonblocking)) void (*)();129// CHECK: TypeAliasDecl {{.*}} nl_fp_talias 'void (*)() __attribute__((nonblocking))'130 131// 5. From a typedef or typealias, on a VarDecl132nl_fp_type nl_fp_var1;133// CHECK: VarDecl {{.*}} nl_fp_var1 'nl_fp_type':'void (*)() __attribute__((nonblocking))'134nl_fp_talias nl_fp_var2;135// CHECK: VarDecl {{.*}} nl_fp_var2 'nl_fp_talias':'void (*)() __attribute__((nonblocking))'136 137// 6. On type of a FieldDecl138struct Struct {139 void (*nl_func_field)() __attribute__((nonblocking));140// CHECK: FieldDecl {{.*}} nl_func_field 'void (*)() __attribute__((nonblocking))'141};142 143} // namespace gnu_style144 145// =========================================================================================146// nonallocating and allocating - quick checks because the code paths are generally147// identical after parsing.148 149void na_function() [[clang::nonallocating]];150// CHECK: FunctionDecl {{.*}} na_function 'void () __attribute__((nonallocating))'151 152void na_true_function() [[clang::nonallocating(true)]];153// CHECK: FunctionDecl {{.*}} na_true_function 'void () __attribute__((nonallocating))'154 155void na_false_function() [[clang::nonallocating(false)]];156// CHECK: FunctionDecl {{.*}} na_false_function 'void () __attribute__((allocating))'157 158void alloc_function() [[clang::allocating]];159// CHECK: FunctionDecl {{.*}} alloc_function 'void () __attribute__((allocating))'160 161 162// =========================================================================================163// Non-blocking with an expression parameter164 165void t0() [[clang::nonblocking(1 - 1)]];166// CHECK: FunctionDecl {{.*}} t0 'void () __attribute__((blocking))'167void t1() [[clang::nonblocking(1 + 1)]];168// CHECK: FunctionDecl {{.*}} t1 'void () __attribute__((nonblocking))'169 170template <bool V>171struct ValueDependent {172 void nb_method() [[clang::nonblocking(V)]];173};174 175void t3() [[clang::nonblocking]]176{177 ValueDependent<false> x1;178 x1.nb_method();179// CHECK: ClassTemplateSpecializationDecl {{.*}} ValueDependent180// CHECK: TemplateArgument integral 'false'181// CHECK: CXXMethodDecl {{.*}} nb_method 'void () __attribute__((blocking))'182 183 ValueDependent<true> x2;184 x2.nb_method();185// CHECK: ClassTemplateSpecializationDecl {{.*}} ValueDependent186// CHECK: TemplateArgument integral 'true'187// CHECK: CXXMethodDecl {{.*}} nb_method 'void () __attribute__((nonblocking))'188}189 190template <typename X>191struct TypeDependent {192 void td_method() [[clang::nonblocking(X::is_nb)]];193};194 195struct NBPolicyTrue {196 static constexpr bool is_nb = true;197};198 199struct NBPolicyFalse {200 static constexpr bool is_nb = false;201};202 203void t4()204{205 TypeDependent<NBPolicyFalse> x1;206 x1.td_method();207// CHECK: ClassTemplateSpecializationDecl {{.*}} TypeDependent208// CHECK: TemplateArgument type 'NBPolicyFalse'209// CHECK: CXXMethodDecl {{.*}} td_method 'void () __attribute__((blocking))'210 211 TypeDependent<NBPolicyTrue> x2;212 x2.td_method();213// CHECK: ClassTemplateSpecializationDecl {{.*}} TypeDependent214// CHECK: TemplateArgument type 'NBPolicyTrue'215// CHECK: CXXMethodDecl {{.*}} td_method 'void () __attribute__((nonblocking))'216}217 218