1 // RUN: %clang_analyze_cc1 -std=c++14 \
2 // RUN: -analyzer-checker=core.CallAndMessage \
3 // RUN: -analyzer-config suppress-null-return-paths=false \
4 // RUN: -verify %s
5 // RUN: %clang_analyze_cc1 -std=c++14 \
6 // RUN: -analyzer-checker=core.CallAndMessage \
7 // RUN: -DSUPPRESSED \
8 // RUN: -verify %s
9
10 #ifdef SUPPRESSED
11 // expected-no-diagnostics
12 #endif
13
14 #include <stdint.h>
15 #include "../Inputs/system-header-simulator-cxx.h"
16
17 void error();
18 void *malloc(size_t);
19
20
21 // From llvm/include/llvm/Support/MathExtras.h
alignAddr(const void * Addr,size_t Alignment)22 inline uintptr_t alignAddr(const void *Addr, size_t Alignment) {
23 return (((uintptr_t)Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1));
24 }
25
alignmentAdjustment(const void * Ptr,size_t Alignment)26 inline size_t alignmentAdjustment(const void *Ptr, size_t Alignment) {
27 return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr;
28 }
29
30
31 // From llvm/include/llvm/Support/MemAlloc.h
safe_malloc(size_t Sz)32 inline void *safe_malloc(size_t Sz) {
33 void *Result = malloc(Sz);
34 if (Result == nullptr)
35 error();
36
37 return Result;
38 }
39
40
41 // From llvm/include/llvm/Support/Allocator.h
42 class MallocAllocator {
43 public:
Allocate(size_t Size,size_t)44 void *Allocate(size_t Size, size_t /*Alignment*/) {
45 return safe_malloc(Size);
46 }
47 };
48
49 class BumpPtrAllocator {
50 public:
Allocate(size_t Size,size_t Alignment)51 void *Allocate(size_t Size, size_t Alignment) {
52 BytesAllocated += Size;
53 size_t Adjustment = alignmentAdjustment(CurPtr, Alignment);
54 size_t SizeToAllocate = Size;
55
56 size_t PaddedSize = SizeToAllocate + Alignment - 1;
57 uintptr_t AlignedAddr = alignAddr(Allocator.Allocate(PaddedSize, 0),
58 Alignment);
59 char *AlignedPtr = (char*)AlignedAddr;
60
61 return AlignedPtr;
62 }
63
64 private:
65 char *CurPtr = nullptr;
66 size_t BytesAllocated = 0;
67 MallocAllocator Allocator;
68 };
69
70
71 // From clang/include/clang/AST/ASTContextAllocate.h
72 class ASTContext;
73
74 void *operator new(size_t Bytes, const ASTContext &C, size_t Alignment = 8);
75 void *operator new[](size_t Bytes, const ASTContext &C, size_t Alignment = 8);
76
77
78 // From clang/include/clang/AST/ASTContext.h
79 class ASTContext {
80 public:
Allocate(size_t Size,unsigned Align=8) const81 void *Allocate(size_t Size, unsigned Align = 8) const {
82 return BumpAlloc.Allocate(Size, Align);
83 }
84
85 template <typename T>
Allocate(size_t Num=1) const86 T *Allocate(size_t Num = 1) const {
87 return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T)));
88 }
89
90 private:
91 mutable BumpPtrAllocator BumpAlloc;
92 };
93
94
95 // From clang/include/clang/AST/ASTContext.h
operator new(size_t Bytes,const ASTContext & C,size_t Alignment)96 inline void *operator new(size_t Bytes, const ASTContext &C,
97 size_t Alignment /* = 8 */) {
98 return C.Allocate(Bytes, Alignment);
99 }
100
operator new[](size_t Bytes,const ASTContext & C,size_t Alignment)101 inline void *operator new[](size_t Bytes, const ASTContext &C,
102 size_t Alignment /* = 8 */) {
103 return C.Allocate(Bytes, Alignment);
104 }
105
106
107 // From clang/include/clang/AST/Attr.h
operator new(size_t Bytes,ASTContext & C,size_t Alignment=8)108 void *operator new(size_t Bytes, ASTContext &C,
109 size_t Alignment = 8) noexcept {
110 return ::operator new(Bytes, C, Alignment);
111 }
112
113
114 class A {
115 public:
setValue(int value)116 void setValue(int value) { Value = value; }
117 private:
118 int Value;
119 };
120
f(const ASTContext & C)121 void f(const ASTContext &C) {
122 A *a = new (C) A;
123 a->setValue(13);
124 #ifndef SUPPRESSED
125 // expected-warning@-2 {{Called C++ object pointer is null}}
126 #endif
127 }
128
g(const ASTContext & C)129 void g(const ASTContext &C) {
130 A *a = new (C) A[1];
131 a[0].setValue(13);
132 #ifndef SUPPRESSED
133 // expected-warning@-2 {{Called C++ object pointer is null}}
134 #endif
135 }
136
137