16using namespace CodeGen;
24 Scopes = {{~0
U,
nullptr}};
25 unsigned ParentScope = 0;
26 AlwaysBypassed = !BuildScopeInformation(Body, ParentScope);
34bool VarBypassDetector::BuildScopeInformation(
const Decl *
D,
35 unsigned &ParentScope) {
36 const VarDecl *VD = dyn_cast<VarDecl>(
D);
38 Scopes.push_back({ParentScope, VD});
39 ParentScope = Scopes.size() - 1;
42 if (
const VarDecl *VD = dyn_cast<VarDecl>(
D))
44 return BuildScopeInformation(
Init, ParentScope);
53bool VarBypassDetector::BuildScopeInformation(
const Stmt *S,
54 unsigned &origParentScope) {
58 unsigned independentParentScope = origParentScope;
59 unsigned &ParentScope =
60 ((isa<Expr>(S) && !isa<StmtExpr>(S)) ? origParentScope
61 : independentParentScope);
63 unsigned StmtsToSkip = 0u;
65 switch (S->getStmtClass()) {
66 case Stmt::IndirectGotoStmtClass:
69 case Stmt::SwitchStmtClass:
70 if (
const Stmt *
Init = cast<SwitchStmt>(S)->getInit()) {
71 if (!BuildScopeInformation(
Init, ParentScope))
75 if (
const VarDecl *Var = cast<SwitchStmt>(S)->getConditionVariable()) {
76 if (!BuildScopeInformation(Var, ParentScope))
82 case Stmt::GotoStmtClass:
83 FromScopes.push_back({S, ParentScope});
86 case Stmt::DeclStmtClass: {
87 const DeclStmt *DS = cast<DeclStmt>(S);
88 for (
auto *I : DS->
decls())
89 if (!BuildScopeInformation(I, origParentScope))
94 case Stmt::CaseStmtClass:
95 case Stmt::DefaultStmtClass:
96 case Stmt::LabelStmtClass:
97 llvm_unreachable(
"the loop below handles labels and cases");
104 for (
const Stmt *SubStmt : S->children()) {
117 if (
const SwitchCase *SC = dyn_cast<SwitchCase>(SubStmt))
118 Next = SC->getSubStmt();
119 else if (
const LabelStmt *LS = dyn_cast<LabelStmt>(SubStmt))
120 Next = LS->getSubStmt();
124 ToScopes[SubStmt] = ParentScope;
129 if (!BuildScopeInformation(SubStmt, ParentScope))
136void VarBypassDetector::Detect() {
137 for (
const auto &S : FromScopes) {
138 const Stmt *St = S.first;
139 unsigned from = S.second;
140 if (
const GotoStmt *GS = dyn_cast<GotoStmt>(St)) {
141 if (
const LabelStmt *LS = GS->getLabel()->getStmt())
142 Detect(from, ToScopes[LS]);
143 }
else if (
const SwitchStmt *SS = dyn_cast<SwitchStmt>(St)) {
144 for (
const SwitchCase *SC = SS->getSwitchCaseList(); SC;
146 Detect(from, ToScopes[SC]);
149 llvm_unreachable(
"goto or switch was expected");
155void VarBypassDetector::Detect(
unsigned From,
unsigned To) {
158 assert(Scopes[To].first < To);
159 const auto &ScopeTo = Scopes[To];
161 Bypasses.insert(ScopeTo.second);
163 assert(Scopes[From].first < From);
164 From = Scopes[From].first;
void Init(const Stmt *Body)
Clear the object and pre-process for the given statement, usually function body statement.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Decl - This represents one declaration (or definition), e.g.
This represents one expression.
GotoStmt - This represents a direct goto.
LabelStmt - Represents a label, which has a substatement.
Stmt - This represents one statement.
const SwitchCase * getNextSwitchCase() const
SwitchStmt - This represents a 'switch' stmt.
Represents a variable declaration or definition.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
The JSON file list parser is used to communicate input to InstallAPI.