diff --git a/gcc/analyzer/analyzer.opt b/gcc/analyzer/analyzer.opt
index b4dcdb8f451..9d1a937e403 100644
--- a/gcc/analyzer/analyzer.opt
+++ b/gcc/analyzer/analyzer.opt
@@ -262,6 +262,10 @@ fanalyzer-state-merge
 Common Var(flag_analyzer_state_merge) Init(1)
 Merge similar-enough states during analysis.
 
+fanalyzer-suppress-followups
+Common Var(flag_analyzer_suppress_followups) Init(1)
+Stop exploring an execution path after certain diagnostics.
+
 fanalyzer-transitivity
 Common Var(flag_analyzer_transitivity) Init(0)
 Enable transitivity of constraints during analysis.
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 24ded267019..a5965c2b8ff 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -125,11 +125,20 @@ impl_region_model_context::warn (std::unique_ptr<pending_diagnostic> d)
       return false;
     }
   if (m_eg)
-    return m_eg->get_diagnostic_manager ().add_diagnostic
-      (m_enode_for_diag, m_enode_for_diag->get_supernode (),
-       m_stmt, m_stmt_finder, std::move (d));
-  else
-    return false;
+    {
+      bool terminate_path = d->terminate_path_p ();
+      if (m_eg->get_diagnostic_manager ().add_diagnostic
+	  (m_enode_for_diag, m_enode_for_diag->get_supernode (),
+	   m_stmt, m_stmt_finder, std::move (d)))
+	{
+	  if (m_path_ctxt
+	      && terminate_path
+	      && flag_analyzer_suppress_followups)
+	    m_path_ctxt->terminate_path ();
+	  return true;
+	}
+    }
+  return false;
 }
 
 void
@@ -378,9 +387,14 @@ public:
       = (var
 	 ? m_old_smap->get_state (var_old_sval, m_eg.get_ext_state ())
 	 : m_old_smap->get_global_state ());
+    bool terminate_path = d->terminate_path_p ();
     m_eg.get_diagnostic_manager ().add_diagnostic
       (&m_sm, m_enode_for_diag, snode, stmt, m_stmt_finder,
        var, var_old_sval, current, std::move (d));
+    if (m_path_ctxt
+	&& terminate_path
+	&& flag_analyzer_suppress_followups)
+      m_path_ctxt->terminate_path ();
   }
 
   void warn (const supernode *snode, const gimple *stmt,
@@ -393,9 +407,14 @@ public:
       = (sval
 	 ? m_old_smap->get_state (sval, m_eg.get_ext_state ())
 	 : m_old_smap->get_global_state ());
+    bool terminate_path = d->terminate_path_p ();
     m_eg.get_diagnostic_manager ().add_diagnostic
       (&m_sm, m_enode_for_diag, snode, stmt, m_stmt_finder,
        NULL_TREE, sval, current, std::move (d));
+    if (m_path_ctxt
+	&& terminate_path
+	&& flag_analyzer_suppress_followups)
+      m_path_ctxt->terminate_path ();
   }
 
   /* Hook for picking more readable trees for SSA names of temporaries,
diff --git a/gcc/analyzer/pending-diagnostic.h b/gcc/analyzer/pending-diagnostic.h
index d9e9e7f8905..6423c8be4ea 100644
--- a/gcc/analyzer/pending-diagnostic.h
+++ b/gcc/analyzer/pending-diagnostic.h
@@ -173,6 +173,10 @@ class pending_diagnostic
      having to generate feasible execution paths for them).  */
   virtual int get_controlling_option () const = 0;
 
+  /* Vfunc to give the diagnostic the chance to terminate the execution
+     path being explored.  By default, don't terminate the path.  */
+  virtual bool terminate_path_p () const { return false; }
+
   /* Vfunc for emitting the diagnostic.  The rich_location will have been
      populated with a diagnostic_path.
      Return true if a diagnostic is actually emitted.  */
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index 9a1a8cd8e52..8dade4b5b3e 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -1105,6 +1105,27 @@ program_state::on_edge (exploded_graph &eg,
 			const superedge *succ,
 			uncertainty_t *uncertainty)
 {
+  class my_path_context : public path_context
+  {
+  public:
+    my_path_context (bool &terminated) : m_terminated (terminated) {}
+    void bifurcate (std::unique_ptr<custom_edge_info>) final override
+    {
+      gcc_unreachable ();
+    }
+
+    void terminate_path () final override
+    {
+      m_terminated = true;
+    }
+
+    bool terminate_path_p () const final override
+    {
+      return m_terminated;
+    }
+    bool &m_terminated;
+  };
+
   /* Update state.  */
   const program_point &point = enode->get_point ();
   const gimple *last_stmt = point.get_supernode ()->get_last_stmt ();
@@ -1117,11 +1138,12 @@ program_state::on_edge (exploded_graph &eg,
      Adding the relevant conditions for the edge could also trigger
      sm-state transitions (e.g. transitions due to ptrs becoming known
      to be NULL or non-NULL) */
-
+  bool terminated = false;
+  my_path_context path_ctxt (terminated);
   impl_region_model_context ctxt (eg, enode,
 				  &enode->get_state (),
 				  this,
-				  uncertainty, NULL,
+				  uncertainty, &path_ctxt,
 				  last_stmt);
   if (!m_region_model->maybe_update_for_edge (*succ,
 					      last_stmt,
@@ -1134,6 +1156,8 @@ program_state::on_edge (exploded_graph &eg,
 		     succ->m_dest->m_index);
       return false;
     }
+  if (terminated)
+    return false;
 
   program_state::detect_leaks (enode->get_state (), *this,
 			       NULL, eg.get_ext_state (),
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index e3de74bbf45..f844b519f61 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -505,6 +505,8 @@ public:
       }
   }
 
+  bool terminate_path_p () const final override { return true; }
+
   bool emit (rich_location *rich_loc) final override
   {
     switch (m_pkind)
diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index c24fe737481..1ea9b30fa13 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -1150,6 +1150,8 @@ public:
     return OPT_Wanalyzer_null_dereference;
   }
 
+  bool terminate_path_p () const final override { return true; }
+
   bool emit (rich_location *rich_loc) final override
   {
     /* CWE-476: NULL Pointer Dereference.  */
@@ -1203,6 +1205,8 @@ public:
     return OPT_Wanalyzer_null_argument;
   }
 
+  bool terminate_path_p () const final override { return true; }
+
   bool emit (rich_location *rich_loc) final override
   {
     /* CWE-476: NULL Pointer Dereference.  */
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 078d29d5313..bcf8510945b 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -428,6 +428,7 @@ Objective-C and Objective-C++ Dialects}.
 -fanalyzer-fine-grained @gol
 -fno-analyzer-state-merge @gol
 -fno-analyzer-state-purge @gol
+-fno-analyzer-suppress-followups @gol
 -fanalyzer-transitivity @gol
 -fno-analyzer-undo-inlining @gol
 -fanalyzer-verbose-edges @gol
@@ -11012,6 +11013,30 @@ and which aren't relevant to leak analysis.
 With @option{-fno-analyzer-state-purge} this purging of state can
 be suppressed, for debugging state-handling issues.
 
+@item -fno-analyzer-suppress-followups
+@opindex fanalyzer-suppress-followups
+@opindex fno-analyzer-suppress-followups
+This option is intended for analyzer developers.
+
+By default the analyzer will stop exploring an execution path after
+encountering certain diagnostics, in order to avoid potentially issuing a
+cascade of follow-up diagnostics.
+
+The diagnostics that terminate analysis along a path are:
+
+@itemize
+@item @option{-Wanalyzer-null-argument}
+@item @option{-Wanalyzer-null-dereference}
+@item @option{-Wanalyzer-use-after-free}
+@item @option{-Wanalyzer-use-of-pointer-in-stale-stack-frame}
+@item @option{-Wanalyzer-use-of-uninitialized-value}
+@end itemize
+
+With @option{-fno-analyzer-suppress-followups} the analyzer will
+continue to explore such paths even after such diagnostics, which may
+be helpful for debugging issues in the analyzer, or for microbenchmarks
+for detecting undefined behavior.
+
 @item -fanalyzer-transitivity
 @opindex fanalyzer-transitivity
 @opindex fno-analyzer-transitivity
diff --git a/gcc/testsuite/gcc.dg/analyzer/attribute-nonnull.c b/gcc/testsuite/gcc.dg/analyzer/attribute-nonnull.c
index 7c71a71c930..5700256c06a 100644
--- a/gcc/testsuite/gcc.dg/analyzer/attribute-nonnull.c
+++ b/gcc/testsuite/gcc.dg/analyzer/attribute-nonnull.c
@@ -16,8 +16,6 @@ void test_1 (void *p, void *q, void *r)
   foo(p, q, r);
   foo(NULL, q, r); /* { dg-warning "use of NULL where non-null expected" "warning" } */
   /* { dg-message "argument 1 NULL where non-null expected" "note" { target *-*-* } .-1 } */
-  foo(p, NULL, r);
-  foo(p, q, NULL); /* { dg-warning "use of NULL where non-null expected" } */
 }
 
 void test_1a (void *q, void *r)
@@ -27,12 +25,29 @@ void test_1a (void *q, void *r)
   /* { dg-message "argument 1 \\('p'\\) NULL where non-null expected" "note" { target *-*-* } .-1 } */
 }
 
