{"id":444362,"date":"2025-01-08T21:01:46","date_gmt":"2025-01-08T21:01:46","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=444362"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=444362","title":{"rendered":"<span>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0439 \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0421++ \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e CLang LibTooling<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/y-\/t8\/37\/y-t837zqbk2jynlorochjcqfuty.jpeg\" alt=\"image\" data-src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/y-\/t8\/37\/y-t837zqbk2jynlorochjcqfuty.jpeg\" data-blurred=\"true\"\/><\/p>\n<p> <\/p>\n<p>\u0415\u0449\u0435 \u043e\u0434\u043d\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0432 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435 \u0442\u0435\u043c\u044b \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0441\u0445\u043e\u0434\u043d\u044b\u0445 \u0442\u0435\u043a\u0441\u0442\u043e\u0432 \u043d\u0430 \u0421\/\u0421++ \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Clang. \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438:<\/p>\n<p> <\/p>\n<ul>\n<li><a href=\"https:\/\/habr.com\/ru\/articles\/870840\/\">\u200b\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430 C++<\/a><\/li>\n<li><a href=\"https:\/\/habr.com\/ru\/articles\/871296\/\">\u0410\u043d\u0430\u043b\u0438\u0437 AST \u0438 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 \u043a\u043e\u0434\u0430 \u0432 Clang<\/a><\/li>\n<\/ul>\n<p> <\/p>\n<p>\u042d\u0442\u043e \u043d\u0435 \u043f\u0435\u0440\u0435\u0432\u043e\u0434 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0439 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 <a href=\"https:\/\/www.goldsborough.me\/c++\/clang\/llvm\/tools\/2017\/02\/24\/00-00-06-emitting_diagnostics_and_fixithints_in_clang_tools\/\" rel=\"nofollow noopener noreferrer\">Emitting Diagnostics in Clang<\/a> \u043e\u0442 <a href=\"https:\/\/www.goldsborough.me\/contact\/\" rel=\"nofollow noopener noreferrer\">Peter Goldsborough<\/a> \u043f\u0440\u043e \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043d\u044e\u0430\u043d\u0441\u044b \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0443 Clang, \u0430 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0430\u0434\u0430\u043f\u0442\u0430\u0446\u0438\u044f \u0441\u0442\u0430\u0440\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043f\u043e\u0434 \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430.<\/p>\n<p> <\/p>\n<p>\u0418 \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0438\u0434\u0435\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u0435\u043d\u044f \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043b\u0430 \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438, \u044d\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 FixIt \u0438\u0437 \u043d\u0430\u0431\u043e\u0440\u0430 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0438 clang \u0434\u043b\u044f \u0432\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0439 \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b.<\/p>\n<p><a name=\"habracut\"><\/a> <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u043e \u0447\u0435\u043c \u0438\u0434\u0435\u0442 \u0440\u0435\u0447\u044c.<\/p>\n<p> <\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0448\u0442\u0430\u0442\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 Clang \u0434\u043b\u044f \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0438 Fixit (\u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0438 \u0441 \u043d\u0438\u0437\u043a\u0438\u043c \u0443\u0440\u043e\u0432\u043d\u0435\u043c \u043b\u043e\u0436\u043d\u044b\u0445 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u0439), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435 \u0438\u043b\u0438 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0438, \u0430 \u0435\u0449\u0435 \u0438 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u0441\u043f\u043e\u0441\u043e\u0431 \u0435\u0433\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f.<\/p>\n<p> <\/p>\n<p>\u0417\u0430 \u0441\u0447\u0435\u0442 \u044d\u0442\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0438 \u0437\u0430\u043c\u0435\u043d\u044b \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439 \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u0430\u0445 \u0421++. \u041f\u0440\u0438\u0447\u0435\u043c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0432\u0438\u0434\u0435 \u0432\u044b\u0432\u043e\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0438\u043b\u0438 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d \u0432 \u0441\u0440\u0435\u0434\u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043d\u043e \u0438 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432 \u0444\u0430\u0439\u043b.<\/p>\n<p> <\/p>\n<p>\u0421\u0442\u0430\u0442\u044c\u044e \u044f \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u043d\u0435 \u0441\u0442\u0430\u043b, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043c\u043d\u043e\u0433\u043e \u0438 \u043e\u043d \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043b\u043e\u0436\u043d\u044b\u0439, \u0430 \u0437\u0430\u043e\u0434\u043d\u043e \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u044e \u043f\u0440\u0438\u0432\u0435\u0442 <a href=\"https:\/\/habr.com\/ru\/ppa\/about\/\">\u041f\u041f\u0410 \u0425\u0430\u0431\u0440\u0430<\/a>.<\/p>\n<p> <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0420\u0430\u0431\u043e\u0447\u0438\u0439 \u043a\u043e\u0434 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0438\u0437 \u0441\u0442\u0430\u0442\u044c\u0438<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">\/\/ Clang includes #include \"clang\/AST\/ASTConsumer.h\" #include \"clang\/AST\/ASTContext.h\" #include \"clang\/AST\/Expr.h\" #include \"clang\/ASTMatchers\/ASTMatchFinder.h\" #include \"clang\/ASTMatchers\/ASTMatchers.h\" #include \"clang\/Basic\/Diagnostic.h\" #include \"clang\/Basic\/SourceLocation.h\" #include \"clang\/Frontend\/FrontendAction.h\" #include \"clang\/Rewrite\/Frontend\/FixItRewriter.h\" #include \"clang\/Tooling\/CommonOptionsParser.h\" #include \"clang\/Tooling\/Tooling.h\"  \/\/ LLVM includes #include \"llvm\/ADT\/ArrayRef.h\" #include \"llvm\/ADT\/StringRef.h\" #include \"llvm\/Support\/CommandLine.h\" #include \"llvm\/Support\/raw_ostream.h\"  \/\/ Standard includes #include &lt;cassert&gt; #include &lt;memory&gt; #include &lt;string&gt; #include &lt;type_traits&gt; #include &lt;iostream&gt;  namespace MinusTool {      class FixItRewriterOptions : public clang::FixItOptions {     public:         using super = clang::FixItOptions;          \/\/\/ Constructor.         \/\/\/         \/\/\/ The \\p RewriteSuffix is the option from the command line.          explicit FixItRewriterOptions(const std::string&amp; RewriteSuffix)         : RewriteSuffix(RewriteSuffix) {             super::InPlace = false;         }          \/\/\/ For a file to be rewritten, returns the (possibly) new filename.         \/\/\/         \/\/\/ If the \\c RewriteSuffix is empty, returns the \\p Filename, causing         \/\/\/ in-place rewriting. If it is not empty, the \\p Filename with that suffix         \/\/\/ is returned.          std::string RewriteFilename(const std::string&amp; Filename, int&amp; fd) override {             fd = -1;              llvm::errs() &lt;&lt; \"Rewriting FixIts \";              if (RewriteSuffix.empty()) {                 llvm::errs() &lt;&lt; \"in-place\\n\";                 return Filename;             }              const auto NewFilename = Filename + RewriteSuffix;             llvm::errs() &lt;&lt; \"from \" &lt;&lt; Filename &lt;&lt; \" to \" &lt;&lt; NewFilename &lt;&lt; \"\\n\";              return NewFilename;         }      private:         \/\/\/ The suffix appended to rewritten files.         std::string RewriteSuffix;     };      class MatchHandler : public clang::ast_matchers::MatchFinder::MatchCallback {     public:         using MatchResult = clang::ast_matchers::MatchFinder::MatchResult;         using RewriterPointer = std::unique_ptr&lt;clang::FixItRewriter&gt;;          \/\/\/ Constructor.         \/\/\/         \/\/\/ \\p DoRewrite and \\p RewriteSuffix are the command line options passed         \/\/\/ to the tool.          MatchHandler(bool DoRewrite, const std::string&amp; RewriteSuffix)         : FixItOptions(RewriteSuffix), DoRewrite(DoRewrite) {         }          \/\/\/ Runs the MatchHandler's action.         \/\/\/         \/\/\/ Emits a diagnostic for each matched expression, optionally rewriting the         \/\/\/ file in-place or to another file, depending on the command line options.          void run(const MatchResult&amp; Result) {             auto&amp; Context = *Result.Context;              const auto&amp; Op = Result.Nodes.getNodeAs&lt;clang::BinaryOperator&gt;(\"op\");             assert(Op != nullptr);              const auto StartLocation = Op-&gt;getOperatorLoc();             const auto EndLocation = StartLocation.getLocWithOffset(+1);             const clang::SourceRange SourceRange(StartLocation, EndLocation);             const auto FixIt = clang::FixItHint::CreateReplacement(SourceRange, \"-\");              auto&amp; DiagnosticsEngine = Context.getDiagnostics();              \/\/ The FixItRewriter is quite a heavy object, so let's             \/\/ not create it unless we really have to.             RewriterPointer Rewriter;             if (DoRewrite) {                 Rewriter = createRewriter(DiagnosticsEngine, Context);             }              const auto ID =                     DiagnosticsEngine.getCustomDiagID(clang::DiagnosticsEngine::Warning,                     \"This should probably be a minus\");              DiagnosticsEngine.Report(StartLocation, ID).AddFixItHint(FixIt);              if (DoRewrite) {                 assert(Rewriter != nullptr);                 Rewriter-&gt;WriteFixedFiles();             }         }      private:         \/\/\/ Allocates a \\c FixItRewriter and sets it as the client of the given \\p         \/\/\/ DiagnosticsEngine.         \/\/\/         \/\/\/ The \\p Context is forwarded to the constructor of the \\c FixItRewriter.          RewriterPointer createRewriter(clang::DiagnosticsEngine&amp; DiagnosticsEngine,                 clang::ASTContext&amp; Context) {             auto Rewriter =                     std::make_unique&lt;clang::FixItRewriter&gt;(DiagnosticsEngine,                     Context.getSourceManager(),                     Context.getLangOpts(),                     &amp;FixItOptions);              \/\/ Note: it would make more sense to just create a raw pointer and have the             \/\/ DiagnosticEngine own it. However, the FixItRewriter stores a pointer to             \/\/ the client of the DiagnosticsEngine when it gets constructed with it.             \/\/ If we then set the rewriter to be the client of the engine, the old             \/\/ client gets destroyed, leading to happy segfaults when the rewriter             \/\/ handles a diagnostic.             DiagnosticsEngine.setClient(Rewriter.get(), \/*ShouldOwnClient=*\/false);              return Rewriter;         }          FixItRewriterOptions FixItOptions;         bool DoRewrite;     };      \/\/\/ Consumes an AST and attempts to match for the     \/\/\/ kinds of nodes we are looking for.      class Consumer : public clang::ASTConsumer {     public:         \/\/\/ Constructor.         \/\/\/         \/\/\/ All arguments are forwarded to the \\c MatchHandler.          template &lt;typename... Args&gt;         explicit Consumer(Args&amp;&amp;... args) : Handler(std::forward&lt;Args&gt;(args)...) {             using namespace clang::ast_matchers;              \/\/ Want to match:             \/\/ int x = 4   +   2;             \/\/     ^   ^   ^   ^             \/\/   var  lhs op  rhs              \/\/ clang-format off             const auto Matcher = varDecl(                     hasType(isInteger()),                     hasInitializer(binaryOperator(                     hasOperatorName(\"+\"),                     hasLHS(integerLiteral().bind(\"lhs\")),                     hasRHS(integerLiteral().bind(\"rhs\"))).bind(\"op\"))).bind(\"var\");             \/\/ clang-format on              MatchFinder.addMatcher(Matcher, &amp;Handler);         }          \/\/\/ Attempts to match the match expression defined in the constructor.          void HandleTranslationUnit(clang::ASTContext&amp; Context) override {             MatchFinder.matchAST(Context);         }      private:         \/\/\/ Our callback for matches.         MatchHandler Handler;          \/\/\/ The MatchFinder we use for matching on the AST.         clang::ast_matchers::MatchFinder MatchFinder;     };      class Action : public clang::ASTFrontendAction {     public:         using ASTConsumerPointer = std::unique_ptr&lt;clang::ASTConsumer&gt;;          \/\/\/ Constructor, taking the \\p RewriteOption and \\p RewriteSuffixOption.          Action(bool DoRewrite, const std::string&amp; RewriteSuffix)         : DoRewrite(DoRewrite), RewriteSuffix(RewriteSuffix) {         }          \/\/\/ Creates the Consumer instance, forwarding the command line options.          ASTConsumerPointer CreateASTConsumer(clang::CompilerInstance&amp; Compiler,                 llvm::StringRef Filename) override {             return std::make_unique&lt;Consumer&gt;(DoRewrite, RewriteSuffix);         }      private:         \/\/\/ Whether we want to rewrite files. Forwarded to the consumer.         bool DoRewrite;          \/\/\/ The suffix for rewritten files. Forwarded to the consumer.         std::string RewriteSuffix;     }; } \/\/ namespace MinusTool  namespace {     llvm::cl::OptionCategory MinusToolCategory(\"minus-tool options\");      llvm::cl::extrahelp MinusToolCategoryHelp(R\"( This tool turns all your plusses into minuses, because why not. Given a binary plus operation with two integer operands:  int x = 4 + 2;  This tool will rewrite the code to change the plus into a minus:  int x = 4 - 2;  You're welcome. )\");      llvm::cl::opt&lt;bool&gt;     RewriteOption(\"rewrite\",             llvm::cl::init(false),             llvm::cl::desc(\"If set, emits rewritten source code\"),             llvm::cl::cat(MinusToolCategory));      llvm::cl::opt&lt;std::string&gt; RewriteSuffixOption(             \"rewrite-suffix\",             llvm::cl::desc(\"If -rewrite is set, changes will be rewritten to a file \"             \"with the same name, but this suffix\"),             llvm::cl::cat(MinusToolCategory));      llvm::cl::extrahelp     CommonHelp(clang::tooling::CommonOptionsParser::HelpMessage); } \/\/ namespace  \/\/\/ A custom \\c FrontendActionFactory so that we can pass the options \/\/\/ to the constructor of the tool.  struct ToolFactory : public clang::tooling::FrontendActionFactory {      std::unique_ptr&lt;clang::FrontendAction&gt; create() override {         return std::unique_ptr&lt;clang::FrontendAction&gt;(new MinusTool::Action(RewriteOption, RewriteSuffixOption));     } };  auto main(int argc, const char* argv[]) -&gt; int {     using namespace clang::tooling;      auto OptionsParser = CommonOptionsParser::create(argc, argv, MinusToolCategory);     if (!OptionsParser) {         llvm::outs() &lt;&lt; OptionsParser.takeError();         return -1;     }     ClangTool Tool(OptionsParser-&gt;getCompilations(), OptionsParser-&gt;getSourcePathList());      return Tool.run(new ToolFactory()); }<\/code><\/pre>\n<\/div><\/div>\n<p> <\/p>\n<p>\u0421\u0441\u043b\u043a\u0430 \u043d\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 <a href=\"https:\/\/github.com\/rsashka\/clang_fixit\" rel=\"nofollow noopener noreferrer\">https:\/\/github.com\/rsashka\/clang_fixit<\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/872268\/\"> https:\/\/habr.com\/ru\/articles\/872268\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/y-\/t8\/37\/y-t837zqbk2jynlorochjcqfuty.jpeg\" alt=\"image\" data-src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/y-\/t8\/37\/y-t837zqbk2jynlorochjcqfuty.jpeg\" data-blurred=\"true\"\/><\/p>\n<p> <\/p>\n<p>\u0415\u0449\u0435 \u043e\u0434\u043d\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0432 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435 \u0442\u0435\u043c\u044b \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0441\u0445\u043e\u0434\u043d\u044b\u0445 \u0442\u0435\u043a\u0441\u0442\u043e\u0432 \u043d\u0430 \u0421\/\u0421++ \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Clang. \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438:<\/p>\n<p> <\/p>\n<ul>\n<li><a href=\"https:\/\/habr.com\/ru\/articles\/870840\/\">\u200b\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430 C++<\/a><\/li>\n<li><a href=\"https:\/\/habr.com\/ru\/articles\/871296\/\">\u0410\u043d\u0430\u043b\u0438\u0437 AST \u0438 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 \u043a\u043e\u0434\u0430 \u0432 Clang<\/a><\/li>\n<\/ul>\n<p> <\/p>\n<p>\u042d\u0442\u043e \u043d\u0435 \u043f\u0435\u0440\u0435\u0432\u043e\u0434 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0439 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 <a href=\"https:\/\/www.goldsborough.me\/c++\/clang\/llvm\/tools\/2017\/02\/24\/00-00-06-emitting_diagnostics_and_fixithints_in_clang_tools\/\" rel=\"nofollow noopener noreferrer\">Emitting Diagnostics in Clang<\/a> \u043e\u0442 <a href=\"https:\/\/www.goldsborough.me\/contact\/\" rel=\"nofollow noopener noreferrer\">Peter Goldsborough<\/a> \u043f\u0440\u043e \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043d\u044e\u0430\u043d\u0441\u044b \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0443 Clang, \u0430 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0430\u0434\u0430\u043f\u0442\u0430\u0446\u0438\u044f \u0441\u0442\u0430\u0440\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043f\u043e\u0434 \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430.<\/p>\n<p> <\/p>\n<p>\u0418 \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0438\u0434\u0435\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u0435\u043d\u044f \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043b\u0430 \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438, \u044d\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 FixIt \u0438\u0437 \u043d\u0430\u0431\u043e\u0440\u0430 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0438 clang \u0434\u043b\u044f \u0432\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0439 \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-444362","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/444362","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=444362"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/444362\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=444362"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=444362"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=444362"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}