0.6.0
C++ to UML diagram generator based on Clang
Loading...
Searching...
No Matches
Functions
of ResursiveASTVisitor methods

Detailed Description

Functions

bool clanguml::class_diagram::visitor::translation_unit_visitor::shouldVisitTemplateInstantiations () const
 
bool clanguml::class_diagram::visitor::translation_unit_visitor::shouldVisitImplicitCode () const
 
virtual bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitNamespaceDecl (clang::NamespaceDecl *ns)
 
virtual bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitRecordDecl (clang::RecordDecl *D)
 
virtual bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitCXXRecordDecl (clang::CXXRecordDecl *d)
 
virtual bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitTypedefDecl (clang::TypedefDecl *decl)
 
virtual bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitEnumDecl (clang::EnumDecl *e)
 
virtual bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitClassTemplateDecl (clang::ClassTemplateDecl *class_template_declaration)
 
virtual bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitClassTemplateSpecializationDecl (clang::ClassTemplateSpecializationDecl *cls)
 
virtual bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitTypeAliasTemplateDecl (clang::TypeAliasTemplateDecl *cls)
 
virtual bool clanguml::class_diagram::visitor::translation_unit_visitor::TraverseConceptDecl (clang::ConceptDecl *cpt)
 
virtual bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitObjCCategoryDecl (clang::ObjCCategoryDecl *decl)
 
virtual bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitObjCProtocolDecl (clang::ObjCProtocolDecl *decl)
 
virtual bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitObjCInterfaceDecl (clang::ObjCInterfaceDecl *decl)
 
virtual bool clanguml::package_diagram::visitor::translation_unit_visitor::VisitNamespaceDecl (clang::NamespaceDecl *ns)
 
virtual bool clanguml::package_diagram::visitor::translation_unit_visitor::VisitEnumDecl (clang::EnumDecl *decl)
 
virtual bool clanguml::package_diagram::visitor::translation_unit_visitor::VisitCXXRecordDecl (clang::CXXRecordDecl *cls)
 
virtual bool clanguml::package_diagram::visitor::translation_unit_visitor::VisitRecordDecl (clang::RecordDecl *cls)
 
virtual bool clanguml::package_diagram::visitor::translation_unit_visitor::VisitClassTemplateDecl (clang::ClassTemplateDecl *decl)
 
virtual bool clanguml::package_diagram::visitor::translation_unit_visitor::VisitFunctionDecl (clang::FunctionDecl *function_declaration)
 
virtual bool clanguml::package_diagram::visitor::translation_unit_visitor::VisitObjCCategoryDecl (clang::ObjCCategoryDecl *decl)
 
virtual bool clanguml::package_diagram::visitor::translation_unit_visitor::VisitObjCProtocolDecl (clang::ObjCProtocolDecl *decl)
 
virtual bool clanguml::package_diagram::visitor::translation_unit_visitor::VisitObjCInterfaceDecl (clang::ObjCInterfaceDecl *decl)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::shouldVisitTemplateInstantiations ()
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitCallExpr (clang::CallExpr *expr)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitObjCMessageExpr (clang::ObjCMessageExpr *expr)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitObjCPropertyRefExpr (clang::ObjCPropertyRefExpr *expr)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseVarDecl (clang::VarDecl *VD)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCallExpr (clang::CallExpr *expr)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseObjCMessageExpr (clang::ObjCMessageExpr *expr)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCUDAKernelCallExpr (clang::CUDAKernelCallExpr *expr)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCXXMemberCallExpr (clang::CXXMemberCallExpr *expr)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCXXOperatorCallExpr (clang::CXXOperatorCallExpr *expr)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitCXXConstructExpr (clang::CXXConstructExpr *expr)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCXXConstructExpr (clang::CXXConstructExpr *expr)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCXXTemporaryObjectExpr (clang::CXXTemporaryObjectExpr *expr)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitLambdaExpr (clang::LambdaExpr *expr)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseLambdaExpr (clang::LambdaExpr *expr)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCXXMethodDecl (clang::CXXMethodDecl *declaration)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseObjCMethodDecl (clang::ObjCMethodDecl *declaration)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitObjCMethodDecl (clang::ObjCMethodDecl *declaration)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitCXXMethodDecl (clang::CXXMethodDecl *declaration)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitCXXRecordDecl (clang::CXXRecordDecl *declaration)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitClassTemplateDecl (clang::ClassTemplateDecl *declaration)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitClassTemplateSpecializationDecl (clang::ClassTemplateSpecializationDecl *declaration)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseFunctionDecl (clang::FunctionDecl *declaration)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitFunctionDecl (clang::FunctionDecl *declaration)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseFunctionTemplateDecl (clang::FunctionTemplateDecl *declaration)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitFunctionTemplateDecl (clang::FunctionTemplateDecl *function_declaration)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_declaration)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitObjCProtocolDecl (clang::ObjCProtocolDecl *protocol_declaration)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCompoundStmt (clang::CompoundStmt *stmt)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseIfStmt (clang::IfStmt *stmt)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseWhileStmt (clang::WhileStmt *stmt)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseDoStmt (clang::DoStmt *stmt)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseForStmt (clang::ForStmt *stmt)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCXXForRangeStmt (clang::CXXForRangeStmt *stmt)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCXXTryStmt (clang::CXXTryStmt *stmt)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCXXCatchStmt (clang::CXXCatchStmt *stmt)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseSwitchStmt (clang::SwitchStmt *stmt)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCaseStmt (clang::CaseStmt *stmt)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseDefaultStmt (clang::DefaultStmt *stmt)
 
bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseConditionalOperator (clang::ConditionalOperator *stmt)
 

Function Documentation

◆ shouldVisitImplicitCode()

bool clanguml::class_diagram::visitor::translation_unit_visitor::shouldVisitImplicitCode ( ) const
inline

Definition at line 100 of file translation_unit_visitor.h.

100{ return false; }

◆ shouldVisitTemplateInstantiations() [1/2]

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::shouldVisitTemplateInstantiations ( )

Definition at line 43 of file translation_unit_visitor.cc.

44{
45 return true;
46}

◆ shouldVisitTemplateInstantiations() [2/2]

bool clanguml::class_diagram::visitor::translation_unit_visitor::shouldVisitTemplateInstantiations ( ) const
inline

Definition at line 98 of file translation_unit_visitor.h.

98{ return false; }

◆ TraverseCallExpr()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCallExpr ( clang::CallExpr *  expr)

Definition at line 715 of file translation_unit_visitor.cc.

716{
717 if (!config().include_system_headers() &&
718 source_manager().isInSystemHeader(expr->getSourceRange().getBegin()))
719 return true;
720
721 LOG_TRACE("Entering call expression at {}",
722 expr->getBeginLoc().printToString(source_manager()));
723
724 context().enter_callexpr(expr);
725
726 RecursiveASTVisitor<translation_unit_visitor>::TraverseCallExpr(expr);
727
728 LOG_TRACE("Leaving call expression at {}",
729 expr->getBeginLoc().printToString(source_manager()));
730
732
734
735 return true;
736}

◆ TraverseCaseStmt()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCaseStmt ( clang::CaseStmt *  stmt)

Definition at line 1179 of file translation_unit_visitor.cc.

1180{
1182
1183 const auto current_caller_id = context().caller_id();
1184
1185 if ((current_caller_id.value() != 0) &&
1186 (context().current_switchstmt() != nullptr)) {
1187 model::message m{message_t::kCase, current_caller_id};
1188 m.set_message_name(common::to_string(stmt->getLHS()));
1189 diagram().add_case_stmt_message(std::move(m));
1190 }
1191
1192 RecursiveASTVisitor<translation_unit_visitor>::TraverseCaseStmt(stmt);
1193
1194 return true;
1195}

◆ TraverseCompoundStmt()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCompoundStmt ( clang::CompoundStmt *  stmt)

Definition at line 843 of file translation_unit_visitor.cc.

844{
849
850 if (stmt == nullptr)
851 return true;
852
853 const auto *current_ifstmt = context().current_ifstmt();
854 const auto *current_elseifstmt =
855 current_ifstmt != nullptr ? context().current_elseifstmt() : nullptr;
856
857 //
858 // Add final else block (not else if)
859 //
860 if (current_elseifstmt != nullptr) {
861 if (current_elseifstmt->getElse() == stmt) {
862 const auto current_caller_id = context().caller_id();
863
864 if (current_caller_id.value() != 0) {
865 model::message m{message_t::kElse, current_caller_id};
866 set_source_location(*stmt, m);
867 diagram().add_message(std::move(m));
868 }
869 }
870 }
871 else if (current_ifstmt != nullptr) {
872 if (current_ifstmt->getElse() == stmt) {
873 const auto current_caller_id = context().caller_id();
874
875 if (current_caller_id.value() != 0) {
876 model::message m{message_t::kElse, current_caller_id};
877 set_source_location(*stmt, m);
878 diagram().add_message(std::move(m));
879 }
880 }
881 }
882
883 RecursiveASTVisitor<translation_unit_visitor>::TraverseCompoundStmt(stmt);
884
885 return true;
886}

◆ TraverseConceptDecl()

bool clanguml::class_diagram::visitor::translation_unit_visitor::TraverseConceptDecl ( clang::ConceptDecl *  cpt)
virtual

Definition at line 541 of file translation_unit_visitor.cc.

542{
543 if (!should_include(cpt))
544 return true;
545
546 LOG_DBG("= Visiting concept (isType: {}) declaration {} at {}",
547 cpt->isTypeConcept(), cpt->getQualifiedNameAsString(),
548 cpt->getLocation().printToString(source_manager()));
549
550 auto concept_model = create_concept_declaration(cpt);
551
552 if (!concept_model)
553 return true;
554
555 const auto concept_id = concept_model->id();
556
557 id_mapper().add(cpt->getID(), concept_id);
558
559 tbuilder().build_from_template_declaration(*concept_model, *cpt);
560
561 constexpr auto kMaxConstraintCount = 24U;
562 llvm::SmallVector<const clang::Expr *, kMaxConstraintCount> constraints{};
563 if (cpt->hasAssociatedConstraints()) {
564 cpt->getAssociatedConstraints(constraints);
565 }
566
567 for (const auto *expr : constraints) {
569 }
570
571 if (cpt->getConstraintExpr() != nullptr) {
573 cpt, cpt->getConstraintExpr(), *concept_model);
574
576 *concept_model, cpt->getConstraintExpr());
577 }
578
579 if (diagram().should_include(*concept_model)) {
580 LOG_DBG("Adding concept {} with id {}", concept_model->full_name(false),
581 concept_model->id());
582
583 add_concept(std::move(concept_model));
584 }
585 else {
586 LOG_DBG("Skipping concept {} with id {}",
587 concept_model->full_name(true), concept_model->id());
588 }
589
590 return true;
591}

