analyzer: introduce namespace to avoid ODR clashes (PR 93307)

Message ID 20200117215458.8453-1-dmalcolm@redhat.com
State New
Headers show
Series
  • analyzer: introduce namespace to avoid ODR clashes (PR 93307)
Related show

Commit Message

David Malcolm Jan. 17, 2020, 9:54 p.m.
PR analyzer/93307 reports that in an LTO bootstrap, there are ODR
violations between:
- the "region" type:
    gcc/analyzer/region-model.h:792
  vs:
    gcc/sched-int.h:1443
- the "constraint" type:
    gcc/analyzer/constraint-manager.h:121
  vs:
    gcc/tree-ssa-structalias.c:533

This patches solves this clash by putting all of the analyzer names
within a namespace.  I chose "ana" as it is short (to save typing).
The analyzer selftests are moved from namespace "selftest" to
"ana::selftest".

There are various places where the namespace has to be closed
and reopened, to allow e.g. for specializations of templates
in the global namespace.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.

OK for master?

gcc/analyzer/ChangeLog:
	PR analyzer/93307
	* analysis-plan.h: Wrap everything namespace "ana".
	* analyzer-logging.cc: Likewise.
	* analyzer-logging.h: Likewise.
	* analyzer-pass.cc (pass_analyzer::execute): Update for "ana"
	namespace.
	* analyzer-selftests.cc: Wrap everything namespace "ana".
	* analyzer-selftests.h: Likewise.
	* analyzer.h: Likewise for forward decls of types.
	* call-string.h: Likewise.
	* checker-path.cc: Likewise.
	* checker-path.h: Likewise.
	* constraint-manager.cc: Likewise.
	* constraint-manager.h: Likewise.
	* diagnostic-manager.cc: Likewise.
	* diagnostic-manager.h: Likewise.
	* engine.cc: Likewise.
	* engine.h: Likewise.
	* exploded-graph.h: Likewise.
	* function-set.cc: Likewise.
	* function-set.h: Likewise.
	* pending-diagnostic.cc: Likewise.
	* pending-diagnostic.h: Likewise.
	* program-point.cc: Likewise.
	* program-point.h: Likewise.
	* program-state.cc: Likewise.
	* program-state.h: Likewise.
	* region-model.cc: Likewise.
	* region-model.h: Likewise.
	* sm-file.cc: Likewise.
	* sm-malloc.cc: Likewise.
	* sm-pattern-test.cc: Likewise.
	* sm-sensitive.cc: Likewise.
	* sm-signal.cc: Likewise.
	* sm-taint.cc: Likewise.
	* sm.cc: Likewise.
	* sm.h: Likewise.
	* state-purge.h: Likewise.
	* supergraph.cc: Likewise.
	* supergraph.h: Likewise.

gcc/ChangeLog:
	PR analyzer/93307
	* gdbinit.in (break-on-saved-diagnostic): Update for move of
	diagnostic_manager into "ana" namespace.
	* selftest-run-tests.c (selftest::run_tests): Update for move of
	selftest::run_analyzer_selftests to
	ana::selftest::run_analyzer_selftests.
---
 gcc/analyzer/analysis-plan.h       |  4 ++
 gcc/analyzer/analyzer-logging.cc   |  4 ++
 gcc/analyzer/analyzer-logging.h    |  4 ++
 gcc/analyzer/analyzer-pass.cc      |  2 +-
 gcc/analyzer/analyzer-selftests.cc |  4 ++
 gcc/analyzer/analyzer-selftests.h  |  6 ++-
 gcc/analyzer/analyzer.h            |  5 ++
 gcc/analyzer/call-string.h         |  4 ++
 gcc/analyzer/checker-path.cc       |  4 ++
 gcc/analyzer/checker-path.h        |  4 ++
 gcc/analyzer/constraint-manager.cc |  4 ++
 gcc/analyzer/constraint-manager.h  |  4 ++
 gcc/analyzer/diagnostic-manager.cc |  4 ++
 gcc/analyzer/diagnostic-manager.h  |  4 ++
 gcc/analyzer/engine.cc             | 12 +++++
 gcc/analyzer/engine.h              |  4 ++
 gcc/analyzer/exploded-graph.h      |  4 ++
 gcc/analyzer/function-set.cc       |  4 ++
 gcc/analyzer/function-set.h        |  4 ++
 gcc/analyzer/pending-diagnostic.cc |  4 ++
 gcc/analyzer/pending-diagnostic.h  |  4 ++
 gcc/analyzer/program-point.cc      |  4 ++
 gcc/analyzer/program-point.h       |  4 ++
 gcc/analyzer/program-state.cc      |  4 ++
 gcc/analyzer/program-state.h       |  8 +++
 gcc/analyzer/region-model.cc       |  8 +++
 gcc/analyzer/region-model.h        | 80 ++++++++++++++++++++++++++++++
 gcc/analyzer/sm-file.cc            |  4 ++
 gcc/analyzer/sm-malloc.cc          |  4 ++
 gcc/analyzer/sm-pattern-test.cc    |  4 ++
 gcc/analyzer/sm-sensitive.cc       |  4 ++
 gcc/analyzer/sm-signal.cc          |  4 ++
 gcc/analyzer/sm-taint.cc           |  4 ++
 gcc/analyzer/sm.cc                 |  4 ++
 gcc/analyzer/sm.h                  |  4 ++
 gcc/analyzer/state-purge.h         |  4 ++
 gcc/analyzer/supergraph.cc         |  4 ++
 gcc/analyzer/supergraph.h          | 26 ++++++++++
 gcc/gdbinit.in                     |  4 +-
 gcc/selftest-run-tests.c           |  2 +-
 40 files changed, 268 insertions(+), 5 deletions(-)

