| // RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -analyzer-config c++-inlining=destructors -std=c++11 -verify -Wno-tautological-undefined-compare %s |
| // RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config c++-inlining=destructors -std=c++11 %s -o %t.plist -Wno-tautological-undefined-compare |
| // RUN: %normalize_plist <%t.plist | diff -ub %S/Inputs/expected-plists/path-notes.cpp.plist - |
| |
| class Foo { |
| public: |
| static void use(int *p) { |
| *p = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}} |
| // expected-note@-1 {{Dereference of null pointer (loaded from variable 'p')}} |
| } |
| |
| Foo(int *p) { |
| use(p); |
| // expected-note@-1 {{Passing null pointer value via 1st parameter 'p'}} |
| // expected-note@-2 {{Calling 'Foo::use'}} |
| } |
| }; |
| |
| static int *globalPtr; |
| |
| class Bar { |
| public: |
| ~Bar() { |
| Foo f(globalPtr); |
| // expected-note@-1 {{Passing null pointer value via 1st parameter 'p'}} |
| // expected-note@-2 {{Calling constructor for 'Foo'}} |
| } |
| }; |
| |
| void test() { |
| Bar b; |
| globalPtr = 0; |
| // expected-note@-1 {{Null pointer value stored to 'globalPtr'}} |
| } // expected-note {{Calling '~Bar'}} |
| |
| |
| void testAnonymous() { |
| class { |
| public: |
| void method(int *p) { |
| *p = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}} |
| // expected-note@-1 {{Dereference of null pointer (loaded from variable 'p')}} |
| } |
| } anonymous; |
| |
| anonymous.method(0); |
| // expected-note@-1 {{Passing null pointer value via 1st parameter 'p'}} |
| // expected-note@-2 {{Calling 'method'}} |
| } |
| |
| |
| // A simplified version of std::move. |
| template <typename T> |
| T &&move(T &obj) { |
| return static_cast<T &&>(obj); |
| } |
| |
| |
| namespace defaulted { |
| class Dereferencer { |
| public: |
| Dereferencer() { |
| *globalPtr = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'globalPtr')}} |
| // expected-note@-1 {{Dereference of null pointer (loaded from variable 'globalPtr')}} |
| } |
| |
| Dereferencer(const Dereferencer &Other) { |
| *globalPtr = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'globalPtr')}} |
| // expected-note@-1 {{Dereference of null pointer (loaded from variable 'globalPtr')}} |
| } |
| |
| Dereferencer(Dereferencer &&Other) { |
| *globalPtr = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'globalPtr')}} |
| // expected-note@-1 {{Dereference of null pointer (loaded from variable 'globalPtr')}} |
| } |
| |
| void operator=(const Dereferencer &Other) { |
| *globalPtr = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'globalPtr')}} |
| // expected-note@-1 {{Dereference of null pointer (loaded from variable 'globalPtr')}} |
| } |
| |
| void operator=(Dereferencer &&Other) { |
| *globalPtr = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'globalPtr')}} |
| // expected-note@-1 {{Dereference of null pointer (loaded from variable 'globalPtr')}} |
| } |
| |
| ~Dereferencer() { |
| *globalPtr = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'globalPtr')}} |
| // expected-note@-1 {{Dereference of null pointer (loaded from variable 'globalPtr')}} |
| } |
| }; |
| |
| class Wrapper { |
| Dereferencer d; |
| }; |
| |
| class MovableWrapper { |
| Dereferencer d; |
| public: |
| MovableWrapper() = default; |
| |
| MovableWrapper(MovableWrapper &&Other) = default; |
| // expected-note@-1 {{Calling move constructor for 'Dereferencer'}} |
| |
| MovableWrapper &operator=(MovableWrapper &&Other) = default; |
| // expected-note@-1 {{Calling move assignment operator for 'Dereferencer'}} |
| }; |
| |
| void testDefaultConstruction() { |
| globalPtr = 0; |
| // expected-note@-1 {{Null pointer value stored to 'globalPtr'}} |
| Wrapper w; |
| // expected-note@-1 {{Calling implicit default constructor for 'Wrapper'}} |
| // expected-note@-2 {{Calling default constructor for 'Dereferencer'}} |
| } |
| |
| void testCopyConstruction(const Wrapper &input) { |
| globalPtr = 0; |
| // expected-note@-1 {{Null pointer value stored to 'globalPtr'}} |
| Wrapper w{input}; |
| // expected-note@-1 {{Calling implicit copy constructor for 'Wrapper'}} |
| // expected-note@-2 {{Calling copy constructor for 'Dereferencer'}} |
| } |
| |
| void testMoveConstruction(MovableWrapper &&input) { |
| globalPtr = 0; |
| // expected-note@-1 {{Null pointer value stored to 'globalPtr'}} |
| MovableWrapper w{move(input)}; |
| // expected-note@-1 {{Calling defaulted move constructor for 'MovableWrapper'}} |
| } |
| |
| void testCopyAssignment(const Wrapper &input) { |
| Wrapper w; |
| globalPtr = 0; |
| // expected-note@-1 {{Null pointer value stored to 'globalPtr'}} |
| w = input; |
| // expected-note@-1 {{Calling implicit copy assignment operator for 'Wrapper'}} |
| // expected-note@-2 {{Calling copy assignment operator for 'Dereferencer'}} |
| } |
| |
| void testMoveAssignment(MovableWrapper &&input) { |
| MovableWrapper w; |
| globalPtr = 0; |
| // expected-note@-1 {{Null pointer value stored to 'globalPtr'}} |
| w = move(input); |
| // expected-note@-1 {{Calling defaulted move assignment operator for 'MovableWrapper'}} |
| } |
| |
| void testDestruction() { |
| Wrapper w; |
| globalPtr = 0; |
| // expected-note@-1 {{Null pointer value stored to 'globalPtr'}} |
| } |
| // expected-note@-1 {{Calling implicit destructor for 'Wrapper'}} |
| // expected-note@-2 {{Calling '~Dereferencer'}} |
| } |
| |
| namespace ReturnZeroNote { |
| int getZero() { |
| return 0; |
| // expected-note@-1 {{Returning zero}} |
| } |
| |
| const int &getZeroByRef() { |
| static int zeroVar; |
| zeroVar = 0; |
| // expected-note@-1 {{The value 0 is assigned to 'zeroVar'}} |
| return zeroVar; |
| // expected-note@-1 {{Returning zero (reference to 'zeroVar')}} |
| } |
| |
| void test() { |
| int problem = 1 / getZero(); // expected-warning {{Division by zero}} |
| // expected-note@-1 {{Calling 'getZero'}} |
| // expected-note@-2 {{Returning from 'getZero'}} |
| // expected-note@-3 {{Division by zero}} |
| } |
| |
| void testRef() { |
| int problem = 1 / getZeroByRef(); // expected-warning {{Division by zero}} |
| // expected-note@-1 {{Calling 'getZeroByRef'}} |
| // expected-note@-2 {{Returning from 'getZeroByRef'}} |
| // expected-note@-3 {{Division by zero}} |
| } |
| } |
| |
| int &returnNullReference() { |
| int *x = 0; |
| // expected-note@-1 {{'x' initialized to a null pointer value}} |
| return *x; // expected-warning{{Returning null reference}} |
| // expected-note@-1 {{Returning null reference}} |
| } |
| |
| struct FooWithInitializer { |
| int *ptr; |
| FooWithInitializer(int *p) : ptr(p) { // expected-note {{Null pointer value stored to 'f.ptr'}} |
| *ptr = 1; // expected-note {{Dereference of null pointer (loaded from field 'ptr')}} |
| // expected-warning@-1 {{Dereference of null pointer (loaded from field 'ptr')}} |
| } |
| }; |
| |
| void testPathNoteOnInitializer() { |
| int *p = 0; // expected-note {{'p' initialized to a null pointer value}} |
| |
| FooWithInitializer f(p); // expected-note {{Passing null pointer value via 1st parameter 'p'}} |
| // expected-note@-1 {{Calling constructor for 'FooWithInitializer'}} |
| } |
| |
| int testNonPrintableAssignment(int **p) { |
| int *&y = *p; // expected-note {{'y' initialized here}} |
| y = 0; // expected-note {{Storing null pointer value}} |
| return *y; // expected-warning {{Dereference of null pointer (loaded from variable 'y')}} |
| // expected-note@-1 {{Dereference of null pointer (loaded from variable 'y')}} |
| } |
| |
| struct Base { int *x; }; |
| struct Derived : public Base {}; |
| |
| void test(Derived d) { |
| d.x = 0; //expected-note {{Null pointer value stored to 'd.x'}} |
| *d.x = 1; // expected-warning {{Dereference of null pointer (loaded from field 'x')}} |
| // expected-note@-1 {{Dereference of null pointer (loaded from field 'x')}} |
| } |
| |
| struct Owner { |
| struct Wrapper { |
| int x; |
| }; |
| Wrapper *arr; |
| void testGetDerefExprOnMemberExprWithADot(); |
| }; |
| |
| void Owner::testGetDerefExprOnMemberExprWithADot() { |
| if (arr) // expected-note {{Assuming field 'arr' is null}} |
| // expected-note@-1 {{Taking false branch}} |
| ; |
| arr[1].x = 1; //expected-warning {{Dereference of null pointer}} |
| //expected-note@-1 {{Dereference of null pointer}} |
| } |
| |
| void testGetDerefExprOnMemberExprWithADot() { |
| Owner::Wrapper *arr; // expected-note {{'arr' declared without an initial value}} |
| arr[2].x = 1; // expected-warning {{Dereference of undefined pointer value}} |
| // expected-note@-1 {{Dereference of undefined pointer value}} |
| } |
| |
| |
| |
| class A { |
| public: |
| void bar() const {} |
| }; |
| const A& testDeclRefExprToReferenceInGetDerefExpr(const A *ptr) { |
| const A& val = *ptr; //expected-note {{'val' initialized here}} |
| |
| // This is not valid C++; if 'ptr' were null, creating 'ref' would be illegal. |
| // However, this is not checked at runtime, so this branch is actually |
| // possible. |
| if (&val == 0) { //expected-note {{Assuming pointer value is null}} |
| // expected-note@-1 {{Taking true branch}} |
| val.bar(); // expected-warning {{Called C++ object pointer is null}} |
| // expected-note@-1 {{Called C++ object pointer is null}} |
| } |
| |
| return val; |
| } |
| |
| int generateNoteOnDefaultArgument(int one, int two = 0) { |
| return one/two; // expected-warning {{Division by zero}} |
| // expected-note@-1 {{Division by zero}} |
| } |
| int callGenerateNoteOnDefaultArgument(int o) { |
| return generateNoteOnDefaultArgument(o); //expected-note{{Calling 'generateNoteOnDefaultArgument'}} |
| //expected-note@-1 {{Passing the value 0 via 2nd parameter 'two'}} |
| } |
| |
| namespace PR17746 { |
| class Inner { |
| public: |
| ~Inner() { |
| *(volatile int *)0 = 1; // expected-warning {{Dereference of null pointer}} |
| // expected-note@-1 {{Dereference of null pointer}} |
| } |
| }; |
| |
| class Outer { |
| public: |
| Inner *inner; |
| ~Outer() { |
| delete inner; |
| // expected-note@-1 {{Calling '~Inner'}} |
| } |
| }; |
| |
| void test(Outer *outer) { |
| delete outer; |
| // expected-note@-1 {{Calling '~Outer'}} |
| } |
| } |
| |