/* We've found a component of the name that's an
                 anonymous namespace.  So add symbols in it to the
                 namespace given by the previous component if there is
-                one, or to the global namespace if there isn't.  */
+                one, or to the global namespace if there isn't.
+                The declared line of this using directive can be set
+                to 0, this way it is always considered valid.  */
              std::vector<const char *> excludes;
              add_using_directive (compunit->get_local_using_directives (),
-                                  dest, src, NULL, NULL, excludes,
+                                  dest, src, NULL, NULL, excludes, 0,
                                   1, &objfile->objfile_obstack);
            }
          /* The "+ 2" is for the "::".  */
   if (sym.symbol != NULL)
     return sym;
 
+  /* Due to a GCC bug, we need to know the boundaries of the current block
+     to know if a certain using directive is valid.  */
+  symtab_and_line boundary_sal = find_pc_line (block->end () - 1, 0);
+
   /* Go through the using directives.  If any of them add new names to
      the namespace we're searching in, see if we can find a match by
      applying them.  */
-
   for (current = block_using (block);
        current != NULL;
        current = current->next)
     {
       const char **excludep;
 
+      /* If the using directive was below the place we are stopped at,
+        do not use this directive.  */
+      if (!current->valid_line (boundary_sal.line))
+       continue;
       len = strlen (current->import_dest);
       directive_match = (search_parents
                         ? (startswith (scope, current->import_dest)
 
     return cu->get_builder ()->get_local_using_directives ();
 }
 
+/* Read the DW_ATTR_decl_line attribute for the given DIE in the
+   given CU.  If the format is not recognized or the attribute is
+   not present, set it to 0.  */
+
+static unsigned int
+read_decl_line (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct attribute *decl_line = dwarf2_attr (die, DW_AT_decl_line, cu);
+  if (decl_line == nullptr)
+    return 0;
+  if (decl_line->form_is_constant ())
+    {
+      LONGEST val = decl_line->constant_value (0);
+      if (0 <= val && val <= UINT_MAX)
+       return (unsigned int) val;
+
+      complaint (_("Declared line for using directive is too large"));
+      return 0;
+    }
+
+  complaint (_("Declared line for using directive is of incorrect format"));
+  return 0;
+}
+
 /* Read the import statement specified by the given die and record it.  */
 
 static void
                       import_alias,
                       imported_declaration,
                       excludes,
+                      read_decl_line (die, cu),
                       0,
                       &objfile->objfile_obstack);
 }
          std::vector<const char *> excludes;
          add_using_directive (using_directives (cu),
                               previous_prefix, type->name (), NULL,
-                              NULL, excludes, 0, &objfile->objfile_obstack);
+                              NULL, excludes,
+                              read_decl_line (die, cu),
+                              0, &objfile->objfile_obstack);
        }
     }
 
 
 
 #include "defs.h"
 #include "namespace.h"
+#include "frame.h"
 
 /* Add a using directive to USING_DIRECTIVES.  If the using directive
    in question has already been added, don't add it twice.
                     const char *alias,
                     const char *declaration,
                     const std::vector<const char *> &excludes,
+                    unsigned int decl_line,
                     int copy_names,
                     struct obstack *obstack)
 {
       if (ix < excludes.size () || current->excludes[ix] != NULL)
        continue;
 
+      if (decl_line != current->decl_line)
+       continue;
+
       /* Parameters exactly match CURRENT.  */
       return;
     }
            excludes.size () * sizeof (*newobj->excludes));
   newobj->excludes[excludes.size ()] = NULL;
 
+  newobj->decl_line = decl_line;
+
   newobj->next = *using_directives;
   *using_directives = newobj;
 }
+
+/* See namespace.h.  */
+
+bool
+using_direct::valid_line (unsigned int boundary) const
+{
+  try
+    {
+      CORE_ADDR curr_pc = get_frame_pc (get_selected_frame (nullptr));
+      symtab_and_line curr_sal = find_pc_line (curr_pc, 0);
+      return (decl_line <= curr_sal.line)
+            || (decl_line >= boundary);
+    }
+  catch (const gdb_exception &ex)
+    {
+      return true;
+    }
+}
 
    string representing the alias.  Otherwise, ALIAS is NULL.
    DECLARATION is the name of the imported declaration, if this import
    statement represents one.  Otherwise DECLARATION is NULL and this
-   import statement represents a namespace.
+   import statement represents a namespace.  DECL_LINE is the line
+   where the using directive is written in the source code.
 
    C++:      using namespace A;
    Fortran:  use A
 
   struct using_direct *next;
 
+  /* The line where the using directive was declared on the source file.
+     This is used to check if the using directive is already active at the
+     point where the inferior is stopped.  */
+  unsigned int decl_line;
+
   /* Used during import search to temporarily mark this node as
      searched.  */
   int searched;
   /* USING_DIRECT has variable allocation size according to the number of
      EXCLUDES entries, the last entry is NULL.  */
   const char *excludes[1];
+
+  /* Returns true if the using_direcive USING_DIR is valid in CURR_LINE.
+     Because current GCC (at least version 12.2) sets the decl_line as
+     the last line in the current block, we need to take this into
+     consideration when checking the validity, by comparing it to
+     BOUNDARY, the last line of the current block.  */
+  bool valid_line (unsigned int boundary) const;
 };
 
 extern void add_using_directive (struct using_direct **using_directives,
                                 const char *alias,
                                 const char *declaration,
                                 const std::vector<const char *> &excludes,
+                                const unsigned int decl_line,
                                 int copy_names,
                                 struct obstack *obstack);
 
 
 
 int marker10 ()
 {
+  int y = 1; // marker10 stop
   using namespace M;
-  int y = x + 1; // marker10 stop
+  y += x;
   using namespace N;
   return y;
 }
 
 
 if { [test_compiler_info {gcc-[0-3]-*}] ||
      [test_compiler_info {gcc-4-[0-3]-*}]} {
-    setup_xfail *-*-*
+    return
 }
 
-# Assert that M::x is printed and not N::x
-gdb_test "print x" "= 911" "print x (from M::x)"
+gdb_test_multiple "print x" "print x, before using statement" {
+    -re -wrap "No symbol .x. in current context.*" {
+       pass $gdb_test_name
+    }
+    -re -wrap "= 911.*" {
+       # GCC doesn't properly set the decl_line for namespaces, so GDB believes
+       # that the "using namespace M" line has already passed at this point.
+       xfail $gdb_test_name
+    }
+}
+gdb_test "next" ".*" "using namespace M"
+gdb_test "print x" "= 911" "print x, only using M"