-- 
2.21.0

Comments

David Malcolm Jan. 22, 2020, 7:23 p.m. | #1
On Fri, 2020-01-17 at 16:54 -0500, David Malcolm wrote:
> PR analyzer/93307 reports that in an LTO bootstrap, there are ODR

> violations between:

> - the "region" type:

>     gcc/analyzer/region-model.h:792

>   vs:

>     gcc/sched-int.h:1443

> - the "constraint" type:

>     gcc/analyzer/constraint-manager.h:121

>   vs:

>     gcc/tree-ssa-structalias.c:533

> 

> This patches solves this clash by putting all of the analyzer names

> within a namespace.  I chose "ana" as it is short (to save typing).

> The analyzer selftests are moved from namespace "selftest" to

> "ana::selftest".

> 

> There are various places where the namespace has to be closed

> and reopened, to allow e.g. for specializations of templates

> in the global namespace.

> 

> Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.

> 

> OK for master?


I was able to successfully reproduce the problem
(via --with-build-config=bootstrap-lto), and verify that the patch
fixed it (with another bootstrap and regression test), so I've pushed
this to master, as r10-6151-g75038aa6aa5b562e6358108619d66ef2ccab9a53.

Dave

Patch

diff --git a/gcc/analyzer/analysis-plan.h b/gcc/analyzer/analysis-plan.h
index a44c79561be..79030bae382 100644
--- a/gcc/analyzer/analysis-plan.h
+++ b/gcc/analyzer/analysis-plan.h
@@ -21,6 +21,8 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_ANALYSIS_PLAN_H
 #define GCC_ANALYZER_ANALYSIS_PLAN_H
 
+namespace ana {
+
 /* A class to encapsulate decisions about how the analysis should happen.
    Examples:
    - the order in which functions should be analyzed, so that function
@@ -53,4 +55,6 @@  private:
   auto_vec<int> m_index_by_uid;
 };
 
+} // namespace ana
+
 #endif /* GCC_ANALYZER_ANALYSIS_PLAN_H */
diff --git a/gcc/analyzer/analyzer-logging.cc b/gcc/analyzer/analyzer-logging.cc
index 9a6b36eee3a..bd82875931c 100644
--- a/gcc/analyzer/analyzer-logging.cc
+++ b/gcc/analyzer/analyzer-logging.cc
@@ -30,6 +30,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if ENABLE_ANALYZER
 
+namespace ana {
+
 /* Implementation of class logger.  */
 
 /* ctor for logger.  */
@@ -221,4 +223,6 @@  log_user::set_logger (logger *logger)
   m_logger = logger;
 }
 
+} // namespace ana
+
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/analyzer-logging.h b/gcc/analyzer/analyzer-logging.h
index 9d5364bfa8f..132f97eb613 100644
--- a/gcc/analyzer/analyzer-logging.h
+++ b/gcc/analyzer/analyzer-logging.h
@@ -23,6 +23,8 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef ANALYZER_LOGGING_H
 #define ANALYZER_LOGGING_H
 
+namespace ana {
+
 /* A logger encapsulates a logging stream: a way to send
    lines of pertinent information to a FILE *.  */
 
@@ -257,4 +259,6 @@  log_user::exit_scope (const char *scope_name)
 #define LOG_FUNC_4(LOGGER, FMT, A0, A1, A2, A3) \
   log_scope s (LOGGER, __func__, FMT, A0, A1, A2, A3)
 
+} // namespace ana
+
 #endif /* ANALYZER_LOGGING_H */
