brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.9 KiB · a6a334d Raw
194 lines · cpp
1// RUN: %clang_cc1 -std=c++20  -Wno-all -Wunsafe-buffer-usage -Wno-unsafe-buffer-usage-in-container\2// RUN:            -fsafe-buffer-usage-suggestions \3// RUN:            -fblocks -include %s -verify %s4 5// RUN: %clang -x c++ -frtti -fsyntax-only -fblocks -include %s %s 2>&1 | FileCheck --allow-empty %s6// RUN: %clang_cc1 -std=c++11 -fblocks -include %s %s 2>&1 | FileCheck --allow-empty %s7// RUN: %clang_cc1 -std=c++20 -fblocks -include %s %s 2>&1 | FileCheck --allow-empty %s8// CHECK-NOT: [-Wunsafe-buffer-usage]9 10#ifndef INCLUDED11#define INCLUDED12#pragma clang system_header13 14// no spanification warnings for system headers15#else16 17typedef __INTPTR_TYPE__ intptr_t;18 19namespace std {20  class type_info;21  class bad_cast;22  class bad_typeid;23}24using size_t = __typeof(sizeof(int));25void *malloc(size_t);26 27void foo(int v) {28}29 30void foo(int *p){}31 32namespace std{33  template <typename T> class span {34 35   T *elements;36 37   span(T *, unsigned){}38 39   public:40 41   constexpr span<T> subspan(size_t offset, size_t count) const {42     return span<T> (elements+offset, count); // expected-warning{{unsafe pointer arithmetic}}43   }44 45   constexpr T* data() const noexcept {46     return elements;47   }48 49   constexpr T* hello() const noexcept {50     return elements;51   }52 };53 54 template <typename T> class vector {55 56   T *elements;57 58   public:59 60   vector(size_t n) {61     elements = new T[n];62   }63 64   constexpr T* data() const noexcept {65      return elements;66   }67 68   ~vector() {69     delete[] elements;70   }71 };72 73 template <class T, size_t N>74 class array {75   T elements[N];76 77   public:78 79   constexpr const T* data() const noexcept {80      return elements;81   }82 83 };84 85 template <typename T> class span_duplicate {86   span_duplicate(T *, unsigned){}87 88   T array[10];89 90   public:91 92   T* data() {93     return array;94   }95 96 };97}98 99using namespace std;100 101class A {102  int a, b, c;103};104 105class B {106  int a, b, c;107};108 109struct Base {110   virtual ~Base() = default;111};112 113struct Derived: Base {114  int d;115};116 117void cast_without_data(int *ptr) {118 A *a = (A*) ptr;119 float *p = (float*) ptr;120}121 122void warned_patterns_span(std::span<int> span_ptr, std::span<Base> base_span, span<int> span_without_qual) {123    A *a1 = (A*)span_ptr.data(); // expected-warning{{unsafe invocation of 'data'}}124    a1 = (A*)span_ptr.data(); // expected-warning{{unsafe invocation of 'data'}}125 126    a1 = (A*)(span_ptr.data()); // expected-warning{{unsafe invocation of 'data'}}127    A *a2 = (A*) (span_without_qual.data()); // expected-warning{{unsafe invocation of 'data'}}128 129    a2 = (A*) span_without_qual.data(); // expected-warning{{unsafe invocation of 'data'}}130 131     // TODO:: Should we warn when we cast from base to derived type?132     Derived *b = dynamic_cast<Derived*> (base_span.data());// expected-warning{{unsafe invocation of 'data'}}133 134    // TODO:: This pattern is safe. We can add special handling for it, if we decide this135    // is the recommended fixit for the unsafe invocations.136    A *a3 = (A*)span_ptr.subspan(0, sizeof(A)).data(); // expected-warning{{unsafe invocation of 'data'}}137}138 139void warned_patterns_array(std::array<int, 5> array_ptr, std::array<Base, 10> base_span, span<int> span_without_qual) {140    const A *a1 = (A*)array_ptr.data(); // expected-warning{{unsafe invocation of 'data'}}141    a1 = (A*)array_ptr.data(); // expected-warning{{unsafe invocation of 'data'}}142 143    a1 = (A*)(array_ptr.data()); // expected-warning{{unsafe invocation of 'data'}}144}145 146void not_warned_patterns(std::span<A> span_ptr, std::span<Base> base_span) {147    int *p = (int*) span_ptr.data(); // Cast to a smaller type148  149    B *b = (B*) span_ptr.data(); // Cast to a type of same size.150 151    p = (int*) span_ptr.data();152    A *a = (A*) span_ptr.hello(); // Invoking other methods.153   154     intptr_t k = (intptr_t) span_ptr.data();155    k = (intptr_t) (span_ptr.data());156}157 158// We do not want to warn about other types159void other_classes(std::span_duplicate<int> span_ptr) {160    int *p;161    A *a = (A*)span_ptr.data();162    a = (A*)span_ptr.data(); 163}164 165// Potential source for false negatives166 167A false_negatives(std::span<int> span_pt, span<A> span_A) {168  int *ptr = span_pt.data();169 170  A *a1 = (A*)ptr; //TODO: We want to warn here eventually.171 172  A *a2= span_A.data();173  return *a2; // TODO: Can cause OOB if span_pt is empty174 175}176 177void test_incomplete_type(std::span<char> S) {178  (struct IncompleteStruct *)S.data(); // expected-warning{{unsafe invocation of 'data'}}179  (class IncompleteClass *)S.data();   // expected-warning{{unsafe invocation of 'data'}}180  (union IncompleteUnion *)S.data();   // expected-warning{{unsafe invocation of 'data'}}181}182 183void test_complete_type(std::span<long> S) {184  (struct CompleteStruct *)S.data(); // no warn as the struct size is smaller than long185  (class CompleteClass *)S.data();   // no warn as the class size is smaller than long186  (union CompleteUnion *)S.data();   // no warn as the union size is smaller than long187 188  struct CompleteStruct {};189  class CompleteClass {};190  union CompleteUnion {};191}192 193#endif194