Index: clang-tidy/ClangTidy.cpp =================================================================== --- clang-tidy/ClangTidy.cpp +++ clang-tidy/ClangTidy.cpp @@ -109,6 +109,13 @@ void reportDiagnostic(const ClangTidyError &Error) { const ClangTidyMessage &Message = Error.Message; + // By default, the working directory of file system is the current + // clang-tidy running directory. + // + // Change the directory to the one used during the analysis. + if (!Error.BuildDirectory.empty()) + Files.getVirtualFileSystem()->setCurrentWorkingDirectory( + Error.BuildDirectory); SourceLocation Loc = getLocation(Message.FilePath, Message.FileOffset); // Contains a pair for each attempted fix: location and whether the fix was // applied successfully. Index: clang-tidy/ClangTidyDiagnosticConsumer.h =================================================================== --- clang-tidy/ClangTidyDiagnosticConsumer.h +++ clang-tidy/ClangTidyDiagnosticConsumer.h @@ -57,8 +57,17 @@ Error = DiagnosticsEngine::Error }; - ClangTidyError(StringRef CheckName, Level DiagLevel, bool IsWarningAsError); - + ClangTidyError(StringRef CheckName, Level DiagLevel, bool IsWarningAsError, + const std::string &BuildDirectory); + + // A build directory of the source file containing the error. + // + // It's an absolute path which is `directory` field of the source file in + // compilation database. If users don't specify compilation database + // directory, it is the current directory where clang-tidy runs. + // + // It can be empty in some cases, e.g. the source file does not exist. + std::string BuildDirectory; std::string CheckName; ClangTidyMessage Message; tooling::Replacements Fix; Index: clang-tidy/ClangTidyDiagnosticConsumer.cpp =================================================================== --- clang-tidy/ClangTidyDiagnosticConsumer.cpp +++ clang-tidy/ClangTidyDiagnosticConsumer.cpp @@ -116,9 +116,10 @@ ClangTidyError::ClangTidyError(StringRef CheckName, ClangTidyError::Level DiagLevel, - bool IsWarningAsError) - : CheckName(CheckName), DiagLevel(DiagLevel), - IsWarningAsError(IsWarningAsError) {} + bool IsWarningAsError, + const std::string &BuildDirectory) + : BuildDirectory(std::move(BuildDirectory)), CheckName(CheckName), + DiagLevel(DiagLevel), IsWarningAsError(IsWarningAsError) {} // Returns true if GlobList starts with the negative indicator ('-'), removes it // from the GlobList. @@ -335,7 +336,17 @@ bool IsWarningAsError = DiagLevel == DiagnosticsEngine::Warning && Context.getWarningAsErrorFilter().contains(CheckName); - Errors.push_back(ClangTidyError(CheckName, Level, IsWarningAsError)); + + std::string BuildDirectory; + if (Info.hasSourceManager()) { + auto WorkingDir = Info.getSourceManager() + .getFileManager().getVirtualFileSystem() + ->getCurrentWorkingDirectory(); + if (WorkingDir) + BuildDirectory = WorkingDir.get(); + } + Errors.push_back( + ClangTidyError(CheckName, Level, IsWarningAsError, BuildDirectory)); } // FIXME: Provide correct LangOptions for each file. Index: test/clang-tidy/Inputs/compilation-database/header.h =================================================================== --- /dev/null +++ test/clang-tidy/Inputs/compilation-database/header.h @@ -0,0 +1,3 @@ +#define NULL 0 + +int *a = NULL; Index: test/clang-tidy/Inputs/compilation-database/template.json =================================================================== --- /dev/null +++ test/clang-tidy/Inputs/compilation-database/template.json @@ -0,0 +1,7 @@ +[ +{ + "directory": "test_dir", + "command": "clang++ -o test.o clang-tidy-run-with-database.cpp", + "file": "test_dir/clang-tidy-run-with-database.cpp" +} +] Index: test/clang-tidy/clang-tidy-run-with-database.cpp =================================================================== --- /dev/null +++ test/clang-tidy/clang-tidy-run-with-database.cpp @@ -0,0 +1,6 @@ +// REQUIRES: shell +// RUN: sed 's|test_dir|%S|g' %S/Inputs/compilation-database/template.json > %T/compile_commands.json +// RUN: clang-tidy --checks=-*,modernize-use-nullptr -p %T %s -header-filter=.* | FileCheck %s -implicit-check-not="{{warning:}}" + +#include "./Inputs/compilation-database/header.h" +// CHECK: warning: use nullptr [modernize-use-nullptr]