brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.7 KiB · a5a17dd Raw
241 lines · cpp
1// RUN: %clang_cc1 -Wall -Wno-unused -Wno-uninitialized -std=c++2b -verify %s2 3#define CFI_UNCHECKED_CALLEE __attribute__((cfi_unchecked_callee))4 5void unchecked(void) CFI_UNCHECKED_CALLEE {}6void checked(void) {}7 8void (*checked_ptr)(void) = unchecked;  // expected-warning{{implicit conversion from 'void () __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}9void (CFI_UNCHECKED_CALLEE *unchecked_ptr)(void) = unchecked;10void (CFI_UNCHECKED_CALLEE *from_normal)(void) = checked;11void (CFI_UNCHECKED_CALLEE *c_no_function_decay)(void) = &unchecked;12void (CFI_UNCHECKED_CALLEE __attribute__((noreturn)) *other_conflict)(void) = &checked; // expected-error{{cannot initialize a variable of type 'void (*)() __attribute__((noreturn)) __attribute__((cfi_unchecked_callee))' with an rvalue of type 'void (*)()'}}13void (CFI_UNCHECKED_CALLEE *arr[10])(void);14void (*cfi_elem)(void) = arr[1];  // expected-warning{{implicit conversion from 'void (*)() __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}15void (CFI_UNCHECKED_CALLEE *cfi_unchecked_elem)(void) = arr[1];16void (CFI_UNCHECKED_CALLEE &ref)(void) = unchecked;17void (CFI_UNCHECKED_CALLEE &ref2)(void) = *unchecked;18void (&ref_cfi_checked)(void) = unchecked;  // expected-warning{{implicit conversion from 'void () __attribute__((cfi_unchecked_callee))' to 'void ()' discards 'cfi_unchecked_callee' attribute}}19void (&ref_cfi_checked2)(void) = *unchecked;  // expected-warning{{implicit conversion from 'void () __attribute__((cfi_unchecked_callee))' to 'void ()' discards 'cfi_unchecked_callee' attribute}}20 21void (CFI_UNCHECKED_CALLEE *unchecked_from_deref)(void) = &*unchecked;22void (*checked_from_deref)(void) = &*unchecked;  // expected-warning{{implicit conversion from 'void (*)() __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}23 24typedef void (CFI_UNCHECKED_CALLEE unchecked_func_t)(void);25typedef void (checked_func_t)(void);26typedef void (CFI_UNCHECKED_CALLEE *unchecked_func_ptr_t)(void);27typedef void (*checked_func_ptr_t)(void);28checked_func_t *checked_func = unchecked;  // expected-warning{{implicit conversion from 'void () __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}29unchecked_func_t *unchecked_func = unchecked;30 31void CFI_UNCHECKED_CALLEE before_func(void);32CFI_UNCHECKED_CALLEE void before_return_type(void);33void (* CFI_UNCHECKED_CALLEE after_name)(void);34 35void UsageOnImproperTypes() {36  int CFI_UNCHECKED_CALLEE i;  // expected-warning{{'cfi_unchecked_callee' only applies to function types; type here is 'int'}}37}38 39/// Explicit casts suppress the warning.40void CheckCasts() {41  void (*should_warn)(void) = unchecked;  // expected-warning{{implicit conversion from 'void () __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}42 43  void (*no_warn_c_style_cast)(void) = (void (*)(void))unchecked;44  void (*no_warn_static_cast)(void) = static_cast<void (*)(void)>(unchecked);45  void (*no_warn_reinterpret_cast)(void) = reinterpret_cast<void (*)(void)>(unchecked);46  unsigned long long ull = (unsigned long long)unchecked;47 48  struct A {};49  void (CFI_UNCHECKED_CALLEE A::*cfi_unchecked_member_ptr)(void);50  void (A::*member_ptr)(void) = cfi_unchecked_member_ptr;  // expected-warning{{implicit conversion from 'void (A::*)() __attribute__((cfi_unchecked_callee))' to 'void (A::*)()' discards 'cfi_unchecked_callee' attribute}}51 52  struct B {} CFI_UNCHECKED_CALLEE b;  // expected-warning{{'cfi_unchecked_callee' attribute only applies to functions and methods}}53  struct CFI_UNCHECKED_CALLEE C {} c;  // expected-warning{{'cfi_unchecked_callee' attribute only applies to functions and methods}}54  CFI_UNCHECKED_CALLEE struct D {} d;  // expected-warning{{'cfi_unchecked_callee' only applies to function types; type here is 'struct D'}}55 56  void *ptr2 = (void *)unchecked;57}58 59void CheckDifferentConstructions() {60  checked_func_t *checked_func(unchecked_func);  // expected-warning{{implicit conversion from 'void (*)() __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}61  new (checked_func_t *)(unchecked_func);  // expected-warning{{implicit conversion from 'void (*)() __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}62  struct S {63    checked_func_t *checked_func;64 65    S(unchecked_func_t *unchecked_func) : checked_func(unchecked_func) {}  // expected-warning{{implicit conversion from 'void (*)() __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}66  };67 68  checked_func_t *checked_func2{unchecked_func};  // expected-warning{{implicit conversion from 'void (*)() __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}69  checked_ptr = checked_func_ptr_t(unchecked);70 71  auto checked_auto = checked;72  auto unchecked_auto = unchecked;73  unchecked_ptr = checked_auto;74  unchecked_ptr = unchecked_auto;75  checked_ptr = checked_auto;76  checked_ptr = unchecked_auto;  // expected-warning{{implicit conversion from 'void (*)() __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}77}78 79checked_func_t *returning_checked_func() {80  return unchecked;  // expected-warning{{implicit conversion from 'void () __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}81}82 83int checked_arg_func(checked_func_t *checked_func);84int invoke = checked_arg_func(unchecked);  // expected-warning{{implicit conversion from 'void () __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}85 86template <typename T>87struct S {88  S(T *ptr) {}89};90S<unchecked_func_t> s(checked);91S<unchecked_func_t> s2(unchecked);92S<checked_func_t> s3(checked);93S<checked_func_t> s4(unchecked);  // expected-warning{{implicit conversion from 'void () __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}94S s5(checked);95S s6(unchecked);96 97template <typename T, typename U>98struct is_same {99  static constexpr bool value = false;100};101template <typename T>102struct is_same<T,T> {103  static constexpr bool value = true;104};105 106template <typename T>107struct ExpectingCFIUncheckedCallee {108  static_assert(is_same<T, unchecked_func_t>::value);109  ExpectingCFIUncheckedCallee(T *) {}110  ExpectingCFIUncheckedCallee() = default;111};112ExpectingCFIUncheckedCallee<unchecked_func_t> expecting;113ExpectingCFIUncheckedCallee expecting2(unchecked);114 115void no_args() __attribute__((cfi_unchecked_callee(10)));  // expected-error{{'cfi_unchecked_callee' attribute takes no arguments}}116 117void bracket_cfi_unchecked(void) [[clang::cfi_unchecked_callee]] {}118 119void BracketNotation() {120  checked_ptr = bracket_cfi_unchecked;  // expected-warning{{implicit conversion from 'void () __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}121}122 123void Comparisons() {124  /// Let's be able to compare checked and unchecked pointers without warnings.125  unchecked == checked_ptr;126  checked_ptr == unchecked;127  unchecked == unchecked_ptr;128  unchecked != checked_ptr;129  checked_ptr != unchecked;130  unchecked != unchecked_ptr;131 132  (void (*)(void))unchecked == checked_ptr;133  checked_ptr == (void (*)(void))unchecked;134 135  struct S {136    typedef void CB() CFI_UNCHECKED_CALLEE;137    constexpr bool operator==(const S &other) const {138      return cb == other.cb;139    }140    CB *cb;141  };142}143 144/// Type aliasing145typedef void (BaseType)(void);146using WithoutAttr = BaseType;147using WithAttr = __attribute__((cfi_unchecked_callee)) BaseType;148 149WithoutAttr *checked_func_alias = unchecked;  // expected-warning{{implicit conversion from 'void () __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}150WithAttr *unchecked_func_allias = unchecked;151WithoutAttr *checked_func_alias2 = checked;152WithAttr *unchecked_func_alias2 = checked;153 154using MyType = WithAttr;  // expected-note{{previous definition is here}}155using MyType = WithoutAttr;  // expected-error{{type alias redefinition with different types ('WithoutAttr' (aka 'void ()') vs 'WithAttr' (aka 'void () __attribute__((cfi_unchecked_callee))'))}}156 157void MemberFunctionPointer() {158  struct A {159    void unchecked() CFI_UNCHECKED_CALLEE {}160    virtual void unchecked_virtual() CFI_UNCHECKED_CALLEE {}161    static void unchecked_static() CFI_UNCHECKED_CALLEE {}162    void unchecked_explicit_this(this A&) CFI_UNCHECKED_CALLEE {}163    int operator+=(int i) CFI_UNCHECKED_CALLEE { return i; }164 165    void checked() {}166    virtual void checked_virtual() {}167    static void checked_static() {}168    void checked_explicit_this(this A&) {}169    int operator-=(int i) { return i; }170  };171 172  void (CFI_UNCHECKED_CALLEE A::*unchecked)() = &A::unchecked;173  unchecked = &A::unchecked_virtual;174  void (CFI_UNCHECKED_CALLEE *unchecked_explicit_this)(A&) = &A::unchecked_explicit_this;175  void (CFI_UNCHECKED_CALLEE *unchecked_static)() = &A::unchecked_static;176  int (CFI_UNCHECKED_CALLEE A::*unchecked_overloaded)(int) = &A::operator+=;177 178  void (A::*checked)() = &A::unchecked;  // expected-warning{{implicit conversion from 'void (A::*)() __attribute__((cfi_unchecked_callee))' to 'void (A::*)()' discards 'cfi_unchecked_callee' attribute}}179  checked = &A::unchecked_virtual;  // expected-warning{{implicit conversion from 'void (A::*)() __attribute__((cfi_unchecked_callee))' to 'void (A::*)()' discards 'cfi_unchecked_callee' attribute}}180  void (*checked_explicit_this)(A&) = &A::unchecked_explicit_this;  // expected-warning{{implicit conversion from 'void (*)(A &) __attribute__((cfi_unchecked_callee))' to 'void (*)(A &)' discards 'cfi_unchecked_callee' attribute}}181  void (*checked_static)() = &A::unchecked_static;  // expected-warning{{implicit conversion from 'void (*)() __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}182  int (A::*checked_overloaded)(int) = &A::operator+=;  // expected-warning{{implicit conversion from 'int (A::*)(int) __attribute__((cfi_unchecked_callee))' to 'int (A::*)(int)' discards 'cfi_unchecked_callee' attribute}}183 184  unchecked = &A::checked;185  unchecked = &A::checked_virtual;186  unchecked_explicit_this = &A::checked_explicit_this;187  unchecked_static = &A::checked_static;188  unchecked_overloaded = &A::operator-=;189 190  checked = &A::checked;191  checked = &A::checked_virtual;192  checked_explicit_this = &A::checked_explicit_this;193  checked_static = &A::checked_static;194  checked_overloaded = &A::operator-=;195 196  typedef void (CFI_UNCHECKED_CALLEE A::*WithAttr)();197  typedef void (CFI_UNCHECKED_CALLEE A::*WithoutAttr)();198  using WithoutAttr = decltype(unchecked);199}200 201void lambdas() {202  auto unchecked_lambda = [](void) CFI_UNCHECKED_CALLEE -> void {};203  auto checked_lambda = [](void) -> void {};204  void (CFI_UNCHECKED_CALLEE *unchecked_func)(void) = unchecked_lambda;205  unchecked_func = checked_lambda;206  void (*checked_func)(void) = unchecked_lambda;  // expected-warning{{implicit conversion from 'void (*)() __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}207  checked_func = checked_lambda;208 209  auto capture_by_value = [unchecked_lambda, checked_lambda]() {210    void (CFI_UNCHECKED_CALLEE *unchecked_func)(void) = unchecked_lambda;211    unchecked_func = checked_lambda;212    void (*checked_func)(void) = unchecked_lambda;  // expected-warning{{implicit conversion from 'void (*)() __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}213    checked_func = checked_lambda;214  };215 216  auto capture_by_ref = [&unchecked_lambda, &checked_lambda]() {217    void (CFI_UNCHECKED_CALLEE *unchecked_func)(void) = unchecked_lambda;218    unchecked_func = checked_lambda;219    void (*checked_func)(void) = unchecked_lambda;  // expected-warning{{implicit conversion from 'void (*)() __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}220    checked_func = checked_lambda;221  };222 223  auto capture_all_by_value = [=]() {224    void (CFI_UNCHECKED_CALLEE *unchecked_func)(void) = unchecked_lambda;225    unchecked_func = checked_lambda;226    void (*checked_func)(void) = unchecked_lambda;  // expected-warning{{implicit conversion from 'void (*)() __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}227    checked_func = checked_lambda;228  };229 230  auto capture_all_by_ref = [&]() {231    void (CFI_UNCHECKED_CALLEE *unchecked_func)(void) = unchecked_lambda;232    unchecked_func = checked_lambda;233    void (*checked_func)(void) = unchecked_lambda;  // expected-warning{{implicit conversion from 'void (*)() __attribute__((cfi_unchecked_callee))' to 'void (*)()' discards 'cfi_unchecked_callee' attribute}}234    checked_func = checked_lambda;235  };236}237 238CFI_UNCHECKED_CALLEE239void func(void);240void func(void) {}  // No warning expected.241