brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.9 KiB · 2b18654 Raw
77 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// This clang-tidy check ensures that we don't use any _LIBCPP_HAS_FOO macro10// inside `#ifdef`, `#ifndef` & friends, since the intent is to always use `#if` instead.11 12#include "internal_ftm_use.hpp"13 14#include <clang/Lex/Lexer.h>15#include <clang/Lex/PPCallbacks.h>16#include <clang/Lex/Preprocessor.h>17 18#include <string>19 20namespace libcpp {21namespace {22std::array valid_macros{23    // Public API macros24    "_LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS",25 26    // Testing macros27    "_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER",28};29 30class internal_ftm_use_callbacks : public clang::PPCallbacks {31public:32  internal_ftm_use_callbacks(clang::tidy::ClangTidyCheck& check) : check_(check) {}33 34  void Defined(const clang::Token& token,35               const clang::MacroDefinition& macro_definition,36               clang::SourceRange location) override {37    check_macro(token.getIdentifierInfo()->getName(), location.getBegin());38  }39 40  void Ifdef(clang::SourceLocation location, const clang::Token& token, const clang::MacroDefinition&) override {41    check_macro(token.getIdentifierInfo()->getName(), location);42  }43 44  void Elifdef(clang::SourceLocation location, const clang::Token& token, const clang::MacroDefinition&) override {45    check_macro(token.getIdentifierInfo()->getName(), location);46  }47 48  void Ifndef(clang::SourceLocation location, const clang::Token& token, const clang::MacroDefinition&) override {49    check_macro(token.getIdentifierInfo()->getName(), location);50  }51 52  void Elifndef(clang::SourceLocation location, const clang::Token& token, const clang::MacroDefinition&) override {53    check_macro(token.getIdentifierInfo()->getName(), location);54  }55 56private:57  void check_macro(std::string_view macro, clang::SourceLocation location) {58    if (macro.starts_with("_LIBCPP_HAS_") && std::ranges::find(valid_macros, macro) == valid_macros.end()) {59      check_.diag(location, std::string("\'") + std::string{macro} + "' is always defined to 1 or 0.");60    }61  }62 63  clang::tidy::ClangTidyCheck& check_;64};65} // namespace66 67internal_ftm_use::internal_ftm_use(llvm::StringRef name, clang::tidy::ClangTidyContext* context)68    : clang::tidy::ClangTidyCheck(name, context) {}69 70void internal_ftm_use::registerPPCallbacks(const clang::SourceManager& source_manager,71                                           clang::Preprocessor* preprocessor,72                                           clang::Preprocessor* module_expander) {73  preprocessor->addPPCallbacks(std::make_unique<internal_ftm_use_callbacks>(*this));74}75 76} // namespace libcpp77