]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/Analysis/ConstructionContext.h
Merge clang trunk r338150, and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / Analysis / ConstructionContext.h
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 /// Construction context is a linked list of multiple layers. Layers are
26 /// created gradually while traversing the AST, and layers that represent
27 /// the outmost AST nodes are built first, while the node that immediately
28 /// contains the constructor would be built last and capture the previous
29 /// layers as its parents. Construction context captures the last layer
30 /// (which has links to the previous layers) and classifies the seemingly
31 /// arbitrary chain of layers into one of the possible ways of constructing
32 /// an object in C++ for user-friendly experience.
33 class ConstructionContextLayer {
34 public:
35   typedef llvm::PointerUnion<Stmt *, CXXCtorInitializer *> TriggerTy;
36
37 private:
38   /// The construction site - the statement that triggered the construction
39   /// for one of its parts. For instance, stack variable declaration statement
40   /// triggers construction of itself or its elements if it's an array,
41   /// new-expression triggers construction of the newly allocated object(s).
42   TriggerTy Trigger;
43
44   /// Sometimes a single trigger is not enough to describe the construction
45   /// site. In this case we'd have a chain of "partial" construction context
46   /// layers.
47   /// Some examples:
48   /// - A constructor within in an aggregate initializer list within a variable
49   ///   would have a construction context of the initializer list with
50   ///   the parent construction context of a variable.
51   /// - A constructor for a temporary that needs to be both destroyed
52   ///   and materialized into an elidable copy constructor would have a
53   ///   construction context of a CXXBindTemporaryExpr with the parent
54   ///   construction context of a MaterializeTemproraryExpr.
55   /// Not all of these are currently supported.
56   const ConstructionContextLayer *Parent = nullptr;
57
58   ConstructionContextLayer(TriggerTy Trigger,
59                           const ConstructionContextLayer *Parent)
60       : Trigger(Trigger), Parent(Parent) {}
61
62 public:
63   static const ConstructionContextLayer *
64   create(BumpVectorContext &C, TriggerTy Trigger,
65          const ConstructionContextLayer *Parent = nullptr);
66
67   const ConstructionContextLayer *getParent() const { return Parent; }
68   bool isLast() const { return !Parent; }
69
70   const Stmt *getTriggerStmt() const {
71     return Trigger.dyn_cast<Stmt *>();
72   }
73
74   const CXXCtorInitializer *getTriggerInit() const {
75     return Trigger.dyn_cast<CXXCtorInitializer *>();
76   }
77
78   /// Returns true if these layers are equal as individual layers, even if
79   /// their parents are different.
80   bool isSameLayer(const ConstructionContextLayer *Other) const {
81     assert(Other);
82     return (Trigger == Other->Trigger);
83   }
84
85   /// See if Other is a proper initial segment of this construction context
86   /// in terms of the parent chain - i.e. a few first parents coincide and
87   /// then the other context terminates but our context goes further - i.e.,
88   /// we are providing the same context that the other context provides,
89   /// and a bit more above that.
90   bool isStrictlyMoreSpecificThan(const ConstructionContextLayer *Other) const;
91 };
92
93
94 /// ConstructionContext's subclasses describe different ways of constructing
95 /// an object in C++. The context re-captures the essential parent AST nodes
96 /// of the CXXConstructExpr it is assigned to and presents these nodes
97 /// through easy-to-understand accessor methods.
98 class ConstructionContext {
99 public:
100   enum Kind {
101     SimpleVariableKind,
102     CXX17ElidedCopyVariableKind,
103     VARIABLE_BEGIN = SimpleVariableKind,
104     VARIABLE_END = CXX17ElidedCopyVariableKind,
105     SimpleConstructorInitializerKind,
106     CXX17ElidedCopyConstructorInitializerKind,
107     INITIALIZER_BEGIN = SimpleConstructorInitializerKind,
108     INITIALIZER_END = CXX17ElidedCopyConstructorInitializerKind,
109     NewAllocatedObjectKind,
110     SimpleTemporaryObjectKind,
111     ElidedTemporaryObjectKind,
112     TEMPORARY_BEGIN = SimpleTemporaryObjectKind,
113     TEMPORARY_END = ElidedTemporaryObjectKind,
114     SimpleReturnedValueKind,
115     CXX17ElidedCopyReturnedValueKind,
116     RETURNED_VALUE_BEGIN = SimpleReturnedValueKind,
117     RETURNED_VALUE_END = CXX17ElidedCopyReturnedValueKind
118   };
119
120 protected:
121   Kind K;
122
123   // Do not make public! These need to only be constructed
124   // via createFromLayers().
125   explicit ConstructionContext(Kind K) : K(K) {}
126
127 private:
128   // A helper function for constructing an instance into a bump vector context.
129   template <typename T, typename... ArgTypes>
130   static T *create(BumpVectorContext &C, ArgTypes... Args) {
131     auto *CC = C.getAllocator().Allocate<T>();
132     return new (CC) T(Args...);
133   }
134
135 public:
136   /// Consume the construction context layer, together with its parent layers,
137   /// and wrap it up into a complete construction context. May return null
138   /// if layers do not form any supported construction context.
139   static const ConstructionContext *
140   createFromLayers(BumpVectorContext &C,
141                    const ConstructionContextLayer *TopLayer);
142
143   Kind getKind() const { return K; }
144 };
145
146 /// An abstract base class for local variable constructors.
147 class VariableConstructionContext : public ConstructionContext {
148   const DeclStmt *DS;
149
150 protected:
151   VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS)
152       : ConstructionContext(K), DS(DS) {
153     assert(classof(this));
154     assert(DS);
155   }
156
157 public:
158   const DeclStmt *getDeclStmt() const { return DS; }
159
160   static bool classof(const ConstructionContext *CC) {
161     return CC->getKind() >= VARIABLE_BEGIN &&
162            CC->getKind() <= VARIABLE_END;
163   }
164 };
165
166 /// Represents construction into a simple local variable, eg. T var(123);.
167 /// If a variable has an initializer, eg. T var = makeT();, then the final
168 /// elidable copy-constructor from makeT() into var would also be a simple
169 /// variable constructor handled by this class.
170 class SimpleVariableConstructionContext : public VariableConstructionContext {
171   friend class ConstructionContext; // Allows to create<>() itself.
172
173   explicit SimpleVariableConstructionContext(const DeclStmt *DS)
174       : VariableConstructionContext(ConstructionContext::SimpleVariableKind,
175                                     DS) {}
176
177 public:
178   static bool classof(const ConstructionContext *CC) {
179     return CC->getKind() == SimpleVariableKind;
180   }
181 };
182
183 /// Represents construction into a simple variable with an initializer syntax,
184 /// with a single constructor, eg. T var = makeT();. Such construction context
185 /// may only appear in C++17 because previously it was split into a temporary
186 /// object constructor and an elidable simple variable copy-constructor and
187 /// we were producing separate construction contexts for these constructors.
188 /// In C++17 we have a single construction context that combines both.
189 /// Note that if the object has trivial destructor, then this code is
190 /// indistinguishable from a simple variable constructor on the AST level;
191 /// in this case we provide a simple variable construction context.
192 class CXX17ElidedCopyVariableConstructionContext
193     : public VariableConstructionContext {
194   const CXXBindTemporaryExpr *BTE;
195
196   friend class ConstructionContext; // Allows to create<>() itself.
197
198   explicit CXX17ElidedCopyVariableConstructionContext(
199       const DeclStmt *DS, const CXXBindTemporaryExpr *BTE)
200       : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) {
201     assert(BTE);
202   }
203
204 public:
205   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
206
207   static bool classof(const ConstructionContext *CC) {
208     return CC->getKind() == CXX17ElidedCopyVariableKind;
209   }
210 };
211
212 // An abstract base class for constructor-initializer-based constructors.
213 class ConstructorInitializerConstructionContext : public ConstructionContext {
214   const CXXCtorInitializer *I;
215
216 protected:
217   explicit ConstructorInitializerConstructionContext(
218       ConstructionContext::Kind K, const CXXCtorInitializer *I)
219       : ConstructionContext(K), I(I) {
220     assert(classof(this));
221     assert(I);
222   }
223
224 public:
225   const CXXCtorInitializer *getCXXCtorInitializer() const { return I; }
226
227   static bool classof(const ConstructionContext *CC) {
228     return CC->getKind() >= INITIALIZER_BEGIN &&
229            CC->getKind() <= INITIALIZER_END;
230   }
231 };
232
233 /// Represents construction into a field or a base class within a bigger object
234 /// via a constructor initializer, eg. T(): field(123) { ... }.
235 class SimpleConstructorInitializerConstructionContext
236     : public ConstructorInitializerConstructionContext {
237   friend class ConstructionContext; // Allows to create<>() itself.
238
239   explicit SimpleConstructorInitializerConstructionContext(
240       const CXXCtorInitializer *I)
241       : ConstructorInitializerConstructionContext(
242             ConstructionContext::SimpleConstructorInitializerKind, I) {}
243
244 public:
245   static bool classof(const ConstructionContext *CC) {
246     return CC->getKind() == SimpleConstructorInitializerKind;
247   }
248 };
249
250 /// Represents construction into a field or a base class within a bigger object
251 /// via a constructor initializer, with a single constructor, eg.
252 /// T(): field(Field(123)) { ... }. Such construction context may only appear
253 /// in C++17 because previously it was split into a temporary object constructor
254 /// and an elidable simple constructor-initializer copy-constructor and we were
255 /// producing separate construction contexts for these constructors. In C++17
256 /// we have a single construction context that combines both. Note that if the
257 /// object has trivial destructor, then this code is indistinguishable from
258 /// a simple constructor-initializer constructor on the AST level; in this case
259 /// we provide a simple constructor-initializer construction context.
260 class CXX17ElidedCopyConstructorInitializerConstructionContext
261     : public ConstructorInitializerConstructionContext {
262   const CXXBindTemporaryExpr *BTE;
263
264   friend class ConstructionContext; // Allows to create<>() itself.
265
266   explicit CXX17ElidedCopyConstructorInitializerConstructionContext(
267       const CXXCtorInitializer *I, const CXXBindTemporaryExpr *BTE)
268       : ConstructorInitializerConstructionContext(
269             CXX17ElidedCopyConstructorInitializerKind, I),
270         BTE(BTE) {
271     assert(BTE);
272   }
273
274 public:
275   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
276
277   static bool classof(const ConstructionContext *CC) {
278     return CC->getKind() == CXX17ElidedCopyConstructorInitializerKind;
279   }
280 };
281
282 /// Represents immediate initialization of memory allocated by operator new,
283 /// eg. new T(123);.
284 class NewAllocatedObjectConstructionContext : public ConstructionContext {
285   const CXXNewExpr *NE;
286
287   friend class ConstructionContext; // Allows to create<>() itself.
288
289   explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE)
290       : ConstructionContext(ConstructionContext::NewAllocatedObjectKind),
291         NE(NE) {
292     assert(NE);
293   }
294
295 public:
296   const CXXNewExpr *getCXXNewExpr() const { return NE; }
297
298   static bool classof(const ConstructionContext *CC) {
299     return CC->getKind() == NewAllocatedObjectKind;
300   }
301 };
302
303 /// Represents a temporary object, eg. T(123), that does not immediately cross
304 /// function boundaries "by value"; constructors that construct function
305 /// value-type arguments or values that are immediately returned from the
306 /// function that returns a value receive separate construction context kinds.
307 class TemporaryObjectConstructionContext : public ConstructionContext {
308   const CXXBindTemporaryExpr *BTE;
309   const MaterializeTemporaryExpr *MTE;
310
311 protected:
312   explicit TemporaryObjectConstructionContext(
313       ConstructionContext::Kind K, const CXXBindTemporaryExpr *BTE,
314       const MaterializeTemporaryExpr *MTE)
315       : ConstructionContext(K), BTE(BTE), MTE(MTE) {
316     // Both BTE and MTE can be null here, all combinations possible.
317     // Even though for now at least one should be non-null, we simply haven't
318     // implemented the other case yet (this would be a temporary in the middle
319     // of nowhere that doesn't have a non-trivial destructor).
320   }
321
322 public:
323   /// CXXBindTemporaryExpr here is non-null as long as the temporary has
324   /// a non-trivial destructor.
325   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const {
326     return BTE;
327   }
328
329   /// MaterializeTemporaryExpr is non-null as long as the temporary is actually
330   /// used after construction, eg. by binding to a reference (lifetime
331   /// extension), accessing a field, calling a method, or passing it into
332   /// a function (an elidable copy or move constructor would be a common
333   /// example) by reference.
334   const MaterializeTemporaryExpr *getMaterializedTemporaryExpr() const {
335     return MTE;
336   }
337
338   static bool classof(const ConstructionContext *CC) {
339     return CC->getKind() >= TEMPORARY_BEGIN && CC->getKind() <= TEMPORARY_END;
340   }
341 };
342
343 /// Represents a temporary object that is not constructed for the purpose of
344 /// being immediately copied/moved by an elidable copy/move-constructor.
345 /// This includes temporary objects "in the middle of nowhere" like T(123) and
346 /// lifetime-extended temporaries.
347 class SimpleTemporaryObjectConstructionContext
348     : public TemporaryObjectConstructionContext {
349   friend class ConstructionContext; // Allows to create<>() itself.
350
351   explicit SimpleTemporaryObjectConstructionContext(
352       const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE)
353       : TemporaryObjectConstructionContext(
354             ConstructionContext::SimpleTemporaryObjectKind, BTE, MTE) {}
355
356 public:
357   static bool classof(const ConstructionContext *CC) {
358     return CC->getKind() == SimpleTemporaryObjectKind;
359   }
360 };
361
362 /// Represents a temporary object that is constructed for the sole purpose
363 /// of being immediately copied by an elidable copy/move constructor.
364 /// For example, T t = T(123); includes a temporary T(123) that is immediately
365 /// copied to variable t. In such cases the elidable copy can (but not
366 /// necessarily should) be omitted ("elided") accodring to the rules of the
367 /// language; the constructor would then construct variable t directly.
368 /// This construction context contains information of the elidable constructor
369 /// and its respective construction context.
370 class ElidedTemporaryObjectConstructionContext
371     : public TemporaryObjectConstructionContext {
372   const CXXConstructExpr *ElidedCE;
373   const ConstructionContext *ElidedCC;
374
375   friend class ConstructionContext; // Allows to create<>() itself.
376
377   explicit ElidedTemporaryObjectConstructionContext(
378       const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE,
379       const CXXConstructExpr *ElidedCE, const ConstructionContext *ElidedCC)
380       : TemporaryObjectConstructionContext(
381             ConstructionContext::ElidedTemporaryObjectKind, BTE, MTE),
382         ElidedCE(ElidedCE), ElidedCC(ElidedCC) {
383     // Elided constructor and its context should be either both specified
384     // or both unspecified. In the former case, the constructor must be
385     // elidable.
386     assert(ElidedCE && ElidedCE->isElidable() && ElidedCC);
387   }
388
389 public:
390   const CXXConstructExpr *getConstructorAfterElision() const {
391     return ElidedCE;
392   }
393
394   const ConstructionContext *getConstructionContextAfterElision() const {
395     return ElidedCC;
396   }
397
398   static bool classof(const ConstructionContext *CC) {
399     return CC->getKind() == ElidedTemporaryObjectKind;
400   }
401 };
402
403 class ReturnedValueConstructionContext : public ConstructionContext {
404   const ReturnStmt *RS;
405
406 protected:
407   explicit ReturnedValueConstructionContext(ConstructionContext::Kind K,
408                                             const ReturnStmt *RS)
409       : ConstructionContext(K), RS(RS) {
410     assert(classof(this));
411     assert(RS);
412   }
413
414 public:
415   const ReturnStmt *getReturnStmt() const { return RS; }
416
417   static bool classof(const ConstructionContext *CC) {
418     return CC->getKind() >= RETURNED_VALUE_BEGIN &&
419            CC->getKind() <= RETURNED_VALUE_END;
420   }
421 };
422
423 /// Represents a temporary object that is being immediately returned from a
424 /// function by value, eg. return t; or return T(123);. In this case there is
425 /// always going to be a constructor at the return site. However, the usual
426 /// temporary-related bureaucracy (CXXBindTemporaryExpr,
427 /// MaterializeTemporaryExpr) is normally located in the caller function's AST.
428 class SimpleReturnedValueConstructionContext
429     : public ReturnedValueConstructionContext {
430   friend class ConstructionContext; // Allows to create<>() itself.
431
432   explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS)
433       : ReturnedValueConstructionContext(
434             ConstructionContext::SimpleReturnedValueKind, RS) {}
435
436 public:
437   static bool classof(const ConstructionContext *CC) {
438     return CC->getKind() == SimpleReturnedValueKind;
439   }
440 };
441
442 /// Represents a temporary object that is being immediately returned from a
443 /// function by value, eg. return t; or return T(123); in C++17.
444 /// In C++17 there is not going to be an elidable copy constructor at the
445 /// return site.  However, the usual temporary-related bureaucracy (CXXBindTemporaryExpr,
446 /// MaterializeTemporaryExpr) is normally located in the caller function's AST.
447 /// Note that if the object has trivial destructor, then this code is
448 /// indistinguishable from a simple returned value constructor on the AST level;
449 /// in this case we provide a simple returned value construction context.
450 class CXX17ElidedCopyReturnedValueConstructionContext
451     : public ReturnedValueConstructionContext {
452   const CXXBindTemporaryExpr *BTE;
453
454   friend class ConstructionContext; // Allows to create<>() itself.
455
456   explicit CXX17ElidedCopyReturnedValueConstructionContext(
457       const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE)
458       : ReturnedValueConstructionContext(
459             ConstructionContext::CXX17ElidedCopyReturnedValueKind, RS),
460         BTE(BTE) {
461     assert(BTE);
462   }
463
464 public:
465   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
466
467   static bool classof(const ConstructionContext *CC) {
468     return CC->getKind() == CXX17ElidedCopyReturnedValueKind;
469   }
470 };
471
472 } // end namespace clang
473
474 #endif // LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H