void Z3AssumptionSolverImpl::postCheck(const Query&) { errs() << "==> Number of assumptions: " << guards_.size() << '\n'; if (guards_.size() > AssumptionResetThreshold) { reset(); guards_.clear(); } }
// Merge adjacent blocks with identical guards. static void mergeGuards(std::deque<std::string>& file_lines, GuardMap& guard_map) { if (guard_map.size() < 2) { return; } auto current = guard_map.begin(); auto next = current; ++next; while (next != guard_map.end()) { if (current->second != next->second) { ++current; ++next; continue; } // Scan from the end of current to the beginning of next. bool in_block_comment = false; bool valid = true; FileLocation current_location = current->first.end; FileLocation end_location = next->first.start; auto nextLine = [¤t_location]() { ++current_location.line; current_location.column = 1; }; auto nextCol = [&file_lines, ¤t_location, &nextLine]() { if (current_location.column == file_lines[current_location.column - 1].length()) { nextLine(); } else { ++current_location.column; } }; // The end location will point to the semicolon, which we don't want to read, so skip it. nextCol(); while (current_location < end_location) { const std::string& line = file_lines[current_location.line - 1]; size_t line_index = current_location.column - 1; if (in_block_comment) { size_t pos = line.find("*/", line_index); if (pos == std::string::npos) { D("Didn't find block comment terminator, skipping line\n"); nextLine(); continue; } else { D("Found block comment terminator\n"); in_block_comment = false; current_location.column = pos + 2; nextCol(); continue; } } else { size_t pos = line.find_first_not_of(" \t", line_index); if (pos == std::string::npos) { nextLine(); continue; } current_location.column = pos + 1; if (line[pos] != '/') { D("Trailing character '%c' is not a slash: %s\n", line[pos], line.substr(pos).c_str()); valid = false; break; } nextCol(); if (line.length() <= pos + 1) { // Trailing slash at the end of a line? D("Trailing slash at end of line\n"); valid = false; break; } if (line[pos + 1] == '/') { // C++ style comment nextLine(); } else if (line[pos + 1] == '*') { // Block comment nextCol(); in_block_comment = true; D("In a block comment\n"); } else { // Garbage? D("Unexpected output after /: %s\n", line.substr(pos).c_str()); valid = false; break; } } } if (!valid) { D("Not merging blocks %s and %s\n", to_string(current->first).c_str(), to_string(next->first).c_str()); ++current; ++next; continue; } D("Merging blocks %s and %s\n", to_string(current->first).c_str(), to_string(next->first).c_str()); Location merged = current->first; merged.end = next->first.end; DeclarationAvailability avail = current->second; guard_map.erase(current); guard_map.erase(next); bool dummy; std::tie(current, dummy) = guard_map.insert(std::make_pair(merged, avail)); next = current; ++next; } }