| /* Convert types from GDB to GCC | 
 |  | 
 |    Copyright (C) 2014-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 "gdbsupport/preprocessor.h" | 
 | #include "gdbtypes.h" | 
 | #include "compile-internal.h" | 
 | #include "compile-cplus.h" | 
 | #include "gdbsupport/gdb_assert.h" | 
 | #include "symtab.h" | 
 | #include "source.h" | 
 | #include "cp-support.h" | 
 | #include "cp-abi.h" | 
 | #include "objfiles.h" | 
 | #include "block.h" | 
 | #include "gdbcmd.h" | 
 | #include "c-lang.h" | 
 | #include "compile-c.h" | 
 | #include <algorithm> | 
 |  | 
 | /* Default compile flags for C++.  */ | 
 |  | 
 | const char *compile_cplus_instance::m_default_cflags = "-std=gnu++11"; | 
 |  | 
 | /* Flag to enable internal debugging.  */ | 
 |  | 
 | static bool debug_compile_cplus_types = false; | 
 |  | 
 | /* Flag to enable internal scope switching debugging.  */ | 
 |  | 
 | static bool debug_compile_cplus_scopes = false; | 
 |  | 
 | /* Forward declarations.  */ | 
 |  | 
 | static gcc_type compile_cplus_convert_func (compile_cplus_instance *instance, | 
 | 					    struct type *type, | 
 | 					    bool strip_artificial); | 
 |  | 
 | /* See description in compile-cplus.h.  */ | 
 |  | 
 | gdb::unique_xmalloc_ptr<char> | 
 | compile_cplus_instance::decl_name (const char *natural) | 
 | { | 
 |   if (natural == nullptr) | 
 |     return nullptr; | 
 |  | 
 |   gdb::unique_xmalloc_ptr<char> name = cp_func_name (natural); | 
 |   if (name != nullptr) | 
 |     return name; | 
 |  | 
 |   return make_unique_xstrdup (natural); | 
 | } | 
 |  | 
 | /* Get the access flag for the NUM'th field of TYPE.  */ | 
 |  | 
 | static enum gcc_cp_symbol_kind | 
 | get_field_access_flag (const struct type *type, int num) | 
 | { | 
 |   if (TYPE_FIELD_PROTECTED (type, num)) | 
 |     return GCC_CP_ACCESS_PROTECTED; | 
 |   else if (TYPE_FIELD_PRIVATE (type, num)) | 
 |     return GCC_CP_ACCESS_PRIVATE; | 
 |  | 
 |   /* GDB assumes everything else is public.  */ | 
 |   return GCC_CP_ACCESS_PUBLIC; | 
 | } | 
 |  | 
 | /* Get the access flag for the NUM'th method of TYPE's FNI'th | 
 |    fieldlist.  */ | 
 |  | 
 | enum gcc_cp_symbol_kind | 
 | get_method_access_flag (const struct type *type, int fni, int num) | 
 | { | 
 |   gdb_assert (type->code () == TYPE_CODE_STRUCT); | 
 |  | 
 |   /* If this type was not declared a class, everything is public.  */ | 
 |   if (!type->is_declared_class ()) | 
 |     return GCC_CP_ACCESS_PUBLIC; | 
 |  | 
 |   /* Otherwise, read accessibility from the fn_field.  */ | 
 |   const struct fn_field *methods = TYPE_FN_FIELDLIST1 (type, fni); | 
 |   if (TYPE_FN_FIELD_PROTECTED (methods, num)) | 
 |     return GCC_CP_ACCESS_PROTECTED; | 
 |   else if (TYPE_FN_FIELD_PRIVATE (methods, num)) | 
 |     return GCC_CP_ACCESS_PRIVATE; | 
 |   else | 
 |     return GCC_CP_ACCESS_PUBLIC; | 
 | } | 
 |  | 
 | /* A useful debugging function to output the scope SCOPE to stdout.  */ | 
 |  | 
 | static void __attribute__ ((used)) | 
 | debug_print_scope (const compile_scope &scope) | 
 | { | 
 |   for (const auto &comp: scope) | 
 |     { | 
 |       const char *symbol = (comp.bsymbol.symbol != nullptr | 
 | 			    ? comp.bsymbol.symbol->natural_name () | 
 | 			    : "<none>"); | 
 |  | 
 |       printf_unfiltered ("\tname = %s, symbol = %s\n", comp.name.c_str (), | 
 | 			 symbol); | 
 |     } | 
 | } | 
 |  | 
 | /* See description in compile-cplus.h.  */ | 
 |  | 
 | compile_scope | 
 | type_name_to_scope (const char *type_name, const struct block *block) | 
 | { | 
 |   compile_scope scope; | 
 |  | 
 |   if (type_name == nullptr) | 
 |     { | 
 |       /* An anonymous type.  We cannot really do much here.  We simply cannot | 
 | 	 look up anonymous types easily/at all.  */ | 
 |       return scope; | 
 |     } | 
 |  | 
 |   const char *p = type_name; | 
 |   std::string lookup_name; | 
 |  | 
 |   while (*p != '\0') | 
 |     { | 
 |       /* Create a string token of the first component of TYPE_NAME.  */ | 
 |       int len = cp_find_first_component (p); | 
 |       std::string s (p, len); | 
 |  | 
 |       /* Advance past the last token.  */ | 
 |       p += len; | 
 |  | 
 |       /* Look up the symbol and decide when to stop.  */ | 
 |       if (!lookup_name.empty ()) | 
 | 	lookup_name += "::"; | 
 |       lookup_name += s; | 
 |  | 
 |       /* Look up the resulting name.  */ | 
 |       struct block_symbol bsymbol | 
 | 	= lookup_symbol (lookup_name.c_str (), block, VAR_DOMAIN, nullptr); | 
 |  | 
 |       if (bsymbol.symbol != nullptr) | 
 | 	{ | 
 | 	  scope_component comp = {s, bsymbol}; | 
 |  | 
 | 	  scope.push_back (comp); | 
 |  | 
 | 	  if (bsymbol.symbol->type ()->code () != TYPE_CODE_NAMESPACE) | 
 | 	    { | 
 | 	      /* We're done.  */ | 
 | 	      break; | 
 | 	    } | 
 | 	} | 
 |  | 
 |       if (*p == ':') | 
 | 	{ | 
 | 	  ++p; | 
 | 	  if (*p == ':') | 
 | 	    ++p; | 
 | 	  else | 
 | 	    { | 
 | 	      /* This shouldn't happen since we are not attempting to | 
 | 		 loop over user input.  This name is generated by GDB | 
 | 		 from debug info.  */ | 
 | 	      internal_error (__FILE__, __LINE__, | 
 | 			      _("malformed TYPE_NAME during parsing")); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 |   return scope; | 
 | } | 
 |  | 
 | /* Compare two scope_components for equality.  These are equal if the names | 
 |    of the two components' are the same.  */ | 
 |  | 
 | bool | 
 | operator== (const scope_component &lhs, const scope_component &rhs) | 
 | { | 
 |   return lhs.name == rhs.name; | 
 | } | 
 |  | 
 | /* Compare two scope_components for inequality.  These are not equal if | 
 |    the two components' names are not equal.  */ | 
 |  | 
 | bool | 
 | operator!= (const scope_component &lhs, const scope_component &rhs) | 
 | { | 
 |   return lhs.name != rhs.name; | 
 | } | 
 |  | 
 | /* Compare two compile_scopes for equality.  These are equal if they are both | 
 |    contain the same number of components and each component is equal.  */ | 
 |  | 
 | bool | 
 | operator== (const compile_scope &lhs, const compile_scope &rhs) | 
 | { | 
 |   if (lhs.size () != rhs.size ()) | 
 |     return false; | 
 |  | 
 |   for (int i = 0; i < lhs.size (); ++i) | 
 |     { | 
 |       if (lhs[i] != rhs[i]) | 
 | 	return false; | 
 |     } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | /* Compare two compile_scopes for inequality.  These are inequal if they | 
 |    contain unequal number of elements or if any of the components are not | 
 |    the same.  */ | 
 |  | 
 | bool | 
 | operator!= (const compile_scope &lhs, const compile_scope &rhs) | 
 | { | 
 |   if (lhs.size () != rhs.size ()) | 
 |     return true; | 
 |  | 
 |   for (int i = 0; i < lhs.size (); ++i) | 
 |     { | 
 |       if (lhs[i] != rhs[i]) | 
 | 	return true; | 
 |     } | 
 |  | 
 |   return false; | 
 | } | 
 |  | 
 | /* See description in compile-cplus.h.  */ | 
 |  | 
 | void | 
 | compile_cplus_instance::enter_scope (compile_scope &&new_scope) | 
 | { | 
 |   bool must_push = m_scopes.empty () || m_scopes.back () != new_scope; | 
 |  | 
 |   new_scope.m_pushed = must_push; | 
 |  | 
 |   /* Save the new scope.  */ | 
 |   m_scopes.push_back (std::move (new_scope)); | 
 |  | 
 |   if (must_push) | 
 |     { | 
 |       if (debug_compile_cplus_scopes) | 
 | 	{ | 
 | 	  gdb_printf (gdb_stdlog, "entering new scope %s\n", | 
 | 		      host_address_to_string (&m_scopes.back ())); | 
 | 	} | 
 |  | 
 |       /* Push the global namespace. */ | 
 |       plugin ().push_namespace (""); | 
 |  | 
 |       /* Push all other namespaces.  Note that we do not push the last | 
 | 	 scope_component -- that's the actual type we are converting.  */ | 
 |       std::for_each | 
 | 	(m_scopes.back ().begin (), m_scopes.back ().end () - 1, | 
 | 	 [this] (const scope_component &comp) | 
 | 	 { | 
 | 	  gdb_assert (comp.bsymbol.symbol->type ()->code () | 
 | 		      == TYPE_CODE_NAMESPACE); | 
 |  | 
 | 	  const char *ns = (comp.name == CP_ANONYMOUS_NAMESPACE_STR ? nullptr | 
 | 			    : comp.name.c_str ()); | 
 |  | 
 | 	  this->plugin ().push_namespace (ns); | 
 | 	 }); | 
 |     } | 
 |   else | 
 |     { | 
 |       if (debug_compile_cplus_scopes) | 
 | 	{ | 
 | 	  gdb_printf (gdb_stdlog, "staying in current scope -- " | 
 | 		      "scopes are identical\n"); | 
 | 	} | 
 |     } | 
 | } | 
 |  | 
 | /* See description in compile-cplus.h.  */ | 
 |  | 
 | void | 
 | compile_cplus_instance::leave_scope () | 
 | { | 
 |   /* Get the current scope and remove it from the internal list of | 
 |      scopes.  */ | 
 |   compile_scope current = m_scopes.back (); | 
 |  | 
 |   m_scopes.pop_back (); | 
 |  | 
 |   if (current.m_pushed) | 
 |     { | 
 |       if (debug_compile_cplus_scopes) | 
 | 	{ | 
 | 	  gdb_printf (gdb_stdlog, "leaving scope %s\n", | 
 | 		      host_address_to_string (¤t)); | 
 | 	} | 
 |  | 
 |       /* Pop namespaces.  */ | 
 |       std::for_each | 
 | 	(current.begin (),current.end () - 1, | 
 | 	 [this] (const scope_component &comp) { | 
 | 	  gdb_assert (comp.bsymbol.symbol->type ()->code () | 
 | 		      == TYPE_CODE_NAMESPACE); | 
 | 	  this->plugin ().pop_binding_level (comp.name.c_str ()); | 
 | 	}); | 
 |  | 
 |       /* Pop global namespace.  */ | 
 |       plugin ().pop_binding_level (""); | 
 |     } | 
 |   else | 
 |     { | 
 |       if (debug_compile_cplus_scopes) | 
 | 	gdb_printf (gdb_stdlog, | 
 | 		    "identical scopes -- not leaving scope\n"); | 
 |     } | 
 | } | 
 |  | 
 | /* See description in compile-cplus.h.  */ | 
 |  | 
 | compile_scope | 
 | compile_cplus_instance::new_scope (const char *type_name, struct type *type) | 
 | { | 
 |   /* Break the type name into components.  If TYPE was defined in some | 
 |      superclass, we do not process TYPE but process the enclosing type | 
 |      instead.  */ | 
 |   compile_scope scope = type_name_to_scope (type_name, block ()); | 
 |  | 
 |   if (!scope.empty ()) | 
 |     { | 
 |       /* Get the name of the last component, which should be the | 
 | 	 unqualified name of the type to process.  */ | 
 |       scope_component &comp = scope.back (); | 
 |  | 
 |       if (!types_equal (type, comp.bsymbol.symbol->type ()) | 
 | 	  && (m_scopes.empty () | 
 | 	      || (m_scopes.back ().back ().bsymbol.symbol | 
 | 		  != comp.bsymbol.symbol))) | 
 | 	{ | 
 | 	  /* The type is defined inside another class(es).  Convert that | 
 | 	     type instead of defining this type.  */ | 
 | 	  convert_type (comp.bsymbol.symbol->type ()); | 
 |  | 
 | 	  /* If the original type (passed in to us) is defined in a nested | 
 | 	     class, the previous call will give us that type's gcc_type. | 
 | 	     Upper layers are expecting to get the original type's | 
 | 	     gcc_type!  */ | 
 | 	  get_cached_type (type, &scope.m_nested_type); | 
 | 	  return scope; | 
 | 	} | 
 |     } | 
 |   else | 
 |     { | 
 |       if (type->name () == nullptr) | 
 | 	{ | 
 | 	  /* Anonymous type  */ | 
 |  | 
 | 	  /* We don't have a qualified name for this to look up, but | 
 | 	     we need a scope.  We have to assume, then, that it is the same | 
 | 	     as the current scope, if any.  */ | 
 | 	  if (!m_scopes.empty ()) | 
 | 	    { | 
 | 	      scope = m_scopes.back (); | 
 | 	      scope.m_pushed = false; | 
 | 	    } | 
 | 	  else | 
 | 	    scope.push_back (scope_component ()); | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  scope_component comp | 
 | 	    = { | 
 | 		decl_name (type->name ()).get (), | 
 | 		lookup_symbol (type->name (), block (), VAR_DOMAIN, nullptr) | 
 | 	      }; | 
 | 	  scope.push_back (comp); | 
 | 	} | 
 |     } | 
 |  | 
 |   /* There must be at least one component in the compile_scope.  */ | 
 |   gdb_assert (scope.size () > 0); | 
 |   return scope; | 
 | } | 
 |  | 
 | /* See description in compile-cplus.h.  */ | 
 |  | 
 | gcc_type | 
 | compile_cplus_instance::convert_reference_base | 
 |   (gcc_type base, enum gcc_cp_ref_qualifiers rquals) | 
 | { | 
 |   return this->plugin ().build_reference_type (base, rquals); | 
 | } | 
 |  | 
 | /* Convert a reference type to its gcc representation.  */ | 
 |  | 
 | static gcc_type | 
 | compile_cplus_convert_reference (compile_cplus_instance *instance, | 
 | 				 struct type *type) | 
 | { | 
 |   gcc_type target = instance->convert_type (TYPE_TARGET_TYPE (type)); | 
 |  | 
 |   enum gcc_cp_ref_qualifiers quals = GCC_CP_REF_QUAL_NONE; | 
 |   switch (type->code ()) | 
 |     { | 
 |     case TYPE_CODE_REF: | 
 |       quals = GCC_CP_REF_QUAL_LVALUE; | 
 |       break; | 
 |     case TYPE_CODE_RVALUE_REF: | 
 |       quals = GCC_CP_REF_QUAL_RVALUE; | 
 |       break; | 
 |     default: | 
 |       gdb_assert_not_reached ("unexpected type code for reference type"); | 
 |     } | 
 |  | 
 |   return instance->convert_reference_base (target, quals); | 
 | } | 
 |  | 
 | /* See description in compile-cplus.h.  */ | 
 |  | 
 | gcc_type | 
 | compile_cplus_instance::convert_pointer_base(gcc_type target) | 
 | { | 
 |   return plugin ().build_pointer_type (target); | 
 | } | 
 |  | 
 | /* Convert a pointer type to its gcc representation.  */ | 
 |  | 
 | static gcc_type | 
 | compile_cplus_convert_pointer (compile_cplus_instance *instance, | 
 | 			       struct type *type) | 
 | { | 
 |   gcc_type target = instance->convert_type (TYPE_TARGET_TYPE (type)); | 
 |  | 
 |   return instance->convert_pointer_base (target); | 
 | } | 
 |  | 
 | /* Convert an array type to its gcc representation.  */ | 
 |  | 
 | static gcc_type | 
 | compile_cplus_convert_array (compile_cplus_instance *instance, | 
 | 			     struct type *type) | 
 | { | 
 |   struct type *range = type->index_type (); | 
 |   gcc_type element_type = instance->convert_type (TYPE_TARGET_TYPE (type)); | 
 |  | 
 |   if (range->bounds ()->low.kind () != PROP_CONST) | 
 |     { | 
 |       const char *s = _("array type with non-constant" | 
 | 			" lower bound is not supported"); | 
 |  | 
 |       return instance->plugin ().error (s); | 
 |     } | 
 |  | 
 |   if (range->bounds ()->low.const_val () != 0) | 
 |     { | 
 |       const char *s = _("cannot convert array type with " | 
 | 			"non-zero lower bound to C"); | 
 |  | 
 |       return instance->plugin ().error (s); | 
 |     } | 
 |  | 
 |   if (range->bounds ()->high.kind () == PROP_LOCEXPR | 
 |       || range->bounds ()->high.kind () == PROP_LOCLIST) | 
 |     { | 
 |       if (type->is_vector ()) | 
 | 	{ | 
 | 	  const char *s = _("variably-sized vector type is not supported"); | 
 |  | 
 | 	  return instance->plugin ().error (s); | 
 | 	} | 
 |  | 
 |       std::string upper_bound | 
 | 	= c_get_range_decl_name (&range->bounds ()->high); | 
 |       return instance->plugin ().build_vla_array_type (element_type, | 
 | 					     upper_bound.c_str ()); | 
 |     } | 
 |   else | 
 |     { | 
 |       LONGEST low_bound, high_bound, count; | 
 |  | 
 |       if (!get_array_bounds (type, &low_bound, &high_bound)) | 
 | 	count = -1; | 
 |       else | 
 | 	{ | 
 | 	  gdb_assert (low_bound == 0); /* Ensured above.  */ | 
 | 	  count = high_bound + 1; | 
 | 	} | 
 |  | 
 |       if (type->is_vector ()) | 
 | 	return instance->plugin ().build_vector_type (element_type, count); | 
 |  | 
 |       return instance->plugin ().build_array_type (element_type, count); | 
 |     } | 
 | } | 
 |  | 
 | /* Convert a typedef of TYPE.  If not GCC_CP_ACCESS_NONE, NESTED_ACCESS | 
 |    will define the accessibility of the typedef definition in its | 
 |    containing class.  */ | 
 |  | 
 | static gcc_type | 
 | compile_cplus_convert_typedef (compile_cplus_instance *instance, | 
 | 			       struct type *type, | 
 | 			       enum gcc_cp_symbol_kind nested_access) | 
 | { | 
 |   compile_scope scope = instance->new_scope (type->name (), type); | 
 |  | 
 |   if (scope.nested_type () != GCC_TYPE_NONE) | 
 |     return scope.nested_type (); | 
 |  | 
 |   gdb::unique_xmalloc_ptr<char> name | 
 |     = compile_cplus_instance::decl_name (type->name ()); | 
 |  | 
 |   /* Make sure the scope for this type has been pushed.  */ | 
 |   instance->enter_scope (std::move (scope)); | 
 |  | 
 |   /* Convert the typedef's real type.  */ | 
 |   gcc_type typedef_type = instance->convert_type (check_typedef (type)); | 
 |  | 
 |   instance->plugin ().build_decl ("typedef", name.get (), | 
 | 				  GCC_CP_SYMBOL_TYPEDEF | nested_access, | 
 | 			typedef_type, 0, 0, nullptr, 0); | 
 |  | 
 |   /* Completed this scope.  */ | 
 |   instance->leave_scope (); | 
 |   return typedef_type; | 
 | } | 
 |  | 
 | /* Convert types defined in TYPE.  */ | 
 |  | 
 | static void | 
 | compile_cplus_convert_type_defns (compile_cplus_instance *instance, | 
 | 				  struct type *type) | 
 | { | 
 |   int i; | 
 |   enum gcc_cp_symbol_kind accessibility; | 
 |  | 
 |   /* Convert typedefs.  */ | 
 |   for (i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (type); ++i) | 
 |     { | 
 |       if (TYPE_TYPEDEF_FIELD_PROTECTED (type, i)) | 
 | 	accessibility = GCC_CP_ACCESS_PROTECTED; | 
 |       else if (TYPE_TYPEDEF_FIELD_PRIVATE (type, i)) | 
 | 	accessibility = GCC_CP_ACCESS_PRIVATE; | 
 |       else | 
 | 	accessibility = GCC_CP_ACCESS_PUBLIC; | 
 |       instance->convert_type (TYPE_TYPEDEF_FIELD_TYPE (type, i), accessibility); | 
 |     } | 
 |  | 
 |   /* Convert nested types.  */ | 
 |   for (i = 0; i < TYPE_NESTED_TYPES_COUNT (type); ++i) | 
 |     { | 
 |       if (TYPE_NESTED_TYPES_FIELD_PROTECTED (type, i)) | 
 | 	accessibility = GCC_CP_ACCESS_PROTECTED; | 
 |       else if (TYPE_NESTED_TYPES_FIELD_PRIVATE (type, i)) | 
 | 	accessibility = GCC_CP_ACCESS_PRIVATE; | 
 |       else | 
 | 	accessibility = GCC_CP_ACCESS_PUBLIC; | 
 |       instance->convert_type (TYPE_NESTED_TYPES_FIELD_TYPE (type, i), | 
 | 			      accessibility); | 
 |     } | 
 | } | 
 |  | 
 | /* Convert data members defined in TYPE, which should be struct/class/union | 
 |    with gcc_type COMP_TYPE.  */ | 
 |  | 
 | static void | 
 | compile_cplus_convert_struct_or_union_members | 
 |   (compile_cplus_instance *instance, struct type *type, gcc_type comp_type) | 
 | { | 
 |   for (int i = TYPE_N_BASECLASSES (type); i < type->num_fields (); ++i) | 
 |     { | 
 |       const char *field_name = type->field (i).name (); | 
 |  | 
 |       if (TYPE_FIELD_IGNORE (type, i) | 
 | 	  || TYPE_FIELD_ARTIFICIAL (type, i)) | 
 | 	continue; | 
 |  | 
 |       /* GDB records unnamed/anonymous fields with empty string names.  */ | 
 |       if (*field_name == '\0') | 
 | 	field_name = nullptr; | 
 |  | 
 |       gcc_type field_type | 
 | 	= instance->convert_type (type->field (i).type ()); | 
 |  | 
 |       if (field_is_static (&type->field (i))) | 
 | 	{ | 
 | 	  CORE_ADDR physaddr; | 
 |  | 
 | 	  switch (type->field (i).loc_kind ()) | 
 | 	    { | 
 | 	    case FIELD_LOC_KIND_PHYSADDR: | 
 | 	      { | 
 | 		physaddr = type->field (i).loc_physaddr (); | 
 |  | 
 | 		instance->plugin ().build_decl | 
 | 		  ("field physaddr", field_name, | 
 | 		   (GCC_CP_SYMBOL_VARIABLE | get_field_access_flag (type, i)), | 
 | 		   field_type, nullptr, physaddr, nullptr, 0); | 
 | 	      } | 
 | 	      break; | 
 |  | 
 | 	    case FIELD_LOC_KIND_PHYSNAME: | 
 | 	      { | 
 | 		const char *physname = type->field (i).loc_physname (); | 
 | 		struct block_symbol sym | 
 | 		  = lookup_symbol (physname, instance->block (), | 
 | 				   VAR_DOMAIN, nullptr); | 
 |  | 
 | 		if (sym.symbol == nullptr) | 
 | 		  { | 
 | 		    /* We didn't actually find the symbol.  There's little | 
 | 		       we can do but ignore this member.  */ | 
 | 		    continue; | 
 | 		  } | 
 | 		const char *filename = symbol_symtab (sym.symbol)->filename; | 
 | 		unsigned int line = sym.symbol->line (); | 
 |  | 
 | 		physaddr = SYMBOL_VALUE_ADDRESS (sym.symbol); | 
 | 		instance->plugin ().build_decl | 
 | 		  ("field physname", field_name, | 
 | 		   (GCC_CP_SYMBOL_VARIABLE| get_field_access_flag (type, i)), | 
 | 		   field_type, nullptr, physaddr, filename, line); | 
 | 	      } | 
 | 	      break; | 
 |  | 
 | 	    default: | 
 | 	      gdb_assert_not_reached | 
 | 		("unexpected static field location kind"); | 
 | 	    } | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  unsigned long bitsize = TYPE_FIELD_BITSIZE (type, i); | 
 | 	  enum gcc_cp_symbol_kind field_flags = GCC_CP_SYMBOL_FIELD | 
 | 	    | get_field_access_flag (type, i); | 
 |  | 
 | 	  if (bitsize == 0) | 
 | 	    bitsize = 8 * TYPE_LENGTH (type->field (i).type ()); | 
 |  | 
 | 	  instance->plugin ().build_field | 
 | 	    (field_name, field_type, field_flags, bitsize, | 
 | 	     type->field (i).loc_bitpos ()); | 
 | 	} | 
 |     } | 
 | } | 
 |  | 
 | /* Convert a method type to its gcc representation.  */ | 
 |  | 
 | static gcc_type | 
 | compile_cplus_convert_method (compile_cplus_instance *instance, | 
 | 			      struct type *parent_type, | 
 | 			      struct type *method_type) | 
 | { | 
 |   /* Get the actual function type of the method, the corresponding class's | 
 |      type and corresponding qualifier flags.  */ | 
 |   gcc_type func_type = compile_cplus_convert_func (instance, method_type, true); | 
 |   gcc_type class_type = instance->convert_type (parent_type); | 
 |   gcc_cp_qualifiers_flags quals = 0; | 
 |  | 
 |   if (TYPE_CONST (method_type)) | 
 |     quals |= GCC_CP_QUALIFIER_CONST; | 
 |   if (TYPE_VOLATILE (method_type)) | 
 |     quals |= GCC_CP_QUALIFIER_VOLATILE; | 
 |   if (TYPE_RESTRICT (method_type)) | 
 |     quals |= GCC_CP_QUALIFIER_RESTRICT; | 
 |  | 
 |   /* Not yet implemented.  */ | 
 |   gcc_cp_ref_qualifiers_flags rquals = GCC_CP_REF_QUAL_NONE; | 
 |  | 
 |   return instance->plugin ().build_method_type | 
 |     (class_type, func_type, quals.raw (), rquals.raw ()); | 
 | } | 
 |  | 
 | /* Convert a member or method pointer represented by TYPE.  */ | 
 |  | 
 | static gcc_type | 
 | compile_cplus_convert_memberptr (compile_cplus_instance *instance, | 
 | 				 struct type *type) | 
 | { | 
 |   struct type *containing_class = TYPE_SELF_TYPE (type); | 
 |  | 
 |   if (containing_class == nullptr) | 
 |     return GCC_TYPE_NONE; | 
 |  | 
 |   gcc_type class_type = instance->convert_type (containing_class); | 
 |   gcc_type member_type | 
 |     = instance->convert_type (TYPE_TARGET_TYPE (type)); | 
 |  | 
 |   return instance->plugin ().build_pointer_to_member_type | 
 |     (class_type, member_type); | 
 | } | 
 |  | 
 | /* Convert all methods defined in TYPE, which should be a class/struct/union | 
 |    with gcc_type CLASS_TYPE.  */ | 
 |  | 
 | static void | 
 | compile_cplus_convert_struct_or_union_methods (compile_cplus_instance *instance, | 
 | 					       struct type *type, | 
 | 					       gcc_type class_type) | 
 | { | 
 |   for (int i = 0; i < TYPE_NFN_FIELDS (type); ++i) | 
 |     { | 
 |       struct fn_field *methods = TYPE_FN_FIELDLIST1 (type, i); | 
 |       gdb::unique_xmalloc_ptr<char> overloaded_name | 
 | 	= compile_cplus_instance::decl_name (TYPE_FN_FIELDLIST_NAME (type, i)); | 
 |  | 
 |       /* Loop through the fieldlist, adding decls to the compiler's | 
 | 	 representation of the class.  */ | 
 |       for (int j = 0; j < TYPE_FN_FIELDLIST_LENGTH (type, i); ++j) | 
 | 	{ | 
 | 	  /* Skip artificial methods.  */ | 
 | 	  if (TYPE_FN_FIELD_ARTIFICIAL (methods, j)) | 
 | 	    continue; | 
 |  | 
 | 	  gcc_cp_symbol_kind_flags sym_kind = GCC_CP_SYMBOL_FUNCTION; | 
 | 	  gcc_type method_type; | 
 | 	  struct block_symbol sym | 
 | 	    = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (methods, j), | 
 | 			     instance->block (), VAR_DOMAIN, nullptr); | 
 |  | 
 | 	  if (sym.symbol == nullptr) | 
 | 	    { | 
 | 	      if (TYPE_FN_FIELD_VIRTUAL_P (methods, j)) | 
 | 		{ | 
 | 		  /* This is beyond hacky, and is really only a workaround for | 
 | 		     detecting pure virtual methods.  */ | 
 | 		  method_type = compile_cplus_convert_method | 
 | 		    (instance, type, TYPE_FN_FIELD_TYPE (methods, j)); | 
 |  | 
 | 		  instance->plugin ().build_decl | 
 | 		    ("pure virtual method", overloaded_name.get (), | 
 | 		     (sym_kind | 
 | 		      | get_method_access_flag (type, i, j) | 
 | 		      | GCC_CP_FLAG_VIRTUAL_FUNCTION | 
 | 		      | GCC_CP_FLAG_PURE_VIRTUAL_FUNCTION).raw (), | 
 | 		     method_type, nullptr, 0, nullptr, 0); | 
 | 		  continue; | 
 | 		} | 
 |  | 
 | 	      /* This can happen if we have a DW_AT_declaration DIE | 
 | 		 for the method, but no "definition"-type DIE (with | 
 | 		 DW_AT_specification referencing the decl DIE), i.e., | 
 | 		 the compiler has probably optimized the method away. | 
 |  | 
 | 		 In this case, all we can hope to do is issue a warning | 
 | 		 to the user letting him know.  If the user has not actually | 
 | 		 requested using this method, things should still work.  */ | 
 | 	      warning (_("Method %s appears to be optimized out.\n" | 
 | 			 "All references to this method will be undefined."), | 
 | 			 TYPE_FN_FIELD_PHYSNAME (methods, j)); | 
 | 	      continue; | 
 | 	    } | 
 |  | 
 | 	  const char *filename = symbol_symtab (sym.symbol)->filename; | 
 | 	  unsigned int line = sym.symbol->line (); | 
 | 	  CORE_ADDR address = BLOCK_START (SYMBOL_BLOCK_VALUE (sym.symbol)); | 
 | 	  const char *kind; | 
 |  | 
 | 	  if (TYPE_FN_FIELD_STATIC_P (methods, j)) | 
 | 	    { | 
 | 	      kind = "static method"; | 
 | 	      method_type = compile_cplus_convert_func | 
 | 		(instance, TYPE_FN_FIELD_TYPE (methods, j), true); | 
 | 	    } | 
 | 	  else | 
 | 	    { | 
 | 	      kind = "method"; | 
 | 	      method_type = (compile_cplus_convert_method | 
 | 			     (instance, type, TYPE_FN_FIELD_TYPE (methods, j))); | 
 | 	    } | 
 |  | 
 | 	  if (TYPE_FN_FIELD_VIRTUAL_P (methods, j)) | 
 | 	    sym_kind |= GCC_CP_FLAG_VIRTUAL_FUNCTION; | 
 |  | 
 | 	  instance->plugin ().build_decl | 
 | 	    (kind, overloaded_name.get (), | 
 | 	     (sym_kind | get_method_access_flag (type, i, j)).raw (), | 
 | 	     method_type, nullptr, address, filename, line); | 
 | 	} | 
 |     } | 
 | } | 
 |  | 
 | /* Convert a struct or union type to its gcc representation.  If this type | 
 |    was defined in another type, NESTED_ACCESS should indicate the | 
 |    accessibility of this type.  */ | 
 |  | 
 | static gcc_type | 
 | compile_cplus_convert_struct_or_union (compile_cplus_instance *instance, | 
 | 				       struct type *type, | 
 | 				       enum gcc_cp_symbol_kind nested_access) | 
 | { | 
 |   const char *filename = nullptr; | 
 |   unsigned short line = 0; | 
 |  | 
 |   /* Get the decl name of this type.  */ | 
 |   gdb::unique_xmalloc_ptr<char> name | 
 |     = compile_cplus_instance::decl_name (type->name ()); | 
 |  | 
 |   /* Create a new scope for TYPE.  */ | 
 |   compile_scope scope = instance->new_scope (type->name (), type); | 
 |  | 
 |   if (scope.nested_type () != GCC_TYPE_NONE) | 
 |     { | 
 |       /* The type requested was actually defined inside another type, | 
 | 	 such as a nested class definition.  Return that type.  */ | 
 |       return scope.nested_type (); | 
 |     } | 
 |  | 
 |   /* Push all scopes.  */ | 
 |   instance->enter_scope (std::move (scope)); | 
 |  | 
 |   /* First we create the resulting type and enter it into our hash | 
 |      table.  This lets recursive types work.  */ | 
 |  | 
 |   gcc_decl resuld; | 
 |   if (type->code () == TYPE_CODE_STRUCT) | 
 |     { | 
 |       const char *what = type->is_declared_class () ? "class" : "struct"; | 
 |  | 
 |       resuld = instance->plugin ().build_decl | 
 | 	(what, name.get (), (GCC_CP_SYMBOL_CLASS | nested_access | 
 | 			     | (type->is_declared_class () | 
 | 				? GCC_CP_FLAG_CLASS_NOFLAG | 
 | 				: GCC_CP_FLAG_CLASS_IS_STRUCT)), | 
 | 	 0, nullptr, 0, filename, line); | 
 |     } | 
 |   else | 
 |     { | 
 |       gdb_assert (type->code () == TYPE_CODE_UNION); | 
 |       resuld = instance->plugin ().build_decl | 
 | 	("union", name.get (), GCC_CP_SYMBOL_UNION | nested_access, | 
 | 	 0, nullptr, 0, filename, line); | 
 |     } | 
 |  | 
 |   gcc_type result; | 
 |   if (type->code () == TYPE_CODE_STRUCT) | 
 |     { | 
 |       int num_baseclasses = TYPE_N_BASECLASSES (type); | 
 |       std::vector<gcc_type> elements (num_baseclasses); | 
 |       std::vector<enum gcc_cp_symbol_kind> flags (num_baseclasses); | 
 |  | 
 |       struct gcc_vbase_array bases {}; | 
 |       bases.elements = elements.data (); | 
 |       bases.flags = flags.data (); | 
 |       bases.n_elements = num_baseclasses; | 
 |  | 
 |       for (int i = 0; i < num_baseclasses; ++i) | 
 | 	{ | 
 | 	  struct type *base_type = TYPE_BASECLASS (type, i); | 
 |  | 
 | 	  bases.flags[i] = (GCC_CP_SYMBOL_BASECLASS | 
 | 			    | get_field_access_flag (type, i) | 
 | 			    | (BASETYPE_VIA_VIRTUAL (type, i) | 
 | 			       ? GCC_CP_FLAG_BASECLASS_VIRTUAL | 
 | 			       : GCC_CP_FLAG_BASECLASS_NOFLAG)); | 
 | 	  bases.elements[i] = instance->convert_type (base_type); | 
 | 	} | 
 |  | 
 |       result = instance->plugin ().start_class_type | 
 | 	(name.get (), resuld, &bases, filename, line); | 
 |     } | 
 |   else | 
 |     { | 
 |       gdb_assert (type->code () == TYPE_CODE_UNION); | 
 |       result = instance->plugin ().start_class_type | 
 | 	(name.get (), resuld, nullptr, filename, line); | 
 |     } | 
 |  | 
 |   instance->insert_type (type, result); | 
 |  | 
 |   /* Add definitions.  */ | 
 |   compile_cplus_convert_type_defns (instance, type); | 
 |  | 
 |   /* Add methods.  */ | 
 |   compile_cplus_convert_struct_or_union_methods (instance, type, result); | 
 |  | 
 |   /* Add members.  */ | 
 |   compile_cplus_convert_struct_or_union_members (instance, type, result); | 
 |  | 
 |   /* All finished.  */ | 
 |   instance->plugin ().finish_class_type (name.get (), TYPE_LENGTH (type)); | 
 |  | 
 |   /* Pop all scopes.  */ | 
 |   instance->leave_scope (); | 
 |   return result; | 
 | } | 
 |  | 
 | /* Convert an enum type to its gcc representation.  If this type | 
 |    was defined in another type, NESTED_ACCESS should indicate the | 
 |    accessibility of this type.*/ | 
 |  | 
 | static gcc_type | 
 | compile_cplus_convert_enum (compile_cplus_instance *instance, struct type *type, | 
 | 			    enum gcc_cp_symbol_kind nested_access) | 
 | { | 
 |   bool scoped_enum_p = false; | 
 |  | 
 |   /* Create a new scope for this type.  */ | 
 |   compile_scope scope = instance->new_scope (type->name (), type); | 
 |  | 
 |   if (scope.nested_type () != GCC_TYPE_NONE) | 
 |     { | 
 |       /* The type requested was actually defined inside another type, | 
 | 	 such as a nested class definition.  Return that type.  */ | 
 |       return scope.nested_type (); | 
 |     } | 
 |  | 
 |   gdb::unique_xmalloc_ptr<char> name | 
 |     = compile_cplus_instance::decl_name (type->name ()); | 
 |  | 
 |   /* Push all scopes.  */ | 
 |   instance->enter_scope (std::move (scope)); | 
 |  | 
 |   gcc_type int_type | 
 |     = instance->plugin ().get_int_type (type->is_unsigned (), | 
 | 					TYPE_LENGTH (type), nullptr); | 
 |   gcc_type result | 
 |     = instance->plugin ().start_enum_type (name.get (), int_type, | 
 | 					   GCC_CP_SYMBOL_ENUM | nested_access | 
 | 					   | (scoped_enum_p | 
 | 					      ? GCC_CP_FLAG_ENUM_SCOPED | 
 | 					      : GCC_CP_FLAG_ENUM_NOFLAG), | 
 | 					   nullptr, 0); | 
 |   for (int i = 0; i < type->num_fields (); ++i) | 
 |     { | 
 |       gdb::unique_xmalloc_ptr<char> fname | 
 | 	= compile_cplus_instance::decl_name (type->field (i).name ()); | 
 |  | 
 |       if (type->field (i).loc_kind () != FIELD_LOC_KIND_ENUMVAL | 
 | 	  || fname == nullptr) | 
 | 	continue; | 
 |  | 
 |       instance->plugin ().build_enum_constant (result, fname.get (), | 
 | 					       type->field (i).loc_enumval ()); | 
 |     } | 
 |  | 
 |   /* Finish enum definition and pop scopes.  */ | 
 |   instance->plugin ().finish_enum_type (result); | 
 |   instance->leave_scope (); | 
 |   return result; | 
 | } | 
 |  | 
 | /* Convert a function type to its gcc representation.  This function does | 
 |    not deal with function templates.  */ | 
 |  | 
 | static gcc_type | 
 | compile_cplus_convert_func (compile_cplus_instance *instance, | 
 | 			    struct type *type, bool strip_artificial) | 
 | { | 
 |   int is_varargs = type->has_varargs (); | 
 |   struct type *target_type = TYPE_TARGET_TYPE (type); | 
 |  | 
 |   /* Functions with no debug info have no return type.  Ideally we'd | 
 |      want to fallback to the type of the cast just before the | 
 |      function, like GDB's built-in expression parser, but we don't | 
 |      have access to that type here.  For now, fallback to int, like | 
 |      GDB's parser used to do.  */ | 
 |   if (target_type == nullptr) | 
 |     { | 
 |       if (type->is_objfile_owned ()) | 
 | 	target_type = objfile_type (type->objfile_owner ())->builtin_int; | 
 |       else | 
 | 	target_type = builtin_type (type->arch_owner ())->builtin_int; | 
 |       warning (_("function has unknown return type; assuming int")); | 
 |     } | 
 |  | 
 |   /* This approach means we can't make self-referential function | 
 |      types.  Those are impossible in C, though.  */ | 
 |   gcc_type return_type = instance->convert_type (target_type); | 
 |  | 
 |   std::vector<gcc_type> elements (type->num_fields ()); | 
 |   struct gcc_type_array array = { type->num_fields (), elements.data () }; | 
 |   int artificials = 0; | 
 |   for (int i = 0; i < type->num_fields (); ++i) | 
 |     { | 
 |       if (strip_artificial && TYPE_FIELD_ARTIFICIAL (type, i)) | 
 | 	{ | 
 | 	  --array.n_elements; | 
 | 	  ++artificials; | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  array.elements[i - artificials] | 
 | 	    = instance->convert_type (type->field (i).type ()); | 
 | 	} | 
 |     } | 
 |  | 
 |   /* We omit setting the argument types to `void' to be a little flexible | 
 |      with some minsyms like printf (compile-cplus.exp has examples).  */ | 
 |   gcc_type result = instance->plugin ().build_function_type | 
 |     (return_type, &array, is_varargs); | 
 |   return result; | 
 | } | 
 |  | 
 | /* Convert an integer type to its gcc representation.  */ | 
 |  | 
 | static gcc_type | 
 | compile_cplus_convert_int (compile_cplus_instance *instance, struct type *type) | 
 | { | 
 |   if (type->has_no_signedness ()) | 
 |     { | 
 |       gdb_assert (TYPE_LENGTH (type) == 1); | 
 |       return instance->plugin ().get_char_type (); | 
 |     } | 
 |  | 
 |   return instance->plugin ().get_int_type | 
 |     (type->is_unsigned (), TYPE_LENGTH (type), type->name ()); | 
 | } | 
 |  | 
 | /* Convert a floating-point type to its gcc representation.  */ | 
 |  | 
 | static gcc_type | 
 | compile_cplus_convert_float (compile_cplus_instance *instance, | 
 | 			     struct type *type) | 
 | { | 
 |   return instance->plugin ().get_float_type | 
 |     (TYPE_LENGTH (type), type->name ()); | 
 | } | 
 |  | 
 | /* Convert the 'void' type to its gcc representation.  */ | 
 |  | 
 | static gcc_type | 
 | compile_cplus_convert_void (compile_cplus_instance *instance, struct type *type) | 
 | { | 
 |   return instance->plugin ().get_void_type (); | 
 | } | 
 |  | 
 | /* Convert a boolean type to its gcc representation.  */ | 
 |  | 
 | static gcc_type | 
 | compile_cplus_convert_bool (compile_cplus_instance *instance, struct type *type) | 
 | { | 
 |   return instance->plugin ().get_bool_type (); | 
 | } | 
 |  | 
 | /* See description in compile-cplus.h.  */ | 
 |  | 
 | gcc_type | 
 | compile_cplus_instance::convert_qualified_base (gcc_type base, | 
 | 						gcc_cp_qualifiers_flags quals) | 
 | { | 
 |   gcc_type result = base; | 
 |  | 
 |   if (quals != 0) | 
 |     result = plugin ().build_qualified_type (base, quals.raw ()); | 
 |  | 
 |   return result; | 
 | } | 
 |  | 
 | /* See description in compile-cplus.h.  */ | 
 |  | 
 | static gcc_type | 
 | compile_cplus_convert_qualified (compile_cplus_instance *instance, | 
 | 				 struct type *type) | 
 | { | 
 |   struct type *unqual = make_unqualified_type (type); | 
 |   gcc_cp_qualifiers_flags quals = (enum gcc_cp_qualifiers) 0; | 
 |   gcc_type unqual_converted = instance->convert_type (unqual); | 
 |  | 
 |   if (TYPE_CONST (type)) | 
 |     quals |= GCC_CP_QUALIFIER_CONST; | 
 |   if (TYPE_VOLATILE (type)) | 
 |     quals |= GCC_CP_QUALIFIER_VOLATILE; | 
 |   if (TYPE_RESTRICT (type)) | 
 |     quals |= GCC_CP_QUALIFIER_RESTRICT; | 
 |  | 
 |   return instance->convert_qualified_base (unqual_converted, quals); | 
 | } | 
 |  | 
 | /* Convert a complex type to its gcc representation.  */ | 
 |  | 
 | static gcc_type | 
 | compile_cplus_convert_complex (compile_cplus_instance *instance, | 
 | 			       struct type *type) | 
 | { | 
 |   gcc_type base = instance->convert_type (TYPE_TARGET_TYPE (type)); | 
 |  | 
 |   return instance->plugin ().build_complex_type (base); | 
 | } | 
 |  | 
 | /* Convert a namespace of TYPE.  */ | 
 |  | 
 | static gcc_type | 
 | compile_cplus_convert_namespace (compile_cplus_instance *instance, | 
 | 				 struct type *type) | 
 | { | 
 |   compile_scope scope = instance->new_scope (type->name (), type); | 
 |   gdb::unique_xmalloc_ptr<char> name | 
 |     = compile_cplus_instance::decl_name (type->name ()); | 
 |  | 
 |   /* Push scope.  */ | 
 |   instance->enter_scope (std::move (scope)); | 
 |  | 
 |   /* Convert this namespace.  */ | 
 |   instance->plugin ().push_namespace (name.get ()); | 
 |   instance->plugin ().pop_binding_level (name.get ()); | 
 |  | 
 |   /* Pop scope.  */ | 
 |   instance->leave_scope (); | 
 |  | 
 |   /* Namespaces are non-cacheable types.  */ | 
 |   return GCC_TYPE_NONE; | 
 | } | 
 |  | 
 | /* A helper function which knows how to convert most types from their | 
 |    gdb representation to the corresponding gcc form.  This examines | 
 |    the TYPE and dispatches to the appropriate conversion function.  It | 
 |    returns the gcc type. | 
 |  | 
 |    If the type was defined in another type, NESTED_ACCESS should indicate the | 
 |    accessibility of this type.  */ | 
 |  | 
 | static gcc_type | 
 | convert_type_cplus_basic (compile_cplus_instance *instance, | 
 | 			  struct type *type, | 
 | 			  enum gcc_cp_symbol_kind nested_access) | 
 | { | 
 |   /* If we are converting a qualified type, first convert the | 
 |      unqualified type and then apply the qualifiers.  */ | 
 |   if ((type->instance_flags () & (TYPE_INSTANCE_FLAG_CONST | 
 | 				  | TYPE_INSTANCE_FLAG_VOLATILE | 
 | 				  | TYPE_INSTANCE_FLAG_RESTRICT)) != 0) | 
 |     return compile_cplus_convert_qualified (instance, type); | 
 |  | 
 |   switch (type->code ()) | 
 |     { | 
 |     case TYPE_CODE_REF: | 
 |     case TYPE_CODE_RVALUE_REF: | 
 |       return compile_cplus_convert_reference (instance, type); | 
 |  | 
 |     case TYPE_CODE_PTR: | 
 |       return compile_cplus_convert_pointer (instance, type); | 
 |  | 
 |     case TYPE_CODE_ARRAY: | 
 |       return compile_cplus_convert_array (instance, type); | 
 |  | 
 |     case TYPE_CODE_STRUCT: | 
 |     case TYPE_CODE_UNION: | 
 |       return | 
 | 	compile_cplus_convert_struct_or_union (instance, type, nested_access); | 
 |  | 
 |     case TYPE_CODE_ENUM: | 
 |       return compile_cplus_convert_enum (instance, type, nested_access); | 
 |  | 
 |     case TYPE_CODE_FUNC: | 
 |       return compile_cplus_convert_func (instance, type, false); | 
 |  | 
 |     case TYPE_CODE_METHOD: | 
 |       return | 
 | 	compile_cplus_convert_method (instance, TYPE_SELF_TYPE (type), type); | 
 |  | 
 |     case TYPE_CODE_MEMBERPTR: | 
 |     case TYPE_CODE_METHODPTR: | 
 |       return compile_cplus_convert_memberptr (instance, type); | 
 |       break; | 
 |  | 
 |     case TYPE_CODE_INT: | 
 |       return compile_cplus_convert_int (instance, type); | 
 |  | 
 |     case TYPE_CODE_FLT: | 
 |       return compile_cplus_convert_float (instance, type); | 
 |  | 
 |     case TYPE_CODE_VOID: | 
 |       return compile_cplus_convert_void (instance, type); | 
 |  | 
 |     case TYPE_CODE_BOOL: | 
 |       return compile_cplus_convert_bool (instance, type); | 
 |  | 
 |     case TYPE_CODE_COMPLEX: | 
 |       return compile_cplus_convert_complex (instance, type); | 
 |  | 
 |     case TYPE_CODE_NAMESPACE: | 
 |       return compile_cplus_convert_namespace (instance, type); | 
 |  | 
 |     case TYPE_CODE_TYPEDEF: | 
 |       return compile_cplus_convert_typedef (instance, type, nested_access); | 
 |  | 
 |     default: | 
 |       break; | 
 |     } | 
 |  | 
 |   std::string s = string_printf (_("unhandled TYPE_CODE %d"), | 
 | 				 type->code ()); | 
 |  | 
 |   return instance->plugin ().error (s.c_str ()); | 
 | } | 
 |  | 
 | gcc_type | 
 | compile_cplus_instance::convert_type (struct type *type, | 
 | 				      enum gcc_cp_symbol_kind nested_access) | 
 | { | 
 |   /* Check if TYPE has already been converted.  */ | 
 |   gcc_type result; | 
 |   if (get_cached_type (type, &result)) | 
 |     return result; | 
 |  | 
 |   /* It is the first time this type has been seen -- convert it | 
 |      and cache it, if appropriate..  */ | 
 |   result = convert_type_cplus_basic (this, type, nested_access); | 
 |   if (result != GCC_TYPE_NONE) | 
 |     insert_type (type, result); | 
 |   return result; | 
 | } | 
 |  | 
 | void | 
 | compile_cplus_instance::gcc_cplus_enter_scope | 
 |  (void *datum, struct gcc_cp_context *gcc_context) | 
 | { | 
 | } | 
 |  | 
 | void | 
 | compile_cplus_instance::gcc_cplus_leave_scope | 
 |   (void *datum, struct gcc_cp_context *gcc_context) | 
 | { | 
 | } | 
 |  | 
 |  | 
 |  | 
 | /* Plug-in forwards.  */ | 
 |  | 
 | /* C++ plug-in wrapper.  */ | 
 |  | 
 | /* A result printer for plug-in calls that return a gcc_type or | 
 |    gcc_decl.  */ | 
 |  | 
 | static void | 
 | compile_cplus_debug_output_1 (ULONGEST arg) | 
 | { | 
 |   gdb_printf (gdb_stdlog, "%s", pulongest (arg)); | 
 | } | 
 |  | 
 | static void | 
 | compile_cplus_debug_output_1 (const char *arg) | 
 | { | 
 |   if (arg == nullptr) | 
 |     gdb_puts ("NULL", gdb_stdlog); | 
 |   else | 
 |     gdb_puts (arg, gdb_stdlog); | 
 | } | 
 |  | 
 | static void | 
 | compile_cplus_debug_output () | 
 | { | 
 | } | 
 |  | 
 | template <typename T> | 
 | static void | 
 | compile_cplus_debug_output_1 (const T *arg) | 
 | { | 
 | } | 
 |  | 
 | template <typename T, typename... Targs> | 
 | static void | 
 | compile_cplus_debug_output (T arg, Targs... Args) | 
 | { | 
 |   compile_cplus_debug_output_1 (arg); | 
 |   gdb_putc (' ', gdb_stdlog); | 
 |   compile_cplus_debug_output (Args...); | 
 | } | 
 |  | 
 | #define FORWARD(OP,...) m_context->cp_ops->OP(m_context, ##__VA_ARGS__) | 
 | #define OUTPUT_DEBUG_RESULT(R)			  \ | 
 |   if (debug_compile_cplus_types)		  \ | 
 |     {						  \ | 
 |       gdb_puts (": ", gdb_stdlog);		  \ | 
 |       compile_cplus_debug_output (R);		  \ | 
 |       gdb_putc ('\n', gdb_stdlog);		  \ | 
 |     }						  \ | 
 |  | 
 | #define GCC_METHOD0(R, N)			  \ | 
 |   R gcc_cp_plugin::N () const			  \ | 
 |   {						  \ | 
 |     if (debug_compile_cplus_types)		  \ | 
 |       compile_cplus_debug_output (STRINGIFY (N)); \ | 
 |     auto result = FORWARD (N);			  \ | 
 |     OUTPUT_DEBUG_RESULT (result);		  \ | 
 |     return result;				  \ | 
 |   } | 
 | #define GCC_METHOD1(R, N, A)				\ | 
 |   R gcc_cp_plugin::N (A a) const			\ | 
 |   {							\ | 
 |     if (debug_compile_cplus_types)			\ | 
 |       compile_cplus_debug_output (STRINGIFY (N), a);	\ | 
 |     auto result = FORWARD (N, a);			\ | 
 |     OUTPUT_DEBUG_RESULT (result);			\ | 
 |     return result;					\ | 
 |   } | 
 | #define GCC_METHOD2(R, N, A, B)				\ | 
 |   R gcc_cp_plugin::N (A a, B b) const			\ | 
 |   {							\ | 
 |     if (debug_compile_cplus_types)			\ | 
 |       compile_cplus_debug_output (STRINGIFY (N), a, b);	\ | 
 |     auto result = FORWARD (N, a, b);			\ | 
 |     OUTPUT_DEBUG_RESULT (result);			\ | 
 |     return result;					\ | 
 |   } | 
 | #define GCC_METHOD3(R, N, A, B, C) \ | 
 |   R gcc_cp_plugin::N (A a, B b, C c) const			\ | 
 |   {								\ | 
 |     if (debug_compile_cplus_types)				\ | 
 |       compile_cplus_debug_output (STRINGIFY (N), a, b, c);	\ | 
 |     auto result = FORWARD (N, a, b, c);				\ | 
 |     OUTPUT_DEBUG_RESULT (result);				\ | 
 |     return result;						\ | 
 |   } | 
 | #define GCC_METHOD4(R, N, A, B, C, D)				\ | 
 |   R gcc_cp_plugin::N (A a, B b, C c, D d) const			\ | 
 |   {								\ | 
 |     if (debug_compile_cplus_types)				\ | 
 |       compile_cplus_debug_output (STRINGIFY (N), a, b, c, d);	\ | 
 |     auto result = FORWARD (N, a, b, c, d);			\ | 
 |     OUTPUT_DEBUG_RESULT (result);				\ | 
 |     return result;						\ | 
 |   } | 
 | #define GCC_METHOD5(R, N, A, B, C, D, E)				\ | 
 |   R gcc_cp_plugin::N (A a, B b, C c, D d, E e) const			\ | 
 |   {									\ | 
 |     if (debug_compile_cplus_types)					\ | 
 |       compile_cplus_debug_output (STRINGIFY (N), a, b, c, d, e);	\ | 
 |     auto result = FORWARD (N, a, b, c, d, e);				\ | 
 |     OUTPUT_DEBUG_RESULT (result);					\ | 
 |     return result;							\ | 
 |   } | 
 | #define GCC_METHOD7(R, N, A, B, C, D, E, F, G)				\ | 
 |   R gcc_cp_plugin::N (A a, B b, C c, D d, E e, F f, G g) const		\ | 
 |   {									\ | 
 |     if (debug_compile_cplus_types)					\ | 
 |       compile_cplus_debug_output (STRINGIFY (N), a, b, c, d, e, f, g);	\ | 
 |     auto result = FORWARD (N, a, b, c, d, e, f, g);			\ | 
 |     OUTPUT_DEBUG_RESULT (result);					\ | 
 |     return result;							\ | 
 |   } | 
 |  | 
 | #include "gcc-cp-fe.def" | 
 |  | 
 | #undef GCC_METHOD0 | 
 | #undef GCC_METHOD1 | 
 | #undef GCC_METHOD2 | 
 | #undef GCC_METHOD3 | 
 | #undef GCC_METHOD4 | 
 | #undef GCC_METHOD5 | 
 | #undef GCC_METHOD7 | 
 | #undef FORWARD | 
 | #undef OUTPUT_DEBUG_RESULT | 
 |  | 
 | gcc_expr | 
 | gcc_cp_plugin::build_decl (const char *debug_decltype, const char *name, | 
 | 			   enum gcc_cp_symbol_kind sym_kind, gcc_type sym_type, | 
 | 			   const char *substitution_name, gcc_address address, | 
 | 			   const char *filename, unsigned int line_number) | 
 | { | 
 |   if (debug_compile_cplus_types) | 
 |     gdb_printf (gdb_stdlog, "<%s> ", debug_decltype); | 
 |  | 
 |   return build_decl (name, sym_kind, sym_type, substitution_name, | 
 | 		     address, filename, line_number); | 
 | } | 
 |  | 
 | gcc_type | 
 | gcc_cp_plugin::start_class_type (const char *debug_name, gcc_decl typedecl, | 
 | 				 const struct gcc_vbase_array *base_classes, | 
 | 				 const char *filename, unsigned int line_number) | 
 | { | 
 |   if (debug_compile_cplus_types) | 
 |     gdb_printf (gdb_stdlog, "<%s> ", debug_name); | 
 |  | 
 |   return start_class_type (typedecl, base_classes, filename, line_number); | 
 | } | 
 |  | 
 | int | 
 | gcc_cp_plugin::finish_class_type (const char *debug_name, | 
 | 				  unsigned long size_in_bytes) | 
 | { | 
 |   if (debug_compile_cplus_types) | 
 |     gdb_printf (gdb_stdlog, "<%s> ", debug_name); | 
 |  | 
 |   return finish_class_type (size_in_bytes); | 
 | } | 
 |  | 
 | int | 
 | gcc_cp_plugin::pop_binding_level (const char *debug_name) | 
 | { | 
 |   if (debug_compile_cplus_types) | 
 |     gdb_printf (gdb_stdlog, "<%s> ", debug_name); | 
 |  | 
 |   return pop_binding_level (); | 
 | } | 
 |  | 
 | void _initialize_compile_cplus_types (); | 
 | void | 
 | _initialize_compile_cplus_types () | 
 | { | 
 |   add_setshow_boolean_cmd ("compile-cplus-types", no_class, | 
 | 			     &debug_compile_cplus_types, _("\ | 
 | Set debugging of C++ compile type conversion."), _("\ | 
 | Show debugging of C++ compile type conversion."), _("\ | 
 | When enabled debugging messages are printed during C++ type conversion for\n\ | 
 | the compile commands."), | 
 | 			     nullptr, | 
 | 			     nullptr, | 
 | 			     &setdebuglist, | 
 | 			     &showdebuglist); | 
 |  | 
 |   add_setshow_boolean_cmd ("compile-cplus-scopes", no_class, | 
 | 			     &debug_compile_cplus_scopes, _("\ | 
 | Set debugging of C++ compile scopes."), _("\ | 
 | Show debugging of C++ compile scopes."), _("\ | 
 | When enabled debugging messages are printed about definition scopes during\n\ | 
 | C++ type conversion for the compile commands."), | 
 | 			     nullptr, | 
 | 			     nullptr, | 
 | 			     &setdebuglist, | 
 | 			     &showdebuglist); | 
 | } |