Evaluate __has_include(include) * @throws std::runtime_error thrown on missing arguments or invalid expression */
| 2672 | * @throws std::runtime_error thrown on missing arguments or invalid expression |
| 2673 | */ |
| 2674 | static void simplifyHasInclude(simplecpp::TokenList &expr, const simplecpp::DUI &dui) |
| 2675 | { |
| 2676 | if (!isCpp17OrLater(dui) && !isGnu(dui)) |
| 2677 | return; |
| 2678 | |
| 2679 | for (simplecpp::Token *tok = expr.front(); tok; tok = tok->next) { |
| 2680 | if (tok->str() != HAS_INCLUDE) |
| 2681 | continue; |
| 2682 | const simplecpp::Token *tok1 = tok->next; |
| 2683 | if (!tok1) { |
| 2684 | throw std::runtime_error("missing __has_include argument"); |
| 2685 | } |
| 2686 | const simplecpp::Token *tok2 = tok1->next; |
| 2687 | if (!tok2) { |
| 2688 | throw std::runtime_error("missing __has_include argument"); |
| 2689 | } |
| 2690 | if (tok1->op == '(') { |
| 2691 | tok1 = tok1->next; |
| 2692 | while (tok2->op != ')') { |
| 2693 | tok2 = tok2->next; |
| 2694 | if (!tok2) { |
| 2695 | throw std::runtime_error("invalid __has_include expression"); |
| 2696 | } |
| 2697 | } |
| 2698 | } |
| 2699 | |
| 2700 | const std::string &sourcefile = expr.file(tok->location); |
| 2701 | const bool systemheader = (tok1 && tok1->op == '<'); |
| 2702 | std::string header; |
| 2703 | if (systemheader) { |
| 2704 | const simplecpp::Token *tok3 = tok1->next; |
| 2705 | if (!tok3) { |
| 2706 | throw std::runtime_error("missing __has_include closing angular bracket"); |
| 2707 | } |
| 2708 | while (tok3->op != '>') { |
| 2709 | tok3 = tok3->next; |
| 2710 | if (!tok3) { |
| 2711 | throw std::runtime_error("invalid __has_include expression"); |
| 2712 | } |
| 2713 | } |
| 2714 | |
| 2715 | for (const simplecpp::Token *headerToken = tok1->next; headerToken != tok3; headerToken = headerToken->next) |
| 2716 | header += headerToken->str(); |
| 2717 | } else { |
| 2718 | header = tok1->str().substr(1U, tok1->str().size() - 2U); |
| 2719 | } |
| 2720 | std::ifstream f; |
| 2721 | const std::string header2 = openHeader(f,dui,sourcefile,header,systemheader); |
| 2722 | tok->setstr(header2.empty() ? "0" : "1"); |
| 2723 | |
| 2724 | tok2 = tok2->next; |
| 2725 | while (tok->next != tok2) |
| 2726 | expr.deleteToken(tok->next); |
| 2727 | } |
| 2728 | } |
| 2729 | |
| 2730 | /** Evaluate name |
| 2731 | * @throws std::runtime_error thrown on undefined function-like macro |
no test coverage detected