GCC with patches for OS216
Revision | a6b5f19c37001d7c9974248ffcb65aadba33283c (tree) |
---|---|
Zeit | 2020-01-15 08:51:44 |
Autor | David Malcolm <dmalcolm@redh...> |
Commiter | David Malcolm |
analyzer: add function-set.cc/h
This patch adds a simple mechanism for tracking sets of functions
for which a particular property holds, as a pragmatic way to build
knowledge about important APIs into the analyzer without requiring
markup of the user's libc.
gcc/ChangeLog:
* Makefile.in (ANALYZER_OBJS): Add analyzer/function-set.o.
gcc/analyzer/ChangeLog:
* analyzer-selftests.cc (selftest::run_analyzer_selftests): Call
selftest::analyzer_function_set_cc_tests.
* analyzer-selftests.h (selftest::analyzer_function_set_cc_tests):
New decl.
* function-set.cc: New file.
* function-set.h: New file.
@@ -1,3 +1,7 @@ | ||
1 | +2020-01-14 David Malcolm <dmalcolm@redhat.com> | |
2 | + | |
3 | + * Makefile.in (ANALYZER_OBJS): Add analyzer/function-set.o. | |
4 | + | |
1 | 5 | 2020-01-15 Jakub Jelinek <jakub@redhat.com> |
2 | 6 | |
3 | 7 | PR target/93009 |
@@ -1226,6 +1226,7 @@ ANALYZER_OBJS = \ | ||
1226 | 1226 | analyzer/constraint-manager.o \ |
1227 | 1227 | analyzer/diagnostic-manager.o \ |
1228 | 1228 | analyzer/engine.o \ |
1229 | + analyzer/function-set.o \ | |
1229 | 1230 | analyzer/pending-diagnostic.o \ |
1230 | 1231 | analyzer/program-point.o \ |
1231 | 1232 | analyzer/program-state.o \ |
@@ -1,5 +1,14 @@ | ||
1 | 1 | 2020-01-14 David Malcolm <dmalcolm@redhat.com> |
2 | 2 | |
3 | + * analyzer-selftests.cc (selftest::run_analyzer_selftests): Call | |
4 | + selftest::analyzer_function_set_cc_tests. | |
5 | + * analyzer-selftests.h (selftest::analyzer_function_set_cc_tests): | |
6 | + New decl. | |
7 | + * function-set.cc: New file. | |
8 | + * function-set.h: New file. | |
9 | + | |
10 | +2020-01-14 David Malcolm <dmalcolm@redhat.com> | |
11 | + | |
3 | 12 | * analyzer.h (fndecl_has_gimple_body_p): New decl. |
4 | 13 | * engine.cc (impl_region_model_context::on_unknown_change): New |
5 | 14 | function. |
@@ -50,6 +50,7 @@ run_analyzer_selftests () | ||
50 | 50 | { |
51 | 51 | #if ENABLE_ANALYZER |
52 | 52 | analyzer_constraint_manager_cc_tests (); |
53 | + analyzer_function_set_cc_tests (); | |
53 | 54 | analyzer_program_point_cc_tests (); |
54 | 55 | analyzer_program_state_cc_tests (); |
55 | 56 | analyzer_region_model_cc_tests (); |
@@ -33,6 +33,7 @@ extern void run_analyzer_selftests (); | ||
33 | 33 | alphabetical order. */ |
34 | 34 | extern void analyzer_checker_script_cc_tests (); |
35 | 35 | extern void analyzer_constraint_manager_cc_tests (); |
36 | +extern void analyzer_function_set_cc_tests (); | |
36 | 37 | extern void analyzer_program_point_cc_tests (); |
37 | 38 | extern void analyzer_program_state_cc_tests (); |
38 | 39 | extern void analyzer_region_model_cc_tests (); |
@@ -0,0 +1,191 @@ | ||
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 | +/* Return true if NAME is within this set. */ | |
31 | + | |
32 | +bool | |
33 | +function_set::contains_name_p (const char *name) const | |
34 | +{ | |
35 | + /* Binary search. */ | |
36 | + int min = 0; | |
37 | + int max = m_count - 1; | |
38 | + while (true) | |
39 | + { | |
40 | + if (min > max) | |
41 | + return false; | |
42 | + int midpoint = (min + max) / 2; | |
43 | + gcc_assert ((size_t)midpoint < m_count); | |
44 | + int cmp = strcmp (name, m_names[midpoint]); | |
45 | + if (cmp == 0) | |
46 | + return true; | |
47 | + else if (cmp < 0) | |
48 | + max = midpoint - 1; | |
49 | + else | |
50 | + min = midpoint + 1; | |
51 | + } | |
52 | +} | |
53 | + | |
54 | +/* Return true if FNDECL is within this set. */ | |
55 | + | |
56 | +bool | |
57 | +function_set::contains_decl_p (tree fndecl) const | |
58 | +{ | |
59 | + gcc_assert (fndecl && DECL_P (fndecl)); | |
60 | + return contains_name_p (IDENTIFIER_POINTER (DECL_NAME (fndecl))); | |
61 | +} | |
62 | + | |
63 | +/* Assert that the list of names is in sorted order. */ | |
64 | + | |
65 | +void | |
66 | +function_set::assert_sorted () const | |
67 | +{ | |
68 | +#if CHECKING_P | |
69 | + for (size_t idx = 1; idx < m_count; idx++) | |
70 | + gcc_assert (strcmp (m_names[idx - 1], m_names[idx]) < 0); | |
71 | +#endif /* #if CHECKING_P */ | |
72 | +} | |
73 | + | |
74 | +/* Assert that contains_p is true for all members of the set. */ | |
75 | + | |
76 | +void | |
77 | +function_set::assert_sane () const | |
78 | +{ | |
79 | +#if CHECKING_P | |
80 | + for (size_t i = 0; i < m_count; i++) | |
81 | + gcc_assert (contains_name_p (m_names[i])); | |
82 | +#endif /* #if CHECKING_P */ | |
83 | +} | |
84 | + | |
85 | +#if CHECKING_P | |
86 | + | |
87 | +namespace selftest { | |
88 | + | |
89 | +/* Verify that an empty function_set works as expected. */ | |
90 | + | |
91 | +static void | |
92 | +test_empty () | |
93 | +{ | |
94 | + function_set fs (NULL, 0); | |
95 | + fs.assert_sorted (); | |
96 | + fs.assert_sane (); | |
97 | + ASSERT_FALSE (fs.contains_name_p ("")); | |
98 | + ASSERT_FALSE (fs.contains_name_p ("haystack")); | |
99 | +} | |
100 | + | |
101 | +/* Verify that a function_set with an odd number of elements works as | |
102 | + expected. */ | |
103 | + | |
104 | +static void | |
105 | +test_odd () | |
106 | +{ | |
107 | + static const char * const names[3] = {"alpha", "beta", "gamma"}; | |
108 | + function_set fs (names, 3); | |
109 | + fs.assert_sorted (); | |
110 | + fs.assert_sane (); | |
111 | + ASSERT_FALSE (fs.contains_name_p ("")); | |
112 | + ASSERT_FALSE (fs.contains_name_p ("haystack")); | |
113 | +} | |
114 | + | |
115 | +/* Verify that a function_set with an even number of elements works as | |
116 | + expected. */ | |
117 | + | |
118 | +static void | |
119 | +test_even () | |
120 | +{ | |
121 | + static const char * const names[3] = {"alpha", "beta"}; | |
122 | + function_set fs (names, 2); | |
123 | + fs.assert_sorted (); | |
124 | + fs.assert_sane (); | |
125 | + ASSERT_FALSE (fs.contains_name_p ("")); | |
126 | + ASSERT_FALSE (fs.contains_name_p ("haystack")); | |
127 | +} | |
128 | + | |
129 | +/* Verify that a function_set with some nontrivial stdio.h data works as | |
130 | + expected. */ | |
131 | + | |
132 | +static void | |
133 | +test_stdio_example () | |
134 | +{ | |
135 | + static const char * const example[] = { | |
136 | + "__fbufsize", | |
137 | + "__flbf", | |
138 | + "__fpending", | |
139 | + "__fpurge", | |
140 | + "__freadable", | |
141 | + "__freading", | |
142 | + "__fsetlocking", | |
143 | + "__fwritable", | |
144 | + "__fwriting", | |
145 | + "clearerr_unlocked", | |
146 | + "feof_unlocked", | |
147 | + "ferror_unlocked", | |
148 | + "fflush_unlocked", | |
149 | + "fgetc_unlocked", | |
150 | + "fgets", | |
151 | + "fgets_unlocked", | |
152 | + "fgetwc_unlocked", | |
153 | + "fgetws_unlocked", | |
154 | + "fileno_unlocked", | |
155 | + "fputc_unlocked", | |
156 | + "fputs_unlocked", | |
157 | + "fputwc_unlocked", | |
158 | + "fputws_unlocked", | |
159 | + "fread_unlocked", | |
160 | + "fwrite_unlocked", | |
161 | + "getc_unlocked", | |
162 | + "getwc_unlocked", | |
163 | + "putc_unlocked" | |
164 | + }; | |
165 | + const size_t count = sizeof(example) / sizeof (example[0]); | |
166 | + function_set fs (example, count); | |
167 | + fs.assert_sorted (); | |
168 | + fs.assert_sane (); | |
169 | + /* Examples of strings not present: before, after and alongside the | |
170 | + sorted list. */ | |
171 | + ASSERT_FALSE (fs.contains_name_p ("___")); | |
172 | + ASSERT_FALSE (fs.contains_name_p ("Z")); | |
173 | + ASSERT_FALSE (fs.contains_name_p ("fgets_WITH_A_PREFIX")); | |
174 | +} | |
175 | + | |
176 | +/* Run all of the selftests within this file. */ | |
177 | + | |
178 | +void | |
179 | +analyzer_function_set_cc_tests () | |
180 | +{ | |
181 | + test_empty (); | |
182 | + test_odd (); | |
183 | + test_even (); | |
184 | + test_stdio_example (); | |
185 | +} | |
186 | + | |
187 | +} // namespace selftest | |
188 | + | |
189 | +#endif /* CHECKING_P */ | |
190 | + | |
191 | +#endif /* #if ENABLE_ANALYZER */ |
@@ -0,0 +1,46 @@ | ||
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 | +#ifndef GCC_ANALYZER_FUNCTION_SET_H | |
22 | +#define GCC_ANALYZER_FUNCTION_SET_H | |
23 | + | |
24 | +/* A set of names. */ | |
25 | + | |
26 | +class function_set | |
27 | +{ | |
28 | +public: | |
29 | + /* Construct from a sorted array NAMES of size COUNT. */ | |
30 | + function_set (const char * const *names, size_t count) | |
31 | + : m_names (names), m_count (count) | |
32 | + { | |
33 | + } | |
34 | + | |
35 | + bool contains_name_p (const char *name) const; | |
36 | + bool contains_decl_p (tree fndecl) const; | |
37 | + | |
38 | + void assert_sorted () const; | |
39 | + void assert_sane () const; | |
40 | + | |
41 | +private: | |
42 | + const char * const *m_names; // must be sorted | |
43 | + size_t m_count; | |
44 | +}; | |
45 | + | |
46 | +#endif /* GCC_ANALYZER_FUNCTION_SET_H */ |