diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index c359c2d4af981..ad533c14d2480 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -23687,6 +23687,33 @@ local_function_static (tree decl)
     && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL;
 }
 
+/* Return true iff DECL completes (overrides) the type of OLD_DIE
+   within CONTEXT_DIE.  */
+
+static bool
+completing_type_p (tree decl, dw_die_ref old_die, dw_die_ref context_die)
+{
+  tree type = TREE_TYPE (decl);
+  int cv_quals;
+
+  if (decl_by_reference_p (decl))
+    {
+      type = TREE_TYPE (type);
+      cv_quals = TYPE_UNQUALIFIED;
+    }
+  else
+    cv_quals = decl_quals (decl);
+
+  dw_die_ref type_die = modified_type_die (type,
+					   cv_quals | TYPE_QUALS (type),
+					   false,
+					   context_die);
+
+  dw_die_ref old_type_die = get_AT_ref (old_die, DW_AT_type);
+
+  return type_die != old_type_die;
+}
+
 /* Generate a DIE to represent a declared data object.
    Either DECL or ORIGIN must be non-null.  */
 
@@ -23939,7 +23966,9 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
 	  && !DECL_ABSTRACT_P (decl_or_origin)
 	  && variably_modified_type_p (TREE_TYPE (decl_or_origin),
 				       decl_function_context
-							(decl_or_origin))))
+				       (decl_or_origin)))
+      || (old_die && specialization_p
+	  && completing_type_p (decl_or_origin, old_die, context_die)))
     {
       tree type = TREE_TYPE (decl_or_origin);
 
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/array-0.C b/gcc/testsuite/g++.dg/debug/dwarf2/array-0.C
new file mode 100644
index 0000000000000..a3458bd0d32a4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/array-0.C
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-gdwarf-2 -dA" } */
+struct S
+{
+  static int array[42];
+};
+
+int S::array[42];
+
+/* Verify that we get only one DW_TAG_subrange_type with a
+   DW_AT_upper_bound.  */
+/* { dg-final { scan-assembler-times " DW_TAG_subrange_type" 2 } } */
+/* { dg-final { scan-assembler-times " DW_AT_upper_bound" 1 } } */
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/array-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/array-1.C
new file mode 100644
index 0000000000000..e8fd6f8ffea56
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/array-1.C
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-gdwarf-2 -dA" } */
+struct S
+{
+  static int array[];
+};
+
+int S::array[42];
+
+/* Verify that we get two DW_TAG_subrange_type, only one of which with
+   a DW_AT_upper_bound.  */
+/* { dg-final { scan-assembler-times " DW_TAG_subrange_type" 4 } } */
+/* { dg-final { scan-assembler-times " DW_AT_upper_bound" 1 } } */
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/array-2.C b/gcc/testsuite/g++.dg/debug/dwarf2/array-2.C
new file mode 100644
index 0000000000000..dd17812043898
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/array-2.C
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-gdwarf-2 -dA" } */
+struct S
+{
+  typedef int i_t;
+  static i_t array[42];
+};
+
+int S::array[42];
+
+/* Verify that we get two DW_TAG_subrange_type (plus abbrev), and two
+   DW_AT_upper_bound, because a different symbolic name is used for
+   the array element type.  */
+/* { dg-final { scan-assembler-times " DW_TAG_subrange_type" 3 } } */
+/* { dg-final { scan-assembler-times " DW_AT_upper_bound" 2 } } */
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/array-3.C b/gcc/testsuite/g++.dg/debug/dwarf2/array-3.C
new file mode 100644
index 0000000000000..8db6133b76585
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/array-3.C
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-gdwarf-2 -dA" } */
+struct S
+{
+  S() {}
+  ~S() {}
+  static const S array[2];
+};
+
+const S S::array[2] = { S(), S() };
+
+/* Verify that we get only one DW_TAG_subrange_type (plus the abbrev),
+   and one DW_AT_upper_bound (non-abbrev), because the array
+   definition loses the readonly wrapper for the array type because of
+   the dynamic initializers.  The const types are 4: S, S*, int, and
+   S[4], plus the abbrev.  A const version of S[4] doesn't make sense,
+   but we output it.  */
+/* { dg-final { scan-assembler-times " DW_TAG_const_type" 5 } } */
+/* { dg-final { scan-assembler-times " DW_TAG_subrange_type" 2 } } */
+/* { dg-final { scan-assembler-times " DW_AT_upper_bound" 1 } } */
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/array-4.C b/gcc/testsuite/g++.dg/debug/dwarf2/array-4.C
new file mode 100644
index 0000000000000..6b3f546c1b583
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/array-4.C
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-gdwarf-2 -dA" } */
+struct S
+{
+  S() {}
+  ~S() {}
+};
+
+const S array[2] = { S(), S() };
+
+/* Like array-3, but with a non-member array without a separate
+   declaration, to check that we don't issue the nonsensical
+   DW_TAG_const_type used by the member array declaration there.  */
+/* { dg-final { scan-assembler-times " DW_TAG_const_type" 4 } } */
+/* { dg-final { scan-assembler-times " DW_TAG_subrange_type" 2 } } */
+/* { dg-final { scan-assembler-times " DW_AT_upper_bound" 1 } } */
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/array-0.c b/gcc/testsuite/gcc.dg/debug/dwarf2/array-0.c
new file mode 100644
index 0000000000000..b06392e04a2db
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/array-0.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-gdwarf-2 -dA" } */
+extern int array[42];
+
+int array[42];
+
+/* Verify that we get only one DW_TAG_subtrange_type (plus abbrev),
+   with a DW_AT_upper_bound.  */
+/* { dg-final { scan-assembler-times " DW_TAG_subrange_type" 2 } } */
+/* { dg-final { scan-assembler-times " DW_AT_upper_bound" 1 } } */
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/array-1.c b/gcc/testsuite/gcc.dg/debug/dwarf2/array-1.c
new file mode 100644
index 0000000000000..ad8f466ef08ad
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/array-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-gdwarf-2 -dA" } */
+extern int array[];
+
+int array[42];
+
+/* Verify that we get two DW_TAG_subtrange_type (each with an abbrev),
+   but only one DW_AT_upper_bound.  */
+/* { dg-final { scan-assembler-times " DW_TAG_subrange_type" 4 } } */
+/* { dg-final { scan-assembler-times " DW_AT_upper_bound" 1 } } */
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/array-2.c b/gcc/testsuite/gcc.dg/debug/dwarf2/array-2.c
new file mode 100644
index 0000000000000..5d1606f0889fc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/array-2.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-gdwarf-2 -dA" } */
+int array[42];
+
+/* Verify that we get only one DW_TAG_subtrange_type (plus abbrev)
+   with DW_AT_upper_bound.  */
+/* { dg-final { scan-assembler-times " DW_TAG_subrange_type" 2 } } */
+/* { dg-final { scan-assembler-times " DW_AT_upper_bound" 1 } } */
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/array-3.c b/gcc/testsuite/gcc.dg/debug/dwarf2/array-3.c
new file mode 100644
index 0000000000000..077a62ef9a3bf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/array-3.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-gdwarf-2 -dA" } */
+int array[] = { 0, 1, 2 };
+
+/* Verify that we get only one DW_TAG_subtrange_type (plus abbrev)
+   with DW_AT_upper_bound.  */
+/* { dg-final { scan-assembler-times " DW_TAG_subrange_type" 2 } } */
+/* { dg-final { scan-assembler-times " DW_AT_upper_bound" 1 } } */