◆ TraverseConditionalOperator()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseConditionalOperator ( clang::ConditionalOperator *  stmt)

Definition at line 1215 of file translation_unit_visitor.cc.

1217{
1219
1220 const auto current_caller_id = context().caller_id();
1221
1222 std::string condition_text;
1223 if (config().generate_condition_statements())
1224 condition_text = common::get_condition_text(source_manager(), stmt);
1225
1226 if (current_caller_id.value() != 0) {
1228 model::message m{message_t::kConditional, current_caller_id};
1229 set_source_location(*stmt, m);
1230 m.condition_text(condition_text);
1231 m.set_comment(get_expression_comment(source_manager(),
1232 *context().get_ast_context(), current_caller_id, stmt));
1233 diagram().add_block_message(std::move(m));
1234 }
1235
1236 RecursiveASTVisitor<translation_unit_visitor>::TraverseStmt(
1237 stmt->getCond());
1238
1239 RecursiveASTVisitor<translation_unit_visitor>::TraverseStmt(
1240 stmt->getTrueExpr());
1241
1242 if (current_caller_id.value() != 0) {
1243 model::message m{message_t::kConditionalElse, current_caller_id};
1244 set_source_location(*stmt, m);
1245 diagram().add_message(std::move(m));
1246 }
1247
1248 RecursiveASTVisitor<translation_unit_visitor>::TraverseStmt(
1249 stmt->getFalseExpr());
1250
1251 if (current_caller_id.value() != 0) {
1253 diagram().end_block_message(
1254 {message_t::kConditionalEnd, current_caller_id},
1255 message_t::kConditional);
1256 }
1257
1258 return true;
1259}

◆ TraverseCUDAKernelCallExpr()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCUDAKernelCallExpr ( clang::CUDAKernelCallExpr *  expr)

Definition at line 738 of file translation_unit_visitor.cc.

740{
741 if (!config().include_system_headers() &&
742 source_manager().isInSystemHeader(expr->getSourceRange().getBegin()))
743 return true;
744
745 LOG_TRACE("Entering CUDA kernel call expression at {}",
746 expr->getBeginLoc().printToString(source_manager()));
747
748 context().enter_callexpr(expr);
749
750 RecursiveASTVisitor<translation_unit_visitor>::TraverseCallExpr(expr);
751
752 LOG_TRACE("Leaving CUDA kernel call expression at {}",
753 expr->getBeginLoc().printToString(source_manager()));
754
756
758
759 return true;
760}

◆ TraverseCXXCatchStmt()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCXXCatchStmt ( clang::CXXCatchStmt *  stmt)

Definition at line 1091 of file translation_unit_visitor.cc.

1092{
1096
1097 const auto current_caller_id = context().caller_id();
1098
1099 if ((current_caller_id.value() != 0) &&
1100 (context().current_trystmt() != nullptr)) {
1101 std::string caught_type;
1102 if (stmt->getCaughtType().isNull())
1103 caught_type = "...";
1104 else
1105 caught_type = common::to_string(
1106 stmt->getCaughtType(), *context().get_ast_context());
1107
1108 model::message m{message_t::kCatch, current_caller_id};
1109 m.set_message_name(std::move(caught_type));
1110 diagram().add_message(std::move(m));
1111 }
1112
1113 RecursiveASTVisitor<translation_unit_visitor>::TraverseCXXCatchStmt(stmt);
1114
1115 return true;
1116}

◆ TraverseCXXConstructExpr()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCXXConstructExpr ( clang::CXXConstructExpr *  expr)

Definition at line 820 of file translation_unit_visitor.cc.

822{
823 LOG_TRACE("Entering cxx construct call expression at {}",
824 expr->getBeginLoc().printToString(source_manager()));
825
826 context().enter_callexpr(expr);
827
828 RecursiveASTVisitor<translation_unit_visitor>::TraverseCXXConstructExpr(
829 expr);
830
832
833 LOG_TRACE("Leaving cxx construct call expression at {}",
834 expr->getBeginLoc().printToString(source_manager()));
835
837
839
840 return true;
841}

◆ TraverseCXXForRangeStmt()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCXXForRangeStmt ( clang::CXXForRangeStmt *  stmt)

Definition at line 1118 of file translation_unit_visitor.cc.

1120{
1124
1125 const auto current_caller_id = context().caller_id();
1126
1127 std::string condition_text;
1128 if (config().generate_condition_statements())
1129 condition_text = common::get_condition_text(source_manager(), stmt);
1130
1131 if (current_caller_id.value() != 0) {
1132 context().enter_loopstmt(stmt);
1133 message m{message_t::kFor, current_caller_id};
1134 set_source_location(*stmt, m);
1135 m.condition_text(condition_text);
1136 m.set_comment(get_expression_comment(source_manager(),
1137 *context().get_ast_context(), current_caller_id, stmt));
1138 diagram().add_block_message(std::move(m));
1139 }
1140
1141 RecursiveASTVisitor<translation_unit_visitor>::TraverseCXXForRangeStmt(
1142 stmt);
1143
1144 if (current_caller_id.value() != 0) {
1145 diagram().end_block_message(
1146 {message_t::kForEnd, current_caller_id}, message_t::kFor);
1148 }
1149
1150 return true;
1151}

◆ TraverseCXXMemberCallExpr()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCXXMemberCallExpr ( clang::CXXMemberCallExpr *  expr)

Definition at line 762 of file translation_unit_visitor.cc.

764{
765 if (!config().include_system_headers() &&
766 source_manager().isInSystemHeader(expr->getSourceRange().getBegin()))
767 return true;
768
769 LOG_TRACE("Entering member call expression at {}",
770 expr->getBeginLoc().printToString(source_manager()));
771
772 context().enter_callexpr(expr);
773
774 RecursiveASTVisitor<translation_unit_visitor>::TraverseCXXMemberCallExpr(
775 expr);
776
777 LOG_TRACE("Leaving member call expression at {}",
778 expr->getBeginLoc().printToString(source_manager()));
779
781
783
784 return true;
785}

◆ TraverseCXXMethodDecl()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCXXMethodDecl ( clang::CXXMethodDecl *  declaration)

Definition at line 373 of file translation_unit_visitor.cc.

375{
376 // We need to backup the context, since other methods or functions can
377 // be traversed during this traversal (e.g. template function/method
378 // specializations)
379 auto context_backup = context();
380
381 RecursiveASTVisitor<translation_unit_visitor>::TraverseCXXMethodDecl(
382 declaration);
383
384 call_expression_context_ = context_backup;
385
386 return true;
387}

◆ TraverseCXXOperatorCallExpr()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCXXOperatorCallExpr ( clang::CXXOperatorCallExpr *  expr)

Definition at line 787 of file translation_unit_visitor.cc.

789{
790 context().enter_callexpr(expr);
791
792 RecursiveASTVisitor<translation_unit_visitor>::TraverseCXXOperatorCallExpr(
793 expr);
794
796
798
799 return true;
800}

◆ TraverseCXXTemporaryObjectExpr()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCXXTemporaryObjectExpr ( clang::CXXTemporaryObjectExpr *  expr)

Definition at line 802 of file translation_unit_visitor.cc.

804{
805 context().enter_callexpr(expr);
806
807 RecursiveASTVisitor<
809
811 clang::dyn_cast<clang::CXXConstructExpr>(expr));
812
814
816
817 return true;
818}

◆ TraverseCXXTryStmt()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseCXXTryStmt ( clang::CXXTryStmt *  stmt)

Definition at line 1063 of file translation_unit_visitor.cc.

1064{
1068
1069 const auto current_caller_id = context().caller_id();
1070
1071 if (current_caller_id.value() != 0) {
1072 context().enter_trystmt(stmt);
1073 message m{message_t::kTry, current_caller_id};
1074 set_source_location(*stmt, m);
1075 m.set_comment(get_expression_comment(source_manager(),
1076 *context().get_ast_context(), current_caller_id, stmt));
1077 diagram().add_block_message(std::move(m));
1078 }
1079
1080 RecursiveASTVisitor<translation_unit_visitor>::TraverseCXXTryStmt(stmt);
1081
1082 if (current_caller_id.value() != 0) {
1083 diagram().end_block_message(
1084 {message_t::kTryEnd, current_caller_id}, message_t::kTry);
1086 }
1087
1088 return true;
1089}

◆ TraverseDefaultStmt()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseDefaultStmt ( clang::DefaultStmt *  stmt)

Definition at line 1197 of file translation_unit_visitor.cc.

1198{
1200
1201 const auto current_caller_id = context().caller_id();
1202
1203 if ((current_caller_id.value() != 0) &&
1204 (context().current_switchstmt() != nullptr)) {
1205 model::message m{message_t::kCase, current_caller_id};
1206 m.set_message_name("default");
1207 diagram().add_case_stmt_message(std::move(m));
1208 }
1209
1210 RecursiveASTVisitor<translation_unit_visitor>::TraverseDefaultStmt(stmt);
1211
1212 return true;
1213}

◆ TraverseDoStmt()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseDoStmt ( clang::DoStmt *  stmt)

Definition at line 995 of file translation_unit_visitor.cc.

996{
1000
1001 const auto current_caller_id = context().caller_id();
1002
1003 std::string condition_text;
1004 if (config().generate_condition_statements())
1005 condition_text = common::get_condition_text(source_manager(), stmt);
1006
1007 if (current_caller_id.value() != 0) {
1008 context().enter_loopstmt(stmt);
1009 message m{message_t::kDo, current_caller_id};
1010 set_source_location(*stmt, m);
1011 m.condition_text(condition_text);
1012 m.set_comment(get_expression_comment(source_manager(),
1013 *context().get_ast_context(), current_caller_id, stmt));
1014 diagram().add_block_message(std::move(m));
1015 }
1016
1017 RecursiveASTVisitor<translation_unit_visitor>::TraverseDoStmt(stmt);
1018
1019 if (current_caller_id.value() != 0) {
1020 diagram().end_block_message(
1021 {message_t::kDoEnd, current_caller_id}, message_t::kDo);
1023 }
1024
1025 return true;
1026}

◆ TraverseForStmt()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseForStmt ( clang::ForStmt *  stmt)

