xref: /llvm-project/clang/unittests/Support/TimeProfilerTest.cpp (revision df9a14d7bbf1180e4f1474254c9d7ed6bcb4ce55)
127d8eeddSEvgeny Shulgin //===- unittests/Support/TimeProfilerTest.cpp -----------------------------===//
227d8eeddSEvgeny Shulgin //
327d8eeddSEvgeny Shulgin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
427d8eeddSEvgeny Shulgin // See https://llvm.org/LICENSE.txt for license information.
527d8eeddSEvgeny Shulgin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
627d8eeddSEvgeny Shulgin //
727d8eeddSEvgeny Shulgin //===----------------------------------------------------------------------===//
827d8eeddSEvgeny Shulgin 
927d8eeddSEvgeny Shulgin #include "clang/Frontend/CompilerInstance.h"
1027d8eeddSEvgeny Shulgin #include "clang/Frontend/FrontendActions.h"
1127d8eeddSEvgeny Shulgin #include "clang/Lex/PreprocessorOptions.h"
1227d8eeddSEvgeny Shulgin 
13ecaacd14SUtkarsh Saxena #include "llvm/ADT/StringMap.h"
1427d8eeddSEvgeny Shulgin #include "llvm/Support/JSON.h"
15ecaacd14SUtkarsh Saxena #include "llvm/Support/Path.h"
1627d8eeddSEvgeny Shulgin #include "llvm/Support/TimeProfiler.h"
17ecaacd14SUtkarsh Saxena #include "llvm/Support/VirtualFileSystem.h"
1848ef912eSNikita Popov #include <stack>
1927d8eeddSEvgeny Shulgin 
2027d8eeddSEvgeny Shulgin #include "gtest/gtest.h"
21ecaacd14SUtkarsh Saxena #include <tuple>
2227d8eeddSEvgeny Shulgin 
2327d8eeddSEvgeny Shulgin using namespace clang;
2427d8eeddSEvgeny Shulgin using namespace llvm;
2527d8eeddSEvgeny Shulgin 
2627d8eeddSEvgeny Shulgin namespace {
2727d8eeddSEvgeny Shulgin 
2827d8eeddSEvgeny Shulgin // Should be called before testing.
2927d8eeddSEvgeny Shulgin void setupProfiler() {
30ecaacd14SUtkarsh Saxena   timeTraceProfilerInitialize(/*TimeTraceGranularity=*/0, "test",
31ecaacd14SUtkarsh Saxena                               /*TimeTraceVerbose=*/true);
3227d8eeddSEvgeny Shulgin }
3327d8eeddSEvgeny Shulgin 
3427d8eeddSEvgeny Shulgin // Should be called after `compileFromString()`.
3527d8eeddSEvgeny Shulgin // Returns profiler's JSON dump.
3627d8eeddSEvgeny Shulgin std::string teardownProfiler() {
3727d8eeddSEvgeny Shulgin   SmallVector<char, 1024> SmallVec;
3827d8eeddSEvgeny Shulgin   raw_svector_ostream OS(SmallVec);
3927d8eeddSEvgeny Shulgin   timeTraceProfilerWrite(OS);
4027d8eeddSEvgeny Shulgin   timeTraceProfilerCleanup();
4127d8eeddSEvgeny Shulgin   return OS.str().str();
4227d8eeddSEvgeny Shulgin }
4327d8eeddSEvgeny Shulgin 
4427d8eeddSEvgeny Shulgin // Returns true if code compiles successfully.
4527d8eeddSEvgeny Shulgin // We only parse AST here. This is enough for constexpr evaluation.
46ecaacd14SUtkarsh Saxena bool compileFromString(StringRef Code, StringRef Standard, StringRef File,
47ecaacd14SUtkarsh Saxena                        llvm::StringMap<std::string> Headers = {}) {
4827d8eeddSEvgeny Shulgin 
49ecaacd14SUtkarsh Saxena   llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS(
50ecaacd14SUtkarsh Saxena       new llvm::vfs::InMemoryFileSystem());
51ecaacd14SUtkarsh Saxena   FS->addFile(File, 0, MemoryBuffer::getMemBuffer(Code));
52ecaacd14SUtkarsh Saxena   for (const auto &Header : Headers) {
53ecaacd14SUtkarsh Saxena     FS->addFile(Header.getKey(), 0,
54ecaacd14SUtkarsh Saxena                 MemoryBuffer::getMemBuffer(Header.getValue()));
55ecaacd14SUtkarsh Saxena   }
56ecaacd14SUtkarsh Saxena   llvm::IntrusiveRefCntPtr<FileManager> Files(
57ecaacd14SUtkarsh Saxena       new FileManager(FileSystemOptions(), FS));
58*df9a14d7SKadir Cetinkaya   CompilerInstance Compiler;
59*df9a14d7SKadir Cetinkaya   Compiler.createDiagnostics(Files->getVirtualFileSystem());
60ecaacd14SUtkarsh Saxena   Compiler.setFileManager(Files.get());
61ecaacd14SUtkarsh Saxena 
6227d8eeddSEvgeny Shulgin   auto Invocation = std::make_shared<CompilerInvocation>();
63ecaacd14SUtkarsh Saxena   std::vector<const char *> Args = {Standard.data(), File.data()};
6427d8eeddSEvgeny Shulgin   CompilerInvocation::CreateFromArgs(*Invocation, Args,
6527d8eeddSEvgeny Shulgin                                      Compiler.getDiagnostics());
6627d8eeddSEvgeny Shulgin   Compiler.setInvocation(std::move(Invocation));
6727d8eeddSEvgeny Shulgin 
6827d8eeddSEvgeny Shulgin   class TestFrontendAction : public ASTFrontendAction {
6927d8eeddSEvgeny Shulgin   private:
7027d8eeddSEvgeny Shulgin     std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
7127d8eeddSEvgeny Shulgin                                                    StringRef InFile) override {
7227d8eeddSEvgeny Shulgin       return std::make_unique<ASTConsumer>();
7327d8eeddSEvgeny Shulgin     }
7427d8eeddSEvgeny Shulgin   } Action;
7527d8eeddSEvgeny Shulgin   return Compiler.ExecuteAction(Action);
7627d8eeddSEvgeny Shulgin }
7727d8eeddSEvgeny Shulgin 
78ecaacd14SUtkarsh Saxena std::string GetMetadata(json::Object *Event) {
79280b04f6SUtkarsh Saxena   std::string M;
80280b04f6SUtkarsh Saxena   llvm::raw_string_ostream OS(M);
81ecaacd14SUtkarsh Saxena   if (json::Object *Args = Event->getObject("args")) {
82ecaacd14SUtkarsh Saxena     if (auto Detail = Args->getString("detail"))
83ecaacd14SUtkarsh Saxena       OS << Detail;
84ecaacd14SUtkarsh Saxena     // Use only filename to not include os-specific path separators.
85ecaacd14SUtkarsh Saxena     if (auto File = Args->getString("file"))
86280b04f6SUtkarsh Saxena       OS << (M.empty() ? "" : ", ") << llvm::sys::path::filename(*File);
87ecaacd14SUtkarsh Saxena     if (auto Line = Args->getInteger("line"))
88ecaacd14SUtkarsh Saxena       OS << ":" << *Line;
89ecaacd14SUtkarsh Saxena   }
90280b04f6SUtkarsh Saxena   return M;
91ecaacd14SUtkarsh Saxena }
92ecaacd14SUtkarsh Saxena 
9327d8eeddSEvgeny Shulgin // Returns pretty-printed trace graph.
9427d8eeddSEvgeny Shulgin std::string buildTraceGraph(StringRef Json) {
9527d8eeddSEvgeny Shulgin   struct EventRecord {
9627d8eeddSEvgeny Shulgin     int64_t TimestampBegin;
9727d8eeddSEvgeny Shulgin     int64_t TimestampEnd;
98ecaacd14SUtkarsh Saxena     std::string Name;
99ecaacd14SUtkarsh Saxena     std::string Metadata;
10027d8eeddSEvgeny Shulgin   };
10127d8eeddSEvgeny Shulgin   std::vector<EventRecord> Events;
10227d8eeddSEvgeny Shulgin 
10327d8eeddSEvgeny Shulgin   // Parse `EventRecord`s from JSON dump.
10427d8eeddSEvgeny Shulgin   Expected<json::Value> Root = json::parse(Json);
10527d8eeddSEvgeny Shulgin   if (!Root)
10627d8eeddSEvgeny Shulgin     return "";
10727d8eeddSEvgeny Shulgin   for (json::Value &TraceEventValue :
10827d8eeddSEvgeny Shulgin        *Root->getAsObject()->getArray("traceEvents")) {
10927d8eeddSEvgeny Shulgin     json::Object *TraceEventObj = TraceEventValue.getAsObject();
11027d8eeddSEvgeny Shulgin 
11127d8eeddSEvgeny Shulgin     int64_t TimestampBegin = TraceEventObj->getInteger("ts").value_or(0);
11227d8eeddSEvgeny Shulgin     int64_t TimestampEnd =
11327d8eeddSEvgeny Shulgin         TimestampBegin + TraceEventObj->getInteger("dur").value_or(0);
114ecaacd14SUtkarsh Saxena     std::string Name = TraceEventObj->getString("name").value_or("").str();
115ecaacd14SUtkarsh Saxena     std::string Metadata = GetMetadata(TraceEventObj);
116ecaacd14SUtkarsh Saxena 
117ecaacd14SUtkarsh Saxena     // Source events are asynchronous events and may not perfectly nest the
118ecaacd14SUtkarsh Saxena     // synchronous events. Skip testing them.
119ecaacd14SUtkarsh Saxena     if (Name == "Source")
120ecaacd14SUtkarsh Saxena       continue;
12127d8eeddSEvgeny Shulgin 
12227d8eeddSEvgeny Shulgin     // This is a "summary" event, like "Total PerformPendingInstantiations",
12327d8eeddSEvgeny Shulgin     // skip it
12427d8eeddSEvgeny Shulgin     if (TimestampBegin == 0)
12527d8eeddSEvgeny Shulgin       continue;
12627d8eeddSEvgeny Shulgin 
12727d8eeddSEvgeny Shulgin     Events.emplace_back(
128ecaacd14SUtkarsh Saxena         EventRecord{TimestampBegin, TimestampEnd, Name, Metadata});
12927d8eeddSEvgeny Shulgin   }
13027d8eeddSEvgeny Shulgin 
13127d8eeddSEvgeny Shulgin   // There can be nested events that are very fast, for example:
13227d8eeddSEvgeny Shulgin   // {"name":"EvaluateAsBooleanCondition",... ,"ts":2380,"dur":1}
13327d8eeddSEvgeny Shulgin   // {"name":"EvaluateAsRValue",... ,"ts":2380,"dur":1}
13427d8eeddSEvgeny Shulgin   // Therefore we should reverse the events list, so that events that have
13527d8eeddSEvgeny Shulgin   // started earlier are first in the list.
13627d8eeddSEvgeny Shulgin   // Then do a stable sort, we need it for the trace graph.
13727d8eeddSEvgeny Shulgin   std::reverse(Events.begin(), Events.end());
13827d8eeddSEvgeny Shulgin   std::stable_sort(
13927d8eeddSEvgeny Shulgin       Events.begin(), Events.end(), [](const auto &lhs, const auto &rhs) {
14027d8eeddSEvgeny Shulgin         return std::make_pair(lhs.TimestampBegin, -lhs.TimestampEnd) <
14127d8eeddSEvgeny Shulgin                std::make_pair(rhs.TimestampBegin, -rhs.TimestampEnd);
14227d8eeddSEvgeny Shulgin       });
14327d8eeddSEvgeny Shulgin 
14427d8eeddSEvgeny Shulgin   std::stringstream Stream;
14527d8eeddSEvgeny Shulgin   // Write a newline for better testing with multiline string literal.
14627d8eeddSEvgeny Shulgin   Stream << "\n";
14727d8eeddSEvgeny Shulgin 
14827d8eeddSEvgeny Shulgin   // Keep the current event stack.
14927d8eeddSEvgeny Shulgin   std::stack<const EventRecord *> EventStack;
15027d8eeddSEvgeny Shulgin   for (const auto &Event : Events) {
15127d8eeddSEvgeny Shulgin     // Pop every event in the stack until meeting the parent event.
15227d8eeddSEvgeny Shulgin     while (!EventStack.empty()) {
15327d8eeddSEvgeny Shulgin       bool InsideCurrentEvent =
15427d8eeddSEvgeny Shulgin           Event.TimestampBegin >= EventStack.top()->TimestampBegin &&
15527d8eeddSEvgeny Shulgin           Event.TimestampEnd <= EventStack.top()->TimestampEnd;
15627d8eeddSEvgeny Shulgin       if (!InsideCurrentEvent)
15727d8eeddSEvgeny Shulgin         EventStack.pop();
15827d8eeddSEvgeny Shulgin       else
15927d8eeddSEvgeny Shulgin         break;
16027d8eeddSEvgeny Shulgin     }
16127d8eeddSEvgeny Shulgin     EventStack.push(&Event);
16227d8eeddSEvgeny Shulgin 
16327d8eeddSEvgeny Shulgin     // Write indentaion, name, detail, newline.
16427d8eeddSEvgeny Shulgin     for (size_t i = 1; i < EventStack.size(); ++i) {
16527d8eeddSEvgeny Shulgin       Stream << "| ";
16627d8eeddSEvgeny Shulgin     }
16727d8eeddSEvgeny Shulgin     Stream.write(Event.Name.data(), Event.Name.size());
168ecaacd14SUtkarsh Saxena     if (!Event.Metadata.empty()) {
16927d8eeddSEvgeny Shulgin       Stream << " (";
170ecaacd14SUtkarsh Saxena       Stream.write(Event.Metadata.data(), Event.Metadata.size());
17127d8eeddSEvgeny Shulgin       Stream << ")";
17227d8eeddSEvgeny Shulgin     }
17327d8eeddSEvgeny Shulgin     Stream << "\n";
17427d8eeddSEvgeny Shulgin   }
17527d8eeddSEvgeny Shulgin   return Stream.str();
17627d8eeddSEvgeny Shulgin }
17727d8eeddSEvgeny Shulgin 
17827d8eeddSEvgeny Shulgin } // namespace
17927d8eeddSEvgeny Shulgin 
1802bb50a55SEvgeny Shulgin TEST(TimeProfilerTest, ConstantEvaluationCxx20) {
181ecaacd14SUtkarsh Saxena   std::string Code = R"(
18227d8eeddSEvgeny Shulgin void print(double value);
18327d8eeddSEvgeny Shulgin 
18427d8eeddSEvgeny Shulgin namespace slow_namespace {
18527d8eeddSEvgeny Shulgin 
18627d8eeddSEvgeny Shulgin consteval double slow_func() {
18727d8eeddSEvgeny Shulgin     double d = 0.0;
18827d8eeddSEvgeny Shulgin     for (int i = 0; i < 100; ++i) { // 8th line
18927d8eeddSEvgeny Shulgin         d += i;                     // 9th line
19027d8eeddSEvgeny Shulgin     }
19127d8eeddSEvgeny Shulgin     return d;
19227d8eeddSEvgeny Shulgin }
19327d8eeddSEvgeny Shulgin 
19427d8eeddSEvgeny Shulgin } // namespace slow_namespace
19527d8eeddSEvgeny Shulgin 
19627d8eeddSEvgeny Shulgin void slow_test() {
19727d8eeddSEvgeny Shulgin     constexpr auto slow_value = slow_namespace::slow_func(); // 17th line
19827d8eeddSEvgeny Shulgin     print(slow_namespace::slow_func());                      // 18th line
19927d8eeddSEvgeny Shulgin     print(slow_value);
20027d8eeddSEvgeny Shulgin }
20127d8eeddSEvgeny Shulgin 
20227d8eeddSEvgeny Shulgin int slow_arr[12 + 34 * 56 +                                  // 22nd line
20327d8eeddSEvgeny Shulgin              static_cast<int>(slow_namespace::slow_func())]; // 23rd line
20427d8eeddSEvgeny Shulgin 
20527d8eeddSEvgeny Shulgin constexpr int slow_init_list[] = {1, 1, 2, 3, 5, 8, 13, 21}; // 25th line
20627d8eeddSEvgeny Shulgin     )";
20727d8eeddSEvgeny Shulgin 
20827d8eeddSEvgeny Shulgin   setupProfiler();
2092bb50a55SEvgeny Shulgin   ASSERT_TRUE(compileFromString(Code, "-std=c++20", "test.cc"));
21027d8eeddSEvgeny Shulgin   std::string Json = teardownProfiler();
211ecaacd14SUtkarsh Saxena   ASSERT_EQ(R"(
212280b04f6SUtkarsh Saxena Frontend (test.cc)
213700d93b0SYing Yi | ParseDeclarationOrFunctionDefinition (test.cc:2:1)
214700d93b0SYing Yi | ParseDeclarationOrFunctionDefinition (test.cc:6:1)
215700d93b0SYing Yi | | ParseFunctionDefinition (slow_func)
216700d93b0SYing Yi | | | EvaluateAsRValue (<test.cc:8:21>)
217700d93b0SYing Yi | | | EvaluateForOverflow (<test.cc:8:21, col:25>)
218700d93b0SYing Yi | | | EvaluateForOverflow (<test.cc:8:30, col:32>)
219700d93b0SYing Yi | | | EvaluateAsRValue (<test.cc:9:14>)
220700d93b0SYing Yi | | | EvaluateForOverflow (<test.cc:9:9, col:14>)
221700d93b0SYing Yi | | | isPotentialConstantExpr (slow_namespace::slow_func)
222700d93b0SYing Yi | | | EvaluateAsBooleanCondition (<test.cc:8:21, col:25>)
223700d93b0SYing Yi | | | | EvaluateAsRValue (<test.cc:8:21, col:25>)
224700d93b0SYing Yi | | | EvaluateAsBooleanCondition (<test.cc:8:21, col:25>)
225700d93b0SYing Yi | | | | EvaluateAsRValue (<test.cc:8:21, col:25>)
226700d93b0SYing Yi | ParseDeclarationOrFunctionDefinition (test.cc:16:1)
227700d93b0SYing Yi | | ParseFunctionDefinition (slow_test)
228700d93b0SYing Yi | | | EvaluateAsInitializer (slow_value)
229700d93b0SYing Yi | | | EvaluateAsConstantExpr (<test.cc:17:33, col:59>)
230700d93b0SYing Yi | | | EvaluateAsConstantExpr (<test.cc:18:11, col:37>)
231700d93b0SYing Yi | ParseDeclarationOrFunctionDefinition (test.cc:22:1)
232700d93b0SYing Yi | | EvaluateAsConstantExpr (<test.cc:23:31, col:57>)
233700d93b0SYing Yi | | EvaluateAsRValue (<test.cc:22:14, line:23:58>)
234700d93b0SYing Yi | ParseDeclarationOrFunctionDefinition (test.cc:25:1)
235700d93b0SYing Yi | | EvaluateAsInitializer (slow_init_list)
23627d8eeddSEvgeny Shulgin | PerformPendingInstantiations
237ecaacd14SUtkarsh Saxena )",
238ecaacd14SUtkarsh Saxena             buildTraceGraph(Json));
239ecaacd14SUtkarsh Saxena }
24027d8eeddSEvgeny Shulgin 
2411be64e54Sivanaivanovska TEST(TimeProfilerTest, ClassTemplateInstantiations) {
2421be64e54Sivanaivanovska   std::string Code = R"(
2431be64e54Sivanaivanovska     template<class T>
2441be64e54Sivanaivanovska     struct S
2451be64e54Sivanaivanovska     {
2461be64e54Sivanaivanovska       void foo() {}
2471be64e54Sivanaivanovska       void bar();
2481be64e54Sivanaivanovska     };
2491be64e54Sivanaivanovska 
2501be64e54Sivanaivanovska     template struct S<double>; // explicit instantiation of S<double>
2511be64e54Sivanaivanovska 
2521be64e54Sivanaivanovska     void user() {
2531be64e54Sivanaivanovska       S<int> a; // implicit instantiation of S<int>
2541be64e54Sivanaivanovska       S<float>* b;
2551be64e54Sivanaivanovska       b->foo(); // implicit instatiation of S<float> and S<float>::foo()
2561be64e54Sivanaivanovska     }
2571be64e54Sivanaivanovska   )";
2581be64e54Sivanaivanovska 
2591be64e54Sivanaivanovska   setupProfiler();
2601be64e54Sivanaivanovska   ASSERT_TRUE(compileFromString(Code, "-std=c++20", "test.cc"));
2611be64e54Sivanaivanovska   std::string Json = teardownProfiler();
2621be64e54Sivanaivanovska   ASSERT_EQ(R"(
2631be64e54Sivanaivanovska Frontend (test.cc)
2641be64e54Sivanaivanovska | ParseClass (S)
2651be64e54Sivanaivanovska | InstantiateClass (S<double>, test.cc:9)
2661be64e54Sivanaivanovska | InstantiateFunction (S<double>::foo, test.cc:5)
2671be64e54Sivanaivanovska | ParseDeclarationOrFunctionDefinition (test.cc:11:5)
2681be64e54Sivanaivanovska | | ParseFunctionDefinition (user)
2691be64e54Sivanaivanovska | | | InstantiateClass (S<int>, test.cc:3)
2701be64e54Sivanaivanovska | | | InstantiateClass (S<float>, test.cc:3)
2711be64e54Sivanaivanovska | | | DeferInstantiation (S<float>::foo)
2721be64e54Sivanaivanovska | PerformPendingInstantiations
2731be64e54Sivanaivanovska | | InstantiateFunction (S<float>::foo, test.cc:5)
2741be64e54Sivanaivanovska )",
2751be64e54Sivanaivanovska             buildTraceGraph(Json));
2761be64e54Sivanaivanovska }
2771be64e54Sivanaivanovska 
278ecaacd14SUtkarsh Saxena TEST(TimeProfilerTest, TemplateInstantiations) {
279ecaacd14SUtkarsh Saxena   std::string B_H = R"(
280ecaacd14SUtkarsh Saxena     template <typename T>
2811be64e54Sivanaivanovska     T fooC(T t) {
282ecaacd14SUtkarsh Saxena       return T();
283ecaacd14SUtkarsh Saxena     }
284ecaacd14SUtkarsh Saxena 
2851be64e54Sivanaivanovska     template <typename T>
2861be64e54Sivanaivanovska     constexpr T fooB(T t) {
2871be64e54Sivanaivanovska       return fooC(t);
2881be64e54Sivanaivanovska     }
2891be64e54Sivanaivanovska 
290ecaacd14SUtkarsh Saxena     #define MacroTemp(x) template <typename T> void foo##x(T) { T(); }
291ecaacd14SUtkarsh Saxena   )";
292ecaacd14SUtkarsh Saxena 
293ecaacd14SUtkarsh Saxena   std::string A_H = R"(
294ecaacd14SUtkarsh Saxena     #include "b.h"
295ecaacd14SUtkarsh Saxena 
296ecaacd14SUtkarsh Saxena     MacroTemp(MTA)
297ecaacd14SUtkarsh Saxena 
298ecaacd14SUtkarsh Saxena     template <typename T>
299ecaacd14SUtkarsh Saxena     void fooA(T t) { fooB(t); fooMTA(t); }
300ecaacd14SUtkarsh Saxena   )";
301ecaacd14SUtkarsh Saxena   std::string Code = R"(
302ecaacd14SUtkarsh Saxena     #include "a.h"
303ecaacd14SUtkarsh Saxena     void user() { fooA(0); }
304ecaacd14SUtkarsh Saxena   )";
305ecaacd14SUtkarsh Saxena 
306ecaacd14SUtkarsh Saxena   setupProfiler();
307ecaacd14SUtkarsh Saxena   ASSERT_TRUE(compileFromString(Code, "-std=c++20", "test.cc",
308ecaacd14SUtkarsh Saxena                                 /*Headers=*/{{"a.h", A_H}, {"b.h", B_H}}));
309ecaacd14SUtkarsh Saxena   std::string Json = teardownProfiler();
310ecaacd14SUtkarsh Saxena   ASSERT_EQ(R"(
311280b04f6SUtkarsh Saxena Frontend (test.cc)
3121be64e54Sivanaivanovska | ParseFunctionDefinition (fooC)
313ecaacd14SUtkarsh Saxena | ParseFunctionDefinition (fooB)
314ecaacd14SUtkarsh Saxena | ParseFunctionDefinition (fooMTA)
315ecaacd14SUtkarsh Saxena | ParseFunctionDefinition (fooA)
316ecaacd14SUtkarsh Saxena | ParseDeclarationOrFunctionDefinition (test.cc:3:5)
317ecaacd14SUtkarsh Saxena | | ParseFunctionDefinition (user)
3181be64e54Sivanaivanovska | | | DeferInstantiation (fooA<int>)
319ecaacd14SUtkarsh Saxena | PerformPendingInstantiations
320ecaacd14SUtkarsh Saxena | | InstantiateFunction (fooA<int>, a.h:7)
3211be64e54Sivanaivanovska | | | InstantiateFunction (fooB<int>, b.h:8)
3221be64e54Sivanaivanovska | | | | DeferInstantiation (fooC<int>)
3231be64e54Sivanaivanovska | | | DeferInstantiation (fooMTA<int>)
3241be64e54Sivanaivanovska | | | InstantiateFunction (fooC<int>, b.h:3)
325ecaacd14SUtkarsh Saxena | | | InstantiateFunction (fooMTA<int>, a.h:4)
326ecaacd14SUtkarsh Saxena )",
327ecaacd14SUtkarsh Saxena             buildTraceGraph(Json));
32827d8eeddSEvgeny Shulgin }
3292bb50a55SEvgeny Shulgin 
3302bb50a55SEvgeny Shulgin TEST(TimeProfilerTest, ConstantEvaluationC99) {
331ecaacd14SUtkarsh Saxena   std::string Code = R"(
3322bb50a55SEvgeny Shulgin struct {
3332bb50a55SEvgeny Shulgin   short quantval[4]; // 3rd line
3342bb50a55SEvgeny Shulgin } value;
3352bb50a55SEvgeny Shulgin     )";
3362bb50a55SEvgeny Shulgin 
3372bb50a55SEvgeny Shulgin   setupProfiler();
3382bb50a55SEvgeny Shulgin   ASSERT_TRUE(compileFromString(Code, "-std=c99", "test.c"));
3392bb50a55SEvgeny Shulgin   std::string Json = teardownProfiler();
340ecaacd14SUtkarsh Saxena   ASSERT_EQ(R"(
341280b04f6SUtkarsh Saxena Frontend (test.c)
342700d93b0SYing Yi | ParseDeclarationOrFunctionDefinition (test.c:2:1)
343700d93b0SYing Yi | | isIntegerConstantExpr (<test.c:3:18>)
344700d93b0SYing Yi | | EvaluateKnownConstIntCheckOverflow (<test.c:3:18>)
3452bb50a55SEvgeny Shulgin | PerformPendingInstantiations
346ecaacd14SUtkarsh Saxena )",
347ecaacd14SUtkarsh Saxena             buildTraceGraph(Json));
3482bb50a55SEvgeny Shulgin }
349