Add clang-format configuration and reformat src/ and test/ sources
authorMilian Wolff <mail@milianw.de>
Sat, 28 Jan 2017 22:41:50 +0000 (23:41 +0100)
committerMilian Wolff <mail@milianw.de>
Sat, 28 Jan 2017 22:41:50 +0000 (23:41 +0100)
52 files changed:
.clang-format [new file with mode: 0644]
src/analyze/accumulatedtracedata.cpp
src/analyze/accumulatedtracedata.h
src/analyze/allocationdata.h
src/analyze/gui/callercalleemodel.cpp
src/analyze/gui/callercalleemodel.h
src/analyze/gui/chartmodel.cpp
src/analyze/gui/chartmodel.h
src/analyze/gui/chartproxy.h
src/analyze/gui/chartwidget.cpp
src/analyze/gui/costdelegate.cpp
src/analyze/gui/costdelegate.h
src/analyze/gui/flamegraph.cpp
src/analyze/gui/flamegraph.h
src/analyze/gui/gui.cpp
src/analyze/gui/histogrammodel.cpp
src/analyze/gui/histogrammodel.h
src/analyze/gui/histogramwidget.cpp
src/analyze/gui/histogramwidget.h
src/analyze/gui/locationdata.h
src/analyze/gui/mainwindow.cpp
src/analyze/gui/mainwindow.h
src/analyze/gui/modeltest.cpp
src/analyze/gui/modeltest.h
src/analyze/gui/parser.cpp
src/analyze/gui/parser.h
src/analyze/gui/summarydata.h
src/analyze/gui/topproxy.cpp
src/analyze/gui/topproxy.h
src/analyze/gui/treemodel.cpp
src/analyze/gui/treemodel.h
src/analyze/gui/treeproxy.h
src/analyze/print/heaptrack_print.cpp
src/interpret/heaptrack_interpret.cpp
src/track/heaptrack_api.h
src/track/heaptrack_inject.cpp
src/track/heaptrack_preload.cpp
src/track/libheaptrack.cpp
src/track/libheaptrack.h
src/track/trace.h
src/track/tracetree.h
src/util/indices.h
src/util/linereader.h
src/util/pointermap.h
tests/auto/tst_trace.cpp
tests/benchmarks/bench_pointermap.cpp
tests/benchmarks/bench_pointers.h
tests/benchmarks/bench_pointersparsehash.cpp
tests/benchmarks/measure_malloc_overhead.cpp
tests/manual/lib.cpp
tests/manual/test.cpp
tests/manual/threaded.cpp

diff --git a/.clang-format b/.clang-format
new file mode 100644 (file)
index 0000000..af53af2
--- /dev/null
@@ -0,0 +1,47 @@
+---
+BasedOnStyle:  WebKit
+Language:        Cpp
+AlignAfterOpenBracket: true
+AlwaysBreakTemplateDeclarations: true
+BreakBeforeBraces: Custom
+BreakConstructorInitializersBeforeComma: true
+BreakBeforeBinaryOperators: NonAssignment
+BraceWrapping:
+    AfterClass: true
+    AfterControlStatement: false
+    AfterEnum: true
+    AfterFunction: true
+    AfterNamespace: false
+    AfterObjCDeclaration: false
+    AfterStruct: true
+    AfterUnion: false
+    BeforeCatch: false
+    BeforeElse: false
+    IndentBraces: false
+ColumnLimit: 120
+Standard:        Cpp11
+IndentWidth:     4
+TabWidth:        8
+UseTab:          Never
+PointerAlignment: Left
+SpacesInParentheses: false
+SpacesInAngles:  false
+SpaceInEmptyParentheses: false
+SpacesInCStyleCastParentheses: false
+SpaceAfterControlStatementKeyword: true
+SpaceBeforeAssignmentOperators: true
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+IncludeCategories:
+  - Regex:           '^<boost/'
+    Priority:        1
+  - Regex:           '^<Q'
+    Priority:        2
+AllowShortFunctionsOnASingleLine: None
+ForEachMacros:   [ foreach, Q_FOREACH, BOOST_FOREACH, forever, Q_FOREVER, QBENCHMARK, QBENCHMARK_ONCE, TEST_CASE, SECTION ]
+NamespaceIndentation: None
+# Only for newer clang-format versions
+#MacroBlockBegin: BEGINTESTFUNCIMPL
+#MacroBlockEnd: ENDTESTFUNCIMPL
+...
+
index 5a28300..ab0c3f4 100644 (file)
 
 #include "accumulatedtracedata.h"
 
-#include <iostream>
-#include <memory>
 #include <algorithm>
 #include <cassert>
+#include <iostream>
+#include <memory>
 
-#include <boost/iostreams/filtering_stream.hpp>
-#include <boost/iostreams/filter/gzip.hpp>
 #include <boost/algorithm/string/predicate.hpp>
+#include <boost/iostreams/filter/gzip.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
 
-#include "util/linereader.h"
 #include "util/config.h"
+#include "util/linereader.h"
 #include "util/pointermap.h"
 
 #ifdef __GNUC__
-#define POTENTIALLY_UNUSED __attribute__ ((unused))
+#define POTENTIALLY_UNUSED __attribute__((unused))
 #else
 #define POTENTIALLY_UNUSED
 #endif
@@ -42,19 +42,18 @@ using namespace std;
 
 namespace {
 
-template<typename Base>
-bool operator>>(LineReader& reader, Index<Base> &index)
+template <typename Base>
+bool operator>>(LineReader& reader, Index<Base>index)
 {
     return reader.readHex(index.index);
 }
 
-template<typename Base>
-ostream& operator<<(ostream &out, const Index<Base> index)
+template <typename Base>
+ostream& operator<<(ostreamout, const Index<Base> index)
 {
     out << index.index;
     return out;
 }
-
 }
 
 AccumulatedTraceData::AccumulatedTraceData()
@@ -144,20 +143,14 @@ bool AccumulatedTraceData::read(istream& in)
 
     vector<string> opNewStrings = {
         // 64 bit
-        "operator new(unsigned long)",
-        "operator new[](unsigned long)",
+        "operator new(unsigned long)", "operator new[](unsigned long)",
         // 32 bit
-        "operator new(unsigned int)",
-        "operator new[](unsigned int)",
+        "operator new(unsigned int)", "operator new[](unsigned int)",
     };
     vector<StringIndex> opNewStrIndices;
     opNewStrIndices.reserve(opNewStrings.size());
 
-    vector<string> stopStrings = {
-        "main",
-        "__libc_start_main",
-        "__static_initialization_and_destruction_0"
-    };
+    vector<string> stopStrings = {"main", "__libc_start_main", "__static_initialization_and_destruction_0"};
 
     const bool reparsing = totalTime != 0;
     m_maxAllocationTraceIndex.index = 0;
@@ -233,7 +226,8 @@ bool AccumulatedTraceData::read(istream& in)
                     cerr << "failed to parse line: " << reader.line() << endl;
                     continue;
                 } else if (allocationIndex.index >= allocationInfos.size()) {
-                    cerr << "allocation index out of bounds: " << allocationIndex.index << ", maximum is: " << allocationInfos.size() << endl;
+                    cerr << "allocation index out of bounds: " << allocationIndex.index
+                         << ", maximum is: " << allocationInfos.size() << endl;
                     continue;
                 }
                 info = allocationInfos[allocationIndex.index];
