0.5.4
C++ to UML diagram generator based on Clang
Loading...
Searching...
No Matches
call_expression_context.cc
Go to the documentation of this file.
1/**
2 * @file src/sequence_diagram/visitor/call_expression_context.cc
3 *
4 * Copyright (c) 2021-2024 Bartek Kryza <bkryza@gmail.com>
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
20
22
24
26{
28 current_class_decl_ = nullptr;
31 current_method_decl_ = nullptr;
32 current_function_decl_ = nullptr;
34}
35
37{
38 LOG_DBG("current_caller_id_ = {}", current_caller_id_);
39 LOG_DBG("current_class_decl_ = {}", (void *)current_class_decl_);
40 LOG_DBG("current_class_template_decl_ = {}",
42 LOG_DBG("current_class_template_specialization_decl_ = {}",
44 LOG_DBG("current_method_decl_ = {}", (void *)current_method_decl_);
45 LOG_DBG("current_function_decl_ = {}", (void *)current_function_decl_);
46 LOG_DBG("current_function_template_decl_ = {}",
48}
49
51{
52 return (current_class_decl_ != nullptr) ||
53 (current_class_template_decl_ != nullptr) ||
55 (current_method_decl_ != nullptr) ||
56 (current_function_decl_ != nullptr) ||
58}
59
61{
63 return &current_class_template_specialization_decl_->getASTContext();
64
65 if (current_class_template_decl_ != nullptr)
66 return &current_class_template_decl_->getASTContext();
67
68 if (current_class_decl_ != nullptr)
69 return &current_class_decl_->getASTContext();
70
72 return &current_function_template_decl_->getASTContext();
73
74 if (current_function_decl_ != nullptr) {
75 return &current_function_decl_->getASTContext();
76 }
77
78 if (current_method_decl_ != nullptr) {
79 return &current_method_decl_->getASTContext();
80 }
81
82 return nullptr;
83}
84
85void call_expression_context::update(clang::CXXRecordDecl *cls)
86{
88}
89
91 clang::ClassTemplateSpecializationDecl *clst)
92{
94}
95
96void call_expression_context::update(clang::ClassTemplateDecl *clst)
97{
99}
100
101void call_expression_context::update(clang::CXXMethodDecl *method)
102{
103 current_method_decl_ = method;
104}
105
106void call_expression_context::update(clang::FunctionDecl *function)
107{
108 if (!function->isCXXClassMember())
109 reset();
110
111 current_function_decl_ = function;
112
113 // Check if this function is a part of template function declaration,
114 // If no - reset the current_function_template_decl_
115 if ((current_function_template_decl_ != nullptr) &&
116 current_function_template_decl_->getQualifiedNameAsString() !=
117 function->getQualifiedNameAsString()) {
119 }
120}
121
123 clang::FunctionTemplateDecl *function_template)
124{
125 current_function_template_decl_ = function_template;
126
127 if (!function_template->isCXXClassMember())
128 current_class_decl_ = nullptr;
129
130 current_function_template_decl_ = function_template;
131}
132
134{
135 if (lambda_caller_id().has_value())
136 return *lambda_caller_id(); // NOLINT
137
138 return current_caller_id_;
139}
140
142{
143 if (current_lambda_caller_id_.empty())
144 return {};
145
146 return current_lambda_caller_id_.top();
147}
148
150{
151 LOG_DBG("Setting current caller id to {}", id);
153}
154
156{
157 LOG_DBG("Setting current lambda caller id to {}", id);
158
159 assert(id.value() != 0);
160
161 current_lambda_caller_id_.emplace(id);
162}
163
165{
166 if (current_lambda_caller_id_.empty())
167 return;
168
169 LOG_DBG("Leaving current lambda expression id to {}",
171
173}
174
176{
177 if (if_stmt_stack_.empty())
178 return nullptr;
179
180 return if_stmt_stack_.top();
181}
182
184{
185 if_stmt_stack_.emplace(stmt);
186}
187
189{
190 if (!if_stmt_stack_.empty()) {
192 if_stmt_stack_.pop();
193 }
194}
195
197{
198 assert(current_ifstmt() != nullptr);
199
200 elseif_stmt_stacks_[current_ifstmt()].emplace(stmt);
201}
202
204{
205 assert(current_ifstmt() != nullptr);
206
207 if (elseif_stmt_stacks_.count(current_ifstmt()) == 0 ||
209 return nullptr;
210
211 return elseif_stmt_stacks_.at(current_ifstmt()).top();
212}
213
215{
216 if (loop_stmt_stack_.empty())
217 return nullptr;
218
219 return loop_stmt_stack_.top();
220}
221
223{
224 loop_stmt_stack_.emplace(stmt);
225}
226
228{
229 if (!loop_stmt_stack_.empty())
230 return loop_stmt_stack_.pop();
231}
232
235{
236 if (call_expr_stack_.empty())
237 return {};
238
239 return call_expr_stack_.top();
240}
241
243{
244 call_expr_stack_.emplace(expr);
245}
246
247void call_expression_context::enter_callexpr(clang::CXXConstructExpr *expr)
248{
249 call_expr_stack_.emplace(expr);
250}
251
253{
254 if (!call_expr_stack_.empty()) {
255 return call_expr_stack_.pop();
256 }
257}
258
260{
261 if (try_stmt_stack_.empty())
262 return nullptr;
263
264 return try_stmt_stack_.top();
265}
266
268{
269 try_stmt_stack_.emplace(stmt);
270}
271
273{
274 if (try_stmt_stack_.empty())
275 try_stmt_stack_.pop();
276}
277
279{
280 if (switch_stmt_stack_.empty())
281 return nullptr;
282
283 return switch_stmt_stack_.top();
284}
285
286void call_expression_context::enter_switchstmt(clang::SwitchStmt *stmt)
287{
288 switch_stmt_stack_.emplace(stmt);
289}
290
292{
293 if (switch_stmt_stack_.empty())
294 switch_stmt_stack_.pop();
295}
296
297clang::ConditionalOperator *
299{
300 if (conditional_operator_stack_.empty())
301 return nullptr;
302
303 return conditional_operator_stack_.top();
304}
305
307 clang::ConditionalOperator *stmt)
308{
309 conditional_operator_stack_.emplace(stmt);
310}
311
313{
314 if (!conditional_operator_stack_.empty())
316}
317
319 const clang::Stmt *stmt) const
320{
321 if (current_ifstmt() != nullptr) {
322 if (common::is_subexpr_of(current_ifstmt()->getCond(), stmt))
323 return true;
324
325 if (const auto *condition_decl_stmt = current_ifstmt()->getInit();
326 condition_decl_stmt != nullptr) {
327 if (common::is_subexpr_of(condition_decl_stmt, stmt))
328 return true;
329 }
330
331 if (current_elseifstmt() != nullptr) {
332 if (common::is_subexpr_of(current_elseifstmt()->getCond(), stmt))
333 return true;
334 }
335 }
336
337 if (current_conditionaloperator() != nullptr) {
339 current_conditionaloperator()->getCond(), stmt))
340 return true;
341 }
342
343 if (const auto *loop_stmt = current_loopstmt(); loop_stmt != nullptr) {
344 if (const auto *for_stmt = clang::dyn_cast<clang::ForStmt>(loop_stmt);
345 for_stmt != nullptr) {
346 if (common::is_subexpr_of(for_stmt->getCond(), stmt)) {
347 return true;
348 }
349 if (common::is_subexpr_of(for_stmt->getInit(), stmt)) {
350 return true;
351 }
352 if (common::is_subexpr_of(for_stmt->getInc(), stmt)) {
353 return true;
354 }
355 }
356
357 if (const auto *range_for_stmt =
358 clang::dyn_cast<clang::CXXForRangeStmt>(loop_stmt);
359 range_for_stmt != nullptr) {
360 if (common::is_subexpr_of(range_for_stmt->getRangeInit(), stmt)) {
361 return true;
362 }
363 }
364
365 if (const auto *while_stmt =
366 clang::dyn_cast<clang::WhileStmt>(loop_stmt);
367 while_stmt != nullptr) {
368 if (common::is_subexpr_of(while_stmt->getCond(), stmt)) {
369 return true;
370 }
371 }
372
373 if (const auto *do_stmt = clang::dyn_cast<clang::DoStmt>(loop_stmt);
374 do_stmt != nullptr) {
375 if (common::is_subexpr_of(do_stmt->getCond(), stmt)) {
376 return true;
377 }
378 }
379
380 if (current_conditionaloperator() != nullptr) {
382 current_conditionaloperator()->getCond(), stmt)) {
383 return true;
384 }
385 }
386 }
387
388 return false;
389}
390
391} // namespace clanguml::sequence_diagram::visitor