diff --git a/gcc/cobol/UAT/testsuite.src/syn_definition.at b/gcc/cobol/UAT/testsuite.src/syn_definition.at
index e73e5950aad38bdce24a7e9a56997f553d87bcdd..a0d25a9e6bbba3755bfbf101c9ab8cafe60e3178 100644
--- a/gcc/cobol/UAT/testsuite.src/syn_definition.at
+++ b/gcc/cobol/UAT/testsuite.src/syn_definition.at
@@ -157,9 +157,9 @@ AT_DATA([prog.cob], [
 
 # better: prog.cob:8: error: 'X IN X' is not defined
 AT_CHECK([$COMPILE_ONLY prog.cob], [1], [],
-[prog.cob:8:25: error: DATA-ITEM 'X' not found
+[prog.cob:8:20: error: DATA-ITEM 'X' not found
     8 |            DISPLAY X IN X
-      |                         ^
+      |                    ^
 cobol1: error: failed compiling prog.cob
 ])
 
diff --git a/gcc/cobol/parse.y b/gcc/cobol/parse.y
index 0adefd0256ec0927348dd21664a659d3d3e32c91..d55e1eef12e51b1a72fb4271e62d84ed96409882 100644
--- a/gcc/cobol/parse.y
+++ b/gcc/cobol/parse.y
@@ -4828,7 +4828,17 @@ scalar88s:	scalar88         { $$ = new refer_list_t($1); }
                 ;
 
 name88:		NAME88 {
-		  $$ = cbl_field_of(symbol_find(@1, $1));
+                  name_queue.qualify(@1, $1);
+		  auto namelocs( name_queue.pop() );
+		  auto names( name_queue.namelist_of(namelocs) );
+                  if( ($$ = field_find(names)) == NULL ) {
+                    if( procedure_div_e == current_division  ) {
+		      error_msg(namelocs.back().loc,
+				"DATA-ITEM '%s' not found", names.back() );
+                      YYERROR;
+                    }
+		  }
+		  assert($$->level == 88);
 		}
 		;
 
@@ -5987,10 +5997,12 @@ typename:       NAME
 name:           qname
                 {
                   build_symbol_map();
-		  auto names( name_queue.pop_as_names() );
+		  auto namelocs( name_queue.pop() );
+		  auto names( name_queue.namelist_of(namelocs) );
                   if( ($$ = field_find(names)) == NULL ) {
                     if( procedure_div_e == current_division  ) {
-		      error_msg(@1, "DATA-ITEM '%s' not found", names.back() );
+		      error_msg(namelocs.back().loc, 
+				"DATA-ITEM '%s' not found", names.back() );
                       YYERROR;
                     }
                     /*
@@ -12694,15 +12706,15 @@ literal_subscripts_valid( YYLTYPE loc, const cbl_refer_t& name ) {
 }
 
 static void
-subscript_dimension_error( YYLTYPE loc, size_t nsub, const cbl_refer_t *name ) {
-  if( 0 == dimensions(name->field) ) {
+subscript_dimension_error( YYLTYPE loc, size_t nsub, const cbl_refer_t *scalar ) {
+  if( 0 == dimensions(scalar->field) ) {
     error_msg(loc, "%zu subscripts provided for %s, "
               "which has no dimensions",
-              nsub, name->name() );
+              nsub, scalar->name() );
   } else {
     error_msg(loc, "%zu subscripts provided for %s, "
               "which requires %zu dimensions",
-              nsub, name->name(), dimensions(name->field) );
+              nsub, scalar->name(), dimensions(scalar->field) );
   }
 }
 
diff --git a/gcc/cobol/parse_ante.h b/gcc/cobol/parse_ante.h
index 24762f9cf8909c03253525b2066081518011b622..c037625b6b35278776523da07ea21e827e6857d1 100644
--- a/gcc/cobol/parse_ante.h
+++ b/gcc/cobol/parse_ante.h
@@ -873,6 +873,21 @@ list_add( list<cbl_num_result_t>& list, cbl_refer_t refer, int round ) {
 static  list<cbl_domain_t> domains;
 typedef list<cbl_domain_t>::iterator domain_iter;
 
+/*
+ * The name queue is a queue of lists of data-item names recognized by the
+ * lexer, but not returned to the parser.  These lists are "teed up" by the
+ * lexer until no more qualifiers are found.  At that point, the last name is
+ * returned as a NAME or NAME88 token. NAME88 is returned only if a correctly,
+ * uniquely specified Level 88 data item is found in the symbol table (because
+ * else we can't know).
+ * 
+ * When the parser gets a NAME or NAME88 token, it retrieves the pending list
+ * of qualifiers, if any, from the name queue.  It adds the returned name to
+ * the list and calls symbol_find() to search the name map.  For correctly
+ * specified names, the lexer has already done that work, which is now
+ * unfortunately repeated.  For incorrect names, the parser emits a most useful
+ * diagnostic. 
+ */
 static  name_queue_t name_queue;
 
 void
diff --git a/gcc/cobol/symbols.h b/gcc/cobol/symbols.h
index a803d45c4494ff26a82db620216604f866572b7e..b55ec8d9f6f29b120ae2d736402eb3cec2639226 100644
--- a/gcc/cobol/symbols.h
+++ b/gcc/cobol/symbols.h
@@ -1981,6 +1981,7 @@ struct cbl_nameloc_t {
     : loc(loc), name(name)
   {}
 };
+
 /*
  * The lexer pushes qualified names unilaterally, regardless of the
  * state of the parser, because it runs ahead of the parser. The
@@ -1994,13 +1995,12 @@ typedef std::list<cbl_nameloc_t> cbl_namelocs_t;
 class name_queue_t : private std::queue<cbl_namelocs_t>
 {
   friend void tee_up_empty();
-  friend cbl_namelist_t teed_up_names();
   cbl_namelocs_t recent;
 
   void allocate() {
     std::queue<cbl_namelocs_t>::push( cbl_namelocs_t() );
   }
- protected:
+ public:
   static cbl_namelist_t
   namelist_of( const cbl_namelocs_t& namelocs ) {
     cbl_namelist_t names;
@@ -2010,7 +2010,6 @@ class name_queue_t : private std::queue<cbl_namelocs_t>
 		    } );
     return names;
   }
- public:
   size_t push( const YYLTYPE& loc, const char name[] ) {
     assert( !empty() );
     back().push_front( cbl_nameloc_t(loc, name) );
diff --git a/gcc/cobol/symfind.cc b/gcc/cobol/symfind.cc
index 93551a1d4cb477c886cad0217bb2265cb8da4d0d..0665b9253dfbc9146e0c49c65f13e9a1fff1f6fc 100644
--- a/gcc/cobol/symfind.cc
+++ b/gcc/cobol/symfind.cc
@@ -533,7 +533,7 @@ symbol_match( size_t program, std::list<const char *> names ) {
     auto inserted = output.insert(*p);
     if( ! inserted.second ) {
       yyerror("%s is not a unique reference", key.name);
-    }
+    } 
   }
   return output;
 }