@@ -344,10 +338,11 @@ bool AccumulatedTraceData::read(istream& in)
                 fileVersion = 1;
             }
             if (fileVersion > HEAPTRACK_FILE_FORMAT_VERSION) {
-                cerr << "The data file has version " << hex << fileVersion
-                     << " (written by heaptrack version " << hex << heaptrackVersion << ")\n"
-                     << "This is not compatible with this build of heaptrack (version " << hex << HEAPTRACK_VERSION << ")"
-                     << ", which can read file format version " << hex << HEAPTRACK_FILE_FORMAT_VERSION << " and below" << endl;
+                cerr << "The data file has version " << hex << fileVersion << " and was written by heaptrack version "
+                     << hex << heaptrackVersion << ")\n"
+                     << "This is not compatible with this build of heaptrack (version " << hex << HEAPTRACK_VERSION
+                     << "), which can read file format version " << hex << HEAPTRACK_FILE_FORMAT_VERSION << " and below"
+                     << endl;
                 return false;
             }
         } else if (reader.mode() == 'I') { // system information
@@ -369,7 +364,7 @@ bool AccumulatedTraceData::read(istream& in)
 
 namespace { // helpers for diffing
 
-template<typename IndexT, typename SortF>
+template <typename IndexT, typename SortF>
 vector<IndexT> sortedIndices(size_t numIndices, SortF sorter)
 {
     vector<IndexT> indices;
@@ -411,16 +406,15 @@ vector<StringIndex> remapStrings(vector<string>& lhs, const vector<string>& rhs)
     return map;
 }
 
-template<typename T>
+template <typename T>
 inline const T& identity(const T& t)
 {
     return t;
 }
 
-template<typename IpMapper>
-int compareTraceIndices(const TraceIndex &lhs, const AccumulatedTraceData& lhsData,
-                          const TraceIndex &rhs, const AccumulatedTraceData& rhsData,
-                          IpMapper ipMapper)
+template <typename IpMapper>
+int compareTraceIndices(const TraceIndex& lhs, const AccumulatedTraceData& lhsData, const TraceIndex& rhs,
+                        const AccumulatedTraceData& rhsData, IpMapper ipMapper)
 {
     if (!lhs && !rhs) {
         return 0;
@@ -436,7 +430,8 @@ int compareTraceIndices(const TraceIndex &lhs, const AccumulatedTraceData& lhsDa
     const auto& lhsTrace = lhsData.findTrace(lhs);
     const auto& rhsTrace = rhsData.findTrace(rhs);
 
-    const int parentComparsion = compareTraceIndices(lhsTrace.parentIndex, lhsData, rhsTrace.parentIndex, rhsData, ipMapper);
+    const int parentComparsion =
+        compareTraceIndices(lhsTrace.parentIndex, lhsData, rhsTrace.parentIndex, rhsData, ipMapper);
     if (parentComparsion != 0) {
         return parentComparsion;
     } // else fall-through to below, parents are equal
@@ -454,11 +449,9 @@ POTENTIALLY_UNUSED void printTrace(const AccumulatedTraceData& data, TraceIndex
     do {
         const auto trace = data.findTrace(index);
         const auto& ip = data.findIp(trace.ipIndex);
-        cerr << index << " (" << trace.ipIndex << ", " << trace.parentIndex << ")"
-            << '\t' << data.stringify(ip.functionIndex)
-            << " in " << data.stringify(ip.moduleIndex)
-            << " at " << data.stringify(ip.fileIndex) << ':' << ip.line
-            << '\n';
+        cerr << index << " (" << trace.ipIndex << ", " << trace.parentIndex << ")" << '\t'
+             << data.stringify(ip.functionIndex) << " in " << data.stringify(ip.moduleIndex) << " at "
+             << data.stringify(ip.fileIndex) << ':' << ip.line << '\n';
         index = trace.parentIndex;
     } while (index);
     cerr << "---\n";
@@ -479,15 +472,13 @@ void AccumulatedTraceData::diff(const AccumulatedTraceData& base)
     allocationTraceNodes.reserve(allocations.size());
     for (auto it = allocations.begin(); it != allocations.end();) {
         const auto& allocation = *it;
-        auto sortedIt = lower_bound(allocationTraceNodes.begin(), allocationTraceNodes.end(), allocation.traceIndex,
-            [this] (const TraceIndex& lhs, const TraceIndex& rhs) -> bool {
-                return compareTraceIndices(lhs, *this,
-                                           rhs, *this,
-                                           identity<InstructionPointer>) < 0;
-            });
+        auto sortedIt =
+            lower_bound(allocationTraceNodes.begin(), allocationTraceNodes.end(), allocation.traceIndex,
+                        [this](const TraceIndex& lhs, const TraceIndex& rhs) -> bool {
+                            return compareTraceIndices(lhs, *this, rhs, *this, identity<InstructionPointer>) < 0;
+                        });
         if (sortedIt == allocationTraceNodes.end()
-            || compareTraceIndices(allocation.traceIndex, *this, *sortedIt, *this, identity<InstructionPointer>) != 0)
-        {
+            || compareTraceIndices(allocation.traceIndex, *this, *sortedIt, *this, identity<InstructionPointer>) != 0) {
             allocationTraceNodes.insert(sortedIt, allocation.traceIndex);
             ++it;
         } else if (*sortedIt != allocation.traceIndex) {
@@ -501,12 +492,12 @@ void AccumulatedTraceData::diff(const AccumulatedTraceData& base)
     // step 3: map string indices from rhs to lhs data
 
     const auto& stringMap = remapStrings(strings, base.strings);
-    auto remapString = [&stringMap] (StringIndex& index) {
+    auto remapString = [&stringMap](StringIndex& index) {
         if (index) {
             index.index = stringMap[index.index].index;
         }
     };
-    auto remapIp = [&remapString] (InstructionPointer ip) -> InstructionPointer {
+    auto remapIp = [&remapString](InstructionPointer ip) -> InstructionPointer {
         remapString(ip.moduleIndex);
         remapString(ip.functionIndex);
         remapString(ip.fileIndex);
@@ -516,14 +507,13 @@ void AccumulatedTraceData::diff(const AccumulatedTraceData& base)
     // step 4: iterate over rhs data and find matching traces
     //         if no match is found, copy the data over
 
-    auto sortedIps = sortedIndices<IpIndex>(instructionPointers.size(),
-        [this] (const IpIndex &lhs, const IpIndex &rhs) {
-            return findIp(lhs).compareWithoutAddress(findIp(rhs));
-        });
+    auto sortedIps = sortedIndices<IpIndex>(instructionPointers.size(), [this](const IpIndex& lhs, const IpIndex& rhs) {
+        return findIp(lhs).compareWithoutAddress(findIp(rhs));
+    });
 
     // map an IpIndex from the rhs data into the lhs data space, or copy the data
     // if it does not exist yet
-    auto remapIpIndex = [&sortedIps, this, &base, &remapIp] (IpIndex rhsIndex) -> IpIndex {
+    auto remapIpIndex = [&sortedIps, this, &base, &remapIp](IpIndex rhsIndex) -> IpIndex {
         if (!rhsIndex) {
             return rhsIndex;
         }
@@ -532,7 +522,7 @@ void AccumulatedTraceData::diff(const AccumulatedTraceData& base)
         const auto& lhsIp = remapIp(rhsIp);
 
         auto it = lower_bound(sortedIps.begin(), sortedIps.end(), lhsIp,
-                              [this] (const IpIndex &lhs, const InstructionPointer &rhs) {
+                              [this](const IpIndex& lhs, const InstructionPointer& rhs) {
                                   return findIp(lhs).compareWithoutAddress(rhs);
                               });
         if (it != sortedIps.end() && findIp(*it).equalWithoutAddress(lhsIp)) {
@@ -548,8 +538,10 @@ void AccumulatedTraceData::diff(const AccumulatedTraceData& base)
         return ret;
     };
 
-    // copy the rhs trace index and the data it references into the lhs data, recursively
-    function<TraceIndex (TraceIndex)> copyTrace = [this, &base, remapIpIndex, &copyTrace] (TraceIndex rhsIndex) -> TraceIndex {
+    // copy the rhs trace index and the data it references into the lhs data,
+    // recursively
+    function<TraceIndex(TraceIndex)> copyTrace = [this, &base, remapIpIndex,
+                                                  &copyTrace](TraceIndex rhsIndex) -> TraceIndex {
         if (!rhsIndex) {
             return rhsIndex;
         }
@@ -569,21 +561,20 @@ void AccumulatedTraceData::diff(const AccumulatedTraceData& base)
     };
 
     // find an equivalent trace or copy the data over if it does not exist yet
-    // a trace is equivalent if the complete backtrace has equal InstructionPointer
+    // a trace is equivalent if the complete backtrace has equal
+    // InstructionPointer
     // data while ignoring the actual pointer address
-    auto remapTrace = [&base, &allocationTraceNodes, this, remapIp, copyTrace] (TraceIndex rhsIndex) -> TraceIndex {
+    auto remapTrace = [&base, &allocationTraceNodes, this, remapIp, copyTrace](TraceIndex rhsIndex) -> TraceIndex {
         if (!rhsIndex) {
             return rhsIndex;
         }
 
         auto it = lower_bound(allocationTraceNodes.begin(), allocationTraceNodes.end(), rhsIndex,
-            [&base, this, remapIp] (const TraceIndex& lhs, const TraceIndex& rhs) -> bool {
-                return compareTraceIndices(lhs, *this, rhs, base, remapIp) < 0;
-            });
+                              [&base, this, remapIp](const TraceIndex& lhs, const TraceIndex& rhs) -> bool {
+                                  return compareTraceIndices(lhs, *this, rhs, base, remapIp) < 0;
+                              });
 
-        if (it != allocationTraceNodes.end()
-            && compareTraceIndices(*it, *this, rhsIndex, base, remapIp) == 0)
-        {
+        if (it != allocationTraceNodes.end() && compareTraceIndices(*it, *this, rhsIndex, base, remapIp) == 0) {
             return *it;
         }
 
@@ -594,7 +585,8 @@ void AccumulatedTraceData::diff(const AccumulatedTraceData& base)
 
     for (const auto& rhsAllocation : base.allocations) {
         const auto lhsTrace = remapTrace(rhsAllocation.traceIndex);
-        assert(base.findIp(base.findTrace(rhsAllocation.traceIndex).ipIndex).equalWithoutAddress(findIp(findTrace(lhsTrace).ipIndex)));
+        assert(base.findIp(base.findTrace(rhsAllocation.traceIndex).ipIndex)
+                   .equalWithoutAddress(findIp(findTrace(lhsTrace).ipIndex)));
         findAllocation(lhsTrace) -= rhsAllocation;
     }
 
@@ -603,9 +595,8 @@ void AccumulatedTraceData::diff(const AccumulatedTraceData& base)
     //         we can still end up with merged backtraces that have a total
     //         of 0, but different "tails" of different origin with non-zero cost
     allocations.erase(remove_if(allocations.begin(), allocations.end(),
-        [] (const Allocation& allocation) -> bool {
-            return allocation == AllocationData();
-        }), allocations.end());
+                                [](const Allocation& allocation) -> bool { return allocation == AllocationData(); }),
+                      allocations.end());
 }
 
 Allocation& AccumulatedTraceData::findAllocation(const TraceIndex traceIndex)
@@ -613,9 +604,9 @@ Allocation& AccumulatedTraceData::findAllocation(const TraceIndex traceIndex)
     if (traceIndex < m_maxAllocationTraceIndex) {
         // only need to search when the trace index is previously known
         auto it = lower_bound(allocations.begin(), allocations.end(), traceIndex,
-                            [] (const Allocation& allocation, const TraceIndex traceIndex) -> bool {
-                                return allocation.traceIndex < traceIndex;
-                            });
+                              [](const Allocation& allocation, const TraceIndex traceIndex) -> bool {
+                                  return allocation.traceIndex < traceIndex;
+                              });
         if (it == allocations.end() || it->traceIndex != traceIndex) {
             Allocation allocation;
             allocation.traceIndex = traceIndex;
index 9804cf9..4833653 100644 (file)
 #include <vector>
 
 #include <fstream>
+#include <map>
 #include <unordered_map>
 #include <unordered_set>
-#include <map>
+
 #include <boost/functional/hash.hpp>
 
-#include "util/indices.h"
 #include "allocationdata.h"
+#include "util/indices.h"
 
 struct InstructionPointer
 {
@@ -41,13 +42,13 @@ struct InstructionPointer
     FileIndex fileIndex;
     int line = 0;
 
-    bool compareWithoutAddress(const InstructionPointer &other) const
+    bool compareWithoutAddress(const InstructionPointerother) const
     {
         return std::tie(moduleIndex, functionIndex, fileIndex, line)
-             < std::tie(other.moduleIndex, other.functionIndex, other.fileIndex, other.line);
+            < std::tie(other.moduleIndex, other.functionIndex, other.fileIndex, other.line);
     }
 
-    bool equalWithoutAddress(const InstructionPointer &other) const
+    bool equalWithoutAddress(const InstructionPointerother) const
     {
         return std::tie(moduleIndex, functionIndex, fileIndex, line)
             == std::tie(other.moduleIndex, other.functionIndex, other.fileIndex, other.line);
@@ -106,7 +107,8 @@ struct AccumulatedTraceData
     int64_t peakTime = 0;
     int64_t peakRSS = 0;
 
-    struct SystemInfo {
+    struct SystemInfo
+    {
         int64_t pages = 0;
         int64_t pageSize = 0;
     };
@@ -125,7 +127,8 @@ struct AccumulatedTraceData
 
     bool isStopIndex(const StringIndex index) const;
 
-    // indices of functions that should stop the backtrace, e.g. main or static initialization
+    // indices of functions that should stop the backtrace, e.g. main or static
+    // initialization
     std::vector<StringIndex> stopIndices;
     std::vector<InstructionPointer> instructionPointers;
     std::vector<TraceNode> traces;
index 3c0e7ba..891ec50 100644 (file)
@@ -38,11 +38,8 @@ struct AllocationData
 
 inline bool operator==(const AllocationData& lhs, const AllocationData& rhs)
 {
-    return lhs.allocations == rhs.allocations
-        && lhs.temporary == rhs.temporary
-        && lhs.allocated == rhs.allocated
-        && lhs.leaked == rhs.leaked
-        && lhs.peak == rhs.peak;
+    return lhs.allocations == rhs.allocations && lhs.temporary == rhs.temporary && lhs.allocated == rhs.allocated
+        && lhs.leaked == rhs.leaked && lhs.peak == rhs.peak;
 }
 
 inline AllocationData& operator+=(AllocationData& lhs, const AllocationData& rhs)
index 82912fa..dde6e92 100644 (file)
@@ -25,7 +25,7 @@
 
 #include <cmath>
 
-namespace{
+namespace {
 /// TODO: share code
 QString basename(const QString& path)
 {
@@ -48,95 +48,112 @@ QVariant CallerCalleeModel::headerData(int section, Qt::Orientation orientation,
         return {};
     }
     if (role == Qt::InitialSortOrderRole) {
-        if (section == SelfAllocatedColumn || section == SelfAllocationsColumn
-            || section == SelfPeakColumn || section == SelfLeakedColumn
-            || section == SelfTemporaryColumn
-            || section == InclusiveAllocatedColumn || section == InclusiveAllocationsColumn
-            || section == InclusivePeakColumn || section == InclusiveLeakedColumn
-            || section == InclusiveTemporaryColumn)
-        {
+        if (section == SelfAllocatedColumn || section == SelfAllocationsColumn || section == SelfPeakColumn
+            || section == SelfLeakedColumn || section == SelfTemporaryColumn || section == InclusiveAllocatedColumn
+            || section == InclusiveAllocationsColumn || section == InclusivePeakColumn
+            || section == InclusiveLeakedColumn || section == InclusiveTemporaryColumn) {
             return Qt::DescendingOrder;
         }
     }
     if (role == Qt::DisplayRole) {
         switch (static_cast<Columns>(section)) {
-            case FileColumn:
-                return i18n("File");
-            case LineColumn:
-                return i18n("Line");
-            case FunctionColumn:
-                return i18n("Function");
-            case ModuleColumn:
-                return i18n("Module");
-            case SelfAllocationsColumn:
-                return i18n("Allocations (Self)");
-            case SelfTemporaryColumn:
-                return i18n("Temporary (Self)");
-            case SelfPeakColumn:
-                return i18n("Peak (Self)");
-            case SelfLeakedColumn:
-                return i18n("Leaked (Self)");
-            case SelfAllocatedColumn:
-                return i18n("Allocated (Self)");
-            case InclusiveAllocationsColumn:
-                return i18n("Allocations (Incl.)");
-            case InclusiveTemporaryColumn:
-                return i18n("Temporary (Incl.)");
-            case InclusivePeakColumn:
-                return i18n("Peak (Incl.)");
-            case InclusiveLeakedColumn:
-                return i18n("Leaked (Incl.)");
-            case InclusiveAllocatedColumn:
-                return i18n("Allocated (Incl.)");
-            case LocationColumn:
-                return i18n("Location");
-            case NUM_COLUMNS:
-                break;
+        case FileColumn:
+            return i18n("File");
+        case LineColumn:
+            return i18n("Line");
+        case FunctionColumn:
+            return i18n("Function");
+        case ModuleColumn:
+            return i18n("Module");
+        case SelfAllocationsColumn:
+            return i18n("Allocations (Self)");
+        case SelfTemporaryColumn:
+            return i18n("Temporary (Self)");
+        case SelfPeakColumn:
+            return i18n("Peak (Self)");
+        case SelfLeakedColumn:
+            return i18n("Leaked (Self)");
+        case SelfAllocatedColumn:
+            return i18n("Allocated (Self)");
+        case InclusiveAllocationsColumn:
+            return i18n("Allocations (Incl.)");
+        case InclusiveTemporaryColumn:
+            return i18n("Temporary (Incl.)");
+        case InclusivePeakColumn:
+            return i18n("Peak (Incl.)");
+        case InclusiveLeakedColumn:
+            return i18n("Leaked (Incl.)");
+        case InclusiveAllocatedColumn:
+            return i18n("Allocated (Incl.)");
+        case LocationColumn:
+            return i18n("Location");
+        case NUM_COLUMNS:
+            break;
         }
     } else if (role == Qt::ToolTipRole) {
         switch (static_cast<Columns>(section)) {
-            case FileColumn:
-                return i18n("<qt>The file where the allocation function was called from. "
-                            "May be empty when debug information is missing.</qt>");
-            case LineColumn:
-                return i18n("<qt>The line number where the allocation function was called from. "
-                            "May be empty when debug information is missing.</qt>");
-            case FunctionColumn:
-                return i18n("<qt>The parent function that called an allocation function. "
-                            "May be unknown when debug information is missing.</qt>");
-            case ModuleColumn:
-                return i18n("<qt>The module, i.e. executable or shared library, from which an allocation function was called.</qt>");
-            case SelfAllocationsColumn:
-                return i18n("<qt>The number of times an allocation function was directly called from this location.</qt>");
-            case SelfTemporaryColumn:
-                return i18n("<qt>The number of direct temporary allocations. These allocations are directly followed by a free without any other allocations in-between.</qt>");
-            case SelfPeakColumn:
-                return i18n("<qt>The maximum heap memory in bytes consumed from allocations originating directly at this location. "
-                            "This takes deallocations into account.</qt>");
-            case SelfLeakedColumn:
-                return i18n("<qt>The bytes allocated directly at this location that have not been deallocated.</qt>");
-            case SelfAllocatedColumn:
-                return i18n("<qt>The sum of all bytes directly allocated from this location, ignoring deallocations.</qt>");
-            case InclusiveAllocationsColumn:
-                return i18n("<qt>The inclusive number of times an allocation function was called from this location or any functions called from here.</qt>");
-            case InclusiveTemporaryColumn:
-                return i18n("<qt>The number of inclusive temporary allocations. These allocations are directly followed by a free without any other allocations in-between.</qt>");
-            case InclusivePeakColumn:
-                return i18n("<qt>The inclusive maximum heap memory in bytes consumed from allocations originating at this location or from functions called from here. "
-                            "This takes deallocations into account.</qt>");
-            case InclusiveLeakedColumn:
-                return i18n("<qt>The bytes allocated at this location that have not been deallocated.</qt>");
-            case InclusiveAllocatedColumn:
-                return i18n("<qt>The inclusive sum of all bytes allocated from this location or functions called from here, ignoring deallocations.</qt>");
-            case LocationColumn:
-                return i18n("<qt>The location from which an allocation function was called. Function symbol and file information "
-                            "may be unknown when debug information was missing when heaptrack was run.</qt>");
-            case NUM_COLUMNS:
-                break;
+        case FileColumn:
+            return i18n("<qt>The file where the allocation function was called from. "
+                        "May be empty when debug information is missing.</qt>");
+        case LineColumn:
+            return i18n("<qt>The line number where the allocation function was called from. "
+                        "May be empty when debug information is missing.</qt>");
+        case FunctionColumn:
+            return i18n("<qt>The parent function that called an allocation function. "
+                        "May be unknown when debug information is missing.</qt>");
+        case ModuleColumn:
+            return i18n("<qt>The module, i.e. executable or shared library, from "
+                        "which an allocation function was "
+                        "called.</qt>");
+        case SelfAllocationsColumn:
+            return i18n("<qt>The number of times an allocation function was directly "
+                        "called from this location.</qt>");
+        case SelfTemporaryColumn:
+            return i18n("<qt>The number of direct temporary allocations. These "
+                        "allocations are directly followed by a "
+                        "free without any other allocations in-between.</qt>");
+        case SelfPeakColumn:
+            return i18n("<qt>The maximum heap memory in bytes consumed from "
+                        "allocations originating directly at "
+                        "this location. "
+                        "This takes deallocations into account.</qt>");
+        case SelfLeakedColumn:
+            return i18n("<qt>The bytes allocated directly at this location that have "
+                        "not been deallocated.</qt>");
+        case SelfAllocatedColumn:
+            return i18n("<qt>The sum of all bytes directly allocated from this "
+                        "location, ignoring deallocations.</qt>");
+        case InclusiveAllocationsColumn:
+            return i18n("<qt>The inclusive number of times an allocation function "
+                        "was called from this location or any "
+                        "functions called from here.</qt>");
+        case InclusiveTemporaryColumn:
+            return i18n("<qt>The number of inclusive temporary allocations. These "
+                        "allocations are directly followed by "
+                        "a free without any other allocations in-between.</qt>");
+        case InclusivePeakColumn:
+            return i18n("<qt>The inclusive maximum heap memory in bytes consumed "
+                        "from allocations originating at this "
+                        "location or from functions called from here. "
+                        "This takes deallocations into account.</qt>");
+        case InclusiveLeakedColumn:
+            return i18n("<qt>The bytes allocated at this location that have not been "
+                        "deallocated.</qt>");
+        case InclusiveAllocatedColumn:
+            return i18n("<qt>The inclusive sum of all bytes allocated from this "
+                        "location or functions called from "
+                        "here, ignoring deallocations.</qt>");
+        case LocationColumn:
+            return i18n("<qt>The location from which an allocation function was "
+                        "called. Function symbol and file "
+                        "information "
+                        "may be unknown when debug information was missing when "
+                        "heaptrack was run.</qt>");
+        case NUM_COLUMNS:
+            break;
         }
     }
     return {};
-
 }
 
 QVariant CallerCalleeModel::data(const QModelIndex& index, int role) const
@@ -203,13 +220,10 @@ QVariant CallerCalleeModel::data(const QModelIndex& index, int role) const
             return row.location->line;
         case LocationColumn:
             if (row.location->file.isEmpty()) {
-                return i18n("%1 in ?? (%2)",
-                            basename(row.location->function),
-                            basename(row.location->module));
+                return i18n("%1 in ?? (%2)", basename(row.location->function), basename(row.location->module));
             } else {
-                return i18n("%1 in %2:%3 (%4)", row.location->function,
-                            basename(row.location->file), row.location->line,
-                            basename(row.location->module));
+                return i18n("%1 in %2:%3 (%4)", row.location->function, basename(row.location->file),
+                            row.location->line, basename(row.location->module));
             }
         case NUM_COLUMNS:
             break;
@@ -220,24 +234,29 @@ QVariant CallerCalleeModel::data(const QModelIndex& index, int role) const
         stream << "<qt><pre style='font-family:monospace;'>";
         if (row.location->line > 0) {
             stream << i18nc("1: function, 2: file, 3: line, 4: module", "%1\n  at %2:%3\n  in %4",
-                            row.location->function.toHtmlEscaped(),
-                            row.location->file.toHtmlEscaped(), row.location->line,
-                            row.location->module.toHtmlEscaped());
+                            row.location->function.toHtmlEscaped(), row.location->file.toHtmlEscaped(),
+                            row.location->line, row.location->module.toHtmlEscaped());
         } else {
-            stream << i18nc("1: function, 2: module", "%1\n  in %2",
-                            row.location->function.toHtmlEscaped(),
+            stream << i18nc("1: function, 2: module", "%1\n  in %2", row.location->function.toHtmlEscaped(),
                             row.location->module.toHtmlEscaped());
         }
         stream << '\n';
-        stream << i18n("inclusive: allocated %1 over %2 calls (%3 temporary, i.e. %4%), peak at %5, leaked %6",
-                       m_format.formatByteSize(row.inclusiveCost.allocated), row.inclusiveCost.allocations, row.inclusiveCost.temporary,
-                       round(float(row.inclusiveCost.temporary) * 100.f * 100.f / std::max(int64_t(1), row.inclusiveCost.allocations)) / 100.f,
-                       m_format.formatByteSize(row.inclusiveCost.peak), m_format.formatByteSize(row.inclusiveCost.leaked));
+        stream << i18n("inclusive: allocated %1 over %2 calls (%3 temporary, i.e. "
+                       "%4%), peak at %5, leaked %6",
+                       m_format.formatByteSize(row.inclusiveCost.allocated), row.inclusiveCost.allocations,
+                       row.inclusiveCost.temporary, round(float(row.inclusiveCost.temporary) * 100.f * 100.f
+                                                          / std::max(int64_t(1), row.inclusiveCost.allocations))
+                           / 100.f,
+                       m_format.formatByteSize(row.inclusiveCost.peak),
+                       m_format.formatByteSize(row.inclusiveCost.leaked));
         stream << '\n';
-        stream << i18n("self: allocated %1 over %2 calls (%3 temporary, i.e. %4%), peak at %5, leaked %6",
-                       m_format.formatByteSize(row.selfCost.allocated), row.selfCost.allocations, row.selfCost.temporary,
-                       round(float(row.selfCost.temporary) * 100.f * 100.f / std::max(int64_t(1), row.selfCost.allocations)) / 100.f,
-                       m_format.formatByteSize(row.selfCost.peak), m_format.formatByteSize(row.selfCost.leaked));
+        stream << i18n(
+            "self: allocated %1 over %2 calls (%3 temporary, i.e. %4%), "
+            "peak at %5, leaked %6",
+            m_format.formatByteSize(row.selfCost.allocated), row.selfCost.allocations, row.selfCost.temporary,
+            round(float(row.selfCost.temporary) * 100.f * 100.f / std::max(int64_t(1), row.selfCost.allocations))
+                / 100.f,
+            m_format.formatByteSize(row.selfCost.peak), m_format.formatByteSize(row.selfCost.leaked));
         stream << '\n';
         stream << "</pre></qt>";
         return tooltip;
index 065973f..5f2314c 100644 (file)
@@ -20,8 +20,8 @@
 #ifndef CALLERCALLEEMODEL_H
 #define CALLERCALLEEMODEL_H
 
-#include <QVector>
 #include <QAbstractTableModel>
+#include <QVector>
 
 #include <KFormat>
 
@@ -47,7 +47,8 @@ public:
     explicit CallerCalleeModel(QObject* parent = nullptr);
     ~CallerCalleeModel();
 
-    enum Columns {
+    enum Columns
+    {
         LocationColumn,
         FunctionColumn,
         FileColumn,
@@ -66,7 +67,8 @@ public:
         NUM_COLUMNS
     };
 
-    enum Roles {
+    enum Roles
+    {
         SortRole = Qt::UserRole,
         MaxCostRole,
         LocationRole
@@ -77,10 +79,11 @@ public:
     QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
 
     int columnCount(const QModelIndex& parent = {}) const override;
-    int rowCount(const QModelIndex &parent = {}) const override;
+    int rowCount(const QModelIndexparent = {}) const override;
 
     void resetData(const QVector<CallerCalleeData>& rows);
     void setSummary(const SummaryData& data);
+
 private:
     QVector<CallerCalleeData> m_rows;
     CallerCalleeData m_maxCost;
index 80b9af8..8c8bd7b 100644 (file)
 
 #include <KChartGlobal>
 #include <KChartLineAttributes>
-#include <KLocalizedString>
 #include <KFormat>
+#include <KLocalizedString>
 
-#include <QPen>
 #include <QBrush>
 #include <QDebug>
+#include <QPen>
 
 namespace {
 QColor colorForColumn(int column, int columnCount)
@@ -87,7 +87,7 @@ QVariant ChartModel::data(const QModelIndex& index, int role) const
     Q_ASSERT(index.column() >= 0 && index.column() < columnCount(index.parent()));
     Q_ASSERT(!index.parent().isValid());
 
-    if ( role == KChart::LineAttributesRole ) {
+    if (role == KChart::LineAttributesRole) {
         KChart::LineAttributes attributes;
         attributes.setDisplayArea(true);
         if (index.column() > 1) {
@@ -98,14 +98,13 @@ QVariant ChartModel::data(const QModelIndex& index, int role) const
         return QVariant::fromValue(attributes);
     }
 
-
-    if ( role == KChart::DatasetPenRole ) {
+    if (role == KChart::DatasetPenRole) {
         return QVariant::fromValue(m_columnDataSetPens.at(index.column()));
-    } else if ( role == KChart::DatasetBrushRole ) {
+    } else if (role == KChart::DatasetBrushRole) {
         return QVariant::fromValue(m_columnDataSetBrushes.at(index.column()));
     }
 
-    if ( role != Qt::DisplayRole && role != Qt::ToolTipRole ) {
+    if (role != Qt::DisplayRole && role != Qt::ToolTipRole) {
         return {};
     }
 
@@ -124,34 +123,36 @@ QVariant ChartModel::data(const QModelIndex& index, int role) const
         KFormat format;
         if (column == 0) {
             switch (m_type) {
-                case Allocations:
-                    return i18n("<qt>%1 allocations in total after %2</qt>",
-                                cost, time);
-                case Temporary:
-                    return i18n("<qt>%1 temporary allocations in total after %2</qt>",
-                                cost, time);
-                case Consumed:
-                    return i18n("<qt>%1 consumed in total after %2</qt>",
-                                format.formatByteSize(cost, 1, KFormat::MetricBinaryDialect), time);
-                case Allocated:
-                    return i18n("<qt>%2 allocated in total after %2</qt>",
-                                format.formatByteSize(cost, 1, KFormat::MetricBinaryDialect), time);
+            case Allocations:
+                return i18n("<qt>%1 allocations in total after %2</qt>", cost, time);
+            case Temporary:
+                return i18n("<qt>%1 temporary allocations in total after %2</qt>", cost, time);
+            case Consumed:
+                return i18n("<qt>%1 consumed in total after %2</qt>",
+                            format.formatByteSize(cost, 1, KFormat::MetricBinaryDialect), time);
+            case Allocated:
+                return i18n("<qt>%2 allocated in total after %2</qt>",
+                            format.formatByteSize(cost, 1, KFormat::MetricBinaryDialect), time);
             }
         } else {
             const auto label = m_data.labels.value(column).toHtmlEscaped();
             switch (m_type) {
-                case Allocations:
-                    return i18n("<qt>%2 allocations after %3 from:<p style='margin-left:10px;'>%1</p></qt>",
-                                label, cost, time);
-                case Temporary:
-                    return i18n("<qt>%2 temporary allocations after %3 from:<p style='margin-left:10px'>%1</p></qt>",
-                                label, cost, time);
-                case Consumed:
-                    return i18n("<qt>%2 consumed after %3 from:<p style='margin-left:10px'>%1</p></qt>",
-                                label, format.formatByteSize(cost, 1, KFormat::MetricBinaryDialect), time);
-                case Allocated:
-                    return i18n("<qt>%2 allocated after %3 from:<p style='margin-left:10px'>%1</p></qt>",
-                                label, format.formatByteSize(cost, 1, KFormat::MetricBinaryDialect), time);
+            case Allocations:
+                return i18n("<qt>%2 allocations after %3 from:<p "
+                            "style='margin-left:10px;'>%1</p></qt>",
+                            label, cost, time);
+            case Temporary:
+                return i18n("<qt>%2 temporary allocations after %3 from:<p "
+                            "style='margin-left:10px'>%1</p></qt>",
+                            label, cost, time);
+            case Consumed:
+                return i18n("<qt>%2 consumed after %3 from:<p "
+                            "style='margin-left:10px'>%1</p></qt>",
+                            label, format.formatByteSize(cost, 1, KFormat::MetricBinaryDialect), time);
+            case Allocated:
+                return i18n("<qt>%2 allocated after %3 from:<p "
+                            "style='margin-left:10px'>%1</p></qt>",
+                            label, format.formatByteSize(cost, 1, KFormat::MetricBinaryDialect), time);
             }
         }
         return {};
index 55a3b81..c1fcece 100644 (file)
 #ifndef CHARTMODEL_H
 #define CHARTMODEL_H
 
+#include <array>
+
 #include <QAbstractTableModel>
 #include <QVector>
-#include <array>
 
 struct ChartRows
 {
@@ -30,7 +31,8 @@ struct ChartRows
     {
         cost.fill(0);
     }
-    enum {
+    enum
+    {
         MAX_NUM_COST = 20
     };
     // time in ms
@@ -51,7 +53,8 @@ class ChartModel : public QAbstractTableModel
 {
     Q_OBJECT
 public:
-    enum Type {
+    enum Type
+    {
         Consumed,
         Allocations,
         Allocated,
@@ -62,7 +65,8 @@ public:
 
     Type type() const;
 
-    QVariant headerData(int section, Qt::Orientation orientation = Qt::Horizontal, int role = Qt::DisplayRole) const override;
+    QVariant headerData(int section, Qt::Orientation orientation = Qt::Horizontal,
+                        int role = Qt::DisplayRole) const override;
     QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
     int rowCount(const QModelIndex& parent = QModelIndex()) const override;
     int columnCount(const QModelIndex& parent = QModelIndex()) const override;
@@ -73,7 +77,8 @@ public slots:
 private:
     ChartData m_data;
     Type m_type;
-    // we cache the pens and brushes as constructing them requires allocations otherwise
+    // we cache the pens and brushes as constructing them requires allocations
+    // otherwise
     QVector<QPen> m_columnDataSetPens;
     QVector<QBrush> m_columnDataSetBrushes;
 };
index 2c8fd4e..a171b13 100644 (file)
@@ -21,6 +21,7 @@
 #define CHARTPROXY_H
 
 #include <QSortFilterProxyModel>
+
 #include "chartmodel.h"
 
 class ChartProxy : public QSortFilterProxyModel
@@ -37,4 +38,4 @@ private:
     bool m_showTotal;
 };
 
-#endif //CHARTPROXY_H
+#endif // CHARTPROXY_H
index de87edb..e8a379e 100644 (file)
 #include <KChartChart>
 #include <KChartPlotter>
 
-#include <KChartGridAttributes>
-#include <KChartHeaderFooter>
+#include <KChartBackgroundAttributes>
 #include <KChartCartesianCoordinatePlane>
-#include <KChartLegend>
 #include <KChartDataValueAttributes>
-#include <KChartBackgroundAttributes>
 #include <KChartFrameAttributes.h>
+#include <KChartGridAttributes>
+#include <KChartHeaderFooter>
+#include <KChartLegend>
 
+#include <KColorScheme>
 #include <KFormat>
 #include <KLocalizedString>
-#include <KColorScheme>
 
 #include "chartmodel.h"
 #include "chartproxy.h"
@@ -48,7 +48,8 @@ class TimeAxis : public CartesianAxis
 public:
     explicit TimeAxis(AbstractCartesianDiagram* diagram = nullptr)
         : CartesianAxis(diagram)
-    {}
+    {
+    }
 
     const QString customizedLabel(const QString& label) const override
     {
@@ -63,7 +64,8 @@ class SizeAxis : public CartesianAxis
 public:
     explicit SizeAxis(AbstractCartesianDiagram* diagram = nullptr)
         : CartesianAxis(diagram)
-    {}
+    {
+    }
 
     const QString customizedLabel(const QString& label) const override
     {
@@ -100,21 +102,23 @@ void ChartWidget::setModel(ChartModel* model, bool minimalMode)
     }
 
     switch (model->type()) {
-        case ChartModel::Consumed:
-            setToolTip(i18n("<qt>Shows the heap memory consumption over time.</qt>"));
-            break;
-        case ChartModel::Allocated:
-            setToolTip(i18n("<qt>Displays total memory allocated over time. "
-                            "This value ignores deallocations and just measures heap allocation throughput.</qt>"));
-            break;
-        case ChartModel::Allocations:
-            setToolTip(i18n("<qt>Shows number of memory allocations over time.</qt>"));
-            break;
-        case ChartModel::Temporary:
-            setToolTip(i18n("<qt>Shows number of temporary memory allocations over time. "
-                            "A temporary allocation is one that is followed immediately by its "
-                            "corresponding deallocation, without other allocations happening in-between.</qt>"));
-            break;
+    case ChartModel::Consumed:
+        setToolTip(i18n("<qt>Shows the heap memory consumption over time.</qt>"));
+        break;
+    case ChartModel::Allocated:
+        setToolTip(i18n("<qt>Displays total memory allocated over time. "
+                        "This value ignores deallocations and just measures heap "
+                        "allocation throughput.</qt>"));
+        break;
+    case ChartModel::Allocations:
+        setToolTip(i18n("<qt>Shows number of memory allocations over time.</qt>"));
+        break;
+    case ChartModel::Temporary:
+        setToolTip(i18n("<qt>Shows number of temporary memory allocations over time. "
+                        "A temporary allocation is one that is followed immediately by its "
+                        "corresponding deallocation, without other allocations happening "
+                        "in-between.</qt>"));
+        break;
     }
 
     {
@@ -147,7 +151,8 @@ void ChartWidget::setModel(ChartModel* model, bool minimalMode)
         totalPlotter->addAxis(bottomAxis);
 
         CartesianAxis* rightAxis = model->type() == ChartModel::Allocations || model->type() == ChartModel::Temporary
-                                    ? new CartesianAxis(totalPlotter) : new SizeAxis(totalPlotter);
+            ? new CartesianAxis(totalPlotter)
+            : new SizeAxis(totalPlotter);
         rightAxis->setTextAttributes(axisTextAttributes);
         rightAxis->setTitleTextAttributes(axisTitleTextAttributes);
         rightAxis->setTitleText(model->headerData(1).toString());
index 16acb18..325a65d 100644 (file)
@@ -60,8 +60,7 @@ void CostDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
         painter->drawRect(option.rect);
     }
 
-    auto color = QColor::fromHsv(120 - fraction * 120, 255, 255,
-                                 (-((fraction-1) * (fraction-1))) * 120 + 120);
+    auto color = QColor::fromHsv(120 - fraction * 120, 255, 255, (-((fraction - 1) * (fraction - 1))) * 120 + 120);
     painter->setBrush(color);
     painter->drawRect(rect);
 
@@ -76,4 +75,3 @@ void CostDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
         QStyledItemDelegate::paint(painter, option, index);
     }
 }
-
index a2d4c40..3ef6b08 100644 (file)
@@ -26,11 +26,10 @@ class CostDelegate : public QStyledItemDelegate
 {
     Q_OBJECT
 public:
-    explicit CostDelegate(QObject *parent = nullptr);
+    explicit CostDelegate(QObjectparent = nullptr);
     ~CostDelegate();
 
-    void paint(QPainter *painter, const QStyleOptionViewItem &option,
-               const QModelIndex &index) const override;
+    void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
 };
 
 #endif // COSTDELEGATE_H
index 5a56487..0537bba 100644 (file)
 
 #include <cmath>
 
-#include <QVBoxLayout>
+#include <QAction>
+#include <QCheckBox>
+#include <QComboBox>
+#include <QCursor>
+#include <QDebug>
+#include <QDoubleSpinBox>
+#include <QEvent>
+#include <QGraphicsRectItem>
 #include <QGraphicsScene>
-#include <QStyleOption>
 #include <QGraphicsView>
 #include <QLabel>
-#include <QGraphicsRectItem>
-#include <QWheelEvent>
-#include <QEvent>
+#include <QStyleOption>
 #include <QToolTip>
-#include <QDebug>
-#include <QAction>
-#include <QComboBox>
-#include <QCheckBox>
-#include <QDoubleSpinBox>
-#include <QCursor>
+#include <QVBoxLayout>
+#include <QWheelEvent>
 
-#include <ThreadWeaver/ThreadWeaver>
-#include <KLocalizedString>
 #include <KColorScheme>
+#include <KLocalizedString>
+#include <ThreadWeaver/ThreadWeaver>
 
 enum CostType
 {
@@ -54,7 +54,8 @@ Q_DECLARE_METATYPE(CostType)
 class FrameGraphicsItem : public QGraphicsRectItem
 {
 public:
-    FrameGraphicsItem(const qint64 cost, CostType costType, const QString& function, FrameGraphicsItem* parent = nullptr);
+    FrameGraphicsItem(const qint64 cost, CostType costType, const QString& function,
+                      FrameGraphicsItem* parent = nullptr);
     FrameGraphicsItem(const qint64 cost, const QString& function, FrameGraphicsItem* parent);
 
     qint64 cost() const;
@@ -66,8 +67,8 @@ public:
     QString description() const;
 
 protected:
-    void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
-    void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
+    void hoverEnterEvent(QGraphicsSceneHoverEventevent) override;
+    void hoverLeaveEvent(QGraphicsSceneHoverEventevent) override;
 
 private:
     qint64 m_cost;
@@ -78,7 +79,8 @@ private:
 
 Q_DECLARE_METATYPE(FrameGraphicsItem*)
 
-FrameGraphicsItem::FrameGraphicsItem(const qint64 cost, CostType costType, const QString& function, FrameGraphicsItem* parent)
+FrameGraphicsItem::FrameGraphicsItem(const qint64 cost, CostType costType, const QString& function,
+                                     FrameGraphicsItem* parent)
     : QGraphicsRectItem(parent)
     , m_cost(cost)
     , m_function(function)
@@ -138,11 +140,12 @@ void FrameGraphicsItem::paint(QPainter* painter, const QStyleOptionGraphicsItem*
 
     const int height = rect().height();
 
-    painter->drawText(margin + rect().x(), rect().y(), width, height, Qt::AlignVCenter | Qt::AlignLeft | Qt::TextSingleLine,
+    painter->drawText(margin + rect().x(), rect().y(), width, height,
+                      Qt::AlignVCenter | Qt::AlignLeft | Qt::TextSingleLine,
                       option->fontMetrics.elidedText(m_function, Qt::ElideRight, width));
 }
 
-void FrameGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+void FrameGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEventevent)
 {
     QGraphicsRectItem::hoverEnterEvent(event);
     m_isHovered = true;
@@ -150,7 +153,8 @@ void FrameGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
 
 QString FrameGraphicsItem::description() const
 {
-    // we build the tooltip text on demand, which is much faster than doing that for potentially thousands of items when we load the data
+    // we build the tooltip text on demand, which is much faster than doing that
+    // for potentially thousands of items when we load the data
     QString tooltip;
     KFormat format;
     qint64 totalCost = 0;
@@ -161,8 +165,9 @@ QString FrameGraphicsItem::description() const
         }
         totalCost = item->cost();
     }
-    const auto fraction = QString::number(double(m_cost)  * 100. / totalCost, 'g', 3);
-    const auto function = QString(QLatin1String("<span style='font-family:monospace'>") + m_function.toHtmlEscaped() + QLatin1String("</span>"));
+    const auto fraction = QString::number(double(m_cost) * 100. / totalCost, 'g', 3);
+    const auto function = QString(QLatin1String("<span style='font-family:monospace'>") + m_function.toHtmlEscaped()
+                                  + QLatin1String("</span>"));
     if (!parentItem()) {
         return function;
     }
@@ -173,16 +178,19 @@ QString FrameGraphicsItem::description() const
                         "%1 (%2%) allocations in %3 and below.", m_cost, fraction, function);
         break;
     case Temporary:
-        tooltip = i18nc("%1: number of temporary allocations, %2: relative number, %3 function label",
+        tooltip = i18nc("%1: number of temporary allocations, %2: relative number, "
+                        "%3 function label",
                         "%1 (%2%) temporary allocations in %3 and below.", m_cost, fraction, function);
         break;
     case Peak:
-        tooltip = i18nc("%1: peak consumption in bytes, %2: relative number, %3: function label",
-                        "%1 (%2%) peak consumption in %3 and below.", format.formatByteSize(m_cost), fraction, function);
+        tooltip =
+            i18nc("%1: peak consumption in bytes, %2: relative number, %3: "
+                  "function label",
+                  "%1 (%2%) peak consumption in %3 and below.", format.formatByteSize(m_cost), fraction, function);
         break;
     case Leaked:
-        tooltip = i18nc("%1: leaked bytes, %2: relative number, %3: function label",
-                        "%1 (%2%) leaked in %3 and below.", format.formatByteSize(m_cost), fraction, function);
+        tooltip = i18nc("%1: leaked bytes, %2: relative number, %3: function label", "%1 (%2%) leaked in %3 and below.",
+                        format.formatByteSize(m_cost), fraction, function);
         break;
     case Allocated:
         tooltip = i18nc("%1: allocated bytes, %2: relative number, %3: function label",
@@ -193,7 +201,7 @@ QString FrameGraphicsItem::description() const
     return tooltip;
 }
 
-void FrameGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+void FrameGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEventevent)
 {
     QGraphicsRectItem::hoverLeaveEvent(event);
     m_isHovered = false;
@@ -207,10 +215,11 @@ namespace {
 QBrush brush()
 {
     // intern the brushes, to reuse them across items which can be thousands
-    // otherwise we'd end up with dozens of allocations and higher memory consumption
+    // otherwise we'd end up with dozens of allocations and higher memory
+    // consumption
     static QVector<QBrush> brushes;
     if (brushes.isEmpty()) {
-        std::generate_n(std::back_inserter(brushes), 100, [] () {
+        std::generate_n(std::back_inserter(brushes), 100, []() {
             return QColor(0, 190 + 50 * qreal(rand()) / RAND_MAX, 210 * qreal(rand()) / RAND_MAX, 125);
         });
     }
@@ -220,7 +229,7 @@ QBrush brush()
 /**
  * Layout the flame graph and hide tiny items.
  */
-void layoutItems(FrameGraphicsItem *parent)
+void layoutItems(FrameGraphicsItemparent)
 {
     const auto& parentRect = parent->rect();
     const auto pos = parentRect.topLeft();
@@ -256,7 +265,7 @@ FrameGraphicsItem* findItemByFunction(const QList<QGraphicsItem*>& items, const
 /**
  * Convert the top-down graph into a tree of FrameGraphicsItem.
  */
-void toGraphicsItems(const QVector<RowData>& data, FrameGraphicsItem *parent, int64_t AllocationData::* member,
+void toGraphicsItems(const QVector<RowData>& data, FrameGraphicsItem* parent, int64_t AllocationData::*member,
                      const double costThreshold, bool collapseRecursion)
 {
     foreach (const auto& row, data) {
@@ -272,13 +281,12 @@ void toGraphicsItems(const QVector<RowData>& data, FrameGraphicsItem *parent, in
             item->setCost(item->cost() + row.cost.*member);
         }
         if (item->cost() > costThreshold) {
-            toGraphicsItems(row.children, item, member,
-                            costThreshold, collapseRecursion);
+            toGraphicsItems(row.children, item, member, costThreshold, collapseRecursion);
         }
     }
 }
 
-int64_t AllocationData::* memberForType(CostType type)
+int64_t AllocationData::*memberForType(CostType type)
 {
     switch (type) {
     case Allocations:
@@ -295,13 +303,13 @@ int64_t AllocationData::* memberForType(CostType type)
     Q_UNREACHABLE();
 }
 
-FrameGraphicsItem* parseData(const QVector<RowData>& topDownData, CostType type,
-                             double costThreshold, bool collapseRecursion)
+FrameGraphicsItem* parseData(const QVector<RowData>& topDownData, CostType type, double costThreshold,
+                             bool collapseRecursion)
 {
     auto member = memberForType(type);
 
     double totalCost = 0;
-    foreach(const auto& frame, topDownData) {
+    foreach (const auto& frame, topDownData) {
         totalCost += frame.cost.*member;
     }
 
@@ -330,11 +338,9 @@ FrameGraphicsItem* parseData(const QVector<RowData>& topDownData, CostType type,
     auto rootItem = new FrameGraphicsItem(totalCost, type, label);
     rootItem->setBrush(scheme.background());
     rootItem->setPen(pen);
-    toGraphicsItems(topDownData, rootItem, member,
-                    totalCost * costThreshold / 100., collapseRecursion);
+    toGraphicsItems(topDownData, rootItem, member, totalCost * costThreshold / 100., collapseRecursion);
     return rootItem;
 }
-
 }
 
 FlameGraph::FlameGraph(QWidget* parent, Qt::WindowFlags flags)
@@ -347,20 +353,30 @@ FlameGraph::FlameGraph(QWidget* parent, Qt::WindowFlags flags)
     qRegisterMetaType<FrameGraphicsItem*>();
 
     m_costSource->addItem(i18n("Allocations"), QVariant::fromValue(Allocations));
-    m_costSource->setItemData(0, i18n("Show a flame graph over the number of allocations triggered by functions in your code."), Qt::ToolTipRole);
+    m_costSource->setItemData(0, i18n("Show a flame graph over the number of allocations triggered by "
+                                      "functions in your code."),
+                              Qt::ToolTipRole);
     m_costSource->addItem(i18n("Temporary Allocations"), QVariant::fromValue(Temporary));
-    m_costSource->setItemData(1, i18n("Show a flame graph over the number of temporary allocations triggered by functions in your code. "
-                                      "Allocations are marked as temporary when they are immediately followed by their deallocation."), Qt::ToolTipRole);
+    m_costSource->setItemData(1, i18n("Show a flame graph over the number of temporary allocations "
+                                      "triggered by functions in your code. "
+                                      "Allocations are marked as temporary when they are immediately "
+                                      "followed by their deallocation."),
+                              Qt::ToolTipRole);
     m_costSource->addItem(i18n("Peak Consumption"), QVariant::fromValue(Peak));
-    m_costSource->setItemData(2, i18n("Show a flame graph over the peak heap memory consumption of your application."), Qt::ToolTipRole);
+    m_costSource->setItemData(2, i18n("Show a flame graph over the peak heap "
+                                      "memory consumption of your application."),
+                              Qt::ToolTipRole);
     m_costSource->addItem(i18n("Leaked"), QVariant::fromValue(Leaked));
     m_costSource->setItemData(3, i18n("Show a flame graph over the leaked heap memory of your application. "
-                                      "Memory is considered to be leaked when it never got deallocated. "), Qt::ToolTipRole);
+                                      "Memory is considered to be leaked when it never got deallocated. "),
+                              Qt::ToolTipRole);
     m_costSource->addItem(i18n("Allocated"), QVariant::fromValue(Allocated));
-    m_costSource->setItemData(4, i18n("Show a flame graph over the total memory allocated by functions in your code. "
-                                      "This aggregates all memory allocations and ignores deallocations."), Qt::ToolTipRole);
-    connect(m_costSource, static_cast<void (QComboBox::*) (int)>(&QComboBox::currentIndexChanged),
-            this, &FlameGraph::showData);
+    m_costSource->setItemData(4, i18n("Show a flame graph over the total memory allocated by functions in "
+                                      "your code. "
+                                      "This aggregates all memory allocations and ignores deallocations."),
+                              Qt::ToolTipRole);
+    connect(m_costSource, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
+            &FlameGraph::showData);
     m_costSource->setToolTip(i18n("Select the data source that should be visualized in the flame graph."));
 
     m_scene->setItemIndexMethod(QGraphicsScene::NoIndex);
@@ -371,7 +387,8 @@ FlameGraph::FlameGraph(QWidget* parent, Qt::WindowFlags flags)
     m_view->setContextMenuPolicy(Qt::ActionsContextMenu);
 
     auto bottomUpCheckbox = new QCheckBox(i18n("Bottom-Down View"), this);
-    bottomUpCheckbox->setToolTip(i18n("Enable the bottom-down flame graph view. When this is unchecked, the top-down view is enabled by default."));
+    bottomUpCheckbox->setToolTip(i18n("Enable the bottom-down flame graph view. When this is unchecked, "
+                                      "the top-down view is enabled by default."));
     connect(bottomUpCheckbox, &QCheckBox::toggled, this, [this, bottomUpCheckbox] {
         m_showBottomUpData = bottomUpCheckbox->isChecked();
         showData();
@@ -380,7 +397,8 @@ FlameGraph::FlameGraph(QWidget* parent, Qt::WindowFlags flags)
     auto collapseRecursionCheckbox = new QCheckBox(i18n("Collapse Recursion"), this);
     collapseRecursionCheckbox->setChecked(m_collapseRecursion);
     collapseRecursionCheckbox->setToolTip(i18n("Collapse stack frames for functions calling themselves. "
-                                               "When this is unchecked, recursive frames will be visualized separately."));
+                                               "When this is unchecked, recursive frames will be visualized "
+                                               "separately."));
     connect(collapseRecursionCheckbox, &QCheckBox::toggled, this, [this, collapseRecursionCheckbox] {
         m_collapseRecursion = collapseRecursionCheckbox->isChecked();
         showData();
@@ -395,11 +413,12 @@ FlameGraph::FlameGraph(QWidget* parent, Qt::WindowFlags flags)
     costThreshold->setValue(m_costThreshold);
     costThreshold->setSingleStep(0.01);
     costThreshold->setToolTip(i18n("<qt>The cost threshold defines a fractional cut-off value. "
-                                   "Items with a relative cost below this value will not be shown in the flame graph. "
-                                   "This is done as an optimization to quickly generate graphs for large data sets with "
-                                   "low memory overhead. If you need more details, decrease the threshold value, or set it to zero.</qt>"));
-    connect(costThreshold, static_cast<void (QDoubleSpinBox::*) (double)>(&QDoubleSpinBox::valueChanged),
-            this, [this] (double threshold) {
+                                   "Items with a relative cost below this value will not be shown in "
+                                   "the flame graph. This is done as an optimization to quickly generate "
+                                   "graphs for large data sets with low memory overhead. If you need more "
+                                   "details, decrease the threshold value, or set it to zero.</qt>"));
+    connect(costThreshold, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), this,
+            [this](double threshold) {
                 m_costThreshold = threshold;
                 showData();
             });
@@ -422,15 +441,13 @@ FlameGraph::FlameGraph(QWidget* parent, Qt::WindowFlags flags)
     {
         auto action = new QAction(tr("back"), this);
         action->setShortcuts({QKeySequence::Back, Qt::Key_Backspace});
-        connect(action, &QAction::triggered,
-                this, &FlameGraph::navigateBack);
+        connect(action, &QAction::triggered, this, &FlameGraph::navigateBack);
         addAction(action);
     }
     {
         auto action = new QAction(tr("forward"), this);
         action->setShortcuts(QKeySequence::Forward);
-        connect(action, &QAction::triggered,
-                this, &FlameGraph::navigateForward);
+        connect(action, &QAction::triggered, this, &FlameGraph::navigateForward);
         addAction(action);
     }
 }
@@ -498,8 +515,7 @@ void FlameGraph::showData()
     auto threshold = m_costThreshold;
     stream() << make_job([data, source, threshold, collapseRecursion, this]() {
         auto parsedData = parseData(data, source, threshold, collapseRecursion);
-        QMetaObject::invokeMethod(this, "setData", Qt::QueuedConnection,
-                                  Q_ARG(FrameGraphicsItem*, parsedData));
+        QMetaObject::invokeMethod(this, "setData", Qt::QueuedConnection, Q_ARG(FrameGraphicsItem*, parsedData));
     });
 }
 
@@ -540,7 +556,8 @@ void FlameGraph::setData(FrameGraphicsItem* rootItem)
     }
 
     m_view->setCursor(Qt::ArrowCursor);
-    // layouting needs a root item with a given height, the rest will be overwritten later
+    // layouting needs a root item with a given height, the rest will be
+    // overwritten later
     rootItem->setRect(0, 0, 800, m_view->fontMetrics().height() + 4);
     m_scene->addItem(rootItem);
 
index aef55da..b238914 100644 (file)
@@ -20,8 +20,8 @@
 #ifndef FLAMEGRAPH_H
 #define FLAMEGRAPH_H
 
-#include <QWidget>
 #include <QVector>
+#include <QWidget>
 
 #include "treemodel.h"
 
index 8976147..a6b7722 100644 (file)
@@ -33,10 +33,11 @@ int main(int argc, char** argv)
 
     KAboutData aboutData(QStringLiteral("heaptrack_gui"), i18n("Heaptrack GUI"), QStringLiteral("0.1"),
                          i18n("A visualizer for heaptrack data files."), KAboutLicense::LGPL,
-                         i18n("Copyright 2015, Milian Wolff <mail@milianw.de>"), QString(), QStringLiteral("mail@milianw.de"));
+                         i18n("Copyright 2015, Milian Wolff <mail@milianw.de>"), QString(),
+                         QStringLiteral("mail@milianw.de"));
 
-    aboutData.addAuthor(i18n("Milian Wolff"), i18n("Original author, maintainer"),
-                        QStringLiteral("mail@milianw.de"), QStringLiteral("http://milianw.de"));
+    aboutData.addAuthor(i18n("Milian Wolff"), i18n("Original author, maintainer"), QStringLiteral("mail@milianw.de"),
+                        QStringLiteral("http://milianw.de"));
 
     aboutData.setOrganizationDomain("kde.org");
     KAboutData::setApplicationData(aboutData);
@@ -53,25 +54,23 @@ int main(int argc, char** argv)
     parser.addHelpOption();
     aboutData.setupCommandLine(&parser);
 
-    QCommandLineOption diffOption {
-        { QStringLiteral("d"), QStringLiteral("diff")},
-        i18n("Base profile data to compare other files to."),
-        QStringLiteral("<file>")
-    };
+    QCommandLineOption diffOption{{QStringLiteral("d"), QStringLiteral("diff")},
+                                  i18n("Base profile data to compare other files to."),
+                                  QStringLiteral("<file>")};
     parser.addOption(diffOption);
-    parser.addPositionalArgument(QStringLiteral("files"), i18n( "Files to load" ), i18n("[FILE...]"));
+    parser.addPositionalArgument(QStringLiteral("files"), i18n("Files to load"), i18n("[FILE...]"));
 
     parser.process(app);
     aboutData.processCommandLine(&parser);
 
-    auto createWindow = [] () -> MainWindow* {
+    auto createWindow = []() -> MainWindow* {
         auto window = new MainWindow;
         window->setAttribute(Qt::WA_DeleteOnClose);
         window->show();
         return window;
     };
 
-    foreach (const QString &file, parser.positionalArguments()) {
+    foreach (const QStringfile, parser.positionalArguments()) {
         createWindow()->loadFile(file, parser.value(diffOption));
     }
 
index 64ef6c7..7c978d2 100644 (file)
@@ -24,8 +24,8 @@
 #include <KFormat>
 #include <KLocalizedString>
 
-#include <QColor>
 #include <QBrush>
+#include <QColor>
 #include <QPen>
 
 #include <limits>
@@ -58,9 +58,9 @@ QVariant HistogramModel::data(const QModelIndex& index, int role) const
     if (!hasIndex(index.row(), index.column(), index.parent())) {
         return {};
     }
-    if ( role == KChart::DatasetBrushRole ) {
+    if (role == KChart::DatasetBrushRole) {
         return QVariant::fromValue(QBrush(colorForColumn(index.column(), columnCount())));
-    } else if ( role == KChart::DatasetPenRole ) {
+    } else if (role == KChart::DatasetPenRole) {
         return QVariant::fromValue(QPen(Qt::black));
     }
 
@@ -75,12 +75,11 @@ QVariant HistogramModel::data(const QModelIndex& index, int role) const
             return i18n("%1 allocations in total", column.allocations);
         }
         if (!column.location->file.isEmpty()) {
-            return i18n("%1 allocations from %2 at %3:%4 in %5", column.allocations,
-                        column.location->function, column.location->file, column.location->line,
-                        column.location->module);
+            return i18n("%1 allocations from %2 at %3:%4 in %5", column.allocations, column.location->function,
+                        column.location->file, column.location->line, column.location->module);
         }
-        return i18n("%1 allocations from %2 in %3", column.allocations,
-                    column.location->function, column.location->module);
+        return i18n("%1 allocations from %2 in %3", column.allocations, column.location->function,
+                    column.location->module);
     }
     return column.allocations;
 }
index 33a6d87..27ab677 100644 (file)
@@ -37,7 +37,8 @@ struct HistogramRow
     {
         columns.fill({0, {}});
     }
-    enum {
+    enum
+    {
         NUM_COLUMNS = 10 + 1
     };
     QString sizeLabel;
index 5a0a3ad..c64b5d0 100644 (file)
 
 #include "histogramwidget.h"
 
-#include <QVBoxLayout>
 #include <QSortFilterProxyModel>
+#include <QVBoxLayout>
 
-#include <KChartChart>
 #include <KChartBarDiagram>
+#include <KChartChart>
 
-#include <KChartGridAttributes>
-#include <KChartHeaderFooter>
+#include <KChartBackgroundAttributes>
 #include <KChartCartesianCoordinatePlane>
-#include <KChartLegend>
 #include <KChartDataValueAttributes>
-#include <KChartBackgroundAttributes>
 #include <KChartFrameAttributes.h>
+#include <KChartGridAttributes>
+#include <KChartHeaderFooter>
+#include <KChartLegend>
 
-#include <KLocalizedString>
 #include <KColorScheme>
 #include <KFormat>
+#include <KLocalizedString>
 
 #include "histogrammodel.h"
 
@@ -48,7 +48,8 @@ class SizeAxis : public CartesianAxis
 public:
     explicit SizeAxis(AbstractCartesianDiagram* diagram = nullptr)
         : CartesianAxis(diagram)
-    {}
+    {
+    }
 
     const QString customizedLabel(const QString& label) const override
     {
@@ -81,7 +82,6 @@ protected:
 private:
     bool m_showTotal;
 };
-
 }
 
 HistogramWidget::HistogramWidget(QWidget* parent)
index 905932d..688cc67 100644 (file)
@@ -45,4 +45,3 @@ private:
 };
 
 #endif // HISTOGRAMWIDGET_H
-
index 2a0b8b2..43f50c3 100644 (file)
@@ -35,10 +35,7 @@ struct LocationData
 
     bool operator==(const LocationData& rhs) const
     {
-        return function == rhs.function
-            && file == rhs.file
-            && module == rhs.module
-            && line == rhs.line;
+        return function == rhs.function && file == rhs.file && module == rhs.module && line == rhs.line;
     }
 
     bool operator<(const LocationData& rhs) const
index a783ea6..d8eccd1 100644 (file)
 
 #include <cmath>
 
-#include <KRecursiveFilterProxyModel>
-#include <KLocalizedString>
 #include <KConfigGroup>
+#include <KLocalizedString>
+#include <KRecursiveFilterProxyModel>
 
-#include <QFileDialog>
-#include <QStatusBar>
-#include <QDebug>
-#include <QMenu>
 #include <QAction>
+#include <QDebug>
 #include <QDesktopServices>
+#include <QFileDialog>
+#include <QMenu>
+#include <QStatusBar>
 
-#include "treemodel.h"
-#include "treeproxy.h"
-#include "topproxy.h"
+#include "callercalleemodel.h"
 #include "costdelegate.h"
 #include "parser.h"
 #include "stacksmodel.h"
-#include "callercalleemodel.h"
+#include "topproxy.h"
+#include "treemodel.h"
+#include "treeproxy.h"
 
 #include "gui_config.h"
 
 #if KChart_FOUND
-#include "chartwidget.h"
 #include "chartmodel.h"
 #include "chartproxy.h"
-#include "histogramwidget.h"
+#include "chartwidget.h"
 #include "histogrammodel.h"
+#include "histogramwidget.h"
 #endif
 
 using namespace std;
@@ -69,29 +69,27 @@ const char State[] = "State";
 void addContextMenu(QTreeView* treeView, int role)
 {
     treeView->setContextMenuPolicy(Qt::CustomContextMenu);
-    QObject::connect(treeView, &QTreeView::customContextMenuRequested,
-        treeView, [treeView, role] (const QPoint& pos) {
-            auto index = treeView->indexAt(pos);
-            if (!index.isValid()) {
-                return;
-            }
-            const auto location = index.data(role).value<LocationData::Ptr>();
-            if (!location || !QFile::exists(location->file)) {
-                return;
-            }
-            auto menu = new QMenu(treeView);
-            auto openFile = new QAction(QIcon::fromTheme(QStringLiteral("document-open")),
-                                        QObject::tr("Open file in editor"));
-            QObject::connect(openFile, &QAction::triggered,
-                openFile, [location] {
-                    /// FIXME: add settings to let user configure this
-                    auto url = QUrl::fromLocalFile(location->file);
-                    url.setFragment(QString::number(location->line));
-                    QDesktopServices::openUrl(url);
-                });
-            menu->addAction(openFile);
-            menu->popup(treeView->mapToGlobal(pos));
+    QObject::connect(treeView, &QTreeView::customContextMenuRequested, treeView, [treeView, role](const QPoint& pos) {
+        auto index = treeView->indexAt(pos);
+        if (!index.isValid()) {
+            return;
+        }
+        const auto location = index.data(role).value<LocationData::Ptr>();
+        if (!location || !QFile::exists(location->file)) {
+            return;
+        }
+        auto menu = new QMenu(treeView);
+        auto openFile =
+            new QAction(QIcon::fromTheme(QStringLiteral("document-open")), QObject::tr("Open file in editor"));
+        QObject::connect(openFile, &QAction::triggered, openFile, [location] {
+            /// FIXME: add settings to let user configure this
+            auto url = QUrl::fromLocalFile(location->file);
+            url.setFragment(QString::number(location->line));
+            QDesktopServices::openUrl(url);
         });
+        menu->addAction(openFile);
+        menu->popup(treeView->mapToGlobal(pos));
+    });
 }
 
 void setupTopView(TreeModel* source, QTreeView* view, TopProxy::Type type)
@@ -108,30 +106,25 @@ void setupTopView(TreeModel* source, QTreeView* view, TopProxy::Type type)
 }
 
 #if KChart_FOUND
-void addChartTab(QTabWidget* tabWidget, const QString& title, ChartModel::Type type,
-                 const Parser* parser, void (Parser::*dataReady)(const ChartData&))
+void addChartTab(QTabWidget* tabWidget, const QString& title, ChartModel::Type type, const Parser* parser,
+                 void (Parser::*dataReady)(const ChartData&))
 {
     auto tab = new ChartWidget(tabWidget->parentWidget());
     tabWidget->addTab(tab, title);
     tabWidget->setTabEnabled(tabWidget->indexOf(tab), false);
     auto model = new ChartModel(type, tab);
     tab->setModel(model);
-    QObject::connect(parser, dataReady,
-        tab, [=] (const ChartData& data) {
-            model->resetData(data);
-            tabWidget->setTabEnabled(tabWidget->indexOf(tab), true);
-        });
+    QObject::connect(parser, dataReady, tab, [=](const ChartData& data) {
+        model->resetData(data);
+        tabWidget->setTabEnabled(tabWidget->indexOf(tab), true);
+    });
 }
 #endif
 
-void setupTreeModel(TreeModel* model, QTreeView* view,
-                    CostDelegate* costDelegate, QLineEdit* filterFunction,
+void setupTreeModel(TreeModel* model, QTreeView* view, CostDelegate* costDelegate, QLineEdit* filterFunction,
                     QLineEdit* filterFile, QLineEdit* filterModule)
 {
-    auto proxy = new TreeProxy(TreeModel::FunctionColumn,
-                               TreeModel::FileColumn,
-                               TreeModel::ModuleColumn,
-                               model);
+    auto proxy = new TreeProxy(TreeModel::FunctionColumn, TreeModel::FileColumn, TreeModel::ModuleColumn, model);
     proxy->setSourceModel(model);
     proxy->setSortRole(TreeModel::SortRole);
 
@@ -146,23 +139,17 @@ void setupTreeModel(TreeModel* model, QTreeView* view,
     view->hideColumn(TreeModel::LineColumn);
     view->hideColumn(TreeModel::ModuleColumn);
 
-    QObject::connect(filterFunction, &QLineEdit::textChanged,
-                     proxy, &TreeProxy::setFunctionFilter);
-    QObject::connect(filterFile, &QLineEdit::textChanged,
-                     proxy, &TreeProxy::setFileFilter);
-    QObject::connect(filterModule, &QLineEdit::textChanged,
-                     proxy, &TreeProxy::setModuleFilter);
+    QObject::connect(filterFunction, &QLineEdit::textChanged, proxy, &TreeProxy::setFunctionFilter);
+    QObject::connect(filterFile, &QLineEdit::textChanged, proxy, &TreeProxy::setFileFilter);
+    QObject::connect(filterModule, &QLineEdit::textChanged, proxy, &TreeProxy::setModuleFilter);
     addContextMenu(view, TreeModel::LocationRole);
 }
 
-void setupCallerCalle(CallerCalleeModel* model, QTreeView* view,
-                      CostDelegate* costDelegate, QLineEdit* filterFunction,
+void setupCallerCalle(CallerCalleeModel* model, QTreeView* view, CostDelegate* costDelegate, QLineEdit* filterFunction,
                       QLineEdit* filterFile, QLineEdit* filterModule)
 {
-    auto callerCalleeProxy = new TreeProxy(CallerCalleeModel::FunctionColumn,
-                                           CallerCalleeModel::FileColumn,
-                                           CallerCalleeModel::ModuleColumn,
-                                           model);
+    auto callerCalleeProxy = new TreeProxy(CallerCalleeModel::FunctionColumn, CallerCalleeModel::FileColumn,
+                                           CallerCalleeModel::ModuleColumn, model);
     callerCalleeProxy->setSourceModel(model);
     callerCalleeProxy->setSortRole(CallerCalleeModel::SortRole);
     view->setModel(callerCalleeProxy);
@@ -181,15 +168,11 @@ void setupCallerCalle(CallerCalleeModel* model, QTreeView* view,
     view->hideColumn(CallerCalleeModel::FileColumn);
     view->hideColumn(CallerCalleeModel::LineColumn);
     view->hideColumn(CallerCalleeModel::ModuleColumn);
-    QObject::connect(filterFunction, &QLineEdit::textChanged,
-                     callerCalleeProxy, &TreeProxy::setFunctionFilter);
-    QObject::connect(filterFile, &QLineEdit::textChanged,
-                     callerCalleeProxy, &TreeProxy::setFileFilter);
-    QObject::connect(filterModule, &QLineEdit::textChanged,
-                     callerCalleeProxy, &TreeProxy::setModuleFilter);
+    QObject::connect(filterFunction, &QLineEdit::textChanged, callerCalleeProxy, &TreeProxy::setFunctionFilter);
+    QObject::connect(filterFile, &QLineEdit::textChanged, callerCalleeProxy, &TreeProxy::setFileFilter);
+    QObject::connect(filterModule, &QLineEdit::textChanged, callerCalleeProxy, &TreeProxy::setModuleFilter);
     addContextMenu(view, CallerCalleeModel::LocationRole);
 }
-
 }
 
 MainWindow::MainWindow(QWidget* parent)
@@ -217,8 +200,7 @@ MainWindow::MainWindow(QWidget* parent)
     m_ui->tabWidget->setTabEnabled(m_ui->tabWidget->indexOf(m_ui->topDownTab), false);
     m_ui->tabWidget->setTabEnabled(m_ui->tabWidget->indexOf(m_ui->flameGraphTab), false);
 
-    connect(m_parser, &Parser::bottomUpDataAvailable,
-            this, [=] (const TreeData& data) {
+    connect(m_parser, &Parser::bottomUpDataAvailable, this, [=](const TreeData& data) {
         bottomUpModel->resetData(data);
         if (!m_diffMode) {
             m_ui->flameGraphTab->setBottomUpData(data);
@@ -228,75 +210,78 @@ MainWindow::MainWindow(QWidget* parent)
         statusBar()->addWidget(m_ui->loadingProgress);
         m_ui->pages->setCurrentWidget(m_ui->resultsPage);
     });
-    connect(m_parser, &Parser::callerCalleeDataAvailable,
-            this, [=] (const CallerCalleeRows& data) {
-                callerCalleeModel->resetData(data);
-                m_ui->tabWidget->setTabEnabled(m_ui->tabWidget->indexOf(m_ui->callerCalleeTab), true);
-            });
-    connect(m_parser, &Parser::topDownDataAvailable,
-            this, [=] (const TreeData& data) {
-                topDownModel->resetData(data);
-                m_ui->tabWidget->setTabEnabled(m_ui->tabWidget->indexOf(m_ui->topDownTab), true);
-                if (!m_diffMode) {
-                    m_ui->flameGraphTab->setTopDownData(data);
-                }
-                m_ui->tabWidget->setTabEnabled(m_ui->tabWidget->indexOf(m_ui->flameGraphTab), !m_diffMode);
-            });
-    connect(m_parser, &Parser::summaryAvailable,
-            this, [=] (const SummaryData& data) {
-                bottomUpModel->setSummary(data);
-                topDownModel->setSummary(data);
-                callerCalleeModel->setSummary(data);
-                KFormat format;
-                QString textLeft;
-                QString textCenter;
-                QString textRight;
-                const double totalTimeS = 0.001 * data.totalTime;
-                const double peakTimeS = 0.001 * data.peakTime;
-                {
-                    QTextStream stream(&textLeft);
-                    stream << "<qt><dl>"
-                           << i18n("<dt><b>debuggee</b>:</dt><dd style='font-family:monospace;'>%1</dd>", data.debuggee)
-                           // xgettext:no-c-format
-                           << i18n("<dt><b>total runtime</b>:</dt><dd>%1s</dd>", totalTimeS)
-                           << i18n("<dt><b>total system memory</b>:</dt><dd>%1</dd>", format.formatByteSize(data.totalSystemMemory))
-                           << "</dl></qt>";
-                }
-                {
-                    QTextStream stream(&textCenter);
-                    stream << "<qt><dl>"
-                           << i18n("<dt><b>calls to allocation functions</b>:</dt><dd>%1 (%2/s)</dd>",
-                                   data.cost.allocations, qint64(data.cost.allocations / totalTimeS))
-                           << i18n("<dt><b>temporary allocations</b>:</dt><dd>%1 (%2%, %3/s)</dd>",
-                                   data.cost.temporary, std::round(float(data.cost.temporary) * 100.f * 100.f / data.cost.allocations) / 100.f,
-                                   qint64(data.cost.temporary / totalTimeS))
-                           << i18n("<dt><b>bytes allocated in total</b> (ignoring deallocations):</dt><dd>%1 (%2/s)</dd>",
-                                   format.formatByteSize(data.cost.allocated, 2), format.formatByteSize(data.cost.allocated / totalTimeS))
-                           << "</dl></qt>";
-                }
-                {
-                    QTextStream stream(&textRight);
-                    stream << "<qt><dl>"
-                           << i18n("<dt><b>peak heap memory consumption</b>:</dt><dd>%1 after %2s</dd>", format.formatByteSize(data.cost.peak), peakTimeS)
-                           << i18n("<dt><b>peak RSS</b> (including heaptrack overhead):</dt><dd>%1</dd>", format.formatByteSize(data.peakRSS))
-                           << i18n("<dt><b>total memory leaked</b>:</dt><dd>%1</dd>", format.formatByteSize(data.cost.leaked))
-                           << "</dl></qt>";
-                }
-
-                m_ui->summaryLeft->setText(textLeft);
-                m_ui->summaryCenter->setText(textCenter);
-                m_ui->summaryRight->setText(textRight);
-            });
-    connect(m_parser, &Parser::progressMessageAvailable,
-            m_ui->progressLabel, &QLabel::setText);
+    connect(m_parser, &Parser::callerCalleeDataAvailable, this, [=](const CallerCalleeRows& data) {
+        callerCalleeModel->resetData(data);
+        m_ui->tabWidget->setTabEnabled(m_ui->tabWidget->indexOf(m_ui->callerCalleeTab), true);
+    });
+    connect(m_parser, &Parser::topDownDataAvailable, this, [=](const TreeData& data) {
+        topDownModel->resetData(data);
+        m_ui->tabWidget->setTabEnabled(m_ui->tabWidget->indexOf(m_ui->topDownTab), true);
+        if (!m_diffMode) {
+            m_ui->flameGraphTab->setTopDownData(data);
+        }
+        m_ui->tabWidget->setTabEnabled(m_ui->tabWidget->indexOf(m_ui->flameGraphTab), !m_diffMode);
+    });
+    connect(m_parser, &Parser::summaryAvailable, this, [=](const SummaryData& data) {
+        bottomUpModel->setSummary(data);
+        topDownModel->setSummary(data);
+        callerCalleeModel->setSummary(data);
+        KFormat format;
+        QString textLeft;
+        QString textCenter;
+        QString textRight;
+        const double totalTimeS = 0.001 * data.totalTime;
+        const double peakTimeS = 0.001 * data.peakTime;
+        {
+            QTextStream stream(&textLeft);
+            stream << "<qt><dl>" << i18n("<dt><b>debuggee</b>:</dt><dd "
+                                         "style='font-family:monospace;'>%1</dd>",
+                                         data.debuggee)
+                   // xgettext:no-c-format
+                   << i18n("<dt><b>total runtime</b>:</dt><dd>%1s</dd>", totalTimeS)
+                   << i18n("<dt><b>total system memory</b>:</dt><dd>%1</dd>",
+                           format.formatByteSize(data.totalSystemMemory))
+                   << "</dl></qt>";
+        }
+        {
+            QTextStream stream(&textCenter);
+            stream << "<qt><dl>" << i18n("<dt><b>calls to allocation functions</b>:</dt><dd>%1 "
+                                         "(%2/s)</dd>",
+                                         data.cost.allocations, qint64(data.cost.allocations / totalTimeS))
+                   << i18n("<dt><b>temporary allocations</b>:</dt><dd>%1 (%2%, "
+                           "%3/s)</dd>",
+                           data.cost.temporary,
+                           std::round(float(data.cost.temporary) * 100.f * 100.f / data.cost.allocations) / 100.f,
+                           qint64(data.cost.temporary / totalTimeS))
+                   << i18n("<dt><b>bytes allocated in total</b> (ignoring "
+                           "deallocations):</dt><dd>%1 (%2/s)</dd>",
+                           format.formatByteSize(data.cost.allocated, 2),
+                           format.formatByteSize(data.cost.allocated / totalTimeS))
+                   << "</dl></qt>";
+        }
+        {
+            QTextStream stream(&textRight);
+            stream << "<qt><dl>" << i18n("<dt><b>peak heap memory consumption</b>:</dt><dd>%1 "
+                                         "after %2s</dd>",
+                                         format.formatByteSize(data.cost.peak), peakTimeS)
+                   << i18n("<dt><b>peak RSS</b> (including heaptrack "
+                           "overhead):</dt><dd>%1</dd>",
+                           format.formatByteSize(data.peakRSS))
+                   << i18n("<dt><b>total memory leaked</b>:</dt><dd>%1</dd>", format.formatByteSize(data.cost.leaked))
+                   << "</dl></qt>";
+        }
+
+        m_ui->summaryLeft->setText(textLeft);
+        m_ui->summaryCenter->setText(textCenter);
+        m_ui->summaryRight->setText(textRight);
+    });
+    connect(m_parser, &Parser::progressMessageAvailable, m_ui->progressLabel, &QLabel::setText);
     auto removeProgress = [this] {
         statusBar()->removeWidget(m_ui->progressLabel);
         statusBar()->removeWidget(m_ui->loadingProgress);
     };
-    connect(m_parser, &Parser::finished,
-            this, removeProgress);
-    connect(m_parser, &Parser::failedToOpen,
-            this, [this, removeProgress] (const QString& failedFile) {
+    connect(m_parser, &Parser::finished, this, removeProgress);
+    connect(m_parser, &Parser::failedToOpen, this, [this, removeProgress](const QString& failedFile) {
         removeProgress();
         m_ui->pages->setCurrentWidget(m_ui->openPage);
         showError(i18n("Failed to parse file %1.", failedFile));
@@ -304,14 +289,13 @@ MainWindow::MainWindow(QWidget* parent)
     m_ui->messages->hide();
 
 #if KChart_FOUND
-    addChartTab(m_ui->tabWidget, tr("Consumed"), ChartModel::Consumed,
-                m_parser, &Parser::consumedChartDataAvailable);
-    addChartTab(m_ui->tabWidget, tr("Allocations"), ChartModel::Allocations,
-                m_parser, &Parser::allocationsChartDataAvailable);
-    addChartTab(m_ui->tabWidget, tr("Temporary Allocations"), ChartModel::Temporary,
-                m_parser, &Parser::temporaryChartDataAvailable);
-    addChartTab(m_ui->tabWidget, tr("Allocated"), ChartModel::Allocated,
-                m_parser, &Parser::allocatedChartDataAvailable);
+    addChartTab(m_ui->tabWidget, tr("Consumed"), ChartModel::Consumed, m_parser, &Parser::consumedChartDataAvailable);
+    addChartTab(m_ui->tabWidget, tr("Allocations"), ChartModel::Allocations, m_parser,
+                &Parser::allocationsChartDataAvailable);
+    addChartTab(m_ui->tabWidget, tr("Temporary Allocations"), ChartModel::Temporary, m_parser,
+                &Parser::temporaryChartDataAvailable);
+    addChartTab(m_ui->tabWidget, tr("Allocated"), ChartModel::Allocated, m_parser,
+                &Parser::allocatedChartDataAvailable);
 
     auto sizesTab = new HistogramWidget(this);
     m_ui->tabWidget->addTab(sizesTab, tr("Sizes"));
@@ -319,29 +303,24 @@ MainWindow::MainWindow(QWidget* parent)
     auto sizeHistogramModel = new HistogramModel(this);
     sizesTab->setModel(sizeHistogramModel);
 
-    connect(m_parser, &Parser::sizeHistogramDataAvailable,
-            this, [=] (const HistogramData& data) {
-                sizeHistogramModel->resetData(data);
-                m_ui->tabWidget->setTabEnabled(m_ui->tabWidget->indexOf(sizesTab), true);
-            });
+    connect(m_parser, &Parser::sizeHistogramDataAvailable, this, [=](const HistogramData& data) {
+        sizeHistogramModel->resetData(data);
+        m_ui->tabWidget->setTabEnabled(m_ui->tabWidget->indexOf(sizesTab), true);
+    });
 #endif
 
     auto costDelegate = new CostDelegate(this);
 
-    setupTreeModel(bottomUpModel, m_ui->bottomUpResults, costDelegate,
-                   m_ui->bottomUpFilterFunction, m_ui->bottomUpFilterFile,
-                   m_ui->bottomUpFilterModule);
+    setupTreeModel(bottomUpModel, m_ui->bottomUpResults, costDelegate, m_ui->bottomUpFilterFunction,
+                   m_ui->bottomUpFilterFile, m_ui->bottomUpFilterModule);
 
-    setupTreeModel(topDownModel, m_ui->topDownResults, costDelegate,
-                   m_ui->topDownFilterFunction, m_ui->topDownFilterFile,
-                   m_ui->topDownFilterModule);
+    setupTreeModel(topDownModel, m_ui->topDownResults, costDelegate, m_ui->topDownFilterFunction,
+                   m_ui->topDownFilterFile, m_ui->topDownFilterModule);
 
-    setupCallerCalle(callerCalleeModel, m_ui->callerCalleeResults, costDelegate,
-                     m_ui->callerCalleeFilterFunction,
-                     m_ui->callerCalleeFilterFile,
-                     m_ui->callerCalleeFilterModule);
+    setupCallerCalle(callerCalleeModel, m_ui->callerCalleeResults, costDelegate, m_ui->callerCalleeFilterFunction,
+                     m_ui->callerCalleeFilterFile, m_ui->callerCalleeFilterModule);
 
-    auto validateInputFile = [this] (const QString &path, bool allowEmpty) -> bool {
+    auto validateInputFile = [this](const QString& path, bool allowEmpty) -> bool {
         if (path.isEmpty()) {
             return allowEmpty;
         }
@@ -359,25 +338,20 @@ MainWindow::MainWindow(QWidget* parent)
         return false;
     };
 
-    auto validateInput = [this, validateInputFile] () {
+    auto validateInput = [this, validateInputFile]() {
         m_ui->messages->hide();
-        m_ui->buttonBox->setEnabled(
-            validateInputFile(m_ui->openFile->url().toLocalFile(), false)
-            && validateInputFile(m_ui->compareTo->url().toLocalFile(), true)
-        );
+        m_ui->buttonBox->setEnabled(validateInputFile(m_ui->openFile->url().toLocalFile(), false)
+                                    && validateInputFile(m_ui->compareTo->url().toLocalFile(), true));
     };
 
-    connect(m_ui->openFile, &KUrlRequester::textChanged,
-            this, validateInput);
-    connect(m_ui->compareTo, &KUrlRequester::textChanged,
-            this, validateInput);
-    connect(m_ui->buttonBox, &QDialogButtonBox::accepted,
-            this, [this] () {
-                const auto path = m_ui->openFile->url().toLocalFile();
-                Q_ASSERT(!path.isEmpty());
-                const auto base = m_ui->compareTo->url().toLocalFile();
-                loadFile(path, base);
-            });
+    connect(m_ui->openFile, &KUrlRequester::textChanged, this, validateInput);
+    connect(m_ui->compareTo, &KUrlRequester::textChanged, this, validateInput);
+    connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, [this]() {
+        const auto path = m_ui->openFile->url().toLocalFile();
+        Q_ASSERT(!path.isEmpty());
+        const auto base = m_ui->compareTo->url().toLocalFile();
+        loadFile(path, base);
+    });
 
     setupStacks();
 
@@ -406,8 +380,7 @@ void MainWindow::loadFile(const QString& file, const QString& diffBase)
 {
     m_ui->loadingLabel->setText(i18n("Loading file %1, please wait...", file));
     if (diffBase.isEmpty()) {
-        setWindowTitle(i18nc("%1: file name that is open", "Heaptrack - %1",
-                             QFileInfo(file).fileName()));
+        setWindowTitle(i18nc("%1: file name that is open", "Heaptrack - %1", QFileInfo(file).fileName()));
         m_diffMode = false;
     } else {
         setWindowTitle(i18nc("%1, %2: file names that are open", "Heaptrack - %1 compared to %2",
@@ -420,17 +393,15 @@ void MainWindow::loadFile(const QString& file, const QString& diffBase)
 
 void MainWindow::openFile()
 {
-    auto dialog = new QFileDialog(this, i18n("Open Heaptrack Output File"), {}, i18n("Heaptrack data files (heaptrack.*)"));
+    auto dialog =
+        new QFileDialog(this, i18n("Open Heaptrack Output File"), {}, i18n("Heaptrack data files (heaptrack.*)"));
     dialog->setAttribute(Qt::WA_DeleteOnClose, true);
     dialog->setFileMode(QFileDialog::ExistingFile);
-    connect(dialog, &QFileDialog::fileSelected,
-            this, [this] (const QString& file) {
-                loadFile(file);
-            });
+    connect(dialog, &QFileDialog::fileSelected, this, [this](const QString& file) { loadFile(file); });
     dialog->show();
 }
 
-void MainWindow::showError(const QString &message)
+void MainWindow::showError(const QStringmessage)
 {
     m_ui->messages->setText(message);
     m_ui->messages->show();
@@ -442,18 +413,17 @@ void MainWindow::setupStacks()
     m_ui->stacksTree->setModel(stacksModel);
     m_ui->stacksTree->setRootIsDecorated(false);
 
-    auto updateStackSpinner = [this] (int stacks) {
+    auto updateStackSpinner = [this](int stacks) {
         m_ui->stackSpinner->setMinimum(min(stacks, 1));
         m_ui->stackSpinner->setSuffix(i18n(" / %1", stacks));
         m_ui->stackSpinner->setMaximum(stacks);
     };
     updateStackSpinner(0);
-    connect(stacksModel, &StacksModel::stacksFound,
-            this, updateStackSpinner);
-    connect(m_ui->stackSpinner, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
-            stacksModel, &StacksModel::setStackIndex);
+    connect(stacksModel, &StacksModel::stacksFound, this, updateStackSpinner);
+    connect(m_ui->stackSpinner, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), stacksModel,
+            &StacksModel::setStackIndex);
 
-    auto fillFromIndex = [stacksModel] (const QModelIndex& current) {
+    auto fillFromIndex = [stacksModel](const QModelIndex& current) {
         if (!current.isValid()) {
             stacksModel->clear();
         } else {
@@ -463,12 +433,10 @@ void MainWindow::setupStacks()
             stacksModel->fillFromIndex(leaf);
         }
     };
-    connect(m_ui->bottomUpResults->selectionModel(), &QItemSelectionModel::currentChanged,
-            this, fillFromIndex);
-    connect(m_ui->topDownResults->selectionModel(), &QItemSelectionModel::currentChanged,
-            this, fillFromIndex);
+    connect(m_ui->bottomUpResults->selectionModel(), &QItemSelectionModel::currentChanged, this, fillFromIndex);
+    connect(m_ui->topDownResults->selectionModel(), &QItemSelectionModel::currentChanged, this, fillFromIndex);
 
-    auto tabChanged = [this, fillFromIndex] (int tabIndex) {
+    auto tabChanged = [this, fillFromIndex](int tabIndex) {
         const auto widget = m_ui->tabWidget->widget(tabIndex);
         const bool showDocks = (widget == m_ui->topDownTab || widget == m_ui->bottomUpTab);
         m_ui->stacksDock->setVisible(showDocks);
@@ -477,10 +445,8 @@ void MainWindow::setupStacks()
             fillFromIndex(tree->selectionModel()->currentIndex());
         }
     };
-    connect(m_ui->tabWidget, &QTabWidget::currentChanged,
-            this, tabChanged);
-    connect(m_parser, &Parser::bottomUpDataAvailable,
-            this, [tabChanged] () { tabChanged(0); });
+    connect(m_ui->tabWidget, &QTabWidget::currentChanged, this, tabChanged);
+    connect(m_parser, &Parser::bottomUpDataAvailable, this, [tabChanged]() { tabChanged(0); });
 
     m_ui->stacksDock->setVisible(false);
 }
index 9f27280..358b5c2 100644 (file)
@@ -21,6 +21,7 @@
 #define MAINWINDOW_H
 
 #include <QMainWindow>
+
 #include <KSharedConfig>
 
 namespace Ui {
@@ -43,7 +44,7 @@ public slots:
     void openFile();
 
 private:
-    void showError(const QString &message);
+    void showError(const QStringmessage);
     void setupStacks();
 
     QScopedPointer<Ui::MainWindow> m_ui;
index a1731e3..eb9ffd9 100644 (file)
@@ -20,6 +20,7 @@
 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 **
 ****************************************************************************/
+// clang-format off
 
 #include "modeltest.h"
 
index 00082d6..dd2599a 100644 (file)
@@ -20,6 +20,7 @@
 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 **
 ****************************************************************************/
+// clang-format off
 
 #ifndef KDEVPLATFORM_MODELTEST_H
 #define KDEVPLATFORM_MODELTEST_H
index cd3d9c5..e307879 100644 (file)
 
 #include "parser.h"
 
-#include <ThreadWeaver/ThreadWeaver>
 #include <KLocalizedString>
+#include <ThreadWeaver/ThreadWeaver>
 
 #include <QDebug>
 
 #include "analyze/accumulatedtracedata.h"
 
-#include <vector>
-#include <tuple>
 #include <future>
+#include <tuple>
+#include <vector>
 
 using namespace std;
 
@@ -94,8 +94,8 @@ struct StringCache
 
     void update(const vector<string>& strings)
     {
-        transform(strings.begin() + m_strings.size(), strings.end(),
-                  back_inserter(m_strings), [] (const string& str) { return QString::fromStdString(str); });
+        transform(strings.begin() + m_strings.size(), strings.end(), back_inserter(m_strings),
+                  [](const string& str) { return QString::fromStdString(str); });
     }
 
     vector<QString> m_strings;
@@ -169,11 +169,11 @@ struct ParserData final : public AccumulatedTraceData
             it->allocations += alloc.allocations;
             it->temporary += alloc.temporary;
         }
-        // find the top hot spots for the individual data members and remember their IP and store the label
-        auto findTopChartEntries = [&] (qint64 ChartMergeData::* member, int LabelIds::* label, ChartData* data) {
-            sort(merged.begin(), merged.end(), [=] (const ChartMergeData& left, const ChartMergeData& right) {
-                return left.*member > right.*member;
-            });
+        // find the top hot spots for the individual data members and remember their
+        // IP and store the label
+        auto findTopChartEntries = [&](qint64 ChartMergeData::*member, int LabelIds::*label, ChartData* data) {
+            sort(merged.begin(), merged.end(),
+                 [=](const ChartMergeData& left, const ChartMergeData& right) { return left.*member > right.*member; });
             for (size_t i = 0; i < min(size_t(ChartRows::MAX_NUM_COST - 1), merged.size()); ++i) {
                 const auto& alloc = merged[i];
                 if (!(alloc.*member)) {
@@ -206,7 +206,7 @@ struct ParserData final : public AccumulatedTraceData
         lastTimeStamp = newStamp;
 
         // create the rows
-        auto createRow = [] (int64_t timeStamp, int64_t totalCost) {
+        auto createRow = [](int64_t timeStamp, int64_t totalCost) {
             ChartRows row;
             row.timeStamp = timeStamp;
             row.cost[0] = totalCost;
@@ -217,9 +217,10 @@ struct ParserData final : public AccumulatedTraceData
         auto allocs = createRow(newStamp, totalCost.allocations);
         auto temporary = createRow(newStamp, totalCost.temporary);
 
-        // if the cost is non-zero and the ip corresponds to a hotspot function selected in the labels,
+        // if the cost is non-zero and the ip corresponds to a hotspot function
+        // selected in the labels,
         // we add the cost to the rows column
-        auto addDataToRow = [] (int64_t cost, int labelId, ChartRows* rows) {
+        auto addDataToRow = [](int64_t cost, int labelId, ChartRows* rows) {
             if (!cost || labelId == -1) {
                 return;
             }
@@ -268,8 +269,7 @@ struct ParserData final : public AccumulatedTraceData
         int64_t allocations;
         bool operator<(const CountedAllocationInfo& rhs) const
         {
-            return tie(info.size, allocations)
-                 < tie(rhs.info.size, rhs.allocations);
+            return tie(info.size, allocations) < tie(rhs.info.size, rhs.allocations);
         }
     };
     vector<CountedAllocationInfo> allocationInfoCounter;
@@ -300,7 +300,7 @@ struct ParserData final : public AccumulatedTraceData
 
 void setParents(QVector<RowData>& children, const RowData* parent)
 {
-    for (auto& row: children) {
+    for (auto& row : children) {
         row.parent = parent;
         setParents(row.children, &row);
     }
@@ -311,7 +311,8 @@ QPair<TreeData, CallerCalleeRows> mergeAllocations(const ParserData& data)
     TreeData topRows;
     CallerCalleeRows callerCalleeRows;
     callerCalleeRows.reserve(data.instructionPointers.size());
-    // merge allocations, leave parent pointers invalid (their location may change)
+    // merge allocations, leave parent pointers invalid (their location may
+    // change)
     for (const auto& allocation : data.allocations) {
         auto traceIndex = allocation.traceIndex;
         auto rows = &topRows;
@@ -323,10 +324,9 @@ QPair<TreeData, CallerCalleeRows> mergeAllocations(const ParserData& data)
             auto location = data.stringCache.location(trace.ipIndex, ip);
 
             if (!recursionGuard.contains(trace.ipIndex)) { // aggregate caller-callee data
-                auto it = lower_bound(callerCalleeRows.begin(), callerCalleeRows.end(), location,
-                                      [] (const CallerCalleeData& lhs, const LocationData::Ptr& rhs) {
-                    return lhs.location < rhs;
-                });
+                auto it = lower_bound(
+                    callerCalleeRows.begin(), callerCalleeRows.end(), location,
+                    [](const CallerCalleeData& lhs, const LocationData::Ptr& rhs) { return lhs.location < rhs; });
                 if (it == callerCalleeRows.end() || it->location != location) {
                     it = callerCalleeRows.insert(it, {{}, {}, location});
                 }
@@ -356,10 +356,11 @@ QPair<TreeData, CallerCalleeRows> mergeAllocations(const ParserData& data)
     if (data.stringCache.diffMode) {
         // remove rows without cost
         callerCalleeRows.erase(remove_if(callerCalleeRows.begin(), callerCalleeRows.end(),
-            [] (const CallerCalleeData& data) -> bool {
-                return data.inclusiveCost == AllocationData()
-                    && data.selfCost == AllocationData();
-            }), callerCalleeRows.end());
+                                         [](const CallerCalleeData& data) -> bool {
+                                             return data.inclusiveCost == AllocationData()
+                                                 && data.selfCost == AllocationData();
+                                         }),
+                               callerCalleeRows.end());
     }
 
     return qMakePair(topRows, callerCalleeRows);
@@ -430,26 +431,25 @@ HistogramData buildSizeHistogram(ParserData& data)
     sort(data.allocationInfoCounter.begin(), data.allocationInfoCounter.end());
     const auto totalLabel = i18n("total");
     HistogramRow row;
-    const pair<uint64_t, QString> buckets[] = {
-        {8, i18n("0B to 8B")},
-        {16, i18n("9B to 16B")},
-        {32, i18n("17B to 32B")},
-        {64, i18n("33B to 64B")},
-        {128, i18n("65B to 128B")},
-        {256, i18n("129B to 256B")},
-        {512, i18n("257B to 512B")},
-        {1024, i18n("512B to 1KB")},
-        {numeric_limits<uint64_t>::max(), i18n("more than 1KB")}
-    };
+    const pair<uint64_t, QString> buckets[] = {{8, i18n("0B to 8B")},
+                                               {16, i18n("9B to 16B")},
+                                               {32, i18n("17B to 32B")},
+                                               {64, i18n("33B to 64B")},
+                                               {128, i18n("65B to 128B")},
+                                               {256, i18n("129B to 256B")},
+                                               {512, i18n("257B to 512B")},
+                                               {1024, i18n("512B to 1KB")},
+                                               {numeric_limits<uint64_t>::max(), i18n("more than 1KB")}};
     uint bucketIndex = 0;
     row.size = buckets[bucketIndex].first;
     row.sizeLabel = buckets[bucketIndex].second;
     vector<MergedHistogramColumnData> columnData;
     columnData.reserve(128);
-    auto insertColumns = [&] () {
-        sort(columnData.begin(), columnData.end(), [] (const MergedHistogramColumnData& lhs, const MergedHistogramColumnData& rhs) {
-            return lhs.allocations > rhs.allocations;
-        });
+    auto insertColumns = [&]() {
+        sort(columnData.begin(), columnData.end(),
+             [](const MergedHistogramColumnData& lhs, const MergedHistogramColumnData& rhs) {
+                 return lhs.allocations > rhs.allocations;
+             });
         // -1 to account for total row
         for (size_t i = 0; i < min(columnData.size(), size_t(HistogramRow::NUM_COLUMNS - 1)); ++i) {
             const auto& column = columnData[i];
@@ -482,7 +482,6 @@ HistogramData buildSizeHistogram(ParserData& data)
     ret << row;
     return ret;
 }
-
 }
 
 Parser::Parser(QObject* parent)
@@ -503,9 +502,8 @@ void Parser::parse(const QString& path, const QString& diffBase)
 
         if (!diffBase.isEmpty()) {
             ParserData diffData;
-            auto readBase = async(launch::async, [&diffData, diffBase] () {
-                return diffData.read(diffBase.toStdString());
-            });
+            auto readBase =
+                async(launch::async, [&diffData, diffBase]() { return diffData.read(diffBase.toStdString()); });
             if (!data->read(stdPath)) {
                 emit failedToOpen(path);
                 return;
@@ -523,14 +521,9 @@ void Parser::parse(const QString& path, const QString& diffBase)
 
         data->updateStringCache();
 
-        emit summaryAvailable({
-            QString::fromStdString(data->debuggee),
-            data->totalCost,
-            data->totalTime,
-            data->peakTime,
-            data->peakRSS * data->systemInfo.pageSize,
-            data->systemInfo.pages * data->systemInfo.pageSize
-        });
+        emit summaryAvailable({QString::fromStdString(data->debuggee), data->totalCost, data->totalTime, data->peakTime,
+                               data->peakRSS * data->systemInfo.pageSize,
+                               data->systemInfo.pages * data->systemInfo.pageSize});
 
         emit progressMessageAvailable(i18n("merging allocations..."));
         // merge allocations before modifying the data again
@@ -565,9 +558,7 @@ void Parser::parse(const QString& path, const QString& diffBase)
         }
 
         auto sequential = new Sequence;
-        *sequential << parallel << make_job([this]() {
-            emit finished();
-        });
+        *sequential << parallel << make_job([this]() { emit finished(); });
 
         stream() << sequential;
     });
index 7eb0e38..f654352 100644 (file)
 
 #include <QObject>
 
-#include "treemodel.h"
+#include "callercalleemodel.h"
 #include "chartmodel.h"
 #include "histogrammodel.h"
-#include "callercalleemodel.h"
+#include "treemodel.h"
 
 class Parser : public QObject
 {
index 9fd785e..dcb2eeb 100644 (file)
@@ -20,9 +20,9 @@
 #ifndef SUMMARYDATA_H
 #define SUMMARYDATA_H
 
-#include <QString>
-#include <QMetaType>
 #include "../allocationdata.h"
+#include <QMetaType>
+#include <QString>
 
 struct SummaryData
 {
index 222929e..db885f3 100644 (file)
@@ -30,7 +30,7 @@ TreeModel::Columns toSource(TopProxy::Type type)
     case TopProxy::Leaked:
         return TreeModel::LeakedColumn;
     case TopProxy::Allocations:
-        return TreeModel::AllocationsColumn;;
+        return TreeModel::AllocationsColumn;
     case TopProxy::Temporary:
         return TreeModel::TemporaryColumn;
     case TopProxy::Allocated:
@@ -60,7 +60,8 @@ bool TopProxy::filterAcceptsRow(int source_row, const QModelIndex& source_parent
         return false;
     }
     if (!sourceModel()->index(source_row, toSource(m_type)).data(TreeModel::SortRole).toULongLong()) {
-        // don't show rows that didn't leak anything, or didn't trigger any temporary allocations
+        // don't show rows that didn't leak anything, or didn't trigger any
+        // temporary allocations
         return false;
     }
     return true;
index 8cfad73..c5e4c03 100644 (file)
@@ -28,7 +28,8 @@ class TopProxy : public QSortFilterProxyModel
 {
     Q_OBJECT
 public:
-    enum Type {
+    enum Type
+    {
         Peak,
         Leaked,
         Allocations,
index 1689098..c939a11 100644 (file)
@@ -53,7 +53,6 @@ QString basename(const QString& path)
     int idx = path.lastIndexOf(QLatin1Char('/'));
     return path.mid(idx + 1);
 }
-
 }
 
 TreeModel::TreeModel(QObject* parent)
@@ -72,67 +71,76 @@ QVariant TreeModel::headerData(int section, Qt::Orientation orientation, int rol
         return {};
     }
     if (role == Qt::InitialSortOrderRole) {
-        if (section == AllocatedColumn || section == AllocationsColumn
-            || section == PeakColumn || section == LeakedColumn
-            || section == TemporaryColumn)
-        {
+        if (section == AllocatedColumn || section == AllocationsColumn || section == PeakColumn
+            || section == LeakedColumn || section == TemporaryColumn) {
             return Qt::DescendingOrder;
         }
     }
     if (role == Qt::DisplayRole) {
         switch (static_cast<Columns>(section)) {
-            case FileColumn:
-                return i18n("File");
-            case LineColumn:
-                return i18n("Line");
-            case FunctionColumn:
-                return i18n("Function");
-            case ModuleColumn:
-                return i18n("Module");
-            case AllocationsColumn:
-                return i18n("Allocations");
-            case TemporaryColumn:
-                return i18n("Temporary");
-            case PeakColumn:
-                return i18n("Peak");
-            case LeakedColumn:
-                return i18n("Leaked");
-            case AllocatedColumn:
-                return i18n("Allocated");
-            case LocationColumn:
-                return i18n("Location");
-            case NUM_COLUMNS:
-                break;
+        case FileColumn:
+            return i18n("File");
+        case LineColumn:
+            return i18n("Line");
+        case FunctionColumn:
+            return i18n("Function");
+        case ModuleColumn:
+            return i18n("Module");
+        case AllocationsColumn:
+            return i18n("Allocations");
+        case TemporaryColumn:
+            return i18n("Temporary");
+        case PeakColumn:
+            return i18n("Peak");
+        case LeakedColumn:
+            return i18n("Leaked");
+        case AllocatedColumn:
+            return i18n("Allocated");
+        case LocationColumn:
+            return i18n("Location");
+        case NUM_COLUMNS:
+            break;
         }
     } else if (role == Qt::ToolTipRole) {
         switch (static_cast<Columns>(section)) {
-            case FileColumn:
-                return i18n("<qt>The file where the allocation function was called from. "
-                            "May be empty when debug information is missing.</qt>");
-            case LineColumn:
-                return i18n("<qt>The line number where the allocation function was called from. "
-                            "May be empty when debug information is missing.</qt>");
-            case FunctionColumn:
-                return i18n("<qt>The parent function that called an allocation function. "
-                            "May be unknown when debug information is missing.</qt>");
-            case ModuleColumn:
-                return i18n("<qt>The module, i.e. executable or shared library, from which an allocation function was called.</qt>");
-            case AllocationsColumn:
-                return i18n("<qt>The number of times an allocation function was called from this location.</qt>");
-            case TemporaryColumn:
-                return i18n("<qt>The number of temporary allocations. These allocations are directly followed by a free without any other allocations in-between.</qt>");
-            case PeakColumn:
-                return i18n("<qt>The maximum heap memory in bytes consumed from allocations originating at this location. "
-                            "This takes deallocations into account.</qt>");
-            case LeakedColumn:
-                return i18n("<qt>The bytes allocated at this location that have not been deallocated.</qt>");
-            case AllocatedColumn:
-                return i18n("<qt>The sum of all bytes allocated from this location, ignoring deallocations.</qt>");
-            case LocationColumn:
-                return i18n("<qt>The location from which an allocation function was called. Function symbol and file information "
-                            "may be unknown when debug information was missing when heaptrack was run.</qt>");
-            case NUM_COLUMNS:
-                break;
+        case FileColumn:
+            return i18n("<qt>The file where the allocation function was called from. "
+                        "May be empty when debug information is missing.</qt>");
+        case LineColumn:
+            return i18n("<qt>The line number where the allocation function was called from. "
+                        "May be empty when debug information is missing.</qt>");
+        case FunctionColumn:
+            return i18n("<qt>The parent function that called an allocation function. "
+                        "May be unknown when debug information is missing.</qt>");
+        case ModuleColumn:
+            return i18n("<qt>The module, i.e. executable or shared library, from "
+                        "which an allocation function was "
+                        "called.</qt>");
+        case AllocationsColumn:
+            return i18n("<qt>The number of times an allocation function was called "
+                        "from this location.</qt>");
+        case TemporaryColumn:
+            return i18n("<qt>The number of temporary allocations. These allocations "
+                        "are directly followed by a free "
+                        "without any other allocations in-between.</qt>");
+        case PeakColumn:
+            return i18n("<qt>The maximum heap memory in bytes consumed from "
+                        "allocations originating at this location. "
+                        "This takes deallocations into account.</qt>");
+        case LeakedColumn:
+            return i18n("<qt>The bytes allocated at this location that have not been "
+                        "deallocated.</qt>");
+        case AllocatedColumn:
+            return i18n("<qt>The sum of all bytes allocated from this location, "
+                        "ignoring deallocations.</qt>");
+        case LocationColumn:
+            return i18n("<qt>The location from which an allocation function was "
+                        "called. Function symbol and file "
+                        "information "
+                        "may be unknown when debug information was missing when "
+                        "heaptrack was run.</qt>");
+        case NUM_COLUMNS:
+            break;
         }
     }
     return {};
@@ -185,13 +193,10 @@ QVariant TreeModel::data(const QModelIndex& index, int role) const
             return row->location->line;
         case LocationColumn:
             if (row->location->file.isEmpty()) {
-                return i18n("%1 in ?? (%2)",
-                            basename(row->location->function),
-                            basename(row->location->module));
+                return i18n("%1 in ?? (%2)", basename(row->location->function), basename(row->location->module));
             } else {
-                return i18n("%1 in %2:%3 (%4)", row->location->function,
-                            basename(row->location->file), row->location->line,
-                            basename(row->location->module));
+                return i18n("%1 in %2:%3 (%4)", row->location->function, basename(row->location->file),
+                            row->location->line, basename(row->location->module));
             }
         case NUM_COLUMNS:
             break;
@@ -202,28 +207,31 @@ QVariant TreeModel::data(const QModelIndex& index, int role) const
         stream << "<qt><pre style='font-family:monospace;'>";
         if (row->location->line > 0) {
             stream << i18nc("1: function, 2: file, 3: line, 4: module", "%1\n  at %2:%3\n  in %4",
-                            row->location->function.toHtmlEscaped(),
-                            row->location->file.toHtmlEscaped(), row->location->line, row->location->module.toHtmlEscaped());
+                            row->location->function.toHtmlEscaped(), row->location->file.toHtmlEscaped(),
+                            row->location->line, row->location->module.toHtmlEscaped());
         } else {
-            stream << i18nc("1: function, 2: module", "%1\n  in %2",
-                            row->location->function.toHtmlEscaped(), row->location->module.toHtmlEscaped());
+            stream << i18nc("1: function, 2: module", "%1\n  in %2", row->location->function.toHtmlEscaped(),
+                            row->location->module.toHtmlEscaped());
         }
         stream << '\n';
         stream << '\n';
         KFormat format;
-        const auto allocatedFraction = QString::number(double(row->cost.allocated)  * 100. / m_maxCost.cost.allocated, 'g', 3);
-        const auto peakFraction = QString::number(double(row->cost.peak)  * 100. / m_maxCost.cost.peak, 'g', 3);
-        const auto leakedFraction = QString::number(double(row->cost.leaked)  * 100. / m_maxCost.cost.leaked, 'g', 3);
-        const auto allocationsFraction = QString::number(double(row->cost.allocations)  * 100. / m_maxCost.cost.allocations, 'g', 3);
-        const auto temporaryFraction = QString::number(double(row->cost.temporary)  * 100. / row->cost.allocations, 'g', 3);
-        const auto temporaryFractionTotal = QString::number(double(row->cost.temporary)  * 100. / m_maxCost.cost.temporary, 'g', 3);
-        stream << i18n("allocated: %1 (%2% of total)\n",
-                       format.formatByteSize(row->cost.allocated), allocatedFraction);
+        const auto allocatedFraction =
+            QString::number(double(row->cost.allocated) * 100. / m_maxCost.cost.allocated, 'g', 3);
+        const auto peakFraction = QString::number(double(row->cost.peak) * 100. / m_maxCost.cost.peak, 'g', 3);
+        const auto leakedFraction = QString::number(double(row->cost.leaked) * 100. / m_maxCost.cost.leaked, 'g', 3);
+        const auto allocationsFraction =
+            QString::number(double(row->cost.allocations) * 100. / m_maxCost.cost.allocations, 'g', 3);
+        const auto temporaryFraction =
+            QString::number(double(row->cost.temporary) * 100. / row->cost.allocations, 'g', 3);
+        const auto temporaryFractionTotal =
+            QString::number(double(row->cost.temporary) * 100. / m_maxCost.cost.temporary, 'g', 3);
+        stream << i18n("allocated: %1 (%2% of total)\n", format.formatByteSize(row->cost.allocated), allocatedFraction);
         stream << i18n("peak: %1 (%2% of total)\n", format.formatByteSize(row->cost.peak), peakFraction);
         stream << i18n("leaked: %1 (%2% of total)\n", format.formatByteSize(row->cost.leaked), leakedFraction);
         stream << i18n("allocations: %1 (%2% of total)\n", row->cost.allocations, allocationsFraction);
-        stream << i18n("temporary: %1 (%2% of allocations, %3% of total)\n",
-                       row->cost.temporary, temporaryFraction, temporaryFractionTotal);
+        stream << i18n("temporary: %1 (%2% of allocations, %3% of total)\n", row->cost.temporary, temporaryFraction,
+                       temporaryFractionTotal);
         if (!row->children.isEmpty()) {
             auto child = row;
             int max = 5;
@@ -234,12 +242,11 @@ QVariant TreeModel::data(const QModelIndex& index, int role) const
                 stream << "\n";
                 if (child->location->line > 0) {
                     stream << i18nc("1: function, 2: file, 3: line, 4: module", "%1\n  at %2:%3\n  in %4",
-                                    child->location->function.toHtmlEscaped(),
-                                    child->location->file.toHtmlEscaped(), child->location->line,
-                                    child->location->module.toHtmlEscaped());
+                                    child->location->function.toHtmlEscaped(), child->location->file.toHtmlEscaped(),
+                                    child->location->line, child->location->module.toHtmlEscaped());
                 } else {
-                    stream << i18nc("1: function, 2: module", "%1\n  in %2",
-                                    child->location->function.toHtmlEscaped(), child->location->module.toHtmlEscaped());
+                    stream << i18nc("1: function, 2: module", "%1\n  in %2", child->location->function.toHtmlEscaped(),
+                                    child->location->module.toHtmlEscaped());
                 }
                 child = child->children.data();
             }
@@ -258,7 +265,7 @@ QVariant TreeModel::data(const QModelIndex& index, int role) const
 
 QModelIndex TreeModel::index(int row, int column, const QModelIndex& parent) const
 {
-    if (row < 0 || column  < 0 || column >= NUM_COLUMNS || row >= rowCount(parent)) {
+    if (row < 0 || column < 0 || column >= NUM_COLUMNS || row >= rowCount(parent)) {
         return QModelIndex();
     }
     return createIndex(row, column, const_cast<void*>(reinterpret_cast<const void*>(toRow(parent))));
index fe2762f..01f95ee 100644 (file)
@@ -25,9 +25,9 @@
 
 #include <KFormat>
 
+#include "../allocationdata.h"
 #include "locationdata.h"
 #include "summarydata.h"
-#include "../allocationdata.h"
 
 struct RowData
 {
@@ -52,7 +52,8 @@ public:
     TreeModel(QObject* parent);
     virtual ~TreeModel();
 
-    enum Columns {
+    enum Columns
+    {
         AllocationsColumn,
         TemporaryColumn,
         PeakColumn,
@@ -66,7 +67,8 @@ public:
         NUM_COLUMNS
     };
 
-    enum Roles {
+    enum Roles
+    {
         SortRole = Qt::UserRole,
         MaxCostRole,
         LocationRole
@@ -96,4 +98,3 @@ private:
 };
 
 #endif // TREEMODEL_H
-
index 74576a3..2af5cf0 100644 (file)
@@ -46,4 +46,4 @@ private:
     QString m_moduleFilter;
 };
 
-#endif //TREEPROXY_H
+#endif // TREEPROXY_H
index cb9ce2d..8579083 100644 (file)
@@ -27,9 +27,9 @@
 
 #include "analyze/accumulatedtracedata.h"
 
-#include <iostream>
-#include <iomanip>
 #include <future>
+#include <iomanip>
+#include <iostream>
 
 #include "util/config.h"
 
@@ -74,13 +74,7 @@ ostream& operator<<(ostream& out, const formatBytes data)
         return out << data.m_bytes << 'B';
     }
 
-    static const auto units = {
-        "B",
-        "KB",
-        "MB",
-        "GB",
-        "TB"
-    };
+    static const auto units = {"B", "KB", "MB", "GB", "TB"};
     auto unit = units.begin();
     size_t i = 0;
     double bytes = data.m_bytes;
@@ -105,14 +99,15 @@ struct Printer final : public AccumulatedTraceData
         const auto trace = findTrace(allocation.traceIndex);
         const auto traceIp = findIp(trace.ipIndex);
         auto it = lower_bound(mergedAllocations->begin(), mergedAllocations->end(), traceIp,
-                                [this] (const MergedAllocation& allocation, const InstructionPointer traceIp) -> bool {
-                                    // Compare meta data without taking the instruction pointer address into account.
-                                    // This is useful since sometimes, esp. when we lack debug symbols, the same function
-                                    // allocates memory at different IP addresses which is pretty useless information most of the time
-                                    // TODO: make this configurable, but on-by-default
-                                    const auto allocationIp = findIp(allocation.ipIndex);
-                                    return allocationIp.compareWithoutAddress(traceIp);
-                                });
+                              [this](const MergedAllocation& allocation, const InstructionPointer traceIp) -> bool {
+                                  // Compare meta data without taking the instruction pointer address into account.
+                                  // This is useful since sometimes, esp. when we lack debug symbols, the same
+                                  // function allocates memory at different IP addresses which is pretty useless
+                                  // information most of the time
+                                  // TODO: make this configurable, but on-by-default
+                                  const auto allocationIp = findIp(allocation.ipIndex);
+                                  return allocationIp.compareWithoutAddress(traceIp);
+                              });
         if (it == mergedAllocations->end() || !findIp(it->ipIndex).equalWithoutAddress(traceIp)) {
             MergedAllocation merged;
             merged.ipIndex = trace.ipIndex;
@@ -137,7 +132,7 @@ struct Printer final : public AccumulatedTraceData
             }
         }
         for (MergedAllocation& merged : ret) {
-            for (const Allocation& allocation: merged.traces) {
+            for (const Allocation& allocation : merged.traces) {
                 merged.allocated += allocation.allocated;
                 merged.allocations += allocation.allocations;
                 merged.leaked += allocation.leaked;
@@ -153,20 +148,22 @@ struct Printer final : public AccumulatedTraceData
         if (filterBtFunction.empty()) {
             return;
         }
-        allocations.erase(remove_if(allocations.begin(), allocations.end(), [&] (const Allocation& allocation) -> bool {
-            auto node = findTrace(allocation.traceIndex);
-            while (node.ipIndex) {
-                const auto& ip = findIp(node.ipIndex);
-                if (isStopIndex(ip.functionIndex)) {
-                    break;
-                }
-                if (stringify(ip.functionIndex).find(filterBtFunction) != string::npos) {
-                    return false;
-                }
-                node = findTrace(node.parentIndex);
-            };
-            return true;
-        }), allocations.end());
+        allocations.erase(remove_if(allocations.begin(), allocations.end(),
+                                    [&](const Allocation& allocation) -> bool {
+                                        auto node = findTrace(allocation.traceIndex);
+                                        while (node.ipIndex) {
+                                            const auto& ip = findIp(node.ipIndex);
+                                            if (isStopIndex(ip.functionIndex)) {
+                                                break;
+                                            }
+                                            if (stringify(ip.functionIndex).find(filterBtFunction) != string::npos) {
+                                                return false;
+                                            }
+                                            node = findTrace(node.parentIndex);
+                                        };
+                                        return true;
+                                    }),
+                          allocations.end());
     }
 
     void printIndent(ostream& out, size_t indent, const char* indentString = "  ") const
@@ -176,7 +173,7 @@ struct Printer final : public AccumulatedTraceData
         }
     }
 
-    void printIp(const IpIndex ip, ostream &out, const size_t indent = 0) const
+    void printIp(const IpIndex ip, ostreamout, const size_t indent = 0) const
     {
         printIp(findIp(ip), out, indent);
     }
@@ -218,7 +215,8 @@ struct Printer final : public AccumulatedTraceData
         out << '\n';
     }
 
-    void printBacktrace(const TraceIndex traceIndex, ostream& out, const size_t indent = 0, bool skipFirst = false) const
+    void printBacktrace(const TraceIndex traceIndex, ostream& out, const size_t indent = 0,
+                        bool skipFirst = false) const
     {
         if (!traceIndex) {
             out << "  ??";
@@ -263,8 +261,8 @@ struct Printer final : public AccumulatedTraceData
         printIp(ip, out, 0, true);
     }
 
-    template<typename T, typename LabelPrinter, typename SubLabelPrinter>
-    void printAllocations(T AllocationData::* member, LabelPrinter label, SubLabelPrinter sublabel)
+    template <typename T, typename LabelPrinter, typename SubLabelPrinter>
+    void printAllocations(T AllocationData::*member, LabelPrinter label, SubLabelPrinter sublabel)
     {
         if (mergeBacktraces) {
             printMerged(member, label, sublabel);
@@ -273,10 +271,10 @@ struct Printer final : public AccumulatedTraceData
         }
     }
 
-    template<typename T, typename LabelPrinter, typename SubLabelPrinter>
-    void printMerged(T AllocationData::* member, LabelPrinter label, SubLabelPrinter sublabel)
+    template <typename T, typename LabelPrinter, typename SubLabelPrinter>
+    void printMerged(T AllocationData::*member, LabelPrinter label, SubLabelPrinter sublabel)
     {
-        auto sortOrder = [member] (const AllocationData& l, const AllocationData& r) {
+        auto sortOrder = [member](const AllocationData& l, const AllocationData& r) {
             return std::abs(l.*member) > std::abs(r.*member);
         };
         sort(mergedAllocations.begin(), mergedAllocations.end(), sortOrder);
@@ -309,13 +307,11 @@ struct Printer final : public AccumulatedTraceData
         }
     }
 
-    template<typename T, typename LabelPrinter>
-    void printUnmerged(T AllocationData::* member, LabelPrinter label)
+    template <typename T, typename LabelPrinter>
+    void printUnmerged(T AllocationData::*member, LabelPrinter label)
     {
         sort(allocations.begin(), allocations.end(),
-            [member] (const Allocation& l, const Allocation &r) {
-                return std::abs(l.*member) > std::abs(r.*member);
-            });
+             [member](const Allocation& l, const Allocation& r) { return std::abs(l.*member) > std::abs(r.*member); });
         for (size_t i = 0; i < min(peakLimit, allocations.size()); ++i) {
             const auto& allocation = allocations[i];
             if (!(allocation.*member)) {
@@ -342,14 +338,13 @@ struct Printer final : public AccumulatedTraceData
             lastMassifPeak = totalCost.leaked;
             massifAllocations = allocations;
         }
-        massifOut
-            << "#-----------\n"
-            << "snapshot=" << massifSnapshotId << '\n'
-            << "#-----------\n"
-            << "time=" << (0.001 * timeStamp) << '\n'
-            << "mem_heap_B=" << lastMassifPeak << '\n'
-            << "mem_heap_extra_B=0\n"
-            << "mem_stacks_B=0\n";
+        massifOut << "#-----------\n"
+                  << "snapshot=" << massifSnapshotId << '\n'
+                  << "#-----------\n"
+                  << "time=" << (0.001 * timeStamp) << '\n'
+                  << "mem_heap_B=" << lastMassifPeak << '\n'
+                  << "mem_heap_extra_B=0\n"
+                  << "mem_stacks_B=0\n";
 
         if (massifDetailedFreq && (isLast || !(massifSnapshotId % massifDetailedFreq))) {
             massifOut << "heap_tree=detailed\n";
@@ -370,9 +365,8 @@ struct Printer final : public AccumulatedTraceData
         size_t numAllocs = 0;
         size_t skipped = 0;
         auto mergedAllocations = mergeAllocations(allocations);
-        sort(mergedAllocations.begin(), mergedAllocations.end(), [] (const MergedAllocation& l, const MergedAllocation& r) {
-            return l.leaked > r.leaked;
-        });
+        sort(mergedAllocations.begin(), mergedAllocations.end(),
+             [](const MergedAllocation& l, const MergedAllocation& r) { return l.leaked > r.leaked; });
 
         const auto ip = findIp(location);
 
@@ -381,14 +375,16 @@ struct Printer final : public AccumulatedTraceData
         if (!shouldStop) {
             for (auto& merged : mergedAllocations) {
                 if (merged.leaked < 0) {
-                    // list is sorted, so we can bail out now - these entries are uninteresting for massif
+                    // list is sorted, so we can bail out now - these entries are
+                    // uninteresting for massif
                     break;
                 }
 
                 // skip items below threshold
                 if (static_cast<size_t>(merged.leaked) >= threshold) {
                     ++numAllocs;
-                    // skip the first level of the backtrace, otherwise we'd endlessly recurse
+                    // skip the first level of the backtrace, otherwise we'd endlessly
+                    // recurse
                     for (auto& alloc : merged.traces) {
                         alloc.traceIndex = findTrace(alloc.traceIndex).parentIndex;
                     }
@@ -402,10 +398,10 @@ struct Printer final : public AccumulatedTraceData
         printIndent(massifOut, depth, " ");
         massifOut << 'n' << (numAllocs + (skipped ? 1 : 0)) << ": " << heapSize;
         if (!depth) {
-            massifOut << " (heap allocation functions) malloc/new/new[], --alloc-fns, etc.\n";
+            massifOut << " (heap allocation functions) malloc/new/new[], "
+                         "--alloc-fns, etc.\n";
         } else {
-            massifOut << " 0x" << hex << ip.instructionPointer << dec
-                      << ": ";
+            massifOut << " 0x" << hex << ip.instructionPointer << dec << ": ";
             if (ip.functionIndex) {
                 massifOut << stringify(ip.functionIndex);
             } else {
@@ -426,8 +422,8 @@ struct Printer final : public AccumulatedTraceData
         auto writeSkipped = [&] {
             if (skipped) {
                 printIndent(massifOut, depth, " ");
-                massifOut << " n0: " << skippedLeaked << " in " << skipped
-                        << " places, all below massif's threshold (" << massifThreshold << ")\n";
+                massifOut << " n0: " << skippedLeaked << " in " << skipped << " places, all below massif's threshold ("
+                          << massifThreshold << ")\n";
                 skipped = 0;
             }
         };
@@ -496,67 +492,67 @@ struct Printer final : public AccumulatedTraceData
 int main(int argc, char** argv)
 {
     po::options_description desc("Options", 120, 60);
-    desc.add_options()
-        ("file,f", po::value<string>(),
-            "The heaptrack data file to print.")
-        ("diff,d", po::value<string>()->default_value({}),
-            "Find the differences to this file.")
-        ("shorten-templates,t", po::value<bool>()->default_value(true)->implicit_value(true),
-            "Shorten template identifiers.")
-        ("merge-backtraces,m", po::value<bool>()->default_value(true)->implicit_value(true),
-            "Merge backtraces.\nNOTE: the merged peak consumption is not correct.")
-        ("print-peaks,p", po::value<bool>()->default_value(true)->implicit_value(true),
-            "Print backtraces to top allocators, sorted by peak consumption.")
-        ("print-allocators,a", po::value<bool>()->default_value(true)->implicit_value(true),
-            "Print backtraces to top allocators, sorted by number of calls to allocation functions.")
-        ("print-temporary,T", po::value<bool>()->default_value(true)->implicit_value(true),
-            "Print backtraces to top allocators, sorted by number of temporary allocations.")
-        ("print-leaks,l", po::value<bool>()->default_value(false)->implicit_value(true),
-            "Print backtraces to leaked memory allocations.")
-        ("print-overall-allocated,o", po::value<bool>()->default_value(false)->implicit_value(true),
-            "Print top overall allocators, ignoring memory frees.")
-         ("peak-limit,n", po::value<size_t>()->default_value(10)->implicit_value(10),
-            "Limit the number of reported peaks.")
-         ("sub-peak-limit,s", po::value<size_t>()->default_value(5)->implicit_value(5),
-            "Limit the number of reported backtraces of merged peak locations.")
-        ("print-histogram,H", po::value<string>()->default_value(string()),
-            "Path to output file where an allocation size histogram will be written to.")
-        ("print-flamegraph,F", po::value<string>()->default_value(string()),
-            "Path to output file where a flame-graph compatible stack file will be written to.\n"
-            "To visualize the resulting file, use flamegraph.pl from https://github.com/brendangregg/FlameGraph:\n"
-            "  heaptrack_print heaptrack.someapp.PID.gz -F stacks.txt\n"
-            "  # optionally pass --reverse to flamegraph.pl\n"
-            "  flamegraph.pl --title \"heaptrack: allocations\" --colors mem \\\n"
-            "    --countname allocations < stacks.txt > heaptrack.someapp.PID.svg\n"
-            "  [firefox|chromium] heaptrack.someapp.PID.svg\n")
-        ("print-massif,M", po::value<string>()->default_value(string()),
-            "Path to output file where a massif compatible data file will be written to.")
-        ("massif-threshold", po::value<double>()->default_value(1.),
-            "Percentage of current memory usage, below which allocations are aggregated into a 'below threshold' entry.\n"
-            "This is only used in the massif output file so far.\n")
-        ("massif-detailed-freq", po::value<size_t>()->default_value(2),
-            "Frequency of detailed snapshots in the massif output file. Increase this to reduce the file size.\n"
-            "You can set the value to zero to disable detailed snapshots.\n")
-        ("filter-bt-function", po::value<string>()->default_value(string()),
-            "Only print allocations where the backtrace contains the given function.")
-        ("help,h",
-            "Show this help message.")
-        ("version,v",
-            "Displays version information.");
+    desc.add_options()("file,f", po::value<string>(), "The heaptrack data file to print.")(
+        "diff,d", po::value<string>()->default_value({}), "Find the differences to this file.")(
+        "shorten-templates,t", po::value<bool>()->default_value(true)->implicit_value(true),
+        "Shorten template identifiers.")("merge-backtraces,m",
+                                         po::value<bool>()->default_value(true)->implicit_value(true),
+                                         "Merge backtraces.\nNOTE: the merged peak consumption is not correct.")(
+        "print-peaks,p", po::value<bool>()->default_value(true)->implicit_value(true),
+        "Print backtraces to top allocators, sorted by peak consumption.")(
+        "print-allocators,a", po::value<bool>()->default_value(true)->implicit_value(true),
+        "Print backtraces to top allocators, sorted by number of calls to "
+        "allocation functions.")("print-temporary,T", po::value<bool>()->default_value(true)->implicit_value(true),
+                                 "Print backtraces to top allocators, sorted by number of temporary "
+                                 "allocations.")("print-leaks,l",
+                                                 po::value<bool>()->default_value(false)->implicit_value(true),
+                                                 "Print backtraces to leaked memory allocations.")(
+        "print-overall-allocated,o", po::value<bool>()->default_value(false)->implicit_value(true),
+        "Print top overall allocators, ignoring memory frees.")(
+        "peak-limit,n", po::value<size_t>()->default_value(10)->implicit_value(10),
+        "Limit the number of reported peaks.")("sub-peak-limit,s",
+                                               po::value<size_t>()->default_value(5)->implicit_value(5),
+                                               "Limit the number of reported backtraces of merged peak locations.")(
+        "print-histogram,H", po::value<string>()->default_value(string()),
+        "Path to output file where an allocation size histogram will be written "
+        "to.")("print-flamegraph,F", po::value<string>()->default_value(string()),
+               "Path to output file where a flame-graph compatible stack file will be "
+               "written to.\n"
+               "To visualize the resulting file, use flamegraph.pl from "
+               "https://github.com/brendangregg/FlameGraph:\n"
+               "  heaptrack_print heaptrack.someapp.PID.gz -F stacks.txt\n"
+               "  # optionally pass --reverse to flamegraph.pl\n"
+               "  flamegraph.pl --title \"heaptrack: allocations\" --colors mem \\\n"
+               "    --countname allocations < stacks.txt > heaptrack.someapp.PID.svg\n"
+               "  [firefox|chromium] heaptrack.someapp.PID.svg\n")(
+        "print-massif,M", po::value<string>()->default_value(string()),
+        "Path to output file where a massif compatible data file will be written "
+        "to.")("massif-threshold", po::value<double>()->default_value(1.),
+               "Percentage of current memory usage, below which allocations are "
+               "aggregated into a 'below threshold' entry.\n"
+               "This is only used in the massif output file so far.\n")(
+        "massif-detailed-freq", po::value<size_t>()->default_value(2),
+        "Frequency of detailed snapshots in the massif output file. Increase "
+        "this to reduce the file size.\n"
+        "You can set the value to zero to disable detailed snapshots.\n")(
+        "filter-bt-function", po::value<string>()->default_value(string()),
+        "Only print allocations where the backtrace contains the given "
+        "function.")("help,h", "Show this help message.")("version,v", "Displays version information.");
     po::positional_options_description p;
     p.add("file", -1);
 
     po::variables_map vm;
     try {
-        po::store(po::command_line_parser(argc, argv)
-                    .options(desc).positional(p).run(), vm);
+        po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
         if (vm.count("help")) {
             cout << "heaptrack_print - analyze heaptrack data files.\n"
-                << "\n"
-                << "heaptrack is a heap memory profiler which records information\n"
-                << "about calls to heap allocation functions such as malloc, operator new etc. pp.\n"
-                << "This print utility can then be used to analyze the generated data files.\n\n"
-                << desc << endl;
+                 << "\n"
+                 << "heaptrack is a heap memory profiler which records information\n"
+                 << "about calls to heap allocation functions such as malloc, "
+                    "operator new etc. pp.\n"
+                 << "This print utility can then be used to analyze the generated "
+                    "data files.\n\n"
+                 << desc << endl;
             return 0;
         } else if (vm.count("version")) {
             cout << "heaptrack_print " << HEAPTRACK_VERSION_STRING << endl;
@@ -564,8 +560,7 @@ int main(int argc, char** argv)
         }
         po::notify(vm);
     } catch (const po::error& error) {
-        cerr << "ERROR: " << error.what() << endl
-             << endl << desc << endl;
+        cerr << "ERROR: " << error.what() << endl << endl << desc << endl;
         return 1;
     }
 
@@ -592,7 +587,7 @@ int main(int argc, char** argv)
     const string printMassif = vm["print-massif"].as<string>();
     if (!printMassif.empty()) {
         data.massifOut.open(printMassif, ios_base::out);
-        if (!data.massifOut.is_open())  {
+        if (!data.massifOut.is_open()) {
             cerr << "Failed to open massif output file \"" << printMassif << "\"." << endl;
             return 1;
         }
@@ -610,9 +605,7 @@ int main(int argc, char** argv)
     if (!diffFile.empty()) {
         cout << "reading diff file \"" << diffFile << "\" - please wait, this might take some time..." << endl;
         Printer diffData;
-        auto diffRead = async(launch::async, [&diffData, diffFile] () {
-            return diffData.read(diffFile);
-        });
+        auto diffRead = async(launch::async, [&diffData, diffFile]() { return diffData.read(diffFile); });
 
         if (!data.read(inputFile) || !diffRead.get()) {
             return 1;
@@ -630,26 +623,34 @@ int main(int argc, char** argv)
     if (printAllocs) {
         // sort by amount of allocations
         cout << "MOST CALLS TO ALLOCATION FUNCTIONS\n";
-        data.printAllocations(&AllocationData::allocations, [] (const AllocationData& data) {
-            cout << data.allocations << " calls to allocation functions with " << formatBytes(data.peak) << " peak consumption from\n";
-        }, [] (const AllocationData& data) {
-            cout << data.allocations << " calls with " << formatBytes(data.peak) << " peak consumption from:\n";
-        });
+        data.printAllocations(&AllocationData::allocations,
+                              [](const AllocationData& data) {
+                                  cout << data.allocations << " calls to allocation functions with "
+                                       << formatBytes(data.peak) << " peak consumption from\n";
+                              },
+                              [](const AllocationData& data) {
+                                  cout << data.allocations << " calls with " << formatBytes(data.peak)
+                                       << " peak consumption from:\n";
+                              });
         cout << endl;
     }
 
     if (printOverallAlloc) {
         cout << "MOST BYTES ALLOCATED OVER TIME (ignoring deallocations)\n";
-        data.printAllocations(&AllocationData::allocated, [] (const AllocationData& data) {
-            cout << formatBytes(data.allocated) << " allocated over " << data.allocations << " calls from\n";
-        }, [] (const AllocationData& data) {
-            cout << formatBytes(data.allocated) << " allocated over " << data.allocations << " calls from:\n";
-        });
+        data.printAllocations(&AllocationData::allocated,
+                              [](const AllocationData& data) {
+                                  cout << formatBytes(data.allocated) << " allocated over " << data.allocations
+                                       << " calls from\n";
+                              },
+                              [](const AllocationData& data) {
+                                  cout << formatBytes(data.allocated) << " allocated over " << data.allocations
+                                       << " calls from:\n";
+                              });
         cout << endl;
     }
 
     if (printPeaks) {
-        ///FIXME: find a way to merge this without breaking temporal dependency.
+        /// FIXME: find a way to merge this without breaking temporal dependency.
         /// I.e. a given function could be called N times from different places
         /// and allocate M bytes each, but free it thereafter.
         /// Then the below would give a wrong total peak size of N * M instead
@@ -661,45 +662,57 @@ int main(int argc, char** argv)
                     " For an accurate overview, disable backtrace merging.\n";
         }
 
-        data.printAllocations(&AllocationData::peak, [] (const AllocationData& data) {
-            cout << formatBytes(data.peak) << " peak memory consumed over " << data.allocations << " calls from\n";
-        }, [] (const AllocationData& data) {
-            cout << formatBytes(data.peak) << " consumed over " << data.allocations << " calls from:\n";
-        });
+        data.printAllocations(&AllocationData::peak,
+                              [](const AllocationData& data) {
+                                  cout << formatBytes(data.peak) << " peak memory consumed over " << data.allocations
+                                       << " calls from\n";
+                              },
+                              [](const AllocationData& data) {
+                                  cout << formatBytes(data.peak) << " consumed over " << data.allocations
+                                       << " calls from:\n";
+                              });
     }
 
     if (printLeaks) {
         // sort by amount of leaks
         cout << "MEMORY LEAKS\n";
-        data.printAllocations(&AllocationData::leaked, [] (const AllocationData& data) {
-            cout << formatBytes(data.leaked) << " leaked over " << data.allocations << " calls from\n";
-        }, [] (const AllocationData& data) {
-            cout << formatBytes(data.leaked) << " leaked over " << data.allocations << " calls from:\n";
-        });
+        data.printAllocations(&AllocationData::leaked,
+                              [](const AllocationData& data) {
+                                  cout << formatBytes(data.leaked) << " leaked over " << data.allocations
+                                       << " calls from\n";
+                              },
+                              [](const AllocationData& data) {
+                                  cout << formatBytes(data.leaked) << " leaked over " << data.allocations
+                                       << " calls from:\n";
+                              });
         cout << endl;
     }
 
     if (printTemporary) {
         // sort by amount of temporary allocations
         cout << "MOST TEMPORARY ALLOCATIONS\n";
-        data.printAllocations(&AllocationData::temporary, [] (const AllocationData& data) {
-            cout << data.temporary << " temporary allocations of " << data.allocations << " allocations in total ("
-                 << setprecision(2) << (float(data.temporary)  * 100.f / data.allocations) << "%) from\n";
-        }, [] (const AllocationData& data) {
-            cout << data.temporary << " temporary allocations of " << data.allocations << " allocations in total ("
-                 << setprecision(2) << (float(data.temporary)  * 100.f / data.allocations) << "%) from:\n";
-        });
+        data.printAllocations(&AllocationData::temporary,
+                              [](const AllocationData& data) {
+                                  cout << data.temporary << " temporary allocations of " << data.allocations
+                                       << " allocations in total (" << setprecision(2)
+                                       << (float(data.temporary) * 100.f / data.allocations) << "%) from\n";
+                              },
+                              [](const AllocationData& data) {
+                                  cout << data.temporary << " temporary allocations of " << data.allocations
+                                       << " allocations in total (" << setprecision(2)
+                                       << (float(data.temporary) * 100.f / data.allocations) << "%) from:\n";
+                              });
         cout << endl;
     }
 
     const double totalTimeS = 0.001 * data.totalTime;
     cout << "total runtime: " << fixed << totalTimeS << "s.\n"
-         << "bytes allocated in total (ignoring deallocations): " << formatBytes(data.totalCost.allocated)
-            << " (" << formatBytes(data.totalCost.allocated / totalTimeS) << "/s)" << '\n'
-         << "calls to allocation functions: " << data.totalCost.allocations
-            << " (" << int64_t(data.totalCost.allocations / totalTimeS) << "/s)\n"
-         << "temporary memory allocations: " << data.totalCost.temporary
-            << " (" << int64_t(data.totalCost.temporary / totalTimeS) << "/s)\n"
+         << "bytes allocated in total (ignoring deallocations): " << formatBytes(data.totalCost.allocated) << " ("
+         << formatBytes(data.totalCost.allocated / totalTimeS) << "/s)" << '\n'
+         << "calls to allocation functions: " << data.totalCost.allocations << " ("
+         << int64_t(data.totalCost.allocations / totalTimeS) << "/s)\n"
+         << "temporary memory allocations: " << data.totalCost.temporary << " ("
+         << int64_t(data.totalCost.temporary / totalTimeS) << "/s)\n"
          << "peak heap memory consumption: " << formatBytes(data.totalCost.peak) << '\n'
          << "peak RSS (including heaptrack overhead): " << formatBytes(data.peakRSS * data.systemInfo.pageSize) << '\n'
          << "total memory leaked: " << formatBytes(data.totalCost.leaked) << '\n';
index 587ead7..33e4c33 100644 (file)
  * @brief Interpret raw heaptrack data and add Dwarf based debug information.
  */
 
+#include <algorithm>
+#include <cinttypes>
 #include <iostream>
 #include <sstream>
+#include <stdio_ext.h>
+#include <tuple>
 #include <unordered_map>
 #include <vector>
-#include <tuple>
-#include <algorithm>
-#include <stdio_ext.h>
-#include <cinttypes>
 
 #include <cxxabi.h>
 
@@ -88,23 +88,27 @@ struct Module
         }
 
         backtrace_pcinfo(backtraceState, address,
-                         [] (void *data, uintptr_t /*addr*/, const char *file, int line, const char *function) -> int {
-                            auto info = reinterpret_cast<AddressInformation*>(data);
-                            info->function = demangle(function);
-                            info->file = file ? file : "";
-                            info->line = line;
-                            return 0;
-                         }, [] (void */*data*/, const char */*msg*/, int /*errnum*/) {}, &info);
+                         [](void* data, uintptr_t /*addr*/, const char* file, int line, const char* function) -> int {
+                             auto info = reinterpret_cast<AddressInformation*>(data);
+                             info->function = demangle(function);
+                             info->file = file ? file : "";
+                             info->line = line;
+                             return 0;
+                         },
+                         [](void* /*data*/, const char* /*msg*/, int /*errnum*/) {}, &info);
 
         if (info.function.empty()) {
-            backtrace_syminfo(backtraceState, address,
-                              [] (void *data, uintptr_t /*pc*/, const char *symname, uintptr_t /*symval*/, uintptr_t /*symsize*/) {
-                                if (symname) {
-                                    reinterpret_cast<AddressInformation*>(data)->function = demangle(symname);
-                                }
-                              }, [] (void */*data*/, const char *msg, int errnum) {
-                                cerr << "Module backtrace error (code " << errnum << "): " << msg << endl;
-                              }, &info);
+            backtrace_syminfo(
+                backtraceState, address,
+                [](void* data, uintptr_t /*pc*/, const char* symname, uintptr_t /*symval*/, uintptr_t /*symsize*/) {
+                    if (symname) {
+                        reinterpret_cast<AddressInformation*>(data)->function = demangle(symname);
+                    }
+                },
+                [](void* /*data*/, const char* msg, int errnum) {
+                    cerr << "Module backtrace error (code " << errnum << "): " << msg << endl;
+                },
+                &info);
         }
 
         return info;
@@ -113,7 +117,7 @@ struct Module
     bool operator<(const Module& module) const
     {
         return tie(addressStart, addressEnd, moduleIndex)
-             < tie(module.addressStart, module.addressEnd, module.moduleIndex);
+            < tie(module.addressStart, module.addressEnd, module.moduleIndex);
     }
 
     bool operator!=(const Module& module) const
@@ -148,8 +152,7 @@ struct AccumulatedTraceData
 
     ~AccumulatedTraceData()
     {
-        fprintf(stdout, "# strings: %zu\n# ips: %zu\n",
-                m_internedData.size(), m_encounteredIps.size());
+        fprintf(stdout, "# strings: %zu\n# ips: %zu\n", m_internedData.size(), m_encounteredIps.size());
     }
 
     ResolvedIP resolve(const uintptr_t ip)
@@ -166,12 +169,11 @@ struct AccumulatedTraceData
                         continue;
                     }
                     const auto& m2 = m_modules[j];
-                    if ((m1.addressStart <= m2.addressStart && m1.addressEnd > m2.addressStart) ||
-                        (m1.addressStart < m2.addressEnd && m1.addressEnd >= m2.addressEnd))
-                    {
-                        cerr << "OVERLAPPING MODULES: " << hex
-                             << m1.moduleIndex << " (" << m1.addressStart << " to " << m1.addressEnd << ") and "
-                             << m1.moduleIndex << " (" << m2.addressStart << " to " << m2.addressEnd << ")\n"
+                    if ((m1.addressStart <= m2.addressStart && m1.addressEnd > m2.addressStart)
+                        || (m1.addressStart < m2.addressEnd && m1.addressEnd >= m2.addressEnd)) {
+                        cerr << "OVERLAPPING MODULES: " << hex << m1.moduleIndex << " (" << m1.addressStart << " to "
+                             << m1.addressEnd << ") and " << m1.moduleIndex << " (" << m2.addressStart << " to "
+                             << m2.addressEnd << ")\n"
                              << dec;
                     } else if (m2.addressStart >= m1.addressEnd) {
                         break;
@@ -185,10 +187,9 @@ struct AccumulatedTraceData
 
         ResolvedIP data;
         // find module for this instruction pointer
-        auto module = lower_bound(m_modules.begin(), m_modules.end(), ip,
-                                    [] (const Module& module, const uintptr_t ip) -> bool {
-                                        return module.addressEnd < ip;
-                                    });
+        auto module =
+            lower_bound(m_modules.begin(), m_modules.end(), ip,
+                        [](const Module& module, const uintptr_t ip) -> bool { return module.addressEnd < ip; });
         if (module != m_modules.end() && module->addressStart <= ip && module->addressEnd >= ip) {
             data.moduleIndex = module->moduleIndex;
             const auto info = module->resolveAddress(ip);
@@ -221,8 +222,8 @@ struct AccumulatedTraceData
         return id;
     }
 
-    void addModule(backtrace_state* backtraceState, const size_t moduleIndex,
-                   const uintptr_t addressStart, const uintptr_t addressEnd)
+    void addModule(backtrace_state* backtraceState, const size_t moduleIndex, const uintptr_t addressStart,
+                   const uintptr_t addressEnd)
     {
         m_modules.emplace_back(addressStart, addressEnd, backtraceState, moduleIndex);
         m_modulesDirty = true;
@@ -277,15 +278,16 @@ struct AccumulatedTraceData
             return it->second;
         }
 
-        struct CallbackData {
+        struct CallbackData
+        {
             const char* fileName;
         };
         CallbackData data = {fileName};
 
-        auto errorHandler = [] (void *rawData, const char *msg, int errnum) {
+        auto errorHandler = [](void* rawData, const char* msg, int errnum) {
             auto data = reinterpret_cast<const CallbackData*>(rawData);
-            cerr << "Failed to create backtrace state for module " << data->fileName << ": "
-                 << msg << " / " << strerror(errnum) << " (error code " << errnum << ")" << endl;
+            cerr << "Failed to create backtrace state for module " << data->fileName << ": " << msg << " / "
+                 << strerror(errnum) << " (error code " << errnum << ")" << endl;
         };
 
         auto state = backtrace_create_state(fileName, /* we are single threaded, so: not thread safe */ false,
@@ -296,8 +298,8 @@ struct AccumulatedTraceData
             if (descriptor >= 1) {
                 int foundSym = 0;
                 int foundDwarf = 0;
-                auto ret = elf_add(state, descriptor, addressStart, errorHandler, &data,
-                                   &state->fileline_fn, &foundSym, &foundDwarf, false);
+                auto ret = elf_add(state, descriptor, addressStart, errorHandler, &data, &state->fileline_fn, &foundSym,
+                                   &foundDwarf, false);
                 if (ret && foundSym) {
                     state->syminfo_fn = &elf_syminfo;
                 }
@@ -317,7 +319,6 @@ private:
     unordered_map<string, size_t> m_internedData;
     unordered_map<uintptr_t, size_t> m_encounteredIps;
 };
-
 }
 
 int main(int /*argc*/, char** /*argv*/)
@@ -353,7 +354,7 @@ int main(int /*argc*/, char** /*argv*/)
                 if (fileName == "x") {
                     fileName = exe;
                 }
-                const char *internedString = nullptr;
+                const charinternedString = nullptr;
                 const auto moduleIndex = data.intern(fileName, &internedString);
                 uintptr_t addressStart = 0;
                 if (!(reader >> addressStart)) {
@@ -364,9 +365,7 @@ int main(int /*argc*/, char** /*argv*/)
                 uintptr_t vAddr = 0;
                 uintptr_t memSize = 0;
                 while ((reader >> vAddr) && (reader >> memSize)) {
-                    data.addModule(state, moduleIndex,
-                                   addressStart + vAddr,
-                                   addressStart + vAddr + memSize);
+                    data.addModule(state, moduleIndex, addressStart + vAddr, addressStart + vAddr + memSize);
                 }
             }
         } else if (reader.mode() == 't') {
@@ -422,10 +421,10 @@ int main(int /*argc*/, char** /*argv*/)
     }
 
     fprintf(stderr, "heaptrack stats:\n"
-           "\tallocations:          \t%" PRIu64 "\n"
-           "\tleaked allocations:   \t%" PRIu64 "\n"
-           "\ttemporary allocations:\t%" PRIu64 "\n",
-           allocations, leakedAllocations, temporaryAllocations);
+                    "\tallocations:          \t%" PRIu64 "\n"
+                    "\tleaked allocations:   \t%" PRIu64 "\n"
+                    "\ttemporary allocations:\t%" PRIu64 "\n",
+            allocations, leakedAllocations, temporaryAllocations);
 
     return 0;
 }
index 3eb0406..e1ea839 100644 (file)
@@ -66,11 +66,17 @@ __attribute__((weak)) void heaptrack_free(void* ptr);
 }
 #endif
 
-#define heaptrack_report_alloc(ptr, size) if (heaptrack_malloc) heaptrack_malloc(ptr, size)
+#define heaptrack_report_alloc(ptr, size)                                                                              \
+    if (heaptrack_malloc)                                                                                              \
+    heaptrack_malloc(ptr, size)
 
-#define heaptrack_report_realloc(ptr_in, size, ptr_out) if (heaptrack_realloc) heaptrack_realloc(ptr_in, size, ptr_out)
+#define heaptrack_report_realloc(ptr_in, size, ptr_out)                                                                \
+    if (heaptrack_realloc)                                                                                             \
+    heaptrack_realloc(ptr_in, size, ptr_out)
 
-#define heaptrack_report_free(ptr) if (heaptrack_free) heaptrack_free(ptr)
+#define heaptrack_report_free(ptr)                                                                                     \
+    if (heaptrack_free)                                                                                                \
+    heaptrack_free(ptr)
 
 #else // HEAPTRACK_API_DLSYM
 
@@ -95,9 +101,9 @@ __attribute__((weak)) void heaptrack_free(void* ptr);
 
 struct heaptrack_api_t
 {
-    void (*malloc) (void *, size_t);
-    void (*free) (void *);
-    void (*realloc) (void *, size_t, void *);
+    void (*malloc)(void*, size_t);
+    void (*free)(void*);
+    void (*realloc)(void*, size_t, void*);
 };
 static struct heaptrack_api_t heaptrack_api = {0, 0, 0};
 
@@ -107,37 +113,40 @@ void heaptrack_init_api()
     if (!initialized) {
         void* sym = dlsym(RTLD_NEXT, "heaptrack_malloc");
         if (sym)
-            heaptrack_api.malloc = (void (*) (void *, size_t)) sym;
+            heaptrack_api.malloc = (void (*)(void*, size_t))sym;
 
         sym = dlsym(RTLD_NEXT, "heaptrack_realloc");
         if (sym)
-            heaptrack_api.realloc = (void (*) (void *, size_t, void *)) sym;
+            heaptrack_api.realloc = (void (*)(void*, size_t, void*))sym;
 
         sym = dlsym(RTLD_NEXT, "heaptrack_free");
         if (sym)
-            heaptrack_api.free = (void (*) (void *)) sym;
+            heaptrack_api.free = (void (*)(void*))sym;
 
         initialized = 1;
     }
 }
 
-#define heaptrack_report_alloc(ptr, size) \
-    do { \
-        heaptrack_init_api(); \
-        if (heaptrack_api.malloc) heaptrack_api.malloc(ptr, size); \
-    } while(0)
-
-#define heaptrack_report_realloc(ptr_in, size, ptr_out) \
-    do { \
-        heaptrack_init_api(); \
-        if (heaptrack_api.realloc) heaptrack_api.realloc(ptr_in, size, ptr_out); \
-    } while(0)
-
-#define heaptrack_report_free(ptr) \
-    do { \
-        heaptrack_init_api(); \
-        if (heaptrack_api.free) heaptrack_api.free(ptr); \
-    } while(0)
+#define heaptrack_report_alloc(ptr, size)                                                                              \
+    do {                                                                                                               \
+        heaptrack_init_api();                                                                                          \
+        if (heaptrack_api.malloc)                                                                                      \
+            heaptrack_api.malloc(ptr, size);                                                                           \
+    } while (0)
+
+#define heaptrack_report_realloc(ptr_in, size, ptr_out)                                                                \
+    do {                                                                                                               \
+        heaptrack_init_api();                                                                                          \
+        if (heaptrack_api.realloc)                                                                                     \
+            heaptrack_api.realloc(ptr_in, size, ptr_out);                                                              \
+    } while (0)
+
+#define heaptrack_report_free(ptr)                                                                                     \
+    do {                                                                                                               \
+        heaptrack_init_api();                                                                                          \
+        if (heaptrack_api.free)                                                                                        \
+            heaptrack_api.free(ptr);                                                                                   \
+    } while (0)
 
 #endif // HEAPTRACK_API_DLSYM
 
index 2ff8e23..e32a5af 100644 (file)
 
 #include "libheaptrack.h"
 
-#include <link.h>
-#include <cstring>
 #include <cstdlib>
-#include <sys/mman.h>
+#include <cstring>
+
+#include <link.h>
 #include <malloc.h>
 
+#include <sys/mman.h>
+
 #include <type_traits>
 
 /**
@@ -68,7 +70,7 @@ struct free
     static constexpr auto name = "free";
     static constexpr auto original = &::free;
 
-    static void hook(void *ptr) noexcept
+    static void hook(voidptr) noexcept
     {
         heaptrack_free(ptr);
         original(ptr);
@@ -80,7 +82,7 @@ struct realloc
     static constexpr auto name = "realloc";
     static constexpr auto original = &::realloc;
 
-    static void* hook(void *ptr, size_t size) noexcept
+    static void* hook(voidptr, size_t size) noexcept
     {
         auto ret = original(ptr, size);
         heaptrack_realloc(ptr, size, ret);
@@ -107,7 +109,7 @@ struct cfree
     static constexpr auto name = "cfree";
     static constexpr auto original = &::cfree;
 
-    static void hook(void *ptr) noexcept
+    static void hook(voidptr) noexcept
     {
         heaptrack_free(ptr);
         original(ptr);
@@ -120,7 +122,7 @@ struct dlopen
     static constexpr auto name = "dlopen";
     static constexpr auto original = &::dlopen;
 
-    static void* hook(const char *filename, int flag) noexcept
+    static void* hook(const charfilename, int flag) noexcept
     {
         auto ret = original(filename, flag);
         if (ret) {
@@ -136,7 +138,7 @@ struct dlclose
     static constexpr auto name = "dlclose";
     static constexpr auto original = &::dlclose;
 
-    static int hook(void *handle) noexcept
+    static int hook(voidhandle) noexcept
     {
         auto ret = original(handle);
         if (!ret) {
@@ -151,7 +153,7 @@ struct posix_memalign
     static constexpr auto name = "posix_memalign";
     static constexpr auto original = &::posix_memalign;
 
-    static int hook(void **memptr, size_t alignment, size_t size) noexcept
+    static int hook(void** memptr, size_t alignment, size_t size) noexcept
     {
         auto ret = original(memptr, alignment, size);
         if (!ret) {
@@ -161,8 +163,8 @@ struct posix_memalign
     }
 };
 
-template<typename Hook>
-bool hook(const char *symname, ElfW(Addr) addr, bool restore)
+template <typename Hook>
+bool hook(const charsymname, ElfW(Addr) addr, bool restore)
 {
     static_assert(std::is_convertible<decltype(&Hook::hook), decltype(Hook::original)>::value,
                   "hook is not compatible to original function");
@@ -173,7 +175,7 @@ bool hook(const char *symname, ElfW(Addr) addr, bool restore)
 
     // try to make the page read/write accessible, which is hackish
     // but apparently required for some shared libraries
-    auto page = reinterpret_cast<void *>(addr & ~(0x1000 - 1));
+    auto page = reinterpret_cast<void*>(addr & ~(0x1000 - 1));
     mprotect(page, 0x1000, PROT_READ | PROT_WRITE);
 
     // now write to the address
@@ -189,30 +191,26 @@ bool hook(const char *symname, ElfW(Addr) addr, bool restore)
     return true;
 }
 
-void apply(const char *symname, ElfW(Addr) addr, bool restore)
+void apply(const charsymname, ElfW(Addr) addr, bool restore)
 {
     // TODO: use std::apply once we can rely on C++17
-    hook<malloc>(symname, addr, restore)
-        || hook<free>(symname, addr, restore)
-        || hook<realloc>(symname, addr, restore)
+    hook<malloc>(symname, addr, restore) || hook<free>(symname, addr, restore) || hook<realloc>(symname, addr, restore)
         || hook<calloc>(symname, addr, restore)
 #if HAVE_CFREE
         || hook<cfree>(symname, addr, restore)
 #endif
-        || hook<posix_memalign>(symname, addr, restore)
-        || hook<dlopen>(symname, addr, restore)
+        || hook<posix_memalign>(symname, addr, restore) || hook<dlopen>(symname, addr, restore)
         || hook<dlclose>(symname, addr, restore);
 }
-
 }
 
-template<typename T, ElfW(Sxword) AddrTag, ElfW(Sxword) SizeTag>
+template <typename T, ElfW(Sxword) AddrTag, ElfW(Sxword) SizeTag>
 struct elftable
 {
     T* table = nullptr;
     ElfW(Xword) size = ElfW(Xword)();
 
-    bool consume(const ElfW(Dyn) *dyn) noexcept
+    bool consume(const ElfW(Dyn) * dyn) noexcept
     {
         if (dyn->d_tag == AddrTag) {
             table = reinterpret_cast<T*>(dyn->d_un.d_ptr);
@@ -229,7 +227,7 @@ using elf_string_table = elftable<const char, DT_STRTAB, DT_STRSZ>;
 using elf_jmprel_table = elftable<ElfW(Rela), DT_JMPREL, DT_PLTRELSZ>;
 using elf_symbol_table = elftable<ElfW(Sym), DT_SYMTAB, DT_SYMENT>;
 
-void try_overwrite_symbols(const ElfW(Dyn) *dyn, const ElfW(Addr) base, const bool restore) noexcept
+void try_overwrite_symbols(const ElfW(Dyn) * dyn, const ElfW(Addr) base, const bool restore) noexcept
 {
     elf_symbol_table symbols;
     elf_jmprel_table jmprels;
@@ -241,17 +239,17 @@ void try_overwrite_symbols(const ElfW(Dyn) *dyn, const ElfW(Addr) base, const bo
     }
 
     // find symbols to overwrite
-    const auto rela_end = reinterpret_cast<ElfW(Rela) *>(reinterpret_cast<char *>(jmprels.table) + jmprels.size);
+    const auto rela_end = reinterpret_cast<ElfW(Rela)*>(reinterpret_cast<char*>(jmprels.table) + jmprels.size);
     for (auto rela = jmprels.table; rela < rela_end; rela++) {
         const auto index = ELF_R_SYM(rela->r_info);
-        const char *symname = strings.table + symbols.table[index].st_name;
+        const charsymname = strings.table + symbols.table[index].st_name;
         auto addr = rela->r_offset + base;
 
         hooks::apply(symname, addr, restore);
     }
 }
 
-int iterate_phdrs(dl_phdr_info *info, size_t /*size*/, void *data) noexcept
+int iterate_phdrs(dl_phdr_info* info, size_t /*size*/, void* data) noexcept
 {
     if (strstr(info->dlpi_name, "/libheaptrack_inject.so")) {
         // prevent infinite recursion: do not overwrite our own symbols
@@ -263,8 +261,8 @@ int iterate_phdrs(dl_phdr_info *info, size_t /*size*/, void *data) noexcept
 
     for (auto phdr = info->dlpi_phdr, end = phdr + info->dlpi_phnum; phdr != end; ++phdr) {
         if (phdr->p_type == PT_DYNAMIC) {
-            try_overwrite_symbols(reinterpret_cast<const ElfW(Dyn) *>(phdr->p_vaddr + info->dlpi_addr),
-                                  info->dlpi_addr, data != nullptr);
+            try_overwrite_symbols(reinterpret_cast<const ElfW(Dyn)*>(phdr->p_vaddr + info->dlpi_addr), info->dlpi_addr,
+                                  data != nullptr);
         }
     }
     return 0;
@@ -274,21 +272,16 @@ void overwrite_symbols() noexcept
 {
     dl_iterate_phdr(&iterate_phdrs, nullptr);
 }
-
 }
 
 extern "C" {
 
-void heaptrack_inject(const char *outputFileName) noexcept
+void heaptrack_inject(const charoutputFileName) noexcept
 {
-    heaptrack_init(outputFileName, [] () {
-        overwrite_symbols();
-    }, [] (FILE* out) {
-        fprintf(out, "A\n");
-    }, [] () {
-        bool do_shutdown = true;
-        dl_iterate_phdr(&iterate_phdrs, &do_shutdown);
-    });
+    heaptrack_init(outputFileName, []() { overwrite_symbols(); }, [](FILE* out) { fprintf(out, "A\n"); },
+                   []() {
+                       bool do_shutdown = true;
+                       dl_iterate_phdr(&iterate_phdrs, &do_shutdown);
+                   });
 }
-
 }
index 8af5140..b106bcd 100644 (file)
 
 #include "libheaptrack.h"
 
-#include <dlfcn.h>
 #include <cstdio>
-#include <cstring>
 #include <cstdlib>
+#include <cstring>
+#include <dlfcn.h>
 
-#include <type_traits>
 #include <atomic>
+#include <type_traits>
 
 using namespace std;
 
@@ -36,7 +36,7 @@ namespace {
 
 namespace hooks {
 
-template<typename Signature, typename Base>
+template <typename Signature, typename Base>
 struct hook
 {
     Signature original = nullptr;
@@ -51,20 +51,23 @@ struct hook
         original = reinterpret_cast<Signature>(ret);
     }
 
-    template<typename... Args>
-    auto operator() (Args... args) const noexcept -> decltype(original(args...))
+    template <typename... Args>
+    auto operator()(Args... args) const noexcept -> decltype(original(args...))
     {
         return original(args...);
     }
 
-    explicit operator bool () const noexcept
+    explicit operator bool() const noexcept
     {
         return original;
     }
 };
 
-#define HOOK(name) struct name ## _t : public hook<decltype(&::name), name ## _t> { \
-    static constexpr const char* identifier = #name; } name
+#define HOOK(name)                                                                                                     \
+    struct name##_t : public hook<decltype(&::name), name##_t>                                                         \
+    {                                                                                                                  \
+        static constexpr const char* identifier = #name;                                                               \
+    } name
 
 HOOK(malloc);
 HOOK(free);
@@ -82,9 +85,11 @@ HOOK(dlopen);
 HOOK(dlclose);
 
 /**
- * Dummy implementation, since the call to dlsym from findReal triggers a call to calloc.
+ * Dummy implementation, since the call to dlsym from findReal triggers a call
+ * to calloc.
  *
- * This is only called at startup and will eventually be replaced by the "proper" calloc implementation.
+ * This is only called at startup and will eventually be replaced by the
+ * "proper" calloc implementation.
  */
 void* dummy_calloc(size_t num, size_t size) noexcept
 {
@@ -97,7 +102,9 @@ void* dummy_calloc(size_t num, size_t size) noexcept
     size_t oldOffset = offset;
     offset += num * size;
     if (offset >= MAX_SIZE) {
-        fprintf(stderr, "failed to initialize, dummy calloc buf size exhausted: %zu requested, %zu available\n", offset, MAX_SIZE);
+        fprintf(stderr, "failed to initialize, dummy calloc buf size exhausted: "
+                        "%zu requested, %zu available\n",
+                offset, MAX_SIZE);
         abort();
     }
     return buf + oldOffset;
@@ -105,32 +112,32 @@ void* dummy_calloc(size_t num, size_t size) noexcept
 
 void init()
 {
-    heaptrack_init(getenv("DUMP_HEAPTRACK_OUTPUT"), [] {
-        hooks::calloc.original = &dummy_calloc;
-        hooks::calloc.init();
-        hooks::dlopen.init();
-        hooks::dlclose.init();
-        hooks::malloc.init();
-        hooks::free.init();
-        hooks::calloc.init();
+    heaptrack_init(getenv("DUMP_HEAPTRACK_OUTPUT"),
+                   [] {
+                       hooks::calloc.original = &dummy_calloc;
+                       hooks::calloc.init();
+                       hooks::dlopen.init();
+                       hooks::dlclose.init();
+                       hooks::malloc.init();
+                       hooks::free.init();
+                       hooks::calloc.init();
 #if HAVE_CFREE
-        hooks::cfree.init();
+                       hooks::cfree.init();
 #endif
-        hooks::realloc.init();
-        hooks::posix_memalign.init();
-        hooks::valloc.init();
+                       hooks::realloc.init();
+                       hooks::posix_memalign.init();
+                       hooks::valloc.init();
 #if HAVE_ALIGNED_ALLOC
-        hooks::aligned_alloc.init();
+                       hooks::aligned_alloc.init();
 #endif
 
-        // cleanup environment to prevent tracing of child apps
-        unsetenv("LD_PRELOAD");
-        unsetenv("DUMP_HEAPTRACK_OUTPUT");
-    }, nullptr, nullptr);
+                       // cleanup environment to prevent tracing of child apps
+                       unsetenv("LD_PRELOAD");
+                       unsetenv("DUMP_HEAPTRACK_OUTPUT");
+                   },
+                   nullptr, nullptr);
 }
-
 }
-
 }
 
 extern "C" {
@@ -210,7 +217,7 @@ void cfree(void* ptr) noexcept
 }
 #endif
 
-int posix_memalign(void **memptr, size_t alignment, size_t size) noexcept
+int posix_memalign(void** memptr, size_t alignment, size_t size) noexcept
 {
     if (!hooks::posix_memalign) {
         hooks::init();
@@ -257,7 +264,7 @@ void* valloc(size_t size) noexcept
     return ret;
 }
 
-void *dlopen(const char *filename, int flag) noexcept
+void* dlopen(const char* filename, int flag) noexcept
 {
     if (!hooks::dlopen) {
         hooks::init();
@@ -272,7 +279,7 @@ void *dlopen(const char *filename, int flag) noexcept
     return ret;
 }
 
-int dlclose(void *handle) noexcept
+int dlclose(voidhandle) noexcept
 {
     if (!hooks::dlclose) {
         hooks::init();
@@ -286,5 +293,4 @@ int dlclose(void *handle) noexcept
 
     return ret;
 }
-
 }
index e7ea91b..20e4383 100644 (file)
 
 #include <cstdio>
 #include <cstdlib>
-#include <stdio_ext.h>
 #include <fcntl.h>
 #include <link.h>
+#include <stdio_ext.h>
 
 #include <atomic>
-#include <string>
+#include <cinttypes>
 #include <memory>
-#include <unordered_set>
 #include <mutex>
+#include <string>
 #include <thread>
-#include <cinttypes>
+#include <unordered_set>
 
 #include <boost/algorithm/string/replace.hpp>
 
@@ -71,7 +71,7 @@ constexpr const DebugVerbosity s_debugVerbosity = NoDebugOutput;
  * Call this to optionally show debug information but give the compiler
  * a hand in removing it all if debug output is disabled.
  */
-template<DebugVerbosity debugLevel, typename... Args>
+template <DebugVerbosity debugLevel, typename... Args>
 inline void debugLog(const char fmt[], Args... args)
 {
     if (debugLevel <= s_debugVerbosity) {
@@ -135,11 +135,12 @@ void writeCommandLine(FILE* out)
     char buf[BUF_SIZE + 1];
     auto fd = open("/proc/self/cmdline", O_RDONLY);
     int bytesRead = read(fd, buf, BUF_SIZE);
-    char *end = buf + bytesRead;
-    for (char *p = buf; p < end;) {
+    charend = buf + bytesRead;
+    for (charp = buf; p < end;) {
         fputc(' ', out);
         fputs(p, out);
-        while (*p++); // skip until start of next 0-terminated section
+        while (*p++)
+            ; // skip until start of next 0-terminated section
     }
 
     close(fd);
@@ -148,9 +149,7 @@ void writeCommandLine(FILE* out)
 
 void writeSystemInfo(FILE* out)
 {
-    fprintf(out, "I %lx %lx\n",
-                sysconf(_SC_PAGESIZE),
-                sysconf(_SC_PHYS_PAGES));
+    fprintf(out, "I %lx %lx\n", sysconf(_SC_PAGESIZE), sysconf(_SC_PHYS_PAGES));
 }
 
 FILE* createFile(const char* fileName)
@@ -185,11 +184,14 @@ FILE* createFile(const char* fileName)
 /**
  * Thread-Safe heaptrack API
  *
- * The only critical section in libheaptrack is the output of the data, dl_iterate_phdr
+ * The only critical section in libheaptrack is the output of the data,
+ * dl_iterate_phdr
  * calls, as well as initialization and shutdown.
  *
- * This uses a spinlock, instead of a std::mutex, as the latter can lead to deadlocks
- * on destruction. The spinlock is "simple", and OK to only guard the small sections.
+ * This uses a spinlock, instead of a std::mutex, as the latter can lead to
+ * deadlocks
+ * on destruction. The spinlock is "simple", and OK to only guard the small
+ * sections.
  */
 class HeapTrack
 {
@@ -205,10 +207,8 @@ public:
         s_locked.store(false, memory_order_release);
     }
 
-    void initialize(const char* fileName,
-                    heaptrack_callback_t initBeforeCallback,
-                    heaptrack_callback_initialized_t initAfterCallback,
-                    heaptrack_callback_t stopCallback)
+    void initialize(const char* fileName, heaptrack_callback_t initBeforeCallback,
+                    heaptrack_callback_initialized_t initAfterCallback, heaptrack_callback_t stopCallback)
     {
         debugLog<MinimalOutput>("initializing: %s", fileName);
         if (s_data) {
@@ -230,17 +230,17 @@ public:
             if (unw_set_caching_policy(unw_local_addr_space, UNW_CACHE_PER_THREAD)) {
                 fprintf(stderr, "WARNING: Failed to enable per-thread libunwind caching.\n");
             }
-            #ifdef unw_set_cache_size
+#ifdef unw_set_cache_size
             if (unw_set_cache_size(unw_local_addr_space, 1024, 0)) {
                 fprintf(stderr, "WARNING: Failed to set libunwind cache size.\n");
             }
-            #endif
+#endif
 
             // do not trace forked child processes
             // TODO: make this configurable
             pthread_atfork(&prepare_fork, &parent_fork, &child_fork);
 
-            atexit([] () {
+            atexit([]() {
                 debugLog<MinimalOutput>("%s", "atexit()");
                 s_atexit.store(true);
                 heaptrack_stop();
@@ -338,7 +338,7 @@ public:
         }
     }
 
-    void handleMalloc(void* ptr, size_t size, const Trace &trace)
+    void handleMalloc(void* ptr, size_t size, const Tracetrace)
     {
         if (!s_data || !s_data->out) {
             return;
@@ -377,10 +377,10 @@ public:
     }
 
 private:
-    static int dl_iterate_phdr_callback(struct dl_phdr_info *info, size_t /*size*/, void *data)
+    static int dl_iterate_phdr_callback(struct dl_phdr_info* info, size_t /*size*/, void* data)
     {
         auto heaptrack = reinterpret_cast<HeapTrack*>(data);
-        const char *fileName = info->dlpi_name;
+        const charfileName = info->dlpi_name;
         if (!fileName || !fileName[0]) {
             fileName = "x";
         }
@@ -454,7 +454,7 @@ private:
         shutdown();
     }
 
-    template<typename AdditionalLockCheck>
+    template <typename AdditionalLockCheck>
     HeapTrack(AdditionalLockCheck lockCheck)
     {
         debugLog<VeryVerboseOutput>("%s", "acquiring lock");
@@ -477,7 +477,7 @@ private:
             if (!procStatm) {
                 fprintf(stderr, "WARNING: Failed to open /proc/self/statm for reading.\n");
             }
-            timerThread = thread([&] () {
+            timerThread = thread([&]() {
                 RecursionGuard::isActive = true;
                 debugLog<MinimalOutput>("%s", "timer thread started");
                 while (!stopTimerThread) {
@@ -500,7 +500,8 @@ private:
             if (timerThread.joinable()) {
                 try {
                     timerThread.join();
-                } catch(std::system_error) {}
+                } catch (std::system_error) {
+                }
             }
 
             if (out) {
@@ -544,9 +545,9 @@ private:
 
         heaptrack_callback_t stopCallback = nullptr;
 
-        #ifdef DEBUG_MALLOC_PTRS
+#ifdef DEBUG_MALLOC_PTRS
         unordered_set<void*> known;
-        #endif
+#endif
     };
 
     static atomic<bool> s_locked;
@@ -555,23 +556,18 @@ private:
 
 atomic<bool> HeapTrack::s_locked{false};
 HeapTrack::LockedData* HeapTrack::s_data{nullptr};
-
 }
 extern "C" {
 
-void heaptrack_init(const char *outputFileName,
-                    heaptrack_callback_t initBeforeCallback,
-                    heaptrack_callback_initialized_t initAfterCallback,
-                    heaptrack_callback_t stopCallback)
+void heaptrack_init(const char* outputFileName, heaptrack_callback_t initBeforeCallback,
+                    heaptrack_callback_initialized_t initAfterCallback, heaptrack_callback_t stopCallback)
 {
     RecursionGuard guard;
 
     debugLog<MinimalOutput>("heaptrack_init(%s)", outputFileName);
 
     HeapTrack heaptrack(guard);
-    heaptrack.initialize(outputFileName,
-                         initBeforeCallback, initAfterCallback,
-                         stopCallback);
+    heaptrack.initialize(outputFileName, initBeforeCallback, initAfterCallback, stopCallback);
 }
 
 void heaptrack_stop()
@@ -638,5 +634,4 @@ void heaptrack_invalidate_module_cache()
     HeapTrack heaptrack(guard);
     heaptrack.invalidateModuleCache();
 }
-
 }
index 411af0a..78ffa60 100644 (file)
 extern "C" {
 #endif
 
-typedef void (*heaptrack_callback_t) ();
-typedef void (*heaptrack_callback_initialized_t) (FILE*);
+typedef void (*heaptrack_callback_t)();
+typedef void (*heaptrack_callback_initialized_t)(FILE*);
 
-void heaptrack_init(const char *outputFileName,
-                    heaptrack_callback_t initCallbackBefore,
-                    heaptrack_callback_initialized_t initCallbackAfter,
-                    heaptrack_callback_t stopCallback);
+void heaptrack_init(const char* outputFileName, heaptrack_callback_t initCallbackBefore,
+                    heaptrack_callback_initialized_t initCallbackAfter, heaptrack_callback_t stopCallback);
 
 void heaptrack_stop();
 
-void heaptrack_malloc(void *ptr, size_t size);
+void heaptrack_malloc(voidptr, size_t size);
 
-void heaptrack_free(void *ptr);
+void heaptrack_free(voidptr);
 
-void heaptrack_realloc(void *ptr_in, size_t size, void *ptr_out);
+void heaptrack_realloc(void* ptr_in, size_t size, void* ptr_out);
 
 void heaptrack_invalidate_module_cache();
 
index 17f9ad2..cfa0789 100644 (file)
@@ -32,7 +32,8 @@ struct Trace
 {
     using ip_t = void*;
 
-    enum : int {
+    enum : int
+    {
         MAX_SIZE = 64
     };
 
@@ -46,7 +47,7 @@ struct Trace
         return begin() + m_size;
     }
 
-    ip_t operator[] (int i) const
+    ip_t operator[](int i) const
     {
         return m_data[m_skip + i];
     }
index 9f1b412..2d28dee 100644 (file)
@@ -25,8 +25,8 @@
  * @brief Efficiently combine and store the data of multiple Traces.
  */
 
-#include <vector>
 #include <algorithm>
+#include <vector>
 
 #include "trace.h"
 
@@ -57,7 +57,8 @@ public:
     }
 
     /**
-     * Index the data in @p trace and return the index of the last instruction pointer.
+     * Index the data in @p trace and return the index of the last instruction
+     * pointer.
      *
      * Unknown instruction pointers will be printed to @p out.
      */
@@ -70,9 +71,9 @@ public:
             if (!ip) {
                 continue;
             }
-            auto it = std::lower_bound(parent->children.begin(), parent->children.end(), ip, [] (const TraceEdge& l, const Trace::ip_t ip) {
-                return l.instructionPointer < ip;
-            });
+            auto it =
+                std::lower_bound(parent->children.begin(), parent->children.end(), ip,
+                                 [](const TraceEdge& l, const Trace::ip_t ip) { return l.instructionPointer < ip; });
             if (it == parent->children.end() || it->instructionPointer != ip) {
                 index = m_index++;
                 it = parent->children.insert(it, {ip, index, {}});
index 5557e4d..5ca1a67 100644 (file)
@@ -23,7 +23,7 @@
 #include <unordered_map>
 
 // sadly, C++ doesn't yet have opaque typedefs
-template<typename Base>
+template <typename Base>
 struct Index
 {
     uint32_t index = 0;
@@ -64,15 +64,16 @@ struct Index
     }
 };
 
-template<typename Base>
+template <typename Base>
 uint qHash(const Index<Base> index, uint seed = 0) noexcept
 {
     return qHash(index.index, seed);
 }
 
 namespace std {
-template<typename Base>
-struct hash<Index<Base>> {
+template <typename Base>
+struct hash<Index<Base>>
+{
     std::size_t operator()(const Index<Base> index) const
     {
         return std::hash<uint32_t>()(index.index);
@@ -80,12 +81,26 @@ struct hash<Index<Base>> {
 };
 }
 
-struct StringIndex : public Index<StringIndex> {};
-struct ModuleIndex : public StringIndex {};
-struct FunctionIndex : public StringIndex {};
-struct FileIndex : public StringIndex {};
-struct IpIndex : public Index<IpIndex> {};
-struct TraceIndex : public Index<TraceIndex> {};
-struct AllocationIndex : public Index<AllocationIndex> {};
+struct StringIndex : public Index<StringIndex>
+{
+};
+struct ModuleIndex : public StringIndex
+{
+};
+struct FunctionIndex : public StringIndex
+{
+};
+struct FileIndex : public StringIndex
+{
+};
+struct IpIndex : public Index<IpIndex>
+{
+};
+struct TraceIndex : public Index<TraceIndex>
+{
+};
+struct AllocationIndex : public Index<AllocationIndex>
+{
+};
 
 #endif // INDICES_H
index 79f6bc0..168c1dc 100644 (file)
@@ -61,7 +61,7 @@ public:
         return m_line;
     }
 
-    template<typename T>
+    template <typename T>
     bool readHex(T& in)
     {
         auto it = m_it;
index f90b472..9a4b017 100644 (file)
 #ifndef POINTERMAP_H
 #define POINTERMAP_H
 
-#include <vector>
+#include <algorithm>
+#include <iostream>
+#include <limits>
+#include <map>
 #include <unordered_map>
 #include <unordered_set>
-#include <map>
-#include <limits>
-#include <iostream>
-#include <algorithm>
+#include <vector>
 
 #include <boost/functional/hash.hpp>
 
@@ -42,16 +42,16 @@ struct IndexedAllocationInfo
     AllocationIndex allocationIndex;
     bool operator==(const IndexedAllocationInfo& rhs) const
     {
-        return rhs.traceIndex == traceIndex
-            && rhs.size == size;
-            // allocationInfoIndex not compared to allow to look it up
+        return rhs.traceIndex == traceIndex && rhs.size == size;
+        // allocationInfoIndex not compared to allow to look it up
     }
 };
 
 namespace std {
-template<>
-struct hash<IndexedAllocationInfo> {
-    size_t operator()(const IndexedAllocationInfo &info) const
+template <>
+struct hash<IndexedAllocationInfo>
+{
+    size_t operator()(const IndexedAllocationInfo& info) const
     {
         size_t seed = 0;
         boost::hash_combine(seed, info.size);
@@ -86,7 +86,8 @@ struct AllocationInfoSet
 };
 
 /**
- * A low-memory-overhead map of 64bit pointer addresses to 32bit allocation indices.
+ * A low-memory-overhead map of 64bit pointer addresses to 32bit allocation
+ * indices.
  *
  * We leverage the fact that pointers are allocated in pages, i.e. close to each
  * other. We split the 64bit address into a common large part and an individual
@@ -95,19 +96,22 @@ struct AllocationInfoSet
  *
  * The big part of the address is used for a hash map to lookup the Indices
  * structure where we aggregate common pointers in two memory-efficient vectors,
- * one for the 16bit small pointer pairs, and one for the 32bit allocation indices.
+ * one for the 16bit small pointer pairs, and one for the 32bit allocation
+ * indices.
  */
 class PointerMap
 {
     struct SplitPointer
     {
-        enum {
+        enum
+        {
             PageSize = std::numeric_limits<uint16_t>::max() / 4
         };
         SplitPointer(uint64_t ptr)
             : big(ptr / PageSize)
             , small(ptr % PageSize)
-        {}
+        {
+        }
         uint64_t big;
         uint16_t small;
     };
@@ -148,7 +152,7 @@ public:
         auto& indices = mapIt->second;
         auto pageIt = std::lower_bound(indices.smallPtrParts.begin(), indices.smallPtrParts.end(), pointer.small);
         if (pageIt == indices.smallPtrParts.end() || *pageIt != pointer.small) {
-            return  {{}, false};
+            return {{}, false};
         }
         auto allocationIt = indices.allocationIndices.begin() + distance(indices.smallPtrParts.begin(), pageIt);
         auto index = *allocationIt;
index d78b50c..0d3840b 100644 (file)
@@ -17,8 +17,8 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
-#include "src/track/trace.h"
 #include "3rdparty/catch.hpp"
+#include "src/track/trace.h"
 
 #include <algorithm>
 
@@ -36,27 +36,27 @@ bool fill(Trace& trace, int depth, int skip)
 
 void validateTrace(const Trace& trace, int expectedSize)
 {
-    SECTION("validate the trace size") {
+    SECTION ("validate the trace size") {
         REQUIRE(trace.size() == expectedSize);
         REQUIRE(distance(trace.begin(), trace.end()) == trace.size());
     }
-    SECTION("validate trace contents") {
+    SECTION ("validate trace contents") {
         REQUIRE(find(trace.begin(), trace.end(), Trace::ip_t(0)) == trace.end());
     }
 }
 }
 
-TEST_CASE("getting backtrace traces", "[trace]") {
+TEST_CASE ("getting backtrace traces", "[trace]") {
     Trace trace;
     validateTrace(trace, 0);
 
-    SECTION("fill without skipping") {
+    SECTION ("fill without skipping") {
         REQUIRE(trace.fill(0));
         const auto offset = trace.size();
         REQUIRE(offset > 1);
         validateTrace(trace, offset);
 
-        SECTION("fill with skipping") {
+        SECTION ("fill with skipping") {
             for (auto skip : {0, 1, 2}) {
                 for (int i = 0; i < 2 * Trace::MAX_SIZE; ++i) {
                     REQUIRE(fill(trace, i, skip));
index 18a7443..74c1d12 100644 (file)
@@ -17,8 +17,8 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
-#include "src/util/pointermap.h"
 #include "bench_pointers.h"
+#include "src/util/pointermap.h"
 
 int main()
 {
index 3f7c568..4beba0c 100644 (file)
 #ifndef BENCH_POINTERS
 #define BENCH_POINTERS
 
-#include <cstdint>
-#include <vector>
 #include <algorithm>
+#include <cstdint>
 #include <iostream>
+#include <vector>
 
 #include <malloc.h>
 
 #include "src/util/indices.h"
 
-template<typename Map>
+template <typename Map>
 void benchPointers()
 {
     uint32_t matches = 0;
@@ -61,7 +61,8 @@ void benchPointers()
             }
 
             const auto added = mallinfo().uordblks - baseline;
-            std::cerr << "pointers added:          \t" << added << " (" << (float(added) * 100.f / allocated) << "% overhead)" << std::endl;
+            std::cerr << "pointers added:          \t" << added << " (" << (float(added) * 100.f / allocated)
+                      << "% overhead)" << std::endl;
 
             std::random_shuffle(pointers.begin(), pointers.end());
             for (auto ptr : pointers) {
index cf42d46..b2b6171 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <sparse_hash_map>
+
 #include "bench_pointers.h"
 #include "src/util/indices.h"
 
index 0b522f2..37e74ea 100644 (file)
@@ -17,9 +17,9 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
+#include <iostream>
 #include <malloc.h>
 #include <unistd.h>
-#include <iostream>
 
 using namespace std;
 
index a62b0fc..55e1645 100644 (file)
@@ -35,7 +35,6 @@ public:
 Foo::Foo()
     : d(new Private)
 {
-
 }
 
 Foo::~Foo()
index 1b6ef67..e3f1870 100644 (file)
@@ -1,9 +1,10 @@
-#include <cstdlib>
 #include <cstdio>
+#include <cstdlib>
 
 #define HAVE_ALIGNED_ALLOC defined(_ISOC11_SOURCE)
 
-struct Foo {
+struct Foo
+{
     Foo()
         : i(new int)
     {
index 7c38891..828691d 100644 (file)
@@ -1,5 +1,5 @@
-#include <thread>
 #include <future>
+#include <thread>
 #include <vector>
 
 using namespace std;