brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.7 KiB · 43500f6 Raw
150 lines · cpp
1//===--- TextDiagnostics.cpp - Text Diagnostics for Paths -------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9//  This file defines the TextDiagnostics object.10//11//===----------------------------------------------------------------------===//12 13#include "clang/Analysis/MacroExpansionContext.h"14#include "clang/Analysis/PathDiagnostic.h"15#include "clang/Basic/SourceManager.h"16#include "clang/CrossTU/CrossTranslationUnit.h"17#include "clang/Frontend/ASTUnit.h"18#include "clang/Lex/Preprocessor.h"19#include "clang/Rewrite/Core/Rewriter.h"20#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"21#include "clang/Tooling/Core/Replacement.h"22#include "clang/Tooling/Tooling.h"23 24using namespace clang;25using namespace ento;26using namespace tooling;27 28namespace {29/// Emits minimal diagnostics (report message + notes) for the 'none' output30/// type to the standard error, or to complement many others. Emits detailed31/// diagnostics in textual format for the 'text' output type.32class TextDiagnostics : public PathDiagnosticConsumer {33  PathDiagnosticConsumerOptions DiagOpts;34  DiagnosticsEngine &DiagEng;35  const LangOptions &LO;36  bool ShouldDisplayPathNotes;37 38public:39  TextDiagnostics(PathDiagnosticConsumerOptions DiagOpts,40                  DiagnosticsEngine &DiagEng, const LangOptions &LO,41                  bool ShouldDisplayPathNotes)42      : DiagOpts(std::move(DiagOpts)), DiagEng(DiagEng), LO(LO),43        ShouldDisplayPathNotes(ShouldDisplayPathNotes) {}44  ~TextDiagnostics() override {}45 46  StringRef getName() const override { return "TextDiagnostics"; }47 48  bool supportsLogicalOpControlFlow() const override { return true; }49  bool supportsCrossFileDiagnostics() const override { return true; }50 51  PathGenerationScheme getGenerationScheme() const override {52    return ShouldDisplayPathNotes ? Minimal : None;53  }54 55  void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,56                            FilesMade *filesMade) override {57    unsigned WarnID =58        DiagOpts.ShouldDisplayWarningsAsErrors59            ? DiagEng.getCustomDiagID(DiagnosticsEngine::Error, "%0")60            : DiagEng.getCustomDiagID(DiagnosticsEngine::Warning, "%0");61    unsigned NoteID = DiagEng.getCustomDiagID(DiagnosticsEngine::Note, "%0");62    SourceManager &SM = DiagEng.getSourceManager();63 64    Replacements Repls;65    auto reportPiece = [&](unsigned ID, FullSourceLoc Loc, StringRef String,66                           ArrayRef<SourceRange> Ranges,67                           ArrayRef<FixItHint> Fixits) {68      if (!DiagOpts.ShouldApplyFixIts) {69        DiagEng.Report(Loc, ID) << String << Ranges << Fixits;70        return;71      }72 73      DiagEng.Report(Loc, ID) << String << Ranges;74      for (const FixItHint &Hint : Fixits) {75        Replacement Repl(SM, Hint.RemoveRange, Hint.CodeToInsert);76 77        if (llvm::Error Err = Repls.add(Repl)) {78          llvm::errs() << "Error applying replacement " << Repl.toString()79                       << ": " << llvm::toString(std::move(Err)) << "\n";80        }81      }82    };83 84    for (const PathDiagnostic *PD : Diags) {85      std::string WarningMsg = (DiagOpts.ShouldDisplayDiagnosticName86                                    ? " [" + PD->getCheckerName() + "]"87                                    : "")88                                   .str();89      reportPiece(WarnID, PD->getLocation().asLocation(),90                  (PD->getShortDescription() + WarningMsg).str(),91                  PD->path.back()->getRanges(), PD->path.back()->getFixits());92 93      // First, add extra notes, even if paths should not be included.94      for (const auto &Piece : PD->path) {95        if (!isa<PathDiagnosticNotePiece>(Piece.get()))96          continue;97 98        reportPiece(NoteID, Piece->getLocation().asLocation(),99                    Piece->getString(), Piece->getRanges(),100                    Piece->getFixits());101      }102 103      if (!ShouldDisplayPathNotes)104        continue;105 106      // Then, add the path notes if necessary.107      PathPieces FlatPath = PD->path.flatten(/*ShouldFlattenMacros=*/true);108      for (const auto &Piece : FlatPath) {109        if (isa<PathDiagnosticNotePiece>(Piece.get()))110          continue;111 112        reportPiece(NoteID, Piece->getLocation().asLocation(),113                    Piece->getString(), Piece->getRanges(),114                    Piece->getFixits());115      }116    }117 118    if (Repls.empty())119      return;120 121    Rewriter Rewrite(SM, LO);122    if (!applyAllReplacements(Repls, Rewrite)) {123      llvm::errs() << "An error occurred during applying fix-it.\n";124    }125 126    Rewrite.overwriteChangedFiles();127  }128};129} // end anonymous namespace130 131void ento::createTextPathDiagnosticConsumer(132    PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,133    const std::string &Prefix, const Preprocessor &PP,134    const cross_tu::CrossTranslationUnitContext &CTU,135    const MacroExpansionContext &MacroExpansions) {136  C.emplace_back(new TextDiagnostics(std::move(DiagOpts), PP.getDiagnostics(),137                                     PP.getLangOpts(),138                                     /*ShouldDisplayPathNotes=*/true));139}140 141void ento::createTextMinimalPathDiagnosticConsumer(142    PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,143    const std::string &Prefix, const Preprocessor &PP,144    const cross_tu::CrossTranslationUnitContext &CTU,145    const MacroExpansionContext &MacroExpansions) {146  C.emplace_back(new TextDiagnostics(std::move(DiagOpts), PP.getDiagnostics(),147                                     PP.getLangOpts(),148                                     /*ShouldDisplayPathNotes=*/false));149}150