Definition at line 1028 of file translation_unit_visitor.cc.

1029{
1033
1034 const auto current_caller_id = context().caller_id();
1035
1036 std::string condition_text;
1037 if (config().generate_condition_statements())
1038 condition_text = common::get_condition_text(source_manager(), stmt);
1039
1040 if (current_caller_id.value() != 0) {
1041 context().enter_loopstmt(stmt);
1042 message m{message_t::kFor, current_caller_id};
1043 set_source_location(*stmt, m);
1044 m.condition_text(condition_text);
1045
1046 m.set_comment(get_expression_comment(source_manager(),
1047 *context().get_ast_context(), current_caller_id, stmt));
1048
1049 diagram().add_block_message(std::move(m));
1050 }
1051
1052 RecursiveASTVisitor<translation_unit_visitor>::TraverseForStmt(stmt);
1053
1054 if (current_caller_id.value() != 0) {
1055 diagram().end_block_message(
1056 {message_t::kForEnd, current_caller_id}, message_t::kFor);
1058 }
1059
1060 return true;
1061}

◆ TraverseFunctionDecl()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseFunctionDecl ( clang::FunctionDecl *  declaration)

Definition at line 451 of file translation_unit_visitor.cc.

453{
454 // We need to backup the context, since other methods or functions can
455 // be traversed during this traversal (e.g. template function/method
456 // specializations)
457 auto context_backup = context();
458
459 RecursiveASTVisitor<translation_unit_visitor>::TraverseFunctionDecl(
460 declaration);
461
462 call_expression_context_ = context_backup;
463
464 return true;
465}

◆ TraverseFunctionTemplateDecl()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseFunctionTemplateDecl ( clang::FunctionTemplateDecl *  declaration)

Definition at line 543 of file translation_unit_visitor.cc.

545{
546 // We need to backup the context, since other methods or functions can
547 // be traversed during this traversal (e.g. template function/method
548 // specializations)
549 auto context_backup = context();
550
551 RecursiveASTVisitor<translation_unit_visitor>::TraverseFunctionTemplateDecl(
552 declaration);
553
554 call_expression_context_ = context_backup;
555
556 return true;
557}

◆ TraverseIfStmt()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseIfStmt ( clang::IfStmt *  stmt)

Definition at line 888 of file translation_unit_visitor.cc.

889{
894
895 bool elseif_block{false};
896
897 const auto current_caller_id = context().caller_id();
898 const auto *current_ifstmt = context().current_ifstmt();
899 const auto *current_elseifstmt =
900 current_ifstmt != nullptr ? context().current_elseifstmt() : nullptr;
901
902 std::string condition_text;
903 if (config().generate_condition_statements())
904 condition_text = common::get_condition_text(source_manager(), stmt);
905
906 // Check if this is a beginning of a new if statement, or an
907 // else if condition of the current if statement
908 auto child_stmt_compare = [stmt](auto *child_stmt) {
909 return child_stmt == stmt;
910 };
911
912 if (current_ifstmt != nullptr)
913 elseif_block = elseif_block ||
914 std::any_of(current_ifstmt->children().begin(),
915 current_ifstmt->children().end(), child_stmt_compare);
916 if (current_elseifstmt != nullptr)
917 elseif_block = elseif_block ||
918 std::any_of(current_elseifstmt->children().begin(),
919 current_elseifstmt->children().end(), child_stmt_compare);
920
921 if ((current_caller_id.value() != 0) && !stmt->isConstexpr()) {
922 if (elseif_block) {
924
925 message m{message_t::kElseIf, current_caller_id};
926 set_source_location(*stmt, m);
927 m.condition_text(condition_text);
929 *context().get_ast_context(), current_caller_id, stmt));
930 diagram().add_block_message(std::move(m));
931 }
932 else {
933 context().enter_ifstmt(stmt);
934 LOG_TRACE("Entered if statement at {}",
935 stmt->getBeginLoc().printToString(source_manager()));
936
937 message m{message_t::kIf, current_caller_id};
938 set_source_location(*stmt, m);
939 m.condition_text(condition_text);
941 *context().get_ast_context(), current_caller_id, stmt));
942 diagram().add_block_message(std::move(m));
943 }
944 }
945
946 RecursiveASTVisitor<translation_unit_visitor>::TraverseIfStmt(stmt);
947
948 if ((current_caller_id.value() != 0) && !stmt->isConstexpr()) {
949 if (!elseif_block) {
950 diagram().end_block_message(
951 {message_t::kIfEnd, current_caller_id}, message_t::kIf);
953 }
954 }
955
956 return true;
957}

◆ TraverseLambdaExpr()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseLambdaExpr ( clang::LambdaExpr *  expr)

Definition at line 680 of file translation_unit_visitor.cc.

681{
682 RecursiveASTVisitor<translation_unit_visitor>::TraverseLambdaExpr(expr);
683
684 // lambda context is entered inside the visitor
686
687 return true;
688}

◆ TraverseObjCMessageExpr()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseObjCMessageExpr ( clang::ObjCMessageExpr *  expr)

Definition at line 690 of file translation_unit_visitor.cc.

692{
693 if (!config().include_system_headers() &&
694 source_manager().isInSystemHeader(expr->getSourceRange().getBegin()))
695 return true;
696
697 LOG_TRACE("Entering ObjC message expression at {}",
698 expr->getBeginLoc().printToString(source_manager()));
699
700 context().enter_callexpr(expr);
701
702 RecursiveASTVisitor<translation_unit_visitor>::TraverseObjCMessageExpr(
703 expr);
704
705 LOG_TRACE("Leaving ObjC message expression at {}",
706 expr->getBeginLoc().printToString(source_manager()));
707
709
711
712 return true;
713}

◆ TraverseObjCMethodDecl()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseObjCMethodDecl ( clang::ObjCMethodDecl *  declaration)

Definition at line 318 of file translation_unit_visitor.cc.

320{
321 // We need to backup the context, since other methods or functions can
322 // be traversed during this traversal (e.g. template function/method
323 // specializations)
324 auto context_backup = context();
325
326 RecursiveASTVisitor<translation_unit_visitor>::TraverseObjCMethodDecl(
327 declaration);
328
329 call_expression_context_ = context_backup;
330
331 return true;
332}

◆ TraverseSwitchStmt()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseSwitchStmt ( clang::SwitchStmt *  stmt)

Definition at line 1153 of file translation_unit_visitor.cc.

1154{
1156
1157 const auto current_caller_id = context().caller_id();
1158
1159 if (current_caller_id.value() != 0) {
1160 context().enter_switchstmt(stmt);
1161 model::message m{message_t::kSwitch, current_caller_id};
1162 set_source_location(*stmt, m);
1163 m.set_comment(get_expression_comment(source_manager(),
1164 *context().get_ast_context(), current_caller_id, stmt));
1165 diagram().add_block_message(std::move(m));
1166 }
1167
1168 RecursiveASTVisitor<translation_unit_visitor>::TraverseSwitchStmt(stmt);
1169
1170 if (current_caller_id.value() != 0) {
1172 diagram().end_block_message(
1173 {message_t::kSwitchEnd, current_caller_id}, message_t::kSwitch);
1174 }
1175
1176 return true;
1177}

◆ TraverseVarDecl()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseVarDecl ( clang::VarDecl *  VD)

Definition at line 1541 of file translation_unit_visitor.cc.

1542{
1543 if (decl->isStaticLocal())
1545
1546 RecursiveASTVisitor::TraverseVarDecl(decl);
1547
1548 if (decl->isStaticLocal())
1550
1551 return true;
1552}

◆ TraverseWhileStmt()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::TraverseWhileStmt ( clang::WhileStmt *  stmt)

Definition at line 959 of file translation_unit_visitor.cc.

960{
964
965 const auto current_caller_id = context().caller_id();
966
967 std::string condition_text;
968 if (config().generate_condition_statements())
969 condition_text = common::get_condition_text(source_manager(), stmt);
970
971 if (current_caller_id.value() != 0) {
972 LOG_TRACE("Entering while statement at {}",
973 stmt->getBeginLoc().printToString(source_manager()));
974
975 context().enter_loopstmt(stmt);
976 message m{message_t::kWhile, current_caller_id};
977 set_source_location(*stmt, m);
978 m.condition_text(condition_text);
980 *context().get_ast_context(), current_caller_id, stmt));
981 diagram().add_block_message(std::move(m));
982 }
983
984 RecursiveASTVisitor<translation_unit_visitor>::TraverseWhileStmt(stmt);
985
986 if (current_caller_id.value() != 0) {
987 diagram().end_block_message(
988 {message_t::kWhileEnd, current_caller_id}, message_t::kWhile);
990 }
991
992 return true;
993}

◆ VisitCallExpr()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitCallExpr ( clang::CallExpr *  expr)

Definition at line 1350 of file translation_unit_visitor.cc.

