lebedev.ri created this revision.
lebedev.ri added reviewers: alexfh, sbenza.
Herald added subscribers: mgrang, xazax.hun.
Continuation of https://reviews.llvm.org/D46504.
Example output:
$ clang-tidy -enable-check-profile -store-check-profile=.
-store-check-profile-elide-prefix=. -checks=-*,readability-function-size
source.cpp 2>&1 >/dev/null
$ cat .csv
"User Time","System Time","User+System","Wall Time","Name"
8.8420499999973945e-01,1.2026799999999757e-01,1.0044729999997370e+00,1.0031676292419434e+00,"readability-function-size"
8.8420499999973945e-01,1.2026799999999757e-01,1.0044729999997370e+00,1.0031676292419434e+00,"Total"
There are two arguments that control profile storage:
- `-store-check-profile=<prefix>` This option controls the prefix where these
per-TU profiles are stored as CSV. If the prefix is not an absolute path, it is
considered to be relative to the directory from where you have run
`clang-tidy`. All `.` and `..` patterns in the path are collapsed, and symlinks
are resolved.
**Example**: Let's suppose you have a source file named `example.cpp`,
located in `/source` directory.
- If you specify `-store-check-profile=/tmp`, then the profile will be saved
to `/tmp/source/example.cpp.csv`
- If you run `clang-tidy` from within `/foo` directory, and specify
`-store-check-profile=.`, then the profile will still be saved to
`/foo/source/example.cpp.csv`
- `-store-check-profile-elide-prefix=<prefix>` When specified, this prefix will
be elided from the source file name, before prepending it with the prefix
specified by `-store-check-profile`. If the prefix is not an absolute path, it
is considered to be relative to the directory from where you have run
`clang-tidy`. All `.` and `..` patterns in the path are collapsed, and symlinks
are resolved.
**Example**: Let's suppose you have a source file named `example.cpp`,
located in `/source` directory.
- If you specify `-store-check-profile=/tmp
-store-check-profile-elide-prefix=/source` , then the profile will be saved to
`/tmp/example.cpp.csv`
- If you run `clang-tidy` from within `/source` directory, and specify
`-store-check-profile=/foo -store-check-profile-elide-prefix=.`, then the
profile will be saved to `/foo/example.cpp.csv`
Repository:
rCTE Clang Tools Extra
https://reviews.llvm.org/D46602
Files:
clang-tidy/ClangTidy.cpp
clang-tidy/ClangTidy.h
clang-tidy/ClangTidyDiagnosticConsumer.cpp
clang-tidy/ClangTidyDiagnosticConsumer.h
clang-tidy/ClangTidyProfiling.cpp
clang-tidy/ClangTidyProfiling.h
clang-tidy/tool/ClangTidyMain.cpp
docs/ReleaseNotes.rst
docs/clang-tidy/index.rst
test/clang-tidy/clang-tidy-store-check-profile-one-tu.cpp
Index: test/clang-tidy/clang-tidy-store-check-profile-one-tu.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/clang-tidy-store-check-profile-one-tu.cpp
@@ -0,0 +1,17 @@
+// RUN: clang-tidy -enable-check-profile -checks='-*,readability-function-size' -store-check-profile=%T -store-check-profile-elide-prefix=%s %s 2>&1 | FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' -check-prefix=CHECK-CONSOLE %s
+// RUN: FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' -input-file=%T/.csv -check-prefix=CHECK-FILE %s
+
+// CHECK-CONSOLE: ===-------------------------------------------------------------------------===
+// CHECK-CONSOLE-NEXT: {{.*}} --- Name ---
+// CHECK-CONSOLE-NEXT: {{.*}} readability-function-size
+// CHECK-CONSOLE-NEXT: {{.*}} Total
+// CHECK-CONSOLE-NEXT: ===-------------------------------------------------------------------------===
+
+// CHECK-FILE: {{.*}}"Wall Time","Name"
+// CHECK-FILE-NEXT: {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}},"readability-function-size"
+// CHECK-FILE-NEXT: {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}},"Total"
+
+class A {
+ A() {}
+ ~A() {}
+};
Index: docs/clang-tidy/index.rst
===================================================================
--- docs/clang-tidy/index.rst
+++ docs/clang-tidy/index.rst
@@ -99,114 +99,127 @@
.. code-block:: console
- $ clang-tidy -help
+ $ clang-tidy --help
USAGE: clang-tidy [options] <source0> [... <sourceN>]
OPTIONS:
Generic Options:
- -help - Display available options (-help-hidden for more)
- -help-list - Display list of available options (-help-list-hidden for more)
- -version - Display the version of this program
+ -help - Display available options (-help-hidden for more)
+ -help-list - Display list of available options (-help-list-hidden for more)
+ -version - Display the version of this program
clang-tidy options:
- -checks=<string> -
- Comma-separated list of globs with optional '-'
- prefix. Globs are processed in order of
- appearance in the list. Globs without '-'
- prefix add checks with matching names to the
- set, globs with the '-' prefix remove checks
- with matching names from the set of enabled
- checks. This option's value is appended to the
- value of the 'Checks' option in .clang-tidy
- file, if any.
- -config=<string> -
- Specifies a configuration in YAML/JSON format:
- -config="{Checks: '*',
- CheckOptions: [{key: x,
- value: y}]}"
- When the value is empty, clang-tidy will
- attempt to find a file named .clang-tidy for
- each source file in its parent directories.
- -dump-config -
- Dumps configuration in the YAML format to
- stdout. This option can be used along with a
- file name (and '--' if the file is outside of a
- project with configured compilation database).
- The configuration used for this file will be
- printed.
- Use along with -checks=* to include
- configuration of all checks.
- -enable-check-profile -
- Enable per-check timing profiles, and print a
- report to stderr.
- -explain-config -
- For each enabled check explains, where it is
- enabled, i.e. in clang-tidy binary, command
- line or a specific configuration file.
- -export-fixes=<filename> -
- YAML file to store suggested fixes in. The
- stored fixes can be applied to the input source
- code with clang-apply-replacements.
- -extra-arg=<string> - Additional argument to append to the compiler command line
- -extra-arg-before=<string> - Additional argument to prepend to the compiler command line
- -fix -
- Apply suggested fixes. Without -fix-errors
- clang-tidy will bail out if any compilation
- errors were found.
- -fix-errors -
- Apply suggested fixes even if compilation
- errors were found. If compiler errors have
- attached fix-its, clang-tidy will apply them as
- well.
- -format-style=<string> -
- Style for formatting code around applied fixes:
- - 'none' (default) turns off formatting
- - 'file' (literally 'file', not a placeholder)
- uses .clang-format file in the closest parent
- directory
- - '{ <json> }' specifies options inline, e.g.
- -format-style='{BasedOnStyle: llvm, IndentWidth: 8}'
- - 'llvm', 'google', 'webkit', 'mozilla'
- See clang-format documentation for the up-to-date
- information about formatting styles and options.
- This option overrides the 'FormatStyle` option in
- .clang-tidy file, if any.
- -header-filter=<string> -
- Regular expression matching the names of the
- headers to output diagnostics from. Diagnostics
- from the main file of each translation unit are
- always displayed.
- Can be used together with -line-filter.
- This option overrides the 'HeaderFilter' option
- in .clang-tidy file, if any.
- -line-filter=<string> -
- List of files with line ranges to filter the
- warnings. Can be used together with
- -header-filter. The format of the list is a
- JSON array of objects:
- [
- {"name":"file1.cpp","lines":[[1,3],[5,7]]},
- {"name":"file2.h"}
- ]
- -list-checks -
- List all enabled checks and exit. Use with
- -checks=* to list all available checks.
- -p=<string> - Build path
- -quiet -
- Run clang-tidy in quiet mode. This suppresses
- printing statistics about ignored warnings and
- warnings treated as errors if the respective
- options are specified.
- -system-headers - Display the errors from system headers.
- -warnings-as-errors=<string> -
- Upgrades warnings to errors. Same format as
- '-checks'.
- This option's value is appended to the value of
- the 'WarningsAsErrors' option in .clang-tidy
- file, if any.
+ -checks=<string> -
+ Comma-separated list of globs with optional '-'
+ prefix. Globs are processed in order of
+ appearance in the list. Globs without '-'
+ prefix add checks with matching names to the
+ set, globs with the '-' prefix remove checks
+ with matching names from the set of enabled
+ checks. This option's value is appended to the
+ value of the 'Checks' option in .clang-tidy
+ file, if any.
+ -config=<string> -
+ Specifies a configuration in YAML/JSON format:
+ -config="{Checks: '*',
+ CheckOptions: [{key: x,
+ value: y}]}"
+ When the value is empty, clang-tidy will
+ attempt to find a file named .clang-tidy for
+ each source file in its parent directories.
+ -dump-config -
+ Dumps configuration in the YAML format to
+ stdout. This option can be used along with a
+ file name (and '--' if the file is outside of a
+ project with configured compilation database).
+ The configuration used for this file will be
+ printed.
+ Use along with -checks=* to include
+ configuration of all checks.
+ -enable-check-profile -
+ Enable per-check timing profiles, and print a
+ report to stderr.
+ -explain-config -
+ For each enabled check explains, where it is
+ enabled, i.e. in clang-tidy binary, command
+ line or a specific configuration file.
+ -export-fixes=<filename> -
+ YAML file to store suggested fixes in. The
+ stored fixes can be applied to the input source
+ code with clang-apply-replacements.
+ -extra-arg=<string> - Additional argument to append to the compiler command line
+ -extra-arg-before=<string> - Additional argument to prepend to the compiler command line
+ -fix -
+ Apply suggested fixes. Without -fix-errors
+ clang-tidy will bail out if any compilation
+ errors were found.
+ -fix-errors -
+ Apply suggested fixes even if compilation
+ errors were found. If compiler errors have
+ attached fix-its, clang-tidy will apply them as
+ well.
+ -format-style=<string> -
+ Style for formatting code around applied fixes:
+ - 'none' (default) turns off formatting
+ - 'file' (literally 'file', not a placeholder)
+ uses .clang-format file in the closest parent
+ directory
+ - '{ <json> }' specifies options inline, e.g.
+ -format-style='{BasedOnStyle: llvm, IndentWidth: 8}'
+ - 'llvm', 'google', 'webkit', 'mozilla'
+ See clang-format documentation for the up-to-date
+ information about formatting styles and options.
+ This option overrides the 'FormatStyle` option in
+ .clang-tidy file, if any.
+ -header-filter=<string> -
+ Regular expression matching the names of the
+ headers to output diagnostics from. Diagnostics
+ from the main file of each translation unit are
+ always displayed.
+ Can be used together with -line-filter.
+ This option overrides the 'HeaderFilter' option
+ in .clang-tidy file, if any.
+ -line-filter=<string> -
+ List of files with line ranges to filter the
+ warnings. Can be used together with
+ -header-filter. The format of the list is a
+ JSON array of objects:
+ [
+ {"name":"file1.cpp","lines":[[1,3],[5,7]]},
+ {"name":"file2.h"}
+ ]
+ -list-checks -
+ List all enabled checks and exit. Use with
+ -checks=* to list all available checks.
+ -p=<string> - Build path
+ -quiet -
+ Run clang-tidy in quiet mode. This suppresses
+ printing statistics about ignored warnings and
+ warnings treated as errors if the respective
+ options are specified.
+ -store-check-profile=<prefix> -
+ When -enable-check-profile option is enabled,
+ this option controls the prefix where these
+ per-TU profiles are stored, as CSV.
+ By default reports are only printed
+ in tabulated format to stderr.
+ -store-check-profile-elide-prefix=<prefix> -
+ When specified, this prefix will be elided
+ from the source file name, before prepending
+ it with the prefix specified by -store-check-profile.
+ -system-headers - Display the errors from system headers.
+ -vfsoverlay=<filename> -
+ Overlay the virtual filesystem described by file
+ over the real file system.
+ -warnings-as-errors=<string> -
+ Upgrades warnings to errors. Same format as
+ '-checks'.
+ This option's value is appended to the value of
+ the 'WarningsAsErrors' option in .clang-tidy
+ file, if any.
-p <build-path> is used to read a compile command database.
@@ -739,3 +752,69 @@
all changes in a temporary directory and applies them. Passing ``-format``
will run clang-format over changed lines.
+
+On checks profiling
+-------------------
+
+:program:`clang-tidy` can collect per-check profiling info, and output it
+for each processed source file (translation unit).
+
+To enable profiling info collection, use ``-enable-check-profile`` argument.
+The timings will be outputted to the ``stderr`` as a table. Example output:
+
+.. code-block:: console
+
+ $ clang-tidy -enable-check-profile -checks=-*,readability-function-size source.cpp
+ ===-------------------------------------------------------------------------===
+ ---User Time--- --System Time-- --User+System-- ---Wall Time--- --- Name ---
+ 0.8842 (100.0%) 0.1203 (100.0%) 1.0045 (100.0%) 1.0032 (100.0%) readability-function-size
+ 0.8842 (100.0%) 0.1203 (100.0%) 1.0045 (100.0%) 1.0032 (100.0%) Total
+ ===-------------------------------------------------------------------------===
+
+It can also store that data as CSV files for further processing. Example output:
+
+.. code-block:: console
+
+ $ clang-tidy -enable-check-profile -store-check-profile=. -store-check-profile-elide-prefix=. -checks=-*,readability-function-size source.cpp 2>&1 >/dev/null
+ $ cat .csv
+ "User Time","System Time","User+System","Wall Time","Name"
+ 8.8420499999973945e-01,1.2026799999999757e-01,1.0044729999997370e+00,1.0031676292419434e+00,"readability-function-size"
+ 8.8420499999973945e-01,1.2026799999999757e-01,1.0044729999997370e+00,1.0031676292419434e+00,"Total"
+
+There are two arguments that control profile storage:
+
+* ``-store-check-profile=<prefix>``
+
+ This option controls the prefix where these per-TU profiles are stored as CSV.
+ If the prefix is not an absolute path, it is considered to be relative to the
+ directory from where you have run :program:`clang-tidy`. All ``.`` and ``..``
+ patterns in the path are collapsed, and symlinks are resolved.
+
+ Example:
+ Let's suppose you have a source file named ``example.cpp``, located in
+ ``/source`` directory.
+
+ * If you specify ``-store-check-profile=/tmp``, then the profile will be saved
+ to ``/tmp/source/example.cpp.csv``
+
+ * If you run :program:`clang-tidy` from within ``/foo`` directory, and specify
+ ``-store-check-profile=.``, then the profile will still be saved to
+ ``/foo/source/example.cpp.csv``
+* ``-store-check-profile-elide-prefix=<prefix>``
+
+ When specified, this prefix will be elided from the source file name,
+ before prepending it with the prefix specified by ``-store-check-profile``.
+ If the prefix is not an absolute path, it is considered to be relative to the
+ directory from where you have run :program:`clang-tidy`. All ``.`` and ``..``
+ patterns in the path are collapsed, and symlinks are resolved.
+
+ Example:
+ Let's suppose you have a source file named ``example.cpp``, located in
+ ``/source`` directory.
+
+ * If you specify ``-store-check-profile=/tmp -store-check-profile-elide-prefix=/source``
+ , then the profile will be saved to ``/tmp/example.cpp.csv``
+
+ * If you run :program:`clang-tidy` from within ``/source`` directory, and
+ specify ``-store-check-profile=/foo -store-check-profile-elide-prefix=.``,
+ then the profile will be saved to ``/foo/example.cpp.csv``
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -57,6 +57,8 @@
Improvements to clang-tidy
--------------------------
+- clang-tidy learned to store checks profiling info as CSV files.
+
- New module `abseil` for checks related to the `Abseil <https://abseil.io>`_
library.
Index: clang-tidy/tool/ClangTidyMain.cpp
===================================================================
--- clang-tidy/tool/ClangTidyMain.cpp
+++ clang-tidy/tool/ClangTidyMain.cpp
@@ -181,6 +181,24 @@
cl::init(false),
cl::cat(ClangTidyCategory));
+static cl::opt<std::string> StoreCheckProfile("store-check-profile",
+ cl::desc(R"(
+When -enable-check-profile option is enabled,
+this option controls the prefix where these
+per-TU profiles are stored, as CSV.
+By default reports are only printed
+in tabulated format to stderr.)"),
+ cl::value_desc("prefix"),
+ cl::cat(ClangTidyCategory));
+
+static cl::opt<std::string> StoreCheckProfileElidePrefix(
+ "store-check-profile-elide-prefix", cl::desc(R"(
+When specified, this prefix will be elided
+from the source file name, before prepending
+it with the prefix specified by -store-check-profile.
+)"),
+ cl::value_desc("prefix"), cl::cat(ClangTidyCategory));
+
static cl::opt<std::string> ExportFixes("export-fixes", cl::desc(R"(
YAML file to store suggested fixes in. The
stored fixes can be applied to the input source
@@ -323,6 +341,26 @@
if (!OptionsProvider)
return 1;
+ auto processPrefix = [](std::string &input, SmallVectorImpl<char> &dest) {
+ dest.clear();
+ if (input.empty())
+ return;
+ SmallString<256> ScratchPath(input);
+ if (std::error_code EC = llvm::sys::fs::make_absolute(ScratchPath)) {
+ llvm::errs() << "Can't make absolute path from " << ScratchPath << ": "
+ << EC.message() << "\n";
+ }
+ if (std::error_code EC = llvm::sys::fs::real_path(ScratchPath, dest)) {
+ llvm::errs() << "Can't make real path from " << ScratchPath << ": "
+ << EC.message() << "\n";
+ }
+ };
+
+ SmallString<256> ProfilePrefix;
+ processPrefix(StoreCheckProfile, ProfilePrefix);
+ SmallString<256> ProfileElidePrefix;
+ processPrefix(StoreCheckProfileElidePrefix, ProfileElidePrefix);
+
StringRef FileName("dummy");
auto PathList = OptionsParser.getSourcePathList();
if (!PathList.empty()) {
@@ -392,7 +430,7 @@
ClangTidyContext Context(std::move(OwningOptionsProvider));
runClangTidy(Context, OptionsParser.getCompilations(), PathList, BaseFS,
- EnableCheckProfile);
+ EnableCheckProfile, ProfilePrefix, ProfileElidePrefix);
ArrayRef<ClangTidyError> Errors = Context.getErrors();
bool FoundErrors = llvm::find_if(Errors, [](const ClangTidyError &E) {
return E.DiagLevel == ClangTidyError::Error;
Index: clang-tidy/ClangTidyProfiling.h
===================================================================
--- clang-tidy/ClangTidyProfiling.h
+++ clang-tidy/ClangTidyProfiling.h
@@ -10,28 +10,41 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYPROFILING_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYPROFILING_H
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
+#include <string>
#include <utility>
#include <vector>
namespace clang {
namespace tidy {
class ClangTidyProfiling {
+ llvm::Optional<std::string> StoreCSVTo;
+
// Time is first to allow for sorting by it.
std::vector<std::pair<llvm::TimeRecord, llvm::StringRef>> Timers;
+
+ // The Total needs to be here, not in preprocess().
llvm::TimeRecord Total;
void preprocess();
- void printProfileData(llvm::raw_ostream &OS) const;
+ void printUserFriendlyTable(llvm::raw_ostream &OS) const;
+ void printCSVTable(llvm::raw_ostream &OS) const;
+
+ void storeProfileData() const;
public:
llvm::StringMap<llvm::TimeRecord> Records;
+ ClangTidyProfiling() = default;
+
+ ClangTidyProfiling(llvm::Optional<std::string> StoreCSVTo);
+
~ClangTidyProfiling();
};
Index: clang-tidy/ClangTidyProfiling.cpp
===================================================================
--- clang-tidy/ClangTidyProfiling.cpp
+++ clang-tidy/ClangTidyProfiling.cpp
@@ -9,27 +9,41 @@
#include "ClangTidyProfiling.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include <system_error>
+#include <utility>
#define DEBUG_TYPE "clang-tidy-profiling"
+namespace {
+static const char *const TotalStr = "Total";
+}
+
namespace clang {
namespace tidy {
void ClangTidyProfiling::preprocess() {
+ assert(Timers.empty() && "Don't preprocess twice");
+
// Convert from a insertion-friendly map to sort-friendly vector.
- Timers.clear();
- Timers.reserve(Records.size());
+ Timers.reserve(1UL + Records.size());
for (const auto &P : Records) {
Timers.emplace_back(P.getValue(), P.getKey());
Total += P.getValue();
}
- assert(Timers.size() == Records.size() && "Size mismatch after processing");
// We want the measurements to be sorted by decreasing time spent.
- llvm::sort(Timers.begin(), Timers.end());
+ llvm::sort(Timers.rbegin(), Timers.rend());
+
+ // And the total at the end.
+ Timers.emplace_back(Total, TotalStr);
+ assert(Timers.size() == 1UL + Records.size() && "Size mismatch afterwards");
}
-void ClangTidyProfiling::printProfileData(llvm::raw_ostream &OS) const {
+void ClangTidyProfiling::printUserFriendlyTable(llvm::raw_ostream &OS) const {
std::string Line = "===" + std::string(73, '-') + "===\n";
OS << Line;
@@ -45,20 +59,79 @@
OS << " --- Name ---\n";
// Loop through all of the timing data, printing it out.
- for (auto I = Timers.rbegin(), E = Timers.rend(); I != E; ++I) {
- I->first.print(Total, OS);
- OS << I->second << '\n';
+ for (const auto &I : Timers) {
+ I.first.print(Total, OS);
+ OS << I.second << '\n';
}
- Total.print(Total, OS);
- OS << "Total\n";
OS << Line << "\n";
OS.flush();
}
+void ClangTidyProfiling::printCSVTable(llvm::raw_ostream &OS) const {
+ int Column = 0;
+ auto comma = [&Column, &OS]() {
+ if (Column)
+ OS << ','; // FIXME: can ',' be a decimal separator?
+ ++Column;
+ };
+ auto printColumn = [comma, &OS](bool print, const char *str) {
+ if (!print)
+ return;
+ comma();
+ OS << "\"";
+ OS << str;
+ OS << "\"";
+ };
+ printColumn(Total.getUserTime(), "User Time");
+ printColumn(Total.getSystemTime(), "System Time");
+ printColumn(Total.getProcessTime(), "User+System");
+ printColumn(true, "Wall Time");
+ printColumn(Total.getMemUsed(), "Mem");
+ printColumn(true, "Name");
+ OS << "\n";
+
+ // Loop through all of the timing data, printing it out.
+ for (const auto &I : Timers) {
+ I.first.printCSV(Total, OS);
+ comma();
+ OS << "\"" << I.second << "\"\n";
+ }
+
+ OS.flush();
+}
+
+void ClangTidyProfiling::storeProfileData() const {
+ assert(StoreCSVTo.hasValue() && "We should have a filename.");
+
+ llvm::SmallString<256> OutputDirectory(*StoreCSVTo);
+ llvm::sys::path::remove_filename(OutputDirectory);
+ if (std::error_code EC = llvm::sys::fs::create_directories(OutputDirectory)) {
+ llvm::errs() << "Unable to create output directory '" << OutputDirectory
+ << "': " << EC.message() << "\n";
+ return;
+ }
+
+ std::error_code EC;
+ llvm::raw_fd_ostream OS(*StoreCSVTo, EC, llvm::sys::fs::F_None);
+ if (EC) {
+ llvm::errs() << "Error opening output file: " << EC.message() << "\n";
+ return;
+ }
+
+ printCSVTable(OS);
+}
+
+ClangTidyProfiling::ClangTidyProfiling(llvm::Optional<std::string> StoreCSV)
+ : StoreCSVTo(std::move(StoreCSV)) {}
+
ClangTidyProfiling::~ClangTidyProfiling() {
preprocess();
- printProfileData(llvm::errs());
+
+ printUserFriendlyTable(llvm::errs());
+
+ if (StoreCSVTo.hasValue())
+ storeProfileData();
}
} // namespace tidy
Index: clang-tidy/ClangTidyDiagnosticConsumer.h
===================================================================
--- clang-tidy/ClangTidyDiagnosticConsumer.h
+++ clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -168,6 +168,10 @@
void setEnableProfiling(bool Profile);
bool getEnableProfiling() const { return Profile; }
+ /// \brief Control storage of profile date.
+ void setStoreProfile(StringRef ProfilePrefix, StringRef PrefixElide);
+ llvm::Optional<std::string> getStoreProfileFilename() const;
+
/// \brief Should be called when starting to process new translation unit.
void setCurrentBuildDirectory(StringRef BuildDirectory) {
CurrentBuildDirectory = BuildDirectory;
@@ -209,6 +213,8 @@
llvm::DenseMap<unsigned, std::string> CheckNamesByDiagnosticID;
bool Profile;
+ std::string ProfilePrefix;
+ std::string ProfilePrefixElide;
};
/// \brief A diagnostic consumer that turns each \c Diagnostic into a
Index: clang-tidy/ClangTidyDiagnosticConsumer.cpp
===================================================================
--- clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -23,6 +23,7 @@
#include "clang/Frontend/DiagnosticRenderer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Path.h"
#include <tuple>
#include <vector>
using namespace clang;
@@ -235,6 +236,28 @@
void ClangTidyContext::setEnableProfiling(bool P) { Profile = P; }
+void ClangTidyContext::setStoreProfile(StringRef Prefix, StringRef Elide) {
+ ProfilePrefix = Prefix;
+ ProfilePrefixElide = Elide;
+}
+
+llvm::Optional<std::string> ClangTidyContext::getStoreProfileFilename() const {
+ if (ProfilePrefix.empty())
+ return llvm::None;
+
+ SmallString<256> OutputFile(CurrentFile);
+
+ // If the current file starts with ProfilePrefixElide, drop that prefix.
+ llvm::sys::path::replace_path_prefix(OutputFile, ProfilePrefixElide, "");
+
+ // Now, append the current file name (after possibly eliding prefix)
+ // to the output prefix.
+ SmallString<256> FinalName(ProfilePrefix);
+ llvm::sys::path::append(FinalName, OutputFile);
+
+ return Twine(FinalName + ".csv").str();
+}
+
bool ClangTidyContext::isCheckEnabled(StringRef CheckName) const {
assert(CheckFilter != nullptr);
return CheckFilter->contains(CheckName);
Index: clang-tidy/ClangTidy.h
===================================================================
--- clang-tidy/ClangTidy.h
+++ clang-tidy/ClangTidy.h
@@ -228,7 +228,9 @@
const tooling::CompilationDatabase &Compilations,
ArrayRef<std::string> InputFiles,
llvm::IntrusiveRefCntPtr<vfs::FileSystem> BaseFS,
- bool EnableCheckProfile = false);
+ bool EnableCheckProfile = false,
+ llvm::StringRef StoreCheckProfile = StringRef(),
+ llvm::StringRef StoreCheckProfileElide = StringRef());
// FIXME: This interface will need to be significantly extended to be useful.
// FIXME: Implement confidence levels for displaying/fixing errors.
Index: clang-tidy/ClangTidy.cpp
===================================================================
--- clang-tidy/ClangTidy.cpp
+++ clang-tidy/ClangTidy.cpp
@@ -362,7 +362,8 @@
std::unique_ptr<ClangTidyProfiling> Profiling;
if (Context.getEnableProfiling()) {
- Profiling = llvm::make_unique<ClangTidyProfiling>();
+ Profiling = llvm::make_unique<ClangTidyProfiling>(
+ Context.getStoreProfileFilename());
FinderOptions.CheckProfiling.emplace(Profiling->Records);
}
@@ -483,7 +484,8 @@
const CompilationDatabase &Compilations,
ArrayRef<std::string> InputFiles,
llvm::IntrusiveRefCntPtr<vfs::FileSystem> BaseFS,
- bool EnableCheckProfile) {
+ bool EnableCheckProfile, llvm::StringRef StoreCheckProfile,
+ llvm::StringRef StoreCheckProfileElide) {
ClangTool Tool(Compilations, InputFiles,
std::make_shared<PCHContainerOperations>(), BaseFS);
@@ -524,6 +526,7 @@
Tool.appendArgumentsAdjuster(PerFileExtraArgumentsInserter);
Tool.appendArgumentsAdjuster(PluginArgumentsRemover);
Context.setEnableProfiling(EnableCheckProfile);
+ Context.setStoreProfile(StoreCheckProfile, StoreCheckProfileElide);
ClangTidyDiagnosticConsumer DiagConsumer(Context);
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits