| 874 | } |
| 875 | |
| 876 | const Token * Token::findClosingBracket() const |
| 877 | { |
| 878 | if (mStr != "<") |
| 879 | return nullptr; |
| 880 | |
| 881 | if (!mPrevious) |
| 882 | return nullptr; |
| 883 | |
| 884 | if (!(mPrevious->isName() || Token::simpleMatch(mPrevious, "]") || |
| 885 | Token::Match(mPrevious->previous(), "operator %op% <") || |
| 886 | Token::Match(mPrevious->tokAt(-2), "operator [([] [)]] <"))) |
| 887 | return nullptr; |
| 888 | |
| 889 | const Token *closing = nullptr; |
| 890 | const bool templateParameter(strAt(-1) == "template"); |
| 891 | std::set<std::string> templateParameters; |
| 892 | |
| 893 | bool isDecl = true; |
| 894 | for (const Token *prev = previous(); prev; prev = prev->previous()) { |
| 895 | if (prev->str() == "=") |
| 896 | isDecl = false; |
| 897 | if (Token::simpleMatch(prev, "template <")) |
| 898 | isDecl = true; |
| 899 | if (Token::Match(prev, "[;{}]")) |
| 900 | break; |
| 901 | } |
| 902 | |
| 903 | unsigned int depth = 0; |
| 904 | for (closing = this; closing != nullptr; closing = closing->next()) { |
| 905 | if (Token::Match(closing, "{|[|(")) { |
| 906 | closing = closing->link(); |
| 907 | if (!closing) |
| 908 | return nullptr; // #6803 |
| 909 | } else if (Token::Match(closing, "}|]|)|;")) |
| 910 | return nullptr; |
| 911 | // we can make some guesses for template parameters |
| 912 | else if (closing->str() == "<" && closing->previous() && |
| 913 | (closing->previous()->isName() || Token::simpleMatch(closing->previous(), "]") || isOperator(closing->previous())) && |
| 914 | (templateParameter ? templateParameters.find(closing->strAt(-1)) == templateParameters.end() : true)) |
| 915 | ++depth; |
| 916 | else if (closing->str() == ">") { |
| 917 | if (--depth == 0) |
| 918 | return closing; |
| 919 | } else if (closing->str() == ">>" || closing->str() == ">>=") { |
| 920 | if (!isDecl && depth == 1) |
| 921 | continue; |
| 922 | if (depth <= 2) |
| 923 | return closing; |
| 924 | depth -= 2; |
| 925 | } |
| 926 | // save named template parameter |
| 927 | else if (templateParameter && depth == 1 && Token::Match(closing, "[,=]") && |
| 928 | closing->previous()->isName() && !Token::Match(closing->previous(), "class|typename|.") && !Token::Match(closing->tokAt(-2), "=|::")) |
| 929 | templateParameters.insert(closing->strAt(-1)); |
| 930 | } |
| 931 | |
| 932 | return closing; |
| 933 | } |
no test coverage detected