brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.0 KiB · 3becd5c Raw
195 lines · cpp
1// RUN: %check_clang_tidy %s cppcoreguidelines-owning-memory %t \2// RUN: -config='{CheckOptions: \3// RUN:  {cppcoreguidelines-owning-memory.LegacyResourceProducers: "::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile", \4// RUN:   cppcoreguidelines-owning-memory.LegacyResourceConsumers: "::free;::realloc;::freopen;::fclose"}}' \5// RUN: -- -nostdlib -nostdinc++6 7namespace gsl {8template <class T>9using owner = T;10} // namespace gsl11 12extern "C" {13using size_t = decltype(sizeof(void*));14using FILE = int;15 16void *malloc(size_t ByteCount);17void *aligned_alloc(size_t Alignment, size_t Size);18void *calloc(size_t Count, size_t SizeSingle);19void *realloc(void *Resource, size_t NewByteCount);20void free(void *Resource);21 22FILE *tmpfile(void);23FILE *fopen(const char *filename, const char *mode);24FILE *freopen(const char *filename, const char *mode, FILE *stream);25void fclose(FILE *Resource);26}27 28namespace std {29using ::FILE;30using ::size_t;31 32using ::fclose;33using ::fopen;34using ::freopen;35using ::tmpfile;36 37using ::aligned_alloc;38using ::calloc;39using ::free;40using ::malloc;41using ::realloc;42} // namespace std43 44void nonOwningCall(int *Resource, size_t Size) {}45void nonOwningCall(FILE *Resource) {}46 47void consumesResource(gsl::owner<int *> Resource, size_t Size) {}48void consumesResource(gsl::owner<FILE *> Resource) {}49 50void testNonCasted(void *Resource) {}51 52void testNonCastedOwner(gsl::owner<void *> Resource) {}53 54FILE *fileFactory1() { return ::fopen("new_file.txt", "w"); }55// CHECK-MESSAGES: [[@LINE-1]]:24: warning: returning a newly created resource of type 'FILE *' (aka 'int *') or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>'56gsl::owner<FILE *> fileFactory2() { return std::fopen("new_file.txt", "w"); } // Ok57 58int *arrayFactory1() { return (int *)std::malloc(100); }59// CHECK-MESSAGES: [[@LINE-1]]:24: warning: returning a newly created resource of type 'int *' or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>'60gsl::owner<int *> arrayFactory2() { return (int *)std::malloc(100); } // Ok61void *dataFactory1() { return std::malloc(100); }62// CHECK-MESSAGES: [[@LINE-1]]:24: warning: returning a newly created resource of type 'void *' or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>'63gsl::owner<void *> dataFactory2() { return std::malloc(100); } // Ok64 65void test_resource_creators() {66  const unsigned int ByteCount = 25 * sizeof(int);67  int Bad = 42;68 69  int *IntArray1 = (int *)std::malloc(ByteCount);70  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'71  int *IntArray2 = static_cast<int *>(std::malloc(ByteCount)); // Bad72  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'73  void *IntArray3 = std::malloc(ByteCount);74  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'void *' with a newly created 'gsl::owner<>'75 76  int *IntArray4 = (int *)::malloc(ByteCount);77  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'78  int *IntArray5 = static_cast<int *>(::malloc(ByteCount)); // Bad79  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'80  void *IntArray6 = ::malloc(ByteCount);81  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'void *' with a newly created 'gsl::owner<>'82 83  gsl::owner<int *> IntArray7 = (int *)malloc(ByteCount); // Ok84  gsl::owner<void *> IntArray8 = malloc(ByteCount);       // Ok85 86  gsl::owner<int *> IntArray9 = &Bad;87  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'88 89  nonOwningCall((int *)malloc(ByteCount), 25);90  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: initializing non-owner argument of type 'int *' with a newly created 'gsl::owner<>'91  nonOwningCall((int *)::malloc(ByteCount), 25);92  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: initializing non-owner argument of type 'int *' with a newly created 'gsl::owner<>'93 94  consumesResource((int *)malloc(ByteCount), 25);   // Ok95  consumesResource((int *)::malloc(ByteCount), 25); // Ok96 97  testNonCasted(malloc(ByteCount));98  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: initializing non-owner argument of type 'void *' with a newly created 'gsl::owner<>'99  testNonCastedOwner(gsl::owner<void *>(malloc(ByteCount))); // Ok100  testNonCastedOwner(malloc(ByteCount));                     // Ok101 102  FILE *File1 = std::fopen("test_name.txt", "w+");103  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'104  FILE *File2 = ::fopen("test_name.txt", "w+");105  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'106 107  gsl::owner<FILE *> File3 = ::fopen("test_name.txt", "w+"); // Ok108 109  FILE *File4;110  File4 = ::fopen("test_name.txt", "w+");111  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: assigning newly created 'gsl::owner<>' to non-owner 'FILE *' (aka 'int *')112 113  gsl::owner<FILE *> File5;114  File5 = ::fopen("test_name.txt", "w+"); // Ok115  File5 = File1;116  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'FILE *' (aka 'int *')117 118  gsl::owner<FILE *> File6 = File1;119  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'FILE *' (aka 'int *')120 121  FILE *File7 = tmpfile();122  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'123  gsl::owner<FILE *> File8 = tmpfile(); // Ok124 125  nonOwningCall(::fopen("test_name.txt", "r"));126  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: initializing non-owner argument of type 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'127  nonOwningCall(std::fopen("test_name.txt", "r"));128  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: initializing non-owner argument of type 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'129 130  consumesResource(::fopen("test_name.txt", "r")); // Ok131 132  int *HeapPointer3 = (int *)aligned_alloc(16ul, 4ul * 32ul);133  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'134  gsl::owner<int *> HeapPointer4 = static_cast<int *>(aligned_alloc(16ul, 4ul * 32ul)); // Ok135 136  void *HeapPointer5 = calloc(10ul, 4ul);137  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'void *' with a newly created 'gsl::owner<>'138  gsl::owner<void *> HeapPointer6 = calloc(10ul, 4ul); // Ok139}140 141void test_legacy_consumers() {142  int StackInteger = 42;143 144  int *StackPointer = &StackInteger;145  int *HeapPointer1 = (int *)malloc(100);146  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'147  gsl::owner<int *> HeapPointer2 = (int *)malloc(100);148 149  std::free(StackPointer);150  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'151  std::free(HeapPointer1);152  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'153  std::free(HeapPointer2); // Ok154  // CHECK MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'155 156  // FIXME: the check complains about initialization of 'void *' with new created owner.157  // This happens, because the argument of `free` is not marked as 'owner<>' (and cannot be),158  // and the check will not figure out could be meant as owner.159  // This property will probably never be fixed, because it is probably a rather rare160  // use-case and 'owner<>' should be wrapped in RAII classes anyway!161  std::free(std::malloc(100)); // Ok but silly :)162  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: initializing non-owner argument of type 'void *' with a newly created 'gsl::owner<>'163 164  // Demonstrate, that multi-argument functions are diagnosed as well.165  std::realloc(StackPointer, 200);166  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'167  std::realloc(HeapPointer1, 200);168  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'169  std::realloc(HeapPointer2, 200);     // Ok170  std::realloc(std::malloc(100), 200); // Ok but silly171  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: initializing non-owner argument of type 'void *' with a newly created 'gsl::owner<>'172 173  fclose(fileFactory1());174  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'175  fclose(fileFactory2()); // Ok, same as FIXME with `free(malloc(100))` applies here176  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: initializing non-owner argument of type 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'177 178  gsl::owner<FILE *> File1 = fopen("testfile.txt", "r"); // Ok179  FILE *File2 = freopen("testfile.txt", "w", File1);180  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'181  // CHECK-MESSAGES: [[@LINE-2]]:17: warning: calling legacy resource function without passing a 'gsl::owner<>'182  // FIXME: The warning for not passing and owner<> is a false positive since both the filename and the183  // mode are not supposed to be owners but still pointers. The check is to coarse for184  // this function. Maybe `freopen` gets special treatment.185 186  gsl::owner<FILE *> File3 = freopen("testfile.txt", "w", File2); // Bad, File2 no owner187  // CHECK-MESSAGES: [[@LINE-1]]:30: warning: calling legacy resource function without passing a 'gsl::owner<>'188 189  FILE *TmpFile = tmpfile();190  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'191  FILE *File6 = freopen("testfile.txt", "w", TmpFile); // Bad, both return and argument192  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'193  // CHECK-MESSAGES: [[@LINE-2]]:17: warning: calling legacy resource function without passing a 'gsl::owner<>'194}195