@@ -31,57 +31,84 @@ template <typename Derived> class ICFGBase {
3131 " An ICFG must also be a CFG" );
3232 }
3333
34+ // / Returns an iterable range of all function definitions or declarations in
35+ // / the ICFG
3436 [[nodiscard]] decltype (auto ) getAllFunctions() const {
3537 return self ().getAllFunctionsImpl ();
3638 }
3739
40+ // / returns the function definition or declaration with the given name. If
41+ // / ther eis no such function, returns a default constructed f_t (nullptr for
42+ // / pointers).
3843 [[nodiscard]] f_t getFunction (llvm::StringRef Fun) const {
3944 return self ().getFunctionImpl (Fun);
4045 }
4146
47+ // / Returns true, iff the given instruction is a call-site where the callee is
48+ // / called via a function-pointer or another kind of virtual call.
49+ // / NOTE: Trivial cases where a bitcast of a function is called may still
50+ // / count as indirect call.
4251 [[nodiscard]] bool isIndirectFunctionCall (ByConstRef<n_t > Inst) const {
4352 return self ().isIndirectFunctionCallImpl (Inst);
4453 }
54+ // / Returns true, iff the given instruction is a call-site where the callee is
55+ // / called via virtual dispatch. NOTE: Here, a class-hierarchy is required and
56+ // / a simple function-pointer is not sufficient.
4557 [[nodiscard]] bool isVirtualFunctionCall (ByConstRef<n_t > Inst) const {
4658 return self ().isVirtualFunctionCallImpl (Inst);
4759 }
60+ // / Returns an iterable range of all instructions in all functions of the ICFG
61+ // / that are neither call-sites nor start-points of a function
4862 [[nodiscard]] decltype (auto ) allNonCallStartNodes() const {
4963 static_assert (
5064 is_iterable_over_v<decltype (self ().allNonCallStartNodesImpl ()), n_t >);
5165 return self ().allNonCallStartNodesImpl ();
5266 }
67+ // / Returns an iterable range of all possible callee candidates at the given
68+ // / call-site induced by the used call-graph. NOTE: This function is typically
69+ // / called in a hot part of the analysis any should therefore be very fast
5370 [[nodiscard]] decltype (auto ) getCalleesOfCallAt(ByConstRef<n_t > Inst) const {
5471 static_assert (
5572 is_iterable_over_v<decltype (self ().getCalleesOfCallAtImpl (Inst)), f_t >);
5673 return self ().getCalleesOfCallAtImpl (Inst);
5774 }
75+ // / Returns an iterable range of all possible call-site candidates that may
76+ // / call the given function induced by the used call-graph.
5877 [[nodiscard]] decltype (auto ) getCallersOf(ByConstRef<f_t > Fun) const {
5978 static_assert (
6079 is_iterable_over_v<decltype (self ().getCallersOfImpl (Fun)), n_t >);
6180 return self ().getCallersOfImpl (Fun);
6281 }
82+ // / Returns an iterable range of all call-instruction in the given function
6383 [[nodiscard]] decltype (auto ) getCallsFromWithin(ByConstRef<f_t > Fun) const {
6484 static_assert (
6585 is_iterable_over_v<decltype (self ().getCallsFromWithinImpl (Fun)), n_t >);
6686 return self ().getCallsFromWithinImpl (Fun);
6787 }
88+ // / Returns an iterable range of all return-sites of the given
89+ // / call-instruction. Often the same as getSuccsOf. NOTE: This function is
90+ // / typically called in a hot part of the analysis and should therefore be
91+ // / very fast
6892 [[nodiscard]] decltype (auto )
6993 getReturnSitesOfCallAt (ByConstRef<n_t > Inst) const {
7094 static_assert (
7195 is_iterable_over_v<decltype (self ().getReturnSitesOfCallAtImpl (Inst)),
7296 n_t >);
7397 return self ().getReturnSitesOfCallAtImpl (Inst);
7498 }
99+ // / Returns an iterable range of all global initializer functions
75100 [[nodiscard]] decltype (auto )
76101 getGlobalInitializers (ByConstRef<f_t > Fun) const {
77102 static_assert (
78103 is_iterable_over_v<decltype (self ().getGlobalInitializersImpl (Fun)),
79104 f_t >);
80105 return self ().getGlobalInitializersImpl (Fun);
81106 }
107+ // / Prints the underlying call-graph as DOT to the given output-stream
82108 void print (llvm::raw_ostream &OS = llvm::outs()) const {
83109 self ().printImpl (OS);
84110 }
111+ // / Returns the underlying call-graph as JSON
85112 [[nodiscard]] nlohmann::json getAsJson () const {
86113 return self ().getAsJsonImpl ();
87114 }
@@ -93,7 +120,10 @@ template <typename Derived> class ICFGBase {
93120 }
94121};
95122
123+ // / True, iff ICF is a proper instantiation of ICFGBase with n_t and f_t taken
124+ // / from the given analysis-Domain
96125template <typename ICF, typename Domain>
126+ // NOLINTNEXTLINE(readability-identifier-naming)
97127constexpr bool is_icfg_v = is_crtp_base_of_v<ICFGBase, ICF>
98128 &&std::is_same_v<typename ICF::n_t , typename Domain::n_t >
99129 &&std::is_same_v<typename ICF::f_t , typename Domain::f_t >;
0 commit comments