Coverage Report

Created: 2020-02-25 14:32

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