brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.1 KiB · ebd0d88 Raw
78 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "proper_version_checks.hpp"10 11#include <clang/Lex/Lexer.h>12#include <clang/Lex/PPCallbacks.h>13#include <clang/Lex/Preprocessor.h>14 15namespace libcpp {16namespace {17class proper_version_checks_callbacks : public clang::PPCallbacks {18public:19  proper_version_checks_callbacks(clang::Preprocessor& preprocessor, clang::tidy::ClangTidyCheck& check)20      : preprocessor_(preprocessor), check_(check) {}21 22  void If(clang::SourceLocation location, clang::SourceRange condition_range, ConditionValueKind) override {23    check_condition(location, condition_range);24  }25 26  void Elif(clang::SourceLocation location,27            clang::SourceRange condition_range,28            ConditionValueKind,29            clang::SourceLocation if_location) override {30    check_condition(location, condition_range);31  }32 33private:34  void check_condition(clang::SourceLocation location, clang::SourceRange condition_range) {35    std::string_view condition = clang::Lexer::getSourceText(36        clang::CharSourceRange::getTokenRange(condition_range),37        preprocessor_.getSourceManager(),38        preprocessor_.getLangOpts());39    if (preprocessor_.getSourceManager().isInMainFile(location))40      return;41 42    if (condition == "__cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)")43      return;44 45    if (condition.starts_with("_LIBCPP_STD_VER") && condition.find(">") != std::string_view::npos &&46        condition.find(">=") == std::string_view::npos)47      check_.diag(location, "_LIBCPP_STD_VER >= version should be used instead of _LIBCPP_STD_VER > prev_version");48 49    else if (condition.starts_with("__cplusplus"))50      check_.diag(location, "Use _LIBCPP_STD_VER instead of __cplusplus to constrain based on the C++ version");51 52    else if (condition == "_LIBCPP_STD_VER >= 11")53      check_.diag(location, "_LIBCPP_STD_VER >= 11 is always true. Did you mean '#ifndef _LIBCPP_CXX03_LANG'?");54 55    else if (condition.starts_with("_LIBCPP_STD_VER >= ") &&56             std::ranges::none_of(std::array{"14", "17", "20", "23", "26"}, [&](auto val) {57               return condition.find(val) != std::string_view::npos;58             }))59      check_.diag(location, "Not a valid value for _LIBCPP_STD_VER. Use 14, 17, 20, 23, or 26");60  }61 62  clang::Preprocessor& preprocessor_;63  clang::tidy::ClangTidyCheck& check_;64};65} // namespace66 67proper_version_checks::proper_version_checks(llvm::StringRef name, clang::tidy::ClangTidyContext* context)68    : clang::tidy::ClangTidyCheck(name, context) {}69 70void proper_version_checks::registerPPCallbacks(71    const clang::SourceManager& source_manager,72    clang::Preprocessor* preprocessor,73    clang::Preprocessor* module_expander) {74  preprocessor->addPPCallbacks(std::make_unique<proper_version_checks_callbacks>(*preprocessor, *this));75}76 77} // namespace libcpp78