1351{
1357
1358 if (!context().valid() || context().get_ast_context() == nullptr)
1359 return true;
1360
1361 LOG_TRACE("Visiting call expression at {} [caller_id = {}]",
1362 expr->getBeginLoc().printToString(source_manager()),
1363 context().caller_id());
1364
1365 message m{message_t::kCall, context().caller_id()};
1366
1367 m.in_static_declaration_context(within_static_variable_declaration_ > 0);
1368
1369 set_source_location(*expr, m);
1370
1371 const auto *raw_expr_comment = clanguml::common::get_expression_raw_comment(
1372 source_manager(), *context().get_ast_context(), expr);
1373 const auto stripped_comment = process_comment(
1374 raw_expr_comment, context().get_ast_context()->getDiagnostics(), m);
1375
1376 if (m.skip())
1377 return true;
1378
1379 auto generated_message_from_comment = generate_message_from_comment(m);
1380
1381 if (!generated_message_from_comment && !should_include(expr)) {
1382 LOG_DBG("Skipping call expression due to filter at: {}",
1383 expr->getBeginLoc().printToString(source_manager()));
1384
1385 processed_comments().erase(raw_expr_comment);
1386 return true;
1387 }
1388
1389 if (context().is_expr_in_current_control_statement_condition(expr)) {
1390 m.set_message_scope(common::model::message_scope_t::kCondition);
1391 }
1392
1393 if (generated_message_from_comment) {
1394 LOG_DBG(
1395 "Message for this call expression is taken from comment directive");
1396 }
1397 //
1398 // Call to a CUDA kernel function
1399 //
1400 else if (const auto *cuda_call_expr =
1401 clang::dyn_cast_or_null<clang::CUDAKernelCallExpr>(expr);
1402 cuda_call_expr != nullptr) {
1403 if (!process_cuda_kernel_call_expression(m, cuda_call_expr))
1404 return true;
1405 }
1406 //
1407 // Call to an overloaded operator
1408 //
1409 else if (const auto *operator_call_expr =
1410 clang::dyn_cast_or_null<clang::CXXOperatorCallExpr>(expr);
1411 operator_call_expr != nullptr) {
1412
1413 if (!process_operator_call_expression(m, operator_call_expr))
1414 return true;
1415 }
1416 //
1417 // Call to a class method
1418 //
1419 else if (const auto *method_call_expr =
1420 clang::dyn_cast_or_null<clang::CXXMemberCallExpr>(expr);
1421 method_call_expr != nullptr) {
1422
1423 if (!process_class_method_call_expression(m, method_call_expr))
1424 return true;
1425 }
1426 //
1427 // Call to function or template
1428 //
1429 else {
1430 auto *callee_decl = expr->getCalleeDecl();
1431
1432 if (callee_decl == nullptr) {
1433 LOG_DBG("Cannot get callee declaration - trying direct function "
1434 "callee...");
1435
1436 callee_decl = expr->getDirectCallee();
1437
1438 if (callee_decl != nullptr)
1439 LOG_DBG("Found function/method callee in: {}",
1440 common::to_string(expr));
1441 }
1442
1443 if (callee_decl == nullptr) {
1444 //
1445 // Call to a method of a class template
1446 //
1447 if (clang::dyn_cast_or_null<clang::CXXDependentScopeMemberExpr>(
1448 expr->getCallee()) != nullptr) {
1450 return true;
1451 }
1452 }
1453 //
1454 // Unresolved lookup expression are sometimes calls to template
1455 // functions
1456 //
1457 else if (clang::dyn_cast_or_null<clang::UnresolvedLookupExpr>(
1458 expr->getCallee()) != nullptr) {
1460 return true;
1461 }
1462 else if (clang::dyn_cast_or_null<clang::LambdaExpr>(
1463 expr->getCallee()) != nullptr) {
1464 LOG_DBG("Processing lambda expression callee");
1465 if (!process_lambda_call_expression(m, expr))
1466 return true;
1467 }
1468 else if (clang::dyn_cast_or_null<clang::DependentScopeDeclRefExpr>(
1469 expr->getCallee()) != nullptr) {
1470 LOG_DBG("Processing dependent scope declaration expression "
1471 "callee - not able to infer the template parameter "
1472 "type at this point: {}",
1473 expr->getBeginLoc().printToString(source_manager()));
1474 }
1475 else {
1476 LOG_DBG("Found unsupported callee decl type for: {} at {}",
1477 common::to_string(expr),
1478 expr->getBeginLoc().printToString(source_manager()));
1479 }
1480 }
1481 else {
1482 auto success = process_function_call_expression(m, expr);
1483
1484 if (!success) {
1485 LOG_DBG("Skipping call expression at: {}",
1486 expr->getBeginLoc().printToString(source_manager()));
1487
1488 return true;
1489 }
1490 }
1491 }
1492
1493 // Add message to diagram
1494 if (m.from().value() > 0 && m.to().value() > 0) {
1495 if (raw_expr_comment != nullptr)
1496 m.set_comment(raw_expr_comment->getBeginLoc().getHashValue(),
1497 stripped_comment);
1498
1500
1501 diagram().add_active_participant(m.from());
1502 diagram().add_active_participant(m.to());
1503
1504 LOG_DBG("Found call {} from {} [{}] to {} [{}] ", m.message_name(),
1505 m.from(), m.from(), m.to(), m.to());
1506
1507 push_message(expr, std::move(m));
1508 }
1509
1510 return true;
1511}

◆ VisitClassTemplateDecl() [1/3]

bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitClassTemplateDecl ( clang::ClassTemplateDecl *  class_template_declaration)
virtual

Definition at line 311 of file translation_unit_visitor.cc.

313{
314 if (!should_include(cls))
315 return true;
316
317 LOG_DBG("= Visiting class template declaration {} at {}",
318 cls->getQualifiedNameAsString(),
319 cls->getLocation().printToString(source_manager()));
320
321 auto c_ptr = create_class_declaration(cls->getTemplatedDecl());
322
323 if (!c_ptr)
324 return true;
325
326 add_processed_template_class(cls->getQualifiedNameAsString());
327
328 tbuilder().build_from_template_declaration(*c_ptr, *cls, *c_ptr);
329
330 // Override the id with the template id, for now we don't care about the
331 // underlying templated class id
332 const auto cls_full_name = c_ptr->full_name(false);
333 const auto id = common::to_id(cls_full_name);
334
335 c_ptr->set_id(id);
336 c_ptr->is_template(true);
337
338 id_mapper().add(cls->getID(), id);
339
340 constexpr auto kMaxConstraintCount = 24U;
341 llvm::SmallVector<const clang::Expr *, kMaxConstraintCount> constraints{};
342 if (cls->hasAssociatedConstraints()) {
343 cls->getAssociatedConstraints(constraints);
344 }
345
346 for (const auto *expr : constraints) {
348 }
349
350 if (!cls->getTemplatedDecl()->isCompleteDefinition()) {
351 forward_declarations_.emplace(id, std::move(c_ptr));
352 return true;
353 }
354 process_class_declaration(*cls->getTemplatedDecl(), *c_ptr);
355 forward_declarations_.erase(id);
356
357 if (diagram().should_include(*c_ptr)) {
358 const auto name = c_ptr->full_name(true);
359 LOG_DBG("Adding class template {} with id {}", name, id);
360
361 add_class(std::move(c_ptr));
362 }
363
364 return true;
365}

◆ VisitClassTemplateDecl() [2/3]

bool clanguml::package_diagram::visitor::translation_unit_visitor::VisitClassTemplateDecl ( clang::ClassTemplateDecl *  decl)
virtual

Definition at line 194 of file translation_unit_visitor.cc.

196{
197 assert(decl != nullptr);
198
199 // Skip system headers
200 if (source_manager().isInSystemHeader(decl->getSourceRange().getBegin()))
201 return true;
202
203 found_relationships_t relationships;
204
205 util::if_not_null(decl->getTemplatedDecl(),
206 [this, &relationships, decl](const auto *template_decl) {
207 if (template_decl->isCompleteDefinition()) {
208 process_class_declaration(*template_decl, relationships);
209 add_relationships(decl, relationships);
210 }
211 });
212
213 return true;
214}

◆ VisitClassTemplateDecl() [3/3]

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitClassTemplateDecl ( clang::ClassTemplateDecl *  declaration)

Definition at line 224 of file translation_unit_visitor.cc.

226{
227 if (!should_include(declaration))
228 return true;
229
230 LOG_TRACE("Visiting class template declaration {} at {} [{}]",
231 declaration->getQualifiedNameAsString(),
232 declaration->getLocation().printToString(source_manager()),
233 (void *)declaration);
234
235 auto class_model_ptr = create_class_model(declaration->getTemplatedDecl());
236
237 if (!class_model_ptr)
238 return true;
239
240 tbuilder().build_from_template_declaration(*class_model_ptr, *declaration);
241
242 const auto class_full_name = class_model_ptr->full_name(false);
243 const auto id = common::to_id(class_full_name);
244
245 // Override the id with the template id, for now we don't care about the
246 // underlying templated class id
247 class_model_ptr->set_id(id);
248
249 set_unique_id(declaration->getID(), id);
250
251 if (!declaration->getTemplatedDecl()->isCompleteDefinition()) {
252 forward_declarations_.emplace(id, std::move(class_model_ptr));
253 return true;
254 }
255 forward_declarations_.erase(id);
256
257 if (diagram().should_include(*class_model_ptr)) {
258 LOG_DBG("Adding class template participant {} with id {}",
259 class_full_name, id);
260
262 context().update(declaration);
263
264 diagram().add_participant(std::move(class_model_ptr));
265 }
266
267 return true;
268}

◆ VisitClassTemplateSpecializationDecl() [1/2]

bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitClassTemplateSpecializationDecl ( clang::ClassTemplateSpecializationDecl *  cls)
virtual

Definition at line 216 of file translation_unit_visitor.cc.

218{
219 if (!should_include(cls))
220 return true;
221
222 LOG_DBG("= Visiting template specialization declaration {} at {} "
223 "(described class id {})",
224 cls->getQualifiedNameAsString(),
225 cls->getLocation().printToString(source_manager()),
226 cls->getSpecializedTemplate()
227 ? cls->getSpecializedTemplate()->getTemplatedDecl()->getID()
228 : 0);
229
230 // TODO: Add support for classes defined in function/method bodies
231 if (cls->isLocalClass() != nullptr)
232 return true;
233
234 auto template_specialization_ptr = process_template_specialization(cls);
235
236 if (!template_specialization_ptr)
237 return true;
238
239 auto &template_specialization = *template_specialization_ptr;
240
241 if (cls->hasDefinition()) {
242 // Process template specialization bases
243 process_class_bases(cls, template_specialization);
244
245 // Process class child entities
246 process_class_children(cls, template_specialization);
247 }
248
249 if (!template_specialization.template_specialization_found()) {
250 // Only do this if we haven't found a better specialization during
251 // construction of the template specialization
252 const eid_t ast_id{cls->getSpecializedTemplate()->getID()};
253 const auto maybe_id = id_mapper().get_global_id(ast_id);
254 if (maybe_id.has_value())
255 template_specialization.add_relationship(
256 {relationship_t::kInstantiation, maybe_id.value()});
257 }
258
259 if (diagram().should_include(template_specialization)) {
260 const auto full_name = template_specialization.full_name(false);
261 const auto id = template_specialization.id();
262
263 LOG_DBG("Adding class template specialization {} with id {}", full_name,
264 id);
265 add_class(std::move(template_specialization_ptr));
266 }
267
268 return true;
269}

◆ VisitClassTemplateSpecializationDecl() [2/2]

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitClassTemplateSpecializationDecl ( clang::ClassTemplateSpecializationDecl *  declaration)

Definition at line 270 of file translation_unit_visitor.cc.

