Index: clang-tidy/ClangTidy.h =================================================================== --- clang-tidy/ClangTidy.h +++ clang-tidy/ClangTidy.h @@ -227,11 +227,15 @@ /// /// \param EnableCheckProfile If provided, it enables check profile collection /// in MatchFinder, and will contain the result of the profile. +/// \param StoreCheckProfile If provided, and EnableCheckProfile is true, +/// the profile will not be output to stderr, but will instead be stored +/// as a JSON file in the specified directory. void runClangTidy(clang::tidy::ClangTidyContext &Context, const tooling::CompilationDatabase &Compilations, ArrayRef InputFiles, llvm::IntrusiveRefCntPtr BaseFS, - bool EnableCheckProfile = false); + bool EnableCheckProfile = false, + llvm::StringRef StoreCheckProfile = 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 @@ -363,7 +363,8 @@ std::unique_ptr Profiling; if (Context.getEnableProfiling()) { - Profiling = llvm::make_unique(); + Profiling = llvm::make_unique( + Context.getProfileStorageParams()); FinderOptions.CheckProfiling.emplace(Profiling->Records); } @@ -492,7 +493,7 @@ const CompilationDatabase &Compilations, ArrayRef InputFiles, llvm::IntrusiveRefCntPtr BaseFS, - bool EnableCheckProfile) { + bool EnableCheckProfile, llvm::StringRef StoreCheckProfile) { ClangTool Tool(Compilations, InputFiles, std::make_shared(), BaseFS); @@ -533,6 +534,7 @@ Tool.appendArgumentsAdjuster(PerFileExtraArgumentsInserter); Tool.appendArgumentsAdjuster(PluginArgumentsRemover); Context.setEnableProfiling(EnableCheckProfile); + Context.setProfileStoragePrefix(StoreCheckProfile); ClangTidyDiagnosticConsumer DiagConsumer(Context); Index: clang-tidy/ClangTidyDiagnosticConsumer.h =================================================================== --- clang-tidy/ClangTidyDiagnosticConsumer.h +++ clang-tidy/ClangTidyDiagnosticConsumer.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H #include "ClangTidyOptions.h" +#include "ClangTidyProfiling.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Tooling/Core/Diagnostic.h" @@ -169,6 +170,11 @@ void setEnableProfiling(bool Profile); bool getEnableProfiling() const { return Profile; } + /// \brief Control storage of profile date. + void setProfileStoragePrefix(StringRef ProfilePrefix); + llvm::Optional + getProfileStorageParams() const; + /// \brief Should be called when starting to process new translation unit. void setCurrentBuildDirectory(StringRef BuildDirectory) { CurrentBuildDirectory = BuildDirectory; @@ -216,6 +222,7 @@ llvm::DenseMap CheckNamesByDiagnosticID; bool Profile; + std::string ProfilePrefix; bool AllowEnablingAnalyzerAlphaCheckers; }; Index: clang-tidy/ClangTidyDiagnosticConsumer.cpp =================================================================== --- clang-tidy/ClangTidyDiagnosticConsumer.cpp +++ clang-tidy/ClangTidyDiagnosticConsumer.cpp @@ -237,6 +237,18 @@ void ClangTidyContext::setEnableProfiling(bool P) { Profile = P; } +void ClangTidyContext::setProfileStoragePrefix(StringRef Prefix) { + ProfilePrefix = Prefix; +} + +llvm::Optional +ClangTidyContext::getProfileStorageParams() const { + if (ProfilePrefix.empty()) + return llvm::None; + + return ClangTidyProfiling::StorageParams(ProfilePrefix, CurrentFile); +} + 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,12 @@ #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/Chrono.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" +#include #include #include @@ -21,17 +23,34 @@ namespace tidy { class ClangTidyProfiling { - // Time is first to allow for sorting by it. - std::vector> Timers; - llvm::TimeRecord Total; +public: + struct StorageParams { + llvm::sys::TimePoint<> Timestamp; + std::string SourceFilename; + std::string StoreFilename; - void preprocess(); + StorageParams() = default; - void printProfileData(llvm::raw_ostream &OS) const; + StorageParams(llvm::StringRef ProfilePrefix, llvm::StringRef SourceFile); + }; + +private: + llvm::Optional TG; + + llvm::Optional Storage; + + void printUserFriendlyTable(llvm::raw_ostream &OS); + void printAsJSON(llvm::raw_ostream &OS); + + void storeProfileData(); public: llvm::StringMap Records; + ClangTidyProfiling() = default; + + ClangTidyProfiling(llvm::Optional Storage); + ~ClangTidyProfiling(); }; Index: clang-tidy/ClangTidyProfiling.cpp =================================================================== --- clang-tidy/ClangTidyProfiling.cpp +++ clang-tidy/ClangTidyProfiling.cpp @@ -9,56 +9,84 @@ #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/YAMLTraits.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"); +ClangTidyProfiling::StorageParams::StorageParams(llvm::StringRef ProfilePrefix, + llvm::StringRef SourceFile) + : Timestamp(std::chrono::system_clock::now()), SourceFilename(SourceFile) { + llvm::SmallString<32> TimestampStr; + llvm::raw_svector_ostream OS(TimestampStr); + llvm::format_provider::format(Timestamp, OS, + "%Y%m%d%H%M%S%N"); - // We want the measurements to be sorted by decreasing time spent. - llvm::sort(Timers.begin(), Timers.end()); + llvm::SmallString<256> FinalPrefix(ProfilePrefix); + llvm::sys::path::append(FinalPrefix, TimestampStr); + + // So the full output name is: /ProfilePrefix/timestamp-inputfilename.json + StoreFilename = llvm::Twine(FinalPrefix + "-" + + llvm::sys::path::filename(SourceFile) + ".json") + .str(); } -void ClangTidyProfiling::printProfileData(llvm::raw_ostream &OS) const { - std::string Line = "===" + std::string(73, '-') + "===\n"; - OS << Line; - - 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"; - - // 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'; - } - - Total.print(Total, OS); - OS << "Total\n"; - OS << Line << "\n"; +void ClangTidyProfiling::printUserFriendlyTable(llvm::raw_ostream &OS) { + TG->print(OS); OS.flush(); } +void ClangTidyProfiling::printAsJSON(llvm::raw_ostream &OS) { + OS << "{\n"; + OS << "\"file\": \"" << Storage->SourceFilename << "\",\n"; + OS << "\"timestamp\": \"" << Storage->Timestamp << "\",\n"; + OS << "\"profile\": {\n"; + TG->printJSONValues(OS, ""); + OS << "\n}\n"; + OS << "}\n"; + OS.flush(); +} + +void ClangTidyProfiling::storeProfileData() { + assert(Storage.hasValue() && "We should have a filename."); + + llvm::SmallString<256> OutputDirectory(Storage->StoreFilename); + 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(Storage->StoreFilename, EC, llvm::sys::fs::F_None); + if (EC) { + llvm::errs() << "Error opening output file '" << Storage->StoreFilename + << "': " << EC.message() << "\n"; + return; + } + + printAsJSON(OS); +} + +ClangTidyProfiling::ClangTidyProfiling(llvm::Optional Storage) + : Storage(std::move(Storage)) {} + ClangTidyProfiling::~ClangTidyProfiling() { - preprocess(); - printProfileData(llvm::errs()); + TG.emplace("clang-tidy", "clang-tidy checks profiling", Records); + + if (!Storage.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,15 @@ 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 JSON. +)"), + cl::value_desc("prefix"), + cl::cat(ClangTidyCategory)); + /// This option allows enabling the experimental alpha checkers from the static /// analyzer. This option is set to false and not visible in help, because it is /// highly not recommended for users. @@ -331,17 +340,27 @@ if (!OptionsProvider) return 1; + auto MakeAbsolute = [](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 " << Input << ": " + << EC.message() << "\n"; + } + return AbsolutePath; + }; + + SmallString<256> ProfilePrefix = MakeAbsolute(StoreCheckProfile); + StringRef FileName("dummy"); auto PathList = OptionsParser.getSourcePathList(); if (!PathList.empty()) { FileName = PathList.front(); } - SmallString<256> FilePath(FileName); - if (std::error_code EC = llvm::sys::fs::make_absolute(FilePath)) { - llvm::errs() << "Can't make absolute path from " << FileName << ": " - << EC.message() << "\n"; - } + SmallString<256> FilePath = MakeAbsolute(FileName); + ClangTidyOptions EffectiveOptions = OptionsProvider->getOptions(FilePath); std::vector EnabledChecks = getCheckNames(EffectiveOptions, AllowEnablingAnalyzerAlphaCheckers); @@ -403,7 +422,7 @@ ClangTidyContext Context(std::move(OwningOptionsProvider), AllowEnablingAnalyzerAlphaCheckers); runClangTidy(Context, OptionsParser.getCompilations(), PathList, BaseFS, - EnableCheckProfile); + EnableCheckProfile, ProfilePrefix); 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 JSON 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,121 @@ .. 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 JSON. + -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 +746,65 @@ 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 the ``-enable-check-profile`` argument. +The timings will be output to ``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 JSON files for further processing. Example output: + +.. code-block:: console + + $ clang-tidy -enable-check-profile -store-check-profile=. -checks=-*,readability-function-size source.cpp + $ # Note that there won't be timings table printed to the console. + $ ls /tmp/out/ + 20180516161318717446360-source.cpp.json + $ cat 20180516161318717446360-source.cpp.json + { + "file": "/path/to/source.cpp", + "timestamp": "2018-05-16 16:13:18.717446360", + "profile": { + "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 is only one argument that controls 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 JSON. + 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 the + ``/source`` directory. Only the input filename is used, not the full path + to the source file. Additionally, it is prefixed with the current timestamp. + + * If you specify ``-store-check-profile=/tmp``, then the profile will be saved + to ``/tmp/-example.cpp.json`` + + * If you run :program:`clang-tidy` from within ``/foo`` directory, and specify + ``-store-check-profile=.``, then the profile will still be saved to + ``/foo/-example.cpp.json`` 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,37 @@ +// RUN: rm -rf %T/out +// RUN: clang-tidy -enable-check-profile -checks='-*,readability-function-size' -store-check-profile=%T/out %s -- 2>&1 | not FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' -check-prefix=CHECK-CONSOLE %s +// RUN: cat %T/out/*-clang-tidy-store-check-profile-one-tu.cpp.json | FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' -check-prefix=CHECK-FILE %s +// RUN: rm -rf %T/out +// RUN: clang-tidy -enable-check-profile -checks='-*,readability-function-size' -store-check-profile=%T/out %s -- 2>&1 +// RUN: cat %T/out/*-clang-tidy-store-check-profile-one-tu.cpp.json | FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' -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: { +// CHECK-FILE-NEXT:"file": "{{.*}}clang-tidy-store-check-profile-one-tu.cpp", +// CHECK-FILE-NEXT:"timestamp": "{{[0-9]+}}-{{[0-9]+}}-{{[0-9]+}} {{[0-9]+}}:{{[0-9]+}}:{{[0-9]+}}.{{[0-9]+}}", +// CHECK-FILE-NEXT:"profile": { +// CHECK-FILE-NEXT: "time.clang-tidy.readability-function-size.wall": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}}, +// CHECK-FILE-NEXT: "time.clang-tidy.readability-function-size.user": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}}, +// CHECK-FILE-NEXT: "time.clang-tidy.readability-function-size.sys": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}} +// CHECK-FILE-NEXT: } +// CHECK-FILE-NEXT: } + +// CHECK-FILE-NOT: { +// CHECK-FILE-NOT: "file": {{.*}}clang-tidy-store-check-profile-one-tu.cpp{{.*}}, +// CHECK-FILE-NOT: "timestamp": "{{[0-9]+}}-{{[0-9]+}}-{{[0-9]+}} {{[0-9]+}}:{{[0-9]+}}:{{[0-9]+}}.{{[0-9]+}}", +// CHECK-FILE-NOT: "profile": { +// CHECK-FILE-NOT: "time.clang-tidy.readability-function-size.wall": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}}, +// CHECK-FILE-NOT: "time.clang-tidy.readability-function-size.user": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}}, +// CHECK-FILE-NOT: "time.clang-tidy.readability-function-size.sys": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}} +// CHECK-FILE-NOT: } +// CHECK-FILE-NOT: } + +class A { + A() {} + ~A() {} +};