brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.0 KiB · c8fb406 Raw
190 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -fblocks -fcxx-exceptions -verify -Wfunction-effects -Wfunction-effect-redeclarations %s2// RUN: %clang_cc1 -fsyntax-only -fblocks -verify -x c -std=c23 -Wfunction-effects -Wfunction-effect-redeclarations %s3 4#if !__has_attribute(nonblocking)5#error "the 'nonblocking' attribute is not available"6#endif7 8// --- ATTRIBUTE SYNTAX: SUBJECTS ---9 10int nl_var [[clang::nonblocking]]; // expected-warning {{'nonblocking' only applies to function types; type here is 'int'}}11struct nl_struct {} [[clang::nonblocking]]; // expected-warning {{attribute 'clang::nonblocking' is ignored, place it after "struct" to apply attribute to type declaration}}12struct [[clang::nonblocking]] nl_struct2 {}; // expected-error {{'clang::nonblocking' attribute cannot be applied to a declaration}}13 14// Positive case15typedef void (*fo)() [[clang::nonblocking]];16void (*read_me_and_weep(17  int val, void (*func)(int) [[clang::nonblocking]])18  [[clang::nonblocking]]) (int)19  [[clang::nonblocking]];20 21// --- ATTRIBUTE SYNTAX: ARGUMENT COUNT ---22void nargs_1() [[clang::nonblocking(1, 2)]];  // expected-error {{'clang::nonblocking' attribute takes no more than 1 argument}}23void nargs_2() [[clang::nonallocating(1, 2)]]; // expected-error {{'clang::nonallocating' attribute takes no more than 1 argument}}24void nargs_3() [[clang::blocking(1)]]; // expected-error {{'clang::blocking' attribute takes no arguments}}25void nargs_4() [[clang::allocating(1)]]; // expected-error {{'clang::allocating' attribute takes no arguments}}26 27// --- ATTRIBUTE SYNTAX: COMBINATIONS ---28// Check invalid combinations of nonblocking/nonallocating attributes29 30void nl_true_false_1() [[clang::nonblocking(true)]] [[clang::blocking]]; // expected-error {{'blocking' and 'nonblocking' attributes are not compatible}}31void nl_true_false_2() [[clang::blocking]] [[clang::nonblocking(true)]]; // expected-error {{'nonblocking' and 'blocking' attributes are not compatible}}32 33void nl_true_false_3() [[clang::nonblocking, clang::blocking]]; // expected-error {{'blocking' and 'nonblocking' attributes are not compatible}}34void nl_true_false_4() [[clang::blocking, clang::nonblocking]]; // expected-error {{'nonblocking' and 'blocking' attributes are not compatible}}35 36void na_true_false_1() [[clang::nonallocating(true)]] [[clang::allocating]]; // expected-error {{'allocating' and 'nonallocating' attributes are not compatible}}37void na_true_false_2() [[clang::allocating]] [[clang::nonallocating(true)]]; // expected-error {{'nonallocating' and 'allocating' attributes are not compatible}}38 39void na_true_false_3() [[clang::nonallocating, clang::allocating]]; // expected-error {{'allocating' and 'nonallocating' attributes are not compatible}}40void na_true_false_4() [[clang::allocating, clang::nonallocating]]; // expected-error {{'nonallocating' and 'allocating' attributes are not compatible}}41 42void nl_true_na_true_1() [[clang::nonblocking]] [[clang::nonallocating]];43void nl_true_na_true_2() [[clang::nonallocating]] [[clang::nonblocking]];44 45void nl_true_na_false_1() [[clang::nonblocking]] [[clang::allocating]]; // expected-error {{'allocating' and 'nonblocking' attributes are not compatible}}46void nl_true_na_false_2() [[clang::allocating]] [[clang::nonblocking]]; // expected-error {{'nonblocking' and 'allocating' attributes are not compatible}}47 48void nl_false_na_true_1() [[clang::blocking]] [[clang::nonallocating]];49void nl_false_na_true_2() [[clang::nonallocating]] [[clang::blocking]];50 51void nl_false_na_false_1() [[clang::blocking]] [[clang::allocating]];52void nl_false_na_false_2() [[clang::allocating]] [[clang::blocking]];53 54// --- TYPE CONVERSIONS ---55 56void unannotated();57void nonblocking() [[clang::nonblocking]];58void nonallocating() [[clang::nonallocating]];59void type_conversions()60{61  // It's fine to remove a performance constraint.62  void (*fp_plain)();63 64  fp_plain = nullptr;65  fp_plain = unannotated;66  fp_plain = nonblocking;67  fp_plain = nonallocating;68 69  // Adding/spoofing nonblocking is unsafe.70  void (*fp_nonblocking)() [[clang::nonblocking]];71  fp_nonblocking = nullptr;72  fp_nonblocking = nonblocking;73  fp_nonblocking = unannotated; // expected-warning {{attribute 'nonblocking' should not be added via type conversion}}74  fp_nonblocking = nonallocating; // expected-warning {{attribute 'nonblocking' should not be added via type conversion}}75 76  // Adding/spoofing nonallocating is unsafe.77  void (*fp_nonallocating)() [[clang::nonallocating]];78  fp_nonallocating = nullptr;79  fp_nonallocating = nonallocating;80  fp_nonallocating = nonblocking; // no warning because nonblocking includes nonallocating81  fp_nonallocating = unannotated; // expected-warning {{attribute 'nonallocating' should not be added via type conversion}}82}83 84#ifdef __cplusplus85struct PTMF {86  void unannotated();87  void nonblocking() [[clang::nonblocking]];88  void nonallocating() [[clang::nonallocating]];89};90 91void type_conversions_ptmf()92{93  // It's fine to remove a performance constraint.94  void (PTMF::*ptmf_plain)() = nullptr;95 96  ptmf_plain = &PTMF::unannotated;97  ptmf_plain = &PTMF::nonblocking;98  ptmf_plain = &PTMF::nonallocating;99 100  // Adding/spoofing nonblocking is unsafe.101  void (PTMF::*fp_nonblocking)() [[clang::nonblocking]] = nullptr;102  fp_nonblocking = &PTMF::nonblocking;103  fp_nonblocking = &PTMF::unannotated; // expected-warning {{attribute 'nonblocking' should not be added via type conversion}}104  fp_nonblocking = &PTMF::nonallocating; // expected-warning {{attribute 'nonblocking' should not be added via type conversion}}105 106  // Adding/spoofing nonallocating is unsafe.107  void (PTMF::*fp_nonallocating)() [[clang::nonallocating]] = nullptr;108  fp_nonallocating = &PTMF::nonallocating;109  fp_nonallocating = &PTMF::nonblocking; // no warning because nonblocking includes nonallocating fp_nonallocating = unannotated;110  fp_nonallocating = &PTMF::unannotated; // expected-warning {{attribute 'nonallocating' should not be added via type conversion}}111}112 113// There was a bug: noexcept and nonblocking could be individually removed in conversion, but not both  114void type_conversions_2()115{116  auto receives_fp = [](void (*fp)()) {117  };118  119  auto ne = +[]() noexcept {};120  auto nl = +[]() [[clang::nonblocking]] {};121  auto nl_ne = +[]() noexcept [[clang::nonblocking]] {};122  123  receives_fp(ne);124  receives_fp(nl);125  receives_fp(nl_ne);126}127#endif128 129// --- VIRTUAL METHODS ---130// Attributes propagate to overridden methods.131// Check this in the syntax tests too.132#ifdef __cplusplus133struct Base {134  virtual void f1();135  virtual void nonblocking() noexcept [[clang::nonblocking]]; // expected-note {{overridden virtual function is here}}136  virtual void nonallocating() noexcept [[clang::nonallocating]]; // expected-note {{overridden virtual function is here}}137  virtual void f2() [[clang::nonallocating]]; // expected-note {{previous declaration is here}}138  virtual void f3() [[clang::nonblocking]]; // expected-note {{overridden virtual function is here}}139};140 141struct Derived : public Base {142  void f1() [[clang::nonblocking]] override;143  void nonblocking() noexcept override; // expected-warning {{overriding function is missing 'nonblocking' attribute from base declaration}}144  void nonallocating() noexcept override; // expected-warning {{overriding function is missing 'nonallocating' attribute from base declaration}}145  void f2() [[clang::allocating]] override; // expected-warning {{effects conflict when merging declarations; kept 'allocating', discarded 'nonallocating'}}146};147 148template <bool B>149struct TDerived : public Base {150  void f3() [[clang::nonblocking(B)]] override; // expected-warning {{attribute 'nonblocking' on overriding function conflicts with base declaration}}151};152#endif // __cplusplus153 154// --- REDECLARATIONS ---155 156void f2();157void f2() [[clang::nonblocking]]; // expected-note {{previous declaration is here}}158void f2(); // expected-warning {{redeclaration is missing 'nonblocking' attribute from previous declaration}}159// Note: we verify that the attribute is actually seen during the constraints tests.160 161void f3() [[clang::blocking]]; // expected-note {{previous declaration is here}}162void f3() [[clang::nonblocking]]; // expected-warning {{effects conflict when merging declarations; kept 'blocking', discarded 'nonblocking'}}163 164// --- OVERLOADS ---165#ifdef __cplusplus166struct S {167  void foo(); // expected-note {{previous declaration is here}}168  void foo() [[clang::nonblocking]]; // expected-error {{class member cannot be redeclared}}169};170#endif // __cplusplus171 172// --- COMPUTED NONBLOCKING ---173void f4() [[clang::nonblocking(__builtin_memset)]] {} // expected-error {{nonblocking attribute requires an integer constant}}174 175#ifdef __cplusplus176// Unexpanded parameter pack177template <bool ...val>178void f5() [[clang::nonblocking(val /* NO ... here */)]] {} // expected-error {{expression contains unexpanded parameter pack 'val'}}179 180void f6() { f5<true, false>(); }181 182template <bool B>183void ambiguous() [[clang::nonblocking(B)]] [[clang::blocking]]; // expected-note {{candidate template ignored: substitution failure [with B = true]: 'blocking' and 'nonblocking' attributes are not compatible}}184 185void f7() {186  ambiguous<true>(); // expected-error {{no matching function for call to 'ambiguous'}}187  ambiguous<false>();188}189#endif // __cplusplus190