Line data Source code
1 : /* Sets of function names.
2 : Copyright (C) 2019-2026 Free Software Foundation, Inc.
3 : Contributed by David Malcolm <dmalcolm@redhat.com>.
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify it
8 : under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3, or (at your option)
10 : any later version.
11 :
12 : GCC is distributed in the hope that it will be useful, but
13 : WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with GCC; see the file COPYING3. If not see
19 : <http://www.gnu.org/licenses/>. */
20 :
21 : #include "config.h"
22 : #include "system.h"
23 : #include "coretypes.h"
24 : #include "tree.h"
25 : #include "selftest.h"
26 : #include "analyzer/function-set.h"
27 :
28 : #if ENABLE_ANALYZER
29 :
30 : namespace ana {
31 :
32 : /* Return true if NAME is within this set. */
33 :
34 : bool
35 77805 : function_set::contains_name_p (const char *name) const
36 : {
37 : /* Binary search. */
38 77805 : int min = 0;
39 77805 : int max = m_count - 1;
40 348945 : while (true)
41 : {
42 348945 : if (min > max)
43 : return false;
44 272368 : int midpoint = (min + max) / 2;
45 272368 : gcc_assert ((size_t)midpoint < m_count);
46 272368 : int cmp = strcmp (name, m_names[midpoint]);
47 272368 : if (cmp == 0)
48 : return true;
49 271140 : else if (cmp < 0)
50 193330 : max = midpoint - 1;
51 : else
52 77810 : min = midpoint + 1;
53 : }
54 : }
55 :
56 : /* Return true if FNDECL is within this set. */
57 :
58 : bool
59 78279 : function_set::contains_decl_p (tree fndecl) const
60 : {
61 78279 : gcc_assert (fndecl && DECL_P (fndecl));
62 78279 : if (!maybe_special_function_p (fndecl))
63 : return false;
64 77389 : return contains_name_p (IDENTIFIER_POINTER (DECL_NAME (fndecl)));
65 : }
66 :
67 : /* Assert that the list of names is in sorted order. */
68 :
69 : void
70 24 : function_set::assert_sorted () const
71 : {
72 : #if CHECKING_P
73 380 : for (size_t idx = 1; idx < m_count; idx++)
74 356 : gcc_assert (strcmp (m_names[idx - 1], m_names[idx]) < 0);
75 : #endif /* #if CHECKING_P */
76 24 : }
77 :
78 : /* Assert that contains_p is true for all members of the set. */
79 :
80 : void
81 24 : function_set::assert_sane () const
82 : {
83 : #if CHECKING_P
84 400 : for (size_t i = 0; i < m_count; i++)
85 376 : gcc_assert (contains_name_p (m_names[i]));
86 : #endif /* #if CHECKING_P */
87 24 : }
88 :
89 : #if CHECKING_P
90 :
91 : namespace selftest {
92 :
93 : /* Verify that an empty function_set works as expected. */
94 :
95 : static void
96 4 : test_empty ()
97 : {
98 4 : function_set fs (nullptr, 0);
99 4 : fs.assert_sorted ();
100 4 : fs.assert_sane ();
101 4 : ASSERT_FALSE (fs.contains_name_p (""));
102 4 : ASSERT_FALSE (fs.contains_name_p ("haystack"));
103 4 : }
104 :
105 : /* Verify that a function_set with an odd number of elements works as
106 : expected. */
107 :
108 : static void
109 4 : test_odd ()
110 : {
111 4 : static const char * const names[3] = {"alpha", "beta", "gamma"};
112 4 : function_set fs (names, 3);
113 4 : fs.assert_sorted ();
114 4 : fs.assert_sane ();
115 4 : ASSERT_FALSE (fs.contains_name_p (""));
116 4 : ASSERT_FALSE (fs.contains_name_p ("haystack"));
117 4 : }
118 :
119 : /* Verify that a function_set with an even number of elements works as
120 : expected. */
121 :
122 : static void
123 4 : test_even ()
124 : {
125 4 : static const char * const names[3] = {"alpha", "beta"};
126 4 : function_set fs (names, 2);
127 4 : fs.assert_sorted ();
128 4 : fs.assert_sane ();
129 4 : ASSERT_FALSE (fs.contains_name_p (""));
130 4 : ASSERT_FALSE (fs.contains_name_p ("haystack"));
131 4 : }
132 :
133 : /* Verify that a function_set with some nontrivial stdio.h data works as
134 : expected. */
135 :
136 : static void
137 4 : test_stdio_example ()
138 : {
139 4 : static const char * const example[] = {
140 : "__fbufsize",
141 : "__flbf",
142 : "__fpending",
143 : "__fpurge",
144 : "__freadable",
145 : "__freading",
146 : "__fsetlocking",
147 : "__fwritable",
148 : "__fwriting",
149 : "clearerr_unlocked",
150 : "feof_unlocked",
151 : "ferror_unlocked",
152 : "fflush_unlocked",
153 : "fgetc_unlocked",
154 : "fgets",
155 : "fgets_unlocked",
156 : "fgetwc_unlocked",
157 : "fgetws_unlocked",
158 : "fileno_unlocked",
159 : "fputc_unlocked",
160 : "fputs_unlocked",
161 : "fputwc_unlocked",
162 : "fputws_unlocked",
163 : "fread_unlocked",
164 : "fwrite_unlocked",
165 : "getc_unlocked",
166 : "getwc_unlocked",
167 : "putc_unlocked"
168 : };
169 4 : const size_t count = ARRAY_SIZE (example);
170 4 : function_set fs (example, count);
171 4 : fs.assert_sorted ();
172 4 : fs.assert_sane ();
173 : /* Examples of strings not present: before, after and alongside the
174 : sorted list. */
175 4 : ASSERT_FALSE (fs.contains_name_p ("___"));
176 4 : ASSERT_FALSE (fs.contains_name_p ("Z"));
177 4 : ASSERT_FALSE (fs.contains_name_p ("fgets_WITH_A_PREFIX"));
178 4 : }
179 :
180 : /* Run all of the selftests within this file. */
181 :
182 : void
183 4 : analyzer_function_set_cc_tests ()
184 : {
185 4 : test_empty ();
186 4 : test_odd ();
187 4 : test_even ();
188 4 : test_stdio_example ();
189 4 : }
190 :
191 : } // namespace selftest
192 :
193 : #endif /* CHECKING_P */
194 :
195 : } // namespace ana
196 :
197 : #endif /* #if ENABLE_ANALYZER */
|