8
8
#include " clang/Analysis/Analyses/LifetimeSafety.h"
9
9
#include " clang/AST/Decl.h"
10
10
#include " clang/AST/Expr.h"
11
+ #include " clang/AST/RecursiveASTVisitor.h"
11
12
#include " clang/AST/StmtVisitor.h"
12
13
#include " clang/AST/Type.h"
13
14
#include " clang/Analysis/Analyses/PostOrderCFGView.h"
@@ -387,25 +388,16 @@ class FactGenerator : public ConstStmtVisitor<FactGenerator> {
387
388
using Base = ConstStmtVisitor<FactGenerator>;
388
389
389
390
public:
390
- FactGenerator (FactManager &FactMgr, AnalysisDeclContext &AC)
391
- : FactMgr(FactMgr), AC(AC) {}
391
+ FactGenerator (FactManager &FactMgr) : FactMgr(FactMgr) {}
392
392
393
- void run () {
394
- llvm::TimeTraceScope TimeProfile (" FactGenerator" );
395
- // Iterate through the CFG blocks in reverse post-order to ensure that
396
- // initializations and destructions are processed in the correct sequence.
397
- for (const CFGBlock *Block : *AC.getAnalysis <PostOrderCFGView>()) {
398
- CurrentBlockFacts.clear ();
399
- for (unsigned I = 0 ; I < Block->size (); ++I) {
400
- const CFGElement &Element = Block->Elements [I];
401
- if (std::optional<CFGStmt> CS = Element.getAs <CFGStmt>())
402
- Visit (CS->getStmt ());
403
- else if (std::optional<CFGAutomaticObjDtor> DtorOpt =
404
- Element.getAs <CFGAutomaticObjDtor>())
405
- handleDestructor (*DtorOpt);
406
- }
407
- FactMgr.addBlockFacts (Block, CurrentBlockFacts);
408
- }
393
+ void startBlock (const CFGBlock *Block) {
394
+ CurrentBlock = Block;
395
+ CurrentBlockFacts.clear ();
396
+ }
397
+
398
+ void endBlock () {
399
+ FactMgr.addBlockFacts (CurrentBlock, CurrentBlockFacts);
400
+ startBlock (nullptr );
409
401
}
410
402
411
403
void VisitDeclStmt (const DeclStmt *DS) {
@@ -425,7 +417,6 @@ class FactGenerator : public ConstStmtVisitor<FactGenerator> {
425
417
void VisitImplicitCastExpr (const ImplicitCastExpr *ICE) {
426
418
if (!hasOrigin (ICE->getType ()))
427
419
return ;
428
- Visit (ICE->getSubExpr ());
429
420
// An ImplicitCastExpr node itself gets an origin, which flows from the
430
421
// origin of its sub-expression (after stripping its own parens/casts).
431
422
// TODO: Consider if this is actually useful in practice. Alternatively, we
@@ -493,18 +484,6 @@ class FactGenerator : public ConstStmtVisitor<FactGenerator> {
493
484
Base::VisitCXXFunctionalCastExpr (FCE);
494
485
}
495
486
496
- private:
497
- // Check if a type has an origin.
498
- bool hasOrigin (QualType QT) { return QT->isPointerOrReferenceType (); }
499
-
500
- template <typename Destination, typename Source>
501
- void addAssignOriginFact (const Destination &D, const Source &S) {
502
- OriginID DestOID = FactMgr.getOriginMgr ().getOrCreate (D);
503
- OriginID SrcOID = FactMgr.getOriginMgr ().get (S);
504
- CurrentBlockFacts.push_back (
505
- FactMgr.createFact <AssignOriginFact>(DestOID, SrcOID));
506
- }
507
-
508
487
void handleDestructor (const CFGAutomaticObjDtor &DtorOpt) {
509
488
// / TODO: Also handle trivial destructors (e.g., for `int`
510
489
// / variables) which will never have a CFGAutomaticObjDtor node.
@@ -527,6 +506,18 @@ class FactGenerator : public ConstStmtVisitor<FactGenerator> {
527
506
}
528
507
}
529
508
509
+ private:
510
+ // Check if a type has an origin.
511
+ bool hasOrigin (QualType QT) { return QT->isPointerOrReferenceType (); }
512
+
513
+ template <typename Destination, typename Source>
514
+ void addAssignOriginFact (const Destination &D, const Source &S) {
515
+ OriginID DestOID = FactMgr.getOriginMgr ().getOrCreate (D);
516
+ OriginID SrcOID = FactMgr.getOriginMgr ().get (S);
517
+ CurrentBlockFacts.push_back (
518
+ FactMgr.createFact <AssignOriginFact>(DestOID, SrcOID));
519
+ }
520
+
530
521
// / Checks if the expression is a `void("__lifetime_test_point_...")` cast.
531
522
// / If so, creates a `TestPointFact` and returns true.
532
523
bool VisitTestPoint (const CXXFunctionalCastExpr *FCE) {
@@ -549,10 +540,59 @@ class FactGenerator : public ConstStmtVisitor<FactGenerator> {
549
540
}
550
541
551
542
FactManager &FactMgr;
552
- AnalysisDeclContext &AC ;
543
+ const CFGBlock *CurrentBlock = nullptr ;
553
544
llvm::SmallVector<Fact *> CurrentBlockFacts;
554
545
};
555
546
547
+ class FactGeneratorDriver : public RecursiveASTVisitor <FactGeneratorDriver> {
548
+ public:
549
+ FactGeneratorDriver (FactGenerator &FG, AnalysisDeclContext &AC)
550
+ : FG(FG), AC(AC) {}
551
+ bool shouldTraversePostOrder () const { return true ; }
552
+ void run () {
553
+ llvm::TimeTraceScope TimeProfile (" FactGenerator" );
554
+ // Iterate through the CFG blocks in reverse post-order to ensure that
555
+ // initializations and destructions are processed in the correct sequence.
556
+ for (const CFGBlock *Block : *AC.getAnalysis <PostOrderCFGView>()) {
557
+ FactGeneratorBlockRAII BlockGenerator (FG, Block);
558
+ for (const CFGElement &Element : *Block) {
559
+ if (std::optional<CFGStmt> CS = Element.getAs <CFGStmt>())
560
+ TraverseStmt (const_cast <Stmt *>(CS->getStmt ()));
561
+ else if (std::optional<CFGAutomaticObjDtor> DtorOpt =
562
+ Element.getAs <CFGAutomaticObjDtor>())
563
+ FG.handleDestructor (*DtorOpt);
564
+ }
565
+ }
566
+ }
567
+
568
+ bool TraverseStmt (Stmt *S) {
569
+ // Avoid re-visiting nodes to not create duplicate facts.
570
+ if (!S || !VisitedStmts.insert (S).second )
571
+ return true ;
572
+ return RecursiveASTVisitor::TraverseStmt (S);
573
+ }
574
+
575
+ bool VisitStmt (Stmt *S) {
576
+ FG.Visit (S);
577
+ return true ; // Continue traversing to children.
578
+ }
579
+
580
+ private:
581
+ struct FactGeneratorBlockRAII {
582
+ FactGeneratorBlockRAII (FactGenerator &FG, const CFGBlock *Block) : FG(FG) {
583
+ FG.startBlock (Block);
584
+ }
585
+ ~FactGeneratorBlockRAII () { FG.endBlock (); }
586
+
587
+ private:
588
+ FactGenerator FG;
589
+ };
590
+
591
+ FactGenerator &FG;
592
+ AnalysisDeclContext &AC;
593
+ llvm::DenseSet<const Stmt *> VisitedStmts;
594
+ };
595
+
556
596
// ========================================================================= //
557
597
// Generic Dataflow Analysis
558
598
// ========================================================================= //
@@ -1096,8 +1136,9 @@ void LifetimeSafetyAnalysis::run() {
1096
1136
DEBUG_WITH_TYPE (" PrintCFG" , Cfg.dump (AC.getASTContext ().getLangOpts (),
1097
1137
/* ShowColors=*/ true ));
1098
1138
1099
- FactGenerator FactGen (*FactMgr, AC);
1100
- FactGen.run ();
1139
+ FactGenerator Generator (*FactMgr);
1140
+ FactGeneratorDriver Driver (Generator, AC);
1141
+ Driver.run ();
1101
1142
DEBUG_WITH_TYPE (" LifetimeFacts" , FactMgr->dump (Cfg, AC));
1102
1143
1103
1144
// / TODO(opt): Consider optimizing individual blocks before running the
0 commit comments