272{
273 if (!should_include(declaration))
274 return true;
275
276 LOG_TRACE("Visiting template specialization declaration {} at {}",
277 declaration->getQualifiedNameAsString(),
278 declaration->getLocation().printToString(source_manager()));
279
280 // TODO: Add support for classes defined in function/method bodies
281 if (declaration->isLocalClass() != nullptr)
282 return true;
283
284 auto template_specialization_ptr =
286
287 if (!template_specialization_ptr)
288 return true;
289
290 const auto class_full_name = template_specialization_ptr->full_name(false);
291 const auto id = common::to_id(class_full_name);
292
293 template_specialization_ptr->set_id(id);
294
295 set_unique_id(declaration->getID(), id);
296
297 if (!declaration->isCompleteDefinition()) {
298 forward_declarations_.emplace(
299 id, std::move(template_specialization_ptr));
300 return true;
301 }
302 forward_declarations_.erase(id);
303
304 if (diagram().should_include(*template_specialization_ptr)) {
305 LOG_DBG(
306 "Adding class template specialization participant {} with id {}",
307 class_full_name, id);
308
310 context().update(declaration);
311
312 diagram().add_participant(std::move(template_specialization_ptr));
313 }
314
315 return true;
316}

◆ VisitCXXConstructExpr()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitCXXConstructExpr ( clang::CXXConstructExpr *  expr)

Definition at line 1554 of file translation_unit_visitor.cc.

1556{
1562
1563 if (expr == nullptr)
1564 return true;
1565
1566 if (const auto *ctor = expr->getConstructor();
1567 ctor != nullptr && !should_include(ctor))
1568 return true;
1569
1570 LOG_TRACE("Visiting cxx construct expression at {} [caller_id = {}]",
1571 expr->getBeginLoc().printToString(source_manager()),
1572 context().caller_id());
1573
1574 message m{message_t::kCall, context().caller_id()};
1575
1576 m.in_static_declaration_context(within_static_variable_declaration_ > 0);
1577
1578 set_source_location(*expr, m);
1579
1580 if (context().is_expr_in_current_control_statement_condition(expr)) {
1581 m.set_message_scope(common::model::message_scope_t::kCondition);
1582 }
1583
1584 if (!process_construct_expression(m, expr))
1585 return true;
1586
1587 if (m.from().value() > 0 && m.to().value() > 0) {
1589
1590 diagram().add_active_participant(m.from());
1591 diagram().add_active_participant(m.to());
1592
1593 LOG_DBG("Found constructor call {} from {} [{}] to {} [{}] ",
1594 m.message_name(), m.from(), m.from(), m.to(), m.to());
1595
1596 push_message(expr, std::move(m));
1597 }
1598
1599 return true;
1600}

◆ VisitCXXMethodDecl()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitCXXMethodDecl ( clang::CXXMethodDecl *  declaration)

Definition at line 389 of file translation_unit_visitor.cc.

391{
392 if (!should_include(declaration))
393 return true;
394
395 if (!declaration->isThisDeclarationADefinition()) {
396 if (auto *declaration_definition = declaration->getDefinition();
397 declaration_definition != nullptr) {
398 if (auto *method_definition = clang::dyn_cast<clang::CXXMethodDecl>(
399 declaration_definition);
400 method_definition != nullptr) {
401 LOG_DBG("Calling VisitCXXMethodDecl recursively for forward "
402 "declaration");
403
404 return VisitCXXMethodDecl(method_definition);
405 }
406 }
407 }
408
409 LOG_TRACE("Visiting method {} in class {} [{}]",
410 declaration->getQualifiedNameAsString(),
411 declaration->getParent()->getQualifiedNameAsString(),
412 (void *)declaration->getParent());
413
414 context().update(declaration);
415
416 auto method_model_ptr = create_method_model(declaration);
417
418 if (!method_model_ptr)
419 return true;
420
421 process_comment(*declaration, *method_model_ptr);
422
423 set_source_location(*declaration, *method_model_ptr);
424
425 const auto method_full_name = method_model_ptr->full_name(false);
426
427 method_model_ptr->set_id(common::to_id(method_full_name));
428
429 // Callee methods in call expressions are referred to by first declaration
430 // id, so they should both be mapped to method_model
431 if (declaration->isThisDeclarationADefinition()) {
433 declaration->getFirstDecl()->getID(), method_model_ptr->id());
434 }
435
436 set_unique_id(declaration->getID(), method_model_ptr->id());
437
438 LOG_TRACE("Set id {} --> {} for method name {} [{}]", declaration->getID(),
439 method_model_ptr->id(), method_full_name,
440 declaration->isThisDeclarationADefinition());
441
442 context().update(declaration);
443
444 context().set_caller_id(method_model_ptr->id());
445
446 diagram().add_participant(std::move(method_model_ptr));
447
448 return true;
449}

◆ VisitCXXRecordDecl() [1/3]

bool clanguml::package_diagram::visitor::translation_unit_visitor::VisitCXXRecordDecl ( clang::CXXRecordDecl *  cls)
virtual

Definition at line 135 of file translation_unit_visitor.cc.

136{
137 assert(cls != nullptr);
138
139 // Skip system headers
140 if (source_manager().isInSystemHeader(cls->getSourceRange().getBegin()))
141 return true;
142
143 // Templated records are handled by VisitClassTemplateDecl()
144 if (cls->isTemplated() || cls->isTemplateDecl() ||
145 (clang::dyn_cast_or_null<clang::ClassTemplateSpecializationDecl>(cls) !=
146 nullptr))
147 return true;
148
149 found_relationships_t relationships;
150
151 if (cls->isCompleteDefinition()) {
152 process_class_declaration(*cls, relationships);
153 add_relationships(cls, relationships);
154 }
155
156 return true;
157}

◆ VisitCXXRecordDecl() [2/3]

bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitCXXRecordDecl ( clang::CXXRecordDecl *  d)
virtual

Definition at line 829 of file translation_unit_visitor.cc.

830{
831 if (!should_include(cls))
832 return true;
833
834 LOG_DBG("= Visiting class declaration {} at {}",
835 cls->getQualifiedNameAsString(),
836 cls->getLocation().printToString(source_manager()));
837
838 LOG_DBG(
839 "== getQualifiedNameAsString() = {}", cls->getQualifiedNameAsString());
840 if (cls->getOwningModule() != nullptr)
841 LOG_DBG(
842 "== getOwningModule()->Name = {}", cls->getOwningModule()->Name);
843 LOG_DBG("== getID() = {}", cls->getID());
844 LOG_DBG("== isTemplateDecl() = {}", cls->isTemplateDecl());
845 LOG_DBG("== isTemplated() = {}", cls->isTemplated());
846 LOG_DBG("== getParent()->isRecord()() = {}", cls->getParent()->isRecord());
847
848 if (const auto *parent_record =
849 clang::dyn_cast<clang::RecordDecl>(cls->getParent());
850 parent_record != nullptr) {
851 LOG_DBG("== getParent()->getQualifiedNameAsString() = {}",
852 parent_record->getQualifiedNameAsString());
853 }
854
855 if (has_processed_template_class(cls->getQualifiedNameAsString()))
856 // If we have already processed the template of this class
857 // skip it
858 return true;
859
860 if (cls->isTemplated() && (cls->getDescribedTemplate() != nullptr)) {
861 // If the described templated of this class is already in the model
862 // skip it:
863 const eid_t ast_id{cls->getDescribedTemplate()->getID()};
864 if (id_mapper().get_global_id(ast_id))
865 return true;
866 }
867
868 // TODO: Add support for classes defined in function/method bodies
869 if (cls->isLocalClass() != nullptr)
870 return true;
871
872 auto c_ptr = create_class_declaration(cls);
873
874 if (!c_ptr)
875 return true;
876
877 const auto cls_id = c_ptr->id();
878
879 id_mapper().add(cls->getID(), cls_id);
880
881 auto &class_model = diagram().find<class_>(cls_id).has_value()
882 ? *diagram().find<class_>(cls_id).get()
883 : *c_ptr;
884
885 if (cls->isCompleteDefinition() && !class_model.complete())
886 process_class_declaration(*cls, class_model);
887
888 auto id = class_model.id();
889 if (!cls->isCompleteDefinition()) {
890 forward_declarations_.emplace(id, std::move(c_ptr));
891 return true;
892 }
893 forward_declarations_.erase(id);
894
895 if (diagram().should_include(class_model)) {
896 LOG_DBG("Adding class {} with id {}", class_model, class_model.id());
897
898 add_class(std::move(c_ptr));
899 }
900 else {
901 LOG_DBG("Skipping class {} with id {}", class_model, class_model.id());
902 }
903
904 return true;
905}

◆ VisitCXXRecordDecl() [3/3]

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitCXXRecordDecl ( clang::CXXRecordDecl *  declaration)

Definition at line 156 of file translation_unit_visitor.cc.

158{
159 if (!should_include(declaration))
160 return true;
161
162 // Skip this class if it's parent template is already in the model
163 if (declaration->isTemplated() &&
164 declaration->getDescribedTemplate() != nullptr) {
165 if (get_unique_id(eid_t{declaration->getDescribedTemplate()->getID()}))
166 return true;
167 }
168
169 // TODO: Add support for classes defined in function/method bodies
170 if (declaration->isLocalClass() != nullptr)
171 return true;
172
173 LOG_TRACE("Visiting class declaration at {}",
174 declaration->getBeginLoc().printToString(source_manager()));
175
176 // Build the class declaration and store it in the diagram, even
177 // if we don't need it for any of the participants of this diagram
178 auto class_model_ptr = create_class_model(declaration);
179
180 if (!class_model_ptr)
181 return true;
182
183 context().reset();
184
185 const auto class_id = class_model_ptr->id();
186
187 set_unique_id(declaration->getID(), class_id);
188
189 auto &class_model =
190 diagram()
191 .get_participant<sequence_diagram::model::class_>(class_id)
192 .has_value()
193 ? *diagram()
194 .get_participant<sequence_diagram::model::class_>(class_id)
195 .get()
196 : *class_model_ptr;
197
198 if (!declaration->isCompleteDefinition()) {
199 forward_declarations_.emplace(class_id, std::move(class_model_ptr));
200 return true;
201 }
202
203 forward_declarations_.erase(class_id);
204
205 if (diagram().should_include(class_model)) {
206 LOG_DBG("Adding class participant {} with id {}",
207 class_model.full_name(false), class_model.id());
208
209 assert(class_model.id() == class_id);
210
211 context().set_caller_id(class_id);
212 context().update(declaration);
213
214 diagram().add_participant(std::move(class_model_ptr));
215 }
216 else {
217 LOG_DBG("Skipping class {} with id {}", class_model.full_name(true),
218 class_id);
219 }
220
221 return true;
222}

