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