-void test_2 (void *p, void *q, void *r)
+void test_1b (void *p, void *r)
+{
+  foo(p, NULL, r);
+}
+
+void test_1c (void *p, void *q, void *r)
+{
+  foo(p, q, NULL); /* { dg-warning "use of NULL where non-null expected" } */
+}
+
+void test_2a (void *p, void *q, void *r)
 {
   bar(p, q, r);
-  bar(NULL, q, r); /* { dg-warning "use of NULL where non-null expected" "warning" } */
+}
+
+void test_2b (void *p, void *q, void *r)
+{
   bar(p, NULL, r); /* { dg-warning "use of NULL where non-null expected" "warning" } */
   /* { dg-message "argument 2 NULL where non-null expected" "note" { target *-*-* } .-1 } */
+}
+
+void test_2c (void *p, void *q, void *r)
+{
   bar(p, q, NULL); /* { dg-warning "use of NULL where non-null expected" "warning" } */
 }
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/call-summaries-2.c b/gcc/testsuite/gcc.dg/analyzer/call-summaries-2.c
index 2d82d02e4e2..1bac24f4c67 100644
--- a/gcc/testsuite/gcc.dg/analyzer/call-summaries-2.c
+++ b/gcc/testsuite/gcc.dg/analyzer/call-summaries-2.c
@@ -607,17 +607,22 @@ void partially_inits (int *p, int v)
   p[1] = v;
 }
 
-void test_partially_inits (int x)
+void test_partially_inits_0 (int x)
 {
   int arr[2];
   partially_inits (arr, x);
   partially_inits (arr, x);
 
-  __analyzer_eval (arr[0]); /* { dg-warning "UNKNOWN" "eval" } */
-  /* { dg-warning "use of uninitialized value 'arr\\\[0\\\]'" "uninit" { target *-*-* } .-1 } */
+  __analyzer_eval (arr[0]); /* { dg-warning "use of uninitialized value 'arr\\\[0\\\]'" } */
+}
+
+void test_partially_inits_1 (int x)
+{
+  int arr[2];
+  partially_inits (arr, x);
+  partially_inits (arr, x);
 
-  __analyzer_eval (arr[1] == x); /* { dg-warning "UNKNOWN" "eval" } */ 
-  /* { dg-bogus "use of uninitialized value 'arr\\\[1\\\]'" "uninit" { xfail *-*-* } .-1 } */
+  __analyzer_eval (arr[1] == x); /* { dg-bogus "use of uninitialized value 'arr\\\[1\\\]'" "uninit" { xfail *-*-* } } */
   // TODO(xfail), and eval should be "TRUE"
 }
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-1.c b/gcc/testsuite/gcc.dg/analyzer/data-model-1.c
index d8930d189bb..86d1ccf11a7 100644
--- a/gcc/testsuite/gcc.dg/analyzer/data-model-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/data-model-1.c
@@ -351,9 +351,8 @@ void test_19 (void)
 {
   int i, j; /* { dg-message "region created on stack here" } */
   /* Compare two uninitialized locals.  */
-    __analyzer_eval (i == j); /* { dg-warning "UNKNOWN" "unknown " } */
-    /* { dg-warning "use of uninitialized value 'i'" "uninit i" { target *-*-* } .-1 } */
-    /* { dg-warning "use of uninitialized value 'j'" "uninit j" { target *-*-* } .-2 } */
+    __analyzer_eval (i == j); /* { dg-warning "use of uninitialized value 'i'" "uninit i" } */
+    /* { dg-warning "use of uninitialized value 'j'" "uninit j" { target *-*-* } .-1 } */
 }
 
 void test_20 (int i, int j)
@@ -653,11 +652,6 @@ void test_29b (void)
   __analyzer_eval (p[9].x == 109024); /* { dg-warning "TRUE" } */
   __analyzer_eval (p[9].y == 109025); /* { dg-warning "TRUE" } */
 
-  __analyzer_eval (p[10].x == 0); /* { dg-warning "UNKNOWN" "unknown" } */
-  /* { dg-warning "use of uninitialized value 'p\\\[10\\\].x'" "uninit" { target *-*-* } .-1 } */
-  __analyzer_eval (p[10].y == 0); /* { dg-warning "UNKNOWN" "unknown" } */
-  /* { dg-warning "use of uninitialized value 'p\\\[10\\\].y'" "uninit" { target *-*-* } .-1 } */
-
   q = &p[7];
 
   __analyzer_eval (q->x == 107024); /* { dg-warning "TRUE" } */
@@ -679,6 +673,8 @@ void test_29b (void)
 
   __analyzer_eval (q->x == 107024); /* { dg-warning "TRUE" } */
   __analyzer_eval (q->y == 107025); /* { dg-warning "TRUE" } */
