From: Keith Seitz Date: Thu, 13 Apr 2017 18:39:07 +0000 (-0700) Subject: Update w/HEAD. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ff9064cfb4e6a40b5889cb9180f97dac1d487a0d;p=thirdparty%2Fbinutils-gdb.git Update w/HEAD. Problems: gdb/ada-lang.c gdb/compile/compile-c-support.c gdb/dwarf2read.c gdb/gdbtypes.h gdb/linespec.c gdb/mdebugread.c gdb/symtab.c gdb/symtab.h --- ff9064cfb4e6a40b5889cb9180f97dac1d487a0d diff --cc gdb/ada-lang.c index e0e3204da24,2e5643bd032..1dba0723864 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@@ -5861,7 -5859,7 +5859,7 @@@ ada_iterate_over_symbol ndefs = ada_lookup_symbol_list_worker (name, block, domain, &results, 0); for (i = 0; i < ndefs; ++i) { - if (! (*callback) (results[i], data)) - if (!callback (results[i].symbol)) ++ if (!callback (&results[i])) break; } } diff --cc gdb/compile/compile-c-support.c index bc25008408d,2614570072d..41f7aecc64f --- a/gdb/compile/compile-c-support.c +++ b/gdb/compile/compile-c-support.c @@@ -67,23 -66,30 +68,25 @@@ c_get_range_decl_name (const struct dyn #define STR(x) #x #define STRINGIFY(x) STR(x) -/* Helper function for c_get_compile_context. Open the GCC front-end - shared library and return the symbol specified by the current - GCC_C_FE_CONTEXT. */ +/* Load the plug-in library FE_LIBCC and return the initialization function + FE_CONTEXT. */ -static gcc_c_fe_context_function * -load_libcc (void) +template +FUNCTYPE * +load_libcompile (const char *fe_libcc, const char *fe_context) { - void *handle; - gcc_c_fe_context_function *func; + FUNCTYPE *func; - /* gdb_dlopen will call error () on an error, so no need to check - value. */ - gdb_dlhandle_up handle = gdb_dlopen (STRINGIFY (GCC_C_FE_LIBCC)); - func = (gcc_c_fe_context_function *) gdb_dlsym (handle, - STRINGIFY (GCC_C_FE_CONTEXT)); + /* gdb_dlopen will call error () on an error, so no need to check + value. */ - handle = gdb_dlopen (fe_libcc); ++ gdb_dlhandle_up handle = gdb_dlopen (fe_libcc); + func = (FUNCTYPE *) (gdb_dlsym (handle, fe_context)); if (func == NULL) - error (_("could not find symbol %s in library %s"), - STRINGIFY (GCC_C_FE_CONTEXT), - STRINGIFY (GCC_C_FE_LIBCC)); + error (_("could not find symbol %s in library %s"), fe_context, fe_libcc); + + /* Leave the library open. */ + handle.release (); return func; } @@@ -198,9 -169,83 +199,18 @@@ write_macro_definitions (const struct b scope = user_macro_scope (); if (scope != NULL && scope->file != NULL && scope->file->table != NULL) - macro_for_each_in_scope (scope->file, scope->line, print_one_macro, file); + { + macro_for_each_in_scope (scope->file, scope->line, + [&] (const char *name, + const macro_definition *macro, + macro_source_file *source, + int line) + { + print_one_macro (name, macro, source, line, file); + }); + } } -/* Helper function to construct a header scope for a block of code. - Takes a scope argument which selects the correct header to - insert into BUF. */ - -static void -add_code_header (enum compile_i_scope_types type, struct ui_file *buf) -{ - switch (type) - { - case COMPILE_I_SIMPLE_SCOPE: - fputs_unfiltered ("void " - GCC_FE_WRAPPER_FUNCTION - " (struct " - COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG - " *" - COMPILE_I_SIMPLE_REGISTER_ARG_NAME - ") {\n", - buf); - break; - case COMPILE_I_PRINT_ADDRESS_SCOPE: - case COMPILE_I_PRINT_VALUE_SCOPE: - /* is needed for a memcpy call below. */ - fputs_unfiltered ("#include \n" - "void " - GCC_FE_WRAPPER_FUNCTION - " (struct " - COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG - " *" - COMPILE_I_SIMPLE_REGISTER_ARG_NAME - ", " - COMPILE_I_PRINT_OUT_ARG_TYPE - " " - COMPILE_I_PRINT_OUT_ARG - ") {\n", - buf); - break; - - case COMPILE_I_RAW_SCOPE: - break; - default: - gdb_assert_not_reached (_("Unknown compiler scope reached.")); - } -} - -/* Helper function to construct a footer scope for a block of code. - Takes a scope argument which selects the correct footer to - insert into BUF. */ - -static void -add_code_footer (enum compile_i_scope_types type, struct ui_file *buf) -{ - switch (type) - { - case COMPILE_I_SIMPLE_SCOPE: - case COMPILE_I_PRINT_ADDRESS_SCOPE: - case COMPILE_I_PRINT_VALUE_SCOPE: - fputs_unfiltered ("}\n", buf); - break; - case COMPILE_I_RAW_SCOPE: - break; - default: - gdb_assert_not_reached (_("Unknown compiler scope reached.")); - } -} - /* Generate a structure holding all the registers used by the function we're generating. */ diff --cc gdb/compile/compile-cplus-types.c index 151c35e2523,00000000000..084d94d0754 mode 100644,000000..100644 --- a/gdb/compile/compile-cplus-types.c +++ b/gdb/compile/compile-cplus-types.c @@@ -1,2273 -1,0 +1,2271 @@@ +/* Convert types from GDB to GCC + + Copyright (C) 2014-2017 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 . */ + + +#include "defs.h" +#include "gdbtypes.h" +#include "compile-internal.h" +#include "compile-cplus.h" +#include "gdb_assert.h" +#include "symtab.h" +#include "source.h" +#include "cp-support.h" +#include "cp-abi.h" +#include "symtab.h" +#include "objfiles.h" +#include "block.h" +#include "gdbcmd.h" +#include "c-lang.h" +#include "compile-c.h" /* Included for c_get_range_decl_name + et al. */ + +#include + +using namespace compile; + +/* Define to enable debugging for ctor/dtor definitions during + type conversion. */ + +#define DEBUG_XTOR 0 + +/* A "type" to indicate that convert_type should not attempt to + cache its resultant type. This is used, for example, when defining + namespaces for the oracle. */ + +#define DONT_CACHE_TYPE ((gcc_type) 0) + +/* Flag to enable internal debugging. */ + +static int debug_compile_cplus_types = 0; + +/* Flag to enable internal scope switching debugging. */ + +static int debug_compile_cplus_scopes = 0; + +/* Forward declarations. */ + +static gcc_type ccp_convert_func (compile_cplus_instance *instance, + struct type *type, int strip_artificial); + +/* See description in compile-cplus.h. */ + +char * +compile::decl_name (const char *natural) +{ + char *name = NULL; + + if (natural != NULL) + { + char *stripped; + + /* !!keiths: FIXME: Write a new parser func to do this? */ + name = cp_func_name (natural); + if (name == NULL) + { + stripped = cp_strip_template_parameters (natural); + if (stripped != NULL) + return stripped; + + name = xstrdup (natural); + } + else + { + stripped = cp_strip_template_parameters (name); + if (stripped != NULL) + { + xfree (name); + return stripped; + } + } + } + + return name; +} + +/* See description in compile-cplus.h. */ + +int +compile::is_varargs_p (const struct type *type) +{ + /* !!keiths: This doesn't always work, unfortunately. When we have a + pure virtual method, TYPE_PROTOTYPED == 0. + But this *may* be needed for several gdb.compile tests. Or at least + indicate other unresolved bugs in this file or elsewhere in gdb. */ + return TYPE_VARARGS (type) /*|| !TYPE_PROTOTYPED (type)*/; +} + +/* 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 +compile::get_method_access_flag (const struct type *type, int fni, int num) +{ + const struct fn_field *methods; + + gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT); + + /* If this type was not declared a class, everything is public. */ + if (!TYPE_DECLARED_CLASS (type)) + return GCC_CP_ACCESS_PUBLIC; + + /* Otherwise, read accessibility from the fn_field. */ + methods = TYPE_FN_FIELDLIST1 (type, fni); + if (TYPE_FN_FIELD_PUBLIC (methods, num)) + return GCC_CP_ACCESS_PUBLIC; + else 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; + + gdb_assert_not_reached ("unhandled method access specifier"); +} + +/* A useful debugging function to output the scope SCOPE + to stdout. */ + +static void __attribute__ ((used)) +debug_print_scope (const compile_scope &scope) +{ + int i; + + for (const auto &comp: scope) + { + std::string symbol = (comp.bsymbol.symbol != NULL + ? SYMBOL_NATURAL_NAME (comp.bsymbol.symbol) + : ""); + + printf ("\tname = %s, symbol = %s\n", comp.name.c_str (), + symbol.c_str ()); + } +} + +/* Utility function to convert CODE into a string. */ + +static const char * +type_code_to_string (enum type_code code) +{ + const char * const s[] = + {"BISTRING (deprecated)", "UNDEF (not used)", + "PTR", "ARRAY", "STRUCT", "UNION", "ENUM", + "FLAGS", "FUNC", "INT", "FLT", "VOID", + "SET", "RANGE", "STRING", "ERROR", "METHOD", + "METHODPTR", "MEMBERPTR", "REF", "CHAR", "BOOL", + "COMPLEX", "TYPEDEF", "NAMESPACE", "DECFLOAT", "MODULE", + "INTERNAL_FUNCTION", "XMETHOD"}; + + return s[code + 1]; +} + +/* See description in compile-cplus.h. */ + +compile_scope +compile::type_name_to_scope (const char *type_name, const struct block *block) +{ + compile_scope scope; + + if (type_name == NULL) + { + /* 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 (1) + { + /* 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, NULL); + + if (bsymbol.symbol != NULL) + { + scope_component comp = {s, bsymbol}; + + scope.push_back (comp); + + if (TYPE_CODE (SYMBOL_TYPE (bsymbol.symbol)) != 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")); + } + } + if (p[0] == '\0') + break; + } + + return scope; +} + +/* Compare two scope_components for equality. These are equal if the names + of the two components' are the same. */ + +bool +compile::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 +compile::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 +compile::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 +compile::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 (new_scope); + + if (must_push) + { + if (debug_compile_cplus_scopes) + printf_unfiltered ("entering new scope %p\n", new_scope); + + /* Push the global namespace. */ + 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 + (new_scope.begin (), new_scope.end () - 1, [this] (const auto &comp) + { + gdb_assert (TYPE_CODE (SYMBOL_TYPE (comp.bsymbol.symbol)) + == TYPE_CODE_NAMESPACE); + + const char *ns = (comp.name == CP_ANONYMOUS_NAMESPACE_STR ? NULL + : comp.name.c_str ()); + + this->push_namespace (ns); + }); + } + else + { + if (debug_compile_cplus_scopes) + { + printf_unfiltered + ("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) + printf_unfiltered ("leaving scope %p\n", current); + + /* Pop namespaces. Do not push the last scope_component -- that's + the type we are converting, not a namespace. */ + std::for_each + (current.begin (),current.end () - 1, [this] (const auto &comp) { + gdb_assert (TYPE_CODE (SYMBOL_TYPE (comp.bsymbol.symbol)) + == TYPE_CODE_NAMESPACE); + this->pop_binding_level (comp.name.c_str ()); + }); + + /* Pop global namespace. */ + pop_binding_level (""); + } + else + { + if (debug_compile_cplus_scopes) + printf_unfiltered ("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, SYMBOL_TYPE (comp.bsymbol.symbol)) + && (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 (SYMBOL_TYPE (comp.bsymbol.symbol)); + + /* 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! */ + type_map_t::iterator pos = m_type_map.find (type); + + gdb_assert (pos != m_type_map.end ()); + scope.m_nested_type = pos->second; + return scope; + } + } + else + { + if (TYPE_NAME (type) == NULL) + { + /* 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; + + comp.bsymbol + = lookup_symbol (TYPE_NAME (type), block (), VAR_DOMAIN, NULL); + + char *name = cp_func_name (TYPE_NAME (type)); + + comp.name = name; + xfree (name); + scope.push_back (comp); + } + } + + /* Ensure least one component in the scope. */ + gdb_assert (scope.size () > 0); + return scope; +} + +/* !!keiths: not RVALUE REFERENCES! */ + +gcc_type +compile::convert_reference_base (compile_cplus_instance *instance, + gcc_type base) +{ + return instance->build_reference_type (base, GCC_CP_REF_QUAL_LVALUE); +} + +/* Convert a reference type to its gcc representation. */ + +static gcc_type +ccp_convert_reference (compile_cplus_instance *instance, + struct type *type) +{ + gcc_type target = instance->convert_type (TYPE_TARGET_TYPE (type)); + + /* !!keiths: GDB does not currently do anything with rvalue references. + [Except set the type code to TYPE_CODE_ERROR! */ + return convert_reference_base (instance, target); +} + +/* See description in compile-cplus.h. */ + +gcc_type +compile::convert_pointer_base (compile_cplus_instance *instance, + gcc_type target) +{ + return instance->build_pointer_type (target); +} + +/* Convert a pointer type to its gcc representation. */ + +static gcc_type +ccp_convert_pointer (compile_cplus_instance *instance, + struct type *type) +{ + gcc_type target = instance->convert_type (TYPE_TARGET_TYPE (type)); + + return convert_pointer_base (instance, target); +} + +/* Convert an array type to its gcc representation. */ + +static gcc_type +ccp_convert_array (compile_cplus_instance *instance, struct type *type) +{ + struct type *range = TYPE_INDEX_TYPE (type); + gcc_type element_type = instance->convert_type (TYPE_TARGET_TYPE (type)); + + if (TYPE_LOW_BOUND_KIND (range) != PROP_CONST) + { + const char *s = _("array type with non-constant" + " lower bound is not supported"); + + return instance->error (s); + } + + if (TYPE_LOW_BOUND (range) != 0) + { + const char *s = _("cannot convert array type with " + "non-zero lower bound to C"); + + return instance->error (s); + } + + if (TYPE_HIGH_BOUND_KIND (range) == PROP_LOCEXPR + || TYPE_HIGH_BOUND_KIND (range) == PROP_LOCLIST) + { + gcc_type result; + char *upper_bound; + + if (TYPE_VECTOR (type)) + { + const char *s = _("variably-sized vector type is not supported"); + + return instance->error (s); + } + + upper_bound = c_get_range_decl_name (&TYPE_RANGE_DATA (range)->high); + result = instance->build_vla_array_type (element_type, upper_bound); + xfree (upper_bound); + return result; + } + else + { + LONGEST low_bound, high_bound, count; + + if (get_array_bounds (type, &low_bound, &high_bound) == 0) + count = -1; + else + { + gdb_assert (low_bound == 0); /* Ensured above. */ + count = high_bound + 1; + } + + if (TYPE_VECTOR (type)) + return instance->build_vector_type (element_type, count); + + return instance->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 +ccp_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), type); + + if (scope.nested_type () != GCC_TYPE_NONE) + return scope.nested_type (); + + char *name = NULL; + struct cleanup *cleanups = make_cleanup (free_current_contents, &name); + + if (TYPE_NAME (type) != NULL) + name = cp_func_name (TYPE_NAME (type)); + + /* Make sure the scope for this type has been pushed. */ + instance->enter_scope (scope); + + /* Convert the typedef's real type. */ + gcc_type typedef_type = instance->convert_type (check_typedef (type)); + + instance->build_decl ("typedef", name, + GCC_CP_SYMBOL_TYPEDEF | nested_access, + typedef_type, + 0, 0, + /* !!keiths: Wow. More of this! */ + NULL, 0); + + /* Completed this scope. */ + instance->leave_scope (); + do_cleanups (cleanups); + return typedef_type; +} + +/* Convert types defined in TYPE. */ + +static void +ccp_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_PUBLIC (type, i)) + accessibility = GCC_CP_ACCESS_PUBLIC; + else 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 + gdb_assert_not_reached ("unknown accessibility"); + 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_PUBLIC (type, i)) + accessibility = GCC_CP_ACCESS_PUBLIC; + else 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 + gdb_assert_not_reached ("unknown accessibility"); + 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 +ccp_convert_struct_or_union_members (compile_cplus_instance *instance, + struct type *type, gcc_type comp_type) +{ + int i; + + for (i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); ++i) + { + CORE_ADDR physaddr; + gcc_type field_type; + const char *field_name = TYPE_FIELD_NAME (type, i); + + if (TYPE_FIELD_IGNORE (type, i) + || TYPE_FIELD_ARTIFICIAL (type, i)) + continue; + + field_type + = instance->convert_type (TYPE_FIELD_TYPE (type, i)); + + if (field_is_static (&TYPE_FIELD (type, i))) + { + switch (TYPE_FIELD_LOC_KIND (type, i)) + { + case FIELD_LOC_KIND_PHYSADDR: + { + physaddr = TYPE_FIELD_STATIC_PHYSADDR (type, i); + + instance->build_decl ("field physaddr", field_name, + (GCC_CP_SYMBOL_VARIABLE + | get_field_access_flag (type, i)), + field_type, NULL, physaddr, + NULL, 0); + } + break; + + case FIELD_LOC_KIND_PHYSNAME: + { + const char *physname = TYPE_FIELD_STATIC_PHYSNAME (type, i); + struct block_symbol sym + = lookup_symbol (physname, instance->block (), VAR_DOMAIN, + NULL); + const char *filename; + unsigned int line; + + if (sym.symbol == NULL) + { + /* We didn't actually find the symbol. There's little + we can do but ignore this member. */ + continue; + } + filename = symbol_symtab (sym.symbol)->filename; + line = SYMBOL_LINE (sym.symbol); + physaddr = SYMBOL_VALUE_ADDRESS (sym.symbol); + instance->build_decl ("field physname", field_name, + (GCC_CP_SYMBOL_VARIABLE + | get_field_access_flag (type, i)), + field_type, NULL, 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) + /* FIXME: + | (field-is-mutable-p (type, i) + ? GCC_CP_FLAG_FIELD_MUTABLE + : GCC_CP_FLAG_FIELD_NOFLAG) + -lxo */ + ; + + if (bitsize == 0) + bitsize = 8 * TYPE_LENGTH (TYPE_FIELD_TYPE (type, i)); + + /* FIXME: We have to save the returned decl somewhere, so + that we can refer to it in expressions, in context for + lambdas, etc. */ + instance->build_field (field_name, field_type, field_flags, + bitsize, TYPE_FIELD_BITPOS (type, i)); + } + } +} + +/* Convert a method type to its gcc representation. */ + +static gcc_type +ccp_convert_method (compile_cplus_instance *instance, + struct type *parent_type, struct type *method_type) +{ + gcc_type result, func_type, class_type; + gcc_cp_qualifiers_flags quals; + gcc_cp_ref_qualifiers_flags rquals; + + /* Get the actual (proto)type of the method, as a function. */ + func_type = ccp_convert_func (instance, method_type, 1); + + class_type = instance->convert_type (parent_type); + quals = (enum gcc_cp_qualifiers) 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; + rquals = GCC_CP_REF_QUAL_NONE; + /* !!keiths FIXME */ + result = instance->build_method_type (class_type, func_type, quals, rquals); + return result; +} + +/* Convert a member or method pointer represented by TYPE. */ + +static gcc_type +ccp_convert_memberptr (compile_cplus_instance *instance, struct type *type) +{ + struct type *containing_class = TYPE_SELF_TYPE (type); + + if (containing_class == NULL) + 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->build_pointer_to_member_type (class_type, member_type); +} + +#define OPHASH1(A) ((uint32_t) A << 16) +#define OPHASH2(A,B) OPHASH1(A) | (uint32_t) B << 8 +#define OPHASH3(A,B,C) OPHASH2(A,B) | (uint32_t) C + +/* Compute a one, two, or three letter hash for the operator given by + OP. Returns the computed hash or zero for (some) conversion operators. */ + +static uint32_t +operator_hash (const char *op) +{ + const char *p = op; + uint32_t hash = 0; + int len = 0; + + while (p[0] != '\0' && (p[0] != '(' || p[1] == ')')) + { + ++len; + ++p; + } + + switch (len) + { + case 1: + hash = OPHASH1(op[0]); + break; + case 2: + hash = OPHASH2(op[0], op[1]); + break; + case 3: + /* This will also hash "operator int", but the plug-in does not + recognize OPHASH3('i', 'n', 't'), so we still end up in the code + to do a conversion operator in the caller. */ + hash = OPHASH3(op[0], op[1], op[2]); + break; + default: + break; + } + + return hash; +} + +/* Returns non-zero iff TYPE represents a binary method. */ + +static int +is_binary_method (const struct type *type) +{ + int i, len; + + for (i = 0, len = 0; i < TYPE_NFIELDS (type); ++i) + { + if (!TYPE_FIELD_ARTIFICIAL (type, i)) + ++len; + } + + return len > 1; +} + +/* See compile-cplus.h. */ + +const char * +compile::maybe_canonicalize_special_function + (const char *field_name, const struct fn_field *method_field, + const struct type *method_type, char **outname, bool *ignore) +{ + /* We assume that no method is to be ignored. */ + *ignore = false; + + /* We only consider ctors and dtors if METHOD_FIELD is non-NULL. */ + if (method_field != NULL) + { + if (method_field->is_constructor) + { +#if DEBUG_XTOR + printf ("*** CONSTRUCTOR %s: ", field_name); +#endif +#if CAUSES_ICE + switch (method_field->cdtor_type.ctor_kind) + { + case complete_object_ctor: +#if DEBUG_XTOR + printf ("complete_object_ctor (C1)\n"); +#endif + return "C1"; + + case base_object_ctor: +#if DEBUG_XTOR + printf ("base_object_ctor (C2)\n"); +#endif + return "C2"; + + case complete_object_allocating_ctor: + *ignore = true; +#if DEBUG_XTOR + printf ("complete_object_allocating_ctor -- ignored\n"); +#endif + return field_name; /* C? */ + + case unified_ctor: +#if DEBUG_XTOR + printf ("unified_ctor (C4) -- ignored\n"); +#endif + *ignore = true; + return field_name; /* C4 */ + + case object_ctor_group: +#if DEBUG_XTOR + printf ("object_ctor_group -- ignored\n"); +#endif + *ignore = true; + return field_name; /* C? */ + + case not_ctor: +#if DEBUG_XTOR + printf ("unknown_ctr -- ignored\n"); +#endif + *ignore = true; + return field_name; /* unknown */ + + default: + gdb_assert_not_reached ("unknown constructor kind"); + } +#else +#if DEBUG_XTOR + printf ("DISABLED -- ignored\n"); +#endif + *ignore = true; +#endif /* CAUSES_ICE */ + } + else if (method_field->is_destructor) + { +#if DEBUG_XTOR + printf ("*** DESTRUCTOR %s: ", field_name); +#endif + switch (method_field->cdtor_type.dtor_kind) + { + case deleting_dtor: +#if DEBUG_XTOR + printf ("deleting_dtor (D0)\n"); +#endif + return "D0"; + + case complete_object_dtor: +#if DEBUG_XTOR + printf ("complete_object_dtor (D1)\n"); +#endif + return "D1"; + + case base_object_dtor: +#if DEBUG_XTOR + printf ("base_object_dtor (D2)\n"); +#endif + return "D2"; + + case unified_dtor: +#if DEBUG_XTOR + printf ("unified_dtor (D4) -- ignored\n"); +#endif + *ignore = true; + return field_name; /* D4 */ + + case object_dtor_group: +#if DEBUG_XTOR + printf ("object_dtor_group (D?) -- ignored\n"); +#endif + *ignore = true; + return field_name; /* D? */ + + case not_dtor: +#if DEBUG_XTOR + printf ("not_dtor -- ignored\n"); +#endif + *ignore = true; + return field_name; /* unknown */ + + default: + gdb_assert_not_reached ("unknown destructor kind"); + } + } + } + + if (!is_operator_name (field_name)) + return field_name; + + /* Skip over "operator". */ + field_name += sizeof ("operator") - 1; + + if (strncmp (field_name, "new", sizeof ("new") - 1) == 0) + { + field_name += 3; + if (*field_name == '\0') + return "nw"; + else if (*field_name == '[') + return "na"; + } + else if (strncmp (field_name, "delete", sizeof ("delete") - 1) == 0) + { + if (*field_name == '\0') + return "dl"; + else if (*field_name == '[') + return "da"; + } + else if (field_name[0] == '\"' && field_name[1] == '\"') + { + const char *end; + size_t len; + + /* Skip over \"\" -- the plug-in doesn't want it. */ + field_name += 2; + + /* Skip any whitespace that may have been introduced during + canonicalization. */ + field_name = skip_spaces_const (field_name); + + /* Find the opening '(', if any. */ + end = strchr (field_name, '('); + if (end == NULL) + end = field_name + strlen (field_name); + + /* Size of buffer: 'li', 'i', sizeof operator name, '\0' */ + len = 2 + end - field_name + 1; + *outname = (char *) xmalloc (len); + strcpy (*outname, "li"); + strncat (*outname, field_name, end - field_name); + (*outname)[len-1] = '\0'; + return "li"; + } + + switch (operator_hash (field_name)) + { + case OPHASH1 ('+'): + if (is_binary_method (method_type)) + return "pl"; + else + return "ps"; + break; + + case OPHASH1 ('-'): + if (is_binary_method (method_type)) + return "mi"; + else + return "ng"; + break; + case OPHASH1 ('&'): + if (is_binary_method (method_type)) + return "an"; + else + return "ad"; + break; + + case OPHASH1 ('*'): + if (is_binary_method (method_type)) + return "ml"; + else + return "de"; + break; + + case OPHASH1 ('~'): + return "co"; + case OPHASH1 ('/'): + return "dv"; + case OPHASH1 ('%'): + return "rm"; + case OPHASH1 ('|'): + return "or"; + case OPHASH1 ('^'): + return "eo"; + case OPHASH1 ('='): + return "aS"; + case OPHASH2 ('+', '='): + return "pL"; + case OPHASH2 ('-', '='): + return "mI"; + case OPHASH2 ('*', '='): + return "mL"; + case OPHASH2 ('/', '='): + return "dV"; + case OPHASH2 ('%', '='): + return "rM"; + case OPHASH2 ('&', '='): + return "aN"; + case OPHASH2 ('|', '='): + return "oR"; + case OPHASH2 ('^', '='): + return "eO"; + case OPHASH2 ('<', '<'): + return "ls"; + case OPHASH2 ('>', '>'): + return "rs"; + case OPHASH3 ('<', '<', '='): + return "lS"; + case OPHASH3 ('>', '>', '='): + return "rS"; + case OPHASH2 ('=', '='): + return "eq"; + case OPHASH2 ('!', '='): + return "ne"; + case OPHASH1 ('<'): + return "lt"; + case OPHASH1 ('>'): + return "gt"; + case OPHASH2 ('<', '='): + return "le"; + case OPHASH2 ('>', '='): + return "ge"; + case OPHASH1 ('!'): + return "nt"; + case OPHASH2 ('&', '&'): + return "aa"; + case OPHASH2 ('|', '|'): + return "oo"; + case OPHASH2 ('+', '+'): + return "pp"; + case OPHASH2 ('-', '-'): + return "mm"; + case OPHASH1 (','): + return "cm"; + case OPHASH3 ('-', '>', '*'): + return "pm"; + case OPHASH2 ('-', '>'): + return "pt"; + case OPHASH2 ('(', ')'): + return "cl"; + case OPHASH2 ('[', ']'): + return "ix"; + case OPHASH1 ('?'): + return "qu"; + + default: + /* Conversion operators: Full name is not needed. */ + return "cv"; + } +} + +/* Convert all methods defined in TYPE, which should be a class/struct/union + with gcc_type CLASS_TYPE. */ + +static void +ccp_convert_struct_or_union_methods (compile_cplus_instance *instance, + struct type *type, gcc_type class_type) +{ + int i; + + /* First things first: If this class had any template methods, emit them so + that the compiler knows about them. */ + instance->emit_function_template_decls (); + + + /* Now define the actual methods/template specializations. */ + for (i = 0; i < TYPE_NFN_FIELDS (type); ++i) + { + int j; + struct fn_field *methods = TYPE_FN_FIELDLIST1 (type, i); + char *overloaded_name + = decl_name (TYPE_FN_FIELDLIST_NAME (type, i)); + struct cleanup *outer = make_cleanup (xfree, overloaded_name); + + /* Loop through the fieldlist, adding decls to the compiler's + representation of the class. */ + for (j = 0; j < TYPE_FN_FIELDLIST_LENGTH (type, i); ++j) + { + CORE_ADDR address; + gcc_type method_type; + struct block_symbol sym; + const char *filename; + unsigned int line; + const char *kind; + gcc_cp_symbol_kind_flags sym_kind = GCC_CP_SYMBOL_FUNCTION; + const char *name; + char *special_name; + struct cleanup *back_to; + bool ignore; + struct template_symbol *tsym = NULL; + + /* Skip artificial methods. */ + if (TYPE_FN_FIELD_ARTIFICIAL (methods, j)) + continue; + + special_name = NULL; + name = maybe_canonicalize_special_function (overloaded_name, + &methods[j], + methods[j].type, + &special_name, + &ignore); + if (ignore) + continue; + + back_to = make_cleanup (null_cleanup, NULL); + + if (special_name != NULL) + { + make_cleanup (xfree, special_name); + name = special_name; + } + + if (name != overloaded_name) + { + sym_kind |= GCC_CP_FLAG_SPECIAL_FUNCTION; + } + sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (methods, j), + instance->block (), VAR_DOMAIN, NULL); + + if (sym.symbol == NULL) + { + 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 + = ccp_convert_method (instance, type, + TYPE_FN_FIELD_TYPE (methods, j)); + + instance->build_decl ("pure virtual method", name, + (sym_kind + | get_method_access_flag (type, i, j) + | GCC_CP_FLAG_VIRTUAL_FUNCTION + | GCC_CP_FLAG_PURE_VIRTUAL_FUNCTION), + method_type, NULL, 0, + NULL /* FIXME: filename */, + 0 /* FIXME: line number */); + do_cleanups (back_to); + 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)); + do_cleanups (back_to); + continue; + } + + filename = symbol_symtab (sym.symbol)->filename; + line = SYMBOL_LINE (sym.symbol); + address = BLOCK_START (SYMBOL_BLOCK_VALUE (sym.symbol)); + + /* Short-circuit for method templates. */ + if (SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION (sym.symbol)) + { + struct template_symbol *tsymbol + = (struct template_symbol *) sym.symbol; + + instance->build_function_template_specialization (tsymbol, + address, + filename, line); + do_cleanups (back_to); + continue; + } + + if (TYPE_FN_FIELD_STATIC_P (methods, j)) + { + kind = "static method"; + method_type = ccp_convert_func (instance, + TYPE_FN_FIELD_TYPE (methods, j), + 1); + } + else + { + kind = "method"; + method_type + = ccp_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; + + /* FIXME: for cdtors, we must call build_decl with a zero + address, if we haven't created the base declaration + yet, and then define_cdtor_clone with the address of + each clone. When we leave the address out, GCC uses + the address oracle. -lxo */ + if ((sym_kind & GCC_CP_FLAG_SPECIAL_FUNCTION) + && (name[0] == 'C' || name[0] == 'D')) + { + address = 0; + /* FIXME: We should declare only one cdtor for each + clone set with "C" or "D" as the name, with address + zero, then define each address with + define_cdtor_clone. Until this is implemented, + declare only one of these, and let the address oracle + take care of the addresses. -lxo */ + if (name[1] != '2' && name[1] != '4') + { + do_cleanups (back_to); + continue; + } + } + + instance->build_decl (kind, name, + sym_kind | get_method_access_flag (type, i, j), + method_type, NULL, address, filename, line); + do_cleanups (back_to); + } + + do_cleanups (outer); + } +} + +/* 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 +ccp_convert_struct_or_union (compile_cplus_instance *instance, + struct type *type, + enum gcc_cp_symbol_kind nested_access) +{ + const char *filename = NULL; /* !!keiths: FIXME */ + unsigned short line = 0; + char *name = NULL; + struct cleanup *back_to = make_cleanup (free_current_contents, &name); + + /* Get the decl name of this type. */ + if (TYPE_NAME (type) != NULL) + name = decl_name (TYPE_NAME (type)); + + /* First things first: If this type has any templates in it, make sure + that we collect default arguments and get those types defined BEFORE + this type is defined. */ + scan_type_for_function_templates (instance, type); + + /* If this is a new template class, make sure the generic has been seen + and defined. */ + instance->maybe_define_new_class_template (type, name); + instance->emit_class_template_decls (); + + /* Create a new scope for TYPE. */ + compile_scope scope = instance->new_scope (TYPE_NAME (type), 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 (scope); + + /* First we create the resulting type and enter it into our hash + table. This lets recursive types work. */ + + gcc_decl resuld; /* FIXME: yeah, it's a terrible pun. Please make + it go once we separate declaration from + definition (see below). -lxo */ + if (TYPE_N_TEMPLATE_ARGUMENTS (type)) + { + resuld = instance->build_class_template_specialization (type, + filename, line); + } + else if (TYPE_CODE (type) == TYPE_CODE_STRUCT) + { + const char *what = TYPE_DECLARED_CLASS (type) ? "struct" : "class"; + + resuld = instance->build_decl (what, name, + GCC_CP_SYMBOL_CLASS | nested_access + | (TYPE_DECLARED_CLASS (type) + ? GCC_CP_FLAG_CLASS_NOFLAG + : GCC_CP_FLAG_CLASS_IS_STRUCT), + 0, NULL, 0, filename, line); + } + else + { + gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION); + resuld = instance->build_decl ("union", name, + GCC_CP_SYMBOL_UNION | nested_access, + 0, NULL, 0, filename, line); + } + + /* FIXME: we should be able to pop the scope at this point, rather + than at the end, and we ought to delay the rest of this function + to the point in which we need the class or union to be a complete + type, otherwise some well-formed C++ types cannot be represented. + -lxo */ + + gcc_type result; + if (TYPE_CODE (type) == TYPE_CODE_STRUCT) + { + struct gcc_vbase_array bases; + int num_baseclasses = TYPE_N_BASECLASSES (type); + + memset (&bases, 0, sizeof (bases)); + + if (num_baseclasses > 0) + { + bases.elements = XNEWVEC (gcc_type, num_baseclasses); + bases.flags = XNEWVEC (enum gcc_cp_symbol_kind, num_baseclasses); + 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->start_class_type (name, resuld, &bases, + filename, line); + xfree (bases.flags); + xfree (bases.elements); + } + else + { + gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION); + result + = instance->start_class_type (name, resuld, NULL, filename, line); + } + + instance->insert_type (type, result); + + /* Add definitions. */ + ccp_convert_type_defns (instance, type); + + /* Add methods. */ + ccp_convert_struct_or_union_methods (instance, type, result); + + /* Add members. */ + ccp_convert_struct_or_union_members (instance, type, result); + + /* All finished. */ + instance->finish_class_type (name, TYPE_LENGTH (type)); + + /* Pop all scopes. */ + instance->leave_scope (); + do_cleanups (back_to); + 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 +ccp_convert_enum (compile_cplus_instance *instance, struct type *type, + enum gcc_cp_symbol_kind nested_access) +{ + int i; + gcc_type int_type; + const char *filename = NULL; + unsigned short line = 0; + /* !!keiths: This does not appear to work. GCC complains about + being unable to convert enum values from '(MyEnum)0' to 'int'. */ + int scoped_enum_p = /*TYPE_DECLARED_CLASS (type) ? TRUE :*/ FALSE; + + /* Create a new scope for this type. */ + compile_scope scope = instance->new_scope (TYPE_NAME (type), 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 (); + } + + char *name = NULL; + struct cleanup *cleanups = make_cleanup (free_current_contents, &name); + + if (TYPE_NAME (type) != NULL) + name = cp_func_name (TYPE_NAME (type)); + + /* Push all scopes. */ + instance->enter_scope (scope); + + int_type = instance->get_int_type (TYPE_UNSIGNED (type), + TYPE_LENGTH (type), NULL); + gcc_type result + = instance->start_enum_type (name, int_type, + GCC_CP_SYMBOL_ENUM | nested_access + | (scoped_enum_p + ? GCC_CP_FLAG_ENUM_SCOPED + : GCC_CP_FLAG_ENUM_NOFLAG), + filename, line); + for (i = 0; i < TYPE_NFIELDS (type); ++i) + { + char *fname = cp_func_name (TYPE_FIELD_NAME (type, i)); + + if (TYPE_FIELD_LOC_KIND (type, i) != FIELD_LOC_KIND_ENUMVAL + || fname == NULL) + { + xfree (fname); + continue; + } + + instance->build_enum_constant (result, fname, + TYPE_FIELD_ENUMVAL (type, i)); + xfree (fname); + } + + instance->finish_enum_type (result); + + /* Pop all scopes. */ + instance->leave_scope (); + do_cleanups (cleanups); + return result; +} + +/* Convert a function type to its gcc representation. This function does + not deal with function templates. */ + +static gcc_type +ccp_convert_func (compile_cplus_instance *instance, struct type *type, + int strip_artificial) +{ + int i, artificials; + gcc_type result, return_type; + struct gcc_type_array array; + int is_varargs = is_varargs_p (type); + + /* This approach means we can't make self-referential function + types. Those are impossible in C, though. */ + return_type = instance->convert_type (TYPE_TARGET_TYPE (type)); + + array.n_elements = TYPE_NFIELDS (type); + array.elements = XNEWVEC (gcc_type, TYPE_NFIELDS (type)); + artificials = 0; + for (i = 0; i < TYPE_NFIELDS (type); ++i) + { + if (strip_artificial && TYPE_FIELD_ARTIFICIAL (type, i)) + { + --array.n_elements; + ++artificials; + } + else + { + array.elements[i - artificials] + = instance->convert_type (TYPE_FIELD_TYPE (type, i)); + } + } + + /* FIXME: add default args, exception specs and, once support is + added, attributes. -lxo */ + + /* We omit setting the argument types to `void' to be a little flexible + with some minsyms like printf (compile-cplus.exp has examples). */ + result = instance->build_function_type (return_type, &array, is_varargs); + xfree (array.elements); + + return result; +} + +/* Convert an integer type to its gcc representation. */ + +static gcc_type +ccp_convert_int (compile_cplus_instance *instance, struct type *type) +{ + if (TYPE_NOSIGN (type)) + { + gdb_assert (TYPE_LENGTH (type) == 1); + return instance->get_char_type (); + } + + return instance->get_int_type (TYPE_UNSIGNED (type), TYPE_LENGTH (type), + TYPE_NAME (type)); +} + +/* Convert a floating-point type to its gcc representation. */ + +static gcc_type +ccp_convert_float (compile_cplus_instance *instance, struct type *type) +{ + return instance->get_float_type (TYPE_LENGTH (type), TYPE_NAME (type)); +} + +/* Convert the 'void' type to its gcc representation. */ + +static gcc_type +ccp_convert_void (compile_cplus_instance *instance, struct type *type) +{ + return instance->get_void_type (); +} + +/* Convert a boolean type to its gcc representation. */ + +static gcc_type +ccp_convert_bool (compile_cplus_instance *instance, struct type *type) +{ + return instance->get_bool_type (); +} + +/* See description in compile-cplus.h. */ + +gcc_type +compile::convert_qualified_base (compile_cplus_instance *instance, + gcc_type base, + gcc_cp_qualifiers_flags quals) +{ + gcc_type result = base; + + if (quals != 0) + result = instance->build_qualified_type (base, quals); + + return result; +} + +/* Convert a qualified type to its gcc representation. */ + +static gcc_type +ccp_convert_qualified (compile_cplus_instance *instance, + struct type *type) +{ + struct type *unqual = make_unqualified_type (type); + gcc_type unqual_converted; + gcc_cp_qualifiers_flags quals = (enum gcc_cp_qualifiers) 0; + gcc_type result; + + 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 convert_qualified_base (instance, unqual_converted, quals); +} + +/* Convert a complex type to its gcc representation. */ + +static gcc_type +ccp_convert_complex (compile_cplus_instance *instance, + struct type *type) +{ + gcc_type base = instance->convert_type (TYPE_TARGET_TYPE (type)); + + return instance->build_complex_type (base); +} + +/* Convert a namespace of TYPE. */ + +static gcc_type +ccp_convert_namespace (compile_cplus_instance *instance, + struct type *type) +{ + compile_scope scope = instance->new_scope (TYPE_NAME (type), type); + + + char *name = NULL; - struct cleanup *cleanups = make_cleanup (null_cleanup, NULL); ++ struct cleanup *cleanups = make_cleanup (free_current_contents, &name); ++ + if (TYPE_NAME (type) != NULL) - { - name = cp_func_name (TYPE_NAME (type)); - make_cleanup (xfree, name); - } ++ name = cp_func_name (TYPE_NAME (type)); + else - name = ""; ++ name = xstrdup (""); // !!keiths: anonymous namespace?! + + /* Push scope. */ + instance->enter_scope (scope); + + /* Convert this namespace. */ + instance->push_namespace (name); + instance->pop_binding_level (name); + + /* Pop scope. */ + instance->leave_scope (); + do_cleanups (cleanups); + + /* Namespaces are non-cacheable types. */ + return DONT_CACHE_TYPE; +} + +/* 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) +{ + /* Reference types seem to always have a const qualifier, but we + don't want that to be propagated to the GCC type, because GCC + doesn't like the reference types themselves to be qualified. */ + if (TYPE_CODE (type) == TYPE_CODE_REF) + return ccp_convert_reference (instance, type); + + /* If we are converting a qualified type, first convert the + unqualified type and then apply the qualifiers. */ + if ((TYPE_INSTANCE_FLAGS (type) & (TYPE_INSTANCE_FLAG_CONST + | TYPE_INSTANCE_FLAG_VOLATILE + | TYPE_INSTANCE_FLAG_RESTRICT)) != 0) + return ccp_convert_qualified (instance, type); + + switch (TYPE_CODE (type)) + { +#if 0 + case TYPE_CODE_REF: + return ccp_convert_reference (instance, type); +#endif + + case TYPE_CODE_PTR: + return ccp_convert_pointer (instance, type); + + case TYPE_CODE_ARRAY: + return ccp_convert_array (instance, type); + + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + return ccp_convert_struct_or_union (instance, type, nested_access); + + case TYPE_CODE_ENUM: + return ccp_convert_enum (instance, type, nested_access); + + case TYPE_CODE_FUNC: + return ccp_convert_func (instance, type, 0); + + case TYPE_CODE_METHOD: + return ccp_convert_method (instance, TYPE_SELF_TYPE (type), type); + + case TYPE_CODE_MEMBERPTR: + case TYPE_CODE_METHODPTR: + return ccp_convert_memberptr (instance, type); + break; + + case TYPE_CODE_INT: + return ccp_convert_int (instance, type); + + case TYPE_CODE_FLT: + return ccp_convert_float (instance, type); + + case TYPE_CODE_VOID: + return ccp_convert_void (instance, type); + + case TYPE_CODE_BOOL: + return ccp_convert_bool (instance, type); + + case TYPE_CODE_COMPLEX: + return ccp_convert_complex (instance, type); + + case TYPE_CODE_NAMESPACE: + return ccp_convert_namespace (instance, type); + + case TYPE_CODE_TYPEDEF: + return ccp_convert_typedef (instance, type, nested_access); + } + + { + char *s = xstrprintf (_("unhandled TYPE_CODE_%s"), + type_code_to_string (TYPE_CODE (type))); + + return instance->error (s); + xfree (s); + } +} + +gcc_type +compile_cplus_instance::convert_type (struct type *type, + enum gcc_cp_symbol_kind nested_access) +{ + type_map_t::iterator pos = m_type_map.find (type); + if (pos != m_type_map.end ()) + return pos->second; + + gcc_type result = convert_type_cplus_basic (this, type, nested_access); + if (result != DONT_CACHE_TYPE) + insert_type (type, result); + return result; +} + + + +/* Default compile flags for C++. */ + +const char *compile_cplus_instance::m_default_cflags = "-std=gnu++11"; + +/* See compile-cplus.h. */ + +compile_cplus_instance::compile_cplus_instance (struct gcc_cp_context *gcc_fe) + : compile_instance (&gcc_fe->base, m_default_cflags), + m_context (gcc_fe), + m_function_template_defns (new function_template_defn_map_t ()), + m_class_template_defns (new class_template_defn_map_t ()) +{ + gcc_fe->cp_ops->set_callbacks (gcc_fe, gcc_cplus_convert_symbol, + gcc_cplus_symbol_address, + gcc_cplus_enter_scope, + gcc_cplus_leave_scope, + this); +} + +/* Plug-in forwards. */ + +/* A result printer for plug-in calls that return a boolean result. */ + +static void +ccp_output_result (int result) +{ + printf_unfiltered ("%s\n", result ? "true" : "false"); +} + +/* A result printer for plug-in calls that return a gcc_type or + gcc_decl. */ + +static void +ccp_output_result (gcc_type result) +{ + printf_unfiltered ("%lld\n", result); +} + +#define STR(x) #x +#define STRINGIFY(x) STR(x) + +#define DECLARE_FORWARD(OP,...) \ + auto forward = [&] (const char *fmt, ...) \ + { \ + if (debug_compile_cplus_types) \ + { \ + std::string format (STRINGIFY (OP)); \ + \ + format += " "; \ + format += fmt; \ + format += ": "; \ + \ + va_list args; \ + \ + va_start (args, fmt); \ + vprintf_unfiltered (format.c_str (), args); \ + va_end (args); \ + } \ + \ + auto result = m_context->cp_ops->OP (m_context, ##__VA_ARGS__); \ + \ + if (debug_compile_cplus_types) \ + ccp_output_result (result); \ + \ + return result; \ + }; + +/* See description in gcc-cp-fe.def. */ + +bool +compile_cplus_instance::build_constant (gcc_type type, const char *name, + unsigned long value, + const char *filename, + unsigned int line_number) +{ + DECLARE_FORWARD (build_constant, type, name, value, filename, line_number); + + return forward ("\"%s\"", name); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_decl +compile_cplus_instance::build_function_template_specialization + (struct template_symbol *concrete, gcc_address address, + const char *filename, unsigned int line_number) +{ + function_template_defn *defn + = find_function_template_defn (concrete); + + /* A generic should already have been defined at this point. */ + gdb_assert (defn != NULL); + + struct gcc_cp_template_args targs; + + targs.n_elements = concrete->template_arguments->n_arguments; + targs.kinds = XNEWVEC (char, targs.n_elements); + + struct cleanup *back_to = make_cleanup (xfree, targs.kinds); + + targs.elements = XNEWVEC (gcc_cp_template_arg, targs.n_elements); + make_cleanup (xfree, targs.elements); + enumerate_template_arguments (&targs, defn, concrete->template_arguments); + + DECLARE_FORWARD (build_function_template_specialization, defn->decl (), + &targs, address, filename, line_number); + + gcc_decl result = forward ("%s", SYMBOL_NATURAL_NAME (&concrete->base)); + do_cleanups (back_to); + return result; +} + +/* See description in gcc-cp-fe.def. */ + +gcc_decl +compile_cplus_instance::build_class_template_specialization + (struct type *concrete, const char *filename, unsigned int line_number) +{ + class_template_defn *defn + = find_class_template_defn (concrete); + + /* A generic should have already been defined at this point. */ + gdb_assert (defn != NULL); + + struct gcc_cp_template_args targs; + + targs.n_elements = TYPE_N_TEMPLATE_ARGUMENTS (concrete); + targs.kinds = XNEWVEC (char, targs.n_elements); + + struct cleanup *back_to = make_cleanup (xfree, targs.kinds); + + targs.elements = XNEWVEC (gcc_cp_template_arg, targs.n_elements); + make_cleanup (xfree, targs.elements); + enumerate_template_arguments (&targs, defn, + TYPE_TEMPLATE_ARGUMENT_INFO (concrete)); + + DECLARE_FORWARD (build_class_template_specialization, defn->decl (), &targs, + filename, line_number); + + gcc_decl result + = forward ("%s for template decl %lld\n", TYPE_NAME (concrete), + defn->decl ()); + do_cleanups (back_to); + return result; +} + +/* See description in gcc-cp-fe.def. */ + +gcc_decl +compile_cplus_instance::build_decl (const char *decl_type, + 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) +{ + DECLARE_FORWARD (build_decl, name, sym_kind, sym_type, + substitution_name, address, filename, line_number); + + return forward ("%s %s %d %s", decl_type, name, (int) sym_kind, + substitution_name); +} + +/* See description in gcc-cp-fe.def. */ + +bool +compile_cplus_instance::push_namespace (const char *name) +{ + DECLARE_FORWARD (push_namespace, name); + + return forward ("\"%s\"", name); +} + +/* See description in gcc-cp-fe.def. */ + +bool +compile_cplus_instance::pop_binding_level (const char *opt_name) +{ + DECLARE_FORWARD (pop_binding_level); + + return forward ("\"%s\"", opt_name); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_type +compile_cplus_instance::error (const char *message) +{ + DECLARE_FORWARD (error, message); + + return forward ("%s", message); +} + +/* See description in gcc-cp-fe.def. */ + + +gcc_type +compile_cplus_instance::build_reference_type (gcc_type base_type, + enum gcc_cp_ref_qualifiers rquals) +{ + DECLARE_FORWARD (build_reference_type, base_type, rquals); + + return forward (""); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_type +compile_cplus_instance::build_pointer_type (gcc_type base_type) +{ + DECLARE_FORWARD (build_pointer_type, base_type); + + return forward (""); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_type +compile_cplus_instance::build_vla_array_type (gcc_type element_type, + const char *upper_bound_name) +{ + DECLARE_FORWARD (build_vla_array_type, element_type, upper_bound_name); + + return forward (""); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_type +compile_cplus_instance::build_vector_type (gcc_type element_type, + int num_elements) +{ + DECLARE_FORWARD (build_vector_type, element_type, num_elements); + + return forward (""); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_type +compile_cplus_instance::build_array_type (gcc_type element_type, + int num_elements) +{ + DECLARE_FORWARD (build_array_type, element_type, num_elements); + + return forward (""); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_decl +compile_cplus_instance::build_field (const char *field_name, + gcc_type field_type, + enum gcc_cp_symbol_kind field_flags, + unsigned long bitsize, + unsigned long bitpos) +{ + DECLARE_FORWARD (build_field, field_name, field_type, field_flags, + bitsize, bitpos); + + return forward ("%s %lld", field_name, field_type); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_type +compile_cplus_instance::build_method_type (gcc_type class_type, + gcc_type func_type, + enum gcc_cp_qualifiers quals, + enum gcc_cp_ref_qualifiers rquals) +{ + DECLARE_FORWARD (build_method_type, class_type, func_type, quals, rquals); + + return forward (""); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_type +compile_cplus_instance::start_class_type + (const char *name, gcc_decl typedecl, + const struct gcc_vbase_array *base_classes, + const char *filename, unsigned int line_number) +{ + DECLARE_FORWARD (start_class_type, typedecl, base_classes, + filename, line_number); + + return forward ("%s", name); +} + +/* See description in gcc-cp-fe.def. */ + +bool +compile_cplus_instance::finish_class_type (const char *name, + unsigned long size_in_bytes) +{ + DECLARE_FORWARD (finish_class_type, size_in_bytes); + + return forward ("%s (%ld)", name, size_in_bytes); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_type +compile_cplus_instance::get_int_type (bool is_unsigned, + unsigned long size_in_bytes, + const char *builtin_name) +{ + DECLARE_FORWARD (get_int_type, is_unsigned, size_in_bytes, builtin_name); + + return forward ("%d %ld %s", is_unsigned, size_in_bytes, builtin_name); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_type +compile_cplus_instance::start_enum_type (const char *name, + gcc_type underlying_int_type, + enum gcc_cp_symbol_kind flags, + const char *filename, + unsigned int line_number) +{ + DECLARE_FORWARD (start_enum_type, name, underlying_int_type, + flags, filename, line_number); + + return forward ("%s", name); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_decl +compile_cplus_instance::build_enum_constant (gcc_type enum_type, + const char *name, + unsigned long value) +{ + DECLARE_FORWARD (build_enum_constant, enum_type, name, value); + + return forward ("%s = %ld", name, value); +} + +/* See description in gcc-cp-fe.def. */ + +bool +compile_cplus_instance::finish_enum_type (gcc_type enum_type) +{ + DECLARE_FORWARD (finish_enum_type, enum_type); + + return forward (""); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_type +compile_cplus_instance::build_function_type + (gcc_type return_type, const struct gcc_type_array *argument_types, + bool is_varargs) +{ + DECLARE_FORWARD (build_function_type, return_type, argument_types, + is_varargs); + + return forward ("%lld %d", return_type, is_varargs); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_type +compile_cplus_instance::get_char_type () +{ + DECLARE_FORWARD (get_char_type); + + return forward (""); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_type +compile_cplus_instance::get_float_type (unsigned long size_in_bytes, + const char *builtin_name) +{ + DECLARE_FORWARD (get_float_type, size_in_bytes, builtin_name); + + return forward ("%ld %s", size_in_bytes, builtin_name); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_type +compile_cplus_instance::get_void_type () +{ + DECLARE_FORWARD (get_void_type); + + return forward (""); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_type +compile_cplus_instance::get_bool_type () +{ + DECLARE_FORWARD (get_bool_type); + + return forward (""); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_type +compile_cplus_instance::build_qualified_type (gcc_type unqualified_type, + enum gcc_cp_qualifiers qualifiers) +{ + DECLARE_FORWARD (build_qualified_type, unqualified_type, qualifiers); + + return forward (""); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_type +compile_cplus_instance::build_complex_type (gcc_type element_type) +{ + DECLARE_FORWARD (build_complex_type, element_type); + + return forward ("%lld", element_type); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_expr +compile_cplus_instance::build_literal_expr (gcc_type type, unsigned long value) +{ + DECLARE_FORWARD (build_literal_expr, type, value); + + return forward ("%lld %ld", type, value); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_type +compile_cplus_instance::build_type_template_parameter (const char *id, + bool pack_p, + gcc_type default_type, + const char *filename, + unsigned int line_number) +{ + DECLARE_FORWARD (build_type_template_parameter, id, pack_p, + default_type, filename, line_number); + + return forward ("%s %d %lld %s %d", id, pack_p, default_type, + filename, line_number); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_decl +compile_cplus_instance::build_value_template_parameter + (gcc_type type, const char *id, gcc_expr default_value, + const char *filename, unsigned int line_number) +{ + DECLARE_FORWARD (build_value_template_parameter, type, id, + default_value, filename, line_number); + + return forward ("%lld %s %lld %s %d", type, id, default_value, + filename, line_number); +} + +/* See description in gcc-cp-fe.def. */ + +bool +compile_cplus_instance::start_template_decl (const char *generic) +{ + DECLARE_FORWARD (start_template_decl); + + return forward ("for generic %s\n", generic); +} + +/* See description in gcc-cp-fe.def. */ + +gcc_type +compile_cplus_instance::build_pointer_to_member_type (gcc_type class_type, + gcc_type member_type) +{ + DECLARE_FORWARD (build_pointer_to_member_type, class_type, member_type); + + return forward ("%lld %lld", class_type, member_type); +} + +#undef DECLARE_FORWARD + +void _initialize_compile_cplus_types (void); + +void +_initialize_compile_cplus_types (void) +{ + 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."), + NULL, + NULL, + &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."), + NULL, + NULL, + &setdebuglist, + &showdebuglist); +} diff --cc gdb/dbxread.c index 712f0cdc06a,daa3ce9f813..ce0eeb06808 --- a/gdb/dbxread.c +++ b/gdb/dbxread.c @@@ -2503,9 -2501,9 +2505,9 @@@ cp_set_block_scope (const struct symbo is used in end_symtab. */ void - process_one_symbol (int type, int desc, CORE_ADDR valu, char *name, + process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name, const struct section_offsets *section_offsets, - struct objfile *objfile) + struct objfile *objfile, enum language language) { struct gdbarch *gdbarch = get_objfile_arch (objfile); struct context_stack *newobj; diff --cc gdb/dwarf2read.c index cbe33b58a7f,b58d0fc16e6..a9d794c8624 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@@ -8995,68 -9009,6 +9080,69 @@@ read_imported_decl (struct die_info *di new_symbol (die, type, cu); return 1; } + else + { + const char *linkage_name = dw2_linkage_name (die, cu); + + /* Handle imported (aka "aliased") constructors and + destructors. */ + if (linkage_name != NULL) + { + enum ctor_kinds ctor_kind; + enum dtor_kinds dtor_kind = not_dtor; + + ctor_kind = is_constructor_name (linkage_name); + if (ctor_kind == not_ctor) + dtor_kind = is_destructor_name (linkage_name); + + /* GCC outputs imported_declaration for C1 constructors + and D1 destructors which alias to the C4/D4/unified + ctor/dtor listed in the parent class's DIE tree. + Deal with those here. */ + if (ctor_kind != not_ctor || dtor_kind != not_dtor) + { + struct die_info *imported_die, *spec_die, *parent_die; + struct die_info *type_die; + struct dwarf2_cu *imported_cu, *spec_cu, *parent_cu; + struct dwarf2_cu *type_cu; + struct type *parent_type; + + /* If there is a specification DIE, use that as the + parent DIE. */ + imported_cu = cu; + imported_die = follow_die_ref (die, attr, &imported_cu); + if (imported_die == NULL) + return 0; + + spec_cu = imported_cu; + spec_die = die_specification (imported_die, &spec_cu); + if (spec_die != NULL) + { + parent_die = spec_die->parent; + parent_cu = spec_cu; + type_die = spec_die; + type_cu = spec_cu; + } + else + { + parent_die = imported_die->parent; + parent_cu = imported_cu; + type_die = imported_die; + type_cu = imported_cu; + } ++ + parent_type - = get_die_type_at_offset (parent_die->offset, ++ = get_die_type_at_offset (parent_die->sect_off, + parent_cu->per_cu); + if (parent_type != NULL) + { + add_xtor_field (parent_type, die, cu, + type_die, type_cu, name); + return 1; + } + } + } + } } } @@@ -11532,79 -11466,6 +11600,79 @@@ inherit_abstract_dies (struct die_info do_cleanups (cleanups); } +/* If DIE represents a constructor or destructor, add an alias + to the parent type's fieldlist. */ + +static void +possibly_add_new_xtor_method (const char *name, struct die_info *die, + struct dwarf2_cu *cu) +{ + const char *linkage_name = dw2_linkage_name (die, cu); + + if (linkage_name == NULL || cu->language != language_cplus) + return; + + enum ctor_kinds ctor_kind = is_constructor_name (linkage_name); + + if (ctor_kind == not_ctor) + { + enum dtor_kinds dtor_kind = is_destructor_name (linkage_name); + + if (dtor_kind == not_dtor) + return; + } + + if (dwarf2_attr (die, DW_AT_specification, cu)) + { + struct dwarf2_cu *spec_cu = cu; + struct die_info *spec_die = die_specification (die, &spec_cu); + const char *spec_linkage_name + = dw2_linkage_name (spec_die, spec_cu); + + if (streq (linkage_name, spec_linkage_name)) + return; + + if (spec_die->parent != NULL) + { + int i; + struct type *parent_type; + + parent_type - = get_die_type_at_offset (spec_die->parent->offset, cu->per_cu); ++ = get_die_type_at_offset (spec_die->parent->sect_off, cu->per_cu); + + add_xtor_field (parent_type, die, cu, NULL, NULL, name); + } + } +} + +/* Return the type of the template parameter given by TAG. */ + +static enum template_argument_kinds +dw2_template_param_kind (enum dwarf_tag tag) +{ + enum template_argument_kinds kind; + + switch (tag) + { + case DW_TAG_template_type_param: + kind = type_parameter; + break; + case DW_TAG_template_value_param: + kind = value_parameter; + break; + case DW_TAG_GNU_template_template_param: + kind = template_parameter; + break; + case DW_TAG_GNU_template_parameter_pack: + kind = variadic_parameter; + break; + default: + gdb_assert_not_reached ("unexpected template parameter tag"); + } + + return kind; +} + static void read_func_scope (struct die_info *die, struct dwarf2_cu *cu) { @@@ -13535,8 -13294,8 +13607,8 @@@ new_fn_field (struct die_info *name_die { complaint (&symfile_complaints, _("cannot determine context for virtual member " -- "function \"%s\" (offset %d)"), - fieldname, type_die->offset.sect_off); - fieldname, to_underlying (die->sect_off)); ++ "function \"%s\" (offset %d)"), fieldname, ++ to_underlying (type_die->sect_off)); } else { @@@ -13564,7 -13323,7 +13636,7 @@@ complaint (&symfile_complaints, _("Member function \"%s\" (offset %d) is virtual " "but the vtable offset is not specified"), - fieldname, type_die->offset.sect_off); - fieldname, to_underlying (die->sect_off)); ++ fieldname, to_underlying (type_die->sect_off)); ALLOCATE_CPLUS_STRUCT_TYPE (type); TYPE_CPLUS_DYNAMIC (type) = 1; } diff --cc gdb/gdbtypes.h index 44a6bc8a6bd,f6b4de90bc2..ed1b37b5658 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@@ -45,7 -45,7 +45,8 @@@ */ #include "hashtab.h" +#include "cp-abi.h" + #include "common/offset-type.h" /* Forward declarations for prototypes. */ struct field; diff --cc gdb/language.h index 4c4468d52b8,58bcbe8faec..e933869ab2f --- a/gdb/language.h +++ b/gdb/language.h @@@ -383,16 -379,10 +383,14 @@@ struct language_def This field may not be NULL. If the language does not need any special processing here, 'iterate_over_symbols' should be used as the definition. */ - void (*la_iterate_over_symbols) (const struct block *block, - const char *name, - domain_enum domain, - symbol_found_callback_ftype *callback, - void *data); + void (*la_iterate_over_symbols) + (const struct block *block, const char *name, domain_enum domain, + gdb::function_view callback); + /* Hash the given STRING. Use default_compute_string_hash if no + special treatment is required. */ + unsigned int (*la_compute_string_hash) (const char *name); + /* Various operations on varobj. */ const struct lang_varobj_ops *la_varobj_ops; diff --cc gdb/linespec.c index d15d6f2bc73,acf4900d456..b4371c11f8d --- a/gdb/linespec.c +++ b/gdb/linespec.c @@@ -44,7 -44,11 +44,8 @@@ #include "ada-lang.h" #include "stack.h" #include "location.h" + #include "common/function-view.h" -typedef struct symbol *symbolp; -DEF_VEC_P (symbolp); - typedef struct type *typep; DEF_VEC_P (typep); @@@ -159,9 -167,28 +160,24 @@@ struct collect_inf VEC (symtab_ptr) *file_symtabs; /* The result being accumulated. */ - struct - { - VEC (symbolp) *symbols; - VEC (bound_minimal_symbol_d) *minimal_symbols; - } result; + struct search_multiple_result result; + + /* Possibly add a symbol to the results. */ - bool add_symbol (symbol *sym); ++ bool add_symbol (block_symbol *bsym); }; + bool -collect_info::add_symbol (symbol *sym) ++collect_info::add_symbol (block_symbol *bsym) + { + /* In list mode, add all matching symbols, regardless of class. + This allows the user to type "list a_global_variable". */ - if (SYMBOL_CLASS (sym) == LOC_BLOCK || this->state->list_mode) - VEC_safe_push (symbolp, this->result.symbols, sym); ++ if (SYMBOL_CLASS (bsym->symbol) == LOC_BLOCK || this->state->list_mode) ++ VEC_safe_push (block_symbol_d, this->result.symbols, bsym); + + /* Continue iterating. */ + return true; + } + /* Token types */ enum ls_token_type @@@ -1023,7 -993,14 +985,14 @@@ iterate_over_all_matching_symtab { block = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), i); state->language->la_iterate_over_symbols - (block, name, domain, iterate_inline_only, &cad); - (block, name, domain, [&] (symbol *sym) ++ (block, name, domain, [&] (block_symbol *bsym) + { + /* Restrict calls to CALLBACK to symbols + representing inline symbols only. */ - if (SYMBOL_INLINED (sym)) - return callback (sym); ++ if (SYMBOL_INLINED (bsym->symbol)) ++ return callback (bsym); + return true; + }); } } } @@@ -2780,25 -2808,38 +2744,39 @@@ public ~decode_compound_collector () { - if (unique_syms != NULL) - htab_delete (unique_syms); + if (m_unique_syms != NULL) + htab_delete (m_unique_syms); } - }; - /* A callback for iterate_over_symbols that is used by - lookup_prefix_sym to collect type symbols. */ + /* Releases ownership of the collected symbols and returns them. */ - VEC (symbolp) *release_symbols () ++ VEC (block_symbol_d) *release_symbols () + { - VEC (symbolp) *res = m_symbols; ++ VEC (block_symbol_d) *res = m_symbols; + m_symbols = NULL; + return res; + } - static int - collect_one_symbol (struct block_symbol block_sym, void *d) + /* Callable as a symbol_found_callback_ftype callback. */ - bool operator () (symbol *sym); ++ bool operator () (block_symbol *bsym); + + private: + /* A hash table of all symbols we found. We use this to avoid + adding any symbol more than once. */ + htab_t m_unique_syms; + + /* The result vector. */ - VEC (symbolp) *m_symbols; ++ VEC (block_symbol_d) *m_symbols; + }; + + bool -decode_compound_collector::operator () (symbol *sym) ++decode_compound_collector::operator () (block_symbol *bsym) { - struct decode_compound_collector *collector - = (struct decode_compound_collector *) d; void **slot; struct type *t; - struct symbol *sym = block_sym.symbol; ++ struct symbol *sym = bsym->symbol; if (SYMBOL_CLASS (sym) != LOC_TYPEDEF) - return 1; /* Continue iterating. */ + return true; /* Continue iterating. */ t = SYMBOL_TYPE (sym); t = check_typedef (t); @@@ -2811,15 -2852,17 +2789,17 @@@ if (!*slot) { *slot = sym; - VEC_safe_push (block_symbol_d, collector->symbols, &block_sym); - VEC_safe_push (symbolp, m_symbols, sym); ++ VEC_safe_push (block_symbol_d, m_symbols, bsym); } - return 1; /* Continue iterating. */ + return true; /* Continue iterating. */ } + } // namespace + /* Return any symbols corresponding to CLASS_NAME in FILE_SYMTABS. */ -static VEC (symbolp) * +static VEC (block_symbol_d) * lookup_prefix_sym (struct linespec_state *state, VEC (symtab_ptr) *file_symtabs, const char *class_name) { @@@ -3873,9 -3817,9 +3833,9 @@@ add_matching_symbols_to_info (const cha { if (elt == NULL) { - iterate_over_all_matching_symtabs (info->state, name, VAR_DOMAIN, - pspace, true, [&] (symbol *sym) - { return info->add_symbol (sym); }); + iterate_over_all_matching_symtabs (info->state, name, domain, - collect_symbols, info, - pspace, 1); ++ pspace, true, [&] (block_symbol *bsym) ++ { return info->add_symbol (bsym); }); search_minsyms_for_name (info, name, pspace, NULL); } else if (pspace == NULL || pspace == SYMTAB_PSPACE (elt)) @@@ -3886,8 -3830,8 +3846,8 @@@ been filtered out earlier. */ gdb_assert (!SYMTAB_PSPACE (elt)->executing_startup); set_current_program_space (SYMTAB_PSPACE (elt)); - iterate_over_file_blocks (elt, name, domain, - collect_symbols, info); - iterate_over_file_blocks (elt, name, VAR_DOMAIN, [&] (symbol *sym) - { return info->add_symbol (sym); }); ++ iterate_over_file_blocks (elt, name, domain, [&] (block_symbol *bsym) ++ { return info->add_symbol (bsym); }); /* If no new symbols were found in this iteration and this symtab is in assembler, we might actually be looking for a label for diff --cc gdb/mdebugread.c index fe7bc90de51,8e27194a642..318eccda2af --- a/gdb/mdebugread.c +++ b/gdb/mdebugread.c @@@ -596,8 -596,8 +596,8 @@@ parse_symbol (SYMR *sh, union aux_ext * struct gdbarch *gdbarch = get_objfile_arch (objfile); const bfd_size_type external_sym_size = debug_swap->external_sym_size; void (*const swap_sym_in) (bfd *, void *, SYMR *) = debug_swap->swap_sym_in; - char *name; + const char *name; - struct symbol *s; + struct symbol *s = NULL; struct block *b; struct mdebug_pending *pend; struct type *t; diff --cc gdb/stabsread.h index d537e49c804,b37be1a0421..b803cf9ac7c --- a/gdb/stabsread.h +++ b/gdb/stabsread.h @@@ -168,9 -167,9 +168,9 @@@ extern struct partial_symtab *dbx_end_p struct partial_symtab **dependency_list, int number_dependencies, int textlow_not_set); - extern void process_one_symbol (int, int, CORE_ADDR, char *, + extern void process_one_symbol (int, int, CORE_ADDR, const char *, const struct section_offsets *, - struct objfile *); + struct objfile *, enum language); extern void elfstab_build_psymtabs (struct objfile *objfile, asection *stabsect, diff --cc gdb/symtab.c index 4053f1e4cd9,20ef76ddd84..964069f7341 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@@ -2798,9 -2775,7 +2775,9 @@@ iterate_over_symbols (const struct bloc if (symbol_matches_domain (SYMBOL_LANGUAGE (sym), SYMBOL_DOMAIN (sym), domain)) { - if (!callback (sym)) + struct block_symbol block_sym = {sym, block}; + - if (!callback (block_sym, data)) ++ if (!callback (&block_sym)) return; } } diff --cc gdb/symtab.h index 3f6029c47c0,341deca56fc..d464e593854 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@@ -1629,30 -1608,25 +1630,25 @@@ int compare_filenames_for_search (cons int compare_glob_filenames_for_search (const char *filename, const char *search_name); - int iterate_over_some_symtabs (const char *name, - const char *real_path, - int (*callback) (struct symtab *symtab, - void *data), - void *data, - struct compunit_symtab *first, - struct compunit_symtab *after_last); + bool iterate_over_some_symtabs (const char *name, + const char *real_path, + struct compunit_symtab *first, + struct compunit_symtab *after_last, + gdb::function_view callback); void iterate_over_symtabs (const char *name, - int (*callback) (struct symtab *symtab, - void *data), - void *data); + gdb::function_view callback); - VEC (CORE_ADDR) *find_pcs_for_symtab_line (struct symtab *symtab, int line, - struct linetable_entry **best_entry); - /* Callback for LA_ITERATE_OVER_SYMBOLS. The callback will be called - once per matching symbol SYM, with DATA being the argument of the - same name that was passed to LA_ITERATE_OVER_SYMBOLS. The callback - should return nonzero to indicate that LA_ITERATE_OVER_SYMBOLS - should continue iterating, or zero to indicate that the iteration - should end. */ + std::vector find_pcs_for_symtab_line + (struct symtab *symtab, int line, struct linetable_entry **best_entry); - typedef int (symbol_found_callback_ftype) (struct block_symbol sym, void *data); + /* Prototype for callbacks for LA_ITERATE_OVER_SYMBOLS. The callback + is called once per matching symbol SYM. The callback should return + true to indicate that LA_ITERATE_OVER_SYMBOLS should continue + iterating, or false to indicate that the iteration should end. */ + -typedef bool (symbol_found_callback_ftype) (symbol *sym); ++typedef bool (symbol_found_callback_ftype) (struct block_symbol *sym); void iterate_over_symbols (const struct block *block, const char *name, const domain_enum domain,