1 /* Sets of function names. 2 Copyright (C) 2019-2020 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 function_set::contains_name_p (const char *name) const 36 { 37 /* Binary search. */ 38 int min = 0; 39 int max = m_count - 1; 40 while (true) 41 { 42 if (min > max) 43 return false; 44 int midpoint = (min + max) / 2; 45 gcc_assert ((size_t)midpoint < m_count); 46 int cmp = strcmp (name, m_names[midpoint]); 47 if (cmp == 0) 48 return true; 49 else if (cmp < 0) 50 max = midpoint - 1; 51 else 52 min = midpoint + 1; 53 } 54 } 55 56 /* Return true if FNDECL is within this set. */ 57 58 bool 59 function_set::contains_decl_p (tree fndecl) const 60 { 61 gcc_assert (fndecl && DECL_P (fndecl)); 62 if (!maybe_special_function_p (fndecl)) 63 return false; 64 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 function_set::assert_sorted () const 71 { 72 #if CHECKING_P 73 for (size_t idx = 1; idx < m_count; idx++) 74 gcc_assert (strcmp (m_names[idx - 1], m_names[idx]) < 0); 75 #endif /* #if CHECKING_P */ 76 } 77 78 /* Assert that contains_p is true for all members of the set. */ 79 80 void 81 function_set::assert_sane () const 82 { 83 #if CHECKING_P 84 for (size_t i = 0; i < m_count; i++) 85 gcc_assert (contains_name_p (m_names[i])); 86 #endif /* #if CHECKING_P */ 87 } 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 test_empty () 97 { 98 function_set fs (NULL, 0); 99 fs.assert_sorted (); 100 fs.assert_sane (); 101 ASSERT_FALSE (fs.contains_name_p ("")); 102 ASSERT_FALSE (fs.contains_name_p ("haystack")); 103 } 104 105 /* Verify that a function_set with an odd number of elements works as 106 expected. */ 107 108 static void 109 test_odd () 110 { 111 static const char * const names[3] = {"alpha", "beta", "gamma"}; 112 function_set fs (names, 3); 113 fs.assert_sorted (); 114 fs.assert_sane (); 115 ASSERT_FALSE (fs.contains_name_p ("")); 116 ASSERT_FALSE (fs.contains_name_p ("haystack")); 117 } 118 119 /* Verify that a function_set with an even number of elements works as 120 expected. */ 121 122 static void 123 test_even () 124 { 125 static const char * const names[3] = {"alpha", "beta"}; 126 function_set fs (names, 2); 127 fs.assert_sorted (); 128 fs.assert_sane (); 129 ASSERT_FALSE (fs.contains_name_p ("")); 130 ASSERT_FALSE (fs.contains_name_p ("haystack")); 131 } 132 133 /* Verify that a function_set with some nontrivial stdio.h data works as 134 expected. */ 135 136 static void 137 test_stdio_example () 138 { 139 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 const size_t count = sizeof(example) / sizeof (example[0]); 170 function_set fs (example, count); 171 fs.assert_sorted (); 172 fs.assert_sane (); 173 /* Examples of strings not present: before, after and alongside the 174 sorted list. */ 175 ASSERT_FALSE (fs.contains_name_p ("___")); 176 ASSERT_FALSE (fs.contains_name_p ("Z")); 177 ASSERT_FALSE (fs.contains_name_p ("fgets_WITH_A_PREFIX")); 178 } 179 180 /* Run all of the selftests within this file. */ 181 182 void 183 analyzer_function_set_cc_tests () 184 { 185 test_empty (); 186 test_odd (); 187 test_even (); 188 test_stdio_example (); 189 } 190 191 } // namespace selftest 192 193 #endif /* CHECKING_P */ 194 195 } // namespace ana 196 197 #endif /* #if ENABLE_ANALYZER */ 198