+
+  __analyzer_eval (p[10].x == 0); /* { dg-warning "use of uninitialized value 'p\\\[10\\\].x'" } */
 }
 
 void test_29c (int len)
@@ -704,11 +700,6 @@ void test_29c (int len)
   __analyzer_eval (p[9].x == 109024); /* { dg-warning "TRUE" } */
   __analyzer_eval (p[9].y == 109025); /* { dg-warning "TRUE" } */
 
-  __analyzer_eval (p[10].x == 0); /* { dg-warning "UNKNOWN" "unknown" } */
-  /* { dg-warning "use of uninitialized value '\\*p\\\[10\\\].x'" "uninit" { target *-*-* } .-1 } */
-  __analyzer_eval (p[10].y == 0); /* { dg-warning "UNKNOWN" "unknown" } */
-  /* { dg-warning "use of uninitialized value '\\*p\\\[10\\\].y'" "uninit" { target *-*-* } .-1 } */
-
   q = &p[7];
 
   __analyzer_eval (q->x == 107024); /* { dg-warning "TRUE" } */
@@ -730,6 +721,8 @@ void test_29c (int len)
 
   __analyzer_eval (q->x == 107024); /* { dg-warning "TRUE" } */
   __analyzer_eval (q->y == 107025); /* { dg-warning "TRUE" } */
+
+  __analyzer_eval (p[10].x == 0); /* { dg-warning "use of uninitialized value '\\*p\\\[10\\\].x'" } */
 }
 
 void test_30 (void *ptr)
diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-5.c b/gcc/testsuite/gcc.dg/analyzer/data-model-5.c
index 2135c70eb8d..b71bad757a1 100644
--- a/gcc/testsuite/gcc.dg/analyzer/data-model-5.c
+++ b/gcc/testsuite/gcc.dg/analyzer/data-model-5.c
@@ -90,10 +90,6 @@ void unref (base_obj *obj)
 {
   if (--obj->ob_refcnt == 0) /* { dg-bogus "dereference of uninitialized pointer 'obj'" } */
     obj->ob_type->tp_dealloc (obj);
-  /* { dg-warning "dereference of NULL 'obj'" "deref of NULL" { target *-*-* } .-2 } */
-  /* FIXME: ideally we wouldn't issue this, as we've already issued a
-     warning about str_obj which is now in the "stop" state; the cast
-     confuses things.  */
 }
 
 void test_1 (const char *str)
