Coverage Report

Created: 2018-09-23 03:40

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/include/clang/Analysis/ConstructionContext.h
Line
Count
Source (jump to first uncovered line)
1
//===- ConstructionContext.h - CFG constructor information ------*- C++ -*-===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
// This file defines the ConstructionContext class and its sub-classes,
11
// which represent various different ways of constructing C++ objects
12
// with the additional information the users may want to know about
13
// the constructor.
14
//
15
//===----------------------------------------------------------------------===//
16
17
#ifndef LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
18
#define LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
19
20
#include "clang/Analysis/Support/BumpVector.h"
21
#include "clang/AST/ExprCXX.h"
22
23
namespace clang {
24
25
/// Represents a single point (AST node) in the program that requires attention
26
/// during construction of an object. ConstructionContext would be represented
27
/// as a list of such items.
28
class ConstructionContextItem {
29
public:
30
  enum ItemKind {
31
    VariableKind,
32
    NewAllocatorKind,
33
    ReturnKind,
34
    MaterializationKind,
35
    TemporaryDestructorKind,
36
    ElidedDestructorKind,
37
    ElidableConstructorKind,
38
    ArgumentKind,
39
    STATEMENT_WITH_INDEX_KIND_BEGIN=ArgumentKind,
40
    STATEMENT_WITH_INDEX_KIND_END=ArgumentKind,
41
    STATEMENT_KIND_BEGIN = VariableKind,
42
    STATEMENT_KIND_END = ArgumentKind,
43
    InitializerKind,
44
    INITIALIZER_KIND_BEGIN=InitializerKind,
45
    INITIALIZER_KIND_END=InitializerKind
46
  };
47
48
0
  LLVM_DUMP_METHOD static StringRef getKindAsString(ItemKind K) {
49
0
    switch (K) {
50
0
      case VariableKind:            return "construct into local variable";
51
0
      case NewAllocatorKind:        return "construct into new-allocator";
52
0
      case ReturnKind:              return "construct into return address";
53
0
      case MaterializationKind:     return "materialize temporary";
54
0
      case TemporaryDestructorKind: return "destroy temporary";
55
0
      case ElidedDestructorKind:    return "elide destructor";
56
0
      case ElidableConstructorKind: return "elide constructor";
57
0
      case ArgumentKind:            return "construct into argument";
58
0
      case InitializerKind:         return "construct into member variable";
59
0
    };
60
0
    llvm_unreachable("Unknown ItemKind");
61
0
  }
62
63
private:
64
  const void *const Data;
65
  const ItemKind Kind;
66
  const unsigned Index = 0;
67
68
0
  bool hasStatement() const {
69
0
    return Kind >= STATEMENT_KIND_BEGIN &&
70
0
           Kind <= STATEMENT_KIND_END;
71
0
  }
72
73
  bool hasIndex() const {
74
    return Kind >= STATEMENT_WITH_INDEX_KIND_BEGIN &&
75
           Kind >= STATEMENT_WITH_INDEX_KIND_END;
76
  }
77
78
  bool hasInitializer() const {
79
    return Kind >= INITIALIZER_KIND_BEGIN &&
80
           Kind <= INITIALIZER_KIND_END;
81
  }
82
83
public:
84
  // ConstructionContextItem should be simple enough so that it was easy to
85
  // re-construct it from the AST node it captures. For that reason we provide
86
  // simple implicit conversions from all sorts of supported AST nodes.
87
  ConstructionContextItem(const DeclStmt *DS)
88
384k
      : Data(DS), Kind(VariableKind) {}
89
90
  ConstructionContextItem(const CXXNewExpr *NE)
91
7.16k
      : Data(NE), Kind(NewAllocatorKind) {}
92
93
  ConstructionContextItem(const ReturnStmt *RS)
94
353k
      : Data(RS), Kind(ReturnKind) {}
95
96
  ConstructionContextItem(const MaterializeTemporaryExpr *MTE)
97
28.1k
      : Data(MTE), Kind(MaterializationKind) {}
98
99
  ConstructionContextItem(const CXXBindTemporaryExpr *BTE,
100
                          bool IsElided = false)
101
      : Data(BTE),
102
9.36k
        Kind(IsElided ? ElidedDestructorKind : TemporaryDestructorKind) {}
103
104
  ConstructionContextItem(const CXXConstructExpr *CE)
105
22.5k
      : Data(CE), Kind(ElidableConstructorKind) {}
106
107
  ConstructionContextItem(const CallExpr *CE, unsigned Index)
108
5.77k
      : Data(CE), Kind(ArgumentKind), Index(Index) {}
109
110
  ConstructionContextItem(const CXXConstructExpr *CE, unsigned Index)
111
2.05k
      : Data(CE), Kind(ArgumentKind), Index(Index) {}
112
113
  ConstructionContextItem(const ObjCMessageExpr *ME, unsigned Index)
114
21
      : Data(ME), Kind(ArgumentKind), Index(Index) {}
115
116
  // A polymorphic version of the previous calls with dynamic type check.
117
  ConstructionContextItem(const Expr *E, unsigned Index)
118
90.4k
      : Data(E), Kind(ArgumentKind), Index(Index) {
119
90.4k
    assert(isa<CallExpr>(E) || isa<CXXConstructExpr>(E) ||
120
90.4k
           isa<ObjCMessageExpr>(E));
121
90.4k
  }
122
123
  ConstructionContextItem(const CXXCtorInitializer *Init)
124
78.7k
      : Data(Init), Kind(InitializerKind), Index(0) {}
125
126
19.8k
  ItemKind getKind() const { return Kind; }
127
128
0
  LLVM_DUMP_METHOD StringRef getKindAsString() const {
129
0
    return getKindAsString(getKind());
130
0
  }
131
132
  /// The construction site - the statement that triggered the construction
133
  /// for one of its parts. For instance, stack variable declaration statement
134
  /// triggers construction of itself or its elements if it's an array,
135
  /// new-expression triggers construction of the newly allocated object(s).
136
17.3k
  const Stmt *getStmt() const {
137
17.3k
    assert(hasStatement());
138
17.3k
    return static_cast<const Stmt *>(Data);
139
17.3k
  }
140
141
0
  const Stmt *getStmtOrNull() const {
142
0
    return hasStatement() ? getStmt() : nullptr;
143
0
  }
144
145
  /// The construction site is not necessarily a statement. It may also be a
146
  /// CXXCtorInitializer, which means that a member variable is being
147
  /// constructed during initialization of the object that contains it.
148
1.36k
  const CXXCtorInitializer *getCXXCtorInitializer() const {
149
1.36k
    assert(hasInitializer());
150
1.36k
    return static_cast<const CXXCtorInitializer *>(Data);
151
1.36k
  }
152
153
  /// If a single trigger statement triggers multiple constructors, they are
154
  /// usually being enumerated. This covers function argument constructors
155
  /// triggered by a call-expression and items in an initializer list triggered
156
  /// by an init-list-expression.
157
1.35k
  unsigned getIndex() const {
158
1.35k
    // This is a fairly specific request. Let's make sure the user knows
159
1.35k
    // what he's doing.
160
1.35k
    assert(hasIndex());
161
1.35k
    return Index;
162
1.35k
  }
163
164
27.8k
  void Profile(llvm::FoldingSetNodeID &ID) const {
165
27.8k
    ID.AddPointer(Data);
166
27.8k
    ID.AddInteger(Kind);
167
27.8k
    ID.AddInteger(Index);
168
27.8k
  }
169
170
86.1k
  bool operator==(const ConstructionContextItem &Other) const {
171
86.1k
    // For most kinds the Index comparison is trivially true, but
172
86.1k
    // checking kind separately doesn't seem to be less expensive
173
86.1k
    // than checking Index. Same in operator<().
174
86.1k
    return std::make_tuple(Data, Kind, Index) ==
175
86.1k
           std::make_tuple(Other.Data, Other.Kind, Other.Index);
176
86.1k
  }
177
178
62.1k
  bool operator<(const ConstructionContextItem &Other) const {
179
62.1k
    return std::make_tuple(Data, Kind, Index) <
180
62.1k
           std::make_tuple(Other.Data, Other.Kind, Other.Index);
181
62.1k
  }
182
};
183
184
/// Construction context can be seen as a linked list of multiple layers.
185
/// Sometimes a single trigger is not enough to describe the construction
186
/// site. That's what causing us to have a chain of "partial" construction
187
/// context layers. Some examples:
188
/// - A constructor within in an aggregate initializer list within a variable
189
///   would have a construction context of the initializer list with
190
///   the parent construction context of a variable.
191
/// - A constructor for a temporary that needs to be both destroyed
192
///   and materialized into an elidable copy constructor would have a
193
///   construction context of a CXXBindTemporaryExpr with the parent
194
///   construction context of a MaterializeTemproraryExpr.
195
/// Not all of these are currently supported.
196
/// Layers are created gradually while traversing the AST, and layers that
197
/// represent the outmost AST nodes are built first, while the node that
198
/// immediately contains the constructor would be built last and capture the
199
/// previous layers as its parents. Construction context captures the last layer
200
/// (which has links to the previous layers) and classifies the seemingly
201
/// arbitrary chain of layers into one of the possible ways of constructing
202
/// an object in C++ for user-friendly experience.
203
class ConstructionContextLayer {
204
  const ConstructionContextLayer *Parent = nullptr;
205
  ConstructionContextItem Item;
206
207
  ConstructionContextLayer(ConstructionContextItem Item,
208
                           const ConstructionContextLayer *Parent)
209
823k
      : Parent(Parent), Item(Item) {}
210
211
public:
212
  static const ConstructionContextLayer *
213
  create(BumpVectorContext &C, const ConstructionContextItem &Item,
214
         const ConstructionContextLayer *Parent = nullptr);
215
216
21.9k
  const ConstructionContextItem &getItem() const { return Item; }
217
8.58k
  const ConstructionContextLayer *getParent() const { return Parent; }
218
  bool isLast() const { return !Parent; }
219
220
  /// See if Other is a proper initial segment of this construction context
221
  /// in terms of the parent chain - i.e. a few first parents coincide and
222
  /// then the other context terminates but our context goes further - i.e.,
223
  /// we are providing the same context that the other context provides,
224
  /// and a bit more above that.
225
  bool isStrictlyMoreSpecificThan(const ConstructionContextLayer *Other) const;
226
};
227
228
229
/// ConstructionContext's subclasses describe different ways of constructing
230
/// an object in C++. The context re-captures the essential parent AST nodes
231
/// of the CXXConstructExpr it is assigned to and presents these nodes
232
/// through easy-to-understand accessor methods.
233
class ConstructionContext {
234
public:
235
  enum Kind {
236
    SimpleVariableKind,
237
    CXX17ElidedCopyVariableKind,
238
    VARIABLE_BEGIN = SimpleVariableKind,
239
    VARIABLE_END = CXX17ElidedCopyVariableKind,
240
    SimpleConstructorInitializerKind,
241
    CXX17ElidedCopyConstructorInitializerKind,
242
    INITIALIZER_BEGIN = SimpleConstructorInitializerKind,
243
    INITIALIZER_END = CXX17ElidedCopyConstructorInitializerKind,
244
    NewAllocatedObjectKind,
245
    SimpleTemporaryObjectKind,
246
    ElidedTemporaryObjectKind,
247
    TEMPORARY_BEGIN = SimpleTemporaryObjectKind,
248
    TEMPORARY_END = ElidedTemporaryObjectKind,
249
    SimpleReturnedValueKind,
250
    CXX17ElidedCopyReturnedValueKind,
251
    RETURNED_VALUE_BEGIN = SimpleReturnedValueKind,
252
    RETURNED_VALUE_END = CXX17ElidedCopyReturnedValueKind,
253
    ArgumentKind
254
  };
255
256
protected:
257
  Kind K;
258
259
  // Do not make public! These need to only be constructed
260
  // via createFromLayers().
261
14.4k
  explicit ConstructionContext(Kind K) : K(K) {}
262
263
private:
264
  // A helper function for constructing an instance into a bump vector context.
265
  template <typename T, typename... ArgTypes>
266
14.4k
  static T *create(BumpVectorContext &C, ArgTypes... Args) {
267
14.4k
    auto *CC = C.getAllocator().Allocate<T>();
268
14.4k
    return new (CC) T(Args...);
269
14.4k
  }
clang::SimpleTemporaryObjectConstructionContext* clang::ConstructionContext::create<clang::SimpleTemporaryObjectConstructionContext, clang::CXXBindTemporaryExpr const*, clang::MaterializeTemporaryExpr const*>(clang::BumpVectorContext&, clang::CXXBindTemporaryExpr const*, clang::MaterializeTemporaryExpr const*)
Line
Count
Source
266
1.96k
  static T *create(BumpVectorContext &C, ArgTypes... Args) {
267
1.96k
    auto *CC = C.getAllocator().Allocate<T>();
268
1.96k
    return new (CC) T(Args...);
269
1.96k
  }
clang::ElidedTemporaryObjectConstructionContext* clang::ConstructionContext::create<clang::ElidedTemporaryObjectConstructionContext, clang::CXXBindTemporaryExpr const*, clang::MaterializeTemporaryExpr const*, clang::CXXConstructExpr const*, clang::ConstructionContext const*>(clang::BumpVectorContext&, clang::CXXBindTemporaryExpr const*, clang::MaterializeTemporaryExpr const*, clang::CXXConstructExpr const*, clang::ConstructionContext const*)
Line
Count
Source
266
2.16k
  static T *create(BumpVectorContext &C, ArgTypes... Args) {
267
2.16k
    auto *CC = C.getAllocator().Allocate<T>();
268
2.16k
    return new (CC) T(Args...);
269
2.16k
  }
clang::SimpleTemporaryObjectConstructionContext* clang::ConstructionContext::create<clang::SimpleTemporaryObjectConstructionContext, clang::CXXBindTemporaryExpr const*, std::nullptr_t>(clang::BumpVectorContext&, clang::CXXBindTemporaryExpr const*, std::nullptr_t)
Line
Count
Source
266
248
  static T *create(BumpVectorContext &C, ArgTypes... Args) {
267
248
    auto *CC = C.getAllocator().Allocate<T>();
268
248
    return new (CC) T(Args...);
269
248
  }
clang::CXX17ElidedCopyVariableConstructionContext* clang::ConstructionContext::create<clang::CXX17ElidedCopyVariableConstructionContext, clang::DeclStmt const*, clang::CXXBindTemporaryExpr const*>(clang::BumpVectorContext&, clang::DeclStmt const*, clang::CXXBindTemporaryExpr const*)
Line
Count
Source
266
60
  static T *create(BumpVectorContext &C, ArgTypes... Args) {
267
60
    auto *CC = C.getAllocator().Allocate<T>();
268
60
    return new (CC) T(Args...);
269
60
  }
clang::CXX17ElidedCopyReturnedValueConstructionContext* clang::ConstructionContext::create<clang::CXX17ElidedCopyReturnedValueConstructionContext, clang::ReturnStmt const*, clang::CXXBindTemporaryExpr const*>(clang::BumpVectorContext&, clang::ReturnStmt const*, clang::CXXBindTemporaryExpr const*)
Line
Count
Source
266
66
  static T *create(BumpVectorContext &C, ArgTypes... Args) {
267
66
    auto *CC = C.getAllocator().Allocate<T>();
268
66
    return new (CC) T(Args...);
269
66
  }
clang::ArgumentConstructionContext* clang::ConstructionContext::create<clang::ArgumentConstructionContext, clang::Expr const*, unsigned int, clang::CXXBindTemporaryExpr const*>(clang::BumpVectorContext&, clang::Expr const*, unsigned int, clang::CXXBindTemporaryExpr const*)
Line
Count
Source
266
172
  static T *create(BumpVectorContext &C, ArgTypes... Args) {
267
172
    auto *CC = C.getAllocator().Allocate<T>();
268
172
    return new (CC) T(Args...);
269
172
  }
clang::CXX17ElidedCopyConstructorInitializerConstructionContext* clang::ConstructionContext::create<clang::CXX17ElidedCopyConstructorInitializerConstructionContext, clang::CXXCtorInitializer const*, clang::CXXBindTemporaryExpr const*>(clang::BumpVectorContext&, clang::CXXCtorInitializer const*, clang::CXXBindTemporaryExpr const*)
Line
Count
Source
266
12
  static T *create(BumpVectorContext &C, ArgTypes... Args) {
267
12
    auto *CC = C.getAllocator().Allocate<T>();
268
12
    return new (CC) T(Args...);
269
12
  }
clang::SimpleVariableConstructionContext* clang::ConstructionContext::create<clang::SimpleVariableConstructionContext, clang::DeclStmt const*>(clang::BumpVectorContext&, clang::DeclStmt const*)
Line
Count
Source
266
5.53k
  static T *create(BumpVectorContext &C, ArgTypes... Args) {
267
5.53k
    auto *CC = C.getAllocator().Allocate<T>();
268
5.53k
    return new (CC) T(Args...);
269
5.53k
  }
clang::NewAllocatedObjectConstructionContext* clang::ConstructionContext::create<clang::NewAllocatedObjectConstructionContext, clang::CXXNewExpr const*>(clang::BumpVectorContext&, clang::CXXNewExpr const*)
Line
Count
Source
266
693
  static T *create(BumpVectorContext &C, ArgTypes... Args) {
267
693
    auto *CC = C.getAllocator().Allocate<T>();
268
693
    return new (CC) T(Args...);
269
693
  }
clang::SimpleReturnedValueConstructionContext* clang::ConstructionContext::create<clang::SimpleReturnedValueConstructionContext, clang::ReturnStmt const*>(clang::BumpVectorContext&, clang::ReturnStmt const*)
Line
Count
Source
266
1.04k
  static T *create(BumpVectorContext &C, ArgTypes... Args) {
267
1.04k
    auto *CC = C.getAllocator().Allocate<T>();
268
1.04k
    return new (CC) T(Args...);
269
1.04k
  }
clang::SimpleConstructorInitializerConstructionContext* clang::ConstructionContext::create<clang::SimpleConstructorInitializerConstructionContext, clang::CXXCtorInitializer const*>(clang::BumpVectorContext&, clang::CXXCtorInitializer const*)
Line
Count
Source
266
1.34k
  static T *create(BumpVectorContext &C, ArgTypes... Args) {
267
1.34k
    auto *CC = C.getAllocator().Allocate<T>();
268
1.34k
    return new (CC) T(Args...);
269
1.34k
  }
clang::ArgumentConstructionContext* clang::ConstructionContext::create<clang::ArgumentConstructionContext, clang::Expr const*, unsigned int, std::nullptr_t>(clang::BumpVectorContext&, clang::Expr const*, unsigned int, std::nullptr_t)
Line
Count
Source
266
1.18k
  static T *create(BumpVectorContext &C, ArgTypes... Args) {
267
1.18k
    auto *CC = C.getAllocator().Allocate<T>();
268
1.18k
    return new (CC) T(Args...);
269
1.18k
  }
270
271
  // A sub-routine of createFromLayers() that deals with temporary objects
272
  // that need to be materialized. The BTE argument is for the situation when
273
  // the object also needs to be bound for destruction.
274
  static const ConstructionContext *createMaterializedTemporaryFromLayers(
275
      BumpVectorContext &C, const MaterializeTemporaryExpr *MTE,
276
      const CXXBindTemporaryExpr *BTE,
277
      const ConstructionContextLayer *ParentLayer);
278
279
  // A sub-routine of createFromLayers() that deals with temporary objects
280
  // that need to be bound for destruction. Automatically finds out if the
281
  // object also needs to be materialized and delegates to
282
  // createMaterializedTemporaryFromLayers() if necessary.
283
  static const ConstructionContext *
284
  createBoundTemporaryFromLayers(
285
      BumpVectorContext &C, const CXXBindTemporaryExpr *BTE,
286
      const ConstructionContextLayer *ParentLayer);
287
288
public:
289
  /// Consume the construction context layer, together with its parent layers,
290
  /// and wrap it up into a complete construction context. May return null
291
  /// if layers do not form any supported construction context.
292
  static const ConstructionContext *
293
  createFromLayers(BumpVectorContext &C,
294
                   const ConstructionContextLayer *TopLayer);
295
296
22.0k
  Kind getKind() const { return K; }
297
};
298
299
/// An abstract base class for local variable constructors.
300
class VariableConstructionContext : public ConstructionContext {
301
  const DeclStmt *DS;
302
303
protected:
304
  VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS)
305
5.59k
      : ConstructionContext(K), DS(DS) {
306
5.59k
    assert(classof(this));
307
5.59k
    assert(DS);
308
5.59k
  }
309
310
public:
311
5.58k
  const DeclStmt *getDeclStmt() const { return DS; }
312
313
  static bool classof(const ConstructionContext *CC) {
314
    return CC->getKind() >= VARIABLE_BEGIN &&
315
           CC->getKind() <= VARIABLE_END;
316
  }
317
};
318
319
/// Represents construction into a simple local variable, eg. T var(123);.
320
/// If a variable has an initializer, eg. T var = makeT();, then the final
321
/// elidable copy-constructor from makeT() into var would also be a simple
322
/// variable constructor handled by this class.
323
class SimpleVariableConstructionContext : public VariableConstructionContext {
324
  friend class ConstructionContext; // Allows to create<>() itself.
325
326
  explicit SimpleVariableConstructionContext(const DeclStmt *DS)
327
      : VariableConstructionContext(ConstructionContext::SimpleVariableKind,
328
5.53k
                                    DS) {}
329
330
public:
331
  static bool classof(const ConstructionContext *CC) {
332
    return CC->getKind() == SimpleVariableKind;
333
  }
334
};
335
336
/// Represents construction into a simple variable with an initializer syntax,
337
/// with a single constructor, eg. T var = makeT();. Such construction context
338
/// may only appear in C++17 because previously it was split into a temporary
339
/// object constructor and an elidable simple variable copy-constructor and
340
/// we were producing separate construction contexts for these constructors.
341
/// In C++17 we have a single construction context that combines both.
342
/// Note that if the object has trivial destructor, then this code is
343
/// indistinguishable from a simple variable constructor on the AST level;
344
/// in this case we provide a simple variable construction context.
345
class CXX17ElidedCopyVariableConstructionContext
346
    : public VariableConstructionContext {
347
  const CXXBindTemporaryExpr *BTE;
348
349
  friend class ConstructionContext; // Allows to create<>() itself.
350
351
  explicit CXX17ElidedCopyVariableConstructionContext(
352
      const DeclStmt *DS, const CXXBindTemporaryExpr *BTE)
353
60
      : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) {
354
60
    assert(BTE);
355
60
  }
