Branch data Line data Source code
1 : : /* Sets of function names.
2 : : Copyright (C) 2019-2024 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 : 82299 : function_set::contains_name_p (const char *name) const
36 : : {
37 : : /* Binary search. */
38 : 82299 : int min = 0;
39 : 82299 : int max = m_count - 1;
40 : 382549 : while (true)
41 : : {
42 : 382549 : if (min > max)
43 : : return false;
44 : 301952 : int midpoint = (min + max) / 2;
45 : 301952 : gcc_assert ((size_t)midpoint < m_count);
46 : 301952 : int cmp = strcmp (name, m_names[midpoint]);
47 : 301952 : if (cmp == 0)
48 : : return true;
49 : 300250 : else if (cmp < 0)
50 : 204385 : max = midpoint - 1;
51 : : else
52 : 95865 : min = midpoint + 1;
53 : : }
54 : : }
55 : :
56 : : /* Return true if FNDECL is within this set. */
57 : :
58 : : bool
59 : 88237 : function_set::contains_decl_p (tree fndecl) const
60 : : {
61 : 88237 : gcc_assert (fndecl && DECL_P (fndecl));
62 : 88237 : if (!maybe_special_function_p (fndecl))
63 : : return false;
64 : 81883 : 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 (NULL, 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 */
|