@@ -87,11 +87,50 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
87
87
}
88
88
89
89
void VisitDeclStmt (const DeclStmt *S) {
90
- // FIXME: Add support for group decls, e.g: `int a, b;`
91
- if (S->isSingleDecl ()) {
92
- if (const auto *D = dyn_cast<VarDecl>(S->getSingleDecl ())) {
93
- visitVarDecl (*D);
90
+ // Group decls are converted into single decls in the CFG so the cast below
91
+ // is safe.
92
+ const auto &D = *cast<VarDecl>(S->getSingleDecl ());
93
+ auto &Loc = Env.createStorageLocation (D);
94
+ Env.setStorageLocation (D, Loc);
95
+
96
+ const Expr *InitExpr = D.getInit ();
97
+ if (InitExpr == nullptr ) {
98
+ // No initializer expression - associate `Loc` with a new value.
99
+ Env.initValueInStorageLocation (Loc, D.getType ());
100
+ return ;
101
+ }
102
+
103
+ // The CFG does not contain `ParenExpr` as top-level statements in basic
104
+ // blocks, however sub-expressions can still be of that type.
105
+ InitExpr = skipExprWithCleanups (D.getInit ()->IgnoreParens ());
106
+ assert (InitExpr != nullptr );
107
+
108
+ if (D.getType ()->isReferenceType ()) {
109
+ // Initializing a reference variable - do not create a reference to
110
+ // reference.
111
+ if (auto *InitExprLoc =
112
+ Env.getStorageLocation (*InitExpr, SkipPast::Reference)) {
113
+ auto &Val =
114
+ Env.takeOwnership (std::make_unique<ReferenceValue>(*InitExprLoc));
115
+ Env.setValue (Loc, Val);
116
+ } else {
117
+ // FIXME: The initializer expression must always be assigned a value.
118
+ // Replace this with an assert when we have sufficient coverage of
119
+ // language features.
120
+ Env.initValueInStorageLocation (Loc, D.getType ());
94
121
}
122
+ return ;
123
+ }
124
+
125
+ if (auto *InitExprVal = Env.getValue (*InitExpr, SkipPast::None)) {
126
+ Env.setValue (Loc, *InitExprVal);
127
+ } else if (!D.getType ()->isStructureOrClassType ()) {
128
+ // FIXME: The initializer expression must always be assigned a value.
129
+ // Replace this with an assert when we have sufficient coverage of
130
+ // language features.
131
+ Env.initValueInStorageLocation (Loc, D.getType ());
132
+ } else {
133
+ llvm_unreachable (" structs and classes must always be assigned values" );
95
134
}
96
135
}
97
136
@@ -309,57 +348,34 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
309
348
Env.setStorageLocation (*S, *SubExprLoc);
310
349
}
311
350
312
- // FIXME: Add support for:
313
- // - CXXBindTemporaryExpr
314
- // - CXXBoolLiteralExpr
315
- // - CXXStaticCastExpr
316
-
317
- private:
318
- void visitVarDecl (const VarDecl &D) {
319
- auto &Loc = Env.createStorageLocation (D);
320
- Env.setStorageLocation (D, Loc);
351
+ void VisitCXXBindTemporaryExpr (const CXXBindTemporaryExpr *S) {
352
+ const Expr *SubExpr = S->getSubExpr ();
353
+ assert (SubExpr != nullptr );
321
354
322
- const Expr *InitExpr = D.getInit ();
323
- if (InitExpr == nullptr ) {
324
- // No initializer expression - associate `Loc` with a new value.
325
- Env.initValueInStorageLocation (Loc, D.getType ());
355
+ auto *SubExprLoc = Env.getStorageLocation (*SubExpr, SkipPast::None);
356
+ if (SubExprLoc == nullptr )
326
357
return ;
327
- }
328
358
329
- // The CFG does not contain `ParenExpr` as top-level statements in basic
330
- // blocks, however sub-expressions can still be of that type.
331
- InitExpr = skipExprWithCleanups (D.getInit ()->IgnoreParens ());
332
- assert (InitExpr != nullptr );
359
+ Env.setStorageLocation (*S, *SubExprLoc);
360
+ }
333
361
334
- if (D.getType ()->isReferenceType ()) {
335
- // Initializing a reference variable - do not create a reference to
336
- // reference.
337
- if (auto *InitExprLoc =
338
- Env.getStorageLocation (*InitExpr, SkipPast::Reference)) {
339
- auto &Val =
340
- Env.takeOwnership (std::make_unique<ReferenceValue>(*InitExprLoc));
341
- Env.setValue (Loc, Val);
342
- } else {
343
- // FIXME: The initializer expression must always be assigned a value.
344
- // Replace this with an assert when we have sufficient coverage of
345
- // language features.
346
- Env.initValueInStorageLocation (Loc, D.getType ());
347
- }
348
- return ;
349
- }
362
+ void VisitCXXStaticCastExpr (const CXXStaticCastExpr *S) {
363
+ if (S->getCastKind () == CK_NoOp) {
364
+ const Expr *SubExpr = S->getSubExpr ();
365
+ assert (SubExpr != nullptr );
350
366
351
- if (auto *InitExprVal = Env.getValue (*InitExpr, SkipPast::None)) {
352
- Env.setValue (Loc, *InitExprVal);
353
- } else if (!D.getType ()->isStructureOrClassType ()) {
354
- // FIXME: The initializer expression must always be assigned a value.
355
- // Replace this with an assert when we have sufficient coverage of
356
- // language features.
357
- Env.initValueInStorageLocation (Loc, D.getType ());
358
- } else {
359
- llvm_unreachable (" structs and classes must always be assigned values" );
367
+ auto *SubExprLoc = Env.getStorageLocation (*SubExpr, SkipPast::None);
368
+ if (SubExprLoc == nullptr )
369
+ return ;
370
+
371
+ Env.setStorageLocation (*S, *SubExprLoc);
360
372
}
361
373
}
362
374
375
+ // FIXME: Add support for:
376
+ // - CXXBoolLiteralExpr
377
+
378
+ private:
363
379
Environment &Env;
364
380
};
365
381
0 commit comments