Line data Source code
1 : /* Base header for the analyzer, plus utility functions.
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 : #ifndef GCC_ANALYZER_COMMON_H
22 : #define GCC_ANALYZER_COMMON_H
23 :
24 : #include "config.h"
25 : #define INCLUDE_ALGORITHM
26 : #define INCLUDE_LIST
27 : #define INCLUDE_MAP
28 : #define INCLUDE_SET
29 : #define INCLUDE_STRING
30 : #define INCLUDE_VECTOR
31 : #include "system.h"
32 : #include "coretypes.h"
33 : #include "tree.h"
34 : #include "function.h"
35 : #include "basic-block.h"
36 : #include "gimple.h"
37 : #include "options.h"
38 : #include "bitmap.h"
39 : #include "diagnostic-core.h"
40 : #include "diagnostics/paths.h"
41 : #include "rich-location.h"
42 : #include "function.h"
43 : #include "json.h"
44 : #include "tristate.h"
45 : #include "value-range.h"
46 :
47 : class graphviz_out;
48 :
49 : namespace ana {
50 :
51 : /* Forward decls of common types, with indentation to show inheritance. */
52 :
53 : class supergraph;
54 : class supernode;
55 : class superedge;
56 :
57 : class svalue;
58 : class region_svalue;
59 : class constant_svalue;
60 : class unknown_svalue;
61 : class poisoned_svalue;
62 : class setjmp_svalue;
63 : class initial_svalue;
64 : class unaryop_svalue;
65 : class binop_svalue;
66 : class sub_svalue;
67 : class repeated_svalue;
68 : class bits_within_svalue;
69 : class unmergeable_svalue;
70 : class placeholder_svalue;
71 : class widening_svalue;
72 : class compound_svalue;
73 : class conjured_svalue;
74 : class asm_output_svalue;
75 : class const_fn_result_svalue;
76 : typedef hash_set<const svalue *> svalue_set;
77 : class region;
78 : class frame_region;
79 : class function_region;
80 : class label_region;
81 : class decl_region;
82 : class symbolic_region;
83 : class element_region;
84 : class offset_region;
85 : class sized_region;
86 : class cast_region;
87 : class field_region;
88 : class string_region;
89 : class bit_range_region;
90 : class var_arg_region;
91 : class region_model_manager;
92 : class conjured_purge;
93 : struct model_merger;
94 : class store_manager;
95 : class store;
96 : class region_model;
97 : class region_model_context;
98 : class impl_region_model_context;
99 : class call_details;
100 : class rejected_constraint;
101 : class constraint_manager;
102 : class equiv_class;
103 : class reachable_regions;
104 : class bounded_ranges;
105 : class bounded_ranges_manager;
106 :
107 : struct pending_location;
108 : class pending_diagnostic;
109 : class pending_note;
110 : class saved_diagnostic;
111 : struct event_loc_info;
112 : class checker_event;
113 : class state_change_event;
114 : class warning_event;
115 : class checker_path;
116 : class extrinsic_state;
117 : class sm_state_map;
118 : class program_point;
119 : class program_state;
120 : class exploded_graph;
121 : class exploded_node;
122 : class exploded_edge;
123 : class feasibility_problem;
124 : class feasibility_state;
125 : class exploded_cluster;
126 : class exploded_path;
127 : class analysis_plan;
128 : class state_purge_map;
129 : class state_purge_per_ssa_name;
130 : class state_purge_per_decl;
131 : class state_change;
132 : class rewind_info_t;
133 :
134 : class engine;
135 : class state_machine;
136 : class logger;
137 : class visitor;
138 : class known_function_manager;
139 : class call_summary;
140 : class call_summary_replay;
141 : struct per_function_data;
142 : struct interesting_t;
143 : class state_transition;
144 : class state_transition_at_call;
145 : class state_transition_at_return;
146 : class uncertainty_t;
147 :
148 : class feasible_node;
149 :
150 : class known_function;
151 : class builtin_known_function;
152 : class internal_known_function;
153 :
154 : class translation_unit;
155 :
156 : /* Forward decls of functions. */
157 :
158 : extern void dump_tree (pretty_printer *pp, tree t);
159 : extern void dump_quoted_tree (pretty_printer *pp, tree t);
160 : extern void print_quoted_type (pretty_printer *pp, tree t);
161 : extern void print_expr_for_user (pretty_printer *pp, tree t);
162 : extern bool printable_expr_p (const_tree expr);
163 : extern int readability_comparator (const void *p1, const void *p2);
164 : extern int tree_cmp (const void *p1, const void *p2);
165 : extern tree fixup_tree_for_diagnostic (tree);
166 : extern tree get_diagnostic_tree_for_gassign (const gassign *);
167 :
168 : inline bool
169 161659 : useful_location_p (location_t loc)
170 : {
171 161659 : return get_pure_location (loc) != UNKNOWN_LOCATION;
172 : }
173 :
174 : /* A tree, extended with stack frame information for locals, so that
175 : we can distinguish between different values of locals within a potentially
176 : recursive callstack. */
177 :
178 : class path_var
179 : {
180 : public:
181 25420 : path_var (tree t, int stack_depth)
182 4891275 : : m_tree (t), m_stack_depth (stack_depth)
183 : {
184 : // TODO: ignore stack depth for globals and constants
185 : }
186 :
187 40 : bool operator== (const path_var &other) const
188 : {
189 40 : return (m_tree == other.m_tree
190 40 : && m_stack_depth == other.m_stack_depth);
191 : }
192 :
193 9769 : operator bool () const
194 : {
195 9769 : return m_tree != NULL_TREE;
196 : }
197 :
198 : void dump (pretty_printer *pp) const;
199 :
200 : tree m_tree;
201 : int m_stack_depth; // or -1 for globals?
202 : };
203 :
204 : typedef offset_int bit_offset_t;
205 : typedef offset_int bit_size_t;
206 : typedef offset_int byte_offset_t;
207 : typedef offset_int byte_size_t;
208 :
209 : extern bool int_size_in_bits (const_tree type, bit_size_t *out);
210 :
211 : extern tree get_field_at_bit_offset (tree record_type, bit_offset_t bit_offset);
212 :
213 : extern bool
214 : compare_bit_offsets_p (bit_offset_t a,
215 : enum tree_code op,
216 : bit_offset_t b);
217 :
218 : /* The location of a region expressesd as an offset relative to a
219 : base region. */
220 :
221 : class region_offset
222 : {
223 : public:
224 1291 : region_offset ()
225 1291 : : m_base_region (nullptr), m_offset (0), m_sym_offset (nullptr)
226 : {
227 : }
228 :
229 153253 : static region_offset make_concrete (const region *base_region,
230 : bit_offset_t offset)
231 : {
232 153253 : return region_offset (base_region, offset, nullptr);
233 : }
234 4035 : static region_offset make_symbolic (const region *base_region,
235 : const svalue *sym_offset)
236 : {
237 4035 : return region_offset (base_region, 0, sym_offset);
238 : }
239 : static region_offset make_byte_offset (const region *base_region,
240 : const svalue *num_bytes_sval);
241 :
242 871729 : const region *get_base_region () const { return m_base_region; }
243 :
244 4025 : bool concrete_p () const { return m_sym_offset == nullptr; }
245 4898252 : bool symbolic_p () const { return m_sym_offset != nullptr; }
246 :
247 3305818 : bit_offset_t get_bit_offset () const
248 : {
249 3305818 : gcc_assert (!symbolic_p ());
250 3305818 : return m_offset;
251 : }
252 :
253 8603 : bool get_concrete_byte_offset (byte_offset_t *out) const
254 : {
255 8603 : gcc_assert (!symbolic_p ());
256 8603 : if (m_offset % BITS_PER_UNIT == 0)
257 : {
258 8603 : *out = m_offset / BITS_PER_UNIT;
259 8603 : return true;
260 : }
261 : return false;
262 : }
263 :
264 15107 : const svalue *get_symbolic_byte_offset () const
265 : {
266 15107 : gcc_assert (symbolic_p ());
267 15107 : return m_sym_offset;
268 : }
269 :
270 : const svalue &calc_symbolic_bit_offset (region_model_manager *mgr) const;
271 : const svalue *calc_symbolic_byte_offset (region_model_manager *mgr) const;
272 :
273 : bool operator== (const region_offset &other) const
274 : {
275 : return (m_base_region == other.m_base_region
276 : && m_offset == other.m_offset
277 : && m_sym_offset == other.m_sym_offset);
278 : }
279 :
280 : void dump_to_pp (pretty_printer *pp, bool) const;
281 : void dump (bool) const;
282 :
283 : private:
284 153714 : region_offset (const region *base_region, bit_offset_t offset,
285 : const svalue *sym_offset)
286 151800 : : m_base_region (base_region), m_offset (offset), m_sym_offset (sym_offset)
287 : {}
288 :
289 : const region *m_base_region;
290 : bit_offset_t m_offset;
291 : const svalue *m_sym_offset;
292 : };
293 :
294 : extern bool operator< (const region_offset &, const region_offset &);
295 : extern bool operator<= (const region_offset &, const region_offset &);
296 : extern bool operator> (const region_offset &, const region_offset &);
297 : extern bool operator>= (const region_offset &, const region_offset &);
298 :
299 : extern tristate
300 : eval_region_offset_comparison (region_offset lhs_offset,
301 : enum tree_code op,
302 : region_offset rhs_offset,
303 : const region_model &model);
304 :
305 : extern location_t get_stmt_location (const gimple *stmt, function *fun);
306 :
307 : extern bool compat_types_p (tree src_type, tree dst_type);
308 :
309 : /* Abstract base class for simulating the behavior of known functions,
310 : supplied by the core of the analyzer, or by plugins.
311 : The former are typically implemented in the various kf*.cc */
312 :
313 194544 : class known_function
314 : {
315 : public:
316 487 : virtual ~known_function () {}
317 : virtual bool matches_call_types_p (const call_details &cd) const = 0;
318 :
319 : /* A hook for performing additional checks on the expected state
320 : at a call. */
321 : virtual void
322 34130 : check_any_preconditions (const call_details &) const
323 : {
324 : // no-op
325 34130 : }
326 :
327 16221 : virtual void impl_call_pre (const call_details &) const
328 : {
329 16221 : return;
330 : }
331 34788 : virtual void impl_call_post (const call_details &) const
332 : {
333 34788 : return;
334 : }
335 :
336 : virtual const builtin_known_function *
337 51770 : dyn_cast_builtin_kf () const { return nullptr; }
338 : };
339 :
340 : /* Subclass of known_function for builtin functions. */
341 :
342 177174 : class builtin_known_function : public known_function
343 : {
344 : public:
345 : virtual enum built_in_function builtin_code () const = 0;
346 63778 : tree builtin_decl () const {
347 63778 : gcc_assert (builtin_code () < END_BUILTINS);
348 63778 : return builtin_info[builtin_code ()].decl;
349 : }
350 :
351 : const builtin_known_function *
352 63778 : dyn_cast_builtin_kf () const final override { return this; }
353 : };
354 :
355 : /* Subclass of known_function for IFN_* functions. */
356 :
357 274446 : class internal_known_function : public known_function
358 : {
359 : public:
360 0 : bool matches_call_types_p (const call_details &) const final override
361 : {
362 : /* Types are assumed to be correct. */
363 0 : return true;
364 : }
365 : };
366 :
367 : /* Abstract subclass of known_function that merely sets the return
368 : value of the function (based on function attributes), and assumes
369 : it has no side-effects. */
370 :
371 107694 : class pure_known_function_with_default_return : public known_function
372 : {
373 : public:
374 : void impl_call_pre (const call_details &cd) const override;
375 : };
376 :
377 : extern void register_known_functions (known_function_manager &kfm,
378 : region_model_manager &rmm);
379 : extern void register_known_analyzer_functions (known_function_manager &kfm);
380 : extern void register_known_fd_functions (known_function_manager &kfm);
381 : extern void register_known_file_functions (known_function_manager &kfm);
382 : extern void register_known_functions_lang_cp (known_function_manager &kfm);
383 : extern void register_varargs_builtins (known_function_manager &kfm);
384 :
385 : /* An enum for describing the direction of an access to memory. */
386 :
387 : enum class access_direction
388 : {
389 : read,
390 : write
391 : };
392 :
393 : /* State tracked along an execution path that's pertinent to a specific
394 : diagnostic (e.g. for a divide-by-zero warning where the zero value
395 : comes from). */
396 :
397 477925 : struct diagnostic_state
398 : {
399 90222 : diagnostic_state ()
400 90222 : : m_region_holding_value (nullptr)
401 : {
402 : }
403 :
404 1198 : diagnostic_state (std::string debug_desc,
405 : const region *region_holding_value)
406 1198 : : m_debug_desc (std::move (debug_desc)),
407 1198 : m_region_holding_value (region_holding_value)
408 : {
409 : }
410 :
411 : void dump_to_pp (pretty_printer *) const;
412 : void dump () const;
413 :
414 : bool
415 : operator== (const diagnostic_state &other) const
416 : {
417 : return m_region_holding_value == other.m_region_holding_value;
418 : }
419 : bool
420 : operator!= (const diagnostic_state &other) const
421 : {
422 : return !(*this == other);
423 : }
424 :
425 : std::string m_debug_desc;
426 : const region *m_region_holding_value;
427 : };
428 :
429 : struct rewind_context;
430 :
431 : /* Abstract base class for associating custom data with an
432 : exploded_edge, for handling non-standard edges such as
433 : rewinding from a longjmp, signal handlers, etc.
434 : Also used when "bifurcating" state: splitting the execution
435 : path in non-standard ways (e.g. for simulating the various
436 : outcomes of "realloc"). */
437 :
438 32910 : class custom_edge_info
439 : {
440 : public:
441 25 : virtual ~custom_edge_info () {}
442 :
443 : /* Hook for making .dot label more readable. */
444 : virtual void print (pretty_printer *pp) const = 0;
445 :
446 : virtual void
447 : get_dot_attrs (const char *&out_style,
448 : const char *&out_color) const;
449 :
450 : /* Hook for updating STATE when handling bifurcation. */
451 : virtual bool update_state (program_state *state,
452 : const exploded_edge *eedge,
453 : region_model_context *ctxt) const;
454 :
455 : /* Hook for updating MODEL within exploded_path::feasible_p
456 : and when handling bifurcation. */
457 : virtual bool update_model (region_model *model,
458 : const exploded_edge *eedge,
459 : region_model_context *ctxt) const = 0;
460 :
461 : virtual void add_events_to_path (checker_path *emission_path,
462 : const exploded_edge &eedge,
463 : pending_diagnostic &pd,
464 : const state_transition *state_trans) const = 0;
465 :
466 : virtual exploded_node *create_enode (exploded_graph &eg,
467 : const program_point &point,
468 : program_state &&state,
469 : exploded_node *enode_for_diag,
470 : region_model_context *ctxt) const;
471 :
472 : virtual bool
473 475 : try_to_rewind_data_flow (rewind_context &) const
474 : {
475 475 : return false;
476 : }
477 : };
478 :
479 : /* Abstract base class for splitting state.
480 :
481 : Most of the state-management code in the analyzer involves
482 : modifying state objects in-place, which assumes a single outcome.
483 :
484 : This class provides an escape hatch to allow for multiple outcomes
485 : for such updates e.g. for modelling multiple outcomes from function
486 : calls, such as the various outcomes of "realloc". */
487 :
488 253834 : class path_context
489 : {
490 : public:
491 114660 : virtual ~path_context () {}
492 :
493 : /* Hook for clients to split state with a non-standard path. */
494 : virtual void bifurcate (std::unique_ptr<custom_edge_info> info) = 0;
495 :
496 : /* Hook for clients to terminate the standard path. */
497 : virtual void terminate_path () = 0;
498 :
499 : /* Hook for clients to determine if the standard path has been
500 : terminated. */
501 : virtual bool terminate_path_p () const = 0;
502 : };
503 :
504 : extern tree get_stashed_constant_by_name (const char *name);
505 : extern void log_stashed_constants (logger *logger);
506 :
507 : extern FILE *get_or_create_any_logfile ();
508 :
509 : extern std::unique_ptr<json::value>
510 : tree_to_json (tree node);
511 :
512 : extern std::unique_ptr<json::value>
513 : diagnostic_event_id_to_json (const diagnostics::paths::event_id_t &);
514 :
515 : extern std::unique_ptr<json::value>
516 : bit_offset_to_json (const bit_offset_t &offset);
517 :
518 : extern std::unique_ptr<json::value>
519 : byte_offset_to_json (const byte_offset_t &offset);
520 :
521 : extern tristate
522 : compare_constants (tree lhs_const, enum tree_code op, tree rhs_const);
523 :
524 : extern tree
525 : get_string_cst_size (const_tree string_cst);
526 :
527 : extern tree
528 : get_ssa_default_def (const function &fun, tree var);
529 :
530 : extern const svalue *
531 : strip_types (const svalue *sval, region_model_manager &mgr);
532 :
533 : extern region_offset
534 : strip_types (const region_offset &offset, region_model_manager &mgr);
535 :
536 : extern tree remove_ssa_names (tree expr);
537 :
538 : } // namespace ana
539 :
540 : extern bool is_special_named_call_p (const gcall &call, const char *funcname,
541 : unsigned int num_args,
542 : bool look_in_std = false);
543 : extern bool is_named_call_p (const_tree fndecl, const char *funcname);
544 : extern bool is_named_call_p (const_tree fndecl, const char *funcname,
545 : const gcall &call, unsigned int num_args);
546 : extern bool is_std_function_p (const_tree fndecl);
547 : extern bool is_std_named_call_p (const_tree fndecl, const char *funcname);
548 : extern bool is_std_named_call_p (const_tree fndecl, const char *funcname,
549 : const gcall &call, unsigned int num_args);
550 : extern bool is_setjmp_call_p (const gcall &call);
551 : extern bool is_longjmp_call_p (const gcall &call);
552 : extern bool is_placement_new_p (const gcall &call);
553 : extern bool is_cxa_throw_p (const gcall &call);
554 : extern bool is_cxa_rethrow_p (const gcall &call);
555 : extern bool is_cxa_end_catch_p (const gcall &call);
556 :
557 : extern const char *get_user_facing_name (const gcall &call);
558 :
559 : extern void register_analyzer_pass ();
560 :
561 : extern label_text make_label_text (bool can_colorize, const char *fmt, ...);
562 : extern label_text make_label_text_n (bool can_colorize,
563 : unsigned HOST_WIDE_INT n,
564 : const char *singular_fmt,
565 : const char *plural_fmt, ...);
566 :
567 : extern bool fndecl_has_gimple_body_p (tree fndecl);
568 :
569 : /* An RAII-style class for pushing/popping cfun within a scope.
570 : Doing so ensures we get "In function " announcements
571 : from the diagnostics subsystem. */
572 :
573 : class auto_cfun
574 : {
575 : public:
576 809261 : auto_cfun (function *fun) { push_cfun (fun); }
577 809261 : ~auto_cfun () { pop_cfun (); }
578 : };
579 :
580 : /* A template for creating hash traits for a POD type. */
581 :
582 : template <typename Type>
583 : struct pod_hash_traits : typed_noop_remove<Type>
584 : {
585 : typedef Type value_type;
586 : typedef Type compare_type;
587 : static inline hashval_t hash (value_type);
588 : static inline bool equal (const value_type &existing,
589 : const value_type &candidate);
590 : static inline void mark_deleted (Type &);
591 : static inline void mark_empty (Type &);
592 : static inline bool is_deleted (Type);
593 : static inline bool is_empty (Type);
594 : };
595 :
596 : /* A hash traits class that uses member functions to implement
597 : the various required ops. */
598 :
599 : template <typename Type>
600 : struct member_function_hash_traits : public typed_noop_remove<Type>
601 : {
602 : typedef Type value_type;
603 : typedef Type compare_type;
604 101407362 : static inline hashval_t hash (value_type v) { return v.hash (); }
605 97084589 : static inline bool equal (const value_type &existing,
606 : const value_type &candidate)
607 : {
608 120314407 : return existing == candidate;
609 : }
610 : static inline void mark_deleted (Type &t) { t.mark_deleted (); }
611 891052 : static inline void mark_empty (Type &t) { t.mark_empty (); }
612 68297623 : static inline bool is_deleted (Type t) { return t.is_deleted (); }
613 326625047 : static inline bool is_empty (Type t) { return t.is_empty (); }
614 : };
615 :
616 : /* A map from T::key_t to T* for use in consolidating instances of T.
617 : Owns all instances of T.
618 : T::key_t should have operator== and be hashable. */
619 :
620 : template <typename T>
621 : class consolidation_map
622 : {
623 : public:
624 : typedef typename T::key_t key_t;
625 : typedef T instance_t;
626 : typedef hash_map<key_t, instance_t *> inner_map_t;
627 : typedef typename inner_map_t::iterator iterator;
628 :
629 : /* Delete all instances of T. */
630 :
631 44390 : ~consolidation_map ()
632 : {
633 129914 : for (typename inner_map_t::iterator iter = m_inner_map.begin ();
634 215438 : iter != m_inner_map.end (); ++iter)
635 85524 : delete (*iter).second;
636 44390 : }
637 :
638 : /* Get the instance of T for K if one exists, or nullptr. */
639 :
640 16051008 : T *get (const key_t &k) const
641 : {
642 16051008 : if (instance_t **slot = const_cast<inner_map_t &> (m_inner_map).get (k))
643 15965484 : return *slot;
644 : return nullptr;
645 : }
646 :
647 : /* Take ownership of INSTANCE. */
648 :
649 85524 : void put (const key_t &k, T *instance)
650 : {
651 85524 : m_inner_map.put (k, instance);
652 : }
653 :
654 110 : size_t elements () const { return m_inner_map.elements (); }
655 :
656 78 : iterator begin () const { return m_inner_map.begin (); }
657 126 : iterator end () const { return m_inner_map.end (); }
658 :
659 : private:
660 : inner_map_t m_inner_map;
661 : };
662 :
663 : /* Disable -Wformat-diag; we want to be able to use pp_printf
664 : for logging/dumping without complying with the rules for diagnostics. */
665 : #if __GNUC__ >= 10
666 : #pragma GCC diagnostic ignored "-Wformat-diag"
667 : #endif
668 :
669 : namespace gcc {
670 : namespace topics {
671 :
672 : /* A topic for messages relating to the analyzer. */
673 :
674 : namespace analyzer_events {
675 :
676 : /* A message published by the analyzer when the frontend finishes
677 : parsing the TU, to allow it to look up pertinent items using the FE's
678 : name-resolution logic. */
679 :
680 : struct on_tu_finished
681 : {
682 : ana::logger *m_logger;
683 : const ana::translation_unit &m_tu;
684 : };
685 :
686 : /* A message published by the analyzer as it starts up, intended for
687 : subsystems/plugins that want to register additional functionality
688 : within the analyzer. */
689 :
690 38 : struct on_ana_init
691 : {
692 : virtual void
693 : register_state_machine (std::unique_ptr<ana::state_machine>) const = 0;
694 :
695 : virtual void
696 : register_known_function (const char *name,
697 : std::unique_ptr<ana::known_function>) const = 0;
698 :
699 : virtual ana::logger *
700 : get_logger () const = 0;
701 : };
702 :
703 : /* A message published by the analyzer when it simulates popping a stack
704 : frame. */
705 :
706 : struct on_frame_popped
707 : {
708 : const ana::region_model *m_new_model;
709 : const ana::region_model *m_old_model;
710 : const ana::svalue *m_retval;
711 : ana::region_model_context *m_ctxt;
712 : };
713 :
714 : struct subscriber {
715 :
716 : virtual ~subscriber () = default;
717 :
718 37 : virtual void on_message (const on_tu_finished &) {}
719 0 : virtual void on_message (const on_ana_init &) {}
720 236 : virtual void on_message (const on_frame_popped &) {}
721 : };
722 :
723 : } // namespace gcc::topics::analyzer_events
724 : } // namespace gcc::topics
725 : } // namespace gcc
726 :
727 : #if !ENABLE_ANALYZER
728 : extern void sorry_no_analyzer ();
729 : #endif /* #if !ENABLE_ANALYZER */
730 :
731 : #endif /* GCC_ANALYZER_COMMON_H */
|