Index: clang-tidy/ClangTidy.h =================================================================== --- clang-tidy/ClangTidy.h +++ clang-tidy/ClangTidy.h @@ -228,7 +228,9 @@ const tooling::CompilationDatabase &Compilations, ArrayRef InputFiles, llvm::IntrusiveRefCntPtr 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 Profiling; if (Context.getEnableProfiling()) { - Profiling = llvm::make_unique(); + Profiling = llvm::make_unique( + Context.getStoreProfileFilename()); FinderOptions.CheckProfiling.emplace(Profiling->Records); } @@ -483,7 +484,8 @@ const CompilationDatabase &Compilations, ArrayRef InputFiles, llvm::IntrusiveRefCntPtr BaseFS, - bool EnableCheckProfile) { + bool EnableCheckProfile, llvm::StringRef StoreCheckProfile, + llvm::StringRef StoreCheckProfileElide) { ClangTool Tool(Compilations, InputFiles, std::make_shared(), BaseFS); @@ -524,6 +526,7 @@ Tool.appendArgumentsAdjuster(PerFileExtraArgumentsInserter); Tool.appendArgumentsAdjuster(PluginArgumentsRemover); Context.setEnableProfiling(EnableCheckProfile); + Context.setStoreProfile(StoreCheckProfile, StoreCheckProfileElide); ClangTidyDiagnosticConsumer DiagConsumer(Context); 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 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 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 #include 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 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 + ".yaml").str(); +} + bool ClangTidyContext::isCheckEnabled(StringRef CheckName) const { assert(CheckFilter != nullptr); return CheckFilter->contains(CheckName); Index: clang-tidy/ClangTidyProfiling.h =================================================================== --- clang-tidy/ClangTidyProfiling.h +++ clang-tidy/ClangTidyProfiling.h @@ -10,10 +10,11 @@ #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 #include #include @@ -21,17 +22,22 @@ namespace tidy { class ClangTidyProfiling { - // Time is first to allow for sorting by it. - std::vector> Timers; - llvm::TimeRecord Total; + llvm::Optional TG; - void preprocess(); + llvm::Optional StoreProfileTo; - void printProfileData(llvm::raw_ostream &OS) const; + void printUserFriendlyTable(llvm::raw_ostream &OS); + void printAsJSON(llvm::raw_ostream &OS); + + void storeProfileData(); public: llvm::StringMap Records; + ClangTidyProfiling() = default; + + ClangTidyProfiling(llvm::Optional StoreProfileTo); + ~ClangTidyProfiling(); }; Index: clang-tidy/ClangTidyProfiling.cpp =================================================================== --- clang-tidy/ClangTidyProfiling.cpp +++ clang-tidy/ClangTidyProfiling.cpp @@ -9,56 +9,58 @@ #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 +#include #define DEBUG_TYPE "clang-tidy-profiling" namespace clang { namespace tidy { -void ClangTidyProfiling::preprocess() { - // Convert from a insertion-friendly map to sort-friendly vector. - Timers.clear(); - Timers.reserve(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()); +void ClangTidyProfiling::printUserFriendlyTable(llvm::raw_ostream &OS) { + TG->print(OS); } -void ClangTidyProfiling::printProfileData(llvm::raw_ostream &OS) const { - std::string Line = "===" + std::string(73, '-') + "===\n"; - OS << Line; +void ClangTidyProfiling::printAsJSON(llvm::raw_ostream &OS) { + TG->printJSONValues(OS, ""); +} - if (Total.getUserTime()) - OS << " ---User Time---"; - if (Total.getSystemTime()) - OS << " --System Time--"; - if (Total.getProcessTime()) - OS << " --User+System--"; - OS << " ---Wall Time---"; - if (Total.getMemUsed()) - OS << " ---Mem---"; - OS << " --- Name ---\n"; +void ClangTidyProfiling::storeProfileData() { + assert(StoreProfileTo.hasValue() && "We should have a filename."); - // 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'; + llvm::SmallString<256> OutputDirectory(*StoreProfileTo); + 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; } - Total.print(Total, OS); - OS << "Total\n"; - OS << Line << "\n"; - OS.flush(); + std::error_code EC; + llvm::raw_fd_ostream OS(*StoreProfileTo, EC, llvm::sys::fs::F_None); + if (EC) { + llvm::errs() << "Error opening output file'" << *StoreProfileTo + << "': " << EC.message() << "\n"; + return; + } + + printAsJSON(OS); } +ClangTidyProfiling::ClangTidyProfiling(llvm::Optional StoreCSV) + : StoreProfileTo(std::move(StoreCSV)) {} + ClangTidyProfiling::~ClangTidyProfiling() { - preprocess(); - printProfileData(llvm::errs()); + TG.emplace("clang-tidy", "clang-tidy checks profiling", Records); + + if (!StoreProfileTo.hasValue()) + printUserFriendlyTable(llvm::errs()); + else + storeProfileData(); } } // namespace tidy Index: clang-tidy/tool/ClangTidyMain.cpp =================================================================== --- clang-tidy/tool/ClangTidyMain.cpp +++ clang-tidy/tool/ClangTidyMain.cpp @@ -181,6 +181,22 @@ cl::init(false), cl::cat(ClangTidyCategory)); +static cl::opt StoreCheckProfile("store-check-profile", + cl::desc(R"( +By default reports are printed in tabulated +format to stderr. When this option is passed, +these per-TU profiles are instead stored as YAML.)"), + cl::value_desc("prefix"), + cl::cat(ClangTidyCategory)); + +static cl::opt 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 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 +339,28 @@ if (!OptionsProvider) return 1; + auto processPrefix = [](const std::string &input) -> SmallString<256> { + if (input.empty()) + return {}; + SmallString<256> AbsolutePath(input); + if (std::error_code EC = llvm::sys::fs::make_absolute(AbsolutePath)) { + llvm::errs() << "Can't make absolute path from " << AbsolutePath << ": " + << EC.message() << "\n"; + } + if (!llvm::sys::fs::exists(AbsolutePath)) { + // If the destination prefix does not exist, don't try to use real_path(). + return AbsolutePath; + } + SmallString<256> dest; + if (std::error_code EC = llvm::sys::fs::real_path(AbsolutePath, dest)) { + llvm::errs() << "Can't make real path from " << AbsolutePath << ": " + << EC.message() << "\n"; + } + return dest; + }; + auto ProfilePrefix = processPrefix(StoreCheckProfile); + auto ProfileElidePrefix = processPrefix(StoreCheckProfileElidePrefix); + 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 Errors = Context.getErrors(); bool FoundErrors = llvm::find_if(Errors, [](const ClangTidyError &E) { return E.DiagLevel == ClangTidyError::Error; Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -57,6 +57,9 @@ Improvements to clang-tidy -------------------------- +- The checks profiling info can now be stored as YAML files for futher + post-processing and analysis. + - New module `abseil` for checks related to the `Abseil `_ library. Index: docs/clang-tidy/index.rst =================================================================== --- docs/clang-tidy/index.rst +++ docs/clang-tidy/index.rst @@ -99,114 +99,125 @@ .. code-block:: console - $ clang-tidy -help + $ clang-tidy --help USAGE: clang-tidy [options] [... ] 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= - - 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= - - 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= - - YAML file to store suggested fixes in. The - stored fixes can be applied to the input source - code with clang-apply-replacements. - -extra-arg= - Additional argument to append to the compiler command line - -extra-arg-before= - 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= - - 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 - - '{ }' 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= - - 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= - - 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= - 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= - - 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= - + 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= - + 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= - + YAML file to store suggested fixes in. The + stored fixes can be applied to the input source + code with clang-apply-replacements. + -extra-arg= - Additional argument to append to the compiler command line + -extra-arg-before= - 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= - + 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 + - '{ }' 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= - + 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= - + 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= - 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= - + By default reports are printed in tabulated + format to stderr. When this option is passed, + these per-TU profiles are instead stored as YAML. + -store-check-profile-elide-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= - + Overlay the virtual filesystem described by file + over the real file system. + -warnings-as-errors= - + 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 is used to read a compile command database. @@ -739,3 +750,74 @@ 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 + ===-------------------------------------------------------------------------=== + clang-tidy checks profiling + ===-------------------------------------------------------------------------=== + Total Execution Time: 1.0282 seconds (1.0258 wall clock) + + ---User Time--- --System Time-- --User+System-- ---Wall Time--- --- Name --- + 0.9136 (100.0%) 0.1146 (100.0%) 1.0282 (100.0%) 1.0258 (100.0%) readability-function-size + 0.9136 (100.0%) 0.1146 (100.0%) 1.0282 (100.0%) 1.0258 (100.0%) Total + +It can also store that data as YAML 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 + $ # Note that there won't be timings table printed to the console. + $ cat .yaml + "time.clang-tidy.readability-function-size.wall": 1.0421266555786133e+00, + "time.clang-tidy.readability-function-size.user": 9.2088400000005421e-01, + "time.clang-tidy.readability-function-size.sys": 1.2418899999999974e-01 + +There are two arguments that control profile storage: + +* ``-store-check-profile=`` + + By default reports are printed in tabulated format to stderr. When this option + is passed, these per-TU profiles are instead stored as YAML. + 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.yaml`` + + * 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.yaml`` +* ``-store-check-profile-elide-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.yaml`` + + * 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.yaml`` Index: test/clang-tidy/clang-tidy-enable-check-profile-one-tu.cpp =================================================================== --- test/clang-tidy/clang-tidy-enable-check-profile-one-tu.cpp +++ test/clang-tidy/clang-tidy-enable-check-profile-one-tu.cpp @@ -1,16 +1,22 @@ // RUN: clang-tidy -enable-check-profile -checks='-*,readability-function-size' %s 2>&1 | FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' %s // CHECK: ===-------------------------------------------------------------------------=== -// CHECK-NEXT: {{.*}} --- Name --- +// CHECK-NEXT: clang-tidy checks profiling +// CHECK-NEXT: ===-------------------------------------------------------------------------=== +// CHECK-NEXT: Total Execution Time: {{.*}} seconds ({{.*}} wall clock) + +// CHECK: {{.*}} --- Name --- // CHECK-NEXT: {{.*}} readability-function-size // CHECK-NEXT: {{.*}} Total -// CHECK-NEXT: ===-------------------------------------------------------------------------=== // CHECK-NOT: ===-------------------------------------------------------------------------=== +// CHECK-NOT: clang-tidy checks profiling +// CHECK-NOT: ===-------------------------------------------------------------------------=== +// CHECK-NOT: Total Execution Time: {{.*}} seconds ({{.*}} wall clock) + // CHECK-NOT: {{.*}} --- Name --- // CHECK-NOT: {{.*}} readability-function-size // CHECK-NOT: {{.*}} Total -// CHECK-NOT: ===-------------------------------------------------------------------------=== class A { A() {} Index: test/clang-tidy/clang-tidy-enable-check-profile-two-tu.cpp =================================================================== --- test/clang-tidy/clang-tidy-enable-check-profile-two-tu.cpp +++ test/clang-tidy/clang-tidy-enable-check-profile-two-tu.cpp @@ -1,22 +1,31 @@ // RUN: clang-tidy -enable-check-profile -checks='-*,readability-function-size' %s %s 2>&1 | FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' %s // CHECK: ===-------------------------------------------------------------------------=== -// CHECK-NEXT: {{.*}} --- Name --- +// CHECK-NEXT: clang-tidy checks profiling +// CHECK-NEXT: ===-------------------------------------------------------------------------=== +// CHECK-NEXT: Total Execution Time: {{.*}} seconds ({{.*}} wall clock) + +// CHECK: {{.*}} --- Name --- // CHECK-NEXT: {{.*}} readability-function-size // CHECK-NEXT: {{.*}} Total -// CHECK-NEXT: ===-------------------------------------------------------------------------=== // CHECK: ===-------------------------------------------------------------------------=== -// CHECK-NEXT: {{.*}} --- Name --- +// CHECK-NEXT: clang-tidy checks profiling +// CHECK-NEXT: ===-------------------------------------------------------------------------=== +// CHECK-NEXT: Total Execution Time: {{.*}} seconds ({{.*}} wall clock) + +// CHECK: {{.*}} --- Name --- // CHECK-NEXT: {{.*}} readability-function-size // CHECK-NEXT: {{.*}} Total -// CHECK-NEXT: ===-------------------------------------------------------------------------=== // CHECK-NOT: ===-------------------------------------------------------------------------=== +// CHECK-NOT: clang-tidy checks profiling +// CHECK-NOT: ===-------------------------------------------------------------------------=== +// CHECK-NOT: Total Execution Time: {{.*}} seconds ({{.*}} wall clock) + // CHECK-NOT: {{.*}} --- Name --- // CHECK-NOT: {{.*}} readability-function-size // CHECK-NOT: {{.*}} Total -// CHECK-NOT: ===-------------------------------------------------------------------------=== class A { A() {} 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/.yaml -check-prefix=CHECK-FILE %s +// RUN: clang-tidy -enable-check-profile -checks='-*,readability-function-size' -store-check-profile=%T/out -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/out/.yaml -check-prefix=CHECK-FILE %s + +// CHECK-CONSOLE-NOT: ===-------------------------------------------------------------------------=== +// CHECK-CONSOLE-NOT: {{.*}} --- Name --- +// CHECK-CONSOLE-NOT: {{.*}} readability-function-size +// CHECK-CONSOLE-NOT: {{.*}} Total +// CHECK-CONSOLE-NOT: ===-------------------------------------------------------------------------=== + +// CHECK-FILE: "time.clang-tidy.readability-function-size.wall": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}}, + +class A { + A() {} + ~A() {} +};