diff options
author | thegeorg <thegeorg@yandex-team.com> | 2024-03-13 13:58:24 +0300 |
---|---|---|
committer | thegeorg <thegeorg@yandex-team.com> | 2024-03-13 14:11:53 +0300 |
commit | 11a895b7e15d1c5a1f52706396b82e3f9db953cb (patch) | |
tree | fabc6d883b0f946151f61ae7865cee9f529a1fdd /contrib/libs/clang16/include/clang/Tooling | |
parent | 9685917341315774aad5733b1793b1e533a88bbb (diff) | |
download | ydb-11a895b7e15d1c5a1f52706396b82e3f9db953cb.tar.gz |
Export clang-format16 via ydblib project
6e6be3a95868fde888d801b7590af4044049563f
Diffstat (limited to 'contrib/libs/clang16/include/clang/Tooling')
51 files changed, 6540 insertions, 0 deletions
diff --git a/contrib/libs/clang16/include/clang/Tooling/AllTUsExecution.h b/contrib/libs/clang16/include/clang/Tooling/AllTUsExecution.h new file mode 100644 index 0000000000..85100b0f96 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/AllTUsExecution.h @@ -0,0 +1,90 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- AllTUsExecution.h - Execute actions on all TUs. -*- C++ --------*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines a tool executor that runs given actions on all TUs in the +// compilation database. Tool results are deuplicated by the result key. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_ALLTUSEXECUTION_H +#define LLVM_CLANG_TOOLING_ALLTUSEXECUTION_H + +#include "clang/Tooling/ArgumentsAdjusters.h" +#include "clang/Tooling/Execution.h" +#include <optional> + +namespace clang { +namespace tooling { + +/// Executes given frontend actions on all files/TUs in the compilation +/// database. +class AllTUsToolExecutor : public ToolExecutor { +public: + static const char *ExecutorName; + + /// Init with \p CompilationDatabase. + /// This uses \p ThreadCount threads to exececute the actions on all files in + /// parallel. If \p ThreadCount is 0, this uses `llvm::hardware_concurrency`. + AllTUsToolExecutor(const CompilationDatabase &Compilations, + unsigned ThreadCount, + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<PCHContainerOperations>()); + + /// Init with \p CommonOptionsParser. This is expected to be used by + /// `createExecutorFromCommandLineArgs` based on commandline options. + /// + /// The executor takes ownership of \p Options. + AllTUsToolExecutor(CommonOptionsParser Options, unsigned ThreadCount, + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<PCHContainerOperations>()); + + StringRef getExecutorName() const override { return ExecutorName; } + + using ToolExecutor::execute; + + llvm::Error + execute(llvm::ArrayRef< + std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>> + Actions) override; + + ExecutionContext *getExecutionContext() override { return &Context; }; + + ToolResults *getToolResults() override { return Results.get(); } + + void mapVirtualFile(StringRef FilePath, StringRef Content) override { + OverlayFiles[FilePath] = std::string(Content); + } + +private: + // Used to store the parser when the executor is initialized with parser. + std::optional<CommonOptionsParser> OptionsParser; + const CompilationDatabase &Compilations; + std::unique_ptr<ToolResults> Results; + ExecutionContext Context; + llvm::StringMap<std::string> OverlayFiles; + unsigned ThreadCount; +}; + +extern llvm::cl::opt<unsigned> ExecutorConcurrency; +extern llvm::cl::opt<std::string> Filter; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_ALLTUSEXECUTION_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/ArgumentsAdjusters.h b/contrib/libs/clang16/include/clang/Tooling/ArgumentsAdjusters.h new file mode 100644 index 0000000000..30cbd0483e --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/ArgumentsAdjusters.h @@ -0,0 +1,86 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- ArgumentsAdjusters.h - Command line arguments adjuster ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares type ArgumentsAdjuster and functions to create several +// useful argument adjusters. +// ArgumentsAdjusters modify command line arguments obtained from a compilation +// database before they are used to run a frontend action. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H +#define LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringRef.h" +#include <functional> +#include <string> +#include <vector> + +namespace clang { +namespace tooling { + +/// A sequence of command line arguments. +using CommandLineArguments = std::vector<std::string>; + +/// A prototype of a command line adjuster. +/// +/// Command line argument adjuster is responsible for command line arguments +/// modification before the arguments are used to run a frontend action. +using ArgumentsAdjuster = std::function<CommandLineArguments( + const CommandLineArguments &, StringRef Filename)>; + +/// Gets an argument adjuster that converts input command line arguments +/// to the "syntax check only" variant. +ArgumentsAdjuster getClangSyntaxOnlyAdjuster(); + +/// Gets an argument adjuster which removes output-related command line +/// arguments. +ArgumentsAdjuster getClangStripOutputAdjuster(); + +/// Gets an argument adjuster which removes dependency-file +/// related command line arguments. +ArgumentsAdjuster getClangStripDependencyFileAdjuster(); + +enum class ArgumentInsertPosition { BEGIN, END }; + +/// Gets an argument adjuster which inserts \p Extra arguments in the +/// specified position. +ArgumentsAdjuster getInsertArgumentAdjuster(const CommandLineArguments &Extra, + ArgumentInsertPosition Pos); + +/// Gets an argument adjuster which inserts an \p Extra argument in the +/// specified position. +ArgumentsAdjuster getInsertArgumentAdjuster( + const char *Extra, + ArgumentInsertPosition Pos = ArgumentInsertPosition::END); + +/// Gets an argument adjuster which strips plugin related command line +/// arguments. +ArgumentsAdjuster getStripPluginsAdjuster(); + +/// Gets an argument adjuster which adjusts the arguments in sequence +/// with the \p First adjuster and then with the \p Second one. +ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First, + ArgumentsAdjuster Second); + +} // namespace tooling +} // namespace clang + +#endif // LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/CommonOptionsParser.h b/contrib/libs/clang16/include/clang/Tooling/CommonOptionsParser.h new file mode 100644 index 0000000000..6188126a44 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/CommonOptionsParser.h @@ -0,0 +1,155 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- CommonOptionsParser.h - common options for clang tools -*- C++ -*-=====// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the CommonOptionsParser class used to parse common +// command-line options for clang tools, so that they can be run as separate +// command-line applications with a consistent common interface for handling +// compilation database and input files. +// +// It provides a common subset of command-line options, common algorithm +// for locating a compilation database and source files, and help messages +// for the basic command-line interface. +// +// It creates a CompilationDatabase and reads common command-line options. +// +// This class uses the Clang Tooling infrastructure, see +// http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html +// for details on setting it up with LLVM source tree. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_COMMONOPTIONSPARSER_H +#define LLVM_CLANG_TOOLING_COMMONOPTIONSPARSER_H + +#include "clang/Tooling/ArgumentsAdjusters.h" +#include "clang/Tooling/CompilationDatabase.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Error.h" + +namespace clang { +namespace tooling { +/// A parser for options common to all command-line Clang tools. +/// +/// Parses a common subset of command-line arguments, locates and loads a +/// compilation commands database and runs a tool with user-specified action. It +/// also contains a help message for the common command-line options. +/// +/// An example of usage: +/// \code +/// #include "clang/Frontend/FrontendActions.h" +/// #include "clang/Tooling/CommonOptionsParser.h" +/// #include "clang/Tooling/Tooling.h" +/// #include "llvm/Support/CommandLine.h" +/// +/// using namespace clang::tooling; +/// using namespace llvm; +/// +/// static cl::OptionCategory MyToolCategory("My tool options"); +/// static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage); +/// static cl::extrahelp MoreHelp("\nMore help text...\n"); +/// static cl::opt<bool> YourOwnOption(...); +/// ... +/// +/// int main(int argc, const char **argv) { +/// CommonOptionsParser OptionsParser(argc, argv, MyToolCategory); +/// ClangTool Tool(OptionsParser.getCompilations(), +/// OptionsParser.getSourcePathList()); +/// return Tool.run(newFrontendActionFactory<SyntaxOnlyAction>().get()); +/// } +/// \endcode +class CommonOptionsParser { + +protected: + /// Parses command-line, initializes a compilation database. + /// + /// This constructor can change argc and argv contents, e.g. consume + /// command-line options used for creating FixedCompilationDatabase. + /// + /// All options not belonging to \p Category become hidden. + /// + /// It also allows calls to set the required number of positional parameters. + CommonOptionsParser( + int &argc, const char **argv, llvm::cl::OptionCategory &Category, + llvm::cl::NumOccurrencesFlag OccurrencesFlag = llvm::cl::OneOrMore, + const char *Overview = nullptr); + +public: + /// A factory method that is similar to the above constructor, except + /// this returns an error instead exiting the program on error. + static llvm::Expected<CommonOptionsParser> + create(int &argc, const char **argv, llvm::cl::OptionCategory &Category, + llvm::cl::NumOccurrencesFlag OccurrencesFlag = llvm::cl::OneOrMore, + const char *Overview = nullptr); + + /// Returns a reference to the loaded compilations database. + CompilationDatabase &getCompilations() { + return *Compilations; + } + + /// Returns a list of source file paths to process. + const std::vector<std::string> &getSourcePathList() const { + return SourcePathList; + } + + /// Returns the argument adjuster calculated from "--extra-arg" and + //"--extra-arg-before" options. + ArgumentsAdjuster getArgumentsAdjuster() { return Adjuster; } + + static const char *const HelpMessage; + +private: + CommonOptionsParser() = default; + + llvm::Error init(int &argc, const char **argv, + llvm::cl::OptionCategory &Category, + llvm::cl::NumOccurrencesFlag OccurrencesFlag, + const char *Overview); + + std::unique_ptr<CompilationDatabase> Compilations; + std::vector<std::string> SourcePathList; + ArgumentsAdjuster Adjuster; +}; + +class ArgumentsAdjustingCompilations : public CompilationDatabase { +public: + ArgumentsAdjustingCompilations( + std::unique_ptr<CompilationDatabase> Compilations) + : Compilations(std::move(Compilations)) {} + + void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster); + + std::vector<CompileCommand> + getCompileCommands(StringRef FilePath) const override; + + std::vector<std::string> getAllFiles() const override; + + std::vector<CompileCommand> getAllCompileCommands() const override; + +private: + std::unique_ptr<CompilationDatabase> Compilations; + std::vector<ArgumentsAdjuster> Adjusters; + + std::vector<CompileCommand> + adjustCommands(std::vector<CompileCommand> Commands) const; +}; + +} // namespace tooling +} // namespace clang + +#endif // LLVM_CLANG_TOOLING_COMMONOPTIONSPARSER_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/CompilationDatabase.h b/contrib/libs/clang16/include/clang/Tooling/CompilationDatabase.h new file mode 100644 index 0000000000..553649b5ba --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/CompilationDatabase.h @@ -0,0 +1,257 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- CompilationDatabase.h ------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file provides an interface and multiple implementations for +// CompilationDatabases. +// +// While C++ refactoring and analysis tools are not compilers, and thus +// don't run as part of the build system, they need the exact information +// of a build in order to be able to correctly understand the C++ code of +// the project. This information is provided via the CompilationDatabase +// interface. +// +// To create a CompilationDatabase from a build directory one can call +// CompilationDatabase::loadFromDirectory(), which deduces the correct +// compilation database from the root of the build tree. +// +// See the concrete subclasses of CompilationDatabase for currently supported +// formats. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_COMPILATIONDATABASE_H +#define LLVM_CLANG_TOOLING_COMPILATIONDATABASE_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/VirtualFileSystem.h" +#include <memory> +#include <string> +#include <utility> +#include <vector> + +namespace clang { +namespace tooling { + +/// Specifies the working directory and command of a compilation. +struct CompileCommand { + CompileCommand() = default; + CompileCommand(const Twine &Directory, const Twine &Filename, + std::vector<std::string> CommandLine, const Twine &Output) + : Directory(Directory.str()), Filename(Filename.str()), + CommandLine(std::move(CommandLine)), Output(Output.str()) {} + + /// The working directory the command was executed from. + std::string Directory; + + /// The source file associated with the command. + std::string Filename; + + /// The command line that was executed. + std::vector<std::string> CommandLine; + + /// The output file associated with the command. + std::string Output; + + /// If this compile command was guessed rather than read from an authoritative + /// source, a short human-readable explanation. + /// e.g. "inferred from foo/bar.h". + std::string Heuristic; + + friend bool operator==(const CompileCommand &LHS, const CompileCommand &RHS) { + return LHS.Directory == RHS.Directory && LHS.Filename == RHS.Filename && + LHS.CommandLine == RHS.CommandLine && LHS.Output == RHS.Output && + LHS.Heuristic == RHS.Heuristic; + } + + friend bool operator!=(const CompileCommand &LHS, const CompileCommand &RHS) { + return !(LHS == RHS); + } +}; + +/// Interface for compilation databases. +/// +/// A compilation database allows the user to retrieve compile command lines +/// for the files in a project. +/// +/// Many implementations are enumerable, allowing all command lines to be +/// retrieved. These can be used to run clang tools over a subset of the files +/// in a project. +class CompilationDatabase { +public: + virtual ~CompilationDatabase(); + + /// Loads a compilation database from a build directory. + /// + /// Looks at the specified 'BuildDirectory' and creates a compilation database + /// that allows to query compile commands for source files in the + /// corresponding source tree. + /// + /// Returns NULL and sets ErrorMessage if we were not able to build up a + /// compilation database for the build directory. + /// + /// FIXME: Currently only supports JSON compilation databases, which + /// are named 'compile_commands.json' in the given directory. Extend this + /// for other build types (like ninja build files). + static std::unique_ptr<CompilationDatabase> + loadFromDirectory(StringRef BuildDirectory, std::string &ErrorMessage); + + /// Tries to detect a compilation database location and load it. + /// + /// Looks for a compilation database in all parent paths of file 'SourceFile' + /// by calling loadFromDirectory. + static std::unique_ptr<CompilationDatabase> + autoDetectFromSource(StringRef SourceFile, std::string &ErrorMessage); + + /// Tries to detect a compilation database location and load it. + /// + /// Looks for a compilation database in directory 'SourceDir' and all + /// its parent paths by calling loadFromDirectory. + static std::unique_ptr<CompilationDatabase> + autoDetectFromDirectory(StringRef SourceDir, std::string &ErrorMessage); + + /// Returns all compile commands in which the specified file was + /// compiled. + /// + /// This includes compile commands that span multiple source files. + /// For example, consider a project with the following compilations: + /// $ clang++ -o test a.cc b.cc t.cc + /// $ clang++ -o production a.cc b.cc -DPRODUCTION + /// A compilation database representing the project would return both command + /// lines for a.cc and b.cc and only the first command line for t.cc. + virtual std::vector<CompileCommand> getCompileCommands( + StringRef FilePath) const = 0; + + /// Returns the list of all files available in the compilation database. + /// + /// By default, returns nothing. Implementations should override this if they + /// can enumerate their source files. + virtual std::vector<std::string> getAllFiles() const { return {}; } + + /// Returns all compile commands for all the files in the compilation + /// database. + /// + /// FIXME: Add a layer in Tooling that provides an interface to run a tool + /// over all files in a compilation database. Not all build systems have the + /// ability to provide a feasible implementation for \c getAllCompileCommands. + /// + /// By default, this is implemented in terms of getAllFiles() and + /// getCompileCommands(). Subclasses may override this for efficiency. + virtual std::vector<CompileCommand> getAllCompileCommands() const; +}; + +/// A compilation database that returns a single compile command line. +/// +/// Useful when we want a tool to behave more like a compiler invocation. +/// This compilation database is not enumerable: getAllFiles() returns {}. +class FixedCompilationDatabase : public CompilationDatabase { +public: + /// Creates a FixedCompilationDatabase from the arguments after "--". + /// + /// Parses the given command line for "--". If "--" is found, the rest of + /// the arguments will make up the command line in the returned + /// FixedCompilationDatabase. + /// The arguments after "--" must not include positional parameters or the + /// argv[0] of the tool. Those will be added by the FixedCompilationDatabase + /// when a CompileCommand is requested. The argv[0] of the returned command + /// line will be "clang-tool". + /// + /// Returns NULL in case "--" is not found. + /// + /// The argument list is meant to be compatible with normal llvm command line + /// parsing in main methods. + /// int main(int argc, char **argv) { + /// std::unique_ptr<FixedCompilationDatabase> Compilations( + /// FixedCompilationDatabase::loadFromCommandLine(argc, argv)); + /// cl::ParseCommandLineOptions(argc, argv); + /// ... + /// } + /// + /// \param Argc The number of command line arguments - will be changed to + /// the number of arguments before "--", if "--" was found in the argument + /// list. + /// \param Argv Points to the command line arguments. + /// \param ErrorMsg Contains error text if the function returns null pointer. + /// \param Directory The base directory used in the FixedCompilationDatabase. + static std::unique_ptr<FixedCompilationDatabase> + loadFromCommandLine(int &Argc, const char *const *Argv, std::string &ErrorMsg, + const Twine &Directory = "."); + + /// Reads flags from the given file, one-per-line. + /// Returns nullptr and sets ErrorMessage if we can't read the file. + static std::unique_ptr<FixedCompilationDatabase> + loadFromFile(StringRef Path, std::string &ErrorMsg); + + /// Reads flags from the given buffer, one-per-line. + /// Directory is the command CWD, typically the parent of compile_flags.txt. + static std::unique_ptr<FixedCompilationDatabase> + loadFromBuffer(StringRef Directory, StringRef Data, std::string &ErrorMsg); + + /// Constructs a compilation data base from a specified directory + /// and command line. + FixedCompilationDatabase(const Twine &Directory, + ArrayRef<std::string> CommandLine); + + /// Returns the given compile command. + /// + /// Will always return a vector with one entry that contains the directory + /// and command line specified at construction with "clang-tool" as argv[0] + /// and 'FilePath' as positional argument. + std::vector<CompileCommand> + getCompileCommands(StringRef FilePath) const override; + +private: + /// This is built up to contain a single entry vector to be returned from + /// getCompileCommands after adding the positional argument. + std::vector<CompileCommand> CompileCommands; +}; + +/// Transforms a compile command so that it applies the same configuration to +/// a different file. Most args are left intact, but tweaks may be needed +/// to certain flags (-x, -std etc). +/// +/// The output command will always end in {"--", Filename}. +tooling::CompileCommand transferCompileCommand(tooling::CompileCommand, + StringRef Filename); + +/// Returns a wrapped CompilationDatabase that defers to the provided one, +/// but getCompileCommands() will infer commands for unknown files. +/// The return value of getAllFiles() or getAllCompileCommands() is unchanged. +/// See InterpolatingCompilationDatabase.cpp for details on heuristics. +std::unique_ptr<CompilationDatabase> + inferMissingCompileCommands(std::unique_ptr<CompilationDatabase>); + +/// Returns a wrapped CompilationDatabase that will add -target and -mode flags +/// to commandline when they can be deduced from argv[0] of commandline returned +/// by underlying database. +std::unique_ptr<CompilationDatabase> +inferTargetAndDriverMode(std::unique_ptr<CompilationDatabase> Base); + +/// Returns a wrapped CompilationDatabase that will expand all rsp(response) +/// files on commandline returned by underlying database. +std::unique_ptr<CompilationDatabase> +expandResponseFiles(std::unique_ptr<CompilationDatabase> Base, + llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS); + +} // namespace tooling +} // namespace clang + +#endif // LLVM_CLANG_TOOLING_COMPILATIONDATABASE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/CompilationDatabasePluginRegistry.h b/contrib/libs/clang16/include/clang/Tooling/CompilationDatabasePluginRegistry.h new file mode 100644 index 0000000000..eef81d94de --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/CompilationDatabasePluginRegistry.h @@ -0,0 +1,56 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- CompilationDatabasePluginRegistry.h ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H +#define LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H + +#include "clang/Tooling/CompilationDatabase.h" +#include "llvm/Support/Registry.h" + +namespace clang { +namespace tooling { + +/// Interface for compilation database plugins. +/// +/// A compilation database plugin allows the user to register custom compilation +/// databases that are picked up as compilation database if the corresponding +/// library is linked in. To register a plugin, declare a static variable like: +/// +/// \code +/// static CompilationDatabasePluginRegistry::Add<MyDatabasePlugin> +/// X("my-compilation-database", "Reads my own compilation database"); +/// \endcode +class CompilationDatabasePlugin { +public: + virtual ~CompilationDatabasePlugin(); + + /// Loads a compilation database from a build directory. + /// + /// \see CompilationDatabase::loadFromDirectory(). + virtual std::unique_ptr<CompilationDatabase> + loadFromDirectory(StringRef Directory, std::string &ErrorMessage) = 0; +}; + +using CompilationDatabasePluginRegistry = + llvm::Registry<CompilationDatabasePlugin>; + +} // namespace tooling +} // namespace clang + +#endif // LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/DiagnosticsYaml.h b/contrib/libs/clang16/include/clang/Tooling/DiagnosticsYaml.h new file mode 100644 index 0000000000..77258ea9ac --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/DiagnosticsYaml.h @@ -0,0 +1,126 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===-- DiagnosticsYaml.h -- Serialiazation for Diagnosticss ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file defines the structure of a YAML document for serializing +/// diagnostics. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_DIAGNOSTICSYAML_H +#define LLVM_CLANG_TOOLING_DIAGNOSTICSYAML_H + +#include "clang/Tooling/Core/Diagnostic.h" +#include "clang/Tooling/ReplacementsYaml.h" +#include "llvm/Support/YAMLTraits.h" +#include <string> + +LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::Diagnostic) +LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::DiagnosticMessage) +LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::FileByteRange) + +namespace llvm { +namespace yaml { + +template <> struct MappingTraits<clang::tooling::FileByteRange> { + static void mapping(IO &Io, clang::tooling::FileByteRange &R) { + Io.mapRequired("FilePath", R.FilePath); + Io.mapRequired("FileOffset", R.FileOffset); + Io.mapRequired("Length", R.Length); + } +}; + +template <> struct MappingTraits<clang::tooling::DiagnosticMessage> { + static void mapping(IO &Io, clang::tooling::DiagnosticMessage &M) { + Io.mapRequired("Message", M.Message); + Io.mapOptional("FilePath", M.FilePath); + Io.mapOptional("FileOffset", M.FileOffset); + std::vector<clang::tooling::Replacement> Fixes; + for (auto &Replacements : M.Fix) { + llvm::append_range(Fixes, Replacements.second); + } + Io.mapRequired("Replacements", Fixes); + for (auto &Fix : Fixes) { + llvm::Error Err = M.Fix[Fix.getFilePath()].add(Fix); + if (Err) { + // FIXME: Implement better conflict handling. + llvm::errs() << "Fix conflicts with existing fix: " + << llvm::toString(std::move(Err)) << "\n"; + } + } + Io.mapOptional("Ranges", M.Ranges); + } +}; + +template <> struct MappingTraits<clang::tooling::Diagnostic> { + /// Helper to (de)serialize a Diagnostic since we don't have direct + /// access to its data members. + class NormalizedDiagnostic { + public: + NormalizedDiagnostic(const IO &) + : DiagLevel(clang::tooling::Diagnostic::Level::Warning) {} + + NormalizedDiagnostic(const IO &, const clang::tooling::Diagnostic &D) + : DiagnosticName(D.DiagnosticName), Message(D.Message), Notes(D.Notes), + DiagLevel(D.DiagLevel), BuildDirectory(D.BuildDirectory) {} + + clang::tooling::Diagnostic denormalize(const IO &) { + return clang::tooling::Diagnostic(DiagnosticName, Message, Notes, + DiagLevel, BuildDirectory); + } + + std::string DiagnosticName; + clang::tooling::DiagnosticMessage Message; + SmallVector<clang::tooling::DiagnosticMessage, 1> Notes; + clang::tooling::Diagnostic::Level DiagLevel; + std::string BuildDirectory; + }; + + static void mapping(IO &Io, clang::tooling::Diagnostic &D) { + MappingNormalization<NormalizedDiagnostic, clang::tooling::Diagnostic> Keys( + Io, D); + Io.mapRequired("DiagnosticName", Keys->DiagnosticName); + Io.mapRequired("DiagnosticMessage", Keys->Message); + Io.mapOptional("Notes", Keys->Notes); + Io.mapOptional("Level", Keys->DiagLevel); + Io.mapOptional("BuildDirectory", Keys->BuildDirectory); + } +}; + +/// Specialized MappingTraits to describe how a +/// TranslationUnitDiagnostics is (de)serialized. +template <> struct MappingTraits<clang::tooling::TranslationUnitDiagnostics> { + static void mapping(IO &Io, clang::tooling::TranslationUnitDiagnostics &Doc) { + Io.mapRequired("MainSourceFile", Doc.MainSourceFile); + Io.mapRequired("Diagnostics", Doc.Diagnostics); + } +}; + +template <> struct ScalarEnumerationTraits<clang::tooling::Diagnostic::Level> { + static void enumeration(IO &IO, clang::tooling::Diagnostic::Level &Value) { + IO.enumCase(Value, "Warning", clang::tooling::Diagnostic::Warning); + IO.enumCase(Value, "Error", clang::tooling::Diagnostic::Error); + IO.enumCase(Value, "Remark", clang::tooling::Diagnostic::Remark); + } +}; + +} // end namespace yaml +} // end namespace llvm + +#endif // LLVM_CLANG_TOOLING_DIAGNOSTICSYAML_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Execution.h b/contrib/libs/clang16/include/clang/Tooling/Execution.h new file mode 100644 index 0000000000..936c7e0ea0 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Execution.h @@ -0,0 +1,197 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- Execution.h - Executing clang frontend actions -*- C++ ---------*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines framework for executing clang frontend actions. +// +// The framework can be extended to support different execution plans including +// standalone execution on the given TUs or parallel execution on all TUs in +// the codebase. +// +// In order to enable multiprocessing execution, tool actions are expected to +// output result into the ToolResults provided by the executor. The +// `ToolResults` is an interface that abstracts how results are stored e.g. +// in-memory for standalone execution or on-disk for large-scale execution. +// +// New executors can be registered as ToolExecutorPlugins via the +// `ToolExecutorPluginRegistry`. CLI tools can use +// `createExecutorFromCommandLineArgs` to create a specific registered executor +// according to the command-line arguments. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_EXECUTION_H +#define LLVM_CLANG_TOOLING_EXECUTION_H + +#include "clang/Tooling/CommonOptionsParser.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/Registry.h" +#include "llvm/Support/StringSaver.h" + +namespace clang { +namespace tooling { + +extern llvm::cl::opt<std::string> ExecutorName; + +/// An abstraction for the result of a tool execution. For example, the +/// underlying result can be in-memory or on-disk. +/// +/// Results should be string key-value pairs. For example, a refactoring tool +/// can use source location as key and a replacement in YAML format as value. +class ToolResults { +public: + virtual ~ToolResults() = default; + virtual void addResult(StringRef Key, StringRef Value) = 0; + virtual std::vector<std::pair<llvm::StringRef, llvm::StringRef>> + AllKVResults() = 0; + virtual void forEachResult( + llvm::function_ref<void(StringRef Key, StringRef Value)> Callback) = 0; +}; + +/// Stores the key-value results in memory. It maintains the lifetime of +/// the result. Clang tools using this class are expected to generate a small +/// set of different results, or a large set of duplicated results. +class InMemoryToolResults : public ToolResults { +public: + InMemoryToolResults() : Strings(Arena) {} + void addResult(StringRef Key, StringRef Value) override; + std::vector<std::pair<llvm::StringRef, llvm::StringRef>> + AllKVResults() override; + void forEachResult(llvm::function_ref<void(StringRef Key, StringRef Value)> + Callback) override; + +private: + llvm::BumpPtrAllocator Arena; + llvm::UniqueStringSaver Strings; + + std::vector<std::pair<llvm::StringRef, llvm::StringRef>> KVResults; +}; + +/// The context of an execution, including the information about +/// compilation and results. +class ExecutionContext { +public: + virtual ~ExecutionContext() {} + + /// Initializes a context. This does not take ownership of `Results`. + explicit ExecutionContext(ToolResults *Results) : Results(Results) {} + + /// Adds a KV pair to the result container of this execution. + void reportResult(StringRef Key, StringRef Value); + + // Returns the source control system's revision number if applicable. + // Otherwise returns an empty string. + virtual std::string getRevision() { return ""; } + + // Returns the corpus being analyzed, e.g. "llvm" for the LLVM codebase, if + // applicable. + virtual std::string getCorpus() { return ""; } + + // Returns the currently processed compilation unit if available. + virtual std::string getCurrentCompilationUnit() { return ""; } + +private: + ToolResults *Results; +}; + +/// Interface for executing clang frontend actions. +/// +/// This can be extended to support running tool actions in different +/// execution mode, e.g. on a specific set of TUs or many TUs in parallel. +/// +/// New executors can be registered as ToolExecutorPlugins via the +/// `ToolExecutorPluginRegistry`. CLI tools can use +/// `createExecutorFromCommandLineArgs` to create a specific registered +/// executor according to the command-line arguments. +class ToolExecutor { +public: + virtual ~ToolExecutor() {} + + /// Returns the name of a specific executor. + virtual StringRef getExecutorName() const = 0; + + /// Executes each action with a corresponding arguments adjuster. + virtual llvm::Error + execute(llvm::ArrayRef< + std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>> + Actions) = 0; + + /// Convenient functions for the above `execute`. + llvm::Error execute(std::unique_ptr<FrontendActionFactory> Action); + /// Executes an action with an argument adjuster. + llvm::Error execute(std::unique_ptr<FrontendActionFactory> Action, + ArgumentsAdjuster Adjuster); + + /// Returns a reference to the execution context. + /// + /// This should be passed to tool callbacks, and tool callbacks should report + /// results via the returned context. + virtual ExecutionContext *getExecutionContext() = 0; + + /// Returns a reference to the result container. + /// + /// NOTE: This should only be used after the execution finishes. Tool + /// callbacks should report results via `ExecutionContext` instead. + virtual ToolResults *getToolResults() = 0; + + /// Map a virtual file to be used while running the tool. + /// + /// \param FilePath The path at which the content will be mapped. + /// \param Content A buffer of the file's content. + virtual void mapVirtualFile(StringRef FilePath, StringRef Content) = 0; +}; + +/// Interface for factories that create specific executors. This is also +/// used as a plugin to be registered into ToolExecutorPluginRegistry. +class ToolExecutorPlugin { +public: + virtual ~ToolExecutorPlugin() {} + + /// Create an `ToolExecutor`. + /// + /// `OptionsParser` can be consumed (e.g. moved) if the creation succeeds. + virtual llvm::Expected<std::unique_ptr<ToolExecutor>> + create(CommonOptionsParser &OptionsParser) = 0; +}; + +/// This creates a ToolExecutor that is in the global registry based on +/// commandline arguments. +/// +/// This picks the right executor based on the `--executor` option. This parses +/// the commandline arguments with `CommonOptionsParser`, so caller does not +/// need to parse again. +/// +/// By default, this creates a `StandaloneToolExecutor` ("standalone") if +/// `--executor` is not provided. +llvm::Expected<std::unique_ptr<ToolExecutor>> +createExecutorFromCommandLineArgs(int &argc, const char **argv, + llvm::cl::OptionCategory &Category, + const char *Overview = nullptr); + +namespace internal { +llvm::Expected<std::unique_ptr<ToolExecutor>> +createExecutorFromCommandLineArgsImpl(int &argc, const char **argv, + llvm::cl::OptionCategory &Category, + const char *Overview = nullptr); +} // end namespace internal + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_EXECUTION_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/FileMatchTrie.h b/contrib/libs/clang16/include/clang/Tooling/FileMatchTrie.h new file mode 100644 index 0000000000..6f6b9effeb --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/FileMatchTrie.h @@ -0,0 +1,99 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- FileMatchTrie.h ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements a match trie to find the matching file in a compilation +// database based on a given path in the presence of symlinks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_FILEMATCHTRIE_H +#define LLVM_CLANG_TOOLING_FILEMATCHTRIE_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringRef.h" +#include <memory> + +namespace clang { +namespace tooling { + +class FileMatchTrieNode; + +struct PathComparator { + virtual ~PathComparator() = default; + + virtual bool equivalent(StringRef FileA, StringRef FileB) const = 0; +}; + +/// A trie to efficiently match against the entries of the compilation +/// database in order of matching suffix length. +/// +/// When a clang tool is supposed to operate on a specific file, we have to +/// find the corresponding file in the compilation database. Although entries +/// in the compilation database are keyed by filename, a simple string match +/// is insufficient because of symlinks. Commonly, a project hierarchy looks +/// like this: +/// /<project-root>/src/<path>/<somefile>.cc (used as input for the tool) +/// /<project-root>/build/<symlink-to-src>/<path>/<somefile>.cc (stored in DB) +/// +/// Furthermore, there might be symlinks inside the source folder or inside the +/// database, so that the same source file is translated with different build +/// options. +/// +/// For a given input file, the \c FileMatchTrie finds its entries in order +/// of matching suffix length. For each suffix length, there might be one or +/// more entries in the database. For each of those entries, it calls +/// \c llvm::sys::fs::equivalent() (injected as \c PathComparator). There might +/// be zero or more entries with the same matching suffix length that are +/// equivalent to the input file. Three cases are distinguished: +/// 0 equivalent files: Continue with the next suffix length. +/// 1 equivalent file: Best match found, return it. +/// >1 equivalent files: Match is ambiguous, return error. +class FileMatchTrie { +public: + FileMatchTrie(); + + /// Construct a new \c FileMatchTrie with the given \c PathComparator. + /// + /// The \c FileMatchTrie takes ownership of 'Comparator'. Used for testing. + FileMatchTrie(PathComparator* Comparator); + + ~FileMatchTrie(); + + /// Insert a new absolute path. Relative paths are ignored. + void insert(StringRef NewPath); + + /// Finds the corresponding file in this trie. + /// + /// Returns file name stored in this trie that is equivalent to 'FileName' + /// according to 'Comparator', if it can be uniquely identified. If there + /// are no matches an empty \c StringRef is returned. If there are ambiguous + /// matches, an empty \c StringRef is returned and a corresponding message + /// written to 'Error'. + StringRef findEquivalent(StringRef FileName, + raw_ostream &Error) const; + +private: + FileMatchTrieNode *Root; + std::unique_ptr<PathComparator> Comparator; +}; + +} // namespace tooling +} // namespace clang + +#endif // LLVM_CLANG_TOOLING_FILEMATCHTRIE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/FixIt.h b/contrib/libs/clang16/include/clang/Tooling/FixIt.h new file mode 100644 index 0000000000..f4ca46b306 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/FixIt.h @@ -0,0 +1,90 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- FixIt.h - FixIt Hint utilities -------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements functions to ease source rewriting from AST-nodes. +// +// Example swapping A and B expressions: +// +// Expr *A, *B; +// tooling::fixit::createReplacement(*A, *B); +// tooling::fixit::createReplacement(*B, *A); +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_FIXIT_H +#define LLVM_CLANG_TOOLING_FIXIT_H + +#include "clang/AST/ASTContext.h" + +namespace clang { +namespace tooling { +namespace fixit { + +namespace internal { +StringRef getText(CharSourceRange Range, const ASTContext &Context); + +/// Returns the token CharSourceRange corresponding to \p Range. +inline CharSourceRange getSourceRange(const SourceRange &Range) { + return CharSourceRange::getTokenRange(Range); +} + +/// Returns the CharSourceRange of the token at Location \p Loc. +inline CharSourceRange getSourceRange(const SourceLocation &Loc) { + return CharSourceRange::getTokenRange(Loc, Loc); +} + +/// Returns the CharSourceRange of an given Node. \p Node is typically a +/// 'Stmt', 'Expr' or a 'Decl'. +template <typename T> CharSourceRange getSourceRange(const T &Node) { + return CharSourceRange::getTokenRange(Node.getSourceRange()); +} +} // end namespace internal + +/// Returns a textual representation of \p Node. +template <typename T> +StringRef getText(const T &Node, const ASTContext &Context) { + return internal::getText(internal::getSourceRange(Node), Context); +} + +// Returns a FixItHint to remove \p Node. +// TODO: Add support for related syntactical elements (i.e. comments, ...). +template <typename T> FixItHint createRemoval(const T &Node) { + return FixItHint::CreateRemoval(internal::getSourceRange(Node)); +} + +// Returns a FixItHint to replace \p Destination by \p Source. +template <typename D, typename S> +FixItHint createReplacement(const D &Destination, const S &Source, + const ASTContext &Context) { + return FixItHint::CreateReplacement(internal::getSourceRange(Destination), + getText(Source, Context)); +} + +// Returns a FixItHint to replace \p Destination by \p Source. +template <typename D> +FixItHint createReplacement(const D &Destination, StringRef Source) { + return FixItHint::CreateReplacement(internal::getSourceRange(Destination), + Source); +} + +} // end namespace fixit +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_FIXIT_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Inclusions/HeaderAnalysis.h b/contrib/libs/clang16/include/clang/Tooling/Inclusions/HeaderAnalysis.h new file mode 100644 index 0000000000..74b614c530 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Inclusions/HeaderAnalysis.h @@ -0,0 +1,57 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- HeaderAnalysis.h -----------------------------------------*-C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_INCLUSIONS_HEADER_ANALYSIS_H +#define LLVM_CLANG_TOOLING_INCLUSIONS_HEADER_ANALYSIS_H + +#include "llvm/ADT/StringRef.h" +#include <optional> + +namespace clang { +class FileEntry; +class SourceManager; +class HeaderSearch; + +namespace tooling { + +/// Returns true if the given physical file is a self-contained header. +/// +/// A header is considered self-contained if +// - it has a proper header guard or has been #imported or contains #import(s) +// - *and* it doesn't have a dont-include-me pattern. +/// +/// This function can be expensive as it may scan the source code to find out +/// dont-include-me pattern heuristically. +bool isSelfContainedHeader(const FileEntry *FE, const SourceManager &SM, + HeaderSearch &HeaderInfo); + +/// This scans the given source code to see if it contains #import(s). +bool codeContainsImports(llvm::StringRef Code); + +/// If Text begins an Include-What-You-Use directive, returns it. +/// Given "// IWYU pragma: keep", returns "keep". +/// Input is a null-terminated char* as provided by SM.getCharacterData(). +/// (This should not be StringRef as we do *not* want to scan for its length). +/// For multi-line comments, we return only the first line. +std::optional<llvm::StringRef> parseIWYUPragma(const char *Text); + +} // namespace tooling +} // namespace clang + +#endif // LLVM_CLANG_TOOLING_INCLUSIONS_HEADER_ANALYSIS_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Inclusions/HeaderIncludes.h b/contrib/libs/clang16/include/clang/Tooling/Inclusions/HeaderIncludes.h new file mode 100644 index 0000000000..c0f74b1cf5 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Inclusions/HeaderIncludes.h @@ -0,0 +1,153 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- HeaderIncludes.h - Insert/Delete #includes for C++ code--*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_INCLUSIONS_HEADERINCLUDES_H +#define LLVM_CLANG_TOOLING_INCLUSIONS_HEADERINCLUDES_H + +#include "clang/Basic/SourceManager.h" +#include "clang/Tooling/Core/Replacement.h" +#include "clang/Tooling/Inclusions/IncludeStyle.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Regex.h" +#include <list> +#include <optional> +#include <unordered_map> + +namespace clang { +namespace tooling { + +/// This class manages priorities of C++ #include categories and calculates +/// priorities for headers. +/// FIXME(ioeric): move this class into implementation file when clang-format's +/// include sorting functions are also moved here. +class IncludeCategoryManager { +public: + IncludeCategoryManager(const IncludeStyle &Style, StringRef FileName); + + /// Returns the priority of the category which \p IncludeName belongs to. + /// If \p CheckMainHeader is true and \p IncludeName is a main header, returns + /// 0. Otherwise, returns the priority of the matching category or INT_MAX. + /// NOTE: this API is not thread-safe! + int getIncludePriority(StringRef IncludeName, bool CheckMainHeader) const; + int getSortIncludePriority(StringRef IncludeName, bool CheckMainHeader) const; + +private: + bool isMainHeader(StringRef IncludeName) const; + + const IncludeStyle Style; + bool IsMainFile; + std::string FileName; + SmallVector<llvm::Regex, 4> CategoryRegexs; +}; + +enum class IncludeDirective { Include, Import }; + +/// Generates replacements for inserting or deleting #include directives in a +/// file. +class HeaderIncludes { +public: + HeaderIncludes(llvm::StringRef FileName, llvm::StringRef Code, + const IncludeStyle &Style); + + /// Inserts an #include or #import directive of \p Header into the code. + /// If \p IsAngled is true, \p Header will be quoted with <> in the directive; + /// otherwise, it will be quoted with "". + /// + /// When searching for points to insert new header, this ignores #include's + /// after the #include block(s) in the beginning of a file to avoid inserting + /// headers into code sections where new #include's should not be added by + /// default. These code sections include: + /// - raw string literals (containing #include). + /// - #if blocks. + /// - Special #include's among declarations (e.g. functions). + /// + /// Returns a replacement that inserts the new header into a suitable #include + /// block of the same category. This respects the order of the existing + /// #includes in the block; if the existing #includes are not already sorted, + /// this will simply insert the #include in front of the first #include of the + /// same category in the code that should be sorted after \p IncludeName. If + /// \p IncludeName already exists (with exactly the same spelling), this + /// returns std::nullopt. + std::optional<tooling::Replacement> insert(llvm::StringRef Header, + bool IsAngled, + IncludeDirective Directive) const; + + /// Removes all existing #includes and #imports of \p Header quoted with <> if + /// \p IsAngled is true or "" if \p IsAngled is false. + /// This doesn't resolve the header file path; it only deletes #includes and + /// #imports with exactly the same spelling. + tooling::Replacements remove(llvm::StringRef Header, bool IsAngled) const; + + // Matches a whole #include directive. + static const llvm::Regex IncludeRegex; + +private: + struct Include { + Include(StringRef Name, tooling::Range R, IncludeDirective D) + : Name(Name), R(R), Directive(D) {} + + // An include header quoted with either <> or "". + std::string Name; + // The range of the whole line of include directive including any leading + // whitespaces and trailing comment. + tooling::Range R; + // Either #include or #import. + IncludeDirective Directive; + }; + + void addExistingInclude(Include IncludeToAdd, unsigned NextLineOffset); + + std::string FileName; + std::string Code; + + // Map from include name (quotation trimmed) to a list of existing includes + // (in case there are more than one) with the name in the current file. <x> + // and "x" will be treated as the same header when deleting #includes. + // std::list is used for pointers stability (see IncludesByPriority) + llvm::StringMap<std::list<Include>> ExistingIncludes; + + /// Map from priorities of #include categories to all #includes in the same + /// category. This is used to find #includes of the same category when + /// inserting new #includes. #includes in the same categories are sorted in + /// in the order they appear in the source file. + /// See comment for "FormatStyle::IncludeCategories" for details about include + /// priorities. + std::unordered_map<int, llvm::SmallVector<const Include *, 8>> + IncludesByPriority; + + int FirstIncludeOffset; + // All new headers should be inserted after this offset (e.g. after header + // guards, file comment). + unsigned MinInsertOffset; + // Max insertion offset in the original code. For example, we want to avoid + // inserting new #includes into the actual code section (e.g. after a + // declaration). + unsigned MaxInsertOffset; + IncludeCategoryManager Categories; + // Record the offset of the end of the last include in each category. + std::unordered_map<int, int> CategoryEndOffsets; + + // All possible priorities. + std::set<int> Priorities; +}; + +} // namespace tooling +} // namespace clang + +#endif // LLVM_CLANG_TOOLING_INCLUSIONS_HEADERINCLUDES_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Inclusions/IncludeStyle.h b/contrib/libs/clang16/include/clang/Tooling/Inclusions/IncludeStyle.h new file mode 100644 index 0000000000..a0c1f280b8 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Inclusions/IncludeStyle.h @@ -0,0 +1,191 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- IncludeStyle.h - Style of C++ #include directives -------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_INCLUSIONS_INCLUDESTYLE_H +#define LLVM_CLANG_TOOLING_INCLUSIONS_INCLUDESTYLE_H + +#include "llvm/Support/YAMLTraits.h" +#include <string> +#include <vector> + +namespace clang { +namespace tooling { + +/// Style for sorting and grouping C++ #include directives. +struct IncludeStyle { + /// Styles for sorting multiple ``#include`` blocks. + enum IncludeBlocksStyle { + /// Sort each ``#include`` block separately. + /// \code + /// #include "b.h" into #include "b.h" + /// + /// #include <lib/main.h> #include "a.h" + /// #include "a.h" #include <lib/main.h> + /// \endcode + IBS_Preserve, + /// Merge multiple ``#include`` blocks together and sort as one. + /// \code + /// #include "b.h" into #include "a.h" + /// #include "b.h" + /// #include <lib/main.h> #include <lib/main.h> + /// #include "a.h" + /// \endcode + IBS_Merge, + /// Merge multiple ``#include`` blocks together and sort as one. + /// Then split into groups based on category priority. See + /// ``IncludeCategories``. + /// \code + /// #include "b.h" into #include "a.h" + /// #include "b.h" + /// #include <lib/main.h> + /// #include "a.h" #include <lib/main.h> + /// \endcode + IBS_Regroup, + }; + + /// Dependent on the value, multiple ``#include`` blocks can be sorted + /// as one and divided based on category. + /// \version 6 + IncludeBlocksStyle IncludeBlocks; + + /// See documentation of ``IncludeCategories``. + struct IncludeCategory { + /// The regular expression that this category matches. + std::string Regex; + /// The priority to assign to this category. + int Priority; + /// The custom priority to sort before grouping. + int SortPriority; + /// If the regular expression is case sensitive. + bool RegexIsCaseSensitive; + bool operator==(const IncludeCategory &Other) const { + return Regex == Other.Regex && Priority == Other.Priority && + RegexIsCaseSensitive == Other.RegexIsCaseSensitive; + } + }; + + /// Regular expressions denoting the different ``#include`` categories + /// used for ordering ``#includes``. + /// + /// `POSIX extended + /// <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html>`_ + /// regular expressions are supported. + /// + /// These regular expressions are matched against the filename of an include + /// (including the <> or "") in order. The value belonging to the first + /// matching regular expression is assigned and ``#includes`` are sorted first + /// according to increasing category number and then alphabetically within + /// each category. + /// + /// If none of the regular expressions match, INT_MAX is assigned as + /// category. The main header for a source file automatically gets category 0. + /// so that it is generally kept at the beginning of the ``#includes`` + /// (https://llvm.org/docs/CodingStandards.html#include-style). However, you + /// can also assign negative priorities if you have certain headers that + /// always need to be first. + /// + /// There is a third and optional field ``SortPriority`` which can used while + /// ``IncludeBlocks = IBS_Regroup`` to define the priority in which + /// ``#includes`` should be ordered. The value of ``Priority`` defines the + /// order of ``#include blocks`` and also allows the grouping of ``#includes`` + /// of different priority. ``SortPriority`` is set to the value of + /// ``Priority`` as default if it is not assigned. + /// + /// Each regular expression can be marked as case sensitive with the field + /// ``CaseSensitive``, per default it is not. + /// + /// To configure this in the .clang-format file, use: + /// \code{.yaml} + /// IncludeCategories: + /// - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + /// Priority: 2 + /// SortPriority: 2 + /// CaseSensitive: true + /// - Regex: '^((<|")(gtest|gmock|isl|json)/)' + /// Priority: 3 + /// - Regex: '<[[:alnum:].]+>' + /// Priority: 4 + /// - Regex: '.*' + /// Priority: 1 + /// SortPriority: 0 + /// \endcode + /// \version 3.8 + std::vector<IncludeCategory> IncludeCategories; + + /// Specify a regular expression of suffixes that are allowed in the + /// file-to-main-include mapping. + /// + /// When guessing whether a #include is the "main" include (to assign + /// category 0, see above), use this regex of allowed suffixes to the header + /// stem. A partial match is done, so that: + /// - "" means "arbitrary suffix" + /// - "$" means "no suffix" + /// + /// For example, if configured to "(_test)?$", then a header a.h would be seen + /// as the "main" include in both a.cc and a_test.cc. + /// \version 3.9 + std::string IncludeIsMainRegex; + + /// Specify a regular expression for files being formatted + /// that are allowed to be considered "main" in the + /// file-to-main-include mapping. + /// + /// By default, clang-format considers files as "main" only when they end + /// with: ``.c``, ``.cc``, ``.cpp``, ``.c++``, ``.cxx``, ``.m`` or ``.mm`` + /// extensions. + /// For these files a guessing of "main" include takes place + /// (to assign category 0, see above). This config option allows for + /// additional suffixes and extensions for files to be considered as "main". + /// + /// For example, if this option is configured to ``(Impl\.hpp)$``, + /// then a file ``ClassImpl.hpp`` is considered "main" (in addition to + /// ``Class.c``, ``Class.cc``, ``Class.cpp`` and so on) and "main + /// include file" logic will be executed (with *IncludeIsMainRegex* setting + /// also being respected in later phase). Without this option set, + /// ``ClassImpl.hpp`` would not have the main include file put on top + /// before any other include. + /// \version 10 + std::string IncludeIsMainSourceRegex; +}; + +} // namespace tooling +} // namespace clang + +LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::IncludeStyle::IncludeCategory) + +namespace llvm { +namespace yaml { + +template <> +struct MappingTraits<clang::tooling::IncludeStyle::IncludeCategory> { + static void mapping(IO &IO, + clang::tooling::IncludeStyle::IncludeCategory &Category); +}; + +template <> +struct ScalarEnumerationTraits< + clang::tooling::IncludeStyle::IncludeBlocksStyle> { + static void + enumeration(IO &IO, clang::tooling::IncludeStyle::IncludeBlocksStyle &Value); +}; + +} // namespace yaml +} // namespace llvm + +#endif // LLVM_CLANG_TOOLING_INCLUSIONS_INCLUDESTYLE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/JSONCompilationDatabase.h b/contrib/libs/clang16/include/clang/Tooling/JSONCompilationDatabase.h new file mode 100644 index 0000000000..aec5375060 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/JSONCompilationDatabase.h @@ -0,0 +1,153 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- JSONCompilationDatabase.h --------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// The JSONCompilationDatabase finds compilation databases supplied as a file +// 'compile_commands.json'. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_JSONCOMPILATIONDATABASE_H +#define LLVM_CLANG_TOOLING_JSONCOMPILATIONDATABASE_H + +#include "clang/Basic/LLVM.h" +#include "clang/Tooling/CompilationDatabase.h" +#include "clang/Tooling/FileMatchTrie.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/YAMLParser.h" +#include <memory> +#include <string> +#include <tuple> +#include <utility> +#include <vector> + +namespace clang { +namespace tooling { + +/// A JSON based compilation database. +/// +/// JSON compilation database files must contain a list of JSON objects which +/// provide the command lines in the attributes 'directory', 'command', +/// 'arguments' and 'file': +/// [ +/// { "directory": "<working directory of the compile>", +/// "command": "<compile command line>", +/// "file": "<path to source file>" +/// }, +/// { "directory": "<working directory of the compile>", +/// "arguments": ["<raw>", "<command>" "<line>" "<parameters>"], +/// "file": "<path to source file>" +/// }, +/// ... +/// ] +/// Each object entry defines one compile action. The specified file is +/// considered to be the main source file for the translation unit. +/// +/// 'command' is a full command line that will be unescaped. +/// +/// 'arguments' is a list of command line arguments that will not be unescaped. +/// +/// JSON compilation databases can for example be generated in CMake projects +/// by setting the flag -DCMAKE_EXPORT_COMPILE_COMMANDS. +enum class JSONCommandLineSyntax { Windows, Gnu, AutoDetect }; +class JSONCompilationDatabase : public CompilationDatabase { +public: + /// Loads a JSON compilation database from the specified file. + /// + /// Returns NULL and sets ErrorMessage if the database could not be + /// loaded from the given file. + static std::unique_ptr<JSONCompilationDatabase> + loadFromFile(StringRef FilePath, std::string &ErrorMessage, + JSONCommandLineSyntax Syntax); + + /// Loads a JSON compilation database from a data buffer. + /// + /// Returns NULL and sets ErrorMessage if the database could not be loaded. + static std::unique_ptr<JSONCompilationDatabase> + loadFromBuffer(StringRef DatabaseString, std::string &ErrorMessage, + JSONCommandLineSyntax Syntax); + + /// Returns all compile commands in which the specified file was + /// compiled. + /// + /// FIXME: Currently FilePath must be an absolute path inside the + /// source directory which does not have symlinks resolved. + std::vector<CompileCommand> + getCompileCommands(StringRef FilePath) const override; + + /// Returns the list of all files available in the compilation database. + /// + /// These are the 'file' entries of the JSON objects. + std::vector<std::string> getAllFiles() const override; + + /// Returns all compile commands for all the files in the compilation + /// database. + std::vector<CompileCommand> getAllCompileCommands() const override; + +private: + /// Constructs a JSON compilation database on a memory buffer. + JSONCompilationDatabase(std::unique_ptr<llvm::MemoryBuffer> Database, + JSONCommandLineSyntax Syntax) + : Database(std::move(Database)), Syntax(Syntax), + YAMLStream(this->Database->getBuffer(), SM) {} + + /// Parses the database file and creates the index. + /// + /// Returns whether parsing succeeded. Sets ErrorMessage if parsing + /// failed. + bool parse(std::string &ErrorMessage); + + // Tuple (directory, filename, commandline, output) where 'commandline' + // points to the corresponding scalar nodes in the YAML stream. + // If the command line contains a single argument, it is a shell-escaped + // command line. + // Otherwise, each entry in the command line vector is a literal + // argument to the compiler. + // The output field may be a nullptr. + using CompileCommandRef = + std::tuple<llvm::yaml::ScalarNode *, llvm::yaml::ScalarNode *, + std::vector<llvm::yaml::ScalarNode *>, + llvm::yaml::ScalarNode *>; + + /// Converts the given array of CompileCommandRefs to CompileCommands. + void getCommands(ArrayRef<CompileCommandRef> CommandsRef, + std::vector<CompileCommand> &Commands) const; + + // Maps file paths to the compile command lines for that file. + llvm::StringMap<std::vector<CompileCommandRef>> IndexByFile; + + /// All the compile commands in the order that they were provided in the + /// JSON stream. + std::vector<CompileCommandRef> AllCommands; + + FileMatchTrie MatchTrie; + + std::unique_ptr<llvm::MemoryBuffer> Database; + JSONCommandLineSyntax Syntax; + llvm::SourceMgr SM; + llvm::yaml::Stream YAMLStream; +}; + +} // namespace tooling +} // namespace clang + +#endif // LLVM_CLANG_TOOLING_JSONCOMPILATIONDATABASE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/NodeIntrospection.h b/contrib/libs/clang16/include/clang/Tooling/NodeIntrospection.h new file mode 100644 index 0000000000..5528d94f98 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/NodeIntrospection.h @@ -0,0 +1,112 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- NodeIntrospection.h ------------------------------------*- C++ -*---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the implementation of the NodeIntrospection. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_NODEINTROSPECTION_H +#define LLVM_CLANG_TOOLING_NODEINTROSPECTION_H + +#include "clang/AST/ASTTypeTraits.h" +#include "clang/AST/DeclarationName.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include <set> + +namespace clang { + +class Stmt; +class Decl; +class CXXCtorInitializer; +class NestedNameSpecifierLoc; +class TemplateArgumentLoc; +class CXXBaseSpecifier; +struct DeclarationNameInfo; + +namespace tooling { + +class LocationCall; +using SharedLocationCall = llvm::IntrusiveRefCntPtr<LocationCall>; + +class LocationCall : public llvm::ThreadSafeRefCountedBase<LocationCall> { +public: + enum LocationCallFlags { NoFlags, ReturnsPointer, IsCast }; + LocationCall(SharedLocationCall on, std::string name, + LocationCallFlags flags = NoFlags) + : m_flags(flags), m_on(std::move(on)), m_name(std::move(name)) {} + + LocationCall *on() const { return m_on.get(); } + StringRef name() const { return m_name; } + bool returnsPointer() const { return m_flags & ReturnsPointer; } + bool isCast() const { return m_flags & IsCast; } + +private: + LocationCallFlags m_flags; + SharedLocationCall m_on; + std::string m_name; +}; + +class LocationCallFormatterCpp { +public: + static void print(const LocationCall &Call, llvm::raw_ostream &OS); + static std::string format(const LocationCall &Call); +}; + +namespace internal { +struct RangeLessThan { + bool operator()(std::pair<SourceRange, SharedLocationCall> const &LHS, + std::pair<SourceRange, SharedLocationCall> const &RHS) const; + bool + operator()(std::pair<SourceLocation, SharedLocationCall> const &LHS, + std::pair<SourceLocation, SharedLocationCall> const &RHS) const; +}; + +} // namespace internal + +// Note that this container stores unique results in a deterministic, but +// the location calls are in an unspecified order. Clients which desire +// a particular order for the location calls, such as alphabetical, +// should sort results after retrieval, because the order is dependent +// on how the LocationCalls are formatted. +template <typename T, typename U> +using UniqueMultiMap = std::set<std::pair<T, U>, internal::RangeLessThan>; + +using SourceLocationMap = UniqueMultiMap<SourceLocation, SharedLocationCall>; +using SourceRangeMap = UniqueMultiMap<SourceRange, SharedLocationCall>; + +struct NodeLocationAccessors { + SourceLocationMap LocationAccessors; + SourceRangeMap RangeAccessors; +}; + +namespace NodeIntrospection { +bool hasIntrospectionSupport(); +NodeLocationAccessors GetLocations(clang::Stmt const *Object); +NodeLocationAccessors GetLocations(clang::Decl const *Object); +NodeLocationAccessors GetLocations(clang::CXXCtorInitializer const *Object); +NodeLocationAccessors GetLocations(clang::NestedNameSpecifierLoc const &); +NodeLocationAccessors GetLocations(clang::TemplateArgumentLoc const &); +NodeLocationAccessors GetLocations(clang::CXXBaseSpecifier const *); +NodeLocationAccessors GetLocations(clang::TypeLoc const &); +NodeLocationAccessors GetLocations(clang::DeclarationNameInfo const &); +NodeLocationAccessors GetLocations(clang::DynTypedNode const &Node); +} // namespace NodeIntrospection +} // namespace tooling +} // namespace clang +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring.h new file mode 100644 index 0000000000..a75fe76b82 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring.h @@ -0,0 +1,110 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- Refactoring.h - Framework for clang refactoring tools --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Interfaces supporting refactorings that span multiple translation units. +// While single translation unit refactorings are supported via the Rewriter, +// when refactoring multiple translation units changes must be stored in a +// SourceManager independent form, duplicate changes need to be removed, and +// all changes must be applied at once at the end of the refactoring so that +// the code is always parseable. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_H +#define LLVM_CLANG_TOOLING_REFACTORING_H + +#include "clang/Tooling/Core/Replacement.h" +#include "clang/Tooling/Tooling.h" +#include <map> +#include <string> + +namespace clang { + +class Rewriter; + +namespace tooling { + +/// A tool to run refactorings. +/// +/// This is a refactoring specific version of \see ClangTool. FrontendActions +/// passed to run() and runAndSave() should add replacements to +/// getReplacements(). +class RefactoringTool : public ClangTool { +public: + /// \see ClangTool::ClangTool. + RefactoringTool(const CompilationDatabase &Compilations, + ArrayRef<std::string> SourcePaths, + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<PCHContainerOperations>()); + + /// Returns the file path to replacements map to which replacements + /// should be added during the run of the tool. + std::map<std::string, Replacements> &getReplacements(); + + /// Call run(), apply all generated replacements, and immediately save + /// the results to disk. + /// + /// \returns 0 upon success. Non-zero upon failure. + int runAndSave(FrontendActionFactory *ActionFactory); + + /// Apply all stored replacements to the given Rewriter. + /// + /// FileToReplaces will be deduplicated with `groupReplacementsByFile` before + /// application. + /// + /// Replacement applications happen independently of the success of other + /// applications. + /// + /// \returns true if all replacements apply. false otherwise. + bool applyAllReplacements(Rewriter &Rewrite); + +private: + /// Write all refactored files to disk. + int saveRewrittenFiles(Rewriter &Rewrite); + +private: + std::map<std::string, Replacements> FileToReplaces; +}; + +/// Groups \p Replaces by the file path and applies each group of +/// Replacements on the related file in \p Rewriter. In addition to applying +/// given Replacements, this function also formats the changed code. +/// +/// \pre Replacements must be conflict-free. +/// +/// FileToReplaces will be deduplicated with `groupReplacementsByFile` before +/// application. +/// +/// Replacement applications happen independently of the success of other +/// applications. +/// +/// \param[in] FileToReplaces Replacements (grouped by files) to apply. +/// \param[in] Rewrite The `Rewritter` to apply replacements on. +/// \param[in] Style The style name used for reformatting. See ```getStyle``` in +/// "include/clang/Format/Format.h" for all possible style forms. +/// +/// \returns true if all replacements applied and formatted. false otherwise. +bool formatAndApplyAllReplacements( + const std::map<std::string, Replacements> &FileToReplaces, + Rewriter &Rewrite, StringRef Style = "file"); + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/ASTSelection.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/ASTSelection.h new file mode 100644 index 0000000000..6ae38a98cc --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/ASTSelection.h @@ -0,0 +1,167 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- ASTSelection.h - Clang refactoring library -----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_ASTSELECTION_H +#define LLVM_CLANG_TOOLING_REFACTORING_ASTSELECTION_H + +#include "clang/AST/ASTTypeTraits.h" +#include "clang/AST/Stmt.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/Support/raw_ostream.h" +#include <optional> +#include <vector> + +namespace clang { + +class ASTContext; + +namespace tooling { + +enum class SourceSelectionKind { + /// A node that's not selected. + None, + + /// A node that's considered to be selected because the whole selection range + /// is inside of its source range. + ContainsSelection, + /// A node that's considered to be selected because the start of the selection + /// range is inside its source range. + ContainsSelectionStart, + /// A node that's considered to be selected because the end of the selection + /// range is inside its source range. + ContainsSelectionEnd, + + /// A node that's considered to be selected because the node is entirely in + /// the selection range. + InsideSelection, +}; + +/// Represents a selected AST node. +/// +/// AST selection is represented using a tree of \c SelectedASTNode. The tree +/// follows the top-down shape of the actual AST. Each selected node has +/// a selection kind. The kind might be none as the node itself might not +/// actually be selected, e.g. a statement in macro whose child is in a macro +/// argument. +struct SelectedASTNode { + DynTypedNode Node; + SourceSelectionKind SelectionKind; + std::vector<SelectedASTNode> Children; + + SelectedASTNode(const DynTypedNode &Node, SourceSelectionKind SelectionKind) + : Node(Node), SelectionKind(SelectionKind) {} + SelectedASTNode(SelectedASTNode &&) = default; + SelectedASTNode &operator=(SelectedASTNode &&) = default; + + void dump(llvm::raw_ostream &OS = llvm::errs()) const; + + using ReferenceType = std::reference_wrapper<const SelectedASTNode>; +}; + +/// Traverses the given ASTContext and creates a tree of selected AST nodes. +/// +/// \returns std::nullopt if no nodes are selected in the AST, or a selected AST +/// node that corresponds to the TranslationUnitDecl otherwise. +std::optional<SelectedASTNode> findSelectedASTNodes(const ASTContext &Context, + SourceRange SelectionRange); + +/// An AST selection value that corresponds to a selection of a set of +/// statements that belong to one body of code (like one function). +/// +/// For example, the following selection in the source. +/// +/// \code +/// void function() { +/// // selection begin: +/// int x = 0; +/// { +/// // selection end +/// x = 1; +/// } +/// x = 2; +/// } +/// \endcode +/// +/// Would correspond to a code range selection of statements "int x = 0" +/// and the entire compound statement that follows it. +/// +/// A \c CodeRangeASTSelection value stores references to the full +/// \c SelectedASTNode tree and should not outlive it. +class CodeRangeASTSelection { +public: + CodeRangeASTSelection(CodeRangeASTSelection &&) = default; + CodeRangeASTSelection &operator=(CodeRangeASTSelection &&) = default; + + /// Returns the parent hierarchy (top to bottom) for the selected nodes. + ArrayRef<SelectedASTNode::ReferenceType> getParents() { return Parents; } + + /// Returns the number of selected statements. + size_t size() const { + if (!AreChildrenSelected) + return 1; + return SelectedNode.get().Children.size(); + } + + const Stmt *operator[](size_t I) const { + if (!AreChildrenSelected) { + assert(I == 0 && "Invalid index"); + return SelectedNode.get().Node.get<Stmt>(); + } + return SelectedNode.get().Children[I].Node.get<Stmt>(); + } + + /// Returns true when a selected code range is in a function-like body + /// of code, like a function, method or a block. + /// + /// This function can be used to test against selected expressions that are + /// located outside of a function, e.g. global variable initializers, default + /// argument values, or even template arguments. + /// + /// Use the \c getFunctionLikeNearestParent to get the function-like parent + /// declaration. + bool isInFunctionLikeBodyOfCode() const; + + /// Returns the nearest function-like parent declaration or null if such + /// declaration doesn't exist. + const Decl *getFunctionLikeNearestParent() const; + + static std::optional<CodeRangeASTSelection> + create(SourceRange SelectionRange, const SelectedASTNode &ASTSelection); + +private: + CodeRangeASTSelection(SelectedASTNode::ReferenceType SelectedNode, + ArrayRef<SelectedASTNode::ReferenceType> Parents, + bool AreChildrenSelected) + : SelectedNode(SelectedNode), Parents(Parents.begin(), Parents.end()), + AreChildrenSelected(AreChildrenSelected) {} + + /// The reference to the selected node (or reference to the selected + /// child nodes). + SelectedASTNode::ReferenceType SelectedNode; + /// The parent hierarchy (top to bottom) for the selected noe. + llvm::SmallVector<SelectedASTNode::ReferenceType, 8> Parents; + /// True only when the children of the selected node are actually selected. + bool AreChildrenSelected; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_ASTSELECTION_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/AtomicChange.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/AtomicChange.h new file mode 100644 index 0000000000..f5da7ec742 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/AtomicChange.h @@ -0,0 +1,203 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- AtomicChange.h - AtomicChange class --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines AtomicChange which is used to create a set of source +// changes, e.g. replacements and header insertions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_ATOMICCHANGE_H +#define LLVM_CLANG_TOOLING_REFACTORING_ATOMICCHANGE_H + +#include "clang/Basic/SourceManager.h" +#include "clang/Format/Format.h" +#include "clang/Tooling/Core/Replacement.h" +#include "llvm/ADT/Any.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" + +namespace clang { +namespace tooling { + +/// An atomic change is used to create and group a set of source edits, +/// e.g. replacements or header insertions. Edits in an AtomicChange should be +/// related, e.g. replacements for the same type reference and the corresponding +/// header insertion/deletion. +/// +/// An AtomicChange is uniquely identified by a key and will either be fully +/// applied or not applied at all. +/// +/// Calling setError on an AtomicChange stores the error message and marks it as +/// bad, i.e. none of its source edits will be applied. +class AtomicChange { +public: + /// Creates an atomic change around \p KeyPosition with the key being a + /// concatenation of the file name and the offset of \p KeyPosition. + /// \p KeyPosition should be the location of the key syntactical element that + /// is being changed, e.g. the call to a refactored method. + AtomicChange(const SourceManager &SM, SourceLocation KeyPosition); + + AtomicChange(const SourceManager &SM, SourceLocation KeyPosition, + llvm::Any Metadata); + + /// Creates an atomic change for \p FilePath with a customized key. + AtomicChange(llvm::StringRef FilePath, llvm::StringRef Key) + : Key(Key), FilePath(FilePath) {} + + AtomicChange(AtomicChange &&) = default; + AtomicChange(const AtomicChange &) = default; + + AtomicChange &operator=(AtomicChange &&) = default; + AtomicChange &operator=(const AtomicChange &) = default; + + bool operator==(const AtomicChange &Other) const; + + /// Returns the atomic change as a YAML string. + std::string toYAMLString(); + + /// Converts a YAML-encoded automic change to AtomicChange. + static AtomicChange convertFromYAML(llvm::StringRef YAMLContent); + + /// Returns the key of this change, which is a concatenation of the + /// file name and offset of the key position. + const std::string &getKey() const { return Key; } + + /// Returns the path of the file containing this atomic change. + const std::string &getFilePath() const { return FilePath; } + + /// If this change could not be created successfully, e.g. because of + /// conflicts among replacements, use this to set an error description. + /// Thereby, places that cannot be fixed automatically can be gathered when + /// applying changes. + void setError(llvm::StringRef Error) { this->Error = std::string(Error); } + + /// Returns whether an error has been set on this list. + bool hasError() const { return !Error.empty(); } + + /// Returns the error message or an empty string if it does not exist. + const std::string &getError() const { return Error; } + + /// Adds a replacement that replaces the given Range with + /// ReplacementText. + /// \returns An llvm::Error carrying ReplacementError on error. + llvm::Error replace(const SourceManager &SM, const CharSourceRange &Range, + llvm::StringRef ReplacementText); + + /// Adds a replacement that replaces range [Loc, Loc+Length) with + /// \p Text. + /// \returns An llvm::Error carrying ReplacementError on error. + llvm::Error replace(const SourceManager &SM, SourceLocation Loc, + unsigned Length, llvm::StringRef Text); + + /// Adds a replacement that inserts \p Text at \p Loc. If this + /// insertion conflicts with an existing insertion (at the same position), + /// this will be inserted before/after the existing insertion depending on + /// \p InsertAfter. Users should use `replace` with `Length=0` instead if they + /// do not want conflict resolving by default. If the conflicting replacement + /// is not an insertion, an error is returned. + /// + /// \returns An llvm::Error carrying ReplacementError on error. + llvm::Error insert(const SourceManager &SM, SourceLocation Loc, + llvm::StringRef Text, bool InsertAfter = true); + + /// Adds a header into the file that contains the key position. + /// Header can be in angle brackets or double quotation marks. By default + /// (header is not quoted), header will be surrounded with double quotes. + void addHeader(llvm::StringRef Header); + + /// Removes a header from the file that contains the key position. + void removeHeader(llvm::StringRef Header); + + /// Returns a const reference to existing replacements. + const Replacements &getReplacements() const { return Replaces; } + + Replacements &getReplacements() { return Replaces; } + + llvm::ArrayRef<std::string> getInsertedHeaders() const { + return InsertedHeaders; + } + + llvm::ArrayRef<std::string> getRemovedHeaders() const { + return RemovedHeaders; + } + + const llvm::Any &getMetadata() const { return Metadata; } + +private: + AtomicChange() {} + + AtomicChange(std::string Key, std::string FilePath, std::string Error, + std::vector<std::string> InsertedHeaders, + std::vector<std::string> RemovedHeaders, + clang::tooling::Replacements Replaces); + + // This uniquely identifies an AtomicChange. + std::string Key; + std::string FilePath; + std::string Error; + std::vector<std::string> InsertedHeaders; + std::vector<std::string> RemovedHeaders; + tooling::Replacements Replaces; + + // This field stores metadata which is ignored for the purposes of applying + // edits to source, but may be useful for other consumers of AtomicChanges. In + // particular, consumers can use this to direct how they want to consume each + // edit. + llvm::Any Metadata; +}; + +using AtomicChanges = std::vector<AtomicChange>; + +// Defines specs for applying changes. +struct ApplyChangesSpec { + // If true, cleans up redundant/erroneous code around changed code with + // clang-format's cleanup functionality, e.g. redundant commas around deleted + // parameter or empty namespaces introduced by deletions. + bool Cleanup = true; + + format::FormatStyle Style = format::getNoStyle(); + + // Options for selectively formatting changes with clang-format: + // kAll: Format all changed lines. + // kNone: Don't format anything. + // kViolations: Format lines exceeding the `ColumnLimit` in `Style`. + enum FormatOption { kAll, kNone, kViolations }; + + FormatOption Format = kNone; +}; + +/// Applies all AtomicChanges in \p Changes to the \p Code. +/// +/// This completely ignores the file path in each change and replaces them with +/// \p FilePath, i.e. callers are responsible for ensuring all changes are for +/// the same file. +/// +/// \returns The changed code if all changes are applied successfully; +/// otherwise, an llvm::Error carrying llvm::StringError is returned (the Error +/// message can be converted to string with `llvm::toString()` and the +/// error_code should be ignored). +llvm::Expected<std::string> +applyAtomicChanges(llvm::StringRef FilePath, llvm::StringRef Code, + llvm::ArrayRef<AtomicChange> Changes, + const ApplyChangesSpec &Spec); + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_ATOMICCHANGE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/Extract/Extract.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/Extract/Extract.h new file mode 100644 index 0000000000..16627c19ca --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/Extract/Extract.h @@ -0,0 +1,65 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- Extract.h - Clang refactoring library ----------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_EXTRACT_H +#define LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_EXTRACT_H + +#include "clang/Tooling/Refactoring/ASTSelection.h" +#include "clang/Tooling/Refactoring/RefactoringActionRules.h" +#include <optional> + +namespace clang { +namespace tooling { + +/// An "Extract Function" refactoring moves code into a new function that's +/// then called from the place where the original code was. +class ExtractFunction final : public SourceChangeRefactoringRule { +public: + /// Initiates the extract function refactoring operation. + /// + /// \param Code The selected set of statements. + /// \param DeclName The name of the extract function. If None, + /// "extracted" is used. + static Expected<ExtractFunction> + initiate(RefactoringRuleContext &Context, CodeRangeASTSelection Code, + std::optional<std::string> DeclName); + + static const RefactoringDescriptor &describe(); + +private: + ExtractFunction(CodeRangeASTSelection Code, + std::optional<std::string> DeclName) + : Code(std::move(Code)), + DeclName(DeclName ? std::move(*DeclName) : "extracted") {} + + Expected<AtomicChanges> + createSourceReplacements(RefactoringRuleContext &Context) override; + + CodeRangeASTSelection Code; + + // FIXME: Account for naming collisions: + // - error when name is specified by user. + // - rename to "extractedN" when name is implicit. + std::string DeclName; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_EXTRACT_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h new file mode 100644 index 0000000000..03a173e23f --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h @@ -0,0 +1,62 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- SourceExtraction.cpp - Clang refactoring library -----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCEEXTRACTION_H +#define LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCEEXTRACTION_H + +#include "clang/Basic/LLVM.h" + +namespace clang { + +class LangOptions; +class SourceManager; +class SourceRange; +class Stmt; + +namespace tooling { + +/// Determines which semicolons should be inserted during extraction. +class ExtractionSemicolonPolicy { +public: + bool isNeededInExtractedFunction() const { + return IsNeededInExtractedFunction; + } + + bool isNeededInOriginalFunction() const { return IsNeededInOriginalFunction; } + + /// Returns the semicolon insertion policy that is needed for extraction of + /// the given statement from the given source range. + static ExtractionSemicolonPolicy compute(const Stmt *S, + SourceRange &ExtractedRange, + const SourceManager &SM, + const LangOptions &LangOpts); + +private: + ExtractionSemicolonPolicy(bool IsNeededInExtractedFunction, + bool IsNeededInOriginalFunction) + : IsNeededInExtractedFunction(IsNeededInExtractedFunction), + IsNeededInOriginalFunction(IsNeededInOriginalFunction) {} + bool IsNeededInExtractedFunction; + bool IsNeededInOriginalFunction; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCEEXTRACTION_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/Lookup.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/Lookup.h new file mode 100644 index 0000000000..0a47f78aa9 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/Lookup.h @@ -0,0 +1,61 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- Lookup.h - Framework for clang refactoring tools --*- C++ -*------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines helper methods for clang tools performing name lookup. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_LOOKUP_H +#define LLVM_CLANG_TOOLING_REFACTORING_LOOKUP_H + +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include <string> + +namespace clang { + +class DeclContext; +class NamedDecl; +class NestedNameSpecifier; + +namespace tooling { + +/// Emulate a lookup to replace one nested name specifier with another using as +/// few additional namespace qualifications as possible. +/// +/// This does not perform a full C++ lookup so ADL will not work. +/// +/// \param Use The nested name to be replaced. +/// \param UseLoc The location of name to be replaced. +/// \param UseContext The context in which the nested name is contained. This +/// will be used to minimize namespace qualifications. +/// \param FromDecl The declaration to which the nested name points. +/// \param ReplacementString The replacement nested name. Must be fully +/// qualified including a leading "::". +/// \returns The new name to be inserted in place of the current nested name. +std::string replaceNestedName(const NestedNameSpecifier *Use, + SourceLocation UseLoc, + const DeclContext *UseContext, + const NamedDecl *FromDecl, + StringRef ReplacementString); + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_LOOKUP_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h new file mode 100644 index 0000000000..09ce6217b4 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h @@ -0,0 +1,164 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- RecursiveSymbolVisitor.h - Clang refactoring library -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// A wrapper class around \c RecursiveASTVisitor that visits each +/// occurrences of a named symbol. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_RECURSIVESYMBOLVISITOR_H +#define LLVM_CLANG_TOOLING_REFACTORING_RECURSIVESYMBOLVISITOR_H + +#include "clang/AST/AST.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Lex/Lexer.h" + +namespace clang { +namespace tooling { + +/// Traverses the AST and visits the occurrence of each named symbol in the +/// given nodes. +template <typename T> +class RecursiveSymbolVisitor + : public RecursiveASTVisitor<RecursiveSymbolVisitor<T>> { + using BaseType = RecursiveASTVisitor<RecursiveSymbolVisitor<T>>; + +public: + RecursiveSymbolVisitor(const SourceManager &SM, const LangOptions &LangOpts) + : SM(SM), LangOpts(LangOpts) {} + + bool visitSymbolOccurrence(const NamedDecl *ND, + ArrayRef<SourceRange> NameRanges) { + return true; + } + + // Declaration visitors: + + bool VisitNamedDecl(const NamedDecl *D) { + return isa<CXXConversionDecl>(D) ? true : visit(D, D->getLocation()); + } + + bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) { + for (const auto *Initializer : CD->inits()) { + // Ignore implicit initializers. + if (!Initializer->isWritten()) + continue; + if (const FieldDecl *FD = Initializer->getMember()) { + if (!visit(FD, Initializer->getSourceLocation(), + Lexer::getLocForEndOfToken(Initializer->getSourceLocation(), + 0, SM, LangOpts))) + return false; + } + } + return true; + } + + // Expression visitors: + + bool VisitDeclRefExpr(const DeclRefExpr *Expr) { + return visit(Expr->getFoundDecl(), Expr->getLocation()); + } + + bool VisitMemberExpr(const MemberExpr *Expr) { + return visit(Expr->getFoundDecl().getDecl(), Expr->getMemberLoc()); + } + + bool VisitOffsetOfExpr(const OffsetOfExpr *S) { + for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) { + const OffsetOfNode &Component = S->getComponent(I); + if (Component.getKind() == OffsetOfNode::Field) { + if (!visit(Component.getField(), Component.getEndLoc())) + return false; + } + // FIXME: Try to resolve dependent field references. + } + return true; + } + + // Other visitors: + + bool VisitTypeLoc(const TypeLoc Loc) { + const SourceLocation TypeBeginLoc = Loc.getBeginLoc(); + const SourceLocation TypeEndLoc = + Lexer::getLocForEndOfToken(TypeBeginLoc, 0, SM, LangOpts); + if (const auto *TemplateTypeParm = + dyn_cast<TemplateTypeParmType>(Loc.getType())) { + if (!visit(TemplateTypeParm->getDecl(), TypeBeginLoc, TypeEndLoc)) + return false; + } + if (const auto *TemplateSpecType = + dyn_cast<TemplateSpecializationType>(Loc.getType())) { + if (!visit(TemplateSpecType->getTemplateName().getAsTemplateDecl(), + TypeBeginLoc, TypeEndLoc)) + return false; + } + if (const Type *TP = Loc.getTypePtr()) { + if (TP->getTypeClass() == clang::Type::Record) + return visit(TP->getAsCXXRecordDecl(), TypeBeginLoc, TypeEndLoc); + } + return true; + } + + bool VisitTypedefTypeLoc(TypedefTypeLoc TL) { + const SourceLocation TypeEndLoc = + Lexer::getLocForEndOfToken(TL.getBeginLoc(), 0, SM, LangOpts); + return visit(TL.getTypedefNameDecl(), TL.getBeginLoc(), TypeEndLoc); + } + + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { + // The base visitor will visit NNSL prefixes, so we should only look at + // the current NNS. + if (NNS) { + const NamespaceDecl *ND = NNS.getNestedNameSpecifier()->getAsNamespace(); + if (!visit(ND, NNS.getLocalBeginLoc(), NNS.getLocalEndLoc())) + return false; + } + return BaseType::TraverseNestedNameSpecifierLoc(NNS); + } + + bool VisitDesignatedInitExpr(const DesignatedInitExpr *E) { + for (const DesignatedInitExpr::Designator &D : E->designators()) { + if (D.isFieldDesignator() && D.getField()) { + const FieldDecl *Decl = D.getField(); + if (!visit(Decl, D.getFieldLoc(), D.getFieldLoc())) + return false; + } + } + return true; + } + +private: + const SourceManager &SM; + const LangOptions &LangOpts; + + bool visit(const NamedDecl *ND, SourceLocation BeginLoc, + SourceLocation EndLoc) { + return static_cast<T *>(this)->visitSymbolOccurrence( + ND, SourceRange(BeginLoc, EndLoc)); + } + bool visit(const NamedDecl *ND, SourceLocation Loc) { + return visit(ND, Loc, Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts)); + } +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_RECURSIVESYMBOLVISITOR_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringAction.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringAction.h new file mode 100644 index 0000000000..28d30fdf90 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringAction.h @@ -0,0 +1,74 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- RefactoringAction.h - Clang refactoring library ------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTION_H +#define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTION_H + +#include "clang/Basic/LLVM.h" +#include "clang/Tooling/Refactoring/RefactoringActionRules.h" +#include <vector> + +namespace clang { +namespace tooling { + +/// A refactoring action is a class that defines a set of related refactoring +/// action rules. These rules get grouped under a common umbrella - a single +/// clang-refactor subcommand. +/// +/// A subclass of \c RefactoringAction is responsible for creating the set of +/// grouped refactoring action rules that represent one refactoring operation. +/// Although the rules in one action may have a number of different +/// implementations, they should strive to produce a similar result. It should +/// be easy for users to identify which refactoring action produced the result +/// regardless of which refactoring action rule was used. +/// +/// The distinction between actions and rules enables the creation of action +/// that uses very different rules, for example: +/// - local vs global: a refactoring operation like +/// "add missing switch cases" can be applied to one switch when it's +/// selected in an editor, or to all switches in a project when an enum +/// constant is added to an enum. +/// - tool vs editor: some refactoring operation can be initiated in the +/// editor when a declaration is selected, or in a tool when the name of +/// the declaration is passed using a command-line argument. +class RefactoringAction { +public: + virtual ~RefactoringAction() {} + + /// Returns the name of the subcommand that's used by clang-refactor for this + /// action. + virtual StringRef getCommand() const = 0; + + virtual StringRef getDescription() const = 0; + + RefactoringActionRules createActiveActionRules(); + +protected: + /// Returns a set of refactoring actions rules that are defined by this + /// action. + virtual RefactoringActionRules createActionRules() const = 0; +}; + +/// Returns the list of all the available refactoring actions. +std::vector<std::unique_ptr<RefactoringAction>> createRefactoringActions(); + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTION_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringActionRule.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringActionRule.h new file mode 100644 index 0000000000..2bc21b0714 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringActionRule.h @@ -0,0 +1,82 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- RefactoringActionRule.h - Clang refactoring library -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULE_H +#define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULE_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringRef.h" + +namespace clang { +namespace tooling { + +class RefactoringOptionVisitor; +class RefactoringResultConsumer; +class RefactoringRuleContext; + +struct RefactoringDescriptor { + /// A unique identifier for the specific refactoring. + StringRef Name; + /// A human readable title for the refactoring. + StringRef Title; + /// A human readable description of what the refactoring does. + StringRef Description; +}; + +/// A common refactoring action rule interface that defines the 'invoke' +/// function that performs the refactoring operation (either fully or +/// partially). +class RefactoringActionRuleBase { +public: + virtual ~RefactoringActionRuleBase() {} + + /// Initiates and performs a specific refactoring action. + /// + /// The specific rule will invoke an appropriate \c handle method on a + /// consumer to propagate the result of the refactoring action. + virtual void invoke(RefactoringResultConsumer &Consumer, + RefactoringRuleContext &Context) = 0; + + /// Returns the structure that describes the refactoring. + // static const RefactoringDescriptor &describe() = 0; +}; + +/// A refactoring action rule is a wrapper class around a specific refactoring +/// action rule (SourceChangeRefactoringRule, etc) that, in addition to invoking +/// the action, describes the requirements that determine when the action can be +/// initiated. +class RefactoringActionRule : public RefactoringActionRuleBase { +public: + /// Returns true when the rule has a source selection requirement that has + /// to be fulfilled before refactoring can be performed. + virtual bool hasSelectionRequirement() = 0; + + /// Traverses each refactoring option used by the rule and invokes the + /// \c visit callback in the consumer for each option. + /// + /// Options are visited in the order of use, e.g. if a rule has two + /// requirements that use options, the options from the first requirement + /// are visited before the options in the second requirement. + virtual void visitRefactoringOptions(RefactoringOptionVisitor &Visitor) = 0; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h new file mode 100644 index 0000000000..438d80433b --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h @@ -0,0 +1,133 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- RefactoringActionRuleRequirements.h - Clang refactoring library --===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULEREQUIREMENTS_H +#define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULEREQUIREMENTS_H + +#include "clang/Basic/LLVM.h" +#include "clang/Tooling/Refactoring/ASTSelection.h" +#include "clang/Tooling/Refactoring/RefactoringDiagnostic.h" +#include "clang/Tooling/Refactoring/RefactoringOption.h" +#include "clang/Tooling/Refactoring/RefactoringRuleContext.h" +#include "llvm/Support/Error.h" +#include <type_traits> + +namespace clang { +namespace tooling { + +/// A refactoring action rule requirement determines when a refactoring action +/// rule can be invoked. The rule can be invoked only when all of the +/// requirements are satisfied. +/// +/// Subclasses must implement the +/// 'Expected<T> evaluate(RefactoringRuleContext &) const' member function. +/// \c T is used to determine the return type that is passed to the +/// refactoring rule's constructor. +/// For example, the \c SourceRangeSelectionRequirement subclass defines +/// 'Expected<SourceRange> evaluate(RefactoringRuleContext &Context) const' +/// function. When this function returns a non-error value, the resulting +/// source range is passed to the specific refactoring action rule +/// constructor (provided all other requirements are satisfied). +class RefactoringActionRuleRequirement { + // Expected<T> evaluate(RefactoringRuleContext &Context) const; +}; + +/// A base class for any requirement that expects some part of the source to be +/// selected in an editor (or the refactoring tool with the -selection option). +class SourceSelectionRequirement : public RefactoringActionRuleRequirement {}; + +/// A selection requirement that is satisfied when any portion of the source +/// text is selected. +class SourceRangeSelectionRequirement : public SourceSelectionRequirement { +public: + Expected<SourceRange> evaluate(RefactoringRuleContext &Context) const { + if (Context.getSelectionRange().isValid()) + return Context.getSelectionRange(); + return Context.createDiagnosticError(diag::err_refactor_no_selection); + } +}; + +/// An AST selection requirement is satisfied when any portion of the AST +/// overlaps with the selection range. +/// +/// The requirement will be evaluated only once during the initiation and +/// search of matching refactoring action rules. +class ASTSelectionRequirement : public SourceRangeSelectionRequirement { +public: + Expected<SelectedASTNode> evaluate(RefactoringRuleContext &Context) const; +}; + +/// A selection requirement that is satisfied when the selection range overlaps +/// with a number of neighbouring statements in the AST. The statemenst must be +/// contained in declaration like a function. The selection range must be a +/// non-empty source selection (i.e. cursors won't be accepted). +/// +/// The requirement will be evaluated only once during the initiation and search +/// of matching refactoring action rules. +/// +/// \see CodeRangeASTSelection +class CodeRangeASTSelectionRequirement : public ASTSelectionRequirement { +public: + Expected<CodeRangeASTSelection> + evaluate(RefactoringRuleContext &Context) const; +}; + +/// A base class for any requirement that requires some refactoring options. +class RefactoringOptionsRequirement : public RefactoringActionRuleRequirement { +public: + virtual ~RefactoringOptionsRequirement() {} + + /// Returns the set of refactoring options that are used when evaluating this + /// requirement. + virtual ArrayRef<std::shared_ptr<RefactoringOption>> + getRefactoringOptions() const = 0; +}; + +/// A requirement that evaluates to the value of the given \c OptionType when +/// the \c OptionType is a required option. When the \c OptionType is an +/// optional option, the requirement will evaluate to \c None if the option is +/// not specified or to an appropriate value otherwise. +template <typename OptionType> +class OptionRequirement : public RefactoringOptionsRequirement { +public: + OptionRequirement() : Opt(createRefactoringOption<OptionType>()) {} + + ArrayRef<std::shared_ptr<RefactoringOption>> + getRefactoringOptions() const final { + return Opt; + } + + Expected<typename OptionType::ValueType> + evaluate(RefactoringRuleContext &) const { + return static_cast<OptionType *>(Opt.get())->getValue(); + } + +private: + /// The partially-owned option. + /// + /// The ownership of the option is shared among the different requirements + /// because the same option can be used by multiple rules in one refactoring + /// action. + std::shared_ptr<RefactoringOption> Opt; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULEREQUIREMENTS_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringActionRules.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringActionRules.h new file mode 100644 index 0000000000..5ef11aee8e --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringActionRules.h @@ -0,0 +1,104 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- RefactoringActionRules.h - Clang refactoring library -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULES_H +#define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULES_H + +#include "clang/Tooling/Refactoring/RefactoringActionRule.h" +#include "clang/Tooling/Refactoring/RefactoringActionRulesInternal.h" + +namespace clang { +namespace tooling { + +/// Creates a new refactoring action rule that constructs and invokes the +/// \c RuleType rule when all of the requirements are satisfied. +/// +/// This function takes in a list of values whose type derives from +/// \c RefactoringActionRuleRequirement. These values describe the initiation +/// requirements that have to be satisfied by the refactoring engine before +/// the provided action rule can be constructed and invoked. The engine +/// verifies that the requirements are satisfied by evaluating them (using the +/// 'evaluate' member function) and checking that the results don't contain +/// any errors. Once all requirements are satisfied, the provided refactoring +/// rule is constructed by passing in the values returned by the requirements' +/// evaluate functions as arguments to the constructor. The rule is then invoked +/// immediately after construction. +/// +/// The separation of requirements, their evaluation and the invocation of the +/// refactoring action rule allows the refactoring clients to: +/// - Disable refactoring action rules whose requirements are not supported. +/// - Gather the set of options and define a command-line / visual interface +/// that allows users to input these options without ever invoking the +/// action. +template <typename RuleType, typename... RequirementTypes> +std::unique_ptr<RefactoringActionRule> +createRefactoringActionRule(const RequirementTypes &... Requirements); + +/// A set of refactoring action rules that should have unique initiation +/// requirements. +using RefactoringActionRules = + std::vector<std::unique_ptr<RefactoringActionRule>>; + +/// A type of refactoring action rule that produces source replacements in the +/// form of atomic changes. +/// +/// This action rule is typically used for local refactorings that replace +/// source in a single AST unit. +class SourceChangeRefactoringRule : public RefactoringActionRuleBase { +public: + void invoke(RefactoringResultConsumer &Consumer, + RefactoringRuleContext &Context) final { + Expected<AtomicChanges> Changes = createSourceReplacements(Context); + if (!Changes) + Consumer.handleError(Changes.takeError()); + else + Consumer.handle(std::move(*Changes)); + } + +private: + virtual Expected<AtomicChanges> + createSourceReplacements(RefactoringRuleContext &Context) = 0; +}; + +/// A type of refactoring action rule that finds a set of symbol occurrences +/// that reference a particular symbol. +/// +/// This action rule is typically used for an interactive rename that allows +/// users to specify the new name and the set of selected occurrences during +/// the refactoring. +class FindSymbolOccurrencesRefactoringRule : public RefactoringActionRuleBase { +public: + void invoke(RefactoringResultConsumer &Consumer, + RefactoringRuleContext &Context) final { + Expected<SymbolOccurrences> Occurrences = findSymbolOccurrences(Context); + if (!Occurrences) + Consumer.handleError(Occurrences.takeError()); + else + Consumer.handle(std::move(*Occurrences)); + } + +private: + virtual Expected<SymbolOccurrences> + findSymbolOccurrences(RefactoringRuleContext &Context) = 0; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULES_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h new file mode 100644 index 0000000000..2b6213da4b --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h @@ -0,0 +1,168 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- RefactoringActionRulesInternal.h - Clang refactoring library -----===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULESINTERNAL_H +#define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULESINTERNAL_H + +#include "clang/Basic/LLVM.h" +#include "clang/Tooling/Refactoring/RefactoringActionRule.h" +#include "clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h" +#include "clang/Tooling/Refactoring/RefactoringResultConsumer.h" +#include "clang/Tooling/Refactoring/RefactoringRuleContext.h" +#include "llvm/Support/Error.h" +#include <type_traits> + +namespace clang { +namespace tooling { +namespace internal { + +inline llvm::Error findError() { return llvm::Error::success(); } + +inline void ignoreError() {} + +template <typename FirstT, typename... RestT> +void ignoreError(Expected<FirstT> &First, Expected<RestT> &... Rest) { + if (!First) + llvm::consumeError(First.takeError()); + ignoreError(Rest...); +} + +/// Scans the tuple and returns a valid \c Error if any of the values are +/// invalid. +template <typename FirstT, typename... RestT> +llvm::Error findError(Expected<FirstT> &First, Expected<RestT> &... Rest) { + if (!First) { + ignoreError(Rest...); + return First.takeError(); + } + return findError(Rest...); +} + +template <typename RuleType, typename... RequirementTypes, size_t... Is> +void invokeRuleAfterValidatingRequirements( + RefactoringResultConsumer &Consumer, RefactoringRuleContext &Context, + const std::tuple<RequirementTypes...> &Requirements, + std::index_sequence<Is...>) { + // Check if the requirements we're interested in can be evaluated. + auto Values = + std::make_tuple(std::get<Is>(Requirements).evaluate(Context)...); + auto Err = findError(std::get<Is>(Values)...); + if (Err) + return Consumer.handleError(std::move(Err)); + // Construct the target action rule by extracting the evaluated + // requirements from Expected<> wrappers and then run it. + auto Rule = + RuleType::initiate(Context, std::move((*std::get<Is>(Values)))...); + if (!Rule) + return Consumer.handleError(Rule.takeError()); + Rule->invoke(Consumer, Context); +} + +inline void visitRefactoringOptionsImpl(RefactoringOptionVisitor &) {} + +/// Scans the list of requirements in a rule and visits all the refactoring +/// options that are used by all the requirements. +template <typename FirstT, typename... RestT> +void visitRefactoringOptionsImpl(RefactoringOptionVisitor &Visitor, + const FirstT &First, const RestT &... Rest) { + struct OptionGatherer { + RefactoringOptionVisitor &Visitor; + + void operator()(const RefactoringOptionsRequirement &Requirement) { + for (const auto &Option : Requirement.getRefactoringOptions()) + Option->passToVisitor(Visitor); + } + void operator()(const RefactoringActionRuleRequirement &) {} + }; + (OptionGatherer{Visitor})(First); + return visitRefactoringOptionsImpl(Visitor, Rest...); +} + +template <typename... RequirementTypes, size_t... Is> +void visitRefactoringOptions( + RefactoringOptionVisitor &Visitor, + const std::tuple<RequirementTypes...> &Requirements, + std::index_sequence<Is...>) { + visitRefactoringOptionsImpl(Visitor, std::get<Is>(Requirements)...); +} + +/// A type trait that returns true when the given type list has at least one +/// type whose base is the given base type. +template <typename Base, typename First, typename... Rest> +struct HasBaseOf : std::conditional_t<HasBaseOf<Base, First>::value || + HasBaseOf<Base, Rest...>::value, + std::true_type, std::false_type> {}; + +template <typename Base, typename T> +struct HasBaseOf<Base, T> : std::is_base_of<Base, T> {}; + +/// A type trait that returns true when the given type list contains types that +/// derive from Base. +template <typename Base, typename First, typename... Rest> +struct AreBaseOf : std::conditional_t<AreBaseOf<Base, First>::value && + AreBaseOf<Base, Rest...>::value, + std::true_type, std::false_type> {}; + +template <typename Base, typename T> +struct AreBaseOf<Base, T> : std::is_base_of<Base, T> {}; + +} // end namespace internal + +template <typename RuleType, typename... RequirementTypes> +std::unique_ptr<RefactoringActionRule> +createRefactoringActionRule(const RequirementTypes &... Requirements) { + static_assert(std::is_base_of<RefactoringActionRuleBase, RuleType>::value, + "Expected a refactoring action rule type"); + static_assert(internal::AreBaseOf<RefactoringActionRuleRequirement, + RequirementTypes...>::value, + "Expected a list of refactoring action rules"); + + class Rule final : public RefactoringActionRule { + public: + Rule(std::tuple<RequirementTypes...> Requirements) + : Requirements(Requirements) {} + + void invoke(RefactoringResultConsumer &Consumer, + RefactoringRuleContext &Context) override { + internal::invokeRuleAfterValidatingRequirements<RuleType>( + Consumer, Context, Requirements, + std::index_sequence_for<RequirementTypes...>()); + } + + bool hasSelectionRequirement() override { + return internal::HasBaseOf<SourceSelectionRequirement, + RequirementTypes...>::value; + } + + void visitRefactoringOptions(RefactoringOptionVisitor &Visitor) override { + internal::visitRefactoringOptions( + Visitor, Requirements, + std::index_sequence_for<RequirementTypes...>()); + } + private: + std::tuple<RequirementTypes...> Requirements; + }; + + return std::make_unique<Rule>(std::make_tuple(Requirements...)); +} + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULESINTERNAL_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h new file mode 100644 index 0000000000..881e71a743 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h @@ -0,0 +1,25 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- RefactoringDiagnostic.h - ------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGDIAGNOSTIC_H +#define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGDIAGNOSTIC_H + +#include "clang/Basic/DiagnosticRefactoring.h" + +#endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGDIAGNOSTIC_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringOption.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringOption.h new file mode 100644 index 0000000000..33b704d385 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringOption.h @@ -0,0 +1,74 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- RefactoringOption.h - Clang refactoring library ------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGOPTION_H +#define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGOPTION_H + +#include "clang/Basic/LLVM.h" +#include <memory> +#include <type_traits> + +namespace clang { +namespace tooling { + +class RefactoringOptionVisitor; + +/// A refactoring option is an interface that describes a value that +/// has an impact on the outcome of a refactoring. +/// +/// Refactoring options can be specified using command-line arguments when +/// the clang-refactor tool is used. +class RefactoringOption { +public: + virtual ~RefactoringOption() {} + + /// Returns the name of the refactoring option. + /// + /// Each refactoring option must have a unique name. + virtual StringRef getName() const = 0; + + virtual StringRef getDescription() const = 0; + + /// True when this option must be specified before invoking the refactoring + /// action. + virtual bool isRequired() const = 0; + + /// Invokes the \c visit method in the option consumer that's appropriate + /// for the option's value type. + /// + /// For example, if the option stores a string value, this method will + /// invoke the \c visit method with a reference to an std::string value. + virtual void passToVisitor(RefactoringOptionVisitor &Visitor) = 0; +}; + +/// Constructs a refactoring option of the given type. +/// +/// The ownership of options is shared among requirements that use it because +/// one option can be used by multiple rules in a refactoring action. +template <typename OptionType> +std::shared_ptr<OptionType> createRefactoringOption() { + static_assert(std::is_base_of<RefactoringOption, OptionType>::value, + "invalid option type"); + return std::make_shared<OptionType>(); +} + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGOPTION_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringOptionVisitor.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringOptionVisitor.h new file mode 100644 index 0000000000..5a8d7dee14 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringOptionVisitor.h @@ -0,0 +1,74 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- RefactoringOptionVisitor.h - Clang refactoring library -----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGOPTIONVISITOR_H +#define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGOPTIONVISITOR_H + +#include "clang/Basic/LLVM.h" +#include <optional> +#include <type_traits> + +namespace clang { +namespace tooling { + +class RefactoringOption; + +/// An interface that declares functions that handle different refactoring +/// option types. +/// +/// A valid refactoring option type must have a corresponding \c visit +/// declaration in this interface. +class RefactoringOptionVisitor { +public: + virtual ~RefactoringOptionVisitor() {} + + virtual void visit(const RefactoringOption &Opt, + std::optional<std::string> &Value) = 0; +}; + +namespace traits { +namespace internal { + +template <typename T> struct HasHandle { +private: + template <typename ClassT> + static auto check(ClassT *) -> typename std::is_same< + decltype(std::declval<RefactoringOptionVisitor>().visit( + std::declval<RefactoringOption>(), + *std::declval<std::optional<T> *>())), + void>::type; + + template <typename> static std::false_type check(...); + +public: + using Type = decltype(check<RefactoringOptionVisitor>(nullptr)); +}; + +} // end namespace internal + +/// A type trait that returns true iff the given type is a type that can be +/// stored in a refactoring option. +template <typename T> +struct IsValidOptionType : internal::HasHandle<T>::Type {}; + +} // end namespace traits +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGOPTIONVISITOR_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringOptions.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringOptions.h new file mode 100644 index 0000000000..fb1f71e9e6 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringOptions.h @@ -0,0 +1,69 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- RefactoringOptions.h - Clang refactoring library -----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGOPTIONS_H +#define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGOPTIONS_H + +#include "clang/Basic/LLVM.h" +#include "clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h" +#include "clang/Tooling/Refactoring/RefactoringOption.h" +#include "clang/Tooling/Refactoring/RefactoringOptionVisitor.h" +#include "llvm/Support/Error.h" +#include <optional> +#include <type_traits> + +namespace clang { +namespace tooling { + +/// A refactoring option that stores a value of type \c T. +template <typename T, + typename = std::enable_if_t<traits::IsValidOptionType<T>::value>> +class OptionalRefactoringOption : public RefactoringOption { +public: + void passToVisitor(RefactoringOptionVisitor &Visitor) final { + Visitor.visit(*this, Value); + } + + bool isRequired() const override { return false; } + + using ValueType = std::optional<T>; + + const ValueType &getValue() const { return Value; } + +protected: + std::optional<T> Value; +}; + +/// A required refactoring option that stores a value of type \c T. +template <typename T, + typename = std::enable_if_t<traits::IsValidOptionType<T>::value>> +class RequiredRefactoringOption : public OptionalRefactoringOption<T> { +public: + using ValueType = T; + + const ValueType &getValue() const { + return *OptionalRefactoringOption<T>::Value; + } + bool isRequired() const final { return true; } +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGOPTIONS_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h new file mode 100644 index 0000000000..fe6d95ccef --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h @@ -0,0 +1,62 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- RefactoringResultConsumer.h - Clang refactoring library ----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGRESULTCONSUMER_H +#define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGRESULTCONSUMER_H + +#include "clang/Basic/LLVM.h" +#include "clang/Tooling/Refactoring/AtomicChange.h" +#include "clang/Tooling/Refactoring/Rename/SymbolOccurrences.h" +#include "llvm/Support/Error.h" + +namespace clang { +namespace tooling { + +/// An abstract interface that consumes the various refactoring results that can +/// be produced by refactoring actions. +/// +/// A valid refactoring result must be handled by a \c handle method. +class RefactoringResultConsumer { +public: + virtual ~RefactoringResultConsumer() {} + + /// Handles an initiation or an invication error. An initiation error typically + /// has a \c DiagnosticError payload that describes why initiation failed. + virtual void handleError(llvm::Error Err) = 0; + + /// Handles the source replacements that are produced by a refactoring action. + virtual void handle(AtomicChanges SourceReplacements) { + defaultResultHandler(); + } + + /// Handles the symbol occurrences that are found by an interactive + /// refactoring action. + virtual void handle(SymbolOccurrences Occurrences) { defaultResultHandler(); } + +private: + void defaultResultHandler() { + handleError(llvm::make_error<llvm::StringError>( + "unsupported refactoring result", llvm::inconvertibleErrorCode())); + } +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGRESULTCONSUMER_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringRuleContext.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringRuleContext.h new file mode 100644 index 0000000000..73a9652b1e --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/RefactoringRuleContext.h @@ -0,0 +1,100 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- RefactoringRuleContext.h - Clang refactoring library -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGRULECONTEXT_H +#define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGRULECONTEXT_H + +#include "clang/Basic/DiagnosticError.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Tooling/Refactoring/ASTSelection.h" + +namespace clang { + +class ASTContext; + +namespace tooling { + +/// The refactoring rule context stores all of the inputs that might be needed +/// by a refactoring action rule. It can create the specialized +/// \c ASTRefactoringOperation or \c PreprocessorRefactoringOperation values +/// that can be used by the refactoring action rules. +/// +/// The following inputs are stored by the operation: +/// +/// - SourceManager: a reference to a valid source manager. +/// +/// - SelectionRange: an optional source selection ranges that can be used +/// to represent a selection in an editor. +class RefactoringRuleContext { +public: + RefactoringRuleContext(const SourceManager &SM) : SM(SM) {} + + const SourceManager &getSources() const { return SM; } + + /// Returns the current source selection range as set by the + /// refactoring engine. Can be invalid. + SourceRange getSelectionRange() const { return SelectionRange; } + + void setSelectionRange(SourceRange R) { SelectionRange = R; } + + bool hasASTContext() const { return AST; } + + ASTContext &getASTContext() const { + assert(AST && "no AST!"); + return *AST; + } + + void setASTContext(ASTContext &Context) { AST = &Context; } + + /// Creates an llvm::Error value that contains a diagnostic. + /// + /// The errors should not outlive the context. + llvm::Error createDiagnosticError(SourceLocation Loc, unsigned DiagID) { + return DiagnosticError::create(Loc, PartialDiagnostic(DiagID, DiagStorage)); + } + + llvm::Error createDiagnosticError(unsigned DiagID) { + return createDiagnosticError(SourceLocation(), DiagID); + } + + void setASTSelection(std::unique_ptr<SelectedASTNode> Node) { + ASTNodeSelection = std::move(Node); + } + +private: + /// The source manager for the translation unit / file on which a refactoring + /// action might operate on. + const SourceManager &SM; + /// An optional source selection range that's commonly used to represent + /// a selection in an editor. + SourceRange SelectionRange; + /// An optional AST for the translation unit on which a refactoring action + /// might operate on. + ASTContext *AST = nullptr; + /// The allocator for diagnostics. + PartialDiagnostic::DiagStorageAllocator DiagStorage; + + // FIXME: Remove when memoized. + std::unique_ptr<SelectedASTNode> ASTNodeSelection; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGRULECONTEXT_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/Rename/RenamingAction.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/Rename/RenamingAction.h new file mode 100644 index 0000000000..cab565a95f --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/Rename/RenamingAction.h @@ -0,0 +1,133 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- RenamingAction.h - Clang refactoring library ---------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Provides an action to rename every symbol at a point. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_RENAME_RENAMINGACTION_H +#define LLVM_CLANG_TOOLING_REFACTORING_RENAME_RENAMINGACTION_H + +#include "clang/Tooling/Refactoring.h" +#include "clang/Tooling/Refactoring/AtomicChange.h" +#include "clang/Tooling/Refactoring/RefactoringActionRules.h" +#include "clang/Tooling/Refactoring/RefactoringOptions.h" +#include "clang/Tooling/Refactoring/Rename/SymbolOccurrences.h" +#include "llvm/Support/Error.h" + +namespace clang { +class ASTConsumer; + +namespace tooling { + +class RenamingAction { +public: + RenamingAction(const std::vector<std::string> &NewNames, + const std::vector<std::string> &PrevNames, + const std::vector<std::vector<std::string>> &USRList, + std::map<std::string, tooling::Replacements> &FileToReplaces, + bool PrintLocations = false) + : NewNames(NewNames), PrevNames(PrevNames), USRList(USRList), + FileToReplaces(FileToReplaces), PrintLocations(PrintLocations) {} + + std::unique_ptr<ASTConsumer> newASTConsumer(); + +private: + const std::vector<std::string> &NewNames, &PrevNames; + const std::vector<std::vector<std::string>> &USRList; + std::map<std::string, tooling::Replacements> &FileToReplaces; + bool PrintLocations; +}; + +class RenameOccurrences final : public SourceChangeRefactoringRule { +public: + static Expected<RenameOccurrences> initiate(RefactoringRuleContext &Context, + SourceRange SelectionRange, + std::string NewName); + + static const RefactoringDescriptor &describe(); + + const NamedDecl *getRenameDecl() const; + +private: + RenameOccurrences(const NamedDecl *ND, std::string NewName) + : ND(ND), NewName(std::move(NewName)) {} + + Expected<AtomicChanges> + createSourceReplacements(RefactoringRuleContext &Context) override; + + const NamedDecl *ND; + std::string NewName; +}; + +class QualifiedRenameRule final : public SourceChangeRefactoringRule { +public: + static Expected<QualifiedRenameRule> initiate(RefactoringRuleContext &Context, + std::string OldQualifiedName, + std::string NewQualifiedName); + + static const RefactoringDescriptor &describe(); + +private: + QualifiedRenameRule(const NamedDecl *ND, + std::string NewQualifiedName) + : ND(ND), NewQualifiedName(std::move(NewQualifiedName)) {} + + Expected<AtomicChanges> + createSourceReplacements(RefactoringRuleContext &Context) override; + + // A NamedDecl which identifies the symbol being renamed. + const NamedDecl *ND; + // The new qualified name to change the symbol to. + std::string NewQualifiedName; +}; + +/// Returns source replacements that correspond to the rename of the given +/// symbol occurrences. +llvm::Expected<std::vector<AtomicChange>> +createRenameReplacements(const SymbolOccurrences &Occurrences, + const SourceManager &SM, const SymbolName &NewName); + +/// Rename all symbols identified by the given USRs. +class QualifiedRenamingAction { +public: + QualifiedRenamingAction( + const std::vector<std::string> &NewNames, + const std::vector<std::vector<std::string>> &USRList, + std::map<std::string, tooling::Replacements> &FileToReplaces) + : NewNames(NewNames), USRList(USRList), FileToReplaces(FileToReplaces) {} + + std::unique_ptr<ASTConsumer> newASTConsumer(); + +private: + /// New symbol names. + const std::vector<std::string> &NewNames; + + /// A list of USRs. Each element represents USRs of a symbol being renamed. + const std::vector<std::vector<std::string>> &USRList; + + /// A file path to replacements map. + std::map<std::string, tooling::Replacements> &FileToReplaces; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_RENAME_RENAMINGACTION_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/Rename/SymbolName.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/Rename/SymbolName.h new file mode 100644 index 0000000000..26915b6e4e --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/Rename/SymbolName.h @@ -0,0 +1,59 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- SymbolName.h - Clang refactoring library -------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_RENAME_SYMBOLNAME_H +#define LLVM_CLANG_TOOLING_REFACTORING_RENAME_SYMBOLNAME_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +namespace clang { +namespace tooling { + +/// A name of a symbol. +/// +/// Symbol's name can be composed of multiple strings. For example, Objective-C +/// methods can contain multiple argument labels: +/// +/// \code +/// - (void) myMethodNamePiece: (int)x anotherNamePieces:(int)y; +/// // ^~ string 0 ~~~~~ ^~ string 1 ~~~~~ +/// \endcode +class SymbolName { +public: + explicit SymbolName(StringRef Name) { + // While empty symbol names are valid (Objective-C selectors can have empty + // name pieces), occurrences Objective-C selectors are created using an + // array of strings instead of just one string. + assert(!Name.empty() && "Invalid symbol name!"); + this->Name.push_back(Name.str()); + } + + ArrayRef<std::string> getNamePieces() const { return Name; } + +private: + llvm::SmallVector<std::string, 1> Name; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_RENAME_SYMBOLNAME_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/Rename/SymbolOccurrences.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/Rename/SymbolOccurrences.h new file mode 100644 index 0000000000..e57212248c --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/Rename/SymbolOccurrences.h @@ -0,0 +1,102 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- SymbolOccurrences.h - Clang refactoring library ------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_RENAME_SYMBOLOCCURRENCES_H +#define LLVM_CLANG_TOOLING_REFACTORING_RENAME_SYMBOLOCCURRENCES_H + +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include <vector> + +namespace clang { +namespace tooling { + +class SymbolName; + +/// An occurrence of a symbol in the source. +/// +/// Occurrences can have difference kinds, that describe whether this occurrence +/// is an exact semantic match, or whether this is a weaker textual match that's +/// not guaranteed to represent the exact declaration. +/// +/// A single occurrence of a symbol can span more than one source range. For +/// example, Objective-C selectors can contain multiple argument labels: +/// +/// \code +/// [object selectorPiece1: ... selectorPiece2: ...]; +/// // ^~~ range 0 ~~ ^~~ range 1 ~~ +/// \endcode +/// +/// We have to replace the text in both range 0 and range 1 when renaming the +/// Objective-C method 'selectorPiece1:selectorPiece2'. +class SymbolOccurrence { +public: + enum OccurrenceKind { + /// This occurrence is an exact match and can be renamed automatically. + /// + /// Note: + /// Symbol occurrences in macro arguments that expand to different + /// declarations get marked as exact matches, and thus the renaming engine + /// will rename them e.g.: + /// + /// \code + /// #define MACRO(x) x + ns::x + /// int foo(int var) { + /// return MACRO(var); // var is renamed automatically here when + /// // either var or ns::var is renamed. + /// }; + /// \endcode + /// + /// The user will have to fix their code manually after performing such a + /// rename. + /// FIXME: The rename verifier should notify user about this issue. + MatchingSymbol + }; + + SymbolOccurrence(const SymbolName &Name, OccurrenceKind Kind, + ArrayRef<SourceLocation> Locations); + + SymbolOccurrence(SymbolOccurrence &&) = default; + SymbolOccurrence &operator=(SymbolOccurrence &&) = default; + + OccurrenceKind getKind() const { return Kind; } + + ArrayRef<SourceRange> getNameRanges() const { + if (MultipleRanges) + return llvm::ArrayRef(MultipleRanges.get(), NumRanges); + return SingleRange; + } + +private: + OccurrenceKind Kind; + std::unique_ptr<SourceRange[]> MultipleRanges; + union { + SourceRange SingleRange; + unsigned NumRanges; + }; +}; + +using SymbolOccurrences = std::vector<SymbolOccurrence>; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_RENAME_SYMBOLOCCURRENCES_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/Rename/USRFinder.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/Rename/USRFinder.h new file mode 100644 index 0000000000..197c7bdab9 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/Rename/USRFinder.h @@ -0,0 +1,60 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- USRFinder.h - Clang refactoring library --------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Methods for determining the USR of a symbol at a location in source +/// code. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_RENAME_USRFINDER_H +#define LLVM_CLANG_TOOLING_REFACTORING_RENAME_USRFINDER_H + +#include "clang/AST/AST.h" +#include "clang/AST/ASTContext.h" +#include <string> +#include <vector> + +namespace clang { + +class ASTContext; +class Decl; +class SourceLocation; +class NamedDecl; + +namespace tooling { + +// Given an AST context and a point, returns a NamedDecl identifying the symbol +// at the point. Returns null if nothing is found at the point. +const NamedDecl *getNamedDeclAt(const ASTContext &Context, + const SourceLocation Point); + +// Given an AST context and a fully qualified name, returns a NamedDecl +// identifying the symbol with a matching name. Returns null if nothing is +// found for the name. +const NamedDecl *getNamedDeclFor(const ASTContext &Context, + const std::string &Name); + +// Converts a Decl into a USR. +std::string getUSRForDecl(const Decl *Decl); + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_RENAME_USRFINDER_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h new file mode 100644 index 0000000000..dbdaed6ebc --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h @@ -0,0 +1,77 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- USRFindingAction.h - Clang refactoring library -------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Provides an action to find all relevant USRs at a point. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_RENAME_USRFINDINGACTION_H +#define LLVM_CLANG_TOOLING_REFACTORING_RENAME_USRFINDINGACTION_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" + +#include <string> +#include <vector> + +namespace clang { +class ASTConsumer; +class ASTContext; +class NamedDecl; + +namespace tooling { + +/// Returns the canonical declaration that best represents a symbol that can be +/// renamed. +/// +/// The following canonicalization rules are currently used: +/// +/// - A constructor is canonicalized to its class. +/// - A destructor is canonicalized to its class. +const NamedDecl *getCanonicalSymbolDeclaration(const NamedDecl *FoundDecl); + +/// Returns the set of USRs that correspond to the given declaration. +std::vector<std::string> getUSRsForDeclaration(const NamedDecl *ND, + ASTContext &Context); + +struct USRFindingAction { + USRFindingAction(ArrayRef<unsigned> SymbolOffsets, + ArrayRef<std::string> QualifiedNames, bool Force) + : SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames), + ErrorOccurred(false), Force(Force) {} + std::unique_ptr<ASTConsumer> newASTConsumer(); + + ArrayRef<std::string> getUSRSpellings() { return SpellingNames; } + ArrayRef<std::vector<std::string>> getUSRList() { return USRList; } + bool errorOccurred() { return ErrorOccurred; } + +private: + std::vector<unsigned> SymbolOffsets; + std::vector<std::string> QualifiedNames; + std::vector<std::string> SpellingNames; + std::vector<std::vector<std::string>> USRList; + bool ErrorOccurred; + bool Force; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_RENAME_USRFINDINGACTION_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h b/contrib/libs/clang16/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h new file mode 100644 index 0000000000..9872165117 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h @@ -0,0 +1,63 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- USRLocFinder.h - Clang refactoring library -----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Provides functionality for finding all instances of a USR in a given +/// AST. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_RENAME_USRLOCFINDER_H +#define LLVM_CLANG_TOOLING_REFACTORING_RENAME_USRLOCFINDER_H + +#include "clang/AST/AST.h" +#include "clang/Tooling/Core/Replacement.h" +#include "clang/Tooling/Refactoring/AtomicChange.h" +#include "clang/Tooling/Refactoring/Rename/SymbolOccurrences.h" +#include "llvm/ADT/StringRef.h" +#include <string> +#include <vector> + +namespace clang { +namespace tooling { + +/// Create atomic changes for renaming all symbol references which are +/// identified by the USRs set to a given new name. +/// +/// \param USRs The set containing USRs of a particular old symbol. +/// \param NewName The new name to replace old symbol name. +/// \param TranslationUnitDecl The translation unit declaration. +/// +/// \return Atomic changes for renaming. +std::vector<tooling::AtomicChange> +createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs, + llvm::StringRef NewName, Decl *TranslationUnitDecl); + +/// Finds the symbol occurrences for the symbol that's identified by the given +/// USR set. +/// +/// \return SymbolOccurrences that can be converted to AtomicChanges when +/// renaming. +SymbolOccurrences getOccurrencesOfUSRs(ArrayRef<std::string> USRs, + StringRef PrevName, Decl *Decl); + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_RENAME_USRLOCFINDER_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/RefactoringCallbacks.h b/contrib/libs/clang16/include/clang/Tooling/RefactoringCallbacks.h new file mode 100644 index 0000000000..ae281bf7ea --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/RefactoringCallbacks.h @@ -0,0 +1,150 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- RefactoringCallbacks.h - Structural query framework ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Provides callbacks to make common kinds of refactorings easy. +// +// The general idea is to construct a matcher expression that describes a +// subtree match on the AST and then replace the corresponding source code +// either by some specific text or some other AST node. +// +// Example: +// int main(int argc, char **argv) { +// ClangTool Tool(argc, argv); +// MatchFinder Finder; +// ReplaceStmtWithText Callback("integer", "42"); +// Finder.AddMatcher(id("integer", expression(integerLiteral())), Callback); +// return Tool.run(newFrontendActionFactory(&Finder)); +// } +// +// This will replace all integer literals with "42". +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORINGCALLBACKS_H +#define LLVM_CLANG_TOOLING_REFACTORINGCALLBACKS_H + +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Tooling/Refactoring.h" + +namespace clang { +namespace tooling { + +/// Base class for RefactoringCallbacks. +/// +/// Collects \c tooling::Replacements while running. +class RefactoringCallback : public ast_matchers::MatchFinder::MatchCallback { +public: + RefactoringCallback(); + Replacements &getReplacements(); + +protected: + Replacements Replace; +}; + +/// Adaptor between \c ast_matchers::MatchFinder and \c +/// tooling::RefactoringTool. +/// +/// Runs AST matchers and stores the \c tooling::Replacements in a map. +class ASTMatchRefactorer { +public: + explicit ASTMatchRefactorer( + std::map<std::string, Replacements> &FileToReplaces); + + template <typename T> + void addMatcher(const T &Matcher, RefactoringCallback *Callback) { + MatchFinder.addMatcher(Matcher, Callback); + Callbacks.push_back(Callback); + } + + void addDynamicMatcher(const ast_matchers::internal::DynTypedMatcher &Matcher, + RefactoringCallback *Callback); + + std::unique_ptr<ASTConsumer> newASTConsumer(); + +private: + friend class RefactoringASTConsumer; + std::vector<RefactoringCallback *> Callbacks; + ast_matchers::MatchFinder MatchFinder; + std::map<std::string, Replacements> &FileToReplaces; +}; + +/// Replace the text of the statement bound to \c FromId with the text in +/// \c ToText. +class ReplaceStmtWithText : public RefactoringCallback { +public: + ReplaceStmtWithText(StringRef FromId, StringRef ToText); + void run(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + std::string FromId; + std::string ToText; +}; + +/// Replace the text of an AST node bound to \c FromId with the result of +/// evaluating the template in \c ToTemplate. +/// +/// Expressions of the form ${NodeName} in \c ToTemplate will be +/// replaced by the text of the node bound to ${NodeName}. The string +/// "$$" will be replaced by "$". +class ReplaceNodeWithTemplate : public RefactoringCallback { +public: + static llvm::Expected<std::unique_ptr<ReplaceNodeWithTemplate>> + create(StringRef FromId, StringRef ToTemplate); + void run(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + struct TemplateElement { + enum { Literal, Identifier } Type; + std::string Value; + }; + ReplaceNodeWithTemplate(llvm::StringRef FromId, + std::vector<TemplateElement> Template); + std::string FromId; + std::vector<TemplateElement> Template; +}; + +/// Replace the text of the statement bound to \c FromId with the text of +/// the statement bound to \c ToId. +class ReplaceStmtWithStmt : public RefactoringCallback { +public: + ReplaceStmtWithStmt(StringRef FromId, StringRef ToId); + void run(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + std::string FromId; + std::string ToId; +}; + +/// Replace an if-statement bound to \c Id with the outdented text of its +/// body, choosing the consequent or the alternative based on whether +/// \c PickTrueBranch is true. +class ReplaceIfStmtWithItsBody : public RefactoringCallback { +public: + ReplaceIfStmtWithItsBody(StringRef Id, bool PickTrueBranch); + void run(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + std::string Id; + const bool PickTrueBranch; +}; + +} // end namespace tooling +} // end namespace clang + +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/ReplacementsYaml.h b/contrib/libs/clang16/include/clang/Tooling/ReplacementsYaml.h new file mode 100644 index 0000000000..f384710193 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/ReplacementsYaml.h @@ -0,0 +1,83 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===-- ReplacementsYaml.h -- Serialiazation for Replacements ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file defines the structure of a YAML document for serializing +/// replacements. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REPLACEMENTSYAML_H +#define LLVM_CLANG_TOOLING_REPLACEMENTSYAML_H + +#include "clang/Tooling/Refactoring.h" +#include "llvm/Support/YAMLTraits.h" +#include <string> + +LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::Replacement) + +namespace llvm { +namespace yaml { + +/// Specialized MappingTraits to describe how a Replacement is +/// (de)serialized. +template <> struct MappingTraits<clang::tooling::Replacement> { + /// Helper to (de)serialize a Replacement since we don't have direct + /// access to its data members. + struct NormalizedReplacement { + NormalizedReplacement(const IO &) : Offset(0), Length(0) {} + + NormalizedReplacement(const IO &, const clang::tooling::Replacement &R) + : FilePath(R.getFilePath()), Offset(R.getOffset()), + Length(R.getLength()), ReplacementText(R.getReplacementText()) {} + + clang::tooling::Replacement denormalize(const IO &) { + return clang::tooling::Replacement(FilePath, Offset, Length, + ReplacementText); + } + + std::string FilePath; + unsigned int Offset; + unsigned int Length; + std::string ReplacementText; + }; + + static void mapping(IO &Io, clang::tooling::Replacement &R) { + MappingNormalization<NormalizedReplacement, clang::tooling::Replacement> + Keys(Io, R); + Io.mapRequired("FilePath", Keys->FilePath); + Io.mapRequired("Offset", Keys->Offset); + Io.mapRequired("Length", Keys->Length); + Io.mapRequired("ReplacementText", Keys->ReplacementText); + } +}; + +/// Specialized MappingTraits to describe how a +/// TranslationUnitReplacements is (de)serialized. +template <> struct MappingTraits<clang::tooling::TranslationUnitReplacements> { + static void mapping(IO &Io, + clang::tooling::TranslationUnitReplacements &Doc) { + Io.mapRequired("MainSourceFile", Doc.MainSourceFile); + Io.mapRequired("Replacements", Doc.Replacements); + } +}; +} // end namespace yaml +} // end namespace llvm + +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/StandaloneExecution.h b/contrib/libs/clang16/include/clang/Tooling/StandaloneExecution.h new file mode 100644 index 0000000000..4452dc9ae9 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/StandaloneExecution.h @@ -0,0 +1,110 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- StandaloneExecution.h - Standalone execution. -*- C++ ----------*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines standalone execution of clang tools. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_STANDALONEEXECUTION_H +#define LLVM_CLANG_TOOLING_STANDALONEEXECUTION_H + +#include "clang/Tooling/ArgumentsAdjusters.h" +#include "clang/Tooling/Execution.h" +#include <optional> + +namespace clang { +namespace tooling { + +/// A standalone executor that runs FrontendActions on a given set of +/// TUs in sequence. +/// +/// By default, this executor uses the following arguments adjusters (as defined +/// in `clang/Tooling/ArgumentsAdjusters.h`): +/// - `getClangStripOutputAdjuster()` +/// - `getClangSyntaxOnlyAdjuster()` +/// - `getClangStripDependencyFileAdjuster()` +class StandaloneToolExecutor : public ToolExecutor { +public: + static const char *ExecutorName; + + /// Init with \p CompilationDatabase and the paths of all files to be + /// proccessed. + StandaloneToolExecutor( + const CompilationDatabase &Compilations, + llvm::ArrayRef<std::string> SourcePaths, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS = + llvm::vfs::getRealFileSystem(), + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<PCHContainerOperations>()); + + /// Init with \p CommonOptionsParser. This is expected to be used by + /// `createExecutorFromCommandLineArgs` based on commandline options. + /// + /// The executor takes ownership of \p Options. + StandaloneToolExecutor( + CommonOptionsParser Options, + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<PCHContainerOperations>()); + + StringRef getExecutorName() const override { return ExecutorName; } + + using ToolExecutor::execute; + + llvm::Error + execute(llvm::ArrayRef< + std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>> + Actions) override; + + /// Set a \c DiagnosticConsumer to use during parsing. + void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) { + Tool.setDiagnosticConsumer(DiagConsumer); + } + + ExecutionContext *getExecutionContext() override { return &Context; }; + + ToolResults *getToolResults() override { return &Results; } + + llvm::ArrayRef<std::string> getSourcePaths() const { + return Tool.getSourcePaths(); + } + + void mapVirtualFile(StringRef FilePath, StringRef Content) override { + Tool.mapVirtualFile(FilePath, Content); + } + + /// Returns the file manager used in the tool. + /// + /// The file manager is shared between all translation units. + FileManager &getFiles() { return Tool.getFiles(); } + +private: + // Used to store the parser when the executor is initialized with parser. + std::optional<CommonOptionsParser> OptionsParser; + // FIXME: The standalone executor is currently just a wrapper of `ClangTool`. + // Merge `ClangTool` implementation into the this. + ClangTool Tool; + ExecutionContext Context; + InMemoryToolResults Results; + ArgumentsAdjuster ArgsAdjuster; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_STANDALONEEXECUTION_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/ToolExecutorPluginRegistry.h b/contrib/libs/clang16/include/clang/Tooling/ToolExecutorPluginRegistry.h new file mode 100644 index 0000000000..08452e4b32 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/ToolExecutorPluginRegistry.h @@ -0,0 +1,34 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- ToolExecutorPluginRegistry.h -----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H +#define LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H + +#include "clang/Tooling/Execution.h" +#include "llvm/Support/Registry.h" + +namespace clang { +namespace tooling { + +using ToolExecutorPluginRegistry = llvm::Registry<ToolExecutorPlugin>; + +} // namespace tooling +} // namespace clang + +#endif // LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Tooling.h b/contrib/libs/clang16/include/clang/Tooling/Tooling.h new file mode 100644 index 0000000000..0afb5368b4 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Tooling.h @@ -0,0 +1,529 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- Tooling.h - Framework for standalone Clang tools ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements functions to run clang tools standalone instead +// of running them as a plugin. +// +// A ClangTool is initialized with a CompilationDatabase and a set of files +// to run over. The tool will then run a user-specified FrontendAction over +// all TUs in which the given files are compiled. +// +// It is also possible to run a FrontendAction over a snippet of code by +// calling runToolOnCode, which is useful for unit testing. +// +// Applications that need more fine grained control over how to run +// multiple FrontendActions over code can use ToolInvocation. +// +// Example tools: +// - running clang -fsyntax-only over source code from an editor to get +// fast syntax checks +// - running match/replace tools over C++ code +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_TOOLING_H +#define LLVM_CLANG_TOOLING_TOOLING_H + +#include "clang/AST/ASTConsumer.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/LLVM.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Frontend/PCHContainerOperations.h" +#include "clang/Tooling/ArgumentsAdjusters.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Option/Option.h" +#include "llvm/Support/VirtualFileSystem.h" +#include <memory> +#include <string> +#include <utility> +#include <vector> + +namespace clang { + +class CompilerInstance; +class CompilerInvocation; +class DiagnosticConsumer; +class DiagnosticsEngine; + +namespace driver { + +class Compilation; + +} // namespace driver + +namespace tooling { + +class CompilationDatabase; + +/// Retrieves the flags of the `-cc1` job in `Compilation` that has only source +/// files as its inputs. +/// Returns nullptr if there are no such jobs or multiple of them. Note that +/// offloading jobs are ignored. +const llvm::opt::ArgStringList * +getCC1Arguments(DiagnosticsEngine *Diagnostics, + driver::Compilation *Compilation); + +/// Interface to process a clang::CompilerInvocation. +/// +/// If your tool is based on FrontendAction, you should be deriving from +/// FrontendActionFactory instead. +class ToolAction { +public: + virtual ~ToolAction(); + + /// Perform an action for an invocation. + virtual bool + runInvocation(std::shared_ptr<CompilerInvocation> Invocation, + FileManager *Files, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + DiagnosticConsumer *DiagConsumer) = 0; +}; + +/// Interface to generate clang::FrontendActions. +/// +/// Having a factory interface allows, for example, a new FrontendAction to be +/// created for each translation unit processed by ClangTool. This class is +/// also a ToolAction which uses the FrontendActions created by create() to +/// process each translation unit. +class FrontendActionFactory : public ToolAction { +public: + ~FrontendActionFactory() override; + + /// Invokes the compiler with a FrontendAction created by create(). + bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation, + FileManager *Files, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + DiagnosticConsumer *DiagConsumer) override; + + /// Returns a new clang::FrontendAction. + virtual std::unique_ptr<FrontendAction> create() = 0; +}; + +/// Returns a new FrontendActionFactory for a given type. +/// +/// T must derive from clang::FrontendAction. +/// +/// Example: +/// std::unique_ptr<FrontendActionFactory> Factory = +/// newFrontendActionFactory<clang::SyntaxOnlyAction>(); +template <typename T> +std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(); + +/// Callbacks called before and after each source file processed by a +/// FrontendAction created by the FrontedActionFactory returned by \c +/// newFrontendActionFactory. +class SourceFileCallbacks { +public: + virtual ~SourceFileCallbacks() = default; + + /// Called before a source file is processed by a FrontEndAction. + /// \see clang::FrontendAction::BeginSourceFileAction + virtual bool handleBeginSource(CompilerInstance &CI) { + return true; + } + + /// Called after a source file is processed by a FrontendAction. + /// \see clang::FrontendAction::EndSourceFileAction + virtual void handleEndSource() {} +}; + +/// Returns a new FrontendActionFactory for any type that provides an +/// implementation of newASTConsumer(). +/// +/// FactoryT must implement: ASTConsumer *newASTConsumer(). +/// +/// Example: +/// struct ProvidesASTConsumers { +/// std::unique_ptr<clang::ASTConsumer> newASTConsumer(); +/// } Factory; +/// std::unique_ptr<FrontendActionFactory> FactoryAdapter( +/// newFrontendActionFactory(&Factory)); +template <typename FactoryT> +inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory( + FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks = nullptr); + +/// Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag. +/// +/// \param ToolAction The action to run over the code. +/// \param Code C++ code. +/// \param FileName The file name which 'Code' will be mapped as. +/// \param PCHContainerOps The PCHContainerOperations for loading and creating +/// clang modules. +/// +/// \return - True if 'ToolAction' was successfully executed. +bool runToolOnCode(std::unique_ptr<FrontendAction> ToolAction, const Twine &Code, + const Twine &FileName = "input.cc", + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<PCHContainerOperations>()); + +/// The first part of the pair is the filename, the second part the +/// file-content. +using FileContentMappings = std::vector<std::pair<std::string, std::string>>; + +/// Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag and +/// with additional other flags. +/// +/// \param ToolAction The action to run over the code. +/// \param Code C++ code. +/// \param Args Additional flags to pass on. +/// \param FileName The file name which 'Code' will be mapped as. +/// \param ToolName The name of the binary running the tool. Standard library +/// header paths will be resolved relative to this. +/// \param PCHContainerOps The PCHContainerOperations for loading and creating +/// clang modules. +/// +/// \return - True if 'ToolAction' was successfully executed. +bool runToolOnCodeWithArgs( + std::unique_ptr<FrontendAction> ToolAction, const Twine &Code, + const std::vector<std::string> &Args, const Twine &FileName = "input.cc", + const Twine &ToolName = "clang-tool", + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<PCHContainerOperations>(), + const FileContentMappings &VirtualMappedFiles = FileContentMappings()); + +// Similar to the overload except this takes a VFS. +bool runToolOnCodeWithArgs( + std::unique_ptr<FrontendAction> ToolAction, const Twine &Code, + llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, + const std::vector<std::string> &Args, const Twine &FileName = "input.cc", + const Twine &ToolName = "clang-tool", + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<PCHContainerOperations>()); + +/// Builds an AST for 'Code'. +/// +/// \param Code C++ code. +/// \param FileName The file name which 'Code' will be mapped as. +/// \param PCHContainerOps The PCHContainerOperations for loading and creating +/// clang modules. +/// +/// \return The resulting AST or null if an error occurred. +std::unique_ptr<ASTUnit> +buildASTFromCode(StringRef Code, StringRef FileName = "input.cc", + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<PCHContainerOperations>()); + +/// Builds an AST for 'Code' with additional flags. +/// +/// \param Code C++ code. +/// \param Args Additional flags to pass on. +/// \param FileName The file name which 'Code' will be mapped as. +/// \param ToolName The name of the binary running the tool. Standard library +/// header paths will be resolved relative to this. +/// \param PCHContainerOps The PCHContainerOperations for loading and creating +/// clang modules. +/// +/// \param Adjuster A function to filter the command line arguments as specified. +/// +/// \return The resulting AST or null if an error occurred. +std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs( + StringRef Code, const std::vector<std::string> &Args, + StringRef FileName = "input.cc", StringRef ToolName = "clang-tool", + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<PCHContainerOperations>(), + ArgumentsAdjuster Adjuster = getClangStripDependencyFileAdjuster(), + const FileContentMappings &VirtualMappedFiles = FileContentMappings(), + DiagnosticConsumer *DiagConsumer = nullptr); + +/// Utility to run a FrontendAction in a single clang invocation. +class ToolInvocation { +public: + /// Create a tool invocation. + /// + /// \param CommandLine The command line arguments to clang. Note that clang + /// uses its binary name (CommandLine[0]) to locate its builtin headers. + /// Callers have to ensure that they are installed in a compatible location + /// (see clang driver implementation) or mapped in via mapVirtualFile. + /// \param FAction The action to be executed. + /// \param Files The FileManager used for the execution. Class does not take + /// ownership. + /// \param PCHContainerOps The PCHContainerOperations for loading and creating + /// clang modules. + ToolInvocation(std::vector<std::string> CommandLine, + std::unique_ptr<FrontendAction> FAction, FileManager *Files, + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<PCHContainerOperations>()); + + /// Create a tool invocation. + /// + /// \param CommandLine The command line arguments to clang. + /// \param Action The action to be executed. + /// \param Files The FileManager used for the execution. + /// \param PCHContainerOps The PCHContainerOperations for loading and creating + /// clang modules. + ToolInvocation(std::vector<std::string> CommandLine, ToolAction *Action, + FileManager *Files, + std::shared_ptr<PCHContainerOperations> PCHContainerOps); + + ~ToolInvocation(); + + /// Set a \c DiagnosticConsumer to use during driver command-line parsing and + /// the action invocation itself. + void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) { + this->DiagConsumer = DiagConsumer; + } + + /// Set a \c DiagnosticOptions to use during driver command-line parsing. + void setDiagnosticOptions(DiagnosticOptions *DiagOpts) { + this->DiagOpts = DiagOpts; + } + + /// Run the clang invocation. + /// + /// \returns True if there were no errors during execution. + bool run(); + + private: + bool runInvocation(const char *BinaryName, + driver::Compilation *Compilation, + std::shared_ptr<CompilerInvocation> Invocation, + std::shared_ptr<PCHContainerOperations> PCHContainerOps); + + std::vector<std::string> CommandLine; + ToolAction *Action; + bool OwnsAction; + FileManager *Files; + std::shared_ptr<PCHContainerOperations> PCHContainerOps; + DiagnosticConsumer *DiagConsumer = nullptr; + DiagnosticOptions *DiagOpts = nullptr; +}; + +/// Utility to run a FrontendAction over a set of files. +/// +/// This class is written to be usable for command line utilities. +/// By default the class uses ClangSyntaxOnlyAdjuster to modify +/// command line arguments before the arguments are used to run +/// a frontend action. One could install an additional command line +/// arguments adjuster by calling the appendArgumentsAdjuster() method. +class ClangTool { +public: + /// Constructs a clang tool to run over a list of files. + /// + /// \param Compilations The CompilationDatabase which contains the compile + /// command lines for the given source paths. + /// \param SourcePaths The source files to run over. If a source files is + /// not found in Compilations, it is skipped. + /// \param PCHContainerOps The PCHContainerOperations for loading and creating + /// clang modules. + /// \param BaseFS VFS used for all underlying file accesses when running the + /// tool. + /// \param Files The file manager to use for underlying file operations when + /// running the tool. + ClangTool(const CompilationDatabase &Compilations, + ArrayRef<std::string> SourcePaths, + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<PCHContainerOperations>(), + IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS = + llvm::vfs::getRealFileSystem(), + IntrusiveRefCntPtr<FileManager> Files = nullptr); + + ~ClangTool(); + + /// Set a \c DiagnosticConsumer to use during parsing. + void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) { + this->DiagConsumer = DiagConsumer; + } + + /// Map a virtual file to be used while running the tool. + /// + /// \param FilePath The path at which the content will be mapped. + /// \param Content A null terminated buffer of the file's content. + void mapVirtualFile(StringRef FilePath, StringRef Content); + + /// Append a command line arguments adjuster to the adjuster chain. + /// + /// \param Adjuster An argument adjuster, which will be run on the output of + /// previous argument adjusters. + void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster); + + /// Clear the command line arguments adjuster chain. + void clearArgumentsAdjusters(); + + /// Runs an action over all files specified in the command line. + /// + /// \param Action Tool action. + /// + /// \returns 0 on success; 1 if any error occurred; 2 if there is no error but + /// some files are skipped due to missing compile commands. + int run(ToolAction *Action); + + /// Create an AST for each file specified in the command line and + /// append them to ASTs. + int buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs); + + /// Sets whether working directory should be restored after calling run(). By + /// default, working directory is restored. However, it could be useful to + /// turn this off when running on multiple threads to avoid the raciness. + void setRestoreWorkingDir(bool RestoreCWD); + + /// Sets whether an error message should be printed out if an action fails. By + /// default, if an action fails, a message is printed out to stderr. + void setPrintErrorMessage(bool PrintErrorMessage); + + /// Returns the file manager used in the tool. + /// + /// The file manager is shared between all translation units. + FileManager &getFiles() { return *Files; } + + llvm::ArrayRef<std::string> getSourcePaths() const { return SourcePaths; } + +private: + const CompilationDatabase &Compilations; + std::vector<std::string> SourcePaths; + std::shared_ptr<PCHContainerOperations> PCHContainerOps; + + llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem; + llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem; + llvm::IntrusiveRefCntPtr<FileManager> Files; + + // Contains a list of pairs (<file name>, <file content>). + std::vector<std::pair<StringRef, StringRef>> MappedFileContents; + + llvm::StringSet<> SeenWorkingDirectories; + + ArgumentsAdjuster ArgsAdjuster; + + DiagnosticConsumer *DiagConsumer = nullptr; + + bool RestoreCWD = true; + bool PrintErrorMessage = true; +}; + +template <typename T> +std::unique_ptr<FrontendActionFactory> newFrontendActionFactory() { + class SimpleFrontendActionFactory : public FrontendActionFactory { + public: + std::unique_ptr<FrontendAction> create() override { + return std::make_unique<T>(); + } + }; + + return std::unique_ptr<FrontendActionFactory>( + new SimpleFrontendActionFactory); +} + +template <typename FactoryT> +inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory( + FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks) { + class FrontendActionFactoryAdapter : public FrontendActionFactory { + public: + explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory, + SourceFileCallbacks *Callbacks) + : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {} + + std::unique_ptr<FrontendAction> create() override { + return std::make_unique<ConsumerFactoryAdaptor>(ConsumerFactory, + Callbacks); + } + + private: + class ConsumerFactoryAdaptor : public ASTFrontendAction { + public: + ConsumerFactoryAdaptor(FactoryT *ConsumerFactory, + SourceFileCallbacks *Callbacks) + : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {} + + std::unique_ptr<ASTConsumer> + CreateASTConsumer(CompilerInstance &, StringRef) override { + return ConsumerFactory->newASTConsumer(); + } + + protected: + bool BeginSourceFileAction(CompilerInstance &CI) override { + if (!ASTFrontendAction::BeginSourceFileAction(CI)) + return false; + if (Callbacks) + return Callbacks->handleBeginSource(CI); + return true; + } + + void EndSourceFileAction() override { + if (Callbacks) + Callbacks->handleEndSource(); + ASTFrontendAction::EndSourceFileAction(); + } + + private: + FactoryT *ConsumerFactory; + SourceFileCallbacks *Callbacks; + }; + FactoryT *ConsumerFactory; + SourceFileCallbacks *Callbacks; + }; + + return std::unique_ptr<FrontendActionFactory>( + new FrontendActionFactoryAdapter(ConsumerFactory, Callbacks)); +} + +/// Returns the absolute path of \c File, by prepending it with +/// the current directory if \c File is not absolute. +/// +/// Otherwise returns \c File. +/// If 'File' starts with "./", the returned path will not contain the "./". +/// Otherwise, the returned path will contain the literal path-concatenation of +/// the current directory and \c File. +/// +/// The difference to llvm::sys::fs::make_absolute is the canonicalization this +/// does by removing "./" and computing native paths. +/// +/// \param File Either an absolute or relative path. +std::string getAbsolutePath(StringRef File); + +/// An overload of getAbsolutePath that works over the provided \p FS. +llvm::Expected<std::string> getAbsolutePath(llvm::vfs::FileSystem &FS, + StringRef File); + +/// Changes CommandLine to contain implicit flags that would have been +/// defined had the compiler driver been invoked through the path InvokedAs. +/// +/// For example, when called with \c InvokedAs set to `i686-linux-android-g++`, +/// the arguments '-target', 'i686-linux-android`, `--driver-mode=g++` will +/// be inserted after the first argument in \c CommandLine. +/// +/// This function will not add new `-target` or `--driver-mode` flags if they +/// are already present in `CommandLine` (even if they have different settings +/// than would have been inserted). +/// +/// \pre `llvm::InitializeAllTargets()` has been called. +/// +/// \param CommandLine the command line used to invoke the compiler driver or +/// Clang tool, including the path to the executable as \c CommandLine[0]. +/// \param InvokedAs the path to the driver used to infer implicit flags. +/// +/// \note This will not set \c CommandLine[0] to \c InvokedAs. The tooling +/// infrastructure expects that CommandLine[0] is a tool path relative to which +/// the builtin headers can be found. +void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine, + StringRef InvokedAs); + +/// Creates a \c CompilerInvocation. +CompilerInvocation *newInvocation(DiagnosticsEngine *Diagnostics, + ArrayRef<const char *> CC1Args, + const char *const BinaryName); + +} // namespace tooling + +} // namespace clang + +#endif // LLVM_CLANG_TOOLING_TOOLING_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Transformer/MatchConsumer.h b/contrib/libs/clang16/include/clang/Tooling/Transformer/MatchConsumer.h new file mode 100644 index 0000000000..ead75d578e --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Transformer/MatchConsumer.h @@ -0,0 +1,114 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- MatchConsumer.h - MatchConsumer abstraction ------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file This file defines the *MatchConsumer* abstraction: a computation over +/// match results, specifically the `ast_matchers::MatchFinder::MatchResult` +/// class. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_MATCHCONSUMER_H +#define LLVM_CLANG_TOOLING_TRANSFORMER_MATCHCONSUMER_H + +#include "clang/AST/ASTTypeTraits.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/Error.h" + +namespace clang { +namespace transformer { +/// A failable computation over nodes bound by AST matchers. +/// +/// The computation should report any errors though its return value (rather +/// than terminating the program) to enable usage in interactive scenarios like +/// clang-query. +/// +/// This is a central abstraction of the Transformer framework. +template <typename T> +using MatchConsumer = + std::function<Expected<T>(const ast_matchers::MatchFinder::MatchResult &)>; + +/// Creates an error that signals that a `MatchConsumer` expected a certain node +/// to be bound by AST matchers, but it was not actually bound. +inline llvm::Error notBoundError(llvm::StringRef Id) { + return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument, + "Id not bound: " + Id); +} + +/// Chooses between the two consumers, based on whether \p ID is bound in the +/// match. +template <typename T> +MatchConsumer<T> ifBound(std::string ID, MatchConsumer<T> TrueC, + MatchConsumer<T> FalseC) { + return [=](const ast_matchers::MatchFinder::MatchResult &Result) { + auto &Map = Result.Nodes.getMap(); + return (Map.find(ID) != Map.end() ? TrueC : FalseC)(Result); + }; +} + +/// A failable computation over nodes bound by AST matchers, with (limited) +/// reflection via the `toString` method. +/// +/// The computation should report any errors though its return value (rather +/// than terminating the program) to enable usage in interactive scenarios like +/// clang-query. +/// +/// This is a central abstraction of the Transformer framework. It is a +/// generalization of `MatchConsumer` and intended to replace it. +template <typename T> class MatchComputation { +public: + virtual ~MatchComputation() = default; + + /// Evaluates the computation and (potentially) updates the accumulator \c + /// Result. \c Result is undefined in the case of an error. `Result` is an + /// out parameter to optimize case where the computation involves composing + /// the result of sub-computation evaluations. + virtual llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &Match, + T *Result) const = 0; + + /// Convenience version of `eval`, for the case where the computation is being + /// evaluated on its own. + llvm::Expected<T> eval(const ast_matchers::MatchFinder::MatchResult &R) const; + + /// Constructs a string representation of the computation, for informational + /// purposes. The representation must be deterministic, but is not required to + /// be unique. + virtual std::string toString() const = 0; + +protected: + MatchComputation() = default; + + // Since this is an abstract class, copying/assigning only make sense for + // derived classes implementing `clone()`. + MatchComputation(const MatchComputation &) = default; + MatchComputation &operator=(const MatchComputation &) = default; +}; + +template <typename T> +llvm::Expected<T> MatchComputation<T>::eval( + const ast_matchers::MatchFinder::MatchResult &R) const { + T Output; + if (auto Err = eval(R, &Output)) + return std::move(Err); + return Output; +} +} // namespace transformer +} // namespace clang +#endif // LLVM_CLANG_TOOLING_TRANSFORMER_MATCHCONSUMER_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Transformer/Parsing.h b/contrib/libs/clang16/include/clang/Tooling/Transformer/Parsing.h new file mode 100644 index 0000000000..d89ed53a8b --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Transformer/Parsing.h @@ -0,0 +1,51 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- Parsing.h - Parsing library for Transformer ------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Defines parsing functions for Transformer types. +/// FIXME: Currently, only supports `RangeSelectors` but parsers for other +/// Transformer types are under development. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_PARSING_H +#define LLVM_CLANG_TOOLING_TRANSFORMER_PARSING_H + +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Tooling/Transformer/RangeSelector.h" +#include "llvm/Support/Error.h" +#include <functional> + +namespace clang { +namespace transformer { + +/// Parses a string representation of a \c RangeSelector. The grammar of these +/// strings is closely based on the (sub)grammar of \c RangeSelectors as they'd +/// appear in C++ code. However, this language constrains the set of permissible +/// strings (for node ids) -- it does not support escapes in the +/// string. Additionally, the \c charRange combinator is not supported, because +/// there is no representation of values of type \c CharSourceRange in this +/// (little) language. +llvm::Expected<RangeSelector> parseRangeSelector(llvm::StringRef Input); + +} // namespace transformer +} // namespace clang + +#endif // LLVM_CLANG_TOOLING_TRANSFORMER_PARSING_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Transformer/RangeSelector.h b/contrib/libs/clang16/include/clang/Tooling/Transformer/RangeSelector.h new file mode 100644 index 0000000000..954f144b3c --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Transformer/RangeSelector.h @@ -0,0 +1,119 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- RangeSelector.h - Source-selection library ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Defines a combinator library supporting the definition of _selectors_, +/// which select source ranges based on (bound) AST nodes. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_RANGESELECTOR_H +#define LLVM_CLANG_TOOLING_TRANSFORMER_RANGESELECTOR_H + +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Tooling/Transformer/MatchConsumer.h" +#include "llvm/Support/Error.h" +#include <functional> +#include <string> + +namespace clang { +namespace transformer { +using RangeSelector = MatchConsumer<CharSourceRange>; + +inline RangeSelector charRange(CharSourceRange R) { + return [R](const ast_matchers::MatchFinder::MatchResult &) + -> Expected<CharSourceRange> { return R; }; +} + +/// Selects from the start of \p Begin and to the end of \p End. +RangeSelector enclose(RangeSelector Begin, RangeSelector End); + +/// Convenience version of \c range where end-points are bound nodes. +RangeSelector encloseNodes(std::string BeginID, std::string EndID); + +/// DEPRECATED. Use `enclose`. +inline RangeSelector range(RangeSelector Begin, RangeSelector End) { + return enclose(std::move(Begin), std::move(End)); +} + +/// DEPRECATED. Use `encloseNodes`. +inline RangeSelector range(std::string BeginID, std::string EndID) { + return encloseNodes(std::move(BeginID), std::move(EndID)); +} + +/// Selects the (empty) range [B,B) when \p Selector selects the range [B,E). +RangeSelector before(RangeSelector Selector); + +/// Selects the point immediately following \p Selector. That is, the +/// (empty) range [E,E), when \p Selector selects either +/// * the CharRange [B,E) or +/// * the TokenRange [B,E'] where the token at E' spans the range [E',E). +RangeSelector after(RangeSelector Selector); + +/// Selects the range between `R1` and `R2. +inline RangeSelector between(RangeSelector R1, RangeSelector R2) { + return enclose(after(std::move(R1)), before(std::move(R2))); +} + +/// Selects a node, including trailing semicolon, if any (for declarations and +/// non-expression statements). \p ID is the node's binding in the match result. +RangeSelector node(std::string ID); + +/// Selects a node, including trailing semicolon (always). Useful for selecting +/// expression statements. \p ID is the node's binding in the match result. +RangeSelector statement(std::string ID); + +/// Given a \c MemberExpr, selects the member token. \p ID is the node's +/// binding in the match result. +RangeSelector member(std::string ID); + +/// Given a node with a "name", (like \c NamedDecl, \c DeclRefExpr, \c +/// CxxCtorInitializer, and \c TypeLoc) selects the name's token. Only selects +/// the final identifier of a qualified name, but not any qualifiers or template +/// arguments. For example, for `::foo::bar::baz` and `::foo::bar::baz<int>`, +/// it selects only `baz`. +/// +/// \param ID is the node's binding in the match result. +RangeSelector name(std::string ID); + +// Given a \c CallExpr (bound to \p ID), selects the arguments' source text (all +// source between the call's parentheses). +RangeSelector callArgs(std::string ID); + +// Given a \c CompoundStmt (bound to \p ID), selects the source of the +// statements (all source between the braces). +RangeSelector statements(std::string ID); + +// Given a \c InitListExpr (bound to \p ID), selects the range of the elements +// (all source between the braces). +RangeSelector initListElements(std::string ID); + +/// Given an \IfStmt (bound to \p ID), selects the range of the else branch, +/// starting from the \c else keyword. +RangeSelector elseBranch(std::string ID); + +/// Selects the range from which `S` was expanded (possibly along with other +/// source), if `S` is an expansion, and `S` itself, otherwise. Corresponds to +/// `SourceManager::getExpansionRange`. +RangeSelector expansion(RangeSelector S); +} // namespace transformer +} // namespace clang + +#endif // LLVM_CLANG_TOOLING_TRANSFORMER_RANGESELECTOR_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Transformer/RewriteRule.h b/contrib/libs/clang16/include/clang/Tooling/Transformer/RewriteRule.h new file mode 100644 index 0000000000..4393847197 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Transformer/RewriteRule.h @@ -0,0 +1,551 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- RewriteRule.h - RewriteRule class ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Defines the RewriteRule class and related functions for creating, +/// modifying and interpreting RewriteRules. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_REWRITERULE_H +#define LLVM_CLANG_TOOLING_TRANSFORMER_REWRITERULE_H + +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/ASTMatchers/ASTMatchersInternal.h" +#include "clang/Tooling/Refactoring/AtomicChange.h" +#include "clang/Tooling/Transformer/MatchConsumer.h" +#include "clang/Tooling/Transformer/RangeSelector.h" +#include "llvm/ADT/Any.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Error.h" +#include <functional> +#include <string> +#include <utility> + +namespace clang { +namespace transformer { +// Specifies how to interpret an edit. +enum class EditKind { + // Edits a source range in the file. + Range, + // Inserts an include in the file. The `Replacement` field is the name of the + // newly included file. + AddInclude, +}; + +/// A concrete description of a source edit, represented by a character range in +/// the source to be replaced and a corresponding replacement string. +struct Edit { + EditKind Kind = EditKind::Range; + CharSourceRange Range; + std::string Replacement; + std::string Note; + llvm::Any Metadata; +}; + +/// Format of the path in an include directive -- angle brackets or quotes. +enum class IncludeFormat { + Quoted, + Angled, +}; + +/// Maps a match result to a list of concrete edits (with possible +/// failure). This type is a building block of rewrite rules, but users will +/// generally work in terms of `ASTEdit`s (below) rather than directly in terms +/// of `EditGenerator`. +using EditGenerator = MatchConsumer<llvm::SmallVector<Edit, 1>>; + +template <typename T> using Generator = std::shared_ptr<MatchComputation<T>>; + +using TextGenerator = Generator<std::string>; + +using AnyGenerator = MatchConsumer<llvm::Any>; + +// Description of a source-code edit, expressed in terms of an AST node. +// Includes: an ID for the (bound) node, a selector for source related to the +// node, a replacement and, optionally, an explanation for the edit. +// +// * Target: the source code impacted by the rule. This identifies an AST node, +// or part thereof (\c Part), whose source range indicates the extent of the +// replacement applied by the replacement term. By default, the extent is the +// node matched by the pattern term (\c NodePart::Node). Target's are typed +// (\c Kind), which guides the determination of the node extent. +// +// * Replacement: a function that produces a replacement string for the target, +// based on the match result. +// +// * Note: (optional) a note specifically for this edit, potentially referencing +// elements of the match. This will be displayed to the user, where possible; +// for example, in clang-tidy diagnostics. Use of notes should be rare -- +// explanations of the entire rewrite should be set in the rule +// (`RewriteRule::Explanation`) instead. Notes serve the rare cases wherein +// edit-specific diagnostics are required. +// +// `ASTEdit` should be built using the `change` convenience functions. For +// example, +// \code +// changeTo(name(fun), cat("Frodo")) +// \endcode +// Or, if we use Stencil for the TextGenerator: +// \code +// using stencil::cat; +// changeTo(statement(thenNode), cat("{", thenNode, "}")) +// changeTo(callArgs(call), cat(x, ",", y)) +// \endcode +// Or, if you are changing the node corresponding to the rule's matcher, you can +// use the single-argument override of \c change: +// \code +// changeTo(cat("different_expr")) +// \endcode +struct ASTEdit { + EditKind Kind = EditKind::Range; + RangeSelector TargetRange; + TextGenerator Replacement; + TextGenerator Note; + // Not all transformations will want or need to attach metadata and therefore + // should not be required to do so. + AnyGenerator Metadata = [](const ast_matchers::MatchFinder::MatchResult &) + -> llvm::Expected<llvm::Any> { + return llvm::Expected<llvm::Any>(llvm::Any()); + }; +}; + +/// Generates a single (specified) edit. +EditGenerator edit(ASTEdit E); + +/// Lifts a list of `ASTEdit`s into an `EditGenerator`. +/// +/// The `EditGenerator` will return an empty vector if any of the edits apply to +/// portions of the source that are ineligible for rewriting (certain +/// interactions with macros, for example) and it will fail if any invariants +/// are violated relating to bound nodes in the match. However, it does not +/// fail in the case of conflicting edits -- conflict handling is left to +/// clients. We recommend use of the \c AtomicChange or \c Replacements classes +/// for assistance in detecting such conflicts. +EditGenerator editList(llvm::SmallVector<ASTEdit, 1> Edits); + +/// Generates no edits. +inline EditGenerator noEdits() { return editList({}); } + +/// Generates a single, no-op edit anchored at the start location of the +/// specified range. A `noopEdit` may be preferred over `noEdits` to associate a +/// diagnostic `Explanation` with the rule. +EditGenerator noopEdit(RangeSelector Anchor); + +/// Generates a single, no-op edit with the associated note anchored at the +/// start location of the specified range. +ASTEdit note(RangeSelector Anchor, TextGenerator Note); + +/// Version of `ifBound` specialized to `ASTEdit`. +inline EditGenerator ifBound(std::string ID, ASTEdit TrueEdit, + ASTEdit FalseEdit) { + return ifBound(std::move(ID), edit(std::move(TrueEdit)), + edit(std::move(FalseEdit))); +} + +/// Version of `ifBound` that has no "False" branch. If the node is not bound, +/// then no edits are produced. +inline EditGenerator ifBound(std::string ID, ASTEdit TrueEdit) { + return ifBound(std::move(ID), edit(std::move(TrueEdit)), noEdits()); +} + +/// Flattens a list of generators into a single generator whose elements are the +/// concatenation of the results of the argument generators. +EditGenerator flattenVector(SmallVector<EditGenerator, 2> Generators); + +namespace detail { +/// Helper function to construct an \c EditGenerator. Overloaded for common +/// cases so that user doesn't need to specify which factory function to +/// use. This pattern gives benefits similar to implicit constructors, while +/// maintaing a higher degree of explicitness. +inline EditGenerator injectEdits(ASTEdit E) { return edit(std::move(E)); } +inline EditGenerator injectEdits(EditGenerator G) { return G; } +} // namespace detail + +template <typename... Ts> EditGenerator flatten(Ts &&...Edits) { + return flattenVector({detail::injectEdits(std::forward<Ts>(Edits))...}); +} + +// Every rewrite rule is triggered by a match against some AST node. +// Transformer guarantees that this ID is bound to the triggering node whenever +// a rewrite rule is applied. +extern const char RootID[]; + +/// Replaces a portion of the source text with \p Replacement. +ASTEdit changeTo(RangeSelector Target, TextGenerator Replacement); +/// DEPRECATED: use \c changeTo. +inline ASTEdit change(RangeSelector Target, TextGenerator Replacement) { + return changeTo(std::move(Target), std::move(Replacement)); +} + +/// Replaces the entirety of a RewriteRule's match with \p Replacement. For +/// example, to replace a function call, one could write: +/// \code +/// makeRule(callExpr(callee(functionDecl(hasName("foo")))), +/// changeTo(cat("bar()"))) +/// \endcode +inline ASTEdit changeTo(TextGenerator Replacement) { + return changeTo(node(RootID), std::move(Replacement)); +} +/// DEPRECATED: use \c changeTo. +inline ASTEdit change(TextGenerator Replacement) { + return changeTo(std::move(Replacement)); +} + +/// Inserts \p Replacement before \p S, leaving the source selected by \S +/// unchanged. +inline ASTEdit insertBefore(RangeSelector S, TextGenerator Replacement) { + return changeTo(before(std::move(S)), std::move(Replacement)); +} + +/// Inserts \p Replacement after \p S, leaving the source selected by \S +/// unchanged. +inline ASTEdit insertAfter(RangeSelector S, TextGenerator Replacement) { + return changeTo(after(std::move(S)), std::move(Replacement)); +} + +/// Removes the source selected by \p S. +ASTEdit remove(RangeSelector S); + +/// Adds an include directive for the given header to the file of `Target`. The +/// particular location specified by `Target` is ignored. +ASTEdit addInclude(RangeSelector Target, StringRef Header, + IncludeFormat Format = IncludeFormat::Quoted); + +/// Adds an include directive for the given header to the file associated with +/// `RootID`. If `RootID` matches inside a macro expansion, will add the +/// directive to the file in which the macro was expanded (as opposed to the +/// file in which the macro is defined). +inline ASTEdit addInclude(StringRef Header, + IncludeFormat Format = IncludeFormat::Quoted) { + return addInclude(expansion(node(RootID)), Header, Format); +} + +// FIXME: If `Metadata` returns an `llvm::Expected<T>` the `AnyGenerator` will +// construct an `llvm::Expected<llvm::Any>` where no error is present but the +// `llvm::Any` holds the error. This is unlikely but potentially surprising. +// Perhaps the `llvm::Expected` should be unwrapped, or perhaps this should be a +// compile-time error. No solution here is perfect. +// +// Note: This function template accepts any type callable with a MatchResult +// rather than a `std::function` because the return-type needs to be deduced. If +// it accepted a `std::function<R(MatchResult)>`, lambdas or other callable +// types would not be able to deduce `R`, and users would be forced to specify +// explicitly the type they intended to return by wrapping the lambda at the +// call-site. +template <typename Callable> +inline ASTEdit withMetadata(ASTEdit Edit, Callable Metadata) { + Edit.Metadata = + [Gen = std::move(Metadata)]( + const ast_matchers::MatchFinder::MatchResult &R) -> llvm::Any { + return Gen(R); + }; + + return Edit; +} + +/// Assuming that the inner range is enclosed by the outer range, creates +/// precision edits to remove the parts of the outer range that are not included +/// in the inner range. +inline EditGenerator shrinkTo(RangeSelector outer, RangeSelector inner) { + return editList({remove(enclose(before(outer), before(inner))), + remove(enclose(after(inner), after(outer)))}); +} + +/// Description of a source-code transformation. +// +// A *rewrite rule* describes a transformation of source code. A simple rule +// contains each of the following components: +// +// * Matcher: the pattern term, expressed as clang matchers (with Transformer +// extensions). +// +// * Edits: a set of Edits to the source code, described with ASTEdits. +// +// However, rules can also consist of (sub)rules, where the first that matches +// is applied and the rest are ignored. So, the above components together form +// a logical "case" and a rule is a sequence of cases. +// +// Rule cases have an additional, implicit, component: the parameters. These are +// portions of the pattern which are left unspecified, yet bound in the pattern +// so that we can reference them in the edits. +// +// The \c Transformer class can be used to apply the rewrite rule and obtain the +// corresponding replacements. +struct RewriteRuleBase { + struct Case { + ast_matchers::internal::DynTypedMatcher Matcher; + EditGenerator Edits; + }; + // We expect RewriteRules will most commonly include only one case. + SmallVector<Case, 1> Cases; +}; + +/// A source-code transformation with accompanying metadata. +/// +/// When a case of the rule matches, the \c Transformer invokes the +/// corresponding metadata generator and provides it alongside the edits. +template <typename MetadataT> struct RewriteRuleWith : RewriteRuleBase { + SmallVector<Generator<MetadataT>, 1> Metadata; +}; + +template <> struct RewriteRuleWith<void> : RewriteRuleBase {}; + +using RewriteRule = RewriteRuleWith<void>; + +namespace detail { + +RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M, + EditGenerator Edits); + +template <typename MetadataT> +RewriteRuleWith<MetadataT> makeRule(ast_matchers::internal::DynTypedMatcher M, + EditGenerator Edits, + Generator<MetadataT> Metadata) { + RewriteRuleWith<MetadataT> R; + R.Cases = {{std::move(M), std::move(Edits)}}; + R.Metadata = {std::move(Metadata)}; + return R; +} + +inline EditGenerator makeEditGenerator(EditGenerator Edits) { return Edits; } +EditGenerator makeEditGenerator(llvm::SmallVector<ASTEdit, 1> Edits); +EditGenerator makeEditGenerator(ASTEdit Edit); + +} // namespace detail + +/// Constructs a simple \c RewriteRule. \c Edits can be an \c EditGenerator, +/// multiple \c ASTEdits, or a single \c ASTEdit. +/// @{ +template <int &..., typename EditsT> +RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M, + EditsT &&Edits) { + return detail::makeRule( + std::move(M), detail::makeEditGenerator(std::forward<EditsT>(Edits))); +} + +RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M, + std::initializer_list<ASTEdit> Edits); +/// @} + +/// Overloads of \c makeRule that also generate metadata when matching. +/// @{ +template <typename MetadataT, int &..., typename EditsT> +RewriteRuleWith<MetadataT> makeRule(ast_matchers::internal::DynTypedMatcher M, + EditsT &&Edits, + Generator<MetadataT> Metadata) { + return detail::makeRule( + std::move(M), detail::makeEditGenerator(std::forward<EditsT>(Edits)), + std::move(Metadata)); +} + +template <typename MetadataT> +RewriteRuleWith<MetadataT> makeRule(ast_matchers::internal::DynTypedMatcher M, + std::initializer_list<ASTEdit> Edits, + Generator<MetadataT> Metadata) { + return detail::makeRule(std::move(M), + detail::makeEditGenerator(std::move(Edits)), + std::move(Metadata)); +} +/// @} + +/// For every case in Rule, adds an include directive for the given header. The +/// common use is assumed to be a rule with only one case. For example, to +/// replace a function call and add headers corresponding to the new code, one +/// could write: +/// \code +/// auto R = makeRule(callExpr(callee(functionDecl(hasName("foo")))), +/// changeTo(cat("bar()"))); +/// addInclude(R, "path/to/bar_header.h"); +/// addInclude(R, "vector", IncludeFormat::Angled); +/// \endcode +void addInclude(RewriteRuleBase &Rule, llvm::StringRef Header, + IncludeFormat Format = IncludeFormat::Quoted); + +/// Applies the first rule whose pattern matches; other rules are ignored. If +/// the matchers are independent then order doesn't matter. In that case, +/// `applyFirst` is simply joining the set of rules into one. +// +// `applyFirst` is like an `anyOf` matcher with an edit action attached to each +// of its cases. Anywhere you'd use `anyOf(m1.bind("id1"), m2.bind("id2"))` and +// then dispatch on those ids in your code for control flow, `applyFirst` lifts +// that behavior to the rule level. So, you can write `applyFirst({makeRule(m1, +// action1), makeRule(m2, action2), ...});` +// +// For example, consider a type `T` with a deterministic serialization function, +// `serialize()`. For performance reasons, we would like to make it +// non-deterministic. Therefore, we want to drop the expectation that +// `a.serialize() = b.serialize() iff a = b` (although we'll maintain +// `deserialize(a.serialize()) = a`). +// +// We have three cases to consider (for some equality function, `eq`): +// ``` +// eq(a.serialize(), b.serialize()) --> eq(a,b) +// eq(a, b.serialize()) --> eq(deserialize(a), b) +// eq(a.serialize(), b) --> eq(a, deserialize(b)) +// ``` +// +// `applyFirst` allows us to specify each independently: +// ``` +// auto eq_fun = functionDecl(...); +// auto method_call = cxxMemberCallExpr(...); +// +// auto two_calls = callExpr(callee(eq_fun), hasArgument(0, method_call), +// hasArgument(1, method_call)); +// auto left_call = +// callExpr(callee(eq_fun), callExpr(hasArgument(0, method_call))); +// auto right_call = +// callExpr(callee(eq_fun), callExpr(hasArgument(1, method_call))); +// +// RewriteRule R = applyFirst({makeRule(two_calls, two_calls_action), +// makeRule(left_call, left_call_action), +// makeRule(right_call, right_call_action)}); +// ``` +/// @{ +template <typename MetadataT> +RewriteRuleWith<MetadataT> +applyFirst(ArrayRef<RewriteRuleWith<MetadataT>> Rules) { + RewriteRuleWith<MetadataT> R; + for (auto &Rule : Rules) { + assert(Rule.Cases.size() == Rule.Metadata.size() && + "mis-match in case and metadata array size"); + R.Cases.append(Rule.Cases.begin(), Rule.Cases.end()); + R.Metadata.append(Rule.Metadata.begin(), Rule.Metadata.end()); + } + return R; +} + +template <> +RewriteRuleWith<void> applyFirst(ArrayRef<RewriteRuleWith<void>> Rules); + +template <typename MetadataT> +RewriteRuleWith<MetadataT> +applyFirst(const std::vector<RewriteRuleWith<MetadataT>> &Rules) { + return applyFirst(llvm::ArrayRef(Rules)); +} + +template <typename MetadataT> +RewriteRuleWith<MetadataT> +applyFirst(std::initializer_list<RewriteRuleWith<MetadataT>> Rules) { + return applyFirst(llvm::ArrayRef(Rules.begin(), Rules.end())); +} +/// @} + +/// Converts a \c RewriteRuleWith<T> to a \c RewriteRule by stripping off the +/// metadata generators. +template <int &..., typename MetadataT> +std::enable_if_t<!std::is_same<MetadataT, void>::value, RewriteRule> +stripMetadata(RewriteRuleWith<MetadataT> Rule) { + RewriteRule R; + R.Cases = std::move(Rule.Cases); + return R; +} + +/// Applies `Rule` to all descendants of the node bound to `NodeId`. `Rule` can +/// refer to nodes bound by the calling rule. `Rule` is not applied to the node +/// itself. +/// +/// For example, +/// ``` +/// auto InlineX = +/// makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3"))); +/// makeRule(functionDecl(hasName("f"), hasBody(stmt().bind("body"))).bind("f"), +/// flatten( +/// changeTo(name("f"), cat("newName")), +/// rewriteDescendants("body", InlineX))); +/// ``` +/// Here, we find the function `f`, change its name to `newName` and change all +/// appearances of `x` in its body to `3`. +EditGenerator rewriteDescendants(std::string NodeId, RewriteRule Rule); + +/// The following three functions are a low-level part of the RewriteRule +/// API. We expose them for use in implementing the fixtures that interpret +/// RewriteRule, like Transformer and TransfomerTidy, or for more advanced +/// users. +// +// FIXME: These functions are really public, if advanced, elements of the +// RewriteRule API. Recast them as such. Or, just declare these functions +// public and well-supported and move them out of `detail`. +namespace detail { +/// The following overload set is a version of `rewriteDescendants` that +/// operates directly on the AST, rather than generating a Transformer +/// combinator. It applies `Rule` to all descendants of `Node`, although not +/// `Node` itself. `Rule` can refer to nodes bound in `Result`. +/// +/// For example, assuming that "body" is bound to a function body in MatchResult +/// `Results`, this will produce edits to change all appearances of `x` in that +/// body to `3`. +/// ``` +/// auto InlineX = +/// makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3"))); +/// const auto *Node = Results.Nodes.getNodeAs<Stmt>("body"); +/// auto Edits = rewriteDescendants(*Node, InlineX, Results); +/// ``` +/// @{ +llvm::Expected<SmallVector<Edit, 1>> +rewriteDescendants(const Decl &Node, RewriteRule Rule, + const ast_matchers::MatchFinder::MatchResult &Result); + +llvm::Expected<SmallVector<Edit, 1>> +rewriteDescendants(const Stmt &Node, RewriteRule Rule, + const ast_matchers::MatchFinder::MatchResult &Result); + +llvm::Expected<SmallVector<Edit, 1>> +rewriteDescendants(const TypeLoc &Node, RewriteRule Rule, + const ast_matchers::MatchFinder::MatchResult &Result); + +llvm::Expected<SmallVector<Edit, 1>> +rewriteDescendants(const DynTypedNode &Node, RewriteRule Rule, + const ast_matchers::MatchFinder::MatchResult &Result); +/// @} + +/// Builds a single matcher for the rule, covering all of the rule's cases. +/// Only supports Rules whose cases' matchers share the same base "kind" +/// (`Stmt`, `Decl`, etc.) Deprecated: use `buildMatchers` instead, which +/// supports mixing matchers of different kinds. +ast_matchers::internal::DynTypedMatcher +buildMatcher(const RewriteRuleBase &Rule); + +/// Builds a set of matchers that cover the rule. +/// +/// One matcher is built for each distinct node matcher base kind: Stmt, Decl, +/// etc. Node-matchers for `QualType` and `Type` are not permitted, since such +/// nodes carry no source location information and are therefore not relevant +/// for rewriting. If any such matchers are included, will return an empty +/// vector. +std::vector<ast_matchers::internal::DynTypedMatcher> +buildMatchers(const RewriteRuleBase &Rule); + +/// Gets the beginning location of the source matched by a rewrite rule. If the +/// match occurs within a macro expansion, returns the beginning of the +/// expansion point. `Result` must come from the matching of a rewrite rule. +SourceLocation +getRuleMatchLoc(const ast_matchers::MatchFinder::MatchResult &Result); + +/// Returns the index of the \c Case of \c Rule that was selected in the match +/// result. Assumes a matcher built with \c buildMatcher. +size_t findSelectedCase(const ast_matchers::MatchFinder::MatchResult &Result, + const RewriteRuleBase &Rule); +} // namespace detail +} // namespace transformer +} // namespace clang + +#endif // LLVM_CLANG_TOOLING_TRANSFORMER_REWRITERULE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Transformer/SourceCode.h b/contrib/libs/clang16/include/clang/Tooling/Transformer/SourceCode.h new file mode 100644 index 0000000000..542eadfe08 --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Transformer/SourceCode.h @@ -0,0 +1,150 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- SourceCode.h - Source code manipulation routines -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file provides functions that simplify extraction of source code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_SOURCECODE_H +#define LLVM_CLANG_TOOLING_TRANSFORMER_SOURCECODE_H + +#include "clang/AST/ASTContext.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/TokenKinds.h" +#include <optional> + +namespace clang { +namespace tooling { + +/// Extends \p Range to include the token \p Terminator, if it immediately +/// follows the end of the range. Otherwise, returns \p Range unchanged. +CharSourceRange maybeExtendRange(CharSourceRange Range, + tok::TokenKind Terminator, + ASTContext &Context); + +/// Returns the source range spanning the node, extended to include \p Next, if +/// it immediately follows \p Node. Otherwise, returns the normal range of \p +/// Node. See comments on `getExtendedText()` for examples. +template <typename T> +CharSourceRange getExtendedRange(const T &Node, tok::TokenKind Next, + ASTContext &Context) { + return maybeExtendRange(CharSourceRange::getTokenRange(Node.getSourceRange()), + Next, Context); +} + +/// Returns the logical source range of the node extended to include associated +/// comments and whitespace before and after the node, and associated +/// terminators. The returned range consists of file locations, if valid file +/// locations can be found for the associated content; otherwise, an invalid +/// range is returned. +/// +/// Note that parsing comments is disabled by default. In order to select a +/// range containing associated comments, you may need to invoke the tool with +/// `-fparse-all-comments`. +CharSourceRange getAssociatedRange(const Decl &D, ASTContext &Context); + +/// Returns the source-code text in the specified range. +StringRef getText(CharSourceRange Range, const ASTContext &Context); + +/// Returns the source-code text corresponding to \p Node. +template <typename T> +StringRef getText(const T &Node, const ASTContext &Context) { + return getText(CharSourceRange::getTokenRange(Node.getSourceRange()), + Context); +} + +/// Returns the source text of the node, extended to include \p Next, if it +/// immediately follows the node. Otherwise, returns the text of just \p Node. +/// +/// For example, given statements S1 and S2 below: +/// \code +/// { +/// // S1: +/// if (!x) return foo(); +/// // S2: +/// if (!x) { return 3; } +/// } +/// \endcode +/// then +/// \code +/// getText(S1, Context) = "if (!x) return foo()" +/// getExtendedText(S1, tok::TokenKind::semi, Context) +/// = "if (!x) return foo();" +/// getExtendedText(*S1.getThen(), tok::TokenKind::semi, Context) +/// = "return foo();" +/// getExtendedText(*S2.getThen(), tok::TokenKind::semi, Context) +/// = getText(S2, Context) = "{ return 3; }" +/// \endcode +template <typename T> +StringRef getExtendedText(const T &Node, tok::TokenKind Next, + ASTContext &Context) { + return getText(getExtendedRange(Node, Next, Context), Context); +} + +/// Determines whether \p Range is one that can be edited by a rewrite; +/// generally, one that starts and ends within a particular file. +llvm::Error validateEditRange(const CharSourceRange &Range, + const SourceManager &SM); + +/// Attempts to resolve the given range to one that can be edited by a rewrite; +/// generally, one that starts and ends within a particular file. If a value is +/// returned, it satisfies \c validateEditRange. +/// +/// If \c IncludeMacroExpansion is true, a limited set of cases involving source +/// locations in macro expansions is supported. For example, if we're looking to +/// rewrite the int literal 3 to 6, and we have the following definition: +/// #define DO_NOTHING(x) x +/// then +/// foo(DO_NOTHING(3)) +/// will be rewritten to +/// foo(6) +std::optional<CharSourceRange> +getFileRangeForEdit(const CharSourceRange &EditRange, const SourceManager &SM, + const LangOptions &LangOpts, + bool IncludeMacroExpansion = true); +inline std::optional<CharSourceRange> +getFileRangeForEdit(const CharSourceRange &EditRange, const ASTContext &Context, + bool IncludeMacroExpansion = true) { + return getFileRangeForEdit(EditRange, Context.getSourceManager(), + Context.getLangOpts(), IncludeMacroExpansion); +} + +/// Attempts to resolve the given range to one that starts and ends in a +/// particular file. +/// +/// If \c IncludeMacroExpansion is true, a limited set of cases involving source +/// locations in macro expansions is supported. For example, if we're looking to +/// get the range of the int literal 3, and we have the following definition: +/// #define DO_NOTHING(x) x +/// foo(DO_NOTHING(3)) +/// the returned range will hold the source text `DO_NOTHING(3)`. +std::optional<CharSourceRange> getFileRange(const CharSourceRange &EditRange, + const SourceManager &SM, + const LangOptions &LangOpts, + bool IncludeMacroExpansion); +inline std::optional<CharSourceRange> +getFileRange(const CharSourceRange &EditRange, const ASTContext &Context, + bool IncludeMacroExpansion) { + return getFileRange(EditRange, Context.getSourceManager(), + Context.getLangOpts(), IncludeMacroExpansion); +} + +} // namespace tooling +} // namespace clang +#endif // LLVM_CLANG_TOOLING_TRANSFORMER_SOURCECODE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Transformer/SourceCodeBuilders.h b/contrib/libs/clang16/include/clang/Tooling/Transformer/SourceCodeBuilders.h new file mode 100644 index 0000000000..e044a0155f --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Transformer/SourceCodeBuilders.h @@ -0,0 +1,131 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- SourceCodeBuilders.h - Source-code building facilities -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file collects facilities for generating source code strings. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_SOURCECODEBUILDERS_H +#define LLVM_CLANG_TOOLING_TRANSFORMER_SOURCECODEBUILDERS_H + +#include "clang/AST/ASTContext.h" +#include "clang/AST/Expr.h" +#include <string> + +namespace clang { +namespace tooling { + +/// \name Code analysis utilities. +/// @{ +/// Ignores implicit object-construction expressions in addition to the normal +/// implicit expressions that are ignored. +const Expr *reallyIgnoreImplicit(const Expr &E); + +/// Determines whether printing this expression in *any* expression requires +/// parentheses to preserve its meaning. This analyses is necessarily +/// conservative because it lacks information about the target context. +bool mayEverNeedParens(const Expr &E); + +/// Determines whether printing this expression to the left of a dot or arrow +/// operator requires a parentheses to preserve its meaning. Given that +/// dot/arrow are (effectively) the highest precedence, this is equivalent to +/// asking whether it ever needs parens. +inline bool needParensBeforeDotOrArrow(const Expr &E) { + return mayEverNeedParens(E); +} + +/// Determines whether printing this expression to the right of a unary operator +/// requires a parentheses to preserve its meaning. +bool needParensAfterUnaryOperator(const Expr &E); + +// Recognizes known types (and sugared versions thereof) that overload the `*` +// and `->` operator. Below is the list of currently included types, but it is +// subject to change: +// +// * std::unique_ptr, std::shared_ptr, std::weak_ptr, +// * std::optional, absl::optional, llvm::Optional, +// * absl::StatusOr, llvm::Expected. +bool isKnownPointerLikeType(QualType Ty, ASTContext &Context); +/// @} + +/// \name Basic code-string generation utilities. +/// @{ + +/// Builds source for an expression, adding parens if needed for unambiguous +/// parsing. +std::optional<std::string> buildParens(const Expr &E, + const ASTContext &Context); + +/// Builds idiomatic source for the dereferencing of `E`: prefix with `*` but +/// simplify when it already begins with `&`. \returns empty string on failure. +std::optional<std::string> buildDereference(const Expr &E, + const ASTContext &Context); + +/// Builds idiomatic source for taking the address of `E`: prefix with `&` but +/// simplify when it already begins with `*`. \returns empty string on failure. +std::optional<std::string> buildAddressOf(const Expr &E, + const ASTContext &Context); + +/// Adds a dot to the end of the given expression, but adds parentheses when +/// needed by the syntax, and simplifies to `->` when possible, e.g.: +/// +/// `x` becomes `x.` +/// `*a` becomes `a->` +/// `a+b` becomes `(a+b).` +/// +/// DEPRECATED. Use `buildAccess`. +std::optional<std::string> buildDot(const Expr &E, const ASTContext &Context); + +/// Adds an arrow to the end of the given expression, but adds parentheses +/// when needed by the syntax, and simplifies to `.` when possible, e.g.: +/// +/// `x` becomes `x->` +/// `&a` becomes `a.` +/// `a+b` becomes `(a+b)->` +/// +/// DEPRECATED. Use `buildAccess`. +std::optional<std::string> buildArrow(const Expr &E, const ASTContext &Context); + +/// Specifies how to classify pointer-like types -- like values or like pointers +/// -- with regard to generating member-access syntax. +enum class PLTClass : bool { + Value, + Pointer, +}; + +/// Adds an appropriate access operator (`.`, `->` or nothing, in the case of +/// implicit `this`) to the end of the given expression. Adds parentheses when +/// needed by the syntax and simplifies when possible. If `PLTypeClass` is +/// `Pointer`, for known pointer-like types (see `isKnownPointerLikeType`), +/// treats `operator->` and `operator*` like the built-in `->` and `*` +/// operators. +/// +/// `x` becomes `x->` or `x.`, depending on `E`'s type +/// `a+b` becomes `(a+b)->` or `(a+b).`, depending on `E`'s type +/// `&a` becomes `a.` +/// `*a` becomes `a->` +std::optional<std::string> +buildAccess(const Expr &E, ASTContext &Context, + PLTClass Classification = PLTClass::Pointer); +/// @} + +} // namespace tooling +} // namespace clang +#endif // LLVM_CLANG_TOOLING_TRANSFORMER_SOURCECODEBUILDERS_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Transformer/Stencil.h b/contrib/libs/clang16/include/clang/Tooling/Transformer/Stencil.h new file mode 100644 index 0000000000..46742a9a0a --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Transformer/Stencil.h @@ -0,0 +1,182 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- Stencil.h - Stencil class ------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file defines the *Stencil* abstraction: a code-generating object, +/// parameterized by named references to (bound) AST nodes. Given a match +/// result, a stencil can be evaluated to a string of source code. +/// +/// A stencil is similar in spirit to a format string: it is composed of a +/// series of raw text strings, references to nodes (the parameters) and helper +/// code-generation operations. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_STENCIL_H_ +#define LLVM_CLANG_TOOLING_TRANSFORMER_STENCIL_H_ + +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTTypeTraits.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Tooling/Transformer/MatchConsumer.h" +#include "clang/Tooling/Transformer/RangeSelector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" +#include <string> +#include <vector> + +namespace clang { +namespace transformer { + +using StencilInterface = MatchComputation<std::string>; + +/// A sequence of code fragments, references to parameters and code-generation +/// operations that together can be evaluated to (a fragment of) source code or +/// a diagnostic message, given a match result. +/// +/// We use a `shared_ptr` to allow for easy and cheap copying of stencils. +/// Since `StencilInterface` is an immutable interface, the sharing doesn't +/// impose any risks. Otherwise, we would have to add a virtual `copy` method to +/// the API and implement it for all derived classes. +using Stencil = std::shared_ptr<StencilInterface>; + +namespace detail { +/// Convenience function to construct a \c Stencil. Overloaded for common cases +/// so that user doesn't need to specify which factory function to use. This +/// pattern gives benefits similar to implicit constructors, while maintaing a +/// higher degree of explicitness. +Stencil makeStencil(llvm::StringRef Text); +Stencil makeStencil(RangeSelector Selector); +inline Stencil makeStencil(Stencil S) { return S; } +} // namespace detail + +/// Constructs the string representing the concatenation of the given \p +/// Parts. If only one element is passed in \p Parts, returns that element. +Stencil catVector(std::vector<Stencil> Parts); + +/// Concatenates 0+ stencil pieces into a single stencil. Arguments can be raw +/// text, ranges in the matched code (\p RangeSelector) or other `Stencil`s. +template <typename... Ts> Stencil cat(Ts &&... Parts) { + return catVector({detail::makeStencil(std::forward<Ts>(Parts))...}); +} + +// +// Functions for conveniently building stencils. +// + +/// Generates the source of the expression bound to \p Id, wrapping it in +/// parentheses if it may parse differently depending on context. For example, a +/// binary operation is always wrapped, while a variable reference is never +/// wrapped. +Stencil expression(llvm::StringRef Id); + +/// Constructs an idiomatic dereferencing of the expression bound to \p ExprId. +/// \p ExprId is wrapped in parentheses, if needed. +Stencil deref(llvm::StringRef ExprId); + +/// If \p ExprId is of pointer type, constructs an idiomatic dereferencing of +/// the expression bound to \p ExprId, including wrapping it in parentheses, if +/// needed. Otherwise, generates the original expression source. +Stencil maybeDeref(llvm::StringRef ExprId); + +/// Constructs an expression that idiomatically takes the address of the +/// expression bound to \p ExprId. \p ExprId is wrapped in parentheses, if +/// needed. +Stencil addressOf(llvm::StringRef ExprId); + +/// If \p ExprId is not a pointer type, constructs an expression that +/// idiomatically takes the address of the expression bound to \p ExprId, +/// including wrapping \p ExprId in parentheses, if needed. Otherwise, generates +/// the original expression source. +Stencil maybeAddressOf(llvm::StringRef ExprId); + +/// Constructs a `MemberExpr` that accesses the named member (\p Member) of the +/// object bound to \p BaseId. The access is constructed idiomatically: if \p +/// BaseId is bound to `e` and \p Member identifies member `m`, then returns +/// `e->m`, when e is a pointer, `e2->m` when e = `*e2` and `e.m` otherwise. +/// Additionally, `e` is wrapped in parentheses, if needed. +Stencil access(llvm::StringRef BaseId, Stencil Member); +inline Stencil access(llvm::StringRef BaseId, llvm::StringRef Member) { + return access(BaseId, detail::makeStencil(Member)); +} + +/// Chooses between the two stencil parts, based on whether \p ID is bound in +/// the match. +Stencil ifBound(llvm::StringRef Id, Stencil TrueStencil, Stencil FalseStencil); + +/// Chooses between the two strings, based on whether \p ID is bound in the +/// match. +inline Stencil ifBound(llvm::StringRef Id, llvm::StringRef TrueText, + llvm::StringRef FalseText) { + return ifBound(Id, detail::makeStencil(TrueText), + detail::makeStencil(FalseText)); +} + +/// Chooses between multiple stencils, based on the presence of bound nodes. \p +/// CaseStencils takes a vector of (ID, \c Stencil) pairs and checks each ID in +/// order to see if it's bound to a node. If so, the associated \c Stencil is +/// run and all other cases are ignored. An optional \p DefaultStencil can be +/// provided to be run if all cases are exhausted beacause none of the provided +/// IDs are bound. If no default case is provided and all cases are exhausted, +/// the stencil will fail with error `llvm::errc::result_out_of_range`. +/// +/// For example, say one matches a statement's type with: +/// anyOf( +/// qualType(isInteger()).bind("int"), +/// qualType(realFloatingPointType()).bind("float"), +/// qualType(isAnyCharacter()).bind("char"), +/// booleanType().bind("bool")) +/// +/// Then, one can decide in a stencil how to construct a literal. +/// cat("a = ", +/// selectBound( +/// {{"int", cat("0")}, +/// {"float", cat("0.0")}, +/// {"char", cat("'\\0'")}, +/// {"bool", cat("false")}})) +/// +/// In addition, one could supply a default case for all other types: +/// selectBound( +/// {{"int", cat("0")}, +/// ... +/// {"bool", cat("false")}}, +/// cat("{}")) +Stencil selectBound(std::vector<std::pair<std::string, Stencil>> CaseStencils, + Stencil DefaultStencil = nullptr); + +/// Wraps a \c MatchConsumer in a \c Stencil, so that it can be used in a \c +/// Stencil. This supports user-defined extensions to the \c Stencil language. +Stencil run(MatchConsumer<std::string> C); + +/// Produces a human-readable rendering of the node bound to `Id`, suitable for +/// diagnostics and debugging. This operator can be applied to any node, but is +/// targeted at those whose source cannot be printed directly, including: +/// +/// * Types. represented based on their structure. Note that namespace +/// qualifiers are always printed, with the anonymous namespace represented +/// explicitly. No desugaring or canonicalization is applied. +Stencil describe(llvm::StringRef Id); + +/// For debug use only; semantics are not guaranteed. +/// +/// \returns the string resulting from calling the node's print() method. +Stencil dPrint(llvm::StringRef Id); +} // namespace transformer +} // namespace clang +#endif // LLVM_CLANG_TOOLING_TRANSFORMER_STENCIL_H_ + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/clang16/include/clang/Tooling/Transformer/Transformer.h b/contrib/libs/clang16/include/clang/Tooling/Transformer/Transformer.h new file mode 100644 index 0000000000..e4852b250e --- /dev/null +++ b/contrib/libs/clang16/include/clang/Tooling/Transformer/Transformer.h @@ -0,0 +1,223 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- Transformer.h - Transformer class ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_TRANSFORMER_H_ +#define LLVM_CLANG_TOOLING_TRANSFORMER_TRANSFORMER_H_ + +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Tooling/Refactoring/AtomicChange.h" +#include "clang/Tooling/Transformer/RewriteRule.h" +#include "llvm/Support/Error.h" +#include <functional> +#include <utility> + +namespace clang { +namespace tooling { + +namespace detail { +/// Implementation details of \c Transformer with type erasure around +/// \c RewriteRule<T> as well as the corresponding consumers. +class TransformerImpl { +public: + virtual ~TransformerImpl() = default; + + void onMatch(const ast_matchers::MatchFinder::MatchResult &Result); + + virtual std::vector<ast_matchers::internal::DynTypedMatcher> + buildMatchers() const = 0; + +protected: + /// Converts a set of \c Edit into a \c AtomicChange per file modified. + /// Returns an error if the edits fail to compose, e.g. overlapping edits. + static llvm::Expected<llvm::SmallVector<AtomicChange, 1>> + convertToAtomicChanges(const llvm::SmallVectorImpl<transformer::Edit> &Edits, + const ast_matchers::MatchFinder::MatchResult &Result); + +private: + virtual void + onMatchImpl(const ast_matchers::MatchFinder::MatchResult &Result) = 0; +}; + +// FIXME: Use std::type_identity or backport when available. +template <class T> struct type_identity { + using type = T; +}; +} // namespace detail + +template <typename T> struct TransformerResult { + llvm::MutableArrayRef<AtomicChange> Changes; + T Metadata; +}; + +template <> struct TransformerResult<void> { + llvm::MutableArrayRef<AtomicChange> Changes; +}; + +/// Handles the matcher and callback registration for a single `RewriteRule`, as +/// defined by the arguments of the constructor. +class Transformer : public ast_matchers::MatchFinder::MatchCallback { +public: + /// Provides the set of changes to the consumer. The callback is free to move + /// or destructively consume the changes as needed. + /// + /// We use \c MutableArrayRef as an abstraction to provide decoupling, and we + /// expect the majority of consumers to copy or move the individual values + /// into a separate data structure. + using ChangeSetConsumer = std::function<void( + Expected<llvm::MutableArrayRef<AtomicChange>> Changes)>; + + /// \param Consumer receives all rewrites for a single match, or an error. + /// Will not necessarily be called for each match; for example, if the rule + /// generates no edits but does not fail. Note that clients are responsible + /// for handling the case that independent \c AtomicChanges conflict with each + /// other. + explicit Transformer(transformer::RewriteRuleWith<void> Rule, + ChangeSetConsumer Consumer) + : Transformer(std::move(Rule), + [Consumer = std::move(Consumer)]( + llvm::Expected<TransformerResult<void>> Result) { + if (Result) + Consumer(Result->Changes); + else + Consumer(Result.takeError()); + }) {} + + /// \param Consumer receives all rewrites and the associated metadata for a + /// single match, or an error. Will always be called for each match, even if + /// the rule generates no edits. Note that clients are responsible for + /// handling the case that independent \c AtomicChanges conflict with each + /// other. + template <typename MetadataT> + explicit Transformer( + transformer::RewriteRuleWith<MetadataT> Rule, + std::function<void(llvm::Expected<TransformerResult< + typename detail::type_identity<MetadataT>::type>>)> + Consumer); + + /// N.B. Passes `this` pointer to `MatchFinder`. So, this object should not + /// be moved after this call. + void registerMatchers(ast_matchers::MatchFinder *MatchFinder); + + /// Not called directly by users -- called by the framework, via base class + /// pointer. + void run(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + std::unique_ptr<detail::TransformerImpl> Impl; +}; + +namespace detail { +/// Runs the metadata generator on \c Rule and stuffs it into \c Result. +/// @{ +template <typename T> +llvm::Error +populateMetadata(const transformer::RewriteRuleWith<T> &Rule, + size_t SelectedCase, + const ast_matchers::MatchFinder::MatchResult &Match, + TransformerResult<T> &Result) { + // Silence a false positive GCC -Wunused-but-set-parameter warning in constexpr + // cases, by marking SelectedCase as used. See + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85827 for details. The issue is + // fixed in GCC 10. + (void)SelectedCase; + if constexpr (!std::is_void_v<T>) { + auto Metadata = Rule.Metadata[SelectedCase]->eval(Match); + if (!Metadata) + return Metadata.takeError(); + Result.Metadata = std::move(*Metadata); + } + return llvm::Error::success(); +} +/// @} + +/// Implementation when metadata is generated as a part of the rewrite. This +/// happens when we have a \c RewriteRuleWith<T>. +template <typename T> class WithMetadataImpl final : public TransformerImpl { + transformer::RewriteRuleWith<T> Rule; + std::function<void(llvm::Expected<TransformerResult<T>>)> Consumer; + +public: + explicit WithMetadataImpl( + transformer::RewriteRuleWith<T> R, + std::function<void(llvm::Expected<TransformerResult<T>>)> Consumer) + : Rule(std::move(R)), Consumer(std::move(Consumer)) { + assert(llvm::all_of(Rule.Cases, + [](const transformer::RewriteRuleBase::Case &Case) + -> bool { return !!Case.Edits; }) && + "edit generator must be provided for each rule"); + if constexpr (!std::is_void_v<T>) + assert(llvm::all_of(Rule.Metadata, + [](const typename transformer::Generator<T> &Metadata) + -> bool { return !!Metadata; }) && + "metadata generator must be provided for each rule"); + } + +private: + void onMatchImpl(const ast_matchers::MatchFinder::MatchResult &Result) final { + size_t I = transformer::detail::findSelectedCase(Result, Rule); + auto Transformations = Rule.Cases[I].Edits(Result); + if (!Transformations) { + Consumer(Transformations.takeError()); + return; + } + + llvm::SmallVector<AtomicChange, 1> Changes; + if (!Transformations->empty()) { + auto C = convertToAtomicChanges(*Transformations, Result); + if (C) { + Changes = std::move(*C); + } else { + Consumer(C.takeError()); + return; + } + } else if (std::is_void<T>::value) { + // If we don't have metadata and we don't have any edits, skip. + return; + } + + TransformerResult<T> RewriteResult; + if (auto E = populateMetadata(Rule, I, Result, RewriteResult)) { + Consumer(std::move(E)); + return; + } + + RewriteResult.Changes = llvm::MutableArrayRef<AtomicChange>(Changes); + Consumer(std::move(RewriteResult)); + } + + std::vector<ast_matchers::internal::DynTypedMatcher> + buildMatchers() const final { + return transformer::detail::buildMatchers(Rule); + } +}; +} // namespace detail + +template <typename MetadataT> +Transformer::Transformer( + transformer::RewriteRuleWith<MetadataT> Rule, + std::function<void(llvm::Expected<TransformerResult< + typename detail::type_identity<MetadataT>::type>>)> + Consumer) + : Impl(std::make_unique<detail::WithMetadataImpl<MetadataT>>( + std::move(Rule), std::move(Consumer))) {} + +} // namespace tooling +} // namespace clang + +#endif // LLVM_CLANG_TOOLING_TRANSFORMER_TRANSFORMER_H_ + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif |