Change EOL style to LF. NFC
authorAlexander Kornienko <alexfh@google.com>
Tue, 9 May 2017 14:56:28 +0000 (14:56 +0000)
committerAlexander Kornienko <alexfh@google.com>
Tue, 9 May 2017 14:56:28 +0000 (14:56 +0000)
llvm-svn: 302534

clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
clang-tools-extra/clang-tidy/misc/ForwardingReferenceOverloadCheck.cpp
clang-tools-extra/test/clang-tidy/misc-non-copyable-objects.c
clang-tools-extra/test/clang-tidy/misc-static-assert.c
clang-tools-extra/test/clang-tidy/misc-undelegated-constructor-cxx98.cpp

index c4a5ede..c4ab236 100644 (file)
-//===--- tools/extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp ----------=== //\r
-//\r
-//                     The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-///\r
-///  \file This file implements ClangTidyDiagnosticConsumer, ClangTidyContext\r
-///  and ClangTidyError classes.\r
-///\r
-///  This tool uses the Clang Tooling infrastructure, see\r
-///    http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html\r
-///  for details on setting it up with LLVM source tree.\r
-///\r
-//===----------------------------------------------------------------------===//\r
-\r
-#include "ClangTidyDiagnosticConsumer.h"\r
-#include "ClangTidyOptions.h"\r
-#include "clang/AST/ASTDiagnostic.h"\r
-#include "clang/Basic/DiagnosticOptions.h"\r
-#include "clang/Frontend/DiagnosticRenderer.h"\r
-#include "llvm/ADT/SmallString.h"\r
-#include <tuple>\r
-#include <vector>\r
-using namespace clang;\r
-using namespace tidy;\r
-\r
-namespace {\r
-class ClangTidyDiagnosticRenderer : public DiagnosticRenderer {\r
-public:\r
-  ClangTidyDiagnosticRenderer(const LangOptions &LangOpts,\r
-                              DiagnosticOptions *DiagOpts,\r
-                              ClangTidyError &Error)\r
-      : DiagnosticRenderer(LangOpts, DiagOpts), Error(Error) {}\r
-\r
-protected:\r
-  void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,\r
-                             DiagnosticsEngine::Level Level, StringRef Message,\r
-                             ArrayRef<CharSourceRange> Ranges,\r
-                             const SourceManager *SM,\r
-                             DiagOrStoredDiag Info) override {\r
-    // Remove check name from the message.\r
-    // FIXME: Remove this once there's a better way to pass check names than\r
-    // appending the check name to the message in ClangTidyContext::diag and\r
-    // using getCustomDiagID.\r
-    std::string CheckNameInMessage = " [" + Error.DiagnosticName + "]";\r
-    if (Message.endswith(CheckNameInMessage))\r
-      Message = Message.substr(0, Message.size() - CheckNameInMessage.size());\r
-\r
-    auto TidyMessage = Loc.isValid()\r
-                           ? tooling::DiagnosticMessage(Message, *SM, Loc)\r
-                           : tooling::DiagnosticMessage(Message);\r
-    if (Level == DiagnosticsEngine::Note) {\r
-      Error.Notes.push_back(TidyMessage);\r
-      return;\r
-    }\r
-    assert(Error.Message.Message.empty() && "Overwriting a diagnostic message");\r
-    Error.Message = TidyMessage;\r
-  }\r
-\r
-  void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,\r
-                         DiagnosticsEngine::Level Level,\r
-                         ArrayRef<CharSourceRange> Ranges,\r
-                         const SourceManager &SM) override {}\r
-\r
-  void emitCodeContext(SourceLocation Loc, DiagnosticsEngine::Level Level,\r
-                       SmallVectorImpl<CharSourceRange> &Ranges,\r
-                       ArrayRef<FixItHint> Hints,\r
-                       const SourceManager &SM) override {\r
-    assert(Loc.isValid());\r
-    for (const auto &FixIt : Hints) {\r
-      CharSourceRange Range = FixIt.RemoveRange;\r
-      assert(Range.getBegin().isValid() && Range.getEnd().isValid() &&\r
-             "Invalid range in the fix-it hint.");\r
-      assert(Range.getBegin().isFileID() && Range.getEnd().isFileID() &&\r
-             "Only file locations supported in fix-it hints.");\r
-\r
-      tooling::Replacement Replacement(SM, Range, FixIt.CodeToInsert);\r
-      llvm::Error Err = Error.Fix[Replacement.getFilePath()].add(Replacement);\r
-      // FIXME: better error handling (at least, don't let other replacements be\r
-      // applied).\r
-      if (Err) {\r
-        llvm::errs() << "Fix conflicts with existing fix! "\r
-                     << llvm::toString(std::move(Err)) << "\n";\r
-        assert(false && "Fix conflicts with existing fix!");\r
-      }\r
-    }\r
-  }\r
-\r
-  void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,\r
-                           const SourceManager &SM) override {}\r
-\r
-  void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,\r
-                          StringRef ModuleName,\r
-                          const SourceManager &SM) override {}\r
-\r
-  void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,\r
-                                  StringRef ModuleName,\r
-                                  const SourceManager &SM) override {}\r
-\r
-  void endDiagnostic(DiagOrStoredDiag D,\r
-                     DiagnosticsEngine::Level Level) override {\r
-    assert(!Error.Message.Message.empty() && "Message has not been set");\r
-  }\r
-\r
-private:\r
-  ClangTidyError &Error;\r
-};\r
-} // end anonymous namespace\r
-\r
-ClangTidyError::ClangTidyError(StringRef CheckName,\r
-                               ClangTidyError::Level DiagLevel,\r
-                               StringRef BuildDirectory, bool IsWarningAsError)\r
-    : tooling::Diagnostic(CheckName, DiagLevel, BuildDirectory),\r
-      IsWarningAsError(IsWarningAsError) {}\r
-\r
-// Returns true if GlobList starts with the negative indicator ('-'), removes it\r
-// from the GlobList.\r
-static bool ConsumeNegativeIndicator(StringRef &GlobList) {\r
-  GlobList = GlobList.trim(' ');\r
-  if (GlobList.startswith("-")) {\r
-    GlobList = GlobList.substr(1);\r
-    return true;\r
-  }\r
-  return false;\r
-}\r
-// Converts first glob from the comma-separated list of globs to Regex and\r
-// removes it and the trailing comma from the GlobList.\r
-static llvm::Regex ConsumeGlob(StringRef &GlobList) {\r
-  StringRef UntrimmedGlob = GlobList.substr(0, GlobList.find(','));\r
-  StringRef Glob = UntrimmedGlob.trim(' ');\r
-  GlobList = GlobList.substr(UntrimmedGlob.size() + 1);\r
-  SmallString<128> RegexText("^");\r
-  StringRef MetaChars("()^$|*+?.[]\\{}");\r
-  for (char C : Glob) {\r
-    if (C == '*')\r
-      RegexText.push_back('.');\r
-    else if (MetaChars.find(C) != StringRef::npos)\r
-      RegexText.push_back('\\');\r
-    RegexText.push_back(C);\r
-  }\r
-  RegexText.push_back('$');\r
-  return llvm::Regex(RegexText);\r
-}\r
-\r
-GlobList::GlobList(StringRef Globs)\r
-    : Positive(!ConsumeNegativeIndicator(Globs)), Regex(ConsumeGlob(Globs)),\r
-      NextGlob(Globs.empty() ? nullptr : new GlobList(Globs)) {}\r
-\r
-bool GlobList::contains(StringRef S, bool Contains) {\r
-  if (Regex.match(S))\r
-    Contains = Positive;\r
-\r
-  if (NextGlob)\r
-    Contains = NextGlob->contains(S, Contains);\r
-  return Contains;\r
-}\r
-\r
-ClangTidyContext::ClangTidyContext(\r
-    std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider)\r
-    : DiagEngine(nullptr), OptionsProvider(std::move(OptionsProvider)),\r
-      Profile(nullptr) {\r
-  // Before the first translation unit we can get errors related to command-line\r
-  // parsing, use empty string for the file name in this case.\r
-  setCurrentFile("");\r
-}\r
-\r
-DiagnosticBuilder ClangTidyContext::diag(\r
-    StringRef CheckName, SourceLocation Loc, StringRef Description,\r
-    DiagnosticIDs::Level Level /* = DiagnosticIDs::Warning*/) {\r
-  assert(Loc.isValid());\r
-  unsigned ID = DiagEngine->getDiagnosticIDs()->getCustomDiagID(\r
-      Level, (Description + " [" + CheckName + "]").str());\r
-  CheckNamesByDiagnosticID.try_emplace(ID, CheckName);\r
-  return DiagEngine->Report(Loc, ID);\r
-}\r
-\r
-void ClangTidyContext::setDiagnosticsEngine(DiagnosticsEngine *Engine) {\r
-  DiagEngine = Engine;\r
-}\r
-\r
-void ClangTidyContext::setSourceManager(SourceManager *SourceMgr) {\r
-  DiagEngine->setSourceManager(SourceMgr);\r
-}\r
-\r
-void ClangTidyContext::setCurrentFile(StringRef File) {\r
-  CurrentFile = File;\r
-  CurrentOptions = getOptionsForFile(CurrentFile);\r
-  CheckFilter.reset(new GlobList(*getOptions().Checks));\r
-  WarningAsErrorFilter.reset(new GlobList(*getOptions().WarningsAsErrors));\r
-}\r
-\r
-void ClangTidyContext::setASTContext(ASTContext *Context) {\r
-  DiagEngine->SetArgToStringFn(&FormatASTNodeDiagnosticArgument, Context);\r
-  LangOpts = Context->getLangOpts();\r
-}\r
-\r
-const ClangTidyGlobalOptions &ClangTidyContext::getGlobalOptions() const {\r
-  return OptionsProvider->getGlobalOptions();\r
-}\r
-\r
-const ClangTidyOptions &ClangTidyContext::getOptions() const {\r
-  return CurrentOptions;\r
-}\r
-\r
-ClangTidyOptions ClangTidyContext::getOptionsForFile(StringRef File) const {\r
-  // Merge options on top of getDefaults() as a safeguard against options with\r
-  // unset values.\r
-  return ClangTidyOptions::getDefaults().mergeWith(\r
-      OptionsProvider->getOptions(File));\r
-}\r
-\r
-void ClangTidyContext::setCheckProfileData(ProfileData *P) { Profile = P; }\r
-\r
-GlobList &ClangTidyContext::getChecksFilter() {\r
-  assert(CheckFilter != nullptr);\r
-  return *CheckFilter;\r
-}\r
-\r
-GlobList &ClangTidyContext::getWarningAsErrorFilter() {\r
-  assert(WarningAsErrorFilter != nullptr);\r
-  return *WarningAsErrorFilter;\r
-}\r
-\r
-/// \brief Store a \c ClangTidyError.\r
-void ClangTidyContext::storeError(const ClangTidyError &Error) {\r
-  Errors.push_back(Error);\r
-}\r
-\r
-StringRef ClangTidyContext::getCheckName(unsigned DiagnosticID) const {\r
-  llvm::DenseMap<unsigned, std::string>::const_iterator I =\r
-      CheckNamesByDiagnosticID.find(DiagnosticID);\r
-  if (I != CheckNamesByDiagnosticID.end())\r
-    return I->second;\r
-  return "";\r
-}\r
-\r
-ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx)\r
-    : Context(Ctx), LastErrorRelatesToUserCode(false),\r
-      LastErrorPassesLineFilter(false), LastErrorWasIgnored(false) {\r
-  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();\r
-  Diags.reset(new DiagnosticsEngine(\r
-      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), &*DiagOpts, this,\r
-      /*ShouldOwnClient=*/false));\r
-  Context.setDiagnosticsEngine(Diags.get());\r
-}\r
-\r
-void ClangTidyDiagnosticConsumer::finalizeLastError() {\r
-  if (!Errors.empty()) {\r
-    ClangTidyError &Error = Errors.back();\r
-    if (!Context.getChecksFilter().contains(Error.DiagnosticName) &&\r
-        Error.DiagLevel != ClangTidyError::Error) {\r
-      ++Context.Stats.ErrorsIgnoredCheckFilter;\r
-      Errors.pop_back();\r
-    } else if (!LastErrorRelatesToUserCode) {\r
-      ++Context.Stats.ErrorsIgnoredNonUserCode;\r
-      Errors.pop_back();\r
-    } else if (!LastErrorPassesLineFilter) {\r
-      ++Context.Stats.ErrorsIgnoredLineFilter;\r
-      Errors.pop_back();\r
-    } else {\r
-      ++Context.Stats.ErrorsDisplayed;\r
-    }\r
-  }\r
-  LastErrorRelatesToUserCode = false;\r
-  LastErrorPassesLineFilter = false;\r
-}\r
-\r
-static bool LineIsMarkedWithNOLINT(SourceManager &SM, SourceLocation Loc) {\r
-  bool Invalid;\r
-  const char *CharacterData = SM.getCharacterData(Loc, &Invalid);\r
-  if (Invalid)\r
-    return false;\r
-\r
-  // Check if there's a NOLINT on this line.\r
-  const char *P = CharacterData;\r
-  while (*P != '\0' && *P != '\r' && *P != '\n')\r
-    ++P;\r
-  StringRef RestOfLine(CharacterData, P - CharacterData + 1);\r
-  // FIXME: Handle /\bNOLINT\b(\([^)]*\))?/ as cpplint.py does.\r
-  if (RestOfLine.find("NOLINT") != StringRef::npos)\r
-    return true;\r
-\r
-  // Check if there's a NOLINTNEXTLINE on the previous line.\r
-  const char *BufBegin =\r
-      SM.getCharacterData(SM.getLocForStartOfFile(SM.getFileID(Loc)), &Invalid);\r
-  if (Invalid || P == BufBegin)\r
-    return false;\r
-\r
-  // Scan backwards over the current line.\r
-  P = CharacterData;\r
-  while (P != BufBegin && *P != '\n')\r
-    --P;\r
-\r
-  // If we reached the begin of the file there is no line before it.\r
-  if (P == BufBegin)\r
-    return false;\r
-\r
-  // Skip over the newline.\r
-  --P;\r
-  const char *LineEnd = P;\r
-\r
-  // Now we're on the previous line. Skip to the beginning of it.\r
-  while (P != BufBegin && *P != '\n')\r
-    --P;\r
-\r
-  RestOfLine = StringRef(P, LineEnd - P + 1);\r
-  if (RestOfLine.find("NOLINTNEXTLINE") != StringRef::npos)\r
-    return true;\r
-\r
-  return false;\r
-}\r
-\r
-static bool LineIsMarkedWithNOLINTinMacro(SourceManager &SM,\r
-                                          SourceLocation Loc) {\r
-  while (true) {\r
-    if (LineIsMarkedWithNOLINT(SM, Loc))\r
-      return true;\r
-    if (!Loc.isMacroID())\r
-      return false;\r
-    Loc = SM.getImmediateExpansionRange(Loc).first;\r
-  }\r
-  return false;\r
-}\r
-\r
-void ClangTidyDiagnosticConsumer::HandleDiagnostic(\r
-    DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {\r
-  if (LastErrorWasIgnored && DiagLevel == DiagnosticsEngine::Note)\r
-    return;\r
-\r
-  if (Info.getLocation().isValid() && DiagLevel != DiagnosticsEngine::Error &&\r
-      DiagLevel != DiagnosticsEngine::Fatal &&\r
-      LineIsMarkedWithNOLINTinMacro(Diags->getSourceManager(),\r
-                                    Info.getLocation())) {\r
-    ++Context.Stats.ErrorsIgnoredNOLINT;\r
-    // Ignored a warning, should ignore related notes as well\r
-    LastErrorWasIgnored = true;\r
-    return;\r
-  }\r
-\r
-  LastErrorWasIgnored = false;\r
-  // Count warnings/errors.\r
-  DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);\r
-\r
-  if (DiagLevel == DiagnosticsEngine::Note) {\r
-    assert(!Errors.empty() &&\r
-           "A diagnostic note can only be appended to a message.");\r
-  } else {\r
-    finalizeLastError();\r
-    StringRef WarningOption =\r
-        Context.DiagEngine->getDiagnosticIDs()->getWarningOptionForDiag(\r
-            Info.getID());\r
-    std::string CheckName = !WarningOption.empty()\r
-                                ? ("clang-diagnostic-" + WarningOption).str()\r
-                                : Context.getCheckName(Info.getID()).str();\r
-\r
-    if (CheckName.empty()) {\r
-      // This is a compiler diagnostic without a warning option. Assign check\r
-      // name based on its level.\r
-      switch (DiagLevel) {\r
-      case DiagnosticsEngine::Error:\r
-      case DiagnosticsEngine::Fatal:\r
-        CheckName = "clang-diagnostic-error";\r
-        break;\r
-      case DiagnosticsEngine::Warning:\r
-        CheckName = "clang-diagnostic-warning";\r
-        break;\r
-      default:\r
-        CheckName = "clang-diagnostic-unknown";\r
-        break;\r
-      }\r
-    }\r
-\r
-    ClangTidyError::Level Level = ClangTidyError::Warning;\r
-    if (DiagLevel == DiagnosticsEngine::Error ||\r
-        DiagLevel == DiagnosticsEngine::Fatal) {\r
-      // Force reporting of Clang errors regardless of filters and non-user\r
-      // code.\r
-      Level = ClangTidyError::Error;\r
-      LastErrorRelatesToUserCode = true;\r
-      LastErrorPassesLineFilter = true;\r
-    }\r
-    bool IsWarningAsError =\r
-        DiagLevel == DiagnosticsEngine::Warning &&\r
-        Context.getWarningAsErrorFilter().contains(CheckName);\r
-    Errors.emplace_back(CheckName, Level, Context.getCurrentBuildDirectory(),\r
-                        IsWarningAsError);\r
-  }\r
-\r
-  ClangTidyDiagnosticRenderer Converter(\r
-      Context.getLangOpts(), &Context.DiagEngine->getDiagnosticOptions(),\r
-      Errors.back());\r
-  SmallString<100> Message;\r
-  Info.FormatDiagnostic(Message);\r
-  SourceManager *Sources = nullptr;\r
-  if (Info.hasSourceManager())\r
-    Sources = &Info.getSourceManager();\r
-  Converter.emitDiagnostic(Info.getLocation(), DiagLevel, Message,\r
-                           Info.getRanges(), Info.getFixItHints(), Sources);\r
-\r
-  checkFilters(Info.getLocation());\r
-}\r
-\r
-bool ClangTidyDiagnosticConsumer::passesLineFilter(StringRef FileName,\r
-                                                   unsigned LineNumber) const {\r
-  if (Context.getGlobalOptions().LineFilter.empty())\r
-    return true;\r
-  for (const FileFilter &Filter : Context.getGlobalOptions().LineFilter) {\r
-    if (FileName.endswith(Filter.Name)) {\r
-      if (Filter.LineRanges.empty())\r
-        return true;\r
-      for (const FileFilter::LineRange &Range : Filter.LineRanges) {\r
-        if (Range.first <= LineNumber && LineNumber <= Range.second)\r
-          return true;\r
-      }\r
-      return false;\r
-    }\r
-  }\r
-  return false;\r
-}\r
-\r
-void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location) {\r
-  // Invalid location may mean a diagnostic in a command line, don't skip these.\r
-  if (!Location.isValid()) {\r
-    LastErrorRelatesToUserCode = true;\r
-    LastErrorPassesLineFilter = true;\r
-    return;\r
-  }\r
-\r
-  const SourceManager &Sources = Diags->getSourceManager();\r
-  if (!*Context.getOptions().SystemHeaders &&\r
-      Sources.isInSystemHeader(Location))\r
-    return;\r
-\r
-  // FIXME: We start with a conservative approach here, but the actual type of\r
-  // location needed depends on the check (in particular, where this check wants\r
-  // to apply fixes).\r
-  FileID FID = Sources.getDecomposedExpansionLoc(Location).first;\r
-  const FileEntry *File = Sources.getFileEntryForID(FID);\r
-\r
-  // -DMACRO definitions on the command line have locations in a virtual buffer\r
-  // that doesn't have a FileEntry. Don't skip these as well.\r
-  if (!File) {\r
-    LastErrorRelatesToUserCode = true;\r
-    LastErrorPassesLineFilter = true;\r
-    return;\r
-  }\r
-\r
-  StringRef FileName(File->getName());\r
-  LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||\r
-                               Sources.isInMainFile(Location) ||\r
-                               getHeaderFilter()->match(FileName);\r
-\r
-  unsigned LineNumber = Sources.getExpansionLineNumber(Location);\r
-  LastErrorPassesLineFilter =\r
-      LastErrorPassesLineFilter || passesLineFilter(FileName, LineNumber);\r
-}\r
-\r
-llvm::Regex *ClangTidyDiagnosticConsumer::getHeaderFilter() {\r
-  if (!HeaderFilter)\r
-    HeaderFilter.reset(\r
-        new llvm::Regex(*Context.getOptions().HeaderFilterRegex));\r
-  return HeaderFilter.get();\r
-}\r
-\r
-void ClangTidyDiagnosticConsumer::removeIncompatibleErrors(\r
-    SmallVectorImpl<ClangTidyError> &Errors) const {\r
-  // Each error is modelled as the set of intervals in which it applies\r
-  // replacements. To detect overlapping replacements, we use a sweep line\r
-  // algorithm over these sets of intervals.\r
-  // An event here consists of the opening or closing of an interval. During the\r
-  // process, we maintain a counter with the amount of open intervals. If we\r
-  // find an endpoint of an interval and this counter is different from 0, it\r
-  // means that this interval overlaps with another one, so we set it as\r
-  // inapplicable.\r
-  struct Event {\r
-    // An event can be either the begin or the end of an interval.\r
-    enum EventType {\r
-      ET_Begin = 1,\r
-      ET_End = -1,\r
-    };\r
-\r
-    Event(unsigned Begin, unsigned End, EventType Type, unsigned ErrorId,\r
-          unsigned ErrorSize)\r
-        : Type(Type), ErrorId(ErrorId) {\r
-      // The events are going to be sorted by their position. In case of draw:\r
-      //\r
-      // * If an interval ends at the same position at which other interval\r
-      //   begins, this is not an overlapping, so we want to remove the ending\r
-      //   interval before adding the starting one: end events have higher\r
-      //   priority than begin events.\r
-      //\r
-      // * If we have several begin points at the same position, we will mark as\r
-      //   inapplicable the ones that we process later, so the first one has to\r
-      //   be the one with the latest end point, because this one will contain\r
-      //   all the other intervals. For the same reason, if we have several end\r
-      //   points in the same position, the last one has to be the one with the\r
-      //   earliest begin point. In both cases, we sort non-increasingly by the\r
-      //   position of the complementary.\r
-      //\r
-      // * In case of two equal intervals, the one whose error is bigger can\r
-      //   potentially contain the other one, so we want to process its begin\r
-      //   points before and its end points later.\r
-      //\r
-      // * Finally, if we have two equal intervals whose errors have the same\r
-      //   size, none of them will be strictly contained inside the other.\r
-      //   Sorting by ErrorId will guarantee that the begin point of the first\r
-      //   one will be processed before, disallowing the second one, and the\r
-      //   end point of the first one will also be processed before,\r
-      //   disallowing the first one.\r
-      if (Type == ET_Begin)\r
-        Priority = std::make_tuple(Begin, Type, -End, -ErrorSize, ErrorId);\r
-      else\r
-        Priority = std::make_tuple(End, Type, -Begin, ErrorSize, ErrorId);\r
-    }\r
-\r
-    bool operator<(const Event &Other) const {\r
-      return Priority < Other.Priority;\r
-    }\r
-\r
-    // Determines if this event is the begin or the end of an interval.\r
-    EventType Type;\r
-    // The index of the error to which the interval that generated this event\r
-    // belongs.\r
-    unsigned ErrorId;\r
-    // The events will be sorted based on this field.\r
-    std::tuple<unsigned, EventType, int, int, unsigned> Priority;\r
-  };\r
-\r
-  // Compute error sizes.\r
-  std::vector<int> Sizes;\r
-  for (const auto &Error : Errors) {\r
-    int Size = 0;\r
-    for (const auto &FileAndReplaces : Error.Fix) {\r
-      for (const auto &Replace : FileAndReplaces.second)\r
-        Size += Replace.getLength();\r
-    }\r
-    Sizes.push_back(Size);\r
-  }\r
-\r
-  // Build events from error intervals.\r
-  std::map<std::string, std::vector<Event>> FileEvents;\r
-  for (unsigned I = 0; I < Errors.size(); ++I) {\r
-    for (const auto &FileAndReplace : Errors[I].Fix) {\r
-      for (const auto &Replace : FileAndReplace.second) {\r
-        unsigned Begin = Replace.getOffset();\r
-        unsigned End = Begin + Replace.getLength();\r
-        const std::string &FilePath = Replace.getFilePath();\r
-        // FIXME: Handle empty intervals, such as those from insertions.\r
-        if (Begin == End)\r
-          continue;\r
-        auto &Events = FileEvents[FilePath];\r
-        Events.emplace_back(Begin, End, Event::ET_Begin, I, Sizes[I]);\r
-        Events.emplace_back(Begin, End, Event::ET_End, I, Sizes[I]);\r
-      }\r
-    }\r
-  }\r
-\r
-  std::vector<bool> Apply(Errors.size(), true);\r
-  for (auto &FileAndEvents : FileEvents) {\r
-    std::vector<Event> &Events = FileAndEvents.second;\r
-    // Sweep.\r
-    std::sort(Events.begin(), Events.end());\r
-    int OpenIntervals = 0;\r
-    for (const auto &Event : Events) {\r
-      if (Event.Type == Event::ET_End)\r
-        --OpenIntervals;\r
-      // This has to be checked after removing the interval from the count if it\r
-      // is an end event, or before adding it if it is a begin event.\r
-      if (OpenIntervals != 0)\r
-        Apply[Event.ErrorId] = false;\r
-      if (Event.Type == Event::ET_Begin)\r
-        ++OpenIntervals;\r
-    }\r
-    assert(OpenIntervals == 0 && "Amount of begin/end points doesn't match");\r
-  }\r
-\r
-  for (unsigned I = 0; I < Errors.size(); ++I) {\r
-    if (!Apply[I]) {\r
-      Errors[I].Fix.clear();\r
-      Errors[I].Notes.emplace_back(\r
-          "this fix will not be applied because it overlaps with another fix");\r
-    }\r
-  }\r
-}\r
-\r
-namespace {\r
-struct LessClangTidyError {\r
-  bool operator()(const ClangTidyError &LHS, const ClangTidyError &RHS) const {\r
-    const tooling::DiagnosticMessage &M1 = LHS.Message;\r
-    const tooling::DiagnosticMessage &M2 = RHS.Message;\r
-\r
-    return std::tie(M1.FilePath, M1.FileOffset, M1.Message) <\r
-           std::tie(M2.FilePath, M2.FileOffset, M2.Message);\r
-  }\r
-};\r
-struct EqualClangTidyError {\r
-  bool operator()(const ClangTidyError &LHS, const ClangTidyError &RHS) const {\r
-    LessClangTidyError Less;\r
-    return !Less(LHS, RHS) && !Less(RHS, LHS);\r
-  }\r
-};\r
-} // end anonymous namespace\r
-\r
-// Flushes the internal diagnostics buffer to the ClangTidyContext.\r
-void ClangTidyDiagnosticConsumer::finish() {\r
-  finalizeLastError();\r
-\r
-  std::sort(Errors.begin(), Errors.end(), LessClangTidyError());\r
-  Errors.erase(std::unique(Errors.begin(), Errors.end(), EqualClangTidyError()),\r
-               Errors.end());\r
-  removeIncompatibleErrors(Errors);\r
-\r
-  for (const ClangTidyError &Error : Errors)\r
-    Context.storeError(Error);\r
-  Errors.clear();\r
-}\r
+//===--- tools/extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp ----------=== //
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+///  \file This file implements ClangTidyDiagnosticConsumer, ClangTidyContext
+///  and ClangTidyError classes.
+///
+///  This tool uses the Clang Tooling infrastructure, see
+///    http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
+///  for details on setting it up with LLVM source tree.
+///
+//===----------------------------------------------------------------------===//
+
+#include "ClangTidyDiagnosticConsumer.h"
+#include "ClangTidyOptions.h"
+#include "clang/AST/ASTDiagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Frontend/DiagnosticRenderer.h"
+#include "llvm/ADT/SmallString.h"
+#include <tuple>
+#include <vector>
+using namespace clang;
+using namespace tidy;
+
+namespace {
+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 {
+    // Remove check name from the message.
+    // FIXME: Remove this once there's a better way to pass check names than
+    // appending the check name to the message in ClangTidyContext::diag and
+    // using getCustomDiagID.
+    std::string CheckNameInMessage = " [" + Error.DiagnosticName + "]";
+    if (Message.endswith(CheckNameInMessage))
+      Message = Message.substr(0, Message.size() - CheckNameInMessage.size());
+
+    auto TidyMessage = Loc.isValid()
+                           ? tooling::DiagnosticMessage(Message, *SM, Loc)
+                           : tooling::DiagnosticMessage(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 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.");
+
+      tooling::Replacement Replacement(SM, Range, FixIt.CodeToInsert);
+      llvm::Error Err = Error.Fix[Replacement.getFilePath()].add(Replacement);
+      // FIXME: better error handling (at least, don't let other replacements be
+      // applied).
+      if (Err) {
+        llvm::errs() << "Fix conflicts with existing fix! "
+                     << llvm::toString(std::move(Err)) << "\n";
+        assert(false && "Fix conflicts with existing fix!");
+      }
+    }
+  }
+
+  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;
+};
+} // end anonymous namespace
+
+ClangTidyError::ClangTidyError(StringRef CheckName,
+                               ClangTidyError::Level DiagLevel,
+                               StringRef BuildDirectory, bool IsWarningAsError)
+    : tooling::Diagnostic(CheckName, DiagLevel, BuildDirectory),
+      IsWarningAsError(IsWarningAsError) {}
+
+// Returns true if GlobList starts with the negative indicator ('-'), removes it
+// from the GlobList.
+static bool ConsumeNegativeIndicator(StringRef &GlobList) {
+  GlobList = GlobList.trim(' ');
+  if (GlobList.startswith("-")) {
+    GlobList = GlobList.substr(1);
+    return true;
+  }
+  return false;
+}
+// Converts first glob from the comma-separated list of globs to Regex and
+// removes it and the trailing comma from the GlobList.
+static llvm::Regex ConsumeGlob(StringRef &GlobList) {
+  StringRef UntrimmedGlob = GlobList.substr(0, GlobList.find(','));
+  StringRef Glob = UntrimmedGlob.trim(' ');
+  GlobList = GlobList.substr(UntrimmedGlob.size() + 1);
+  SmallString<128> RegexText("^");
+  StringRef MetaChars("()^$|*+?.[]\\{}");
+  for (char C : Glob) {
+    if (C == '*')
+      RegexText.push_back('.');
+    else if (MetaChars.find(C) != StringRef::npos)
+      RegexText.push_back('\\');
+    RegexText.push_back(C);
+  }
+  RegexText.push_back('$');
+  return llvm::Regex(RegexText);
+}
+
+GlobList::GlobList(StringRef Globs)
+    : Positive(!ConsumeNegativeIndicator(Globs)), Regex(ConsumeGlob(Globs)),
+      NextGlob(Globs.empty() ? nullptr : new GlobList(Globs)) {}
+
+bool GlobList::contains(StringRef S, bool Contains) {
+  if (Regex.match(S))
+    Contains = Positive;
+
+  if (NextGlob)
+    Contains = NextGlob->contains(S, Contains);
+  return Contains;
+}
+
+ClangTidyContext::ClangTidyContext(
+    std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider)
+    : DiagEngine(nullptr), OptionsProvider(std::move(OptionsProvider)),
+      Profile(nullptr) {
+  // Before the first translation unit we can get errors related to command-line
+  // parsing, use empty string for the file name in this case.
+  setCurrentFile("");
+}
+
+DiagnosticBuilder ClangTidyContext::diag(
+    StringRef CheckName, SourceLocation Loc, StringRef Description,
+    DiagnosticIDs::Level Level /* = DiagnosticIDs::Warning*/) {
+  assert(Loc.isValid());
+  unsigned ID = DiagEngine->getDiagnosticIDs()->getCustomDiagID(
+      Level, (Description + " [" + CheckName + "]").str());
+  CheckNamesByDiagnosticID.try_emplace(ID, CheckName);
+  return DiagEngine->Report(Loc, ID);
+}
+
+void ClangTidyContext::setDiagnosticsEngine(DiagnosticsEngine *Engine) {
+  DiagEngine = Engine;
+}
+
+void ClangTidyContext::setSourceManager(SourceManager *SourceMgr) {
+  DiagEngine->setSourceManager(SourceMgr);
+}
+
+void ClangTidyContext::setCurrentFile(StringRef File) {
+  CurrentFile = File;
+  CurrentOptions = getOptionsForFile(CurrentFile);
+  CheckFilter.reset(new GlobList(*getOptions().Checks));
+  WarningAsErrorFilter.reset(new GlobList(*getOptions().WarningsAsErrors));
+}
+
+void ClangTidyContext::setASTContext(ASTContext *Context) {
+  DiagEngine->SetArgToStringFn(&FormatASTNodeDiagnosticArgument, Context);
+  LangOpts = Context->getLangOpts();
+}
+
+const ClangTidyGlobalOptions &ClangTidyContext::getGlobalOptions() const {
+  return OptionsProvider->getGlobalOptions();
+}
+
+const ClangTidyOptions &ClangTidyContext::getOptions() const {
+  return CurrentOptions;
+}
+
+ClangTidyOptions ClangTidyContext::getOptionsForFile(StringRef File) const {
+  // Merge options on top of getDefaults() as a safeguard against options with
+  // unset values.
+  return ClangTidyOptions::getDefaults().mergeWith(
+      OptionsProvider->getOptions(File));
+}
+
+void ClangTidyContext::setCheckProfileData(ProfileData *P) { Profile = P; }
+
+GlobList &ClangTidyContext::getChecksFilter() {
+  assert(CheckFilter != nullptr);
+  return *CheckFilter;
+}
+
+GlobList &ClangTidyContext::getWarningAsErrorFilter() {
+  assert(WarningAsErrorFilter != nullptr);
+  return *WarningAsErrorFilter;
+}
+
+/// \brief Store a \c ClangTidyError.
+void ClangTidyContext::storeError(const ClangTidyError &Error) {
+  Errors.push_back(Error);
+}
+
+StringRef ClangTidyContext::getCheckName(unsigned DiagnosticID) const {
+  llvm::DenseMap<unsigned, std::string>::const_iterator I =
+      CheckNamesByDiagnosticID.find(DiagnosticID);
+  if (I != CheckNamesByDiagnosticID.end())
+    return I->second;
+  return "";
+}
+
+ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx)
+    : Context(Ctx), LastErrorRelatesToUserCode(false),
+      LastErrorPassesLineFilter(false), LastErrorWasIgnored(false) {
+  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+  Diags.reset(new DiagnosticsEngine(
+      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), &*DiagOpts, this,
+      /*ShouldOwnClient=*/false));
+  Context.setDiagnosticsEngine(Diags.get());
+}
+
+void ClangTidyDiagnosticConsumer::finalizeLastError() {
+  if (!Errors.empty()) {
+    ClangTidyError &Error = Errors.back();
+    if (!Context.getChecksFilter().contains(Error.DiagnosticName) &&
+        Error.DiagLevel != ClangTidyError::Error) {
+      ++Context.Stats.ErrorsIgnoredCheckFilter;
+      Errors.pop_back();
+    } else if (!LastErrorRelatesToUserCode) {
+      ++Context.Stats.ErrorsIgnoredNonUserCode;
+      Errors.pop_back();
+    } else if (!LastErrorPassesLineFilter) {
+      ++Context.Stats.ErrorsIgnoredLineFilter;
+      Errors.pop_back();
+    } else {
+      ++Context.Stats.ErrorsDisplayed;
+    }
+  }
+  LastErrorRelatesToUserCode = false;
+  LastErrorPassesLineFilter = false;
+}
+
+static bool LineIsMarkedWithNOLINT(SourceManager &SM, SourceLocation Loc) {
+  bool Invalid;
+  const char *CharacterData = SM.getCharacterData(Loc, &Invalid);
+  if (Invalid)
+    return false;
+
+  // Check if there's a NOLINT on this line.
+  const char *P = CharacterData;
+  while (*P != '\0' && *P != '\r' && *P != '\n')
+    ++P;
+  StringRef RestOfLine(CharacterData, P - CharacterData + 1);
+  // FIXME: Handle /\bNOLINT\b(\([^)]*\))?/ as cpplint.py does.
+  if (RestOfLine.find("NOLINT") != StringRef::npos)
+    return true;
+
+  // Check if there's a NOLINTNEXTLINE on the previous line.
+  const char *BufBegin =
+      SM.getCharacterData(SM.getLocForStartOfFile(SM.getFileID(Loc)), &Invalid);
+  if (Invalid || P == BufBegin)
+    return false;
+
+  // Scan backwards over the current line.
+  P = CharacterData;
+  while (P != BufBegin && *P != '\n')
+    --P;
+
+  // If we reached the begin of the file there is no line before it.
+  if (P == BufBegin)
+    return false;
+
+  // Skip over the newline.
+  --P;
+  const char *LineEnd = P;
+
+  // Now we're on the previous line. Skip to the beginning of it.
+  while (P != BufBegin && *P != '\n')
+    --P;
+
+  RestOfLine = StringRef(P, LineEnd - P + 1);
+  if (RestOfLine.find("NOLINTNEXTLINE") != StringRef::npos)
+    return true;
+
+  return false;
+}
+
+static bool LineIsMarkedWithNOLINTinMacro(SourceManager &SM,
+                                          SourceLocation Loc) {
+  while (true) {
+    if (LineIsMarkedWithNOLINT(SM, Loc))
+      return true;
+    if (!Loc.isMacroID())
+      return false;
+    Loc = SM.getImmediateExpansionRange(Loc).first;
+  }
+  return false;
+}
+
+void ClangTidyDiagnosticConsumer::HandleDiagnostic(
+    DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {
+  if (LastErrorWasIgnored && DiagLevel == DiagnosticsEngine::Note)
+    return;
+
+  if (Info.getLocation().isValid() && DiagLevel != DiagnosticsEngine::Error &&
+      DiagLevel != DiagnosticsEngine::Fatal &&
+      LineIsMarkedWithNOLINTinMacro(Diags->getSourceManager(),
+                                    Info.getLocation())) {
+    ++Context.Stats.ErrorsIgnoredNOLINT;
+    // Ignored a warning, should ignore related notes as well
+    LastErrorWasIgnored = true;
+    return;
+  }
+
+  LastErrorWasIgnored = false;
+  // Count warnings/errors.
+  DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
+
+  if (DiagLevel == DiagnosticsEngine::Note) {
+    assert(!Errors.empty() &&
+           "A diagnostic note can only be appended to a message.");
+  } else {
+    finalizeLastError();
+    StringRef WarningOption =
+        Context.DiagEngine->getDiagnosticIDs()->getWarningOptionForDiag(
+            Info.getID());
+    std::string CheckName = !WarningOption.empty()
+                                ? ("clang-diagnostic-" + WarningOption).str()
+                                : Context.getCheckName(Info.getID()).str();
+
+    if (CheckName.empty()) {
+      // This is a compiler diagnostic without a warning option. Assign check
+      // name based on its level.
+      switch (DiagLevel) {
+      case DiagnosticsEngine::Error:
+      case DiagnosticsEngine::Fatal:
+        CheckName = "clang-diagnostic-error";
+        break;
+      case DiagnosticsEngine::Warning:
+        CheckName = "clang-diagnostic-warning";
+        break;
+      default:
+        CheckName = "clang-diagnostic-unknown";
+        break;
+      }
+    }
+
+    ClangTidyError::Level Level = ClangTidyError::Warning;
+    if (DiagLevel == DiagnosticsEngine::Error ||
+        DiagLevel == DiagnosticsEngine::Fatal) {
+      // Force reporting of Clang errors regardless of filters and non-user
+      // code.
+      Level = ClangTidyError::Error;
+      LastErrorRelatesToUserCode = true;
+      LastErrorPassesLineFilter = true;
+    }
+    bool IsWarningAsError =
+        DiagLevel == DiagnosticsEngine::Warning &&
+        Context.getWarningAsErrorFilter().contains(CheckName);
+    Errors.emplace_back(CheckName, Level, Context.getCurrentBuildDirectory(),
+                        IsWarningAsError);
+  }
+
+  ClangTidyDiagnosticRenderer Converter(
+      Context.getLangOpts(), &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(), Info.getFixItHints(), Sources);
+
+  checkFilters(Info.getLocation());
+}
+
+bool ClangTidyDiagnosticConsumer::passesLineFilter(StringRef FileName,
+                                                   unsigned LineNumber) const {
+  if (Context.getGlobalOptions().LineFilter.empty())
+    return true;
+  for (const FileFilter &Filter : Context.getGlobalOptions().LineFilter) {
+    if (FileName.endswith(Filter.Name)) {
+      if (Filter.LineRanges.empty())
+        return true;
+      for (const FileFilter::LineRange &Range : Filter.LineRanges) {
+        if (Range.first <= LineNumber && LineNumber <= Range.second)
+          return true;
+      }
+      return false;
+    }
+  }
+  return false;
+}
+
+void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location) {
+  // Invalid location may mean a diagnostic in a command line, don't skip these.
+  if (!Location.isValid()) {
+    LastErrorRelatesToUserCode = true;
+    LastErrorPassesLineFilter = true;
+    return;
+  }
+
+  const SourceManager &Sources = Diags->getSourceManager();
+  if (!*Context.getOptions().SystemHeaders &&
+      Sources.isInSystemHeader(Location))
+    return;
+
+  // FIXME: We start with a conservative approach here, but the actual type of
+  // location needed depends on the check (in particular, where this check wants
+  // to apply fixes).
+  FileID FID = Sources.getDecomposedExpansionLoc(Location).first;
+  const FileEntry *File = Sources.getFileEntryForID(FID);
+
+  // -DMACRO definitions on the command line have locations in a virtual buffer
+  // that doesn't have a FileEntry. Don't skip these as well.
+  if (!File) {
+    LastErrorRelatesToUserCode = true;
+    LastErrorPassesLineFilter = true;
+    return;
+  }
+
+  StringRef FileName(File->getName());
+  LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
+                               Sources.isInMainFile(Location) ||
+                               getHeaderFilter()->match(FileName);
+
+  unsigned LineNumber = Sources.getExpansionLineNumber(Location);
+  LastErrorPassesLineFilter =
+      LastErrorPassesLineFilter || passesLineFilter(FileName, LineNumber);
+}
+
+llvm::Regex *ClangTidyDiagnosticConsumer::getHeaderFilter() {
+  if (!HeaderFilter)
+    HeaderFilter.reset(
+        new llvm::Regex(*Context.getOptions().HeaderFilterRegex));
+  return HeaderFilter.get();
+}
+
+void ClangTidyDiagnosticConsumer::removeIncompatibleErrors(
+    SmallVectorImpl<ClangTidyError> &Errors) const {
+  // Each error is modelled as the set of intervals in which it applies
+  // replacements. To detect overlapping replacements, we use a sweep line
+  // algorithm over these sets of intervals.
+  // An event here consists of the opening or closing of an interval. During the
+  // process, we maintain a counter with the amount of open intervals. If we
+  // find an endpoint of an interval and this counter is different from 0, it
+  // means that this interval overlaps with another one, so we set it as
+  // inapplicable.
+  struct Event {
+    // An event can be either the begin or the end of an interval.
+    enum EventType {
+      ET_Begin = 1,
+      ET_End = -1,
+    };
+
+    Event(unsigned Begin, unsigned End, EventType Type, unsigned ErrorId,
+          unsigned ErrorSize)
+        : Type(Type), ErrorId(ErrorId) {
+      // The events are going to be sorted by their position. In case of draw:
+      //
+      // * If an interval ends at the same position at which other interval
+      //   begins, this is not an overlapping, so we want to remove the ending
+      //   interval before adding the starting one: end events have higher
+      //   priority than begin events.
+      //
+      // * If we have several begin points at the same position, we will mark as
+      //   inapplicable the ones that we process later, so the first one has to
+      //   be the one with the latest end point, because this one will contain
+      //   all the other intervals. For the same reason, if we have several end
+      //   points in the same position, the last one has to be the one with the
+      //   earliest begin point. In both cases, we sort non-increasingly by the
+      //   position of the complementary.
+      //
+      // * In case of two equal intervals, the one whose error is bigger can
+      //   potentially contain the other one, so we want to process its begin
+      //   points before and its end points later.
+      //
+      // * Finally, if we have two equal intervals whose errors have the same
+      //   size, none of them will be strictly contained inside the other.
+      //   Sorting by ErrorId will guarantee that the begin point of the first
+      //   one will be processed before, disallowing the second one, and the
+      //   end point of the first one will also be processed before,
+      //   disallowing the first one.
+      if (Type == ET_Begin)
+        Priority = std::make_tuple(Begin, Type, -End, -ErrorSize, ErrorId);
+      else
+        Priority = std::make_tuple(End, Type, -Begin, ErrorSize, ErrorId);
+    }
+
+    bool operator<(const Event &Other) const {
+      return Priority < Other.Priority;
+    }
+
+    // Determines if this event is the begin or the end of an interval.
+    EventType Type;
+    // The index of the error to which the interval that generated this event
+    // belongs.
+    unsigned ErrorId;
+    // The events will be sorted based on this field.
+    std::tuple<unsigned, EventType, int, int, unsigned> Priority;
+  };
+
+  // Compute error sizes.
+  std::vector<int> Sizes;
+  for (const auto &Error : Errors) {
+    int Size = 0;
+    for (const auto &FileAndReplaces : Error.Fix) {
+      for (const auto &Replace : FileAndReplaces.second)
+        Size += Replace.getLength();
+    }
+    Sizes.push_back(Size);
+  }
+
+  // Build events from error intervals.
+  std::map<std::string, std::vector<Event>> FileEvents;
+  for (unsigned I = 0; I < Errors.size(); ++I) {
+    for (const auto &FileAndReplace : Errors[I].Fix) {
+      for (const auto &Replace : FileAndReplace.second) {
+        unsigned Begin = Replace.getOffset();
+        unsigned End = Begin + Replace.getLength();
+        const std::string &FilePath = Replace.getFilePath();
+        // FIXME: Handle empty intervals, such as those from insertions.
+        if (Begin == End)
+          continue;
+        auto &Events = FileEvents[FilePath];
+        Events.emplace_back(Begin, End, Event::ET_Begin, I, Sizes[I]);
+        Events.emplace_back(Begin, End, Event::ET_End, I, Sizes[I]);
+      }
+    }
+  }
+
+  std::vector<bool> Apply(Errors.size(), true);
+  for (auto &FileAndEvents : FileEvents) {
+    std::vector<Event> &Events = FileAndEvents.second;
+    // Sweep.
+    std::sort(Events.begin(), Events.end());
+    int OpenIntervals = 0;
+    for (const auto &Event : Events) {
+      if (Event.Type == Event::ET_End)
+        --OpenIntervals;
+      // This has to be checked after removing the interval from the count if it
+      // is an end event, or before adding it if it is a begin event.
+      if (OpenIntervals != 0)
+        Apply[Event.ErrorId] = false;
+      if (Event.Type == Event::ET_Begin)
+        ++OpenIntervals;
+    }
+    assert(OpenIntervals == 0 && "Amount of begin/end points doesn't match");
+  }
+
+  for (unsigned I = 0; I < Errors.size(); ++I) {
+    if (!Apply[I]) {
+      Errors[I].Fix.clear();
+      Errors[I].Notes.emplace_back(
+          "this fix will not be applied because it overlaps with another fix");
+    }
+  }
+}
+
+namespace {
+struct LessClangTidyError {
+  bool operator()(const ClangTidyError &LHS, const ClangTidyError &RHS) const {
+    const tooling::DiagnosticMessage &M1 = LHS.Message;
+    const tooling::DiagnosticMessage &M2 = RHS.Message;
+
+    return std::tie(M1.FilePath, M1.FileOffset, M1.Message) <
+           std::tie(M2.FilePath, M2.FileOffset, M2.Message);
+  }
+};
+struct EqualClangTidyError {
+  bool operator()(const ClangTidyError &LHS, const ClangTidyError &RHS) const {
+    LessClangTidyError Less;
+    return !Less(LHS, RHS) && !Less(RHS, LHS);
+  }
+};
+} // end anonymous namespace
+
+// Flushes the internal diagnostics buffer to the ClangTidyContext.
+void ClangTidyDiagnosticConsumer::finish() {
+  finalizeLastError();
+
+  std::sort(Errors.begin(), Errors.end(), LessClangTidyError());
+  Errors.erase(std::unique(Errors.begin(), Errors.end(), EqualClangTidyError()),
+               Errors.end());
+  removeIncompatibleErrors(Errors);
+
+  for (const ClangTidyError &Error : Errors)
+    Context.storeError(Error);
+  Errors.clear();
+}
index 9b9a21b..2efa535 100644 (file)
-//===--- ForwardingReferenceOverloadCheck.cpp - clang-tidy-----------------===//\r
-//\r
-//                     The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-#include "ForwardingReferenceOverloadCheck.h"\r
-#include "clang/AST/ASTContext.h"\r
-#include "clang/ASTMatchers/ASTMatchFinder.h"\r
-#include <algorithm>\r
-\r
-using namespace clang::ast_matchers;\r
-\r
-namespace clang {\r
-namespace tidy {\r
-namespace misc {\r
-\r
-namespace {\r
-// Check if the given type is related to std::enable_if.\r
-AST_MATCHER(QualType, isEnableIf) {\r
-  auto CheckTemplate = [](const TemplateSpecializationType *Spec) {\r
-    if (!Spec || !Spec->getTemplateName().getAsTemplateDecl()) {\r
-      return false;\r
-    }\r
-    const NamedDecl *TypeDecl =\r
-        Spec->getTemplateName().getAsTemplateDecl()->getTemplatedDecl();\r
-    return TypeDecl->isInStdNamespace() &&\r
-           (TypeDecl->getName().equals("enable_if") ||\r
-            TypeDecl->getName().equals("enable_if_t"));\r
-  };\r
-  const Type *BaseType = Node.getTypePtr();\r
-  // Case: pointer or reference to enable_if.\r
-  while (BaseType->isPointerType() || BaseType->isReferenceType()) {\r
-    BaseType = BaseType->getPointeeType().getTypePtr();\r
-  }\r
-  // Case: type parameter dependent (enable_if<is_integral<T>>).\r
-  if (const auto *Dependent = BaseType->getAs<DependentNameType>()) {\r
-    BaseType = Dependent->getQualifier()->getAsType();\r
-  }\r
-  if (CheckTemplate(BaseType->getAs<TemplateSpecializationType>())) {\r
-    return true; // Case: enable_if_t< >.\r
-  } else if (const auto *Elaborated = BaseType->getAs<ElaboratedType>()) {\r
-    if (const auto *Qualifier = Elaborated->getQualifier()->getAsType()) {\r
-      if (CheckTemplate(Qualifier->getAs<TemplateSpecializationType>())) {\r
-        return true; // Case: enable_if< >::type.\r
-      }\r
-    }\r
-  }\r
-  return false;\r
-}\r
-AST_MATCHER_P(TemplateTypeParmDecl, hasDefaultArgument,\r
-              clang::ast_matchers::internal::Matcher<QualType>, TypeMatcher) {\r
-  return Node.hasDefaultArgument() &&\r
-         TypeMatcher.matches(Node.getDefaultArgument(), Finder, Builder);\r
-}\r
-} // namespace\r
-\r
-void ForwardingReferenceOverloadCheck::registerMatchers(MatchFinder *Finder) {\r
-  // Forwarding references require C++11 or later.\r
-  if (!getLangOpts().CPlusPlus11)\r
-    return;\r
-\r
-  auto ForwardingRefParm =\r
-      parmVarDecl(\r
-          hasType(qualType(rValueReferenceType(),\r
-                           references(templateTypeParmType(hasDeclaration(\r
-                               templateTypeParmDecl().bind("type-parm-decl")))),\r
-                           unless(references(isConstQualified())))))\r
-          .bind("parm-var");\r
-\r
-  DeclarationMatcher findOverload =\r
-      cxxConstructorDecl(\r
-          hasParameter(0, ForwardingRefParm),\r
-          unless(hasAnyParameter(\r
-              // No warning: enable_if as constructor parameter.\r
-              parmVarDecl(hasType(isEnableIf())))),\r
-          unless(hasParent(functionTemplateDecl(has(templateTypeParmDecl(\r
-              // No warning: enable_if as type parameter.\r
-              hasDefaultArgument(isEnableIf())))))))\r
-          .bind("ctor");\r
-  Finder->addMatcher(findOverload, this);\r
-}\r
-\r
-void ForwardingReferenceOverloadCheck::check(\r
-    const MatchFinder::MatchResult &Result) {\r
-  const auto *ParmVar = Result.Nodes.getNodeAs<ParmVarDecl>("parm-var");\r
-  const auto *TypeParmDecl =\r
-      Result.Nodes.getNodeAs<TemplateTypeParmDecl>("type-parm-decl");\r
-\r
-  // Get the FunctionDecl and FunctionTemplateDecl containing the function\r
-  // parameter.\r
-  const auto *FuncForParam = dyn_cast<FunctionDecl>(ParmVar->getDeclContext());\r
-  if (!FuncForParam)\r
-    return;\r
-  const FunctionTemplateDecl *FuncTemplate =\r
-      FuncForParam->getDescribedFunctionTemplate();\r
-  if (!FuncTemplate)\r
-    return;\r
-\r
-  // Check that the template type parameter belongs to the same function\r
-  // template as the function parameter of that type. (This implies that type\r
-  // deduction will happen on the type.)\r
-  const TemplateParameterList *Params = FuncTemplate->getTemplateParameters();\r
-  if (std::find(Params->begin(), Params->end(), TypeParmDecl) == Params->end())\r
-    return;\r
-\r
-  // Every parameter after the first must have a default value.\r
-  const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor");\r
-  for (auto Iter = Ctor->param_begin() + 1; Iter != Ctor->param_end(); ++Iter) {\r
-    if (!(*Iter)->hasDefaultArg())\r
-      return;\r
-  }\r
-  bool EnabledCopy = false, DisabledCopy = false, EnabledMove = false,\r
-       DisabledMove = false;\r
-  for (const auto *OtherCtor : Ctor->getParent()->ctors()) {\r
-    if (OtherCtor->isCopyOrMoveConstructor()) {\r
-      if (OtherCtor->isDeleted() || OtherCtor->getAccess() == AS_private)\r
-        (OtherCtor->isCopyConstructor() ? DisabledCopy : DisabledMove) = true;\r
-      else\r
-        (OtherCtor->isCopyConstructor() ? EnabledCopy : EnabledMove) = true;\r
-    }\r
-  }\r
-  bool Copy = (!EnabledMove && !DisabledMove && !DisabledCopy) || EnabledCopy;\r
-  bool Move = !DisabledMove || EnabledMove;\r
-  if (!Copy && !Move)\r
-    return;\r
-  diag(Ctor->getLocation(),\r
-       "constructor accepting a forwarding reference can "\r
-       "hide the %select{copy|move|copy and move}0 constructor%s1")\r
-      << (Copy && Move ? 2 : (Copy ? 0 : 1)) << Copy + Move;\r
-  for (const auto *OtherCtor : Ctor->getParent()->ctors()) {\r
-    if (OtherCtor->isCopyOrMoveConstructor() && !OtherCtor->isDeleted() &&\r
-        OtherCtor->getAccess() != AS_private) {\r
-      diag(OtherCtor->getLocation(),\r
-           "%select{copy|move}0 constructor declared here", DiagnosticIDs::Note)\r
-          << OtherCtor->isMoveConstructor();\r
-    }\r
-  }\r
-}\r
-\r
-} // namespace misc\r
-} // namespace tidy\r
-} // namespace clang\r
+//===--- ForwardingReferenceOverloadCheck.cpp - clang-tidy-----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ForwardingReferenceOverloadCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include <algorithm>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+namespace {
+// Check if the given type is related to std::enable_if.
+AST_MATCHER(QualType, isEnableIf) {
+  auto CheckTemplate = [](const TemplateSpecializationType *Spec) {
+    if (!Spec || !Spec->getTemplateName().getAsTemplateDecl()) {
+      return false;
+    }
+    const NamedDecl *TypeDecl =
+        Spec->getTemplateName().getAsTemplateDecl()->getTemplatedDecl();
+    return TypeDecl->isInStdNamespace() &&
+           (TypeDecl->getName().equals("enable_if") ||
+            TypeDecl->getName().equals("enable_if_t"));
+  };
+  const Type *BaseType = Node.getTypePtr();
+  // Case: pointer or reference to enable_if.
+  while (BaseType->isPointerType() || BaseType->isReferenceType()) {
+    BaseType = BaseType->getPointeeType().getTypePtr();
+  }
+  // Case: type parameter dependent (enable_if<is_integral<T>>).
+  if (const auto *Dependent = BaseType->getAs<DependentNameType>()) {
+    BaseType = Dependent->getQualifier()->getAsType();
+  }
+  if (CheckTemplate(BaseType->getAs<TemplateSpecializationType>())) {
+    return true; // Case: enable_if_t< >.
+  } else if (const auto *Elaborated = BaseType->getAs<ElaboratedType>()) {
+    if (const auto *Qualifier = Elaborated->getQualifier()->getAsType()) {
+      if (CheckTemplate(Qualifier->getAs<TemplateSpecializationType>())) {
+        return true; // Case: enable_if< >::type.
+      }
+    }
+  }
+  return false;
+}
+AST_MATCHER_P(TemplateTypeParmDecl, hasDefaultArgument,
+              clang::ast_matchers::internal::Matcher<QualType>, TypeMatcher) {
+  return Node.hasDefaultArgument() &&
+         TypeMatcher.matches(Node.getDefaultArgument(), Finder, Builder);
+}
+} // namespace
+
+void ForwardingReferenceOverloadCheck::registerMatchers(MatchFinder *Finder) {
+  // Forwarding references require C++11 or later.
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  auto ForwardingRefParm =
+      parmVarDecl(
+          hasType(qualType(rValueReferenceType(),
+                           references(templateTypeParmType(hasDeclaration(
+                               templateTypeParmDecl().bind("type-parm-decl")))),
+                           unless(references(isConstQualified())))))
+          .bind("parm-var");
+
+  DeclarationMatcher findOverload =
+      cxxConstructorDecl(
+          hasParameter(0, ForwardingRefParm),
+          unless(hasAnyParameter(
+              // No warning: enable_if as constructor parameter.
+              parmVarDecl(hasType(isEnableIf())))),
+          unless(hasParent(functionTemplateDecl(has(templateTypeParmDecl(
+              // No warning: enable_if as type parameter.
+              hasDefaultArgument(isEnableIf())))))))
+          .bind("ctor");
+  Finder->addMatcher(findOverload, this);
+}
+
+void ForwardingReferenceOverloadCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *ParmVar = Result.Nodes.getNodeAs<ParmVarDecl>("parm-var");
+  const auto *TypeParmDecl =
+      Result.Nodes.getNodeAs<TemplateTypeParmDecl>("type-parm-decl");
+
+  // Get the FunctionDecl and FunctionTemplateDecl containing the function
+  // parameter.
+  const auto *FuncForParam = dyn_cast<FunctionDecl>(ParmVar->getDeclContext());
+  if (!FuncForParam)
+    return;
+  const FunctionTemplateDecl *FuncTemplate =
+      FuncForParam->getDescribedFunctionTemplate();
+  if (!FuncTemplate)
+    return;
+
+  // Check that the template type parameter belongs to the same function
+  // template as the function parameter of that type. (This implies that type
+  // deduction will happen on the type.)
+  const TemplateParameterList *Params = FuncTemplate->getTemplateParameters();
+  if (std::find(Params->begin(), Params->end(), TypeParmDecl) == Params->end())
+    return;
+
+  // Every parameter after the first must have a default value.
+  const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor");
+  for (auto Iter = Ctor->param_begin() + 1; Iter != Ctor->param_end(); ++Iter) {
+    if (!(*Iter)->hasDefaultArg())
+      return;
+  }
+  bool EnabledCopy = false, DisabledCopy = false, EnabledMove = false,
+       DisabledMove = false;
+  for (const auto *OtherCtor : Ctor->getParent()->ctors()) {
+    if (OtherCtor->isCopyOrMoveConstructor()) {
+      if (OtherCtor->isDeleted() || OtherCtor->getAccess() == AS_private)
+        (OtherCtor->isCopyConstructor() ? DisabledCopy : DisabledMove) = true;
+      else
+        (OtherCtor->isCopyConstructor() ? EnabledCopy : EnabledMove) = true;
+    }
+  }
+  bool Copy = (!EnabledMove && !DisabledMove && !DisabledCopy) || EnabledCopy;
+  bool Move = !DisabledMove || EnabledMove;
+  if (!Copy && !Move)
+    return;
+  diag(Ctor->getLocation(),
+       "constructor accepting a forwarding reference can "
+       "hide the %select{copy|move|copy and move}0 constructor%s1")
+      << (Copy && Move ? 2 : (Copy ? 0 : 1)) << Copy + Move;
+  for (const auto *OtherCtor : Ctor->getParent()->ctors()) {
+    if (OtherCtor->isCopyOrMoveConstructor() && !OtherCtor->isDeleted() &&
+        OtherCtor->getAccess() != AS_private) {
+      diag(OtherCtor->getLocation(),
+           "%select{copy|move}0 constructor declared here", DiagnosticIDs::Note)
+          << OtherCtor->isMoveConstructor();
+    }
+  }
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
index 98e52b9..ac6198e 100644 (file)
@@ -1,43 +1,43 @@
-// RUN: %check_clang_tidy %s misc-non-copyable-objects %t\r
-\r
-typedef struct FILE {} FILE;\r
-typedef struct pthread_cond_t {} pthread_cond_t;\r
-typedef int pthread_mutex_t;\r
-\r
-// CHECK-MESSAGES: :[[@LINE+1]]:13: warning: 'f' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'? [misc-non-copyable-objects]\r
-void g(FILE f);\r
-// CHECK-MESSAGES: :[[@LINE+1]]:24: warning: 'm' declared as type 'pthread_mutex_t', which is unsafe to copy; did you mean 'pthread_mutex_t *'?\r
-void h(pthread_mutex_t m);\r
-// CHECK-MESSAGES: :[[@LINE+1]]:23: warning: 'c' declared as type 'pthread_cond_t', which is unsafe to copy; did you mean 'pthread_cond_t *'?\r
-void i(pthread_cond_t c);\r
-\r
-struct S {\r
-  pthread_cond_t c; // ok\r
-  // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: 'f' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?\r
-  FILE f;\r
-};\r
-\r
-void func(FILE *f) {\r
-  // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: 'f1' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?\r
-  FILE f1; // match\r
-  // CHECK-MESSAGES: :[[@LINE+2]]:8: warning: 'f2' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?\r
-  // CHECK-MESSAGES: :[[@LINE+1]]:13: warning: expression has opaque data structure type 'FILE'; type should only be used as a pointer and not dereferenced\r
-  FILE f2 = *f;\r
-  // CHECK-MESSAGES: :[[@LINE+1]]:15: warning: 'f3' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?\r
-  struct FILE f3;\r
-  // CHECK-MESSAGES: :[[@LINE+1]]:16: warning: expression has opaque data structure type 'FILE'; type should only be used as a pointer and not dereferenced\r
-  (void)sizeof(*f);\r
-  (void)sizeof(FILE);\r
-  // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: expression has opaque data structure type 'FILE'; type should only be used as a pointer and not dereferenced\r
-  g(*f);\r
-\r
-  pthread_mutex_t m; // ok\r
-  h(m); // ok\r
-\r
-  pthread_cond_t c; // ok\r
-  i(c); // ok\r
-\r
-  pthread_mutex_t *m1 = &m; // ok\r
-  // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: expression has opaque data structure type 'pthread_mutex_t'; type should only be used as a pointer and not dereferenced\r
-  h(*m1);\r
-}
\ No newline at end of file
+// RUN: %check_clang_tidy %s misc-non-copyable-objects %t
+
+typedef struct FILE {} FILE;
+typedef struct pthread_cond_t {} pthread_cond_t;
+typedef int pthread_mutex_t;
+
+// CHECK-MESSAGES: :[[@LINE+1]]:13: warning: 'f' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'? [misc-non-copyable-objects]
+void g(FILE f);
+// CHECK-MESSAGES: :[[@LINE+1]]:24: warning: 'm' declared as type 'pthread_mutex_t', which is unsafe to copy; did you mean 'pthread_mutex_t *'?
+void h(pthread_mutex_t m);
+// CHECK-MESSAGES: :[[@LINE+1]]:23: warning: 'c' declared as type 'pthread_cond_t', which is unsafe to copy; did you mean 'pthread_cond_t *'?
+void i(pthread_cond_t c);
+
+struct S {
+  pthread_cond_t c; // ok
+  // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: 'f' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+  FILE f;
+};
+
+void func(FILE *f) {
+  // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: 'f1' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+  FILE f1; // match
+  // CHECK-MESSAGES: :[[@LINE+2]]:8: warning: 'f2' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+  // CHECK-MESSAGES: :[[@LINE+1]]:13: warning: expression has opaque data structure type 'FILE'; type should only be used as a pointer and not dereferenced
+  FILE f2 = *f;
+  // CHECK-MESSAGES: :[[@LINE+1]]:15: warning: 'f3' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+  struct FILE f3;
+  // CHECK-MESSAGES: :[[@LINE+1]]:16: warning: expression has opaque data structure type 'FILE'; type should only be used as a pointer and not dereferenced
+  (void)sizeof(*f);
+  (void)sizeof(FILE);
+  // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: expression has opaque data structure type 'FILE'; type should only be used as a pointer and not dereferenced
+  g(*f);
+
+  pthread_mutex_t m; // ok
+  h(m); // ok
+
+  pthread_cond_t c; // ok
+  i(c); // ok
+
+  pthread_mutex_t *m1 = &m; // ok
+  // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: expression has opaque data structure type 'pthread_mutex_t'; type should only be used as a pointer and not dereferenced
+  h(*m1);
+}
index 0fca945..e3e8304 100644 (file)
@@ -1,27 +1,27 @@
-// RUN: %check_clang_tidy %s misc-static-assert %t -- -- -std=c11\r
-// RUN: clang-tidy %s -checks=-*,misc-static-assert -- -std=c99 | count 0\r
-\r
-void abort() {}\r
-#ifdef NDEBUG\r
-#define assert(x) 1\r
-#else\r
-#define assert(x)                                                              \\r
-  if (!(x))                                                                    \\r
-  abort()\r
-#endif\r
-\r
-void f(void) {\r
-  int x = 1;\r
-  assert(x == 0);\r
-  // CHECK-FIXES: {{^  }}assert(x == 0);\r
-\r
-  #define static_assert(x, msg) _Static_assert(x, msg)\r
-  assert(11 == 5 + 6);\r
-  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be\r
-  // CHECK-FIXES: {{^  }}static_assert(11 == 5 + 6, "");\r
-  #undef static_assert\r
-\r
-  assert(10 == 5 + 5);\r
-  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be\r
-  // CHECK-FIXES: {{^  }}static_assert(10 == 5 + 5, "");\r
-}\r
+// RUN: %check_clang_tidy %s misc-static-assert %t -- -- -std=c11
+// RUN: clang-tidy %s -checks=-*,misc-static-assert -- -std=c99 | count 0
+
+void abort() {}
+#ifdef NDEBUG
+#define assert(x) 1
+#else
+#define assert(x)                                                              \
+  if (!(x))                                                                    \
+  abort()
+#endif
+
+void f(void) {
+  int x = 1;
+  assert(x == 0);
+  // CHECK-FIXES: {{^  }}assert(x == 0);
+
+  #define static_assert(x, msg) _Static_assert(x, msg)
+  assert(11 == 5 + 6);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+  // CHECK-FIXES: {{^  }}static_assert(11 == 5 + 6, "");
+  #undef static_assert
+
+  assert(10 == 5 + 5);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+  // CHECK-FIXES: {{^  }}static_assert(10 == 5 + 5, "");
+}
index e614f22..78b53bb 100644 (file)
@@ -1,23 +1,23 @@
-// RUN: clang-tidy %s -checks=-*,misc-undelegated-constructor -- -std=c++98 | count 0\r
-\r
-// Note: this test expects no diagnostics, but FileCheck cannot handle that,\r
-// hence the use of | count 0.\r
-\r
-struct Ctor;\r
-Ctor foo();\r
-\r
-struct Ctor {\r
-  Ctor();\r
-  Ctor(int);\r
-  Ctor(int, int);\r
-  Ctor(Ctor *i) {\r
-    Ctor();\r
-    Ctor(0);\r
-    Ctor(1, 2);\r
-    foo();\r
-  }\r
-};\r
-\r
-Ctor::Ctor() {\r
-  Ctor(1);\r
-}\r
+// RUN: clang-tidy %s -checks=-*,misc-undelegated-constructor -- -std=c++98 | count 0
+
+// Note: this test expects no diagnostics, but FileCheck cannot handle that,
+// hence the use of | count 0.
+
+struct Ctor;
+Ctor foo();
+
+struct Ctor {
+  Ctor();
+  Ctor(int);
+  Ctor(int, int);
+  Ctor(Ctor *i) {
+    Ctor();
+    Ctor(0);
+    Ctor(1, 2);
+    foo();
+  }
+};
+
+Ctor::Ctor() {
+  Ctor(1);
+}