Skip to content

Commit 5b0fbe0

Browse files
committed
Guard statement scopes with a ScopeRAII handle. NFC
clad's statement visitors open a clang::Scope with beginScope and have to close it with a matching endScope on every exit path. A forgotten endScope leaks the Scope object and strands the function-spanning scopes opened by Derive(); this already bit the forward range-for and reverse switch handlers, each since repaired by adding the missing endScope by hand. Introduce a ScopeRAII guard that opens a scope on construction and closes it on destruction, and adopt it in the statement handlers whose scope both opens and closes within a single function body. The balance is now enforced by the type rather than by hand, so an early return can no longer strand a scope. The scopes that do not coincide with a single C++ block stay as explicit begin/endScope pairs: Derive()'s function-spanning function and body scopes, the derived-lambda construction scopes, the forward switch body scope that closes in DeriveSwitchStmtBodyHelper, and the OpenMP canonical-loop scope.
1 parent 2cd5bef commit 5b0fbe0

4 files changed

Lines changed: 58 additions & 66 deletions

File tree

include/clad/Differentiator/VisitorBase.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,25 @@ namespace clad {
251251
void beginScope(unsigned ScopeFlags);
252252
void endScope();
253253

254+
/// RAII guard that opens a scope on construction and closes it on
255+
/// destruction, so a beginScope is always balanced by an endScope even
256+
/// when a statement handler returns early. Use it for statement scopes
257+
/// that nest within a single function; Derive()'s function-spanning scope
258+
/// stays explicit because it is captured into m_DerivativeFnScope and
259+
/// interleaves with Push/PopDeclContext.
260+
class [[nodiscard]] ScopeRAII {
261+
VisitorBase& m_Visitor;
262+
263+
public:
264+
ScopeRAII(VisitorBase& Visitor, unsigned ScopeFlags)
265+
: m_Visitor(Visitor) {
266+
m_Visitor.beginScope(ScopeFlags);
267+
}
268+
~ScopeRAII() { m_Visitor.endScope(); }
269+
ScopeRAII(const ScopeRAII&) = delete;
270+
ScopeRAII& operator=(const ScopeRAII&) = delete;
271+
};
272+
254273
/// A shorthand to simplify syntax for creation of new expressions.
255274
/// This function uses m_Sema.BuildUnOp internally to build unary
256275
/// operations. Typical usage of this function looks like the following:

lib/Differentiator/BaseForwardModeVisitor.cpp

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -466,15 +466,14 @@ StmtDiff BaseForwardModeVisitor::VisitStmt(const Stmt* S) {
466466
}
467467

468468
StmtDiff BaseForwardModeVisitor::VisitCompoundStmt(const CompoundStmt* CS) {
469-
beginScope(Scope::DeclScope);
469+
ScopeRAII compoundScope(*this, Scope::DeclScope);
470470
beginBlock();
471471
for (Stmt* S : CS->body()) {
472472
StmtDiff SDiff = Visit(S);
473473
addToCurrentBlock(SDiff.getStmt_dx());
474474
addToCurrentBlock(SDiff.getStmt());
475475
}
476476
CompoundStmt* Result = endBlock();
477-
endScope();
478477
// Differentation of CompundStmt produces another CompoundStmt with both
479478
// original and derived statements, i.e. Stmt() is Result and Stmt_dx() is
480479
// null.
@@ -484,7 +483,7 @@ StmtDiff BaseForwardModeVisitor::VisitCompoundStmt(const CompoundStmt* CS) {
484483
StmtDiff BaseForwardModeVisitor::VisitIfStmt(const IfStmt* If) {
485484
// Control scope of the IfStmt. E.g., in if (double x = ...) {...}, x goes
486485
// to this scope.
487-
beginScope(Scope::DeclScope | Scope::ControlScope);
486+
ScopeRAII ifScope(*this, Scope::DeclScope | Scope::ControlScope);
488487
// Create a block "around" if statement, e.g:
489488
// {
490489
// ...
@@ -532,12 +531,11 @@ StmtDiff BaseForwardModeVisitor::VisitIfStmt(const IfStmt* If) {
532531
return BranchDiff.getStmt();
533532
} else {
534533
beginBlock();
535-
beginScope(Scope::DeclScope);
534+
ScopeRAII branchScope(*this, Scope::DeclScope);
536535
StmtDiff BranchDiff = Visit(Branch);
537536
for (Stmt* S : BranchDiff.getBothStmts())
538537
addToCurrentBlock(S);
539538
CompoundStmt* Block = endBlock();
540-
endScope();
541539
if (Block->size() == 1)
542540
return Block->body_front();
543541
else
@@ -554,7 +552,6 @@ StmtDiff BaseForwardModeVisitor::VisitIfStmt(const IfStmt* If) {
554552
addToCurrentBlock(ifDiff);
555553
CompoundStmt* Block = endBlock();
556554
// If IfStmt is the only statement in the block, remove the block:
557-
endScope();
558555
// {
559556
// if (...) {...}
560557
// }
@@ -596,8 +593,8 @@ StmtDiff BaseForwardModeVisitor::VisitConditionalOperator(
596593

597594
StmtDiff
598595
BaseForwardModeVisitor::VisitCXXForRangeStmt(const CXXForRangeStmt* FRS) {
599-
beginScope(Scope::DeclScope | Scope::ControlScope | Scope::BreakScope |
600-
Scope::ContinueScope);
596+
ScopeRAII rangeScope(*this, Scope::DeclScope | Scope::ControlScope |
597+
Scope::BreakScope | Scope::ContinueScope);
601598
// Visiting for range-based ststement produces __range1, __begin1 and __end1
602599
// variables, so for(auto i: a){
603600
// ...
@@ -656,13 +653,12 @@ BaseForwardModeVisitor::VisitCXXForRangeStmt(const CXXForRangeStmt* FRS) {
656653
Stmt* forStmtDiff = new (m_Context)
657654
ForStmt(m_Context, nullptr, cond, /*condVar=*/nullptr, Inc, bodyResult,
658655
FRS->getForLoc(), FRS->getBeginLoc(), FRS->getEndLoc());
659-
endScope();
660656
return StmtDiff(forStmtDiff);
661657
}
662658

663659
StmtDiff BaseForwardModeVisitor::VisitForStmt(const ForStmt* FS) {
664-
beginScope(Scope::DeclScope | Scope::ControlScope | Scope::BreakScope |
665-
Scope::ContinueScope);
660+
ScopeRAII forScope(*this, Scope::DeclScope | Scope::ControlScope |
661+
Scope::BreakScope | Scope::ContinueScope);
666662
beginBlock();
667663
const Stmt* init = FS->getInit();
668664
StmtDiff initDiff = init ? Visit(init) : StmtDiff{};
@@ -760,22 +756,22 @@ StmtDiff BaseForwardModeVisitor::VisitForStmt(const ForStmt* FS) {
760756

761757
// Build the derived for loop body.
762758
const Stmt* body = FS->getBody();
763-
beginScope(Scope::DeclScope);
764759
Stmt* bodyResult = nullptr;
765-
beginBlock();
766-
StmtDiff bodyVisited = Visit(body);
767-
for (Stmt* S : bodyVisited.getBothStmts())
768-
addToCurrentBlock(S);
769-
bodyResult = utils::unwrapIfSingleStmt(endBlock());
770-
endScope();
760+
{
761+
ScopeRAII bodyScope(*this, Scope::DeclScope);
762+
beginBlock();
763+
StmtDiff bodyVisited = Visit(body);
764+
for (Stmt* S : bodyVisited.getBothStmts())
765+
addToCurrentBlock(S);
766+
bodyResult = utils::unwrapIfSingleStmt(endBlock());
767+
}
771768

772769
Stmt* forStmtDiff = new (m_Context)
773770
ForStmt(m_Context, initDiff.getStmt(), cond, /*condVar=*/nullptr,
774771
incResult, bodyResult, noLoc, noLoc, noLoc);
775772

776773
addToCurrentBlock(forStmtDiff);
777774
CompoundStmt* Block = endBlock();
778-
endScope();
779775

780776
StmtDiff Result =
781777
(Block->size() == 1) ? StmtDiff(forStmtDiff) : StmtDiff(Block);
@@ -1823,9 +1819,9 @@ StmtDiff BaseForwardModeVisitor::VisitStringLiteral(const StringLiteral* SL) {
18231819
}
18241820

18251821
StmtDiff BaseForwardModeVisitor::VisitWhileStmt(const WhileStmt* WS) {
1826-
// begin scope for while loop
1827-
beginScope(Scope::ContinueScope | Scope::BreakScope | Scope::DeclScope |
1828-
Scope::ControlScope);
1822+
// Scope for the whole while loop.
1823+
ScopeRAII whileScope(*this, Scope::ContinueScope | Scope::BreakScope |
1824+
Scope::DeclScope | Scope::ControlScope);
18291825

18301826
const VarDecl* condVar = WS->getConditionVariable();
18311827
VarDecl* condVarClone = nullptr;
@@ -1882,13 +1878,12 @@ StmtDiff BaseForwardModeVisitor::VisitWhileStmt(const WhileStmt* WS) {
18821878
if (isa<CompoundStmt>(body)) {
18831879
bodyResult = Visit(body).getStmt();
18841880
} else {
1885-
beginScope(Scope::DeclScope);
1881+
ScopeRAII bodyScope(*this, Scope::DeclScope);
18861882
beginBlock();
18871883
StmtDiff Result = Visit(body);
18881884
for (Stmt* S : Result.getBothStmts())
18891885
addToCurrentBlock(S);
18901886
CompoundStmt* Block = endBlock();
1891-
endScope();
18921887
bodyResult = Block;
18931888
}
18941889

@@ -1897,8 +1892,6 @@ StmtDiff BaseForwardModeVisitor::VisitWhileStmt(const WhileStmt* WS) {
18971892
.ActOnWhileStmt(/*WhileLoc=*/noLoc, /*LParenLoc=*/noLoc, condRes,
18981893
/*RParenLoc=*/noLoc, bodyResult)
18991894
.get();
1900-
// end scope for while loop
1901-
endScope();
19021895
return StmtDiff(WSDiff);
19031896
}
19041897

@@ -1908,22 +1901,21 @@ BaseForwardModeVisitor::VisitContinueStmt(const ContinueStmt* ContStmt) {
19081901
}
19091902

19101903
StmtDiff BaseForwardModeVisitor::VisitDoStmt(const DoStmt* DS) {
1911-
// begin scope for do-while statement
1912-
beginScope(Scope::ContinueScope | Scope::BreakScope);
1904+
// Scope for the whole do-while statement.
1905+
ScopeRAII doScope(*this, Scope::ContinueScope | Scope::BreakScope);
19131906
Expr* clonedCond = DS->getCond() ? Clone(DS->getCond()) : nullptr;
19141907
const Stmt* body = DS->getBody();
19151908

19161909
Stmt* bodyResult = nullptr;
19171910
if (isa<CompoundStmt>(body)) {
19181911
bodyResult = Visit(body).getStmt();
19191912
} else {
1920-
beginScope(Scope::DeclScope);
1913+
ScopeRAII bodyScope(*this, Scope::DeclScope);
19211914
beginBlock();
19221915
StmtDiff Result = Visit(body);
19231916
for (Stmt* S : Result.getBothStmts())
19241917
addToCurrentBlock(S);
19251918
CompoundStmt* Block = endBlock();
1926-
endScope();
19271919
bodyResult = Block;
19281920
}
19291921

@@ -1933,8 +1925,6 @@ StmtDiff BaseForwardModeVisitor::VisitDoStmt(const DoStmt* DS) {
19331925
/*CondRParen=*/noLoc)
19341926
.get();
19351927

1936-
// end scope for do-while statement
1937-
endScope();
19381928
return StmtDiff(S);
19391929
}
19401930

lib/Differentiator/ReverseModeForwPassVisitor.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,14 +236,13 @@ StmtDiff ReverseModeForwPassVisitor::ProcessSingleStmt(const clang::Stmt* S) {
236236

237237
StmtDiff
238238
ReverseModeForwPassVisitor::VisitCompoundStmt(const clang::CompoundStmt* CS) {
239-
beginScope(Scope::DeclScope);
239+
ScopeRAII compoundScope(*this, Scope::DeclScope);
240240
beginBlock();
241241
for (Stmt* S : CS->body()) {
242242
StmtDiff SDiff = ProcessSingleStmt(S);
243243
addToCurrentBlock(SDiff.getStmt());
244244
}
245245
CompoundStmt* forward = endBlock();
246-
endScope();
247246
return {forward};
248247
}
249248

0 commit comments

Comments
 (0)