356
357
public:
358
4
  const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
359
360
  static bool classof(const ConstructionContext *CC) {
361
    return CC->getKind() == CXX17ElidedCopyVariableKind;
362
  }
363
};
364
365
// An abstract base class for constructor-initializer-based constructors.
366
class ConstructorInitializerConstructionContext : public ConstructionContext {
367
  const CXXCtorInitializer *I;
368
369
protected:
370
  explicit ConstructorInitializerConstructionContext(
371
      ConstructionContext::Kind K, const CXXCtorInitializer *I)
372
1.36k
      : ConstructionContext(K), I(I) {
373
1.36k
    assert(classof(this));
374
1.36k
    assert(I);
375
1.36k
  }
376
377
public:
378
831
  const CXXCtorInitializer *getCXXCtorInitializer() const { return I; }
379
380
  static bool classof(const ConstructionContext *CC) {
381
    return CC->getKind() >= INITIALIZER_BEGIN &&
382
           CC->getKind() <= INITIALIZER_END;
383
  }
384
};
385
386
/// Represents construction into a field or a base class within a bigger object
387
/// via a constructor initializer, eg. T(): field(123) { ... }.
388
class SimpleConstructorInitializerConstructionContext
389
    : public ConstructorInitializerConstructionContext {
390
  friend class ConstructionContext; // Allows to create<>() itself.
391
392
  explicit SimpleConstructorInitializerConstructionContext(
393
      const CXXCtorInitializer *I)
394
      : ConstructorInitializerConstructionContext(
395
1.34k
            ConstructionContext::SimpleConstructorInitializerKind, I) {}
396
397
public:
398
  static bool classof(const ConstructionContext *CC) {
399
    return CC->getKind() == SimpleConstructorInitializerKind;
400
  }
401
};
402
403
/// Represents construction into a field or a base class within a bigger object
404
/// via a constructor initializer, with a single constructor, eg.
405
/// T(): field(Field(123)) { ... }. Such construction context may only appear
406
/// in C++17 because previously it was split into a temporary object constructor
407
/// and an elidable simple constructor-initializer copy-constructor and we were
408
/// producing separate construction contexts for these constructors. In C++17
409
/// we have a single construction context that combines both. Note that if the
410
/// object has trivial destructor, then this code is indistinguishable from
411
/// a simple constructor-initializer constructor on the AST level; in this case
412
/// we provide a simple constructor-initializer construction context.
413
class CXX17ElidedCopyConstructorInitializerConstructionContext
414
    : public ConstructorInitializerConstructionContext {
415
  const CXXBindTemporaryExpr *BTE;
416
417
  friend class ConstructionContext; // Allows to create<>() itself.
418
419
  explicit CXX17ElidedCopyConstructorInitializerConstructionContext(
420
      const CXXCtorInitializer *I, const CXXBindTemporaryExpr *BTE)
421
      : ConstructorInitializerConstructionContext(
422
            CXX17ElidedCopyConstructorInitializerKind, I),
423
12
        BTE(BTE) {
424
12
    assert(BTE);
425
12
  }
426
427
public:
428
2
  const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
429
430
  static bool classof(const ConstructionContext *CC) {
431
    return CC->getKind() == CXX17ElidedCopyConstructorInitializerKind;
432
  }
433
};
434
435
/// Represents immediate initialization of memory allocated by operator new,
436
/// eg. new T(123);.
437
class NewAllocatedObjectConstructionContext : public ConstructionContext {
438
  const CXXNewExpr *NE;
439
440
  friend class ConstructionContext; // Allows to create<>() itself.
441
442
  explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE)
