1*89a1d03eSRichard // RUN: %check_clang_tidy %s cppcoreguidelines-owning-memory %t
2*89a1d03eSRichard 
3*89a1d03eSRichard namespace gsl {
4*89a1d03eSRichard template <typename T>
5*89a1d03eSRichard using owner = T;
6*89a1d03eSRichard }
7*89a1d03eSRichard 
8*89a1d03eSRichard namespace std {
9*89a1d03eSRichard 
10*89a1d03eSRichard // Not actually a vector, but more a dynamic, fixed size array. Just to demonstrate
11*89a1d03eSRichard // functionality or the lack of the same.
12*89a1d03eSRichard template <typename T>
13*89a1d03eSRichard class vector {
14*89a1d03eSRichard public:
vector(unsigned long size,T val)15*89a1d03eSRichard   vector(unsigned long size, T val) : data{new T[size]}, size{size} {
16*89a1d03eSRichard     for (unsigned long i = 0ul; i < size; ++i) {
17*89a1d03eSRichard       data[i] = val;
18*89a1d03eSRichard     }
19*89a1d03eSRichard   }
20*89a1d03eSRichard 
begin()21*89a1d03eSRichard   T *begin() { return data; }
end()22*89a1d03eSRichard   T *end() { return &data[size]; }
operator [](unsigned long index)23*89a1d03eSRichard   T &operator[](unsigned long index) { return data[index]; }
24*89a1d03eSRichard 
25*89a1d03eSRichard private:
26*89a1d03eSRichard   T *data;
27*89a1d03eSRichard   unsigned long size;
28*89a1d03eSRichard };
29*89a1d03eSRichard 
30*89a1d03eSRichard } // namespace std
31*89a1d03eSRichard 
32*89a1d03eSRichard // All of the following codesnippets should be valid with appropriate 'owner<>' analysis,
33*89a1d03eSRichard // but currently the type information of 'gsl::owner<>' gets lost in typededuction.
main()34*89a1d03eSRichard int main() {
35*89a1d03eSRichard   std::vector<gsl::owner<int *>> OwnerStdVector(100, nullptr);
36*89a1d03eSRichard 
37*89a1d03eSRichard   // Rangebased looping in resource vector.
38*89a1d03eSRichard   for (auto *Element : OwnerStdVector) {
39*89a1d03eSRichard     Element = new int(42);
40*89a1d03eSRichard     // CHECK-NOTES: [[@LINE-1]]:5: warning: assigning newly created 'gsl::owner<>' to non-owner 'int *'
41*89a1d03eSRichard   }
42*89a1d03eSRichard   for (auto *Element : OwnerStdVector) {
43*89a1d03eSRichard     delete Element;
44*89a1d03eSRichard     // CHECK-NOTES: [[@LINE-1]]:5: warning: deleting a pointer through a type that is not marked 'gsl::owner<>'; consider using a smart pointer instead
45*89a1d03eSRichard     // CHECK-NOTES: [[@LINE-3]]:8: note: variable declared here
46*89a1d03eSRichard   }
47*89a1d03eSRichard 
48*89a1d03eSRichard   // Indexbased looping in resource vector.
49*89a1d03eSRichard   for (int i = 0; i < 100; ++i) {
50*89a1d03eSRichard     OwnerStdVector[i] = new int(42);
51*89a1d03eSRichard     // CHECK-NOTES: [[@LINE-1]]:5: warning: assigning newly created 'gsl::owner<>' to non-owner 'int *'
52*89a1d03eSRichard   }
53*89a1d03eSRichard   for (int i = 0; i < 100; ++i) {
54*89a1d03eSRichard     delete OwnerStdVector[i];
55*89a1d03eSRichard     // CHECK-NOTES: [[@LINE-1]]:5: warning: deleting a pointer through a type that is not marked 'gsl::owner<>'; consider using a smart pointer instead
56*89a1d03eSRichard     // CHECK-NOTES: [[@LINE-21]]:3: note: variable declared here
57*89a1d03eSRichard     // A note gets emitted here pointing to the return value of the operator[] from the
58*89a1d03eSRichard     // vector implementation. Maybe this is considered misleading.
59*89a1d03eSRichard   }
60*89a1d03eSRichard 
61*89a1d03eSRichard   return 0;
62*89a1d03eSRichard }
63