brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.7 KiB · f3abe87 Raw
311 lines · cpp
1// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \2// RUN:            -fsafe-buffer-usage-suggestions -verify %s3 4[[clang::unsafe_buffer_usage]]5void deprecatedFunction3();6 7void deprecatedFunction4(int z);8 9void someFunction();10 11[[clang::unsafe_buffer_usage]]12void overloading(int* x);13 14void overloading(char c[]);15 16void overloading(int* x, int size);17 18[[clang::unsafe_buffer_usage]]19void deprecatedFunction4(int z);20 21void caller(int z, int* x, int size, char c[]) {22    deprecatedFunction3(); // expected-warning{{function introduces unsafe buffer manipulation}}23    deprecatedFunction4(z); // expected-warning{{function introduces unsafe buffer manipulation}}24    someFunction();25 26    overloading(x); // expected-warning{{function introduces unsafe buffer manipulation}}27    overloading(x, size);28    overloading(c);29}30 31[[clang::unsafe_buffer_usage]]32void overloading(char c[]);33 34// Test variadics35[[clang::unsafe_buffer_usage]]36void testVariadics(int *ptr, ...);37 38template<typename T, typename... Args>39[[clang::unsafe_buffer_usage]]40T adder(T first, Args... args);41 42template <typename T>43void foo(T t) {}44 45template<>46[[clang::unsafe_buffer_usage]]47void foo<int *>(int *t) {}48 49void caller1(int *p, int *q) {50    testVariadics(p, q);  // expected-warning{{function introduces unsafe buffer manipulation}}51    adder(p, q);  // expected-warning{{function introduces unsafe buffer manipulation}}52    53    int x;54    foo(x);55    foo(&x);  // expected-warning{{function introduces unsafe buffer manipulation}}56}57 58// Test virtual functions59class BaseClass {60public:61    [[clang::unsafe_buffer_usage]]62    virtual void func() {}63    64    virtual void func1() {}65};66 67class DerivedClass : public BaseClass {68public:69    void func() {}70    71    [[clang::unsafe_buffer_usage]]72    void func1() {}73};74 75void testInheritance() {76    DerivedClass DC;77    DC.func();78    DC.func1();  // expected-warning{{function introduces unsafe buffer manipulation}}79    80    BaseClass *BC;81    BC->func();  // expected-warning{{function introduces unsafe buffer manipulation}}82    BC->func1();83    84    BC = &DC;85    BC->func();  // expected-warning{{function introduces unsafe buffer manipulation}}86    BC->func1();87}88 89class UnsafeMembers {90public:91    UnsafeMembers() {}92 93    [[clang::unsafe_buffer_usage]]94    UnsafeMembers(int) {}95 96    [[clang::unsafe_buffer_usage]]97    explicit operator int() { return 0; }98 99    [[clang::unsafe_buffer_usage]]100    void Method() {}101 102    [[clang::unsafe_buffer_usage]]103    void operator()() {}104 105    [[clang::unsafe_buffer_usage]]106    int operator+(UnsafeMembers) { return 0; }107};108 109template <class... Vs>110int testFoldExpression(Vs&&... v) {111    return (... + v);  // expected-warning{{function introduces unsafe buffer manipulation}}112}113 114struct HoldsUnsafeMembers {115    HoldsUnsafeMembers()116        : FromCtor(3),  // expected-warning{{function introduces unsafe buffer manipulation}}117          FromCtor2{3}  // expected-warning{{function introduces unsafe buffer manipulation}}118    {}119 120    [[clang::unsafe_buffer_usage]]121    HoldsUnsafeMembers(int i)122        : FromCtor(i),123          FromCtor2{i} {}124 125    HoldsUnsafeMembers(float f)126        : HoldsUnsafeMembers(0) {}  // expected-warning{{function introduces unsafe buffer manipulation}}127 128    UnsafeMembers FromCtor;129    UnsafeMembers FromCtor2;130    UnsafeMembers FromField{3};  // expected-warning {{function introduces unsafe buffer manipulation}}131};132 133struct SubclassUnsafeMembers : public UnsafeMembers {134    SubclassUnsafeMembers()135        : UnsafeMembers(3)  // expected-warning{{function introduces unsafe buffer manipulation}}136    {}137 138    [[clang::unsafe_buffer_usage]]139    SubclassUnsafeMembers(int i)140        : UnsafeMembers(i){}141};142 143// https://github.com/llvm/llvm-project/issues/80482144void testClassMembers() {145    UnsafeMembers(3);  // expected-warning{{function introduces unsafe buffer manipulation}}146 147    (void)static_cast<int>(UnsafeMembers());  // expected-warning{{function introduces unsafe buffer manipulation}}148 149    UnsafeMembers().Method();  // expected-warning{{function introduces unsafe buffer manipulation}}150 151    UnsafeMembers()();  // expected-warning{{function introduces unsafe buffer manipulation}}152 153    testFoldExpression(UnsafeMembers(), UnsafeMembers());154 155    HoldsUnsafeMembers();156    HoldsUnsafeMembers(3);  // expected-warning{{function introduces unsafe buffer manipulation}}157 158    SubclassUnsafeMembers();159    SubclassUnsafeMembers(3);  // expected-warning{{function introduces unsafe buffer manipulation}}160}161 162// Not an aggregate, so its constructor is not implicit code and will be163// visited/checked for warnings.164struct NotCalledHoldsUnsafeMembers {165    NotCalledHoldsUnsafeMembers()166        : FromCtor(3),  // expected-warning{{function introduces unsafe buffer manipulation}}167          FromCtor2{3}  // expected-warning{{function introduces unsafe buffer manipulation}}168    {}169 170    UnsafeMembers FromCtor;171    UnsafeMembers FromCtor2;172    UnsafeMembers FromField{3};  // expected-warning{{function introduces unsafe buffer manipulation}}173};174 175// An aggregate, so its constructor is implicit code. Since it's not called, it176// is never generated.177struct AggregateUnused {178    UnsafeMembers f1;179    // While this field would trigger the warning during initialization, since180    // it's unused, there's no code generated that does the initialization, so181    // no warning.182    UnsafeMembers f2{3};183};184 185struct AggregateExplicitlyInitializedSafe {186    UnsafeMembers f1;187    // The warning is not fired as the field is always explicltly initialized188    // elsewhere. This initializer is never used.189    UnsafeMembers f2{3};190};191 192void testAggregateExplicitlyInitializedSafe() {193    AggregateExplicitlyInitializedSafe A{194        .f2 = UnsafeMembers(),  // A safe constructor.195    };196}197 198struct AggregateExplicitlyInitializedUnsafe {199    UnsafeMembers f1;200    // The warning is not fired as the field is always explicltly initialized201    // elsewhere. This initializer is never used.202    UnsafeMembers f2{3};203};204 205void testAggregateExplicitlyInitializedUnsafe() {206    AggregateExplicitlyInitializedUnsafe A{207        .f2 = UnsafeMembers(3),  // expected-warning{{function introduces unsafe buffer manipulation}}208    };209}210 211struct AggregateViaAggregateInit {212    UnsafeMembers f1;213    // FIXME: A construction of this class does initialize the field through214    // this initializer, so it should warn. Ideally it should also point to215    // where the site of the construction is in testAggregateViaAggregateInit().216    UnsafeMembers f2{3};217};218 219void testAggregateViaAggregateInit() {220    AggregateViaAggregateInit A{};221};222 223struct AggregateViaValueInit {224    UnsafeMembers f1;225    // FIXME: A construction of this class does initialize the field through226    // this initializer, so it should warn. Ideally it should also point to227    // where the site of the construction is in testAggregateViaValueInit().228    UnsafeMembers f2{3};229};230 231void testAggregateViaValueInit() {232    auto A = AggregateViaValueInit();233};234 235struct AggregateViaDefaultInit {236    UnsafeMembers f1;237    // FIXME: A construction of this class does initialize the field through238    // this initializer, so it should warn. Ideally it should also point to239    // where the site of the construction is in testAggregateViaValueInit().240    UnsafeMembers f2{3};241};242 243void testAggregateViaDefaultInit() {244    AggregateViaDefaultInit A;245};246 247struct A {248  int arr[2];249 250  [[clang::unsafe_buffer_usage]]251  int *ptr;252};253 254namespace std{255  template <typename T> class span {256 257   T *elements;258 259   public:260 261   constexpr span(T *, unsigned){}262 263   template<class Begin, class End>264   constexpr span(Begin first, End last){}265 266   constexpr T* data() const noexcept {267     return elements;268   }269 };270}271 272[[clang::unsafe_buffer_usage]]273void check_no_warnings(unsigned idx) {274  int *arr = new int[20];275 276  int k = arr[idx]; // no-warning277 278  std::span<int> sp = {arr, 20}; // no-warning279  A *ptr = reinterpret_cast<A*> (sp.data()); // no-warning280  A a;281  a.ptr = arr; // no-warning282}283 284[[clang::unsafe_buffer_usage]]285void check_no_warning_variadic(unsigned idx, int arr[20], ...) {286  int k = arr[idx]; // no-warning287 288  std::span<int> sp = {arr, 20}; // no-warning289  A *ptr = reinterpret_cast<A*> (sp.data()); // no-warning290  A a;291  a.ptr = arr; // no-warning292}293 294template<typename T>295[[clang::unsafe_buffer_usage]]296void check_no_warnings_template(unsigned idx, T* arr) {297  int k = arr[idx]; // no-warning298 299  std::span<int> sp = {arr, 20}; // no-warning300  A *ptr = reinterpret_cast<A*> (sp.data()); // no-warning301  A a;302  a.ptr = arr; // no-warning303}304 305void invoke_methods() {306  int array[20];307  check_no_warnings(30); //expected-warning{{function introduces unsafe buffer manipulation}}308  check_no_warning_variadic(15, array); //expected-warning{{function introduces unsafe buffer manipulation}}309  check_no_warnings_template(10, array); //expected-warning{{function introduces unsafe buffer manipulation}}310}311