diff --git a/gcc/analyzer/analyzer-pass.cc b/gcc/analyzer/analyzer-pass.cc
index 4070e6d44b5..a27421e46d4 100644
--- a/gcc/analyzer/analyzer-pass.cc
+++ b/gcc/analyzer/analyzer-pass.cc
@@ -81,7 +81,7 @@  unsigned int
 pass_analyzer::execute (function *)
 {
 #if ENABLE_ANALYZER
-  run_checkers ();
+  ana::run_checkers ();
 #else
   sorry ("%qs was not enabled in this build of GCC"
 	 " (missing configure-time option %qs)",
diff --git a/gcc/analyzer/analyzer-selftests.cc b/gcc/analyzer/analyzer-selftests.cc
index 1272936769a..8e200a3844b 100644
--- a/gcc/analyzer/analyzer-selftests.cc
+++ b/gcc/analyzer/analyzer-selftests.cc
@@ -29,6 +29,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if CHECKING_P
 
+namespace ana {
+
 namespace selftest {
 
 /* Build a VAR_DECL named NAME of type TYPE, simulating a file-level
@@ -61,4 +63,6 @@  run_analyzer_selftests ()
 
 } /* end of namespace selftest.  */
 
+} // namespace ana
+
 #endif /* #if CHECKING_P */
diff --git a/gcc/analyzer/analyzer-selftests.h b/gcc/analyzer/analyzer-selftests.h
index 62da6cd0559..7924b8c8f01 100644
--- a/gcc/analyzer/analyzer-selftests.h
+++ b/gcc/analyzer/analyzer-selftests.h
@@ -23,6 +23,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if CHECKING_P
 
+namespace ana {
+
 namespace selftest {
 
 extern tree build_global_decl (const char *name, tree type);
@@ -40,7 +42,9 @@  extern void analyzer_region_model_cc_tests ();
 extern void analyzer_sm_file_cc_tests ();
 extern void analyzer_sm_signal_cc_tests ();
 
-} /* end of namespace selftest.  */
+} /* end of namespace ana::selftest.  */
+
+} // namespace ana
 
 #endif /* #if CHECKING_P */
 
diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h
index 7fc6959c460..e84e6958cec 100644
--- a/gcc/analyzer/analyzer.h
+++ b/gcc/analyzer/analyzer.h
@@ -24,6 +24,9 @@  along with GCC; see the file COPYING3.  If not see
 /* Forward decls of common types, with indentation to show inheritance.  */
 
 class graphviz_out;
+
+namespace ana {
+
 class supergraph;
 class supernode;
 class superedge;
@@ -68,6 +71,8 @@  class state_purge_per_ssa_name;
 class state_change;
 class rewind_info_t;
 
+} // namespace ana
+
 extern bool is_special_named_call_p (const gcall *call, const char *funcname,
 				     unsigned int num_args);
 extern bool is_named_call_p (tree fndecl, const char *funcname);
diff --git a/gcc/analyzer/call-string.h b/gcc/analyzer/call-string.h
index d0b25099336..5e362d8cadb 100644
--- a/gcc/analyzer/call-string.h
+++ b/gcc/analyzer/call-string.h
@@ -21,6 +21,8 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_CALL_STRING_H
 #define GCC_ANALYZER_CALL_STRING_H
 
+namespace ana {
+
 class supergraph;
 class call_superedge;
 class return_superedge;
@@ -73,4 +75,6 @@  private:
   auto_vec<const return_superedge *> m_return_edges;
 };
 
+} // namespace ana
+
 #endif /* GCC_ANALYZER_CALL_STRING_H */
diff --git a/gcc/analyzer/checker-path.cc b/gcc/analyzer/checker-path.cc
index 6c0f66cc275..f7455ba1245 100644
--- a/gcc/analyzer/checker-path.cc
+++ b/gcc/analyzer/checker-path.cc
@@ -61,6 +61,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if ENABLE_ANALYZER
 
+namespace ana {
+
 /* Get a string for EK.  */
 
 const char *
@@ -954,4 +956,6 @@  checker_path::add_final_event (const state_machine *sm,
   add_event (end_of_path);
 }
 
+} // namespace ana
+
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/checker-path.h b/gcc/analyzer/checker-path.h
index 20bab77b719..cceffe079fa 100644
--- a/gcc/analyzer/checker-path.h
+++ b/gcc/analyzer/checker-path.h
@@ -21,6 +21,8 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_CHECKER_PATH_H
 #define GCC_ANALYZER_CHECKER_PATH_H
 
+namespace ana {
+
 /* An enum for discriminating between the concrete subclasses of
    checker_event.  */
 
@@ -519,4 +521,6 @@  private:
   hash_map <const exploded_node *, diagnostic_event_id_t> m_setjmp_event_ids;
 };
 
+} // namespace ana
+
 #endif /* GCC_ANALYZER_CHECKER_PATH_H */
diff --git a/gcc/analyzer/constraint-manager.cc b/gcc/analyzer/constraint-manager.cc
index 669d604e1b7..9d13ec360be 100644
--- a/gcc/analyzer/constraint-manager.cc
+++ b/gcc/analyzer/constraint-manager.cc
@@ -45,6 +45,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if ENABLE_ANALYZER
 
+namespace ana {
+
 /* One of the end-points of a range.  */
 
 struct bound
@@ -2257,4 +2259,6 @@  analyzer_constraint_manager_cc_tests ()
 
 #endif /* CHECKING_P */
 
+} // namespace ana
+
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/constraint-manager.h b/gcc/analyzer/constraint-manager.h
index c6a40f90a33..0f4506cc40d 100644
--- a/gcc/analyzer/constraint-manager.h
+++ b/gcc/analyzer/constraint-manager.h
@@ -21,6 +21,8 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_CONSTRAINT_MANAGER_H
 #define GCC_ANALYZER_CONSTRAINT_MANAGER_H
 
+namespace ana {
+
 class constraint_manager;
 
 /* Abstract base class for specifying how state should be purged.  */
@@ -243,4 +245,6 @@  public:
 				equiv_class_id rhs_id);
 };
 
+} // namespace ana
+
 #endif /* GCC_ANALYZER_CONSTRAINT_MANAGER_H */
diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc
index a00d9f74398..02bc4a61e60 100644
--- a/gcc/analyzer/diagnostic-manager.cc
+++ b/gcc/analyzer/diagnostic-manager.cc
@@ -58,6 +58,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if ENABLE_ANALYZER
 
+namespace ana {
+
 /* class saved_diagnostic.  */
 
 /* saved_diagnostic's ctor.
@@ -1274,4 +1276,6 @@  diagnostic_manager::finish_pruning (checker_path *path) const
     }
 }
 
+} // namespace ana
+
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/diagnostic-manager.h b/gcc/analyzer/diagnostic-manager.h
index c0f13bf8895..0c1d9766a10 100644
--- a/gcc/analyzer/diagnostic-manager.h
+++ b/gcc/analyzer/diagnostic-manager.h
@@ -21,6 +21,8 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_DIAGNOSTIC_MANAGER_H
 #define GCC_ANALYZER_DIAGNOSTIC_MANAGER_H
 
+namespace ana {
+
 /* A to-be-emitted diagnostic stored within diagnostic_manager.  */
 
 class saved_diagnostic
@@ -121,4 +123,6 @@  private:
   const int m_verbosity;
 };
 
