| 9115 | |
| 9116 | |
| 9117 | Label *Line::IsJumpValid(Label &aTargetLabel, bool aSilent) |
| 9118 | // Returns aTargetLabel is the jump is valid, or NULL otherwise. |
| 9119 | { |
| 9120 | // aTargetLabel can be NULL if this Goto's target is the physical end of the script. |
| 9121 | // And such a destination is always valid, regardless of where aOrigin is. |
| 9122 | // UPDATE: It's no longer possible for the destination of a Goto to be |
| 9123 | // NULL because the script loader has ensured that the end of the script always has |
| 9124 | // an extra ACT_EXIT that serves as an anchor for any final labels in the script: |
| 9125 | //if (aTargetLabel == NULL) |
| 9126 | // return OK; |
| 9127 | // The above check is also necessary to avoid dereferencing a NULL pointer below. |
| 9128 | |
| 9129 | if (!CheckValidFinallyJump(aTargetLabel.mJumpToLine, aSilent)) |
| 9130 | return NULL; |
| 9131 | |
| 9132 | Line *parent_line_of_label_line; |
| 9133 | if ( !(parent_line_of_label_line = aTargetLabel.mJumpToLine->mParentLine) ) |
| 9134 | // A Goto can always jump to a point anywhere in the outermost layer |
| 9135 | // (i.e. outside all blocks) without restriction (except from inside a |
| 9136 | // function to outside, but in that case the label would not be found): |
| 9137 | return &aTargetLabel; // Indicate success. |
| 9138 | |
| 9139 | // So now we know this Goto is attempting to jump into a block somewhere. Is that |
| 9140 | // block a legal place to jump?: |
| 9141 | |
| 9142 | for (Line *ancestor = mParentLine; ancestor != NULL; ancestor = ancestor->mParentLine) |
| 9143 | if (parent_line_of_label_line == ancestor) |
| 9144 | // Since aTargetLabel is in the same block as the Goto line itself (or a block |
| 9145 | // that encloses that block), it's allowed: |
| 9146 | return &aTargetLabel; // Indicate success. |
| 9147 | // This can happen if the Goto's target is at a deeper level than it, or if the target |
| 9148 | // is at a more shallow level but is in some block totally unrelated to it! |
| 9149 | // Returns FAIL by default, which is what we want because that value is zero: |
| 9150 | if (!aSilent) |
| 9151 | LineError(_T("A Goto must not jump into a block that doesn't enclose it.")); |
| 9152 | return NULL; |
| 9153 | } |
| 9154 | |
| 9155 | |
| 9156 | BOOL Line::CheckValidFinallyJump(Line* jumpTarget, bool aSilent) |
nothing calls this directly
no outgoing calls
no test coverage detected