Coverage Report

Created: 2023-11-11 10:31

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