+} // namespace ana
+
 #endif /* GCC_ANALYZER_DIAGNOSTIC_MANAGER_H */
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 92615e6cd4f..53c93791a07 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -62,6 +62,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if ENABLE_ANALYZER
 
+namespace ana {
+
 static int readability_comparator (const void *p1, const void *p2);
 
 /* class impl_region_model_context : public region_model_context.  */
@@ -882,6 +884,8 @@  exploded_node::dump (const extrinsic_state &ext_state) const
   dump (stderr, ext_state);
 }
 
+} // namespace ana
+
 /* Return true if FNDECL has a gimple body.  */
 // TODO: is there a pre-canned way to do this?
 
@@ -898,6 +902,8 @@  fndecl_has_gimple_body_p (tree fndecl)
   return n->has_gimple_body_p ();
 }
 
+namespace ana {
+
 /* A pending_diagnostic subclass for implementing "__analyzer_dump_path".  */
 
 class dump_path_diagnostic
@@ -2930,6 +2936,8 @@  struct function_call_string
   call_string m_cs;
 };
 
+} // namespace ana
+
 template <> struct default_hash_traits<function_call_string>
 : public pod_hash_traits<function_call_string>
 {
@@ -2975,6 +2983,8 @@  pod_hash_traits<function_call_string>::is_empty (value_type v)
   return v.m_fun == reinterpret_cast<function *> (NULL);
 }
 
+namespace ana {
+
 /* Top-level cluster for generating .dot output for exploded graphs,
    handling the functionless nodes, and grouping the remaining nodes by
    callstring.  */
@@ -3631,4 +3641,6 @@  run_checkers ()
     fclose (dump_fout);
 }
 
+} // namespace ana
+
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/engine.h b/gcc/analyzer/engine.h
index bbad2e2fe04..24b51ecf04a 100644
--- a/gcc/analyzer/engine.h
+++ b/gcc/analyzer/engine.h
@@ -21,6 +21,10 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_ENGINE_H
 #define GCC_ANALYZER_ENGINE_H
 
+namespace ana {
+
 extern void run_checkers ();
 
+} // namespace ana
+
 #endif /* GCC_ANALYZER_ENGINE_H */
diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h
index 357a1b478f0..57636fbe07c 100644
--- a/gcc/analyzer/exploded-graph.h
+++ b/gcc/analyzer/exploded-graph.h
@@ -21,6 +21,8 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_EXPLODED_GRAPH_H
 #define GCC_ANALYZER_EXPLODED_GRAPH_H
 
+namespace ana {
+
 /* Concrete implementation of region_model_context, wiring it up to the
    rest of the analysis engine.  */
 
@@ -828,4 +830,6 @@  public:
 
 // TODO: split the above up?
 
+} // namespace ana
+
 #endif /* GCC_ANALYZER_EXPLODED_GRAPH_H */
diff --git a/gcc/analyzer/function-set.cc b/gcc/analyzer/function-set.cc
index 93ce473405f..6ed15ae95ad 100644
--- a/gcc/analyzer/function-set.cc
+++ b/gcc/analyzer/function-set.cc
@@ -27,6 +27,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if ENABLE_ANALYZER
 
+namespace ana {
+
 /* Return true if NAME is within this set.  */
 
 bool
@@ -188,4 +190,6 @@  analyzer_function_set_cc_tests ()
 
 #endif /* CHECKING_P */
 
+} // namespace ana
+
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/function-set.h b/gcc/analyzer/function-set.h
index 9c73bf57ade..f12ca72c42c 100644
--- a/gcc/analyzer/function-set.h
+++ b/gcc/analyzer/function-set.h
@@ -21,6 +21,8 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_FUNCTION_SET_H
 #define GCC_ANALYZER_FUNCTION_SET_H
 
+namespace ana {
+
 /* A set of names.  */
 
 class function_set
@@ -43,4 +45,6 @@  private:
   size_t m_count;
 };
 
+} // namespace ana
+
 #endif /* GCC_ANALYZER_FUNCTION_SET_H */
diff --git a/gcc/analyzer/pending-diagnostic.cc b/gcc/analyzer/pending-diagnostic.cc
index b692c98304f..c196903afe0 100644
--- a/gcc/analyzer/pending-diagnostic.cc
+++ b/gcc/analyzer/pending-diagnostic.cc
@@ -35,6 +35,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if ENABLE_ANALYZER
 
