| /* Type stack for GDB parser. | 
 |  | 
 |    Copyright (C) 1986-2023 Free Software Foundation, Inc. | 
 |  | 
 |    This file is part of GDB. | 
 |  | 
 |    This program is free software; you can redistribute it and/or modify | 
 |    it under the terms of the GNU General Public License as published by | 
 |    the Free Software Foundation; either version 3 of the License, or | 
 |    (at your option) any later version. | 
 |  | 
 |    This program is distributed in the hope that it will be useful, | 
 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |    GNU General Public License for more details. | 
 |  | 
 |    You should have received a copy of the GNU General Public License | 
 |    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ | 
 |  | 
 | #include "defs.h" | 
 | #include "type-stack.h" | 
 |  | 
 | #include "gdbtypes.h" | 
 | #include "parser-defs.h" | 
 |  | 
 | /* See type-stack.h.  */ | 
 |  | 
 | void | 
 | type_stack::insert (enum type_pieces tp) | 
 | { | 
 |   union type_stack_elt element; | 
 |   int slot; | 
 |  | 
 |   gdb_assert (tp == tp_pointer || tp == tp_reference | 
 | 	      || tp == tp_rvalue_reference || tp == tp_const | 
 | 	      || tp == tp_volatile || tp == tp_restrict | 
 | 	      || tp == tp_atomic); | 
 |  | 
 |   /* If there is anything on the stack (we know it will be a | 
 |      tp_pointer), insert the qualifier above it.  Otherwise, simply | 
 |      push this on the top of the stack.  */ | 
 |   if (!m_elements.empty () && (tp == tp_const || tp == tp_volatile | 
 | 			       || tp == tp_restrict)) | 
 |     slot = 1; | 
 |   else | 
 |     slot = 0; | 
 |  | 
 |   element.piece = tp; | 
 |   insert_into (slot, element); | 
 | } | 
 |  | 
 | /* See type-stack.h.  */ | 
 |  | 
 | void | 
 | type_stack::insert (struct expr_builder *pstate, const char *string) | 
 | { | 
 |   union type_stack_elt element; | 
 |   int slot; | 
 |  | 
 |   /* If there is anything on the stack (we know it will be a | 
 |      tp_pointer), insert the address space qualifier above it. | 
 |      Otherwise, simply push this on the top of the stack.  */ | 
 |   if (!m_elements.empty ()) | 
 |     slot = 1; | 
 |   else | 
 |     slot = 0; | 
 |  | 
 |   element.piece = tp_space_identifier; | 
 |   insert_into (slot, element); | 
 |   element.int_val | 
 |     = address_space_name_to_type_instance_flags (pstate->gdbarch (), | 
 | 						 string); | 
 |   insert_into (slot, element); | 
 | } | 
 |  | 
 | /* See type-stack.h.  */ | 
 |  | 
 | type_instance_flags | 
 | type_stack::follow_type_instance_flags () | 
 | { | 
 |   type_instance_flags flags = 0; | 
 |  | 
 |   for (;;) | 
 |     switch (pop ()) | 
 |       { | 
 |       case tp_end: | 
 | 	return flags; | 
 |       case tp_const: | 
 | 	flags |= TYPE_INSTANCE_FLAG_CONST; | 
 | 	break; | 
 |       case tp_volatile: | 
 | 	flags |= TYPE_INSTANCE_FLAG_VOLATILE; | 
 | 	break; | 
 |       case tp_atomic: | 
 | 	flags |= TYPE_INSTANCE_FLAG_ATOMIC; | 
 | 	break; | 
 |       case tp_restrict: | 
 | 	flags |= TYPE_INSTANCE_FLAG_RESTRICT; | 
 | 	break; | 
 |       default: | 
 | 	gdb_assert_not_reached ("unrecognized tp_ value in follow_types"); | 
 |       } | 
 | } | 
 |  | 
 | /* See type-stack.h.  */ | 
 |  | 
 | struct type * | 
 | type_stack::follow_types (struct type *follow_type) | 
 | { | 
 |   int done = 0; | 
 |   int make_const = 0; | 
 |   int make_volatile = 0; | 
 |   type_instance_flags make_addr_space = 0; | 
 |   bool make_restrict = false; | 
 |   bool make_atomic = false; | 
 |   int array_size; | 
 |  | 
 |   while (!done) | 
 |     switch (pop ()) | 
 |       { | 
 |       case tp_end: | 
 | 	done = 1; | 
 | 	goto process_qualifiers; | 
 | 	break; | 
 |       case tp_const: | 
 | 	make_const = 1; | 
 | 	break; | 
 |       case tp_volatile: | 
 | 	make_volatile = 1; | 
 | 	break; | 
 |       case tp_space_identifier: | 
 | 	make_addr_space = (enum type_instance_flag_value) pop_int (); | 
 | 	break; | 
 |       case tp_atomic: | 
 | 	make_atomic = true; | 
 | 	break; | 
 |       case tp_restrict: | 
 | 	make_restrict = true; | 
 | 	break; | 
 |       case tp_pointer: | 
 | 	follow_type = lookup_pointer_type (follow_type); | 
 | 	goto process_qualifiers; | 
 |       case tp_reference: | 
 | 	follow_type = lookup_lvalue_reference_type (follow_type); | 
 | 	goto process_qualifiers; | 
 |       case tp_rvalue_reference: | 
 | 	follow_type = lookup_rvalue_reference_type (follow_type); | 
 |       process_qualifiers: | 
 | 	if (make_const) | 
 | 	  follow_type = make_cv_type (make_const, | 
 | 				      TYPE_VOLATILE (follow_type), | 
 | 				      follow_type, 0); | 
 | 	if (make_volatile) | 
 | 	  follow_type = make_cv_type (TYPE_CONST (follow_type), | 
 | 				      make_volatile, | 
 | 				      follow_type, 0); | 
 | 	if (make_addr_space) | 
 | 	  follow_type = make_type_with_address_space (follow_type, | 
 | 						      make_addr_space); | 
 | 	if (make_restrict) | 
 | 	  follow_type = make_restrict_type (follow_type); | 
 | 	if (make_atomic) | 
 | 	  follow_type = make_atomic_type (follow_type); | 
 | 	make_const = make_volatile = 0; | 
 | 	make_addr_space = 0; | 
 | 	make_restrict = make_atomic = false; | 
 | 	break; | 
 |       case tp_array: | 
 | 	array_size = pop_int (); | 
 | 	/* FIXME-type-allocation: need a way to free this type when we are | 
 | 	   done with it.  */ | 
 | 	follow_type = | 
 | 	  lookup_array_range_type (follow_type, | 
 | 				   0, array_size >= 0 ? array_size - 1 : 0); | 
 | 	if (array_size < 0) | 
 | 	  follow_type->bounds ()->high.set_undefined (); | 
 | 	break; | 
 |       case tp_function: | 
 | 	/* FIXME-type-allocation: need a way to free this type when we are | 
 | 	   done with it.  */ | 
 | 	follow_type = lookup_function_type (follow_type); | 
 | 	break; | 
 |  | 
 |       case tp_function_with_arguments: | 
 | 	{ | 
 | 	  std::vector<struct type *> *args = pop_typelist (); | 
 |  | 
 | 	  follow_type | 
 | 	    = lookup_function_type_with_arguments (follow_type, | 
 | 						   args->size (), | 
 | 						   args->data ()); | 
 | 	} | 
 | 	break; | 
 |  | 
 |       case tp_type_stack: | 
 | 	{ | 
 | 	  struct type_stack *stack = pop_type_stack (); | 
 | 	  follow_type = stack->follow_types (follow_type); | 
 | 	} | 
 | 	break; | 
 |       default: | 
 | 	gdb_assert_not_reached ("unrecognized tp_ value in follow_types"); | 
 |       } | 
 |   return follow_type; | 
 | } |