[sema] Wire up VarDecl parent pointers for case stmt related Var Decls

This is in preparation for fixing issues around SILGenPattern fallthrough
emission and bad rename/edit all in scope of case stmt var decls. Specifically,
I am going to ensure that we can get from any VarDecl in the following to any
other VarDecl:

switch x {
case .a(let v1, let v2), .b(let v1, let v2):
  ...
  fallthrough
case .c(let v1, let v2), .d(let v1, let v2):
  ...
}

This will be done by:

1. Pointing the var decls in .d at the corresponding var decls in .c.
2. Pointing the var decls in .c at the corresponding var decls in .b.
3. Pointing the var decls in .b at the corresponding var decls in .a.
4. Pointing the var decls in .a at the case stmt. Recognizing that we are asking
for the next VarDecl, but have a case stmt, we check if we have a fallthrough
case stmt. If so, follow down the fallthrough case stmts until you find a
fallthrough case stmt that doesn't fallthrough itself and then return the
corresponding var decl in the last case label item in that var decl (in the
above .d).

In a subsequent commit I am going to add case body var decls. The only change as
a result of that is that I will insert them into the VarDecl double linked list
after the last case var decl of each case stmt.
This commit is contained in:
Michael Gottesman
2019-03-15 11:31:44 -07:00
parent 500f34c0ef
commit b1a7b488fd
4 changed files with 282 additions and 79 deletions

View File

@@ -4667,19 +4667,32 @@ public:
/// returns null.
///
Pattern *getParentPattern() const;
/// Return the statement that owns the pattern associated with this VarDecl,
/// if one exists.
///
/// NOTE: After parsing and before type checking, all VarDecls from
/// CaseLabelItem's Patterns return their CaseStmt. After type checking, we
/// will have constructed the CaseLabelItem VarDecl linked list implying this
/// will return nullptr. After type checking, if one wishes to find a parent
/// pattern of a VarDecl of a CaseStmt, \see getRecursiveParentPatternStmt
/// instead.
Stmt *getParentPatternStmt() const {
if (!Parent)
return nullptr;
return Parent.dyn_cast<Stmt *>();
}
void setParentPatternStmt(Stmt *s) {
assert(s);
Parent = s;
}
/// Look for the parent pattern stmt of this var decl, recursively
/// looking through var decl pointers and then through any
/// fallthroughts.
Stmt *getRecursiveParentPatternStmt() const;
/// Returns the var decl that this var decl is an implicit reference to if
/// such a var decl exists.
VarDecl *getParentVarDecl() const {
@@ -4695,6 +4708,12 @@ public:
Parent = v;
}
/// If this is a VarDecl that does not belong to a CaseLabelItem's pattern,
/// return this. Otherwise, this VarDecl must belong to a CaseStmt's
/// CaseLabelItem. In that case, return the first case label item of the first
/// case stmt in a sequence of case stmts that fallthrough into each other.
VarDecl *getCanonicalVarDecl() const;
/// True if the global stored property requires lazy initialization.
bool isLazilyInitializedGlobal() const;