File: pointer-arithmetic-on-polymorphic-object-all.cpp

package info (click to toggle)
llvm-toolchain-20 1%3A20.1.8-1~exp1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 2,111,388 kB
  • sloc: cpp: 7,438,767; ansic: 1,393,871; asm: 1,012,926; python: 241,728; f90: 86,635; objc: 75,411; lisp: 42,144; pascal: 17,286; sh: 10,027; ml: 5,082; perl: 4,730; awk: 3,523; makefile: 3,349; javascript: 2,251; xml: 892; fortran: 672
file content (140 lines) | stat: -rw-r--r-- 4,456 bytes parent folder | download | duplicates (14)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// RUN: %check_clang_tidy %s bugprone-pointer-arithmetic-on-polymorphic-object %t --

class Base {
public:  
  virtual ~Base() {}
};

class Derived : public Base {};

class FinalDerived final : public Base {};

class AbstractBase {
public:
  virtual void f() = 0;
  virtual ~AbstractBase() {}
};

class AbstractInherited : public AbstractBase {};

class AbstractOverride : public AbstractInherited {
public:
  void f() override {}
};

void operators() {
  Base *b = new Derived[10];

  b += 1;
  // 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]

  b = b + 1;
  // 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]

  b++;
  // 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]

  --b;
  // 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]

  b[1];
  // 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]

  delete[] static_cast<Derived*>(b);
}

void subclassWarnings() {
  Base *b = new Base[10];

  // False positive that's impossible to distinguish without
  // path-sensitive analysis, but the code is bug-prone regardless.
  b += 1;
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'Base'

  delete[] b;

  // Common false positive is a class that overrides all parent functions.
  // Is a warning because of the check configuration.
  Derived *d = new Derived[10];

  d += 1;
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'Derived'

  delete[] d;

  // Final classes cannot have a dynamic type.
  FinalDerived *fd = new FinalDerived[10];

  fd += 1;
  // no-warning

  delete[] fd;
}

void abstractWarnings() {
  // Classes with an abstract member funtion are always matched.
  AbstractBase *ab = new AbstractOverride[10];

  ab += 1;
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'AbstractBase'

  delete[] static_cast<AbstractOverride*>(ab);

  AbstractInherited *ai = new AbstractOverride[10];

  ai += 1;
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'AbstractInherited'

  delete[] static_cast<AbstractOverride*>(ai);

  // Is a warning because of the check configuration.
  AbstractOverride *ao = new AbstractOverride[10];

  ao += 1;
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'AbstractOverride'

  delete[] ao;
}

template <typename T>
void templateWarning(T *t) {
  // FIXME: Tidy doesn't support template instantiation locations properly.
  t += 1;
  // no-warning
}

void functionArgument(Base *b) {
  b += 1;
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'Base'

  templateWarning(b);
}

using BaseAlias = Base;
using DerivedAlias = Derived;
using FinalDerivedAlias = FinalDerived;

using BasePtr = Base*;
using DerivedPtr = Derived*;
using FinalDerivedPtr = FinalDerived*;

void typeAliases(BaseAlias *b, DerivedAlias *d, FinalDerivedAlias *fd,
                 BasePtr bp, DerivedPtr dp, FinalDerivedPtr fdp) {
  b += 1;
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'Base'

  d += 1;
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'Derived'

  fd += 1;
  // no-warning

  bp += 1;
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'Base'

  dp += 1;
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: pointer arithmetic on polymorphic object of type 'Derived'

  fdp += 1;
  // no-warning
}