summaryrefslogtreecommitdiffstats
path: root/tests/cxx/placement_new.cc
blob: a879a4ae8c3c4f45b999967522021092c8b49120 (plain) (blame)
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
141
142
143
144
145
146
147
148
149
150
151
//===--- placement_new.cc - test input file for iwyu ----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// Test that use of placement-new requires include of <new> in all the usual
// scenarios.
//
// Requires -std=c++17 on the command-line to have std::aligned_val_t available
// in <new>.

#include "tests/cxx/direct.h"
#include "tests/cxx/placement_new-d1.h"

// Placement new of builtin types.
void PlacementNewBuiltinType() {
  // Make sure we only report a use of <new> because of placement new, not
  // ordinary new-expressions.
  int* newed_int = new int;
  // IWYU: operator new is...*<new>
  new (newed_int) int(4);

  delete newed_int;
}

// Placement new of user-defined type.
void PlacementNewUserType() {
  // IWYU: IndirectClass needs a declaration
  // IWYU: IndirectClass is...*indirect.h
  IndirectClass* icptr = new IndirectClass;

  // IWYU: IndirectClass is...*indirect.h
  // IWYU: operator new is...*<new>
  new (icptr) IndirectClass;

  // IWYU: IndirectClass is...*indirect.h
  delete icptr;
}

// Placement new in macro, use is attributed to the macro.
static char global_buffer[256];
// IWYU: operator new is...*<new>
#define CONSTRUCT_GLOBAL(T) new (global_buffer) T;

void PlacementNewInMacro() {
  // IWYU: IndirectClass needs a declaration
  // IWYU: IndirectClass is...*indirect.h
  IndirectClass* a = CONSTRUCT_GLOBAL(IndirectClass);
}

// Placement new inside a template.
template <typename T>
void PlacementNewInTemplate(T t) {
  static char buffer[sizeof(t)];
  // These should all be iwyu violations here, even though we can't be
  // *sure* some of these are actually placement new until we get a
  // specific type for T (at template-instantiation time).
  // IWYU: operator new is...*<new>
  new (&t) int;
  // IWYU: operator new is...*<new>
  new (buffer) T();
  // IWYU: operator new is...*<new>
  new (&t) T();
}

// Placement new when the newed type _is_ a template.
void PlacementNewOfTemplate() {
  // IWYU: IndirectClass needs a declaration
  // IWYU: IndirectClass is...*indirect.h
  // IWYU: ClassTemplate is...*placement_new-i1.h
  char template_storage[sizeof(ClassTemplate<IndirectClass, IndirectClass>)];

  // IWYU: IndirectClass needs a declaration
  // IWYU: ClassTemplate needs a declaration
  ClassTemplate<IndirectClass, IndirectClass>* placement_newed_template =
      // Need <new> because of placement new, and requires both template and
      // arguments as complete types.
      //
      // IWYU: IndirectClass needs a declaration
      // IWYU: IndirectClass is...*indirect.h
      // IWYU: ClassTemplate is...*placement_new-i1.h
      // IWYU: operator new is...*<new>
      new (template_storage) ClassTemplate<IndirectClass, IndirectClass>();

  // Make sure we handle it right when we explicitly call the dtor, as well.
  // IWYU: ClassTemplate is...*placement_new-i1.h
  placement_newed_template->~ClassTemplate();
}

// new(std::nothrow) is not strictly placement allocation, but it uses placement
// syntax to adjust exception policy.
// To use 'std::nothrow' we must include <new>, even if we don't need it for
// 'new' itself.
void NoThrow() {
  // IWYU: IndirectClass needs a declaration
  // IWYU: IndirectClass is...*indirect.h
  // IWYU: std::nothrow is...*<new>
  IndirectClass* elem = new (std::nothrow) IndirectClass;
  // IWYU: IndirectClass is...*indirect.h
  delete elem;

  // IWYU: IndirectClass needs a declaration
  // IWYU: IndirectClass is...*indirect.h
  // IWYU: std::nothrow is...*<new>
  IndirectClass* arr = new (std::nothrow) IndirectClass[4];
  // IWYU: IndirectClass is...*indirect.h
  delete[] arr;
}

// new(std::align_val_t) is not strictly placement allocation, but it uses
// placement syntax to provide alignment hints.
// To use 'std::align_val_t' we must include <new>, even if we don't need it
// for 'new' itself.
// The aligned allocation mechanics are only available as of C++17.
void ExplicitAlignedAllocation() {
  // IWYU: IndirectClass needs a declaration
  // IWYU: IndirectClass is...*indirect.h
  // IWYU: std::align_val_t is...*<new>
  IndirectClass* elem = new (std::align_val_t(32)) IndirectClass;
  // IWYU: IndirectClass is...*indirect.h
  delete elem;

  // IWYU: IndirectClass needs a declaration
  // IWYU: IndirectClass is...*indirect.h
  // IWYU: std::align_val_t is...*<new>
  IndirectClass* arr = new (std::align_val_t(32)) IndirectClass[10];
  // IWYU: IndirectClass is...*indirect.h
  delete[] arr;
}

/**** IWYU_SUMMARY

tests/cxx/placement_new.cc should add these lines:
#include <new>
#include "tests/cxx/indirect.h"
#include "tests/cxx/placement_new-i1.h"

tests/cxx/placement_new.cc should remove these lines:
- #include "tests/cxx/direct.h"  // lines XX-XX
- #include "tests/cxx/placement_new-d1.h"  // lines XX-XX

The full include-list for tests/cxx/placement_new.cc:
#include <new>  // for align_val_t, nothrow, operator new
#include "tests/cxx/indirect.h"  // for IndirectClass
#include "tests/cxx/placement_new-i1.h"  // for ClassTemplate

***** IWYU_SUMMARY */