+namespace ana {
+
 /* Generate a label_text by printing FMT.
 
    Use a clone of the global_dc for formatting callbacks.
@@ -76,4 +78,6 @@  pending_diagnostic::same_tree_p (tree t1, tree t2)
   return simple_cst_equal (t1, t2) == 1;
 }
 
+} // namespace ana
+
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/pending-diagnostic.h b/gcc/analyzer/pending-diagnostic.h
index 6132fcfa481..b1ff2688bcc 100644
--- a/gcc/analyzer/pending-diagnostic.h
+++ b/gcc/analyzer/pending-diagnostic.h
@@ -21,6 +21,8 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_PENDING_DIAGNOSTIC_H
 #define GCC_ANALYZER_PENDING_DIAGNOSTIC_H
 
+namespace ana {
+
 /* Various bundles of information used for generating more precise
    messages for events within a diagnostic_path, for passing to the
    various "describe_*" vfuncs of pending_diagnostic.  See those
@@ -267,4 +269,6 @@  class pending_diagnostic_subclass : public pending_diagnostic
   }
 };
 
+} // namespace ana
+
 #endif /* GCC_ANALYZER_PENDING_DIAGNOSTIC_H */
diff --git a/gcc/analyzer/program-point.cc b/gcc/analyzer/program-point.cc
index e85f1ba49f0..2e7f7694111 100644
--- a/gcc/analyzer/program-point.cc
+++ b/gcc/analyzer/program-point.cc
@@ -55,6 +55,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if ENABLE_ANALYZER
 
+namespace ana {
+
 /* Get a string for PK.  */
 
 const char *
@@ -551,4 +553,6 @@  analyzer_program_point_cc_tests ()
 
 #endif /* CHECKING_P */
 
+} // namespace ana
+
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/program-point.h b/gcc/analyzer/program-point.h
index b9fe548f3a6..3772a419d1a 100644
--- a/gcc/analyzer/program-point.h
+++ b/gcc/analyzer/program-point.h
@@ -21,6 +21,8 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_PROGRAM_POINT_H
 #define GCC_ANALYZER_PROGRAM_POINT_H
 
+namespace ana {
+
 class exploded_graph;
 
 /* An enum for distinguishing the various kinds of program_point.  */
@@ -307,4 +309,6 @@  public:
   call_string m_call_string;
 };
 
+} // namespace ana
+
 #endif /* GCC_ANALYZER_PROGRAM_POINT_H */
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index 7dbdf9df84e..72daee6428e 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -57,6 +57,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if ENABLE_ANALYZER
 
+namespace ana {
+
 /* class sm_state_map.  */
 
 /* sm_state_map's ctor.  */
@@ -1396,4 +1398,6 @@  analyzer_program_state_cc_tests ()
 
 #endif /* CHECKING_P */
 
+} // namespace ana
+
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h
index 155eaf877ef..a2c5c9a1137 100644
--- a/gcc/analyzer/program-state.h
+++ b/gcc/analyzer/program-state.h
@@ -21,6 +21,8 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_PROGRAM_STATE_H
 #define GCC_ANALYZER_PROGRAM_STATE_H
 
+namespace ana {
+
 /* Data shared by all program_state instances.  */
 
 class extrinsic_state
@@ -47,6 +49,8 @@  public:
   auto_delete_vec <state_machine> &m_checkers;
 };
 
+} // namespace ana
+
 template <> struct default_hash_traits<svalue_id>
 : public pod_hash_traits<svalue_id>
 {
@@ -92,6 +96,8 @@  pod_hash_traits<svalue_id>::is_empty (value_type v)
   return v.null_p ();
 }
 
+namespace ana {
+
 /* Map from svalue_id to state machine state, also capturing the origin of
    each state.  */
 
@@ -362,4 +368,6 @@  class state_change
   auto_vec<sm_change> m_sm_changes;
 };
 
+} // namespace ana
+
 #endif /* GCC_ANALYZER_PROGRAM_STATE_H */
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 1e0be312e03..7e995701dce 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -62,6 +62,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if ENABLE_ANALYZER
 
+namespace ana {
+
 /* Dump T to PP in language-independent form, for debugging/logging/dumping
    purposes.  */
 
@@ -6901,6 +6903,8 @@  canonicalization::dump () const
   dump (stderr);
 }
 
+} // namespace ana
+
 /* Update HSTATE with a hash of SID.  */
 
 void
@@ -6925,6 +6929,8 @@  debug (const region_model &rmodel)
   rmodel.dump (false);
 }
 
+namespace ana {
+
 #if CHECKING_P
 
 namespace selftest {
@@ -7979,4 +7985,6 @@  analyzer_region_model_cc_tests ()
 
 #endif /* CHECKING_P */
 
+} // namespace ana
+
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h
index eea808e61eb..6a63a9336b8 100644
--- a/gcc/analyzer/region-model.h
+++ b/gcc/analyzer/region-model.h
@@ -31,6 +31,10 @@  along with GCC; see the file COPYING3.  If not see
    recursive callstack.  */
 // TODO: would this be better as a new tree code?
 
+using namespace ana;
+
+namespace ana {
+
 class path_var
 {
 public:
@@ -52,12 +56,16 @@  public:
   int m_stack_depth; // or -1 for globals?
 };
 
+} // namespace ana
+
 namespace inchash
 {
   extern void add_path_var (path_var pv, hash &hstate);
 } // namespace inchash
 
 
+namespace ana {
+
 /* A region_model is effectively a graph of regions and symbolic values.
    We store per-model IDs rather than pointers to make it easier to clone
    and to compare graphs.  */
@@ -549,6 +557,8 @@  public:
   region_id m_rid;
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -557,6 +567,8 @@  is_a_helper <region_svalue *>::test (svalue *sval)
   return sval->get_kind () == SK_REGION;
 }
 
+namespace ana {
+
 /* Concrete subclass of svalue representing a specific constant value.  */
 
 class constant_svalue : public svalue
@@ -606,6 +618,8 @@  public:
   tree m_cst_expr;
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -614,6 +628,8 @@  is_a_helper <constant_svalue *>::test (svalue *sval)
   return sval->get_kind () == SK_CONSTANT;
 }
 
+namespace ana {
+
 /* Concrete subclass of svalue representing a unique but unknown value.
    Comparisons of variables that share the same unknown value are known
    to be equal, even if we don't know what the value is.  */
@@ -690,6 +706,8 @@  public:
   enum poison_kind m_kind;
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -698,6 +716,8 @@  is_a_helper <poisoned_svalue *>::test (svalue *sval)
   return sval->get_kind () == SK_POISONED;
 }
 
+namespace ana {
+
 /* Concrete subclass of svalue representing setjmp buffers, so that
    longjmp can potentially "return" to an entirely different function.  */
 
@@ -876,6 +896,8 @@  public:
   region_id m_active_view_rid;
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -884,6 +906,8 @@  is_a_helper <region *>::test (region *)
   return true;
 }
 
+namespace ana {
+
 /* Concrete region subclass for storing "primitive" types (integral types,
    pointers, etc).  */
 
@@ -972,6 +996,8 @@  public:
   map_t m_map;
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -980,6 +1006,8 @@  is_a_helper <map_region *>::test (region *reg)
   return (reg->dyn_cast_map_region () != NULL);
 }
 
+namespace ana {
+
 /* Abstract subclass representing a region with fields
    (either a struct or a union).  */
 
@@ -996,6 +1024,8 @@  public:
   bool compare_fields (const struct_or_union_region &other) const;
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -1005,6 +1035,8 @@  is_a_helper <struct_or_union_region *>::test (region *reg)
 	  || reg->get_kind () == RK_UNION);
 }
 
