Author: alexfh Date: Mon Mar 10 08:11:17 2014 New Revision: 203457 URL: http://llvm.org/viewvc/llvm-project?rev=203457&view=rev Log: Use DiagnosticRenderer to convert clang diagnostics to clang-tidy ones.
Summary: This is immediately useful for generating macro expansion notes, and may be useful for other things later on. Reviewers: klimek, djasper Reviewed By: klimek CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D2950 Added: clang-tools-extra/trunk/test/clang-tidy/macros.cpp Modified: clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h Modified: clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp?rev=203457&r1=203456&r2=203457&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp (original) +++ clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp Mon Mar 10 08:11:17 2014 @@ -17,6 +17,8 @@ //===----------------------------------------------------------------------===// #include "ClangTidyDiagnosticConsumer.h" + +#include "clang/Frontend/DiagnosticRenderer.h" #include "llvm/ADT/SmallString.h" #include <set> @@ -25,19 +27,91 @@ namespace clang { namespace tidy { +class ClangTidyDiagnosticRenderer : public DiagnosticRenderer { +public: + ClangTidyDiagnosticRenderer(const LangOptions &LangOpts, + DiagnosticOptions *DiagOpts, + ClangTidyError &Error) + : DiagnosticRenderer(LangOpts, DiagOpts), Error(Error) {} + +protected: + void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level, StringRef Message, + ArrayRef<CharSourceRange> Ranges, + const SourceManager *SM, + DiagOrStoredDiag Info) override { + if (Level == DiagnosticsEngine::Ignored) + return; + ClangTidyMessage TidyMessage = Loc.isValid() + ? ClangTidyMessage(Message, *SM, Loc) + : ClangTidyMessage(Message); + if (Level == DiagnosticsEngine::Note) { + Error.Notes.push_back(TidyMessage); + return; + } + assert(Error.Message.Message.empty() && + "Overwriting a diagnostic message"); + Error.Message = TidyMessage; + } + + void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level, + ArrayRef<CharSourceRange> Ranges, + const SourceManager &SM) override {} + + void emitBasicNote(StringRef Message) override { + Error.Notes.push_back(ClangTidyMessage(Message)); + } + + void emitCodeContext(SourceLocation Loc, DiagnosticsEngine::Level Level, + SmallVectorImpl<CharSourceRange> &Ranges, + ArrayRef<FixItHint> Hints, + const SourceManager &SM) override { + assert(Loc.isValid()); + for (const auto &FixIt : Hints) { + CharSourceRange Range = FixIt.RemoveRange; + assert(Range.getBegin().isValid() && Range.getEnd().isValid() && + "Invalid range in the fix-it hint."); + assert(Range.getBegin().isFileID() && Range.getEnd().isFileID() && + "Only file locations supported in fix-it hints."); + + Error.Fix.insert(tooling::Replacement(SM, Range, FixIt.CodeToInsert)); + } + } + + void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, + const SourceManager &SM) override {} + + void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, + StringRef ModuleName, + const SourceManager &SM) override {} + + void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, + StringRef ModuleName, + const SourceManager &SM) override {} + + void endDiagnostic(DiagOrStoredDiag D, + DiagnosticsEngine::Level Level) override { + assert(!Error.Message.Message.empty() && "Message has not been set"); + } + +private: + ClangTidyError &Error; +}; + ClangTidyMessage::ClangTidyMessage(StringRef Message) : Message(Message) {} ClangTidyMessage::ClangTidyMessage(StringRef Message, const SourceManager &Sources, SourceLocation Loc) : Message(Message) { + assert(Loc.isValid() && Loc.isFileID()); FilePath = Sources.getFilename(Loc); FileOffset = Sources.getFileOffset(Loc); } -ClangTidyError::ClangTidyError(StringRef CheckName, - const ClangTidyMessage &Message) - : CheckName(CheckName), Message(Message) {} +ClangTidyError::ClangTidyError(StringRef CheckName) + : CheckName(CheckName) {} DiagnosticBuilder ClangTidyContext::diag( StringRef CheckName, SourceLocation Loc, StringRef Description, @@ -100,17 +174,27 @@ void ClangTidyDiagnosticConsumer::finali void ClangTidyDiagnosticConsumer::HandleDiagnostic( DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) { - // FIXME: Deduplicate diagnostics. if (DiagLevel == DiagnosticsEngine::Note) { assert(!Errors.empty() && "A diagnostic note can only be appended to a message."); - Errors.back().Notes.push_back(getMessage(Info)); } else { finalizeLastError(); - Errors.push_back( - ClangTidyError(Context.getCheckName(Info.getID()), getMessage(Info))); + Errors.push_back(ClangTidyError(Context.getCheckName(Info.getID()))); } - addFixes(Info, Errors.back()); + + // FIXME: Provide correct LangOptions for each file. + LangOptions LangOpts; + ClangTidyDiagnosticRenderer Converter( + LangOpts, &Context.DiagEngine->getDiagnosticOptions(), Errors.back()); + SmallString<100> Message; + Info.FormatDiagnostic(Message); + SourceManager *Sources = nullptr; + if (Info.hasSourceManager()) + Sources = &Info.getSourceManager(); + Converter.emitDiagnostic( + Info.getLocation(), DiagLevel, Message, Info.getRanges(), + llvm::makeArrayRef(Info.getFixItHints(), Info.getNumFixItHints()), + Sources); // Let argument parsing-related warnings through. if (!Info.getLocation().isValid() || @@ -140,33 +224,5 @@ void ClangTidyDiagnosticConsumer::finish Errors.clear(); } -void ClangTidyDiagnosticConsumer::addFixes(const Diagnostic &Info, - ClangTidyError &Error) { - if (!Info.hasSourceManager()) - return; - SourceManager &Sources = Info.getSourceManager(); - tooling::Replacements Replacements; - for (unsigned i = 0, e = Info.getNumFixItHints(); i != e; ++i) { - CharSourceRange Range = Info.getFixItHint(i).RemoveRange; - assert(Range.getBegin().isValid() && Range.getEnd().isValid() && - "Invalid range in the fix-it hint."); - assert(Range.getBegin().isFileID() && Range.getEnd().isFileID() && - "Only file locations supported in fix-it hints."); - std::string Text = Info.getFixItHint(i).CodeToInsert; - Error.Fix.insert(tooling::Replacement(Sources, Range, Text)); - } -} - -ClangTidyMessage -ClangTidyDiagnosticConsumer::getMessage(const Diagnostic &Info) const { - SmallString<100> Buf; - Info.FormatDiagnostic(Buf); - if (!Info.hasSourceManager()) { - return ClangTidyMessage(Buf.str()); - } - return ClangTidyMessage(Buf.str(), Info.getSourceManager(), - Info.getLocation()); -} - } // namespace tidy } // namespace clang Modified: clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h?rev=203457&r1=203456&r2=203457&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h (original) +++ clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h Mon Mar 10 08:11:17 2014 @@ -47,7 +47,7 @@ struct ClangTidyMessage { /// /// FIXME: Make Diagnostics flexible enough to support this directly. struct ClangTidyError { - ClangTidyError(StringRef CheckName, const ClangTidyMessage &Message); + ClangTidyError(StringRef CheckName); std::string CheckName; ClangTidyMessage Message; @@ -123,8 +123,6 @@ public: void finish() override; private: - void addFixes(const Diagnostic &Info, ClangTidyError &Error); - ClangTidyMessage getMessage(const Diagnostic &Info) const; void finalizeLastError(); ClangTidyContext &Context; Added: clang-tools-extra/trunk/test/clang-tidy/macros.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/macros.cpp?rev=203457&view=auto ============================================================================== --- clang-tools-extra/trunk/test/clang-tidy/macros.cpp (added) +++ clang-tools-extra/trunk/test/clang-tidy/macros.cpp Mon Mar 10 08:11:17 2014 @@ -0,0 +1,7 @@ +// RUN: clang-tidy -checks=google-explicit-constructor %s -- | FileCheck %s + +#define Q(name) class name { name(int i); } + +Q(A); +// CHECK: :[[@LINE-1]]:3: warning: Single-argument constructors must be explicit [google-explicit-constructor] +// CHECK: :3:30: note: expanded from macro 'Q' _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