◆ VisitEnumDecl() [1/2]

bool clanguml::package_diagram::visitor::translation_unit_visitor::VisitEnumDecl ( clang::EnumDecl *  decl)
virtual

Definition at line 177 of file translation_unit_visitor.cc.

178{
179 assert(decl != nullptr);
180
181 // Skip system headers
182 if (source_manager().isInSystemHeader(decl->getSourceRange().getBegin()))
183 return true;
184
185 found_relationships_t relationships;
186
187 if (decl->isCompleteDefinition()) {
188 add_relationships(decl, relationships);
189 }
190
191 return true;
192}

◆ VisitEnumDecl() [2/2]

bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitEnumDecl ( clang::EnumDecl *  e)
virtual

Definition at line 127 of file translation_unit_visitor.cc.

128{
129 assert(enm != nullptr);
130
131 // Anonymous enum values are either class fields with type enum or
132 // `typedef enum` declarations
133 if (enm->getNameAsString().empty()) {
134 return true;
135 }
136
137 if (!should_include(enm))
138 return true;
139
140 LOG_DBG("= Visiting enum declaration {} at {}",
141 enm->getQualifiedNameAsString(),
142 enm->getLocation().printToString(source_manager()));
143
144 auto e_ptr = create_enum_declaration(enm, nullptr);
145
146 if (e_ptr && diagram().should_include(*e_ptr))
147 add_enum(std::move(e_ptr));
148
149 return true;
150}

◆ VisitFunctionDecl() [1/2]

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitFunctionDecl ( clang::FunctionDecl *  declaration)

Definition at line 467 of file translation_unit_visitor.cc.

469{
470 if (declaration->isCXXClassMember())
471 return true;
472
473 if (!should_include(declaration))
474 return true;
475
476 if (!declaration->isThisDeclarationADefinition()) {
477 if (auto *declaration_definition = declaration->getDefinition();
478 declaration_definition != nullptr)
479 return VisitFunctionDecl(
480 static_cast<clang::FunctionDecl *>(declaration_definition));
481 }
482
483 LOG_TRACE("Visiting function declaration {} at {}",
484 declaration->getQualifiedNameAsString(),
485 declaration->getLocation().printToString(source_manager()));
486
487 if (declaration->isTemplated()) {
488 if (declaration->getDescribedTemplate() != nullptr) {
489 // If the described templated of this function is already in the
490 // model skip it:
491 if (get_unique_id(
492 eid_t{declaration->getDescribedTemplate()->getID()}))
493 return true;
494 }
495 }
496
497 std::unique_ptr<model::function> function_model_ptr{};
498
499 if (declaration->isFunctionTemplateSpecialization()) {
500 function_model_ptr =
502 }
503 else {
504 function_model_ptr = build_function_model(*declaration);
505 }
506
507 if (!function_model_ptr)
508 return true;
509
510 function_model_ptr->set_id(
511 common::to_id(function_model_ptr->full_name(false)));
512
513 function_model_ptr->is_void(declaration->getReturnType()->isVoidType());
514
515 function_model_ptr->is_operator(declaration->isOverloadedOperator());
516
517 function_model_ptr->is_cuda_kernel(
518 common::has_attr(declaration, clang::attr::CUDAGlobal));
519
520 function_model_ptr->is_cuda_device(
521 common::has_attr(declaration, clang::attr::CUDADevice));
522
523 context().update(declaration);
524
525 context().set_caller_id(function_model_ptr->id());
526
527 if (declaration->isThisDeclarationADefinition()) {
529 declaration->getFirstDecl()->getID(), function_model_ptr->id());
530 }
531
532 set_unique_id(declaration->getID(), function_model_ptr->id());
533
534 process_comment(*declaration, *function_model_ptr);
535
536 set_source_location(*declaration, *function_model_ptr);
537
538 diagram().add_participant(std::move(function_model_ptr));
539
540 return true;
541}

◆ VisitFunctionDecl() [2/2]

bool clanguml::package_diagram::visitor::translation_unit_visitor::VisitFunctionDecl ( clang::FunctionDecl *  function_declaration)
virtual

Definition at line 109 of file translation_unit_visitor.cc.

111{
112 assert(function_declaration != nullptr);
113
114 // Skip system headers
115 if (source_manager().isInSystemHeader(
116 function_declaration->getSourceRange().getBegin()))
117 return true;
118
119 found_relationships_t relationships;
120
121 find_relationships(function_declaration,
122 function_declaration->getReturnType(), relationships);
123
124 for (const auto *param : function_declaration->parameters()) {
125 if (param != nullptr)
127 function_declaration, param->getType(), relationships);
128 }
129
130 add_relationships(function_declaration, relationships);
131
132 return true;
133}

◆ VisitFunctionTemplateDecl()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitFunctionTemplateDecl ( clang::FunctionTemplateDecl *  function_declaration)

Definition at line 559 of file translation_unit_visitor.cc.

561{
562 if (!should_include(declaration))
563 return true;
564
565 const auto function_name = declaration->getQualifiedNameAsString();
566
567 LOG_TRACE("Visiting function template declaration {} at {}", function_name,
568 declaration->getLocation().printToString(source_manager()));
569
570 auto function_template_model = build_function_template(*declaration);
571
572 process_comment(*declaration, *function_template_model);
573
574 set_source_location(*declaration, *function_template_model);
575 set_owning_module(*declaration, *function_template_model);
576
577 function_template_model->is_void(
578 declaration->getAsFunction()->getReturnType()->isVoidType());
579
580 function_template_model->set_id(
581 common::to_id(function_template_model->full_name(false)));
582
583 function_template_model->is_operator(
584 declaration->getAsFunction()->isOverloadedOperator());
585
586 context().update(declaration);
587
588 context().set_caller_id(function_template_model->id());
589
590 set_unique_id(declaration->getID(), function_template_model->id());
591
592 diagram().add_participant(std::move(function_template_model));
593
594 return true;
595}

◆ VisitLambdaExpr()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitLambdaExpr ( clang::LambdaExpr *  expr)

Definition at line 597 of file translation_unit_visitor.cc.

598{
599 if (!should_include(expr))
600 return true;
601
602 const auto lambda_full_name =
603 expr->getLambdaClass()->getCanonicalDecl()->getNameAsString();
604
605 LOG_TRACE("Visiting lambda expression {} at {} [caller_id = {}]",
606 lambda_full_name, expr->getBeginLoc().printToString(source_manager()),
607 context().caller_id());
608
609 LOG_TRACE("Lambda call operator ID {} - lambda class ID {}, class call "
610 "operator ID {}",
611 expr->getCallOperator()->getID(), expr->getLambdaClass()->getID(),
612 expr->getLambdaClass()->getLambdaCallOperator()->getID());
613
614 // Create lambda class participant
615 auto *cls = expr->getLambdaClass();
616 auto lambda_class_model_ptr = create_class_model(cls);
617
618 if (!lambda_class_model_ptr)
619 return true;
620
621 const auto cls_id = lambda_class_model_ptr->id();
622
623 set_unique_id(cls->getID(), cls_id);
624
625 auto lambda_method_model_ptr =
626 create_lambda_method_model(expr->getCallOperator());
627
628 lambda_method_model_ptr->set_class_id(cls_id);
629
630 // If this is a nested lambda, prepend the parent lambda name to this lambda
631 auto lambda_class_full_name = lambda_class_model_ptr->full_name(false);
632 lambda_method_model_ptr->set_class_full_name(lambda_class_full_name);
633
634 diagram().add_participant(std::move(lambda_class_model_ptr));
635
636 lambda_method_model_ptr->set_id(
637 common::to_id(get_participant(cls_id).value().full_name(false) +
638 "::" + lambda_method_model_ptr->full_name_no_ns()));
639
640 get_participant<model::class_>(cls_id).value().set_lambda_operator_id(
641 lambda_method_model_ptr->id());
642
643 // If lambda expression is in an argument to a method/function, and that
644 // method function would be excluded by filters
645 if (std::holds_alternative<clang::CallExpr *>(
646 context().current_callexpr()) &&
647 (!context().lambda_caller_id().has_value())) {
650
651 message m{message_t::kCall, context().caller_id()};
652 set_source_location(*expr, m);
653 m.set_from(context().caller_id());
654 m.set_to(lambda_method_model_ptr->id());
655
657
658 diagram().add_active_participant(m.from());
659 diagram().add_active_participant(m.to());
660
661 LOG_DBG("Found call {} from {} [{}] to {} [{}]", m.message_name(),
662 m.from(), m.from(), m.to(), m.to());
663
664 push_message(std::get<clang::CallExpr *>(context().current_callexpr()),
665 std::move(m));
666 }
667
668 context().enter_lambda_expression(lambda_method_model_ptr->id());
669
671 expr->getCallOperator()->getID(), lambda_method_model_ptr->id());
672
673 diagram().add_participant(std::move(lambda_method_model_ptr));
674
675 [[maybe_unused]] const auto is_generic_lambda = expr->isGenericLambda();
676
677 return true;
678}

◆ VisitNamespaceDecl() [1/2]

bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitNamespaceDecl ( clang::NamespaceDecl *  ns)
virtual

Definition at line 45 of file translation_unit_visitor.cc.

46{
47 assert(ns != nullptr);
48
49 if (config().package_type() == config::package_type_t::kDirectory)
50 return true;
51
52 if (ns->isAnonymousNamespace() || ns->isInline())
53 return true;
54
55 LOG_DBG("= Visiting namespace declaration {} at {}",
56 ns->getQualifiedNameAsString(),
57 ns->getLocation().printToString(source_manager()));
58
59 auto package_path = namespace_{common::get_qualified_name(*ns)};
60
61 auto package_parent = package_path;
62 bool is_root =
63 (package_path.size() == 1) && !config().using_namespace().is_empty();
64 package_path.is_root(is_root);
65
66 std::string name;
67 if (!package_path.is_empty())
68 name = package_path.name();
69
70 if (!package_parent.is_empty())
71 package_parent.pop_back();
72
73 const auto usn = config().using_namespace();
74
75 auto p = std::make_unique<common::model::package>(usn);
76 package_path = package_path.relative_to(usn);
77
78 p->set_name(name);
79 p->set_namespace(package_parent);
80 p->set_id(common::to_id(*ns));
81 p->is_root(is_root);
82 id_mapper().add(ns->getID(), p->id());
83
84 if (config().filter_mode() == config::filter_mode_t::advanced ||
85 (diagram().should_include(*p) && !diagram().get(p->id()))) {
86 process_comment(*ns, *p);
87 set_source_location(*ns, *p);
88
89 p->set_style(p->style_spec());
90
91 for (const auto *attr : ns->attrs()) {
92 if (attr->getKind() == clang::attr::Kind::Deprecated) {
93 p->set_deprecated(true);
94 break;
95 }
96 }
97
98 if (!p->skip()) {
99 diagram().add(package_path, std::move(p));
100 }
101 }
102
103 return true;
104}