443
      : ConstructionContext(ConstructionContext::NewAllocatedObjectKind),
444
693
        NE(NE) {
445
693
    assert(NE);
446
693
  }
447
448
public:
449
482
  const CXXNewExpr *getCXXNewExpr() const { return NE; }
450
451
4.09k
  static bool classof(const ConstructionContext *CC) {
452
4.09k
    return CC->getKind() == NewAllocatedObjectKind;
453
4.09k
  }
454
};
455
456
/// Represents a temporary object, eg. T(123), that does not immediately cross
457
/// function boundaries "by value"; constructors that construct function
458
/// value-type arguments or values that are immediately returned from the
459
/// function that returns a value receive separate construction context kinds.
460
class TemporaryObjectConstructionContext : public ConstructionContext {
461
  const CXXBindTemporaryExpr *BTE;
462
  const MaterializeTemporaryExpr *MTE;
463
464
protected:
465
  explicit TemporaryObjectConstructionContext(
466
      ConstructionContext::Kind K, const CXXBindTemporaryExpr *BTE,
467
      const MaterializeTemporaryExpr *MTE)
468
4.37k
      : ConstructionContext(K), BTE(BTE), MTE(MTE) {
469
4.37k
    // Both BTE and MTE can be null here, all combinations possible.
470
4.37k
    // Even though for now at least one should be non-null, we simply haven't
471
4.37k
    // implemented the other case yet (this would be a temporary in the middle
472
4.37k
    // of nowhere that doesn't have a non-trivial destructor).
473
4.37k
  }
474
475
public:
476
  /// CXXBindTemporaryExpr here is non-null as long as the temporary has
477
  /// a non-trivial destructor.
478
3.06k
  const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const {
479
3.06k
    return BTE;
480
3.06k
  }
481
482
  /// MaterializeTemporaryExpr is non-null as long as the temporary is actually
483
  /// used after construction, eg. by binding to a reference (lifetime
484
  /// extension), accessing a field, calling a method, or passing it into
485
  /// a function (an elidable copy or move constructor would be a common
486
  /// example) by reference.
487
3.06k
  const MaterializeTemporaryExpr *getMaterializedTemporaryExpr() const {
488
3.06k
    return MTE;
489
3.06k
  }
490
491
  static bool classof(const ConstructionContext *CC) {
492
    return CC->getKind() >= TEMPORARY_BEGIN && CC->getKind() <= TEMPORARY_END;
493
  }
494
};
495
496
/// Represents a temporary object that is not constructed for the purpose of
497
/// being immediately copied/moved by an elidable copy/move-constructor.
498
/// This includes temporary objects "in the middle of nowhere" like T(123) and
499
/// lifetime-extended temporaries.
500
class SimpleTemporaryObjectConstructionContext
501
    : public TemporaryObjectConstructionContext {
502
  friend class ConstructionContext; // Allows to create<>() itself.
503
504
  explicit SimpleTemporaryObjectConstructionContext(
505
      const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE)
506
      : TemporaryObjectConstructionContext(
507
2.21k
            ConstructionContext::SimpleTemporaryObjectKind, BTE, MTE) {}
508
509
public:
510
  static bool classof(const ConstructionContext *CC) {
511
    return CC->getKind() == SimpleTemporaryObjectKind;
512
  }
513
};
514
515
/// Represents a temporary object that is constructed for the sole purpose
516
/// of being immediately copied by an elidable copy/move constructor.
517
/// For example, T t = T(123); includes a temporary T(123) that is immediately
518
/// copied to variable t. In such cases the elidable copy can (but not
519
/// necessarily should) be omitted ("elided") accodring to the rules of the
520
/// language; the constructor would then construct variable t directly.
521
/// This construction context contains information of the elidable constructor
522
/// and its respective construction context.
523
class ElidedTemporaryObjectConstructionContext
524
    : public TemporaryObjectConstructionContext {
525
  const CXXConstructExpr *ElidedCE;
526
  const ConstructionContext *ElidedCC;
527
528
  friend class ConstructionContext; // Allows to create<>() itself.
529
530
  explicit ElidedTemporaryObjectConstructionContext(
531
      const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE,
532
      const CXXConstructExpr *ElidedCE, const ConstructionContext *ElidedCC)
533
      : TemporaryObjectConstructionContext(
534
            ConstructionContext::ElidedTemporaryObjectKind, BTE, MTE),
535
2.16k
        ElidedCE(ElidedCE), ElidedCC(ElidedCC) {
536
2.16k
    // Elided constructor and its context should be either both specified
537
2.16k
    // or both unspecified. In the former case, the constructor must be
538
2.16k
    // elidable.
539
2.16k
    assert(ElidedCE && ElidedCE->isElidable() && ElidedCC);
540
2.16k
  }
541
542
public:
543
1.73k
  const CXXConstructExpr *getConstructorAfterElision() const {
544
1.73k
    return ElidedCE;
545
1.73k
  }
546
547
1.65k
  const ConstructionContext *getConstructionContextAfterElision() const {
548
1.65k
    return ElidedCC;
549
1.65k
  }
550
551
  static bool classof(const ConstructionContext *CC) {
552
    return CC->getKind() == ElidedTemporaryObjectKind;
553
  }
554
};
555
556
class ReturnedValueConstructionContext : public ConstructionContext {
557
  const ReturnStmt *RS;
558
559
protected:
560
  explicit ReturnedValueConstructionContext(ConstructionContext::Kind K,
561
                                            const ReturnStmt *RS)
562
1.10k
      : ConstructionContext(K), RS(RS) {
563
1.10k
    assert(classof(this));
564
1.10k
    assert(RS);
565
1.10k
  }
566
567
public:
568
40
  const ReturnStmt *getReturnStmt() const { return RS; }
569
570
  static bool classof(const ConstructionContext *CC) {
571
    return CC->getKind() >= RETURNED_VALUE_BEGIN &&
572
           CC->getKind() <= RETURNED_VALUE_END;
573
  }
574
};
575
576
/// Represents a temporary object that is being immediately returned from a
577
/// function by value, eg. return t; or return T(123);. In this case there is
578
/// always going to be a constructor at the return site. However, the usual
579
/// temporary-related bureaucracy (CXXBindTemporaryExpr,
580
/// MaterializeTemporaryExpr) is normally located in the caller function's AST.
581
class SimpleReturnedValueConstructionContext
582
    : public ReturnedValueConstructionContext {
583
  friend class ConstructionContext; // Allows to create<>() itself.
584
585
  explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS)
