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