◆ VisitNamespaceDecl() [2/2]

bool clanguml::package_diagram::visitor::translation_unit_visitor::VisitNamespaceDecl ( clang::NamespaceDecl *  ns)
virtual

Definition at line 45 of file translation_unit_visitor.cc.

46{
47 assert(ns != nullptr);
48
49 if (config().package_type() != config::package_type_t::kNamespace)
50 return true;
51
52 if (ns->isAnonymousNamespace() || ns->isInline())
53 return true;
54
55 auto qualified_name = common::get_qualified_name(*ns);
56
57 if (!diagram().should_include(namespace_{qualified_name}))
58 return true;
59
60 LOG_DBG("Visiting namespace declaration: {}", qualified_name);
61
62 auto package_path = namespace_{qualified_name};
63 auto package_parent = package_path;
64 bool is_root =
65 (package_path.size() == 1) && !config().using_namespace().is_empty();
66
67 std::string name;
68 if (!package_path.is_empty())
69 name = package_path.name();
70
71 if (!package_parent.is_empty())
72 package_parent.pop_back();
73
74 const auto usn = config().using_namespace();
75
76 auto p = std::make_unique<common::model::package>(usn);
77 package_path = package_path.relative_to(usn);
78
79 p->set_name(name);
80 p->set_namespace(package_parent);
81 p->is_root(is_root);
82 p->set_id(common::to_id(*ns));
83 set_source_location(*ns, *p);
84
85 assert(p->id().value() > 0);
86
87 if (diagram().should_include(*p) && !diagram().get(p->id())) {
88 process_comment(*ns, *p);
89
90 p->set_style(p->style_spec());
91
92 for (const auto *attr : ns->attrs()) {
93 if (attr->getKind() == clang::attr::Kind::Deprecated) {
94 p->set_deprecated(true);
95 break;
96 }
97 }
98
99 if (!p->skip()) {
100 LOG_DBG("Adding package {}", p->full_name(false));
101
102 diagram().add(p->path(), std::move(p));
103 }
104 }
105
106 return true;
107}

◆ VisitObjCCategoryDecl() [1/2]

bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitObjCCategoryDecl ( clang::ObjCCategoryDecl *  decl)
virtual

Definition at line 420 of file translation_unit_visitor.cc.

422{
423 if (!should_include(decl))
424 return true;
425
426 LOG_DBG("= Visiting ObjC category declaration {} at {}",
427 decl->getQualifiedNameAsString(),
428 decl->getLocation().printToString(source_manager()));
429
430 auto category_ptr = create_objc_category_declaration(decl);
431
432 if (!category_ptr)
433 return true;
434
435 const auto category_id = category_ptr->id();
436
437 id_mapper().add(decl->getID(), category_id);
438
439 auto &category_model =
440 diagram().find<objc_interface>(category_id).has_value()
441 ? *diagram().find<objc_interface>(category_id).get()
442 : *category_ptr;
443
444 process_objc_category_declaration(*decl, category_model);
445
446 if (diagram().should_include(category_model)) {
447 LOG_DBG("Adding ObjC category {} with id {}",
448 category_model.full_name(false), category_model.id());
449
450 add_objc_interface(std::move(category_ptr));
451 }
452 else {
453 LOG_DBG("Skipping ObjC category {} with id {}",
454 category_model.full_name(true), category_model.id());
455 }
456
457 return true;
458}

◆ VisitObjCCategoryDecl() [2/2]

bool clanguml::package_diagram::visitor::translation_unit_visitor::VisitObjCCategoryDecl ( clang::ObjCCategoryDecl *  decl)
virtual

Definition at line 216 of file translation_unit_visitor.cc.

218{
219 assert(decl != nullptr);
220
221 // Skip system headers
222 if (source_manager().isInSystemHeader(decl->getSourceRange().getBegin()))
223 return true;
224
225 found_relationships_t relationships;
226
227 const auto target_id = get_package_id(decl->getClassInterface());
228 relationships.emplace_back(target_id, relationship_t::kDependency, decl);
229
230 process_objc_container_children(*decl, relationships);
231 add_relationships(decl, relationships);
232
233 return true;
234}

◆ VisitObjCInterfaceDecl() [1/3]

bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitObjCInterfaceDecl ( clang::ObjCInterfaceDecl *  decl)
virtual

Definition at line 500 of file translation_unit_visitor.cc.

502{
503 if (!should_include(decl))
504 return true;
505
506 LOG_DBG("= Visiting ObjC interface declaration {} at {}",
507 decl->getQualifiedNameAsString(),
508 decl->getLocation().printToString(source_manager()));
509
510 auto interface_ptr = create_objc_interface_declaration(decl);
511
512 if (!interface_ptr)
513 return true;
514
515 const auto protocol_id = interface_ptr->id();
516
517 id_mapper().add(decl->getID(), protocol_id);
518
519 auto &interface_model =
520 diagram().find<objc_interface>(protocol_id).has_value()
521 ? *diagram().find<objc_interface>(protocol_id).get()
522 : *interface_ptr;
523
524 if (!interface_model.complete())
525 process_objc_interface_declaration(*decl, interface_model);
526
527 if (diagram().should_include(interface_model)) {
528 LOG_DBG("Adding ObjC interface {} with id {}",
529 interface_model.full_name(false), interface_model.id());
530
531 add_objc_interface(std::move(interface_ptr));
532 }
533 else {
534 LOG_DBG("Skipping ObjC interface {} with id {}",
535 interface_model.full_name(true), interface_model.id());
536 }
537
538 return true;
539}

◆ VisitObjCInterfaceDecl() [2/3]

bool clanguml::package_diagram::visitor::translation_unit_visitor::VisitObjCInterfaceDecl ( clang::ObjCInterfaceDecl *  decl)
virtual

Definition at line 257 of file translation_unit_visitor.cc.

259{
260 assert(decl != nullptr);
261
262 // Skip system headers
263 if (source_manager().isInSystemHeader(decl->getSourceRange().getBegin()))
264 return true;
265
266 found_relationships_t relationships;
267
268 for (const auto *protocol : decl->protocols()) {
269 process_interface_protocol(*protocol, relationships);
270 }
271
272 // Iterate over regular class fields
273 for (const auto *field : decl->ivars()) {
274 if (field != nullptr)
275 process_field(*field, relationships);
276 }
277
278 process_objc_container_children(*decl, relationships);
279
280 add_relationships(decl, relationships);
281
282 return true;
283}

◆ VisitObjCInterfaceDecl() [3/3]

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitObjCInterfaceDecl ( clang::ObjCInterfaceDecl *  interface_declaration)

Definition at line 106 of file translation_unit_visitor.cc.

108{
109 if (!should_include(declaration))
110 return true;
111
112 LOG_TRACE("Visiting ObjC interface declaration at {}",
113 declaration->getBeginLoc().printToString(source_manager()));
114
115 // Build the class declaration and store it in the diagram, even
116 // if we don't need it for any of the participants of this diagram
117 auto objc_interface_model_ptr = create_objc_interface_model(declaration);
118
119 if (!objc_interface_model_ptr)
120 return true;
121
122 context().reset();
123
124 const auto class_id = objc_interface_model_ptr->id();
125
126 set_unique_id(declaration->getID(), class_id);
127
128 auto &class_model =
129 diagram()
130 .get_participant<sequence_diagram::model::class_>(class_id)
131 .has_value()
132 ? *diagram()
133 .get_participant<sequence_diagram::model::class_>(class_id)
134 .get()
135 : *objc_interface_model_ptr;
136
137 if (diagram().should_include(class_model)) {
138 LOG_DBG("Adding ObjC interface participant {} with id {}",
139 class_model.full_name(false), class_model.id());
140
141 assert(class_model.id() == class_id);
142
143 context().set_caller_id(class_id);
144 context().update(declaration);
145
146 diagram().add_participant(std::move(objc_interface_model_ptr));
147 }
148 else {
149 LOG_DBG("Skipping ObjC interface {} with id {}",
150 class_model.full_name(true), class_id);
151 }
152
153 return true;
154}

◆ VisitObjCMessageExpr()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitObjCMessageExpr ( clang::ObjCMessageExpr *  expr)

Definition at line 1261 of file translation_unit_visitor.cc.

1263{
1269
1270 if (!context().valid() || context().get_ast_context() == nullptr)
1271 return true;
1272
1273 LOG_TRACE("Visiting ObjC message expression at {} [caller_id = {}]",
1274 expr->getBeginLoc().printToString(source_manager()),
1275 context().caller_id());
1276
1277 message m{message_t::kCall, context().caller_id()};
1278
1279 set_source_location(*expr, m);
1280
1281 const auto *raw_expr_comment = clanguml::common::get_expression_raw_comment(
1282 source_manager(), *context().get_ast_context(), expr);
1283 const auto stripped_comment = process_comment(
1284 raw_expr_comment, context().get_ast_context()->getDiagnostics(), m);
1285
1286 if (m.skip())
1287 return true;
1288
1289 auto generated_message_from_comment = generate_message_from_comment(m);
1290
1291 if (!generated_message_from_comment && !should_include(expr)) {
1292 LOG_DBG("Skipping call expression due to filter at: {}",
1293 expr->getBeginLoc().printToString(source_manager()));
1294
1295 processed_comments().erase(raw_expr_comment);
1296 return true;
1297 }
1298
1299 if (context().is_expr_in_current_control_statement_condition(expr)) {
1300 m.set_message_scope(common::model::message_scope_t::kCondition);
1301 }
1302
1303 if (generated_message_from_comment) {
1304 LOG_DBG(
1305 "Message for this call expression is taken from comment directive");
1306 return true;
1307 }
1308
1310
1311 // Add message to diagram
1312 if (m.from().value() > 0 && m.to().value() > 0) {
1313 if (raw_expr_comment != nullptr)
1314 m.set_comment(raw_expr_comment->getBeginLoc().getHashValue(),
1315 stripped_comment);
1316
1318
1319 diagram().add_active_participant(m.from());
1320 diagram().add_active_participant(m.to());
1321
1322 LOG_DBG("Found ObjC message {} from {} [{}] to {} [{}] ",
1323 m.message_name(), m.from(), m.from(), m.to(), m.to());
1324
1325 push_message(expr, std::move(m));
1326 }
1327
1328 return true;
1329}

