| /* Type stack for GDB parser. | |
| Copyright (C) 1986-2022 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; | |
| } |