1 // RUN: %check_clang_tidy %s bugprone-pointer-arithmetic-on-polymorphic-object %t --
2
3 class Base {
4 public:
~Base()5 virtual ~Base() {}
6 };
7
8 class Derived : public Base {};
9
10 class FinalDerived final : public Base {};
11
12 class AbstractBase {
13 public:
14 virtual void f() = 0;
~AbstractBase()15 virtual ~AbstractBase() {}
16 };
17
18 class AbstractInherited : public AbstractBase {};
19
20 class AbstractOverride : public AbstractInherited {
21 public:
f()22 void f() override {}
23 };
24
operators()25 void operators() {
26 Base *b = new Derived[10];
27
28 b += 1;
29 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'Base' can result in undefined behavior if the dynamic type differs from the pointer type [bugprone-pointer-arithmetic-on-polymorphic-object]
30
31 b = b + 1;
32 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: pointer arithmetic on polymorphic object of type 'Base' can result in undefined behavior if the dynamic type differs from the pointer type [bugprone-pointer-arithmetic-on-polymorphic-object]
33
34 b++;
35 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'Base' can result in undefined behavior if the dynamic type differs from the pointer type [bugprone-pointer-arithmetic-on-polymorphic-object]
36
37 --b;
38 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pointer arithmetic on polymorphic object of type 'Base' can result in undefined behavior if the dynamic type differs from the pointer type [bugprone-pointer-arithmetic-on-polymorphic-object]
39
40 b[1];
41 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'Base' can result in undefined behavior if the dynamic type differs from the pointer type [bugprone-pointer-arithmetic-on-polymorphic-object]
42
43 delete[] static_cast<Derived*>(b);
44 }
45
subclassWarnings()46 void subclassWarnings() {
47 Base *b = new Base[10];
48
49 // False positive that's impossible to distinguish without
50 // path-sensitive analysis, but the code is bug-prone regardless.
51 b += 1;
52 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'Base'
53
54 delete[] b;
55
56 // Common false positive is a class that overrides all parent functions.
57 // Is a warning because of the check configuration.
58 Derived *d = new Derived[10];
59
60 d += 1;
61 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'Derived'
62
63 delete[] d;
64
65 // Final classes cannot have a dynamic type.
66 FinalDerived *fd = new FinalDerived[10];
67
68 fd += 1;
69 // no-warning
70
71 delete[] fd;
72 }
73
abstractWarnings()74 void abstractWarnings() {
75 // Classes with an abstract member funtion are always matched.
76 AbstractBase *ab = new AbstractOverride[10];
77
78 ab += 1;
79 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'AbstractBase'
80
81 delete[] static_cast<AbstractOverride*>(ab);
82
83 AbstractInherited *ai = new AbstractOverride[10];
84
85 ai += 1;
86 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'AbstractInherited'
87
88 delete[] static_cast<AbstractOverride*>(ai);
89
90 // Is a warning because of the check configuration.
91 AbstractOverride *ao = new AbstractOverride[10];
92
93 ao += 1;
94 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'AbstractOverride'
95
96 delete[] ao;
97 }
98
99 template <typename T>
templateWarning(T * t)100 void templateWarning(T *t) {
101 // FIXME: Tidy doesn't support template instantiation locations properly.
102 t += 1;
103 // no-warning
104 }
105
functionArgument(Base * b)106 void functionArgument(Base *b) {
107 b += 1;
108 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'Base'
109
110 templateWarning(b);
111 }
112
113 using BaseAlias = Base;
114 using DerivedAlias = Derived;
115 using FinalDerivedAlias = FinalDerived;
116
117 using BasePtr = Base*;
118 using DerivedPtr = Derived*;
119 using FinalDerivedPtr = FinalDerived*;
120
typeAliases(BaseAlias * b,DerivedAlias * d,FinalDerivedAlias * fd,BasePtr bp,DerivedPtr dp,FinalDerivedPtr fdp)121 void typeAliases(BaseAlias *b, DerivedAlias *d, FinalDerivedAlias *fd,
122 BasePtr bp, DerivedPtr dp, FinalDerivedPtr fdp) {
123 b += 1;
124 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'Base'
125
126 d += 1;
127 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'Derived'
128
129 fd += 1;
130 // no-warning
131
132 bp += 1;
133 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'Base'
134
135 dp += 1;
136 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'Derived'
137
138 fdp += 1;
139 // no-warning
140 }
141