16 using namespace clang;
17 using namespace CodeGen;
25 Scopes = {{~0U,
nullptr}};
26 unsigned ParentScope = 0;
27 AlwaysBypassed = !BuildScopeInformation(Body, ParentScope);
35 bool VarBypassDetector::BuildScopeInformation(
const Decl *D,
36 unsigned &ParentScope) {
39 Scopes.push_back({ParentScope, VD});
40 ParentScope = Scopes.size() - 1;
43 if (
const VarDecl *VD = dyn_cast<VarDecl>(D))
45 return BuildScopeInformation(
Init, ParentScope);
54 bool VarBypassDetector::BuildScopeInformation(
const Stmt *S,
55 unsigned &origParentScope) {
59 unsigned independentParentScope = origParentScope;
60 unsigned &ParentScope =
61 ((isa<Expr>(S) && !isa<StmtExpr>(S)) ? origParentScope
62 : independentParentScope);
64 unsigned StmtsToSkip = 0u;
67 case Stmt::IndirectGotoStmtClass:
70 case Stmt::SwitchStmtClass:
71 if (
const Stmt *
Init = cast<SwitchStmt>(S)->getInit()) {
72 if (!BuildScopeInformation(
Init, ParentScope))
76 if (
const VarDecl *Var = cast<SwitchStmt>(S)->getConditionVariable()) {
77 if (!BuildScopeInformation(Var, ParentScope))
83 case Stmt::GotoStmtClass:
84 FromScopes.push_back({S, ParentScope});
87 case Stmt::DeclStmtClass: {
88 const DeclStmt *DS = cast<DeclStmt>(S);
89 for (
auto *I : DS->
decls())
90 if (!BuildScopeInformation(I, origParentScope))
95 case Stmt::CaseStmtClass:
96 case Stmt::DefaultStmtClass:
97 case Stmt::LabelStmtClass:
98 llvm_unreachable(
"the loop below handles labels and cases");
118 if (
const SwitchCase *SC = dyn_cast<SwitchCase>(SubStmt))
119 Next = SC->getSubStmt();
120 else if (
const LabelStmt *LS = dyn_cast<LabelStmt>(SubStmt))
121 Next = LS->getSubStmt();
125 ToScopes[SubStmt] = ParentScope;
130 if (!BuildScopeInformation(SubStmt, ParentScope))
137 void VarBypassDetector::Detect() {
138 for (
const auto &S : FromScopes) {
139 const Stmt *St = S.first;
140 unsigned from = S.second;
141 if (
const GotoStmt *GS = dyn_cast<GotoStmt>(St)) {
142 if (
const LabelStmt *LS = GS->getLabel()->getStmt())
143 Detect(from, ToScopes[LS]);
144 }
else if (
const SwitchStmt *SS = dyn_cast<SwitchStmt>(St)) {
145 for (
const SwitchCase *SC = SS->getSwitchCaseList(); SC;
147 Detect(from, ToScopes[SC]);
150 llvm_unreachable(
"goto or switch was expected");
156 void VarBypassDetector::Detect(
unsigned From,
unsigned To) {
159 assert(Scopes[To].first < To);
160 const auto &ScopeTo = Scopes[To];
162 Bypasses.insert(ScopeTo.second);
164 assert(Scopes[From].first < From);
165 From = Scopes[From].first;
Stmt - This represents one statement.
Decl - This represents one declaration (or definition), e.g.
Represents a variable declaration or definition.
LabelStmt - Represents a label, which has a substatement.
Expr - This represents one expression.
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Dataflow Directional Tag Classes.
void Init(const Stmt *Body)
Clear the object and pre-process for the given statement, usually function body statement.
const Expr * getInit() const
StmtClass getStmtClass() const
SwitchStmt - This represents a 'switch' stmt.
GotoStmt - This represents a direct goto.
const SwitchCase * getNextSwitchCase() const