12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427 |
- /* 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);
- }
|