diff --git a/gcc/testsuite/gcc.dg/analyzer/doom-s_sound-pr108867.c b/gcc/testsuite/gcc.dg/analyzer/doom-s_sound-pr108867.c
new file mode 100644
index 00000000000..ebbfed2982a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/doom-s_sound-pr108867.c
@@ -0,0 +1,653 @@
+/* Reduced from Doom's linuxdoom-1.10/s_sound.c, which is GPLv2 or later.  */
+
+/* { dg-additional-options "-fno-analyzer-call-summaries -Wno-analyzer-too-complex" } */
+
+typedef struct _IO_FILE FILE;
+extern FILE* stderr;
+extern int
+fprintf(FILE* __restrict __stream, const char* __restrict __format, ...);
+extern int
+sprintf(char* __restrict __s, const char* __restrict __format, ...)
+  __attribute__((__nothrow__));
+extern int
+abs(int __x) __attribute__((__nothrow__, __leaf__)) __attribute__((__const__));
+
+typedef enum
+{
+  false,
+  true
+} boolean;
+
+typedef unsigned char byte;
+
+void
+I_Error(char* error, ...);
+
+typedef enum
+{
+  shareware,
+  registered,
+  commercial,
+  /* [...snip...] */
+} GameMode_t;
+
+typedef int fixed_t;
+
+fixed_t
+FixedMul(fixed_t a, fixed_t b);
+
+extern fixed_t finesine[5 * 8192 / 4];
+typedef unsigned angle_t;
+
+typedef struct mobj_s
+{
+  /* [...snip...] */
+  fixed_t x;
+  fixed_t y;
+  fixed_t z;
+  /* [...snip...] */
+  angle_t angle;
+  /* [...snip...] */
+} mobj_t;
+
+typedef struct player_s
+{
+  mobj_t* mo;
+  /* [...snip...] */
+} player_t;
+
+extern GameMode_t gamemode;
+extern int gameepisode;
+extern int gamemap;
+extern int consoleplayer;
+extern player_t players[4];
+
+typedef struct sfxinfo_struct sfxinfo_t;
+
+struct sfxinfo_struct
+{
+  /* [...snip...] */
+  int priority;
+  sfxinfo_t* link;
+  int pitch;
+  int volume;
+  void* data;
+  int usefulness;
+  int lumpnum;
+};
+
+typedef struct
+{
+  char* name;
+  int lumpnum;
+  void* data;
+  int handle;
+} musicinfo_t;
+
+extern sfxinfo_t S_sfx[];
+
+extern musicinfo_t S_music[];
+
+typedef enum
+{
+  mus_None,
+  mus_e1m1,
+  /* [...snip...] */
+  mus_e1m5,
+  /* [...snip...] */
+  mus_e1m9,
+  /* [...snip...] */
+  mus_e2m4,
+  mus_e2m5,
+  mus_e2m6,
+  mus_e2m7,
+  /* [...snip...] */
+  mus_e3m2,
+  mus_e3m3,
+  mus_e3m4,
+  /* [...snip...] */
+  mus_runnin,
+  /* [...snip...] */
+  NUMMUSIC
+} musicenum_t;
+
+typedef enum
+{
+  /* [...snip...] */
+  sfx_sawup,
+  /* [...snip...] */
+  sfx_sawhit,
+  /* [...snip...] */
+  sfx_itemup,
+  /* [...snip...] */
+  sfx_tink,
+  /* [...snip...] */
+  NUMSFX
+} sfxenum_t;
+
+
+void
+I_SetChannels();
+
+int
+I_GetSfxLumpNum(sfxinfo_t* sfxinfo);
+
+int
+I_StartSound(int id, int vol, int sep, int pitch, int priority);
+
+void
+I_StopSound(int handle);
+int
+I_SoundIsPlaying(int handle);
+void
+I_UpdateSoundParams(int handle, int vol, int sep, int pitch);
+
+void
+I_SetMusicVolume(int volume);
+
+void
+I_PauseSong(int handle);
+void
+I_ResumeSong(int handle);
+int
+I_RegisterSong(void* data);
+
+void
+I_PlaySong(int handle, int looping);
+
+void
+I_StopSong(int handle);
+
+void
+I_UnRegisterSong(int handle);
+void
+S_StopSound(void* origin);
+void
+S_ChangeMusic(int music_id, int looping);
+void
+S_StopMusic(void);
+
+void
+S_SetMusicVolume(int volume);
+void
+S_SetSfxVolume(int volume);
+
+void*
+Z_Malloc(int size, int tag, void* ptr);
+void
+Z_ChangeTag2(void* ptr, int tag);
+
+typedef struct memblock_s
+{
+  /* [...snip...] */
+  int id;
+  /* [...snip...] */
+} memblock_t;
+int
+M_Random(void);
+int
+W_GetNumForName(char* name);
+void*
+W_CacheLumpNum(int lump, int tag);
+angle_t
+R_PointToAngle2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2);
+
+typedef struct
+{
+  sfxinfo_t* sfxinfo;
+  void* origin;
+  int handle;
+} channel_t;
+static channel_t* channels;
+
+int snd_SfxVolume = 15;
+int snd_MusicVolume = 15;
+static boolean mus_paused;
+static musicinfo_t* mus_playing = 0;
+int numChannels;
+static int nextcleanup;
+
+int
+S_getChannel(void* origin, sfxinfo_t* sfxinfo);
+
+int
+S_AdjustSoundParams(mobj_t* listener,
+                    mobj_t* source,
+                    int* vol,
+                    int* sep,
+                    int* pitch);
+void
+S_StopChannel(int cnum);
+
+void
+S_Init(int sfxVolume, int musicVolume)
+{
+  int i;
+
+  fprintf(stderr, "S_Init: default sfx volume %d\n", sfxVolume);
+
+  I_SetChannels();
+
+  S_SetSfxVolume(sfxVolume);
+
+  S_SetMusicVolume(musicVolume);
+
+  channels = (channel_t*)Z_Malloc(numChannels * sizeof(channel_t), 1, 0);
+
+  for (i = 0; i < numChannels; i++)
+    channels[i].sfxinfo = 0;
+
+  mus_paused = 0;
+
+  for (i = 1; i < NUMSFX; i++)
+    S_sfx[i].lumpnum = S_sfx[i].usefulness = -1;
+}
+void
+S_Start(void)
+{
+  int cnum;
+  int mnum;
+
+  for (cnum = 0; cnum < numChannels; cnum++)
+    if (channels[cnum].sfxinfo)
+      S_StopChannel(cnum);
+
+  mus_paused = 0;
+
+  if (gamemode == commercial)
+    mnum = mus_runnin + gamemap - 1;
+  else {
+    int spmus[] = {
+
+      mus_e3m4, mus_e3m2, mus_e3m3, mus_e1m5, mus_e2m7,
+      mus_e2m4, mus_e2m6, mus_e2m5, mus_e1m9
+    };
+
+    if (gameepisode < 4)
+      mnum = mus_e1m1 + (gameepisode - 1) * 9 + gamemap - 1;
+    else
+      mnum = spmus[gamemap - 1];
+  }
+
+  S_ChangeMusic(mnum, true);
+
+  nextcleanup = 15;
+}
+
+void
+S_StartSoundAtVolume(void* origin_p, int sfx_id, int volume)
+{
+
+  int rc;
+  int sep;
+  int pitch;
+  int priority;
+  sfxinfo_t* sfx;
+  int cnum;
+
+  mobj_t* origin = (mobj_t*)origin_p;
+  if (sfx_id < 1 || sfx_id > NUMSFX)
+    I_Error("Bad sfx #: %d", sfx_id);
+
+  sfx = &S_sfx[sfx_id];
+
+  if (sfx->link) {
+    pitch = sfx->pitch;
+    priority = sfx->priority;
+    volume += sfx->volume;
+
+    if (volume < 1)
+      return;
+
+    if (volume > snd_SfxVolume)
+      volume = snd_SfxVolume;
+  } else {
+    pitch = 128;
+    priority = 64;
+  }
+
+  if (origin && origin != players[consoleplayer].mo) {
+    rc = S_AdjustSoundParams(
+      players[consoleplayer].mo, origin, &volume, &sep, &pitch);
+
+    if (origin->x == players[consoleplayer].mo->x &&
+        origin->y == players[consoleplayer].mo->y) {
+      sep = 128;
+    }
+
+    if (!rc)
+      return;
+  } else {
+    sep = 128;
+  }
+
+  if (sfx_id >= sfx_sawup && sfx_id <= sfx_sawhit) {
+    pitch += 8 - (M_Random() & 15);
+
+    if (pitch < 0)
+      pitch = 0;
+    else if (pitch > 255)
+      pitch = 255;
+  } else if (sfx_id != sfx_itemup && sfx_id != sfx_tink) {
+    pitch += 16 - (M_Random() & 31);
+
+    if (pitch < 0)
+      pitch = 0;
+    else if (pitch > 255)
+      pitch = 255;
+  }
+
+  S_StopSound(origin);
+
+  cnum = S_getChannel(origin, sfx);
+
+  if (cnum < 0)
+    return;
+  if (sfx->lumpnum < 0)
+    sfx->lumpnum = I_GetSfxLumpNum(sfx);
+
+  if (!sfx->data) {
+    fprintf(stderr, "S_StartSoundAtVolume: 16bit and not pre-cached - wtf?\n");
+  }
+
+  if (sfx->usefulness++ < 0)
+    sfx->usefulness = 1;
+
+  channels[cnum].handle = I_StartSound(sfx_id,
+
+                                       volume,
+                                       sep,
+                                       pitch,
+                                       priority);
+}
+
+void
+S_StartSound(void* origin, int sfx_id)
+{
+
+  S_StartSoundAtVolume(origin, sfx_id, snd_SfxVolume);
+}
+
+void
+S_StopSound(void* origin)
+{
+
+  int cnum;
+
+  for (cnum = 0; cnum < numChannels; cnum++) {
+    if (channels[cnum].sfxinfo && channels[cnum].origin == origin) {
+      S_StopChannel(cnum);
+      break;
+    }
+  }
+}
+void
+S_PauseSound(void)
+{
+  if (mus_playing && !mus_paused) {
+    I_PauseSong(mus_playing->handle);
+    mus_paused = true;
+  }
+}
+
+void
+S_ResumeSound(void)
+{
+  if (mus_playing && mus_paused) {
+    I_ResumeSong(mus_playing->handle);
+    mus_paused = false;
+  }
+}
+
+void
+S_UpdateSounds(void* listener_p)
+{
+  int audible;
+  int cnum;
+  int volume;
+  int sep;
+  int pitch;
+  sfxinfo_t* sfx;
+  channel_t* c;
+
+  mobj_t* listener = (mobj_t*)listener_p;
+  for (cnum = 0; cnum < numChannels; cnum++) {
+    c = &channels[cnum];
+    sfx = c->sfxinfo;
+
+    if (c->sfxinfo) {
+      if (I_SoundIsPlaying(c->handle)) {
+
+        volume = snd_SfxVolume;
+        pitch = 128;
+        sep = 128;
+
+        if (sfx->link) {
+          pitch = sfx->pitch;
+          volume += sfx->volume;
+          if (volume < 1) {
+            S_StopChannel(cnum);
+            continue;
+          } else if (volume > snd_SfxVolume) {
+            volume = snd_SfxVolume;
+          }
+        }
+
+        if (c->origin && listener_p != c->origin) {
+          audible =
+            S_AdjustSoundParams(listener, c->origin, &volume, &sep, &pitch);
+
+          if (!audible) {
+            S_StopChannel(cnum);
+          } else
+            I_UpdateSoundParams(c->handle, volume, sep, pitch);
+        }
+      } else {
+
+        S_StopChannel(cnum);
+      }
+    }
+  }
+}
+
+void
+S_SetMusicVolume(int volume)
+{
+  if (volume < 0 || volume > 127) {
+    I_Error("Attempt to set music volume at %d", volume);
+  }
+
+  I_SetMusicVolume(127);
+  I_SetMusicVolume(volume);
+  snd_MusicVolume = volume;
+}
+
+void
+S_SetSfxVolume(int volume)
+{
+
+  if (volume < 0 || volume > 127)
+    I_Error("Attempt to set sfx volume at %d", volume);
+
+  snd_SfxVolume = volume;
+}
+
+void
+S_StartMusic(int m_id)
+{
+  S_ChangeMusic(m_id, false);
+}
+
+void
+S_ChangeMusic(int musicnum, int looping)
+{
+  musicinfo_t* music;
+  char namebuf[9];
+
+  if ((musicnum <= mus_None) || (musicnum >= NUMMUSIC)) {
+    I_Error("Bad music number %d", musicnum);
+  } else
+    music = &S_music[musicnum];
+
+  /* We don't know that I_Error exits, so actually a false positive;
+     see PR analyzer/108867.  */
+
+  if (mus_playing == music) /* { dg-warning "use of uninitialized value 'music'" } */
+    return;
+
+  S_StopMusic();
+
+  /* We shouldn't issue further warnings about 'music' being
+     uninitialized.  */
+
+  if (!music->lumpnum) { /* { dg-bogus "use of uninitialized value 'music'" } */
+    sprintf(namebuf, "d_%s", music->name); /* { dg-bogus "use of uninitialized value 'music'" } */
+    music->lumpnum = W_GetNumForName(namebuf); /* { dg-bogus "use of uninitialized value 'music'" } */
+  }
+
+  music->data = (void*)W_CacheLumpNum(music->lumpnum, 3); /* { dg-bogus "use of uninitialized value 'music'" } */
+  music->handle = I_RegisterSong(music->data); /* { dg-bogus "use of uninitialized value 'music'" } */
+
+  I_PlaySong(music->handle, looping); /* { dg-bogus "use of uninitialized value 'music'" } */
+
+  mus_playing = music; /* { dg-bogus "use of uninitialized value 'music'" } */
+}
+
+void
+S_StopMusic(void)
+{
+  if (mus_playing) {
+    if (mus_paused)
+      I_ResumeSong(mus_playing->handle);
+
+    I_StopSong(mus_playing->handle);
+    I_UnRegisterSong(mus_playing->handle);
+    {
+      if (((memblock_t*)((byte*)(mus_playing->data) - sizeof(memblock_t)))
+            ->id != 0x1d4a11)
+        I_Error("Z_CT at "
+                "s_sound.c"
+                ":%i",
+                699);
+      Z_ChangeTag2(mus_playing->data, 101);
+    };
+    ;
+
+    mus_playing->data = 0;
+    mus_playing = 0;
+  }
+}
+
+void
+S_StopChannel(int cnum)
+{
+
+  int i;
+  channel_t* c = &channels[cnum];
+
+  if (c->sfxinfo) {
+
+    if (I_SoundIsPlaying(c->handle)) {
+
+      I_StopSound(c->handle);
+    }
+
+    for (i = 0; i < numChannels; i++) {
+      if (cnum != i && c->sfxinfo == channels[i].sfxinfo) {
+        break;
+      }
+    }
+
+    c->sfxinfo->usefulness--;
+
+    c->sfxinfo = 0;
+  }
+}
+int
+S_AdjustSoundParams(mobj_t* listener,
+                    mobj_t* source,
+                    int* vol,
+                    int* sep,
+                    int* pitch)
+{
+  fixed_t approx_dist;
+  fixed_t adx;
+  fixed_t ady;
+  angle_t angle;
+
+  adx = abs(listener->x - source->x);
+  ady = abs(listener->y - source->y);
+
+  approx_dist = adx + ady - ((adx < ady ? adx : ady) >> 1);
+
+  if (gamemap != 8 && approx_dist > (1200 * 0x10000)) {
+    return 0;
+  }
+
+  angle = R_PointToAngle2(listener->x, listener->y, source->x, source->y);
+
+  if (angle > listener->angle)
+    angle = angle - listener->angle;
+  else
+    angle = angle + (0xffffffff - listener->angle);
+
+  angle >>= 19;
+
+  *sep = 128 - (FixedMul((96 * 0x10000), finesine[angle]) >> 16);
+
+  if (approx_dist < (160 * 0x10000)) {
+    *vol = snd_SfxVolume;
+  } else if (gamemap == 8) {
+    if (approx_dist > (1200 * 0x10000))
+      approx_dist = (1200 * 0x10000);
+
+    *vol =
+      15 + ((snd_SfxVolume - 15) * (((1200 * 0x10000) - approx_dist) >> 16)) /
+             (((1200 * 0x10000) - (160 * 0x10000)) >> 16);
+  } else {
+
+    *vol = (snd_SfxVolume * (((1200 * 0x10000) - approx_dist) >> 16)) /
+           (((1200 * 0x10000) - (160 * 0x10000)) >> 16);
+  }
+
+  return (*vol > 0);
+}
+int
+S_getChannel(void* origin, sfxinfo_t* sfxinfo)
+{
+
+  int cnum;
+
+  channel_t* c;
+
+  for (cnum = 0; cnum < numChannels; cnum++) {
+    if (!channels[cnum].sfxinfo)
+      break;
+    else if (origin && channels[cnum].origin == origin) {
+      S_StopChannel(cnum);
+      break;
+    }
+  }
+
+  if (cnum == numChannels) {
+
+    for (cnum = 0; cnum < numChannels; cnum++)
+      if (channels[cnum].sfxinfo->priority >= sfxinfo->priority) /* { dg-warning "dereference of NULL" } */
+        break;
+
+    if (cnum == numChannels) {
+
+      return -1;
+    } else {
+
+      S_StopChannel(cnum);
+    }
+  }
+
+  c = &channels[cnum];
+
+  c->sfxinfo = sfxinfo;
+  c->origin = origin;
+
+  return cnum;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/memset-CVE-2017-18549-1.c b/gcc/testsuite/gcc.dg/analyzer/memset-CVE-2017-18549-1.c
index b12408a69a0..418168d413e 100644
--- a/gcc/testsuite/gcc.dg/analyzer/memset-CVE-2017-18549-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/memset-CVE-2017-18549-1.c
@@ -5,6 +5,8 @@
    It was fixed by e.g. 342ffc26693b528648bdc9377e51e4f2450b4860 on linux-4.13.y
    in linux-stable.  */
 
+/* { dg-additional-options "-fno-analyzer-suppress-followups" } */
+
 #include "analyzer-decls.h"
 #include <string.h>
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/null-deref-pr108830.c b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr108830.c
new file mode 100644
index 00000000000..417ab00794d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr108830.c
@@ -0,0 +1,94 @@
+/* Reduced from apr-1.7.0/tables/apr_hash.c: 'apr_hash_merge' */
+
+/* { dg-additional-options "-Wno-analyzer-too-complex" } */
+
+#define NULL ((void*)0)
+
+typedef __SIZE_TYPE__ size_t;
+
+extern void*
+memset(void* __s, int __c, size_t __n)
+  __attribute__((__nothrow__, __leaf__, __nonnull__(1)));
+
+typedef struct apr_pool_t apr_pool_t;
+
+void*
+apr_palloc(apr_pool_t* p, size_t size)
+  __attribute__((alloc_size(2), nonnull(1)));
+
+typedef struct apr_hash_t apr_hash_t;
+typedef struct apr_hash_index_t apr_hash_index_t;
+typedef unsigned int (*apr_hashfunc_t)(const char* key, size_t* klen);
+typedef struct apr_hash_entry_t apr_hash_entry_t;
+
+struct apr_hash_entry_t
+{
+  apr_hash_entry_t* next;
+  unsigned int hash;
+  const void* key;
+  size_t klen;
+  const void* val;
+};
+
+struct apr_hash_t
+{
+  apr_pool_t* pool;
+  apr_hash_entry_t** array;
+  /* [...snip.../ */
+  unsigned int count, max, seed;
+  apr_hashfunc_t hash_func;
+  apr_hash_entry_t* free;
+};
+
+static apr_hash_entry_t**
+alloc_array(apr_hash_t* ht, unsigned int max)
+{
+  return memset(apr_palloc(ht->pool, sizeof(*ht->array) * (max + 1)),
+                0,
+                sizeof(*ht->array) * (max + 1));
+}
+
+apr_hash_t*
+apr_hash_merge(apr_pool_t* p,
+               const apr_hash_t* overlay,
+               const apr_hash_t* base)
+{
+  apr_hash_t* res;
+  apr_hash_entry_t* new_vals = NULL;
+  apr_hash_entry_t* iter;
+  unsigned int i, j, k;
+  res = apr_palloc(p, sizeof(apr_hash_t));
+  res->pool = p;
+  res->free = NULL;
+  res->hash_func = base->hash_func;
+  res->count = base->count;
+  res->max = (overlay->max > base->max) ? overlay->max : base->max;
+  if (base->count + overlay->count > res->max) {
+    res->max = res->max * 2 + 1;
+  }
+  res->seed = base->seed;
+  res->array = alloc_array(res, res->max);
+  if (base->count + overlay->count) {
+    new_vals =
+      apr_palloc(p, sizeof(apr_hash_entry_t) * (base->count + overlay->count));
+  }
+  j = 0;
+  for (k = 0; k <= base->max; k++) {
+    for (iter = base->array[k]; iter; iter = iter->next) {
+      i = iter->hash & res->max;
+      /* We should only warn for the first of these
+	 (it's actually a false positive, but we don't have the
+	 invariante to know that).  */
+      new_vals[j].klen = iter->klen;   /* { dg-warning "dereference of NULL 'new_vals'" } */
+      /* ...but not for subsequent ones: */
+      new_vals[j].key = iter->key;      /* { dg-bogus "dereference of NULL 'new_vals'" "PR analyzer/108830" } */
+      new_vals[j].val = iter->val;      /* { dg-bogus "dereference of NULL 'new_vals'" "PR analyzer/108830" } */
+      new_vals[j].hash = iter->hash;    /* { dg-bogus "dereference of NULL 'new_vals'" "PR analyzer/108830" } */
+      new_vals[j].next = res->array[i]; /* { dg-bogus "dereference of NULL 'new_vals'" "PR analyzer/108830" } */
+      res->array[i] = &new_vals[j];     /* { dg-bogus "dereference of NULL 'new_vals'" "PR analyzer/108830" } */
+      j++;
+    }
+  }
+  /* [...snip...] */
+  return res;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pipe-1.c b/gcc/testsuite/gcc.dg/analyzer/pipe-1.c
index 6b95442e322..156f0114fd5 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pipe-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pipe-1.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-fno-analyzer-suppress-followups" } */
+
 #include "analyzer-decls.h"
 
 extern int pipe(int pipefd[2]);
diff --git a/gcc/testsuite/gcc.dg/analyzer/pipe-void-return.c b/gcc/testsuite/gcc.dg/analyzer/pipe-void-return.c
index 0de676305f6..8b1822d97f9 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pipe-void-return.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pipe-void-return.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-fno-analyzer-suppress-followups" } */
+
 extern void pipe(int pipefd[2]);
 extern int close(int fd);
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/pipe2-1.c b/gcc/testsuite/gcc.dg/analyzer/pipe2-1.c
index d7afc9caaf9..aa0684e5c86 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pipe2-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pipe2-1.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-fno-analyzer-suppress-followups" } */
+
 #include "analyzer-decls.h"
 
 extern int pipe2(int pipefd[2], int flags);
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr101547.c b/gcc/testsuite/gcc.dg/analyzer/pr101547.c
index b42e64ce338..d1c3c915e0e 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr101547.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr101547.c
@@ -2,10 +2,18 @@ char *
 fopen (const char *restrict, const char *restrict);
 
 void
-k2 (void)
+k2_uninit (void)
 {
   char *setfiles[1];
   int i; /* { dg-message "region created on stack here" } */
 
   setfiles[i] = fopen ("", ""); /* { dg-warning "use of uninitialized value 'i'" } */
+}
+
+void
+k2_leak (int i)
+{
+  char *setfiles[1];
+
+  setfiles[i] = fopen ("", "");
 } /* { dg-warning "leak of FILE" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr101875.c b/gcc/testsuite/gcc.dg/analyzer/pr101875.c
index 7700c7d030f..4bef2f161a4 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr101875.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr101875.c
@@ -5,12 +5,22 @@ void
 err (void);
 
 void
-k2 (void)
+k2_uninit (void)
 {
   char *setfiles[1];
   int i; /* { dg-message "region created on stack here" } */
 
   setfiles[i] = fopen("", ""); /* { dg-warning "use of uninitialized value 'i'" } */
-  if (!setfiles[i]) /* { dg-warning "use of uninitialized value 'i'" } */
+  if (!setfiles[i])
+    err ();
+}
+
+void
+k2_leak (int i)
+{
+  char *setfiles[1];
+
+  setfiles[i] = fopen("", "");
+  if (!setfiles[i])
     err ();
 } /* { dg-warning "leak of FILE" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr104224-split.c b/gcc/testsuite/gcc.dg/analyzer/pr104224-split.c
new file mode 100644
index 00000000000..b90fe559f2c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr104224-split.c
@@ -0,0 +1,136 @@
+#include <stdio.h>
+
+struct test {
+        int one;
+        int two;
+};
+
+void func2(const struct test *t)
+{
+        if (t->one == 0)
+                printf("init func2\n");
+
+        if (t->two == 0)  /* { dg-warning "uninitialized" } */
+                printf("uninit func2\n");
+}
+
+void func1(struct test *t)
+{
+        t->one = 1;
+        func2(t);
+}
+
+int func3(int num)
+{
+        if (num)
+                return num;
+        else
+                return 0;
+}
+
+void func4(int *a, int max)
+{
+        int i;
+        // skip the first
+        for (i=1; i<max; i++)
+                a[i] = 0;
+}
+
+void func5(const int *a, int max)
+{
+        /* a[0] is uninitialized, but the rest of the array is initialized.  */
+        int i;
+        for (i=0; i<max; i++) {
+                if (a[i]) /* { dg-warning "uninitialized" "" { xfail *-*-* } } */
+                        printf("func5: %d\n", i);
+        }
+}
+
+int func6(const int *num)
+{
+        if (*num)  /* { dg-warning "uninitialized" } */
+                return *num;
+        else
+                return 0;
+}
+
+int j;
+int func7(void)
+{
+        return j;  /* { dg-bogus "uninitialized" } */
+}
+
+void func8(const int *a, int max)
+{
+        int i;
+        for (i=0; i<max; i++) {
+                if (a[i]) /* { dg-warning "uninitialized" } */
+                        printf("func8: %d\n", i);
+        }
+}
+
+enum {RED, AMBER, GREEN, BLACK};
+
+int test_1 (void)
+{
+        struct test t;  /* { dg-message "region created on stack here" } */
+
+        func1(&t);
+        return 0;
+}
+
+int test_2 (void)
+{
+        int num;  /* { dg-message "region created on stack here" } */
+
+        func3(num);  /* { dg-warning "use of uninitialized value 'num'" } */
+        return 0;
+}
+
+int test_3 (void)
+{
+        int arry[10];
+
+        func4(arry, 10);
+        func5(arry, 10);
+
+        return 0;
+}
+
+int test_4 (void)
+{
+        int num;  /* { dg-message "region created on stack here" } */
+
+        func6(&num);
+        return 0;
+}
+
+int test_5 (void)
+{
+        int arry_2[10];  /* { dg-message "region created on stack here" } */
+
+        printf("func7: %d\n", func7());
+        func8(arry_2, 10);
+
+        return 0;
+}
+
+int test_6 (void)
+{
+        int go;  /* { dg-message "region created on stack here" } */
+        int color = BLACK;
+
+        switch (color) {
+        case RED:
+        case AMBER:
+                go = 0;
+                break;
+        case GREEN:
+                go = 1;
+                break;
+        }
+
+        printf("go :%d\n", go); /* { dg-warning "use of uninitialized value 'go'" } */
+
+        return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr104224.c b/gcc/testsuite/gcc.dg/analyzer/pr104224.c
index b047c4ca5f2..1ff5f9eae71 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr104224.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr104224.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-fno-analyzer-suppress-followups" } */
+
 #include <stdio.h>
 
 struct test {
diff --git a/gcc/testsuite/gcc.dg/analyzer/realloc-2.c b/gcc/testsuite/gcc.dg/analyzer/realloc-2.c
index a39775354a3..ab3e4b6628a 100644
--- a/gcc/testsuite/gcc.dg/analyzer/realloc-2.c
+++ b/gcc/testsuite/gcc.dg/analyzer/realloc-2.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-fno-analyzer-suppress-followups" } */
+
 #include "analyzer-decls.h"
 
 typedef __SIZE_TYPE__ size_t;
diff --git a/gcc/testsuite/gcc.dg/analyzer/realloc-3.c b/gcc/testsuite/gcc.dg/analyzer/realloc-3.c
index 89676e1ca0d..eec61497d5b 100644
--- a/gcc/testsuite/gcc.dg/analyzer/realloc-3.c
+++ b/gcc/testsuite/gcc.dg/analyzer/realloc-3.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-fno-analyzer-suppress-followups" } */
+
 #include "analyzer-decls.h"
 
 typedef __SIZE_TYPE__ size_t;
diff --git a/gcc/testsuite/gcc.dg/analyzer/realloc-5.c b/gcc/testsuite/gcc.dg/analyzer/realloc-5.c
index 75f0b70a996..137e05b87aa 100644
--- a/gcc/testsuite/gcc.dg/analyzer/realloc-5.c
+++ b/gcc/testsuite/gcc.dg/analyzer/realloc-5.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-fno-analyzer-suppress-followups" } */
+
 #include "analyzer-decls.h"
 
 typedef __SIZE_TYPE__ size_t;
diff --git a/gcc/testsuite/gcc.dg/analyzer/stdarg-1-ms_abi.c b/gcc/testsuite/gcc.dg/analyzer/stdarg-1-ms_abi.c
index e55f10de66b..4422075e2b5 100644
--- a/gcc/testsuite/gcc.dg/analyzer/stdarg-1-ms_abi.c
+++ b/gcc/testsuite/gcc.dg/analyzer/stdarg-1-ms_abi.c
@@ -1,5 +1,6 @@
 /* As per stdarg-1.c, but using the ms_abi versions of the builtins.  */
 
+/* { dg-additional-options "-fno-analyzer-suppress-followups" } */
 /* { dg-do compile { target { x86_64-*-* && lp64 } } } */
 
 #include "analyzer-decls.h"
diff --git a/gcc/testsuite/gcc.dg/analyzer/stdarg-1-sysv_abi.c b/gcc/testsuite/gcc.dg/analyzer/stdarg-1-sysv_abi.c
index fb49b3584e2..ba90df20588 100644
--- a/gcc/testsuite/gcc.dg/analyzer/stdarg-1-sysv_abi.c
+++ b/gcc/testsuite/gcc.dg/analyzer/stdarg-1-sysv_abi.c
@@ -1,5 +1,6 @@
 /* As per stdarg-1.c, but using the sysv_abi versions of the builtins.  */
 
+/* { dg-additional-options "-fno-analyzer-suppress-followups" } */
 /* { dg-do compile { target { x86_64-*-* && lp64 } } } */
 
 #include "analyzer-decls.h"
diff --git a/gcc/testsuite/gcc.dg/analyzer/stdarg-1.c b/gcc/testsuite/gcc.dg/analyzer/stdarg-1.c
index f2766a50522..4d5431b822c 100644
--- a/gcc/testsuite/gcc.dg/analyzer/stdarg-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/stdarg-1.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-fno-analyzer-suppress-followups" } */
+
 #include "analyzer-decls.h"
 
 /* Unpacking a va_list.  */
diff --git a/gcc/testsuite/gcc.dg/analyzer/symbolic-1.c b/gcc/testsuite/gcc.dg/analyzer/symbolic-1.c
index 2f4e00bcc25..0d78242381a 100644
--- a/gcc/testsuite/gcc.dg/analyzer/symbolic-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/symbolic-1.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-fno-analyzer-suppress-followups" } */
+
 #include "analyzer-decls.h"
 
 /* The example from store.h  */
diff --git a/gcc/testsuite/gcc.dg/analyzer/symbolic-7.c b/gcc/testsuite/gcc.dg/analyzer/symbolic-7.c
index 665e0b645d3..c1464555e8a 100644
--- a/gcc/testsuite/gcc.dg/analyzer/symbolic-7.c
+++ b/gcc/testsuite/gcc.dg/analyzer/symbolic-7.c
@@ -31,16 +31,20 @@ void test_2 (int i)
   __analyzer_eval (arr[i] == 42); /* { dg-warning "UNKNOWN" } */
 }
 
-void test_3 (int i)
+void test_3_concrete_read (int i)
 {
   /* An array that can't have been touched.  */
   int arr[2];
   
   /* Concrete reads.  */
-  __analyzer_eval (arr[0] == 42); /* { dg-warning "UNKNOWN" "unknown" } */
-  /* { dg-warning "use of uninitialized value 'arr\\\[0\\\]'" "uninit" { target *-*-* } .-1 } */
+  __analyzer_eval (arr[0] == 42); /* { dg-warning "use of uninitialized value 'arr\\\[0\\\]'" } */
+}
 
+void test_3_symbolic_read (int i)
+{
+  /* An array that can't have been touched.  */
+  int arr[2];
+  
   /* Symbolic read.  */
-  __analyzer_eval (arr[i] == 42); /* { dg-warning "UNKNOWN" "unknown" } */
-  /* { dg-warning "use of uninitialized value 'arr\\\[i\\\]'" "uninit" { target *-*-* } .-1 } */
+  __analyzer_eval (arr[i] == 42); /* { dg-warning "use of uninitialized value 'arr\\\[i\\\]'" } */
 }
diff --git a/gcc/testsuite/gcc.dg/analyzer/uninit-4.c b/gcc/testsuite/gcc.dg/analyzer/uninit-4.c
index 616cb342348..31c6ae0c611 100644
--- a/gcc/testsuite/gcc.dg/analyzer/uninit-4.c
+++ b/gcc/testsuite/gcc.dg/analyzer/uninit-4.c
@@ -22,7 +22,7 @@ alloc_foo (int a, int b)
   return p;
 }
 
