From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-lj1-x232.google.com (mail-lj1-x232.google.com [IPv6:2a00:1450:4864:20::232]) by sourceware.org (Postfix) with ESMTPS id EA8C33858CDB for ; Thu, 20 Jul 2023 13:10:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org EA8C33858CDB Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-lj1-x232.google.com with SMTP id 38308e7fff4ca-2b6f943383eso11020721fa.2 for ; Thu, 20 Jul 2023 06:10:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1689858601; x=1690463401; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=HzMsHsMti3VRbkvBZnC/r3qMsVpctj5hcs7cyrmR5wk=; b=FAOc6Z18X0Xcyftl4sGBAzN8fhbJ3V5o581+KKun+idHfWnccYPgf7/AU7UCfyxGBH uy71a79y5a87JsQ5om1vs2bizJkgr3R/jUdduiPbzFCgs9Zi/CSYolnL/977s8iB0kEa Yw+3Nkn8+MiwZD1aaJ5fP3rS9wDPCi3fUqNjSbrNw4dRfuUPdKFEKPSta0IJRyJcpo6C TUXf23ktdTJVt1ReVEq70qtZw2RyjSFZ+1uF/lirFApTN0GwrNBD9M8JEAn2E2f2ZpeV fv2lb+i99v9ru6CVPPE9G68A1AinJnZfweR+956vg0+9gPSCO+CvHjGGh2ulsJSgCGP3 h8pw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689858601; x=1690463401; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=HzMsHsMti3VRbkvBZnC/r3qMsVpctj5hcs7cyrmR5wk=; b=JPtpD+p8HCvNAt4p9Q8aEodYyFXYM/kAH9VRK9xD8omDNXpm1lXjp38hBN0zsFPGOa MP0qdLUskFA9Ty1tR6OwcgANA6AOwIsMt3QTLWev2TLuad9LtpvRaKQZppcad1FEfnmN Gf1XkQLmcQo8sJTEskFRRNC6eCG0AxJZbRPsejdwXQgCp5EIf/tTDg7sxbs0BHpKD9B2 9gtc6c3z6Xvusf+A0TawmVeccIFWOZqacPjgLqPGmb2G2XX2F37pznsXfrUPXRA+3iJR ATC75Ot5lbe1q/0ltJC4oKs7rTWP/wqUk4ZjqrWs14QbIYN46I2VJLbgu5a835RPessD 9zJw== X-Gm-Message-State: ABy/qLa9zftvhVEXBS0XVh1Bif2540xuMb2qeimCWl+Qry7oQh0pbUSM FEq4MDwp8JNYZJ31olvQNiVKspWmnZKrWeTFzAOLH4YT X-Google-Smtp-Source: APBJJlF3EwfwVklGmpfSZ1BWTIkulWojN6D18sOMJEP5/Y4/statMvlkone/qfuRqRfKMSzVKNR8qU/byXtqk/O8e+s= X-Received: by 2002:a2e:86d5:0:b0:2b9:383b:89fc with SMTP id n21-20020a2e86d5000000b002b9383b89fcmr2207422ljj.0.1689858600300; Thu, 20 Jul 2023 06:10:00 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Richard Biener Date: Thu, 20 Jul 2023 15:09:25 +0200 Message-ID: Subject: Re: [PATCH v4] Introduce attribute sym To: Alexandre Oliva Cc: Jan Hubicka , Nathan Sidwell , gcc-patches@gcc.gnu.org, jason@redhat.com, joseph@codesourcery.com, hainque@adacore.com, ebotcazou@adacore.com Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-6.5 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,GIT_PATCH_0,KAM_STOCKGEN,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On Thu, Jul 20, 2023 at 1:11=E2=80=AFAM Alexandre Oliva = wrote: > > On Jul 18, 2023, Richard Biener wrote: > > > I think the __symver__ attribute does something similar already so > > maybe use __attribute__((__sym__("foo")))? > > Cool, thanks, that will do. Regstrapped on x86_64-linux-gnu. Ok to > install? > > > This patch introduces an attribute to add extra asm names (aliases) > for a decl when its definition is output. The main goal is to ease > interfacing C++ with Ada, as C++ mangled names have to be named, and > in some cases (e.g. when using stdint.h typedefs in function > arguments) the symbol names may vary across platforms. > > The attribute is usable in C and C++, presumably in all C-family > languages. It can be attached to global variables and functions. In > C++, it can also be attached to class types, namespace-scoped > variables and functions, static data members, member functions, > explicit instantiations and specializations of template functions, > members and classes. > > When applied to constructors or destructor, additional sym aliases > with _Base and _Del suffixes are defined for variants other than > complete-object ones. This changes the assumption that clones always > carry the same attributes as their abstract declarations, so there is > now a function to adjust them. > > C++ also had a bug in which attributes from local extern declarations > failed to be propagated to a preexisting corresponding > namespace-scoped decl. I've fixed that, and adjusted acc tests that > distinguished between C and C++ in this regard. > > Applying the attribute to class types is only valid in C++, and the > effect is to attach the alias to the RTTI object associated with the > class type. I wonder if we could have shared some of the cgraph/varasm bits with the symver attribute handling? It's just a new 'sym' but without the version part? I hope Honza can chime in here. Thanks, Richard. > for gcc/ChangeLog > > * attribs.cc: Include cgraph.h. > (decl_attributes): Allow late introduction of sym alias in > types. > (create_sym_alias_decl, create_sym_alias_decls): New. > * attribs.h: Declare them. > (FOR_EACH_SYM_ALIAS): New macro. > * cgraph.cc (cgraph_node::create): Create sym alias decls. > * varpool.cc (varpool_node::get_create): Create sym alias > decls. > * cgraph.h (symtab_node::remap_sym_alias_target): New. > * symtab.cc (symtab_node::remap_sym_alias_target): Define. > * cgraphunit.cc (cgraph_node::analyze): Create alias_target > node if needed. > (analyze_functions): Fixup visibility of implicit alias only > after its node is analyzed. > * doc/extend.texi (sym): Document for variables, functions and > types. > > for gcc/ada/ChangeLog > > * doc/gnat_rm/interfacing_to_other_languages.rst: Mention > attribute sym to give RTTI symbols mnemonic names. > * doc/gnat_ugn/the_gnat_compilation_model.rst: Mention > aliases. Fix incorrect ref to C1 ctor variant. > > for gcc/c-family/ChangeLog > > * c-ada-spec.cc (pp_asm_name): Use first sym alias if > available. > * c-attribs.cc (handle_sym_attribute): New. > (c_common_attribute_table): Add sym. > (handle_copy_attribute): Do not copy sym attribute. > > for gcc/c/ChangeLog > > * c-decl.cc (duplicate_decls): Remap sym alias target. > > for gcc/cp/ChangeLog > > * class.cc (adjust_clone_attributes): New. > (copy_fndecl_with_name, build_clone): Call it. > * cp-tree.h (adjust_clone_attributes): Declare. > (update_sym_alias_interface): Declare. > (update_tinfo_sym_alias): Declare. > * decl.cc (duplicate_decls): Remap sym_alias target. > Adjust clone attributes. > (grokfndecl): Tentatively create sym alias decls after > adding attributes in e.g. a template member function explicit > instantiation. > * decl2.cc (cplus_decl_attributes): Update tinfo sym alias. > (copy_interface, update_sym_alias_interface): New. > (determine_visibility): Update sym alias interface. > (tentative_decl_linkage, import_export_decl): Likewise. > * name-lookup.cc: Include target.h and cgraph.h. > (push_local_extern_decl_alias): Merge attributes with > namespace-scoped decl, and drop duplicate sym alias. > * optimize.cc (maybe_clone_body): Re-adjust attributes after > cloning them. Update sym alias interface. > * rtti.cc: Include attribs.h and cgraph.h. > (get_tinfo_decl): Copy sym attributes from type to tinfo decl. > Create sym alias decls. > (update_tinfo_sym_alias): New. > > for gcc/testsuite/ChangeLog > > * c-c++-common/goacc/declare-1.c: Adjust. > * c-c++-common/goacc/declare-2.c: Adjust. > * c-c++-common/torture/attr-sym-1.c: New. > * c-c++-common/torture/attr-sym-2.c: New. > * c-c++-common/torture/attr-sym-3.c: New. > * c-c++-common/torture/attr-sym-4.c: New. > * g++.dg/torture/attr-sym-1.C: New. > * g++.dg/torture/attr-sym-2.C: New. > * g++.dg/torture/attr-sym-3.C: New. > * g++.dg/torture/attr-sym-4.C: New. > * g++.dg/torture/attr-sym-5.C: New. > --- > .../doc/gnat_rm/interfacing_to_other_languages.rst | 6 + > .../doc/gnat_ugn/the_gnat_compilation_model.rst | 10 ++ > gcc/attribs.cc | 68 ++++++++++++++= ++ > gcc/attribs.h | 7 ++ > gcc/c-family/c-ada-spec.cc | 7 ++ > gcc/c-family/c-attribs.cc | 33 +++++++- > gcc/c/c-decl.cc | 2 > gcc/cgraph.cc | 2 > gcc/cgraph.h | 4 + > gcc/cgraphunit.cc | 2 > gcc/cp/class.cc | 64 ++++++++++++++= + > gcc/cp/cp-tree.h | 4 + > gcc/cp/decl.cc | 4 + > gcc/cp/decl2.cc | 50 ++++++++++++ > gcc/cp/name-lookup.cc | 11 +++ > gcc/cp/optimize.cc | 3 + > gcc/cp/rtti.cc | 71 ++++++++++++++= +++ > gcc/doc/extend.texi | 52 +++++++++++++ > gcc/symtab.cc | 36 +++++++++ > gcc/testsuite/c-c++-common/goacc/declare-1.c | 6 + > gcc/testsuite/c-c++-common/goacc/declare-2.c | 14 ++- > gcc/testsuite/c-c++-common/torture/attr-sym-1.c | 39 +++++++++ > gcc/testsuite/c-c++-common/torture/attr-sym-2.c | 13 +++ > gcc/testsuite/c-c++-common/torture/attr-sym-3.c | 41 ++++++++++ > gcc/testsuite/c-c++-common/torture/attr-sym-4.c | 28 +++++++ > gcc/testsuite/g++.dg/torture/attr-sym-1.C | 72 ++++++++++++++= +++ > gcc/testsuite/g++.dg/torture/attr-sym-2.C | 26 ++++++ > gcc/testsuite/g++.dg/torture/attr-sym-3.C | 83 ++++++++++++++= ++++++ > gcc/testsuite/g++.dg/torture/attr-sym-4.C | 28 +++++++ > gcc/testsuite/g++.dg/torture/attr-sym-5.C | 14 +++ > gcc/varpool.cc | 3 + > 31 files changed, 784 insertions(+), 19 deletions(-) > create mode 100644 gcc/testsuite/c-c++-common/torture/attr-sym-1.c > create mode 100644 gcc/testsuite/c-c++-common/torture/attr-sym-2.c > create mode 100644 gcc/testsuite/c-c++-common/torture/attr-sym-3.c > create mode 100644 gcc/testsuite/c-c++-common/torture/attr-sym-4.c > create mode 100644 gcc/testsuite/g++.dg/torture/attr-sym-1.C > create mode 100644 gcc/testsuite/g++.dg/torture/attr-sym-2.C > create mode 100644 gcc/testsuite/g++.dg/torture/attr-sym-3.C > create mode 100644 gcc/testsuite/g++.dg/torture/attr-sym-4.C > create mode 100644 gcc/testsuite/g++.dg/torture/attr-sym-5.C > > diff --git a/gcc/ada/doc/gnat_rm/interfacing_to_other_languages.rst b/gcc= /ada/doc/gnat_rm/interfacing_to_other_languages.rst > index ad0be511d4800..5e30912e434aa 100644 > --- a/gcc/ada/doc/gnat_rm/interfacing_to_other_languages.rst > +++ b/gcc/ada/doc/gnat_rm/interfacing_to_other_languages.rst > @@ -123,6 +123,12 @@ It is also possible to import a C++ exception using = the following syntax: > The ``External_Name`` is the name of the C++ RTTI symbol. You can then > cover a specific C++ exception in an exception handler. > > +RTTI symbols undergo C++ name mangling, which can make for identifiers > +that are inconvenient to use. An alias with a mnemonic name can be > +introduced by adding attribute ``sym`` to the class that the RTTI > +symbol refers to. > + > + > .. _Interfacing_to_COBOL: > > Interfacing to COBOL > diff --git a/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst b/gcc/ad= a/doc/gnat_ugn/the_gnat_compilation_model.rst > index 148d40815b8f8..fcae7e912ef36 100644 > --- a/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst > +++ b/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst > @@ -4274,6 +4274,7 @@ and two public primitives to set and get the value = of this attribute. > public: > virtual void Set_Age (int New_Age); > virtual int Age (); > + __attribute__ ((__sym__ ("Ctor_For_Animal"))) > Animal() {Age_Count =3D 0;}; > private: > int Age_Count; > @@ -4306,6 +4307,7 @@ both Carnivore and Domestic, that is: > virtual int Number_Of_Teeth (); > virtual void Set_Owner (char* Name); > > + __attribute__ ((__sym__ ("Ctor_For_Dog"))) // mnemonic alias > Dog(); // Constructor > private: > int Tooth_Count; > @@ -4344,7 +4346,8 @@ how to import these C++ declarations from the Ada s= ide: > > function New_Animal return Animal; > pragma CPP_Constructor (New_Animal); > - pragma Import (CPP, New_Animal, "_ZN6AnimalC1Ev"); > + pragma Import (CPP, New_Animal, > + "_ZN6AnimalC1Ev"); -- or "Ctor_For_Animal" > > type Dog is new Animal and Carnivore and Domestic with record > Tooth_Count : Natural; > @@ -4360,7 +4363,7 @@ how to import these C++ declarations from the Ada s= ide: > > function New_Dog return Dog; > pragma CPP_Constructor (New_Dog); > - pragma Import (CPP, New_Dog, "_ZN3DogC2Ev"); > + pragma Import (CPP, New_Dog, "Ctor_For_Dog"); -- or "_ZN3DogC1Ev" > end Animals; > > Thanks to the compatibility between GNAT run-time structures and the C++= ABI, > @@ -4382,7 +4385,8 @@ associated with each subprogram because it is assum= ed that all the calls to > these primitives will be dispatching calls. The only exception is the > constructor, which must be registered with the compiler by means of > ``pragma CPP_Constructor`` and needs to provide its associated C++ > -mangled name because the Ada compiler generates direct calls to it. > +mangled name (or an alias) because the Ada compiler generates direct > +calls to it. > > With the above packages we can now declare objects of type Dog on the Ad= a side > and dispatch calls to the corresponding subprograms on the C++ side. We = can > diff --git a/gcc/attribs.cc b/gcc/attribs.cc > index b8cb55b97df38..cd394f4c5f608 100644 > --- a/gcc/attribs.cc > +++ b/gcc/attribs.cc > @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see > #include "coretypes.h" > #include "target.h" > #include "tree.h" > +#include "cgraph.h" > #include "stringpool.h" > #include "diagnostic-core.h" > #include "attribs.h" > @@ -819,7 +820,8 @@ decl_attributes (tree *node, tree attributes, int fla= gs, > > if (TYPE_P (*anode) > && (flags & (int) ATTR_FLAG_TYPE_IN_PLACE) > - && COMPLETE_TYPE_P (*anode)) > + && COMPLETE_TYPE_P (*anode) > + && !is_attribute_p ("sym", name)) > { > warning (OPT_Wattributes, "type attributes ignored after type i= s already defined"); > continue; > @@ -2631,6 +2633,70 @@ attr_access::array_as_string (tree type) const > return typstr; > } > > +/* Create a sym attribute for DECL to be visible with linkage name ID. = */ > + > +tree > +create_sym_alias_decl (tree decl, tree id) > +{ > + const char *attr_str =3D "sym"; > + > + if (symtab_node *sym_node =3D symtab_node::get_for_asmname (id)) > + { > + if ((sym_node->analyzed > + ? sym_node->get_alias_target ()->decl > + : sym_node->alias_target) =3D=3D decl) > + return sym_node->decl; > + > + tree attr_name =3D get_identifier (attr_str); > + error_at (DECL_SOURCE_LOCATION (decl), > + "duplicate symbol name %qE in %qE attribute of %qD", > + id, attr_name, decl); > + inform (DECL_SOURCE_LOCATION (sym_node->decl), > + "already used by %qD", sym_node->decl); > + } > + > + tree clone =3D copy_node (decl); > + DECL_ATTRIBUTES (clone) =3D remove_attribute (attr_str, > + DECL_ATTRIBUTES (decl)); > + SET_DECL_ASSEMBLER_NAME (clone, id); > + TREE_USED (id) =3D 1; > + TREE_USED (clone) =3D 1; > + DECL_PRESERVE_P (clone) =3D 1; > + DECL_EXTERNAL (clone) =3D 0; > + TREE_STATIC (clone) =3D 1; > + > + if (VAR_P (clone)) > + { > + DECL_READ_P (clone) =3D 1; > + varpool_node::create_extra_name_alias (clone, decl); > + } > + else > + { > + cgraph_node::create_same_body_alias (clone, decl); > + } > + > + return clone; > +} > + > +/* Create decls for all sym aliases requested in DECL's attributes. */ > + > +void > +create_sym_alias_decls (tree decl) > +{ > + if (!decl_in_symtab_p (decl) > + || !symtab_node::get (decl) > + || DECL_ABSTRACT_P (decl)) > + return; > + > + FOR_EACH_SYM_ALIAS (sym, DECL_ATTRIBUTES (decl)) > + { > + tree id =3D TREE_VALUE (TREE_VALUE (sym)); > + id =3D get_identifier (TREE_STRING_POINTER (id)); > + > + create_sym_alias_decl (decl, id); > + } > +} > + > #if CHECKING_P > > namespace selftest > diff --git a/gcc/attribs.h b/gcc/attribs.h > index 84a43658a70da..734fa83f8d572 100644 > --- a/gcc/attribs.h > +++ b/gcc/attribs.h > @@ -398,4 +398,11 @@ extern void init_attr_rdwr_indices (rdwr_map *, tree= ); > extern attr_access *get_parm_access (rdwr_map &, tree, > tree =3D current_function_decl); > > +extern tree create_sym_alias_decl (tree, tree); > +extern void create_sym_alias_decls (tree); > + > +#define FOR_EACH_SYM_ALIAS(sym, attrs) \ > + for (tree sym =3D lookup_attribute ("sym", (attrs)); = \ > + sym; sym =3D lookup_attribute ("sym", TREE_CHAIN (sym))) > + > #endif // GCC_ATTRIBS_H > diff --git a/gcc/c-family/c-ada-spec.cc b/gcc/c-family/c-ada-spec.cc > index 050994d841665..5042b9cfecd80 100644 > --- a/gcc/c-family/c-ada-spec.cc > +++ b/gcc/c-family/c-ada-spec.cc > @@ -1431,6 +1431,13 @@ pp_ada_tree_identifier (pretty_printer *buffer, tr= ee node, tree type, > static void > pp_asm_name (pretty_printer *buffer, tree t) > { > + FOR_EACH_SYM_ALIAS (sym, DECL_ATTRIBUTES (t)) > + { > + tree id =3D TREE_VALUE (TREE_VALUE (sym)); > + pp_string (buffer, TREE_STRING_POINTER (id)); > + return; > + } > + > tree name =3D DECL_ASSEMBLER_NAME (t); > char *ada_name =3D XALLOCAVEC (char, IDENTIFIER_LENGTH (name) + 1), *s= ; > const char *ident =3D IDENTIFIER_POINTER (name); > diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc > index e2792ca6898b3..f5d72cef49794 100644 > --- a/gcc/c-family/c-attribs.cc > +++ b/gcc/c-family/c-attribs.cc > @@ -108,7 +108,8 @@ static tree handle_noplt_attribute (tree *, tree, tre= e, int, bool *) ; > static tree handle_alias_ifunc_attribute (bool, tree *, tree, tree, bool= *); > static tree handle_ifunc_attribute (tree *, tree, tree, int, bool *); > static tree handle_alias_attribute (tree *, tree, tree, int, bool *); > -static tree handle_weakref_attribute (tree *, tree, tree, int, bool *) ; > +static tree handle_weakref_attribute (tree *, tree, tree, int, bool *); > +static tree handle_sym_attribute (tree *, tree, tree, int, bool *); > static tree handle_visibility_attribute (tree *, tree, tree, int, > bool *); > static tree handle_tls_model_attribute (tree *, tree, tree, int, > @@ -383,6 +384,8 @@ const struct attribute_spec c_common_attribute_table[= ] =3D > handle_alias_attribute, NULL }, > { "weakref", 0, 1, true, false, false, false, > handle_weakref_attribute, NULL }, > + { "sym", 1, 1, false, false, false, false, > + handle_sym_attribute, NULL }, > { "no_instrument_function", 0, 0, true, false, false, false, > handle_no_instrument_function_attribute, > NULL }, > @@ -2855,7 +2858,7 @@ handle_alias_ifunc_attribute (bool is_alias, tree *= node, tree name, tree args, > return NULL_TREE; > } > > -/* Handle an "alias" or "ifunc" attribute; arguments as in > +/* Handle an "ifunc" attribute; arguments as in > struct attribute_spec.handler. */ > > static tree > @@ -2865,7 +2868,7 @@ handle_ifunc_attribute (tree *node, tree name, tree= args, > return handle_alias_ifunc_attribute (false, node, name, args, no_add_a= ttrs); > } > > -/* Handle an "alias" or "ifunc" attribute; arguments as in > +/* Handle an "alias" attribute; arguments as in > struct attribute_spec.handler. */ > > static tree > @@ -2875,6 +2878,29 @@ handle_alias_attribute (tree *node, tree name, tre= e args, > return handle_alias_ifunc_attribute (true, node, name, args, no_add_at= trs); > } > > +/* Handle a "sym" attribute; arguments as in struct > + attribute_spec.handler. */ > + > +static tree > +handle_sym_attribute (tree *pnode, tree name, tree args, > + int ARG_UNUSED (flags), bool *no_add_attrs) > +{ > + tree node =3D *pnode; > + > + *no_add_attrs =3D true; > + > + if (TREE_CODE (TREE_VALUE (args)) !=3D STRING_CST) > + error ("%qE attribute argument not a string", name); > + else if (decl_in_symtab_p (node)) > + *no_add_attrs =3D false; > + else if (TYPE_P (node) && c_dialect_cxx ()) > + *no_add_attrs =3D false; > + else > + return error_mark_node; > + > + return NULL_TREE; > +} > + > /* Handle the "copy" attribute NAME by copying the set of attributes > from the symbol referenced by ARGS to the declaration of *NODE. */ > > @@ -3008,6 +3034,7 @@ handle_copy_attribute (tree *node, tree name, tree = args, > || is_attribute_p ("visibility", atname) > || is_attribute_p ("weak", atname) > || is_attribute_p ("weakref", atname) > + || is_attribute_p ("sym", atname) > || is_attribute_p ("target_clones", atname)) > continue; > > diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc > index ecd10ebb69caf..5d6ce11cbb3ab 100644 > --- a/gcc/c/c-decl.cc > +++ b/gcc/c/c-decl.cc > @@ -3073,6 +3073,8 @@ duplicate_decls (tree newdecl, tree olddecl) > > merge_decls (newdecl, olddecl, newtype, oldtype); > > + symtab_node::remap_sym_alias_target (newdecl, olddecl); > + > /* The NEWDECL will no longer be needed. > > Before releasing the node, be sure to remove function from symbol > diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc > index e41e5ad3ae74d..c45ce2d0a1332 100644 > --- a/gcc/cgraph.cc > +++ b/gcc/cgraph.cc > @@ -523,6 +523,8 @@ cgraph_node::create (tree decl) > node->register_symbol (); > maybe_record_nested_function (node); > > + create_sym_alias_decls (decl); > + > return node; > } > > diff --git a/gcc/cgraph.h b/gcc/cgraph.h > index cedaaac3a45b7..6a444e6fa5bcf 100644 > --- a/gcc/cgraph.h > +++ b/gcc/cgraph.h > @@ -327,6 +327,10 @@ public: > /* Return DECL that alias is aliasing. */ > inline tree get_alias_target_tree (); > > + /* Remap sym alias nodes recorded as aliasing REPLACED to alias REPLAC= EMENT > + instead. */ > + static void remap_sym_alias_target (tree replaced, tree replacement); > + > /* Set section for symbol and its aliases. */ > void set_section (const char *section); > > diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc > index bccd2f2abb5a3..eb2d05094e989 100644 > --- a/gcc/cgraphunit.cc > +++ b/gcc/cgraphunit.cc > @@ -1175,7 +1175,7 @@ analyze_functions (bool first_time) > C++ FE is confused about the COMDAT groups being right. */ > if (symtab->cpp_implicit_aliases_done) > FOR_EACH_SYMBOL (node) > - if (node->cpp_implicit_alias) > + if (node->cpp_implicit_alias && node->analyzed) > node->fixup_same_cpp_alias_visibility (node->get_alias_target (= )); > build_type_inheritance_graph (); > > diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc > index 778759237dc72..d6218bab28b21 100644 > --- a/gcc/cp/class.cc > +++ b/gcc/cp/class.cc > @@ -4859,6 +4859,68 @@ check_methods (tree t) > } > } > > +/* Adjust sym alias name for CLONE, cloned from FN and named NAME, > + if it is a cdtor, and drop the sym alias from other clones. */ > + > +void > +adjust_clone_attributes (tree fn, tree clone, tree name, bool skip_copy_= p) > +{ > + if (IDENTIFIER_CDTOR_P (name)) > + { > + bool found =3D false; > + FOR_EACH_SYM_ALIAS (sym, DECL_ATTRIBUTES (clone)) > + { > + found =3D true; > + break; > + } > + > + if (found > + && (name =3D=3D complete_ctor_identifier > + || name =3D=3D complete_dtor_identifier)) > + { > + /* Reuse the sym alias decls created for the primary cdtor > + decl. */ > + symtab_node::remap_sym_alias_target (fn, clone); > + } > + else if (found) > + { > + const char *suf; > + > + if (name =3D=3D base_ctor_identifier > + || name =3D=3D base_dtor_identifier) > + suf =3D "_Base"; > + else if (name =3D=3D deleting_dtor_identifier) > + suf =3D "_Del"; > + else > + gcc_unreachable (); > + > + size_t xlen =3D strlen (suf); > + > + if (!skip_copy_p) > + DECL_ATTRIBUTES (clone) =3D copy_list (DECL_ATTRIBUTES (clone= )); > + > + FOR_EACH_SYM_ALIAS (sym, DECL_ATTRIBUTES (clone)) > + { > + /* We need to copy this even with skip_copy_p, because > + even then copying was shallow. */ > + TREE_VALUE (sym) =3D copy_list (TREE_VALUE (sym)); > + /* Append suf to the sym alias name. */ > + tree str =3D TREE_VALUE (TREE_VALUE (sym)); > + char *symname =3D concat (TREE_STRING_POINTER (str), suf, N= ULL); > + str =3D build_string (TREE_STRING_LENGTH (str) + xlen, symn= ame); > + TREE_VALUE (TREE_VALUE (sym)) =3D str; > + free (symname); > + } > + > + if (symtab_node::get (clone)) > + create_sym_alias_decls (clone); > + } > + } > + else > + DECL_ATTRIBUTES (clone) > + =3D remove_attribute ("sym", DECL_ATTRIBUTES (clone)); > +} > + > /* FN is constructor, destructor or operator function. Clone the > declaration to create a NAME'd variant. NEED_VTT_PARM_P and > OMIT_INHERITED_PARMS_P are relevant if it's a cdtor. */ > @@ -5026,6 +5088,8 @@ build_clone (tree fn, tree name, bool need_vtt_parm= _p, > DECL_CHAIN (clone) =3D DECL_CHAIN (fn); > DECL_CHAIN (fn) =3D clone; > > + adjust_clone_attributes (fn, clone, name); > + > return clone; > } > > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h > index 3de0e154c124c..0a998d0bafd15 100644 > --- a/gcc/cp/cp-tree.h > +++ b/gcc/cp/cp-tree.h > @@ -5747,6 +5747,8 @@ struct GTY((for_user)) spec_entry > > extern int current_class_depth; > > +void adjust_clone_attributes (tree fn, tree clone, tree name, bool =3D f= alse); > + > /* in decl.cc */ > > /* An array of static vars & fns. */ > @@ -6960,6 +6962,7 @@ extern void do_push_parm_decls (= tree, tree, tree *); > extern tree do_aggregate_paren_init (tree, tree); > > /* in decl2.cc */ > +extern void update_sym_alias_interface (tree); > extern void record_mangling (tree, bool); > extern void overwrite_mangling (tree, tree); > extern void note_mangling_alias (tree, tree); > @@ -7535,6 +7538,7 @@ extern bool emit_tinfo_decl (= tree); > extern unsigned get_pseudo_tinfo_index (tree); > extern tree get_pseudo_tinfo_type (unsigned); > extern tree build_if_nonnull (tree, tree, tsubst_flags= _t); > +extern void update_tinfo_sym_alias (tree); > > /* in search.cc */ > extern tree get_parent_with_private_access (tree decl, tree binfo); > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc > index 60f107d50c4c5..28f7dbaf35d75 100644 > --- a/gcc/cp/decl.cc > +++ b/gcc/cp/decl.cc > @@ -3195,6 +3195,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool h= iding, bool was_hidden) > && TREE_STATIC (olddecl)))) > make_decl_rtl (olddecl); > > + symtab_node::remap_sym_alias_target (newdecl, olddecl); > + > /* The NEWDECL will no longer be needed. Because every out-of-class > declaration of a member results in a call to duplicate_decls, > freeing these nodes represents in a significant savings. > @@ -3218,6 +3220,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool h= iding, bool was_hidden) > FOR_EACH_CLONE (clone, olddecl) > { > DECL_ATTRIBUTES (clone) =3D DECL_ATTRIBUTES (olddecl); > + adjust_clone_attributes (olddecl, clone, DECL_NAME (clone)); > DECL_PRESERVE_P (clone) |=3D DECL_PRESERVE_P (olddecl); > } > } > @@ -10683,6 +10686,7 @@ grokfndecl (tree ctype, > { > cplus_decl_attributes (&decl, *attrlist, 0); > *attrlist =3D NULL_TREE; > + create_sym_alias_decls (decl); > } > > if (DECL_HAS_CONTRACTS_P (decl)) > diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc > index b402befba6da4..68232b8863f16 100644 > --- a/gcc/cp/decl2.cc > +++ b/gcc/cp/decl2.cc > @@ -1773,6 +1773,9 @@ cplus_decl_attributes (tree *decl, tree attributes,= int flags) > if (late_attrs) > save_template_attributes (late_attrs, decl, flags); > > + if (TYPE_P (*decl) && attributes) > + update_tinfo_sym_alias (*decl); > + > /* Propagate deprecation out to the template. */ > if (TREE_DEPRECATED (*decl)) > if (tree ti =3D get_template_info (*decl)) > @@ -2129,6 +2132,47 @@ adjust_var_decl_tls_model (tree decl) > set_decl_tls_model (decl, decl_default_tls_model (decl)); > } > > +/* Copy externalness and linkage from DECL to DEST. */ > + > +static void > +copy_interface (tree dest, tree decl) > +{ > + TREE_PUBLIC (dest) =3D TREE_PUBLIC (decl); > + TREE_STATIC (dest) =3D TREE_STATIC (decl); > + DECL_COMMON (dest) =3D DECL_COMMON (decl); > + DECL_COMDAT (dest) =3D DECL_COMDAT (decl); > + DECL_WEAK (dest) =3D DECL_WEAK (decl); > + DECL_EXTERNAL (dest) =3D DECL_EXTERNAL (decl); > + if (DECL_LANG_SPECIFIC (dest) && DECL_LANG_SPECIFIC (decl)) > + DECL_NOT_REALLY_EXTERN (dest) =3D DECL_NOT_REALLY_EXTERN (decl); > + DECL_INTERFACE_KNOWN (dest) =3D DECL_INTERFACE_KNOWN (decl); > + DECL_VISIBILITY (dest) =3D DECL_VISIBILITY (decl); > + DECL_VISIBILITY_SPECIFIED (dest) =3D DECL_VISIBILITY_SPECIFIED (decl); > +} > + > +/* Propagate linkage changes to sym aliases. */ > + > +void > +update_sym_alias_interface (tree decl) > +{ > + if (!decl_in_symtab_p (decl) > + || !symtab_node::get (decl)) > + return; > + > + FOR_EACH_SYM_ALIAS (sym, DECL_ATTRIBUTES (decl)) > + { > + tree id =3D TREE_VALUE (TREE_VALUE (sym)); > + id =3D get_identifier (TREE_STRING_POINTER (id)); > + symtab_node *sym_node =3D symtab_node::get_for_asmname (id); > + > + if (sym_node > + && (sym_node->analyzed > + ? sym_node->get_alias_target ()->decl > + : sym_node->alias_target) =3D=3D decl) > + copy_interface (sym_node->decl, decl); > + } > +} > + > /* Set DECL up to have the closest approximation of "initialized common" > linkage available. */ > > @@ -2936,6 +2980,8 @@ determine_visibility (tree decl) > translation unit, we can make the type internal. */ > constrain_visibility (decl, VISIBILITY_ANON, false); > > + update_sym_alias_interface (decl); > + > /* If visibility changed and DECL already has DECL_RTL, ensure > symbol flags are updated. */ > if ((DECL_VISIBILITY (decl) !=3D orig_visibility > @@ -3198,6 +3244,8 @@ tentative_decl_linkage (tree decl) > else if (VAR_P (decl)) > maybe_commonize_var (decl); > } > + > + update_sym_alias_interface (decl); > } > > /* DECL is a FUNCTION_DECL or VAR_DECL. If the object file linkage > @@ -3432,6 +3480,8 @@ import_export_decl (tree decl) > } > > DECL_INTERFACE_KNOWN (decl) =3D 1; > + > + update_sym_alias_interface (decl); > } > > /* Return an expression that performs the destruction of DECL, which > diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc > index 74565184403c1..12e4c78086016 100644 > --- a/gcc/cp/name-lookup.cc > +++ b/gcc/cp/name-lookup.cc > @@ -22,9 +22,11 @@ along with GCC; see the file COPYING3. If not see > #define INCLUDE_MEMORY > #include "system.h" > #include "coretypes.h" > +#include "target.h" > #include "cp-tree.h" > #include "timevar.h" > #include "stringpool.h" > +#include "cgraph.h" > #include "print-tree.h" > #include "attribs.h" > #include "debug.h" > @@ -3466,6 +3468,15 @@ push_local_extern_decl_alias (tree decl) > /* Adjust visibility. */ > determine_visibility (alias); > } > + else if (DECL_P (alias)) > + DECL_ATTRIBUTES (alias) > + =3D targetm.merge_decl_attributes (alias, decl); > + if (DECL_P (alias)) > + { > + symtab_node::remap_sym_alias_target (decl, alias); > + DECL_ATTRIBUTES (decl) > + =3D remove_attribute ("sym", DECL_ATTRIBUTES (alias)); > + } > } > > retrofit_lang_decl (decl); > diff --git a/gcc/cp/optimize.cc b/gcc/cp/optimize.cc > index 9e8926e4cc603..4a2e8cb435404 100644 > --- a/gcc/cp/optimize.cc > +++ b/gcc/cp/optimize.cc > @@ -528,9 +528,12 @@ maybe_clone_body (tree fn) > DECL_VISIBILITY_SPECIFIED (clone) =3D DECL_VISIBILITY_SPECIFIED (f= n); > DECL_DLLIMPORT_P (clone) =3D DECL_DLLIMPORT_P (fn); > DECL_ATTRIBUTES (clone) =3D clone_attrs (DECL_ATTRIBUTES (fn)); > + adjust_clone_attributes (fn, clone, DECL_NAME (clone), true); > DECL_DISREGARD_INLINE_LIMITS (clone) =3D DECL_DISREGARD_INLINE_LIM= ITS (fn); > set_decl_section_name (clone, fn); > > + update_sym_alias_interface (clone); > + > /* Adjust the parameter names and locations. */ > parm =3D DECL_ARGUMENTS (fn); > clone_parm =3D DECL_ARGUMENTS (clone); > diff --git a/gcc/cp/rtti.cc b/gcc/cp/rtti.cc > index 7878929c24679..4bb7b8c8c6e78 100644 > --- a/gcc/cp/rtti.cc > +++ b/gcc/cp/rtti.cc > @@ -28,8 +28,10 @@ along with GCC; see the file COPYING3. If not see > #include "stringpool.h" > #include "intl.h" > #include "stor-layout.h" > +#include "attribs.h" > #include "c-family/c-pragma.h" > #include "gcc-rich-location.h" > +#include "cgraph.h" > > /* C++ returns type information to the user in struct type_info > objects. We also use type information to implement dynamic_cast and > @@ -479,8 +481,13 @@ get_tinfo_decl_direct (tree type, tree name, int pse= udo_ix) > =3D build_tree_list (get_identifier ("non overlapping"), > NULL_TREE); > else > + /* Share the non overlapping attribute, without assuming it's > + the only attribute, but assuming it's the last if it's > + present. There may be sym aliases too, and those are not > + to be shared. */ > DECL_ATTRIBUTES (d) > - =3D DECL_ATTRIBUTES ((*unemitted_tinfo_decls)[0]); > + =3D lookup_attribute ("non overlapping", > + DECL_ATTRIBUTES ((*unemitted_tinfo_decls)[0= ])); > > /* Mark the variable as undefined -- but remember that we can > define it later if we need to do so. */ > @@ -492,6 +499,16 @@ get_tinfo_decl_direct (tree type, tree name, int pse= udo_ix) > if (CLASS_TYPE_P (type)) > CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) =3D d; > > + /* Copy sym alias attributes from the type to the rtti obj decl. = */ > + tree *attrs =3D &DECL_ATTRIBUTES (d); > + FOR_EACH_SYM_ALIAS (sym, TYPE_ATTRIBUTES (type)) > + { > + tree attr =3D tree_cons (TREE_PURPOSE (sym), TREE_VALUE (sym), = *attrs); > + *attrs =3D attr; > + attrs =3D &TREE_CHAIN (attr); > + } > + create_sym_alias_decls (d); > + > /* Add decl to the global array of tinfo decls. */ > vec_safe_push (unemitted_tinfo_decls, d); > } > @@ -499,6 +516,58 @@ get_tinfo_decl_direct (tree type, tree name, int pse= udo_ix) > return d; > } > > +/* After modifying the attributes of TYPE, check whether tinfo was > + already created and, if so, add to it any sym alias attributes > + that were not already present. */ > + > +void > +update_tinfo_sym_alias (tree type) > +{ > + if (!TYPE_SIZE (type) || !CLASS_TYPE_P (type)) > + return; > + > + tree d =3D CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)); > + if (!d) > + return; > + > + bool first =3D true; > + symtab_node *node =3D NULL; > + > + tree *attrs =3D &DECL_ATTRIBUTES (d); > + FOR_EACH_SYM_ALIAS (sym, TYPE_ATTRIBUTES (type)) > + { > + bool found =3D false; > + FOR_EACH_SYM_ALIAS (d_sym, *attrs) > + if (TREE_VALUE (sym) =3D=3D TREE_VALUE (d_sym)) > + { > + found =3D true; > + break; > + } > + > + if (found) > + continue; > + > + tree attr =3D tree_cons (TREE_PURPOSE (sym), > + TREE_VALUE (sym), > + *attrs); > + *attrs =3D attr; > + attrs =3D &TREE_CHAIN (attr); > + > + if (first) > + { > + first =3D false; > + node =3D symtab_node::get (d); > + } > + > + if (!node) > + continue; > + > + tree id =3D TREE_VALUE (TREE_VALUE (sym)); > + id =3D get_identifier (TREE_STRING_POINTER (id)); > + create_sym_alias_decl (d, id); > + } > +} > + > /* Return the type_info object for TYPE. */ > > tree > diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi > index dda35358ce746..4ffe06dc805cd 100644 > --- a/gcc/doc/extend.texi > +++ b/gcc/doc/extend.texi > @@ -4057,6 +4057,39 @@ Function Attributes}, @ref{PowerPC Function Attrib= utes}, > @ref{Nios II Function Attributes}, and @ref{S/390 Function Attributes} > for details. > > +@cindex @code{sym} function attribute > +@item sym ("@var{name}") > +The @code{sym} attribute causes @var{name} to be output as an alias to > +the definition. For instance, > + > +@smallexample > +void f (uint64_t) __attribute__ ((__sym__ ("f_u64"))); > +void f (uint64_t) @{ /* @r{Do something.} */; @} > +@end smallexample > + > +@noindent > +defines @samp{f}, and outputs @samp{f_u64} as an alias for @samp{f}. > +This is particularly useful when exporting C++ names for use in other > +languages, or as an alias target, when machine-dependent types would > +make mangled names harder to deal with. > + > +In the case of C++ constructors and destructors, in which a single > +definition may output multiple symbols, the specified name is associated > +with the variant that constructs or destructs a complete object. The > +variant that applies to a base subobject gets a @code{_Base} suffix, and > +the deleting destructor gets a @code{_Del} suffix. > + > +This attribute is silently ignored if @samp{f} is not defined in the > +same translation unit, so that the attribute can be attached to forward > +declarations. > + > +The name @samp{f_u64} is an assembly symbol name: it does not undergo > +C++ name mangling, and it is not made visible in any scope in the source > +language, but it can be named as an alias target. > + > +This attribute requires assembler and object file support for aliases, > +and may not be available on all targets. > + > @cindex @code{symver} function attribute > @item symver ("@var{name2}@@@var{nodename}") > On ELF targets this attribute creates a symbol version. The @var{name2}= part > @@ -7873,6 +7906,10 @@ will be placed in new, unique sections. > > This additional functionality requires Binutils version 2.36 or later. > > +@cindex @code{sym} variable attribute > +@item sym ("@var{name}") > +See @pxref{Common Function Attributes}. > + > @cindex @code{uninitialized} variable attribute > @item uninitialized > This attribute, attached to a variable with automatic storage, means tha= t > @@ -8902,6 +8939,21 @@ is not supported; that is to say, if a given scala= r object can be accessed > through distinct types that assign a different storage order to it, then= the > behavior is undefined. > > +@cindex @code{sym} type attribute > +@item sym ("@var{name}") > +The @code{sym} type attribute causes @var{name} to be emitted as an > +alias to the definition of the C++ Run-Time Type Information (RTTI) > +@code{std::type_info} object associated with the type. For instance, > + > +@smallexample > +class foo __attribute__ ((__sym__ ("TI_foo"))); > +@end smallexample > + > +@noindent > +arranges for @samp{TI_foo} to be defined as an alias to the RTTI object > +for class @samp{foo}, once the class is defined and used in ways that > +cause its RTTI object to be synthesized and output. > + > @cindex @code{transparent_union} type attribute > @item transparent_union > > diff --git a/gcc/symtab.cc b/gcc/symtab.cc > index 0470509a98d2a..0812088e59f38 100644 > --- a/gcc/symtab.cc > +++ b/gcc/symtab.cc > @@ -1943,6 +1943,42 @@ symtab_node::noninterposable_alias (symtab_node *n= ode, void *data) > return false; > } > > +/* Remap sym alias nodes recorded as aliasing REPLACED to alias > + REPLACEMENT instead. */ > + > +void > +symtab_node::remap_sym_alias_target (tree replaced, tree replacement) > +{ > + if (!decl_in_symtab_p (replacement) > + || !symtab_node::get (replacement)) > + return; > + > + FOR_EACH_SYM_ALIAS (sym, DECL_ATTRIBUTES (replaced)) > + { > + tree id =3D TREE_VALUE (TREE_VALUE (sym)); > + id =3D get_identifier (TREE_STRING_POINTER (id)); > + > + symtab_node *sym_node =3D symtab_node::get_for_asmname (id); > + > + if (!sym_node) > + { > + create_sym_alias_decl (replacement, id); > + continue; > + } > + > + gcc_assert (!sym_node->analyzed); > + if (sym_node->alias_target !=3D replaced) > + continue; > + > + sym_node->definition =3D 0; > + > + if (VAR_P (replaced)) > + varpool_node::create_extra_name_alias (sym_node->decl, replacemen= t); > + else > + cgraph_node::create_same_body_alias (sym_node->decl, replacement)= ; > + } > +} > + > /* If node cannot be overwriten by static or dynamic linker to point to > different definition, return NODE. Otherwise look for alias with such > property and if none exists, introduce new one. */ > diff --git a/gcc/testsuite/c-c++-common/goacc/declare-1.c b/gcc/testsuite= /c-c++-common/goacc/declare-1.c > index 46ee01b675950..f284289331807 100644 > --- a/gcc/testsuite/c-c++-common/goacc/declare-1.c > +++ b/gcc/testsuite/c-c++-common/goacc/declare-1.c > @@ -113,11 +113,11 @@ f_2 (void) > int va3; > #pragma acc declare device_resident(va3) > > -#ifndef __cplusplus > +#if 0 > /* TODO PR90868 > > - C: "error: variable '[...]' used more than once with '#pragma acc d= eclare'". */ > -#else > + "error: variable '[...]' used more than once with '#pragma acc decl= are'". */ > + > extern int ve0; > #pragma acc declare create(ve0) > > diff --git a/gcc/testsuite/c-c++-common/goacc/declare-2.c b/gcc/testsuite= /c-c++-common/goacc/declare-2.c > index e2e22be57e9e4..aec59b69754c5 100644 > --- a/gcc/testsuite/c-c++-common/goacc/declare-2.c > +++ b/gcc/testsuite/c-c++-common/goacc/declare-2.c > @@ -137,25 +137,25 @@ void > f_pr90868_2 (void) > { > extern int we0; > -#pragma acc declare create(we0) /* { dg-error "variable 'we0' used more = than once with '#pragma acc declare'" "" { target c } } */ > +#pragma acc declare create(we0) /* { dg-error "variable 'we0' used more = than once with '#pragma acc declare'" "" } */ > > extern int we1; > -#pragma acc declare copyin(we1) /* { dg-error "variable 'we1' used more = than once with '#pragma acc declare'" "" { target c } } */ > +#pragma acc declare copyin(we1) /* { dg-error "variable 'we1' used more = than once with '#pragma acc declare'" "" } */ > > extern int *we2; > -#pragma acc declare deviceptr(we2) /* { dg-error "variable 'we2' used mo= re than once with '#pragma acc declare'" "" { target c } } */ > +#pragma acc declare deviceptr(we2) /* { dg-error "variable 'we2' used mo= re than once with '#pragma acc declare'" "" } */ > > extern int we3; > -#pragma acc declare device_resident(we3) /* { dg-error "variable 'we3' u= sed more than once with '#pragma acc declare'" "" { target c } } */ > +#pragma acc declare device_resident(we3) /* { dg-error "variable 'we3' u= sed more than once with '#pragma acc declare'" "" } */ > > extern int we4; > -#pragma acc declare link(we4) /* { dg-error "variable 'we4' used more th= an once with '#pragma acc declare'" "" { target c } } */ > +#pragma acc declare link(we4) /* { dg-error "variable 'we4' used more th= an once with '#pragma acc declare'" "" } */ > > extern int we5; > -#pragma acc declare present_or_copyin(we5) /* { dg-error "variable 'we5'= used more than once with '#pragma acc declare'" "" { target c } } */ > +#pragma acc declare present_or_copyin(we5) /* { dg-error "variable 'we5'= used more than once with '#pragma acc declare'" "" } */ > > extern int we6; > -#pragma acc declare present_or_create(we6) /* { dg-error "variable 'we6'= used more than once with '#pragma acc declare'" "" { target c } } */ > +#pragma acc declare present_or_create(we6) /* { dg-error "variable 'we6'= used more than once with '#pragma acc declare'" "" } */ > } > > > diff --git a/gcc/testsuite/c-c++-common/torture/attr-sym-1.c b/gcc/testsu= ite/c-c++-common/torture/attr-sym-1.c > new file mode 100644 > index 0000000000000..6254c4ffd35bb > --- /dev/null > +++ b/gcc/testsuite/c-c++-common/torture/attr-sym-1.c > @@ -0,0 +1,39 @@ > +/* { dg-do compile } */ > +/* { dg-require-alias "" } */ > + > +extern int var_a __attribute__ ((__sym__ ("FOOVAR_A"))); > +int var_a =3D 1; > + > +void foo_a () __attribute__ ((__sym__ ("FOOBAR_A"))); > + > +void > +foo_a () > +{ > +} > + > + > +int var_b; > +extern int var_b __attribute__ ((__sym__ ("FOOVAR_B"))); > + > +void > +foo_b () > +{ > +} > + > +void foo_b () __attribute__ ((__sym__ ("FOOBAR_B"))); > + > + > +int var_c __attribute__ ((__sym__ ("FOOVAR_C"))); > + > +void __attribute__ ((__sym__ ("FOOBAR_C"))) > +foo_c () > +{ > +} > + > + > +/* { dg-final { scan-assembler "FOOBAR_A" } } */ > +/* { dg-final { scan-assembler "FOOVAR_A" } } */ > +/* { dg-final { scan-assembler "FOOBAR_B" } } */ > +/* { dg-final { scan-assembler "FOOVAR_B" } } */ > +/* { dg-final { scan-assembler "FOOBAR_C" } } */ > +/* { dg-final { scan-assembler "FOOVAR_C" } } */ > diff --git a/gcc/testsuite/c-c++-common/torture/attr-sym-2.c b/gcc/testsu= ite/c-c++-common/torture/attr-sym-2.c > new file mode 100644 > index 0000000000000..62a62d772f40c > --- /dev/null > +++ b/gcc/testsuite/c-c++-common/torture/attr-sym-2.c > @@ -0,0 +1,13 @@ > +/* { dg-do compile } */ > +/* { dg-require-alias "" } */ > + > +struct s > +{ > + int mem __attribute__ ((__sym__ ("MEMFOO"))); /* { dg-warning "attribu= te ignored" } */ > +}; > + > +void foo() > +{ > + extern void bar () __attribute__ ((__sym__ ("FOOBAR"))); > + int var __attribute__ ((__sym__ ("FOOVAR"))); /* { dg-warning "attribu= te ignored" } */ > +} > diff --git a/gcc/testsuite/c-c++-common/torture/attr-sym-3.c b/gcc/testsu= ite/c-c++-common/torture/attr-sym-3.c > new file mode 100644 > index 0000000000000..5f0da2813fc37 > --- /dev/null > +++ b/gcc/testsuite/c-c++-common/torture/attr-sym-3.c > @@ -0,0 +1,41 @@ > +/* { dg-do compile } */ > +/* { dg-require-alias "" } */ > + > +int var_a =3D 1; > + > +void > +foo_a () > +{ > + extern int var_a __attribute__ ((__sym__ ("FOOVAR_A"))); > + void foo_a () __attribute__ ((__sym__ ("FOOBAR_A"))); > +} > + > +#if 0 // __cplusplus > +/* Without this declaration before the local declaration below, the > + attributes of the local declaration do not get propagated to the > + (global) namespace scope. */ > +extern int var_b; > +#endif > + > +void > +foo_b () > +{ > + extern int var_b __attribute__ ((__sym__ ("FOOVAR_B"))); > +} > + > +int var_b; > + > +void __attribute__ ((__sym__ ("FOOBAR_C"))) > +foo_c () > +{ > + void foo_b () __attribute__ ((__sym__ ("FOOBAR_B"))); > + /* Another sym for var_b. */ > + extern int var_b __attribute__ ((__sym__ ("FOOVAR_C"))); > +} > + > +/* { dg-final { scan-assembler "FOOBAR_A" } } */ > +/* { dg-final { scan-assembler "FOOVAR_A" } } */ > +/* { dg-final { scan-assembler "FOOBAR_B" } } */ > +/* { dg-final { scan-assembler "FOOVAR_B" } } */ > +/* { dg-final { scan-assembler "FOOBAR_C" } } */ > +/* { dg-final { scan-assembler "FOOVAR_C" } } */ > diff --git a/gcc/testsuite/c-c++-common/torture/attr-sym-4.c b/gcc/testsu= ite/c-c++-common/torture/attr-sym-4.c > new file mode 100644 > index 0000000000000..93312a38de61c > --- /dev/null > +++ b/gcc/testsuite/c-c++-common/torture/attr-sym-4.c > @@ -0,0 +1,28 @@ > +/* { dg-do run } */ > +/* { dg-require-alias "" } */ > + > +int var_a __attribute__ ((__sym__ ("FOOVAR_A"))) =3D 42; > + > +int __attribute__ ((__sym__ ("FOOBAR_A"))) > +foo_a (int p) > +{ > + return p; > +} > + > +extern int __attribute__ ((__alias__ (("FOOVAR_A")))) var_b; > +extern int __attribute__ ((__alias__ (("FOOBAR_A")))) foo_b (int p); > + > +int > +foo_c () > +{ > + return foo_b (var_b); > +} > + > +int > +main () > +{ > + if (foo_c () !=3D 42) > + __builtin_abort (); > + > + return 0; > +} > diff --git a/gcc/testsuite/g++.dg/torture/attr-sym-1.C b/gcc/testsuite/g+= +.dg/torture/attr-sym-1.C > new file mode 100644 > index 0000000000000..11aaabfa6599c > --- /dev/null > +++ b/gcc/testsuite/g++.dg/torture/attr-sym-1.C > @@ -0,0 +1,72 @@ > +/* { dg-do compile } */ > +/* { dg-require-alias "" } */ > + > +class __attribute__ ((__sym__ ("FOOCLS_A"), > + __sym__ ("FOOCLS_A_Dupe"))) foo { > + static int var __attribute__ ((__sym__ ("FOOVAR_A"))); > + __attribute__ ((__sym__ ("FOOCTR_A"))) foo (); > + void __attribute__ ((__sym__ ("FOOBAR_A"))) bar (); > + virtual __attribute__ ((__sym__ ("FOODTR_A"))) ~foo() {} > +}; > + > +int foo::var =3D 1; > + > +foo::foo () {} > + > +void foo::bar () {} > + > +namespace b { > + class __attribute__ ((__sym__ ("FOOCLS_B"))) foo { > + static int var __attribute__ ((__sym__ ("FOOVAR_B"))); > + __attribute__ ((__sym__ ("FOOCTR_B"))) foo (); > + void __attribute__ ((__sym__ ("FOOBAR_B"))) bar () {} > + virtual __attribute__ ((__sym__ ("FOODTR_B"))) ~foo() {} > + }; > + > + int foo::var =3D 2; > + > + foo::foo () { > + void (foo::*pbar)() =3D &foo::bar; > + } > +} > + > +namespace c { > + namespace cd { > + class __attribute__ ((__sym__ ("FOOCLS_C"))) foo { > + static int var __attribute__ ((__sym__ ("FOOVAR_C"))); > + __attribute__ ((__sym__ ("FOOCTR_C"))) foo () { > + void (foo::*pbar)() =3D &foo::bar; > + } > + void __attribute__ ((__sym__ ("FOOBAR_C"))) bar () {} > + virtual __attribute__ ((__sym__ ("FOODTR_C"))) ~foo() {} > + }; > + > + int foo::var =3D 3; > + } > +} > + > +/* { dg-final { scan-assembler "FOOCLS_A" } } */ > +/* { dg-final { scan-assembler "FOOCLS_A_Dupe" } } */ > +/* { dg-final { scan-assembler "FOOBAR_A" } } */ > +/* { dg-final { scan-assembler "FOOCTR_A" } } */ > +/* { dg-final { scan-assembler "FOOCTR_A_Base" } } */ > +/* { dg-final { scan-assembler "FOODTR_A" } } */ > +/* { dg-final { scan-assembler "FOODTR_A_Base" } } */ > +/* { dg-final { scan-assembler "FOODTR_A_Del" } } */ > +/* { dg-final { scan-assembler "FOOVAR_A" } } */ > +/* { dg-final { scan-assembler "FOOCLS_B" } } */ > +/* { dg-final { scan-assembler "FOOBAR_B" } } */ > +/* { dg-final { scan-assembler "FOOCTR_B" } } */ > +/* { dg-final { scan-assembler "FOOCTR_A_Base" } } */ > +/* { dg-final { scan-assembler "FOODTR_B" } } */ > +/* { dg-final { scan-assembler "FOODTR_B_Base" } } */ > +/* { dg-final { scan-assembler "FOODTR_B_Del" } } */ > +/* { dg-final { scan-assembler "FOOVAR_B" } } */ > +/* { dg-final { scan-assembler "FOOCLS_C" } } */ > +/* { dg-final { scan-assembler "FOOBAR_C" } } */ > +/* { dg-final { scan-assembler "FOOCTR_C" } } */ > +/* { dg-final { scan-assembler "FOOCTR_C_Base" } } */ > +/* { dg-final { scan-assembler "FOODTR_C" } } */ > +/* { dg-final { scan-assembler "FOODTR_C_Base" } } */ > +/* { dg-final { scan-assembler "FOODTR_C_Del" } } */ > +/* { dg-final { scan-assembler "FOOVAR_C" } } */ > diff --git a/gcc/testsuite/g++.dg/torture/attr-sym-2.C b/gcc/testsuite/g+= +.dg/torture/attr-sym-2.C > new file mode 100644 > index 0000000000000..f4714ea1ce5bd > --- /dev/null > +++ b/gcc/testsuite/g++.dg/torture/attr-sym-2.C > @@ -0,0 +1,26 @@ > +/* { dg-do compile } */ > +/* { dg-require-alias "" } */ > + > +namespace { > + class __attribute__ ((__sym__ ("FOOCLS_A"))) foo { > + static int var __attribute__ ((__sym__ ("FOOVAR_A"))); > + __attribute__ ((__sym__ ("FOOCTR_A"))) foo (); > + virtual __attribute__ ((__sym__ ("FOODTR_A"))) ~foo (); > + void __attribute__ ((__sym__ ("FOOBAR_A"))) bar (); > + }; > + > + int foo::var =3D 3; > + foo::foo () {} > + foo::~foo () {} > + void foo::bar () {} > +} > + > +/* { dg-final { scan-assembler-not "\.globl" } } */ > +/* { dg-final { scan-assembler "FOOCLS_A" } } */ > +/* { dg-final { scan-assembler "FOOBAR_A" } } */ > +/* { dg-final { scan-assembler "FOOCTR_A" } } */ > +/* { dg-final { scan-assembler "FOOCTR_A_Base" } } */ > +/* { dg-final { scan-assembler "FOODTR_A" } } */ > +/* { dg-final { scan-assembler "FOODTR_A_Base" } } */ > +/* { dg-final { scan-assembler "FOODTR_A_Del" } } */ > +/* { dg-final { scan-assembler "FOOVAR_A" } } */ > diff --git a/gcc/testsuite/g++.dg/torture/attr-sym-3.C b/gcc/testsuite/g+= +.dg/torture/attr-sym-3.C > new file mode 100644 > index 0000000000000..f819d5a02ce47 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/torture/attr-sym-3.C > @@ -0,0 +1,83 @@ > +/* { dg-do compile } */ > +/* { dg-require-alias "" } */ > + > +// sym can be applied to template function explicit instantiations. > + > +template > +void > +fn(T) { > +}; > + > +template void __attribute__ ((__sym__ ("FOOFUN_UINT"))) fn<>(unsigned in= t); > +template void __attribute__ ((__sym__ ("FOOFUN_LONG"))) fn<>(long); > + > +template<> void __attribute__ ((__sym__ ("FOOFUN_CHAR"))) fn<>(char) {} > + > + > +template > +struct > +foo { > + virtual ~foo() {} > + > + virtual void virtfun() {} > + > + static void stfun() {} > + void inlfun() {} > +}; > + > +// Explicitly instantiate members before the enclosing class. > + > +template void > +__attribute__ ((__sym__ ("FOOCLS_CHAR_VIRT"))) foo::virtfun(); > + > +template class __attribute__ ((__sym__ ("FOOCLS_CHAR_TI"))) foo; > + > +// Though they're only output if the enclosing class is. > +template void > +__attribute__ ((__sym__ ("FOOCLS_LONG_VIRT"))) foo::virtfun(); > +extern > +template class __attribute__ ((__sym__ ("FOOCLS_LONG_TI_X"))) foo; > + > + > +template void > +__attribute__ ((__sym__ ("FOOCLS_VOID_ST"))) foo::stfun(); > + > +template class __attribute__ ((__sym__ ("FOOCLS_VOID_TI"))) foo<>; > + > + > +extern > +template class __attribute__ ((__sym__ ("FOOCLS_SHORT_TI_X"))) foo; > + > +template void > +__attribute__ ((__sym__ ("FOOCLS_SHORT_ST"))) foo::stfun(); > +template void > +__attribute__ ((__sym__ ("FOOCLS_SHORT_INL"))) foo::inlfun(); > + > +template class __attribute__ ((__sym__ ("FOOCLS_SHORT_TI_D"))) foo; > + > +// Explicit specializations work too. > + > +template <> > +struct __attribute__ ((__sym__ ("FOOCLS_INT_TI"))) > +foo > +{ > + virtual ~foo() {} > + virtual void __attribute__ ((__sym__ ("FOOCLS_INT_VIRT"))) virtfun() {= } > +}; > + > +/* { dg-final { scan-assembler "FOOFUN_UINT" } } */ > +/* { dg-final { scan-assembler "FOOFUN_LONG" } } */ > +/* { dg-final { scan-assembler "FOOFUN_CHAR" } } */ > + > +/* { dg-final { scan-assembler "FOOCLS_VOID_TI" } } */ > +/* { dg-final { scan-assembler "FOOCLS_VOID_ST" } } */ > +/* { dg-final { scan-assembler "FOOCLS_CHAR_TI" } } */ > +/* { dg-final { scan-assembler "FOOCLS_CHAR_VIRT" } } */ > +/* { dg-final { scan-assembler "FOOCLS_SHORT_TI_X" } } */ > +/* { dg-final { scan-assembler "FOOCLS_SHORT_ST" } } */ > +/* { dg-final { scan-assembler "FOOCLS_SHORT_INL" } } */ > +/* { dg-final { scan-assembler "FOOCLS_SHORT_TI_D" } } */ > +/* { dg-final { scan-assembler-not "FOOCLS_LONG_TI_X" } } */ > +/* { dg-final { scan-assembler-not "FOOCLS_LONG_VIRT" } } */ > +/* { dg-final { scan-assembler "FOOCLS_INT_TI" } } */ > +/* { dg-final { scan-assembler "FOOCLS_INT_VIRT" } } */ > diff --git a/gcc/testsuite/g++.dg/torture/attr-sym-4.C b/gcc/testsuite/g+= +.dg/torture/attr-sym-4.C > new file mode 100644 > index 0000000000000..cc6a25a7962e6 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/torture/attr-sym-4.C > @@ -0,0 +1,28 @@ > +/* { dg-do compile } */ > +/* { dg-require-alias "" } */ > + > +template > +class > +__attribute__ ((__sym__ ("FOOCLS"))) > +foo // { dg-error "duplicate|already" } > +{ > + virtual ~foo() {} > + > + template > + void > + __attribute__ ((__sym__ ("FOOTMF"))) > + tmemfun () {} // { dg-error "duplicate|already" } > +}; > + > +template > +void > +__attribute__ ((__sym__ ("FOOTFN"))) > +fn(T) { // { dg-error "duplicate|already" } > +}; > + > +template class foo<>; > +template class foo; > +template void foo<>::tmemfun(); > +template void foo::tmemfun(); > +template void fn<>(int); > +template void fn<>(long); > diff --git a/gcc/testsuite/g++.dg/torture/attr-sym-5.C b/gcc/testsuite/g+= +.dg/torture/attr-sym-5.C > new file mode 100644 > index 0000000000000..2f79408b8d8ec > --- /dev/null > +++ b/gcc/testsuite/g++.dg/torture/attr-sym-5.C > @@ -0,0 +1,14 @@ > +/* { dg-do compile { target c++11 } } */ > +/* { dg-require-alias "" } */ > + > +struct foo { > + __attribute__ ((__sym__ ("FOOCTR_A"))) foo (); > + virtual __attribute__ ((__sym__ ("FOODTR_A"))) ~foo() {} > +}; > + > +foo::foo () {} > + > +// Make sure the inherited cdtors don't duplicate the syms. > +struct bar : foo { > + using foo::foo; > +}; > diff --git a/gcc/varpool.cc b/gcc/varpool.cc > index e7b51b15e4a84..33649906d1d11 100644 > --- a/gcc/varpool.cc > +++ b/gcc/varpool.cc > @@ -163,6 +163,9 @@ varpool_node::get_create (tree decl) > } > > node->register_symbol (); > + > + create_sym_alias_decls (decl); > + > return node; > } > > > > -- > Alexandre Oliva, happy hacker https://FSFLA.org/blogs/lxo/ > Free Software Activist GNU Toolchain Engineer > Disinformation flourishes because many people care deeply about injustice > but very few check the facts. Ask me about