586
      : ReturnedValueConstructionContext(
587
1.04k
            ConstructionContext::SimpleReturnedValueKind, RS) {}
588
589
public:
590
  static bool classof(const ConstructionContext *CC) {
591
    return CC->getKind() == SimpleReturnedValueKind;
592
  }
593
};
594
595
/// Represents a temporary object that is being immediately returned from a
596
/// function by value, eg. return t; or return T(123); in C++17.
597
/// In C++17 there is not going to be an elidable copy constructor at the
598
/// return site.  However, the usual temporary-related bureaucracy (CXXBindTemporaryExpr,
599
/// MaterializeTemporaryExpr) is normally located in the caller function's AST.
600
/// Note that if the object has trivial destructor, then this code is
601
/// indistinguishable from a simple returned value constructor on the AST level;
602
/// in this case we provide a simple returned value construction context.
603
class CXX17ElidedCopyReturnedValueConstructionContext
604
    : public ReturnedValueConstructionContext {
605
  const CXXBindTemporaryExpr *BTE;
606
607
  friend class ConstructionContext; // Allows to create<>() itself.
608
609
  explicit CXX17ElidedCopyReturnedValueConstructionContext(
610
      const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE)
611
      : ReturnedValueConstructionContext(
612
            ConstructionContext::CXX17ElidedCopyReturnedValueKind, RS),
613
66
        BTE(BTE) {
614
66
    assert(BTE);
615
66
  }
616
617
public:
618
2
  const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
619
620
  static bool classof(const ConstructionContext *CC) {
621
    return CC->getKind() == CXX17ElidedCopyReturnedValueKind;
622
  }
623
};
624
625
class ArgumentConstructionContext : public ConstructionContext {
626
  // The call of which the context is an argument.
627
  const Expr *CE;
628
629
  // Which argument we're constructing. Note that when numbering between
630
  // arguments and parameters is inconsistent (eg., operator calls),
631
  // this is the index of the argument, not of the parameter.
632
  unsigned Index;
633
634
  // Whether the object needs to be destroyed.
635
  const CXXBindTemporaryExpr *BTE;
636
637
  friend class ConstructionContext; // Allows to create<>() itself.
638
639
  explicit ArgumentConstructionContext(const Expr *CE, unsigned Index,
640
                                       const CXXBindTemporaryExpr *BTE)
641
      : ConstructionContext(ArgumentKind), CE(CE),
642
1.35k
        Index(Index), BTE(BTE) {
643
1.35k
    assert(isa<CallExpr>(CE) || isa<CXXConstructExpr>(CE) ||
644
1.35k
           isa<ObjCMessageExpr>(CE));
645
1.35k
    // BTE is optional.
646
1.35k
  }
647
648
public:
649
10.1k
  const Expr *getCallLikeExpr() const { return CE; }
650
10.1k
  unsigned getIndex() const { return Index; }
651
10.1k
  const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
652
653
  static bool classof(const ConstructionContext *CC) {
654
    return CC->getKind() == ArgumentKind;
655
  }
656
};
657
658
} // end namespace clang
659
660
#endif // LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H