Bug Summary

File:tools/clang/tools/extra/clangd/Trace.cpp
Warning:line 100, column 11
Value stored to 'OriginTime' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name Trace.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -relaxed-aliasing -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/tools/clang/tools/extra/clangd -I /build/llvm-toolchain-snapshot-7~svn338205/tools/clang/tools/extra/clangd -I /build/llvm-toolchain-snapshot-7~svn338205/tools/clang/include -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/tools/clang/include -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn338205/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/x86_64-linux-gnu/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/x86_64-linux-gnu/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/lib/gcc/x86_64-linux-gnu/8/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/tools/clang/tools/extra/clangd -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fno-common -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-07-29-043837-17923-1 -x c++ /build/llvm-toolchain-snapshot-7~svn338205/tools/clang/tools/extra/clangd/Trace.cpp -faddrsig
1//===--- Trace.cpp - Performance tracing facilities -----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "Trace.h"
11#include "Context.h"
12#include "Function.h"
13#include "llvm/ADT/DenseSet.h"
14#include "llvm/ADT/ScopeExit.h"
15#include "llvm/Support/Chrono.h"
16#include "llvm/Support/FormatProviders.h"
17#include "llvm/Support/FormatVariadic.h"
18#include "llvm/Support/Threading.h"
19#include <atomic>
20#include <mutex>
21
22namespace clang {
23namespace clangd {
24namespace trace {
25using namespace llvm;
26
27namespace {
28// The current implementation is naive: each thread writes to Out guarded by Mu.
29// Perhaps we should replace this by something that disturbs performance less.
30class JSONTracer : public EventTracer {
31public:
32 JSONTracer(raw_ostream &Out, bool Pretty)
33 : Out(Out), Sep(""), Start(std::chrono::system_clock::now()),
34 JSONFormat(Pretty ? "{0:2}" : "{0}") {
35 // The displayTimeUnit must be ns to avoid low-precision overlap
36 // calculations!
37 Out << R"({"displayTimeUnit":"ns","traceEvents":[)"
38 << "\n";
39 rawEvent("M", json::Object{
40 {"name", "process_name"},
41 {"args", json::Object{{"name", "clangd"}}},
42 });
43 }
44
45 ~JSONTracer() {
46 Out << "\n]}";
47 Out.flush();
48 }
49
50 // We stash a Span object in the context. It will record the start/end,
51 // and this also allows us to look up the parent Span's information.
52 Context beginSpan(llvm::StringRef Name, json::Object *Args) override {
53 return Context::current().derive(
54 SpanKey, llvm::make_unique<JSONSpan>(this, Name, Args));
55 }
56
57 // Trace viewer requires each thread to properly stack events.
58 // So we need to mark only duration that the span was active on the thread.
59 // (Hopefully any off-thread activity will be connected by a flow event).
60 // Record the end time here, but don't write the event: Args aren't ready yet.
61 void endSpan() override {
62 Context::current().getExisting(SpanKey)->markEnded();
63 }
64
65 void instant(llvm::StringRef Name, json::Object &&Args) override {
66 captureThreadMetadata();
67 jsonEvent("i", json::Object{{"name", Name}, {"args", std::move(Args)}});
68 }
69
70 // Record an event on the current thread. ph, pid, tid, ts are set.
71 // Contents must be a list of the other JSON key/values.
72 void jsonEvent(StringRef Phase, json::Object &&Contents,
73 uint64_t TID = get_threadid(), double Timestamp = 0) {
74 Contents["ts"] = Timestamp ? Timestamp : timestamp();
75 Contents["tid"] = int64_t(TID);
76 std::lock_guard<std::mutex> Lock(Mu);
77 rawEvent(Phase, std::move(Contents));
78 }
79
80private:
81 class JSONSpan {
82 public:
83 JSONSpan(JSONTracer *Tracer, llvm::StringRef Name, json::Object *Args)
84 : StartTime(Tracer->timestamp()), EndTime(0), Name(Name),
85 TID(get_threadid()), Tracer(Tracer), Args(Args) {
86 // ~JSONSpan() may run in a different thread, so we need to capture now.
87 Tracer->captureThreadMetadata();
88
89 // We don't record begin events here (and end events in the destructor)
90 // because B/E pairs have to appear in the right order, which is awkward.
91 // Instead we send the complete (X) event in the destructor.
92
93 // If our parent was on a different thread, add an arrow to this span.
94 auto *Parent = Context::current().get(SpanKey);
95 if (Parent && *Parent && (*Parent)->TID != TID) {
96 // If the parent span ended already, then show this as "following" it.
97 // Otherwise show us as "parallel".
98 double OriginTime = (*Parent)->EndTime;
99 if (!OriginTime)
100 OriginTime = (*Parent)->StartTime;
Value stored to 'OriginTime' is never read
101
102 auto FlowID = nextID();
103 Tracer->jsonEvent("s",
104 json::Object{{"id", FlowID},
105 {"name", "Context crosses threads"},
106 {"cat", "dummy"}},
107 (*Parent)->TID, (*Parent)->StartTime);
108 Tracer->jsonEvent("f",
109 json::Object{{"id", FlowID},
110 {"bp", "e"},
111 {"name", "Context crosses threads"},
112 {"cat", "dummy"}},
113 TID);
114 }
115 }
116
117 ~JSONSpan() {
118 // Finally, record the event (ending at EndTime, not timestamp())!
119 Tracer->jsonEvent("X",
120 json::Object{{"name", std::move(Name)},
121 {"args", std::move(*Args)},
122 {"dur", EndTime - StartTime}},
123 TID, StartTime);
124 }
125
126 // May be called by any thread.
127 void markEnded() {
128 EndTime = Tracer->timestamp();
129 }
130
131 private:
132 static int64_t nextID() {
133 static std::atomic<int64_t> Next = {0};
134 return Next++;
135 }
136
137 double StartTime;
138 std::atomic<double> EndTime; // Filled in by markEnded().
139 std::string Name;
140 uint64_t TID;
141 JSONTracer *Tracer;
142 json::Object *Args;
143 };
144 static Key<std::unique_ptr<JSONSpan>> SpanKey;
145
146 // Record an event. ph and pid are set.
147 // Contents must be a list of the other JSON key/values.
148 void rawEvent(StringRef Phase, json::Object &&Event) /*REQUIRES(Mu)*/ {
149 // PID 0 represents the clangd process.
150 Event["pid"] = 0;
151 Event["ph"] = Phase;
152 Out << Sep << formatv(JSONFormat, json::Value(std::move(Event)));
153 Sep = ",\n";
154 }
155
156 // If we haven't already, emit metadata describing this thread.
157 void captureThreadMetadata() {
158 uint64_t TID = get_threadid();
159 std::lock_guard<std::mutex> Lock(Mu);
160 if (ThreadsWithMD.insert(TID).second) {
161 SmallString<32> Name;
162 get_thread_name(Name);
163 if (!Name.empty()) {
164 rawEvent("M", json::Object{
165 {"tid", int64_t(TID)},
166 {"name", "thread_name"},
167 {"args", json::Object{{"name", Name}}},
168 });
169 }
170 }
171 }
172
173 double timestamp() {
174 using namespace std::chrono;
175 return duration<double, std::micro>(system_clock::now() - Start).count();
176 }
177
178 std::mutex Mu;
179 raw_ostream &Out /*GUARDED_BY(Mu)*/;
180 const char *Sep /*GUARDED_BY(Mu)*/;
181 DenseSet<uint64_t> ThreadsWithMD /*GUARDED_BY(Mu)*/;
182 const sys::TimePoint<> Start;
183 const char *JSONFormat;
184};
185
186Key<std::unique_ptr<JSONTracer::JSONSpan>> JSONTracer::SpanKey;
187
188EventTracer *T = nullptr;
189} // namespace
190
191Session::Session(EventTracer &Tracer) {
192 assert(!T && "Resetting global tracer is not allowed.")(static_cast <bool> (!T && "Resetting global tracer is not allowed."
) ? void (0) : __assert_fail ("!T && \"Resetting global tracer is not allowed.\""
, "/build/llvm-toolchain-snapshot-7~svn338205/tools/clang/tools/extra/clangd/Trace.cpp"
, 192, __extension__ __PRETTY_FUNCTION__))
;
193 T = &Tracer;
194}
195
196Session::~Session() { T = nullptr; }
197
198std::unique_ptr<EventTracer> createJSONTracer(llvm::raw_ostream &OS,
199 bool Pretty) {
200 return llvm::make_unique<JSONTracer>(OS, Pretty);
201}
202
203void log(const Twine &Message) {
204 if (!T)
205 return;
206 T->instant("Log", json::Object{{"Message", Message.str()}});
207}
208
209// Returned context owns Args.
210static Context makeSpanContext(llvm::Twine Name, json::Object *Args) {
211 if (!T)
212 return Context::current().clone();
213 WithContextValue WithArgs{std::unique_ptr<json::Object>(Args)};
214 return T->beginSpan(Name.isSingleStringRef() ? Name.getSingleStringRef()
215 : llvm::StringRef(Name.str()),
216 Args);
217}
218
219// Span keeps a non-owning pointer to the args, which is how users access them.
220// The args are owned by the context though. They stick around until the
221// beginSpan() context is destroyed, when the tracing engine will consume them.
222Span::Span(llvm::Twine Name)
223 : Args(T ? new json::Object() : nullptr),
224 RestoreCtx(makeSpanContext(Name, Args)) {}
225
226Span::~Span() {
227 if (T)
228 T->endSpan();
229}
230
231} // namespace trace
232} // namespace clangd
233} // namespace clang