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
}
|