| 120 | } |
| 121 | |
| 122 | void CheckIOImpl::checkFileUsage() |
| 123 | { |
| 124 | const bool windows = mSettings.platform.isWindows(); |
| 125 | const bool printPortability = mSettings.severity.isEnabled(Severity::portability); |
| 126 | const bool printWarnings = mSettings.severity.isEnabled(Severity::warning); |
| 127 | |
| 128 | std::map<int, Filepointer> filepointers; |
| 129 | |
| 130 | logChecker("CheckIO::checkFileUsage"); |
| 131 | |
| 132 | const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 133 | for (const Variable* var : symbolDatabase->variableList()) { |
| 134 | if (!var || !var->declarationId() || var->isArray() || !Token::simpleMatch(var->typeStartToken(), "FILE *")) |
| 135 | continue; |
| 136 | |
| 137 | if (var->isLocal()) { |
| 138 | if (var->nameToken()->strAt(1) == "(") // initialize by calling "ctor" |
| 139 | filepointers.emplace(var->declarationId(), Filepointer(OpenMode::UNKNOWN_OM)); |
| 140 | else |
| 141 | filepointers.emplace(var->declarationId(), Filepointer(OpenMode::CLOSED)); |
| 142 | } else { |
| 143 | filepointers.emplace(var->declarationId(), Filepointer(OpenMode::UNKNOWN_OM)); |
| 144 | // TODO: If all fopen calls we find open the file in the same type, we can set Filepointer::mode |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | for (const Scope * scope : symbolDatabase->functionScopes) { |
| 149 | int indent = 0; |
| 150 | for (const Token *tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { |
| 151 | if (Token::Match(tok, "%name% (") && isUnevaluated(tok)) { |
| 152 | tok = tok->linkAt(1); |
| 153 | continue; |
| 154 | } |
| 155 | if (tok->str() == "{") |
| 156 | indent++; |
| 157 | else if (tok->str() == "}") { |
| 158 | indent--; |
| 159 | for (std::pair<const int, Filepointer>& filepointer : filepointers) { |
| 160 | if (indent < filepointer.second.mode_indent) { |
| 161 | filepointer.second.mode_indent = 0; |
| 162 | filepointer.second.mode = OpenMode::UNKNOWN_OM; |
| 163 | } |
| 164 | if (indent < filepointer.second.op_indent) { |
| 165 | filepointer.second.op_indent = 0; |
| 166 | filepointer.second.lastOperation = Filepointer::Operation::UNKNOWN_OP; |
| 167 | } |
| 168 | } |
| 169 | } else if (tok->str() == "return" || tok->str() == "continue" || tok->str() == "break" || mSettings.library.isnoreturn(tok)) { // Reset upon return, continue or break |
| 170 | for (std::pair<const int, Filepointer>& filepointer : filepointers) { |
| 171 | filepointer.second.mode_indent = 0; |
| 172 | filepointer.second.mode = OpenMode::UNKNOWN_OM; |
| 173 | filepointer.second.op_indent = 0; |
| 174 | filepointer.second.lastOperation = Filepointer::Operation::UNKNOWN_OP; |
| 175 | } |
| 176 | } else if (Token::Match(tok, "%var% =") && |
| 177 | (tok->strAt(2) != "fopen" && tok->strAt(2) != "freopen" && tok->strAt(2) != "tmpfile" && |
| 178 | (windows ? (tok->str() != "_wfopen" && tok->str() != "_wfreopen") : true))) { |
| 179 | const auto i = filepointers.find(tok->varId()); |
no test coverage detected