diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2017-02-24 10:21:39 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2017-02-24 10:21:39 +0000 |
commit | 59909673d11f6e1a0655c360c96653e9b0a37b84 (patch) | |
tree | df12757df9ec86f21787ed3c08d95ad2187e1379 /gcc/ada/gcc-interface/decl.c | |
parent | 8ff873dcdc0b87cbb30a1a951384293cc2d15a41 (diff) | |
download | gcc-59909673d11f6e1a0655c360c96653e9b0a37b84.zip gcc-59909673d11f6e1a0655c360c96653e9b0a37b84.tar.gz gcc-59909673d11f6e1a0655c360c96653e9b0a37b84.tar.bz2 |
c-ada-spec.c (dump_ada_function_declaration): Add comment about the treatment of parameters with pointer-to-tagged type and...
c-family/
* c-ada-spec.c (dump_ada_function_declaration): Add comment about the
treatment of parameters with pointer-to-tagged type and tidy up.
(print_ada_methods): Remove the special treatment of C++ static member
functions.
ada/
* gcc-interface/decl.c: Include demangle.h.
(is_cplusplus_method): Return again true for a primitive operation
only if it is dispatching. For a subprogram with an interface name,
call the demangler to get the number of C++ parameters and compare it
with the number of Ada parameters.
From-SVN: r245700
Diffstat (limited to 'gcc/ada/gcc-interface/decl.c')
-rw-r--r-- | gcc/ada/gcc-interface/decl.c | 81 |
1 files changed, 69 insertions, 12 deletions
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index 18ec63d..b493e80 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -6,7 +6,7 @@ * * * C Implementation File * * * - * Copyright (C) 1992-2016, Free Software Foundation, Inc. * + * Copyright (C) 1992-2017, Free Software Foundation, Inc. * * * * GNAT is free software; you can redistribute it and/or modify it under * * terms of the GNU General Public License as published by the Free Soft- * @@ -34,6 +34,7 @@ #include "fold-const.h" #include "stor-layout.h" #include "tree-inline.h" +#include "demangle.h" #include "ada.h" #include "types.h" @@ -5093,10 +5094,6 @@ get_unpadded_type (Entity_Id gnat_entity) bool is_cplusplus_method (Entity_Id gnat_entity) { - /* Check that the subprogram has C++ convention. */ - if (Convention (gnat_entity) != Convention_CPP) - return false; - /* A constructor is a method on the C++ side. We deal with it now because it is declared without the 'this' parameter in the sources and, although the front-end will create a version with the 'this' parameter for code @@ -5104,6 +5101,10 @@ is_cplusplus_method (Entity_Id gnat_entity) if (Is_Constructor (gnat_entity)) return true; + /* Check that the subprogram has C++ convention. */ + if (Convention (gnat_entity) != Convention_CPP) + return false; + /* And that the type of the first parameter (indirectly) has it too. */ Entity_Id gnat_first = First_Formal (gnat_entity); if (No (gnat_first)) @@ -5115,19 +5116,75 @@ is_cplusplus_method (Entity_Id gnat_entity) if (Convention (gnat_type) != Convention_CPP) return false; - /* This is the main case: C++ method imported as a primitive operation. - Note that a C++ class with no virtual functions can be imported as a - limited record type so the operation is not necessarily dispatching. */ - if (Is_Primitive (gnat_entity)) + /* This is the main case: a C++ virtual method imported as a primitive + operation of a tagged type. */ + if (Is_Dispatching_Operation (gnat_entity)) + return true; + + /* This is set on the E_Subprogram_Type built for a dispatching call. */ + if (Is_Dispatch_Table_Entity (gnat_entity)) return true; /* A thunk needs to be handled like its associated primitive operation. */ if (Is_Subprogram (gnat_entity) && Is_Thunk (gnat_entity)) return true; - /* This is set on the E_Subprogram_Type built for a dispatching call. */ - if (Is_Dispatch_Table_Entity (gnat_entity)) - return true; + /* Now on to the annoying case: a C++ non-virtual method, imported either + as a non-primitive operation of a tagged type or as a primitive operation + of an untagged type. We cannot reliably differentiate these cases from + their static member or regular function equivalents in Ada, so we ask + the C++ side through the mangled name of the function, as the implicit + 'this' parameter is not encoded in the mangled name of a method. */ + if (Is_Subprogram (gnat_entity) && Present (Interface_Name (gnat_entity))) + { + String_Pointer sp = { NULL, NULL }; + Get_External_Name (gnat_entity, false, sp); + + void *mem; + struct demangle_component *cmp + = cplus_demangle_v3_components (Name_Buffer, + DMGL_GNU_V3 + | DMGL_TYPES + | DMGL_PARAMS + | DMGL_RET_DROP, + &mem); + if (!cmp) + return false; + + /* We need to release MEM once we have a successful demangling. */ + bool ret = false; + + if (cmp->type == DEMANGLE_COMPONENT_TYPED_NAME + && cmp->u.s_binary.right->type == DEMANGLE_COMPONENT_FUNCTION_TYPE + && (cmp = cmp->u.s_binary.right->u.s_binary.right) != NULL + && cmp->type == DEMANGLE_COMPONENT_ARGLIST) + { + /* Make sure there is at least one parameter in C++ too. */ + if (cmp->u.s_binary.left) + { + unsigned int n_ada_args = 0; + do { + n_ada_args++; + gnat_first = Next_Formal (gnat_first); + } while (Present (gnat_first)); + + unsigned int n_cpp_args = 0; + do { + n_cpp_args++; + cmp = cmp->u.s_binary.right; + } while (cmp); + + if (n_cpp_args < n_ada_args) + ret = true; + } + else + ret = true; + } + + free (mem); + + return ret; + } return false; } |