| 2885 | } |
| 2886 | |
| 2887 | const Token* findEscapeStatement(const Scope* scope, const Library& library) |
| 2888 | { |
| 2889 | if (!scope) |
| 2890 | return nullptr; |
| 2891 | for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { |
| 2892 | const Scope* escapeScope = tok->scope(); |
| 2893 | if (!escapeScope->isExecutable()) { // skip type definitions |
| 2894 | tok = escapeScope->bodyEnd; |
| 2895 | continue; |
| 2896 | } |
| 2897 | if (const Token* lambdaEnd = findLambdaEndToken(tok)) { // skip lambdas |
| 2898 | tok = lambdaEnd; |
| 2899 | continue; |
| 2900 | } |
| 2901 | if (!tok->isName()) |
| 2902 | continue; |
| 2903 | if (isEscapeFunction(tok, library)) |
| 2904 | return tok; |
| 2905 | if (!tok->isKeyword()) |
| 2906 | continue; |
| 2907 | if (Token::Match(tok, "goto|return|throw")) // TODO: check try/catch, labels? |
| 2908 | return tok; |
| 2909 | if (!Token::Match(tok, "break|continue")) |
| 2910 | continue; |
| 2911 | const bool isBreak = tok->str()[0] == 'b'; |
| 2912 | while (escapeScope && escapeScope != scope) { |
| 2913 | if (escapeScope->isLoopScope() || (isBreak && escapeScope->type == ScopeType::eSwitch)) |
| 2914 | return nullptr; |
| 2915 | escapeScope = escapeScope->nestedIn; |
| 2916 | } |
| 2917 | return tok; |
| 2918 | } |
| 2919 | return nullptr; |
| 2920 | } |
| 2921 | |
| 2922 | template<class F, |
| 2923 | REQUIRES("F must be a function that returns a Token class", |
no test coverage detected