+namespace ana {
+
 /* Concrete region subclass.  A map_region representing a struct, using
    FIELD_DECLs for its keys.  */
 
@@ -1024,6 +1056,8 @@  public:
   bool compare_fields (const struct_region &other) const;
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -1032,6 +1066,8 @@  is_a_helper <struct_region *>::test (region *reg)
   return reg->get_kind () == RK_STRUCT;
 }
 
+namespace ana {
+
 /* Concrete region subclass.  A map_region representing a union, using
    FIELD_DECLs for its keys.  */
 
@@ -1051,6 +1087,8 @@  public:
   bool compare_fields (const union_region &other) const;
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -1059,6 +1097,8 @@  is_a_helper <union_region *>::test (region *reg)
   return reg->get_kind () == RK_UNION;
 }
 
+namespace ana {
+
 /* Abstract map_region subclass for accessing decls, used as a base class
    for function frames and for the globals region.  */
 
@@ -1117,6 +1157,8 @@  public:
   int m_depth;
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -1125,6 +1167,8 @@  is_a_helper <frame_region *>::test (region *reg)
   return reg->get_kind () == RK_FRAME;
 }
 
+namespace ana {
+
 /* Concrete region subclass, to hold global variables (data and bss).  */
 
 class globals_region : public scope_region
@@ -1149,6 +1193,8 @@  class globals_region : public scope_region
   bool compare_fields (const globals_region &other) const;
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -1157,6 +1203,8 @@  is_a_helper <globals_region *>::test (region *reg)
   return reg->get_kind () == RK_GLOBALS;
 }
 
+namespace ana {
+
 /* Concrete region subclass.  A map_region representing the code, using
    FUNCTION_DECLs for its keys.  */
 
@@ -1185,6 +1233,8 @@  public:
   bool compare_fields (const code_region &other) const;
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -1193,6 +1243,8 @@  is_a_helper <code_region *>::test (region *reg)
   return reg->get_kind () == RK_CODE;
 }
 
+namespace ana {
+
 /* Concrete region subclass.  A map_region representing the code for
    a particular function, using LABEL_DECLs for its keys.  */
 
@@ -1223,6 +1275,8 @@  public:
   bool compare_fields (const function_region &other) const;
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -1231,6 +1285,8 @@  is_a_helper <function_region *>::test (region *reg)
   return reg->get_kind () == RK_FUNCTION;
 }
 
+namespace ana {
+
 /* Concrete region subclass representing an array (or an array-like view
    of a parent region of memory.
    This can't be a map_region as we can't use trees as the keys: there's
@@ -1323,6 +1379,8 @@  public:
   map_t m_map;
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -1331,6 +1389,8 @@  is_a_helper <array_region *>::test (region *reg)
   return reg->get_kind () == RK_ARRAY;
 }
 
+namespace ana {
+
 /* Concrete region subclass representing a stack, containing all stack
    frames, and implicitly providing a POISON_KIND_UNINIT value to all
    child regions by default.  */
@@ -1385,6 +1445,8 @@  public:
   auto_vec<region_id> m_frame_rids;
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -1393,6 +1455,8 @@  is_a_helper <stack_region *>::test (region *reg)
   return reg->get_kind () == RK_STACK;
 }
 
+namespace ana {
+
 /* Concrete region subclass: a region within which regions can be
    dynamically allocated.  */
 
@@ -1419,6 +1483,8 @@  public:
 
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -1427,6 +1493,8 @@  is_a_helper <heap_region *>::test (region *reg)
   return reg->get_kind () == RK_HEAP;
 }
 
+namespace ana {
+
 /* Concrete region subclass.  The root region, containing all regions
    (either directly, or as descendents).
    Unique within a region_model.  */
@@ -1495,6 +1563,8 @@  private:
   region_id m_heap_rid;
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -1503,6 +1573,8 @@  is_a_helper <root_region *>::test (region *reg)
   return reg->get_kind () == RK_ROOT;
 }
 
+namespace ana {
+
 /* Concrete region subclass: a region to use when dereferencing an unknown
    pointer.  */
 
@@ -1939,6 +2011,8 @@  struct canonicalization
   int m_next_sid_int;
 };
 