◆ VisitObjCMethodDecl()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitObjCMethodDecl ( clang::ObjCMethodDecl *  declaration)

Definition at line 334 of file translation_unit_visitor.cc.

336{
337 if (!should_include(declaration))
338 return true;
339
340 LOG_TRACE("Visiting ObjC method {} in class",
341 declaration->getQualifiedNameAsString());
342
343 context().update(declaration);
344
345 auto method_model_ptr = create_objc_method_model(declaration);
346
347 if (!method_model_ptr)
348 return true;
349
350 process_comment(*declaration, *method_model_ptr);
351
352 set_source_location(*declaration, *method_model_ptr);
353
354 const auto method_full_name = method_model_ptr->full_name(false);
355
356 method_model_ptr->set_id(common::to_id(method_full_name));
357
358 set_unique_id(declaration->getID(), method_model_ptr->id());
359
360 LOG_TRACE("Set id {} --> {} for method name {} [{}]", declaration->getID(),
361 method_model_ptr->id(), method_full_name,
362 declaration->isThisDeclarationADefinition());
363
364 context().update(declaration);
365
366 context().set_caller_id(method_model_ptr->id());
367
368 diagram().add_participant(std::move(method_model_ptr));
369
370 return true;
371}

◆ VisitObjCPropertyRefExpr()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitObjCPropertyRefExpr ( clang::ObjCPropertyRefExpr *  expr)

Definition at line 1331 of file translation_unit_visitor.cc.

1333{
1339
1340 if (!context().valid() || context().get_ast_context() == nullptr)
1341 return true;
1342
1343 LOG_TRACE("Visiting ObjC property ref expression at {} [caller_id = {}]",
1344 expr->getBeginLoc().printToString(source_manager()),
1345 context().caller_id());
1346
1347 return true;
1348}

◆ VisitObjCProtocolDecl() [1/3]

bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitObjCProtocolDecl ( clang::ObjCProtocolDecl *  decl)
virtual

Definition at line 460 of file translation_unit_visitor.cc.

462{
463 if (!should_include(decl))
464 return true;
465
466 LOG_DBG("= Visiting ObjC protocol declaration {} at {}",
467 decl->getQualifiedNameAsString(),
468 decl->getLocation().printToString(source_manager()));
469
470 auto protocol_ptr = create_objc_protocol_declaration(decl);
471
472 if (!protocol_ptr)
473 return true;
474
475 const auto protocol_id = protocol_ptr->id();
476
477 id_mapper().add(decl->getID(), protocol_id);
478
479 auto &protocol_model =
480 diagram().find<objc_interface>(protocol_id).has_value()
481 ? *diagram().find<objc_interface>(protocol_id).get()
482 : *protocol_ptr;
483
484 process_objc_protocol_declaration(*decl, protocol_model);
485
486 if (diagram().should_include(protocol_model)) {
487 LOG_DBG("Adding ObjC protocol {} with id {}",
488 protocol_model.full_name(false), protocol_model.id());
489
490 add_objc_interface(std::move(protocol_ptr));
491 }
492 else {
493 LOG_DBG("Skipping ObjC protocol {} with id {}",
494 protocol_model.full_name(true), protocol_model.id());
495 }
496
497 return true;
498}

◆ VisitObjCProtocolDecl() [2/3]

bool clanguml::package_diagram::visitor::translation_unit_visitor::VisitObjCProtocolDecl ( clang::ObjCProtocolDecl *  decl)
virtual

Definition at line 236 of file translation_unit_visitor.cc.

238{
239 assert(decl != nullptr);
240
241 // Skip system headers
242 if (source_manager().isInSystemHeader(decl->getSourceRange().getBegin()))
243 return true;
244
245 found_relationships_t relationships;
246
247 for (const auto *protocol : decl->protocols()) {
248 process_interface_protocol(*protocol, relationships);
249 }
250
251 process_objc_container_children(*decl, relationships);
252 add_relationships(decl, relationships);
253
254 return true;
255}

◆ VisitObjCProtocolDecl() [3/3]

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::VisitObjCProtocolDecl ( clang::ObjCProtocolDecl *  protocol_declaration)

Definition at line 58 of file translation_unit_visitor.cc.

60{
61 if (!should_include(declaration))
62 return true;
63
64 LOG_TRACE("Visiting ObjC interface declaration at {}",
65 declaration->getBeginLoc().printToString(source_manager()));
66
67 auto objc_protocol_model_ptr = create_objc_protocol_model(declaration);
68
69 if (!objc_protocol_model_ptr)
70 return true;
71
72 context().reset();
73
74 const auto class_id = objc_protocol_model_ptr->id();
75
76 set_unique_id(declaration->getID(), class_id);
77
78 auto &class_model =
79 diagram()
80 .get_participant<sequence_diagram::model::class_>(class_id)
81 .has_value()
82 ? *diagram()
83 .get_participant<sequence_diagram::model::class_>(class_id)
84 .get()
85 : *objc_protocol_model_ptr;
86
87 if (diagram().should_include(class_model)) {
88 LOG_DBG("Adding ObjC protocol participant {} with id {}",
89 class_model.full_name(false), class_model.id());
90
91 assert(class_model.id() == class_id);
92
93 context().set_caller_id(class_id);
94 context().update(declaration);
95
96 diagram().add_participant(std::move(objc_protocol_model_ptr));
97 }
98 else {
99 LOG_DBG("Skipping ObjC protocol {} with id {}",
100 class_model.full_name(true), class_id);
101 }
102
103 return true;
104}

◆ VisitRecordDecl() [1/2]

bool clanguml::package_diagram::visitor::translation_unit_visitor::VisitRecordDecl ( clang::RecordDecl *  cls)
virtual

Definition at line 159 of file translation_unit_visitor.cc.

160{
161 assert(decl != nullptr);
162
163 // Skip system headers
164 if (source_manager().isInSystemHeader(decl->getSourceRange().getBegin()))
165 return true;
166
167 found_relationships_t relationships;
168
169 if (decl->isCompleteDefinition()) {
170 process_record_children(*decl, relationships);
171 add_relationships(decl, relationships);
172 }
173
174 return true;
175}

◆ VisitRecordDecl() [2/2]

bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitRecordDecl ( clang::RecordDecl *  D)
virtual

Definition at line 367 of file translation_unit_visitor.cc.

368{
369 if (clang::dyn_cast_or_null<clang::CXXRecordDecl>(rec) != nullptr)
370 // This is handled by VisitCXXRecordDecl()
371 return true;
372
373 // It seems we are in a C (not C++) translation unit
374 if (!should_include(rec))
375 return true;
376
377 LOG_DBG("= Visiting record declaration {} at {}",
378 rec->getQualifiedNameAsString(),
379 rec->getLocation().printToString(source_manager()));
380
381 auto record_ptr = create_record_declaration(rec);
382
383 if (!record_ptr)
384 return true;
385
386 const auto rec_id = record_ptr->id();
387
388 id_mapper().add(rec->getID(), rec_id);
389
390 auto &record_model = diagram().find<class_>(rec_id).has_value()
391 ? *diagram().find<class_>(rec_id).get()
392 : *record_ptr;
393
394 if (rec->isCompleteDefinition() && !record_model.complete()) {
395 process_record_members(rec, record_model);
396 record_model.complete(true);
397 }
398
399 auto id = record_model.id();
400 if (!rec->isCompleteDefinition()) {
401 forward_declarations_.emplace(id, std::move(record_ptr));
402 return true;
403 }
404 forward_declarations_.erase(id);
405
406 if (diagram().should_include(record_model)) {
407 LOG_DBG("Adding struct/union {} with id {}",
408 record_model.full_name(false), record_model.id());
409
410 add_class(std::move(record_ptr));
411 }
412 else {
413 LOG_DBG("Skipping struct/union {} with id {}",
414 record_model.full_name(true), record_model.id());
415 }
416
417 return true;
418}

◆ VisitTypeAliasTemplateDecl()

bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitTypeAliasTemplateDecl ( clang::TypeAliasTemplateDecl *  cls)
virtual

Definition at line 271 of file translation_unit_visitor.cc.

273{
274 if (!should_include(cls))
275 return true;
276
277 LOG_DBG("= Visiting template type alias declaration {} at {}",
278 cls->getQualifiedNameAsString(),
279 cls->getLocation().printToString(source_manager()));
280
281 const auto *template_type_specialization_ptr =
282 cls->getTemplatedDecl()
283 ->getUnderlyingType()
284 ->getAs<clang::TemplateSpecializationType>();
285
286 if (template_type_specialization_ptr == nullptr)
287 return true;
288
289 auto template_specialization_ptr =
290 std::make_unique<class_>(config().using_namespace());
292 *template_specialization_ptr, cls, *template_type_specialization_ptr);
293
294 template_specialization_ptr->is_template(true);
295
296 if (diagram().should_include(*template_specialization_ptr)) {
297 const auto name = template_specialization_ptr->full_name(true);
298 const auto id = template_specialization_ptr->id();
299
300 LOG_DBG("Adding class {} with id {}", name, id);
301
302 set_source_location(*cls, *template_specialization_ptr);
303 set_owning_module(*cls, *template_specialization_ptr);
304
305 add_class(std::move(template_specialization_ptr));
306 }
307
308 return true;
309}

◆ VisitTypedefDecl()

bool clanguml::class_diagram::visitor::translation_unit_visitor::VisitTypedefDecl ( clang::TypedefDecl *  decl)
virtual

Definition at line 106 of file translation_unit_visitor.cc.

107{
108 if (const auto *enm = common::get_typedef_enum_decl(decl)) {
109 // Associate a typedef with an anonymous declaration so that it can
110 // be later used to assign proper name to enum
111 if (!should_include(enm))
112 return true;
113
114 LOG_DBG("= Visiting typedef enum declaration {} at {}",
115 enm->getQualifiedNameAsString(),
116 enm->getLocation().printToString(source_manager()));
117
118 auto e_ptr = create_enum_declaration(enm, decl);
119
120 if (e_ptr && diagram().should_include(*e_ptr))
121 add_enum(std::move(e_ptr));
122 }
123
124 return true; // Continue traversing
125}