0.6.0
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-2025 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 objc_interface_decl_ = nullptr;
35 objc_protocol_decl_ = nullptr;
36}
37
39{
40 LOG_DBG("current_caller_id_ = {}", current_caller_id_);
41 LOG_DBG("current_class_decl_ = {}", (void *)current_class_decl_);
42 LOG_DBG("current_class_template_decl_ = {}",
44 LOG_DBG("current_class_template_specialization_decl_ = {}",
46 LOG_DBG("current_method_decl_ = {}", (void *)current_method_decl_);
47 LOG_DBG("current_function_decl_ = {}", (void *)current_function_decl_);
48 LOG_DBG("current_function_template_decl_ = {}",
50 LOG_DBG("objc_interface_decl_ = {}", (void *)objc_interface_decl_);
51 LOG_DBG(
52 "current_objc_method_decl_ = {}", (void *)current_objc_method_decl_);
53 LOG_DBG("objc_protocol_decl_ = {}", (void *)objc_protocol_decl_);
54}
55
57{
58 return (current_class_decl_ != nullptr) ||
59 (current_class_template_decl_ != nullptr) ||
61 (current_method_decl_ != nullptr) ||
62 (current_function_decl_ != nullptr) ||
64 (objc_interface_decl_ != nullptr) ||
65 (current_objc_method_decl_ != nullptr) ||
66 (objc_protocol_decl_ != nullptr);
67}
68
70{
72 return &current_class_template_specialization_decl_->getASTContext();
73
74 if (current_class_template_decl_ != nullptr)
75 return &current_class_template_decl_->getASTContext();
76
77 if (current_class_decl_ != nullptr)
78 return &current_class_decl_->getASTContext();
79
81 return &current_function_template_decl_->getASTContext();
82
83 if (current_function_decl_ != nullptr) {
84 return &current_function_decl_->getASTContext();
85 }
86
87 if (current_method_decl_ != nullptr) {
88 return &current_method_decl_->getASTContext();
89 }
90
91 if (objc_interface_decl_ != nullptr) {
92 return &objc_interface_decl_->getASTContext();
93 }
94
95 if (objc_protocol_decl_ != nullptr) {
96 return &objc_protocol_decl_->getASTContext();
97 }
98
99 if (current_objc_method_decl_ != nullptr) {
100 return &current_objc_method_decl_->getASTContext();
101 }
102
103 return nullptr;
104}
105
106void call_expression_context::update(clang::CXXRecordDecl *cls)
107{
109}
110
111void call_expression_context::update(clang::ObjCInterfaceDecl *cls)
112{
114}
115
116void call_expression_context::update(clang::ObjCProtocolDecl *cls)
117{
119}
120
122 clang::ClassTemplateSpecializationDecl *clst)
123{
125}
126
127void call_expression_context::update(clang::ClassTemplateDecl *clst)
128{
130}
131
132void call_expression_context::update(clang::CXXMethodDecl *method)
133{
134 current_method_decl_ = method;
135}
136
137void call_expression_context::update(clang::ObjCMethodDecl *method)
138{
140}
141
142void call_expression_context::update(clang::FunctionDecl *function)
143{
144 if (!function->isCXXClassMember())
145 reset();
146
147 current_function_decl_ = function;
148
149 // Check if this function is a part of template function declaration,
150 // If no - reset the current_function_template_decl_
151 if ((current_function_template_decl_ != nullptr) &&
152 current_function_template_decl_->getQualifiedNameAsString() !=
153 function->getQualifiedNameAsString()) {
155 }
156}
157
159 clang::FunctionTemplateDecl *function_template)
160{
161 current_function_template_decl_ = function_template;
162
163 if (!function_template->isCXXClassMember())
164 current_class_decl_ = nullptr;
165
166 current_function_template_decl_ = function_template;
167}
168
170{
171 if (lambda_caller_id().has_value())
172 return *lambda_caller_id(); // NOLINT
173
174 return current_caller_id_;
175}
176
178{
179 if (current_lambda_caller_id_.empty())
180 return {};
181
182 return current_lambda_caller_id_.top();
183}
184
186{
187 LOG_DBG("Setting current caller id to {}", id);
189}
190
192{
193 LOG_DBG("Setting current lambda caller id to {}", id);
194
195 assert(id.value() != 0);
196
197 current_lambda_caller_id_.emplace(id);
198}
199
201{
202 if (current_lambda_caller_id_.empty())
203 return;
204
205 LOG_DBG("Leaving current lambda expression id to {}",
207
209}
210
212{
213 if (if_stmt_stack_.empty())
214 return nullptr;
215
216 return if_stmt_stack_.top();
217}
218
220{
221 if_stmt_stack_.emplace(stmt);
222}
223
225{
226 if (!if_stmt_stack_.empty()) {
228 if_stmt_stack_.pop();
229 }
230}
231
233{
234 assert(current_ifstmt() != nullptr);
235
236 elseif_stmt_stacks_[current_ifstmt()].emplace(stmt);
237}
238
240{
241 assert(current_ifstmt() != nullptr);
242
243 if (elseif_stmt_stacks_.count(current_ifstmt()) == 0 ||
245 return nullptr;
246
247 return elseif_stmt_stacks_.at(current_ifstmt()).top();
248}
249
251{
252 if (loop_stmt_stack_.empty())
253 return nullptr;
254
255 return loop_stmt_stack_.top();
256}
257
259{
260 loop_stmt_stack_.emplace(stmt);
261}
262
264{
265 if (!loop_stmt_stack_.empty())
266 return loop_stmt_stack_.pop();
267}
268
271{
272 if (call_expr_stack_.empty())
273 return {};
274
275 return call_expr_stack_.top();
276}
277
279{
280 call_expr_stack_.emplace(expr);
281}
282
283void call_expression_context::enter_callexpr(clang::CXXConstructExpr *expr)
284{
285 call_expr_stack_.emplace(expr);
286}
287
288void call_expression_context::enter_callexpr(clang::ObjCMessageExpr *expr)
289{
290 call_expr_stack_.emplace(expr);
291}
292
294{
295 if (!call_expr_stack_.empty()) {
296 return call_expr_stack_.pop();
297 }
298}
299
301{
302 if (try_stmt_stack_.empty())
303 return nullptr;
304
305 return try_stmt_stack_.top();
306}
307
309{
310 try_stmt_stack_.emplace(stmt);
311}
312
314{
315 if (try_stmt_stack_.empty())
316 try_stmt_stack_.pop();
317}
318
320{
321 if (switch_stmt_stack_.empty())
322 return nullptr;
323
324 return switch_stmt_stack_.top();
325}
326
327void call_expression_context::enter_switchstmt(clang::SwitchStmt *stmt)
328{
329 switch_stmt_stack_.emplace(stmt);
330}
331
333{
334 if (switch_stmt_stack_.empty())
335 switch_stmt_stack_.pop();
336}
337
338clang::ConditionalOperator *
340{
341 if (conditional_operator_stack_.empty())
342 return nullptr;
343
344 return conditional_operator_stack_.top();
345}
346
348 clang::ConditionalOperator *stmt)
349{
350 conditional_operator_stack_.emplace(stmt);
351}
352
354{
355 if (!conditional_operator_stack_.empty())
357}
358
360 const clang::Stmt *stmt) const
361{
362 if (current_ifstmt() != nullptr) {
363 if (common::is_subexpr_of(current_ifstmt()->getCond(), stmt))
364 return true;
365
366 if (const auto *condition_decl_stmt = current_ifstmt()->getInit();
367 condition_decl_stmt != nullptr) {
368 if (common::is_subexpr_of(condition_decl_stmt, stmt))
369 return true;
370 }
371
372 if (current_elseifstmt() != nullptr) {
373 if (common::is_subexpr_of(current_elseifstmt()->getCond(), stmt))
374 return true;
375 }
376 }
377
378 if (current_conditionaloperator() != nullptr) {
380 current_conditionaloperator()->getCond(), stmt))
381 return true;
382 }
383
384 if (const auto *loop_stmt = current_loopstmt(); loop_stmt != nullptr) {
385 if (const auto *for_stmt = clang::dyn_cast<clang::ForStmt>(loop_stmt);
386 for_stmt != nullptr) {
387 if (common::is_subexpr_of(for_stmt->getCond(), stmt)) {
388 return true;
389 }
390 if (common::is_subexpr_of(for_stmt->getInit(), stmt)) {
391 return true;
392 }
393 if (common::is_subexpr_of(for_stmt->getInc(), stmt)) {
394 return true;
395 }
396 }
397
398 if (const auto *range_for_stmt =
399 clang::dyn_cast<clang::CXXForRangeStmt>(loop_stmt);
400 range_for_stmt != nullptr) {
401 if (common::is_subexpr_of(range_for_stmt->getRangeInit(), stmt)) {
402 return true;
403 }
404 }
405
406 if (const auto *while_stmt =
407 clang::dyn_cast<clang::WhileStmt>(loop_stmt);
408 while_stmt != nullptr) {
409 if (common::is_subexpr_of(while_stmt->getCond(), stmt)) {
410 return true;
411 }
412 }
413
414 if (const auto *do_stmt = clang::dyn_cast<clang::DoStmt>(loop_stmt);
415 do_stmt != nullptr) {
416 if (common::is_subexpr_of(do_stmt->getCond(), stmt)) {
417 return true;
418 }
419 }
420
421 if (current_conditionaloperator() != nullptr) {
423 current_conditionaloperator()->getCond(), stmt)) {
424 return true;
425 }
426 }
427 }
428
429 return false;
430}
431
432} // namespace clanguml::sequence_diagram::visitor