+} // namespace ana
+
 namespace inchash
 {
   extern void add (svalue_id sid, hash &hstate);
@@ -1947,10 +2021,14 @@  namespace inchash
 
 extern void debug (const region_model &rmodel);
 
+namespace ana {
+
 #if CHECKING_P
 
 namespace selftest {
 
+using namespace ::selftest;
+
 /* An implementation of region_model_context for use in selftests, which
    stores any pending_diagnostic instances passed to it.  */
 
@@ -2066,4 +2144,6 @@  void assert_condition (const location &loc,
 
 #endif /* #if CHECKING_P */
 
+} // namespace ana
+
 #endif /* GCC_ANALYZER_REGION_MODEL_H */
diff --git a/gcc/analyzer/sm-file.cc b/gcc/analyzer/sm-file.cc
index f731981b0f5..11444926538 100644
--- a/gcc/analyzer/sm-file.cc
+++ b/gcc/analyzer/sm-file.cc
@@ -39,6 +39,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if ENABLE_ANALYZER
 
+namespace ana {
+
 namespace {
 
 /* A state machine for detecting misuses of <stdio.h>'s FILE * API.  */
@@ -434,4 +436,6 @@  analyzer_sm_file_cc_tests ()
 
 #endif /* CHECKING_P */
 
+} // namespace ana
+
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index 15fa1c76471..526680accf2 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -38,6 +38,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if ENABLE_ANALYZER
 
+namespace ana {
+
 namespace {
 
 /* A state machine for detecting misuses of the malloc/free API.
@@ -794,4 +796,6 @@  make_malloc_state_machine (logger *logger)
   return new malloc_state_machine (logger);
 }
 
+} // namespace ana
+
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/sm-pattern-test.cc b/gcc/analyzer/sm-pattern-test.cc
index 571e13eb47c..cac78e7c041 100644
--- a/gcc/analyzer/sm-pattern-test.cc
+++ b/gcc/analyzer/sm-pattern-test.cc
@@ -39,6 +39,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if ENABLE_ANALYZER
 
+namespace ana {
+
 namespace {
 
 /* A state machine for use in DejaGnu tests, to check that
@@ -149,4 +151,6 @@  make_pattern_test_state_machine (logger *logger)
   return new pattern_test_state_machine (logger);
 }
 
+} // namespace ana
+
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/sm-sensitive.cc b/gcc/analyzer/sm-sensitive.cc
index 16b53e2c9e4..a067c18fba4 100644
--- a/gcc/analyzer/sm-sensitive.cc
+++ b/gcc/analyzer/sm-sensitive.cc
@@ -39,6 +39,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if ENABLE_ANALYZER
 
+namespace ana {
+
 namespace {
 
 /* An experimental state machine, for tracking exposure of sensitive
@@ -245,4 +247,6 @@  make_sensitive_state_machine (logger *logger)
   return new sensitive_state_machine (logger);
 }
 
+} // namespace ana
+
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/sm-signal.cc b/gcc/analyzer/sm-signal.cc
index 0057ab96d44..146ad713f86 100644
--- a/gcc/analyzer/sm-signal.cc
+++ b/gcc/analyzer/sm-signal.cc
@@ -61,6 +61,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if ENABLE_ANALYZER
 
+namespace ana {
+
 namespace {
 
 /* An experimental state machine, for tracking calls to async-signal-unsafe
@@ -367,5 +369,7 @@  analyzer_sm_signal_cc_tests ()
 
 } // namespace selftest
 
+} // namespace ana
+
 #endif /* CHECKING_P */
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc
index e454407e7af..00b794a3698 100644
--- a/gcc/analyzer/sm-taint.cc
+++ b/gcc/analyzer/sm-taint.cc
@@ -39,6 +39,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if ENABLE_ANALYZER
 
+namespace ana {
+
 namespace {
 
 /* An experimental state machine, for tracking "taint": unsanitized uses
@@ -325,4 +327,6 @@  make_taint_state_machine (logger *logger)
   return new taint_state_machine (logger);
 }
 
+} // namespace ana
+
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/sm.cc b/gcc/analyzer/sm.cc
index 03d65ffed3d..74fd17033ff 100644
--- a/gcc/analyzer/sm.cc
+++ b/gcc/analyzer/sm.cc
@@ -61,6 +61,8 @@  any_pointer_p (tree var)
   return POINTER_TYPE_P (TREE_TYPE (var));
 }
 
+namespace ana {
+
 /* Add a state with name NAME to this state_machine.
    The string is required to outlive the state_machine.
 
@@ -119,4 +121,6 @@  make_checkers (auto_delete_vec <state_machine> &out, logger *logger)
     }
 }
 
+} // namespace ana
+
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/sm.h b/gcc/analyzer/sm.h
index fb49630f073..25163d7a7b1 100644
--- a/gcc/analyzer/sm.h
+++ b/gcc/analyzer/sm.h
@@ -26,6 +26,8 @@  along with GCC; see the file COPYING3.  If not see
 extern tree is_zero_assignment (const gimple *stmt);
 extern bool any_pointer_p (tree var);
 
+namespace ana {
+
 class state_machine;
 class sm_context;
 class pending_diagnostic;
@@ -175,4 +177,6 @@  extern state_machine *make_sensitive_state_machine (logger *logger);
 extern state_machine *make_signal_state_machine (logger *logger);
 extern state_machine *make_pattern_test_state_machine (logger *logger);
 
+} // namespace ana
+
 #endif /* GCC_ANALYZER_SM_H */
diff --git a/gcc/analyzer/state-purge.h b/gcc/analyzer/state-purge.h
index e33733a6cc5..ee7d10c4c71 100644
--- a/gcc/analyzer/state-purge.h
+++ b/gcc/analyzer/state-purge.h
@@ -68,6 +68,8 @@  pod_hash_traits<function_point>::is_empty (value_type v)
   return v.get_kind () == PK_EMPTY;
 }
 
+namespace ana {
+
 /* The result of analyzing which SSA names can be purged from state at
    different points in the program, so that we can simplify program_state
    objects, in the hope of reducing state-blowup.  */
@@ -159,4 +161,6 @@  private:
   const state_purge_map *m_map;
 };
 
+} // namespace ana
+
 #endif /* GCC_ANALYZER_STATE_PURGE_H */
diff --git a/gcc/analyzer/supergraph.cc b/gcc/analyzer/supergraph.cc
index 1dcc2742568..4660239082a 100644
--- a/gcc/analyzer/supergraph.cc
+++ b/gcc/analyzer/supergraph.cc
@@ -54,6 +54,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #if ENABLE_ANALYZER
 
+namespace ana {
+
 /* Get the cgraph_edge, but only if there's an underlying function body.  */
 
 cgraph_edge *
@@ -976,4 +978,6 @@  callgraph_superedge::map_expr_from_callee_to_caller (tree callee_expr,
   return NULL_TREE;
 }
 
+} // namespace ana
+
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/supergraph.h b/gcc/analyzer/supergraph.h
index 4c0775c59e2..3580ae60c08 100644
--- a/gcc/analyzer/supergraph.h
+++ b/gcc/analyzer/supergraph.h
@@ -21,6 +21,10 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_SUPERGRAPH_H
 #define GCC_ANALYZER_SUPERGRAPH_H
 
+using namespace ana;
+
+namespace ana {
+
 /* Forward decls, using indentation to show inheritance.  */
 
 class supergraph;
@@ -372,6 +376,8 @@  class callgraph_superedge : public superedge
   cgraph_edge *const m_cedge;
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -382,6 +388,8 @@  is_a_helper <const callgraph_superedge *>::test (const superedge *sedge)
 	  || sedge->get_kind () == SUPEREDGE_RETURN);
 }
 
+namespace ana {
+
 /* A subclass of superedge representing an interprocedural call.  */
 
 class call_superedge : public callgraph_superedge
@@ -416,6 +424,8 @@  class call_superedge : public callgraph_superedge
   }
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -424,6 +434,8 @@  is_a_helper <const call_superedge *>::test (const superedge *sedge)
   return sedge->get_kind () == SUPEREDGE_CALL;
 }
 
+namespace ana {
+
 /* A subclass of superedge represesnting an interprocedural return.  */
 
 class return_superedge : public callgraph_superedge
@@ -453,6 +465,8 @@  class return_superedge : public callgraph_superedge
   }
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -461,6 +475,8 @@  is_a_helper <const return_superedge *>::test (const superedge *sedge)
   return sedge->get_kind () == SUPEREDGE_RETURN;
 }
 
+namespace ana {
+
 /* A subclass of superedge that corresponds to a CFG edge.  */
 
 class cfg_superedge : public superedge
@@ -487,6 +503,8 @@  class cfg_superedge : public superedge
   const ::edge m_cfg_edge;
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -495,6 +513,8 @@  is_a_helper <const cfg_superedge *>::test (const superedge *sedge)
   return sedge->get_kind () == SUPEREDGE_CFG_EDGE;
 }
 
+namespace ana {
+
 /* A subclass for edges from switch statements, retaining enough
    information to identify the pertinent case, and for adding labels
    when rendering via graphviz.  */
@@ -526,6 +546,8 @@  class switch_cfg_superedge : public cfg_superedge {
   const int m_idx;
 };
 
+} // namespace ana
+
 template <>
 template <>
 inline bool
@@ -534,6 +556,8 @@  is_a_helper <const switch_cfg_superedge *>::test (const superedge *sedge)
   return sedge->dyn_cast_switch_cfg_superedge () != NULL;
 }
 
+namespace ana {
+
 /* Base class for adding additional content to the .dot output
    for a supergraph.  */
 
@@ -551,4 +575,6 @@  class dot_annotator
 
 extern cgraph_edge *supergraph_call_edge (function *fun, gimple *stmt);
 
+} // namespace ana
+
 #endif /* GCC_ANALYZER_SUPERGRAPH_H */
diff --git a/gcc/gdbinit.in b/gcc/gdbinit.in
index c5b020c2180..c3f0acb9d95 100644
--- a/gcc/gdbinit.in
+++ b/gcc/gdbinit.in
@@ -220,11 +220,11 @@  command-line options).
 end
 
 define break-on-saved-diagnostic
-break diagnostic_manager::add_diagnostic
+break ana::diagnostic_manager::add_diagnostic
 end
 
 document break-on-saved-diagnostic
-Put a breakpoint on diagnostic_manager::add_diagnostic, called within
+Put a breakpoint on ana::diagnostic_manager::add_diagnostic, called within
 the analyzer whenever a diagnostic is saved for later de-duplication and
 possible emission.
 end
diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c
index e451387ab21..d47e92862f1 100644
--- a/gcc/selftest-run-tests.c
+++ b/gcc/selftest-run-tests.c
@@ -119,7 +119,7 @@  selftest::run_tests ()
   lang_hooks.run_lang_selftests ();
 
   /* Run the analyzer selftests (if enabled).  */
-  run_analyzer_selftests ();
+  ana::selftest::run_analyzer_selftests ();
 
   /* Force a GC at the end of the selftests, to shake out GC-related
      issues.  For example, if any GC-managed items have buggy (or missing)