-void test (int x, int y, int z)
+void test_access_inited_fields (int x, int y, int z)
 {
   struct foo *p = alloc_foo (x, z);
   if (!p)
@@ -30,10 +30,20 @@ void test (int x, int y, int z)
 
   __analyzer_eval (p->i == x); /* { dg-warning "TRUE" } */
 
-  __analyzer_eval (p->j == y); /* { dg-warning "UNKNOWN" "unknown" } */
-  /* { dg-warning "use of uninitialized value '\\*p\\.j'" "uninit" { target *-*-* } .-1 } */
-
   __analyzer_eval (p->k == z); /* { dg-warning "TRUE" } */
   
   free (p);
 }
+
+void test_stop_after_accessing_uninit (int x, int y, int z)
+{
+  struct foo *p = alloc_foo (x, z);
+  if (!p)
+    return;
+
+  __analyzer_eval (p->i == x); /* { dg-warning "TRUE" } */
+
+  __analyzer_eval (p->j == y); /* { dg-warning "use of uninitialized value '\\*p\\.j'" } */
+
+  __analyzer_dump_path (); /* { dg-bogus "path" } */
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/uninit-8.c b/gcc/testsuite/gcc.dg/analyzer/uninit-8.c
new file mode 100644
index 00000000000..2fa10525cd0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/uninit-8.c
@@ -0,0 +1,73 @@
+struct st
+{
+  int a, b, c, d, e;
+};
+
+int
+test_1 (int flag, struct st *p)
+{
+  struct st *q;
+  int result = 0;
+  if (flag)
+    q = p;
+  /* We should only warn about the first use of uninit for 'q':  */
+  result += q->a; /* { dg-warning "use of uninitialized value 'q'" } */
+  /* ...and not for these:  */
+  result += q->b; /* { dg-bogus "use of uninitialized value 'q'" } */
+  result += q->c; /* { dg-bogus "use of uninitialized value 'q'" } */
+  result += q->d; /* { dg-bogus "use of uninitialized value 'q'" } */
+  result += q->e; /* { dg-bogus "use of uninitialized value 'q'" } */
+  return result;
+}
+
+int
+test_2 (int flag, struct st *p, struct st *r)
+{
+  struct st *q;
+  int result = 0;
+  if (flag)
+    q = p;
+  /* We should only warn about the first use of uninit for 'q':  */
+  if (q == r) /* { dg-warning "use of uninitialized value 'q'" } */
+    result += 1;
+  /* ...and not for these, after a conditional:  */
+  result += q->b; /* { dg-bogus "use of uninitialized value 'q'" } */
+  result += q->c; /* { dg-bogus "use of uninitialized value 'q'" } */
+  result += q->d; /* { dg-bogus "use of uninitialized value 'q'" } */
+  result += q->e; /* { dg-bogus "use of uninitialized value 'q'" } */
+  return result;
+}
+
+int
+test_3 (int flag, int val)
+{
+  int result = 0;
+  int idx;
+  if (flag)
+    idx = val;
+  switch (idx) /* { dg-warning "use of uninitialized value 'idx'" } */
+    {
+    case 0:
+      result = 3;
+      break;
+    case 1:
+      result = 4;
+      break;
+    default:
+      result = 5;
+      break;      
+    }
+  switch (idx) /* { dg-bogus "use of uninitialized value 'idx'" } */
+    {
+    case 0:
+      result += 3;
+      break;
+    case 1:
+      result += 4;
+      break;
+    default:
+      result += 5;
+      break;
+    }
+  return result;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/uninit-pr94713.c b/gcc/testsuite/gcc.dg/analyzer/uninit-pr94713.c
index e3bb8ceb5b3..cb91462c36b 100644
--- a/gcc/testsuite/gcc.dg/analyzer/uninit-pr94713.c
+++ b/gcc/testsuite/gcc.dg/analyzer/uninit-pr94713.c
@@ -1,11 +1,19 @@
 void f1 (int *);
 void f2 (int);
 
-int foo (void)
+int test_1 (void)
 {
   int *p; /* { dg-message "region created on stack here" } */
 
   f1 (p); /* { dg-warning "use of uninitialized value 'p'" } */
+  f1 (p); /* { dg-bogus "use of uninitialized value 'p'" "no followup warnings" } */
+  return 0;
+}
+
+int test_2 (void)
+{
+  int *p; /* { dg-message "region created on stack here" } */
+
   f2 (p[0]); /* { dg-warning "use of uninitialized value 'p'" } */
   return 0;
 }
diff --git a/gcc/testsuite/gcc.dg/analyzer/zlib-6a.c b/gcc/testsuite/gcc.dg/analyzer/zlib-6a.c
index 9676e0b3845..8c83de4863b 100644
--- a/gcc/testsuite/gcc.dg/analyzer/zlib-6a.c
+++ b/gcc/testsuite/gcc.dg/analyzer/zlib-6a.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-fno-analyzer-suppress-followups" } */
+
 typedef unsigned char Byte;
 typedef unsigned int uInt;
 typedef unsigned long uLong;
