From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lxmtout2.gsi.de (lxmtout2.gsi.de [140.181.3.112]) by sourceware.org (Postfix) with ESMTPS id 6F76E385BF9D; Tue, 4 May 2021 11:13:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 6F76E385BF9D Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=gsi.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=M.Kretz@gsi.de Received: from localhost (localhost [127.0.0.1]) by lxmtout2.gsi.de (Postfix) with ESMTP id 383C6202AD78; Tue, 4 May 2021 13:13:24 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at lxmtout2.gsi.de Received: from lxmtout2.gsi.de ([127.0.0.1]) by localhost (lxmtout2.gsi.de [127.0.0.1]) (amavisd-new, port 10024) with LMTP id vvpHFI8j0Ikz; Tue, 4 May 2021 13:13:24 +0200 (CEST) Received: from srvex1.campus.gsi.de (srvex1.campus.gsi.de [10.10.4.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) by lxmtout2.gsi.de (Postfix) with ESMTPS id 1A4AE202AD55; Tue, 4 May 2021 13:13:24 +0200 (CEST) Received: from excalibur.localnet (140.181.3.12) by srvex1.campus.gsi.de (10.10.4.11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2242.4; Tue, 4 May 2021 13:13:23 +0200 From: Matthias Kretz To: CC: Subject: [PATCH] Add gnu::diagnose_as attribute Date: Tue, 4 May 2021 13:13:23 +0200 Message-ID: <91863212.B8guWdUDZo@excalibur> Organization: GSI Helmholtzzentrum =?UTF-8?B?ZsO8cg==?= Schwerionenforschung In-Reply-To: <20210427094648.GL3008@redhat.com> References: <14205410.xuKvIAzr1H@excalibur> <20210427094648.GL3008@redhat.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="nextPart3957499.YAXv53MpCN" Content-Transfer-Encoding: 7Bit X-Originating-IP: [140.181.3.12] X-ClientProxiedBy: srvex3.Campus.gsi.de (10.10.4.16) To srvex1.campus.gsi.de (10.10.4.11) X-Spam-Status: No, score=-12.5 required=5.0 tests=BAYES_00, BODY_8BITS, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_PASS, TXREP, T_SPF_HELO_PERMERROR autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 04 May 2021 11:13:28 -0000 --nextPart3957499.YAXv53MpCN Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="UTF-8" =46rom: Matthias Kretz This attribute overrides the diagnostics output string for the entity it appertains to. The motivation is to improve QoI for library TS implementations, where diagnostics have a very bad signal-to-noise ratio due to the long namespaces involved. On Tuesday, 27 April 2021 11:46:48 CEST Jonathan Wakely wrote: > I think it's a great idea and would like to use it for all the TS > implementations where there is some inline namespace that the user > doesn't care about. std::experimental::fundamentals_v1:: would be much > better as just std::experimental::, or something like std::[LFTS]::. With the attribute, it is possible to solve PR89370 and make std::__cxx11::basic_string<_CharT, _Traits, _Alloc> appear as std::string in diagnostic output without extra hacks to recognize the type. gcc/ChangeLog: PR c++/89370 * doc/extend.texi: Document the diagnose_as attribute. * doc/invoke.texi: Document -fno-diagnostics-use-aliases. gcc/c-family/ChangeLog: PR c++/89370 * c.opt (fdiagnostics-use-aliases): New diagnostics flag. gcc/cp/ChangeLog: PR c++/89370 * error.c (dump_scope): When printing the name of a namespace, look for the diagnose_as attribute. If found, print the associated string instead of calling dump_decl. (dump_decl_name_or_diagnose_as): New function to replace dump_decl (pp, DECL_NAME(t), flags) and inspect the tree for the diagnose_as attribute before printing the DECL_NAME. (dump_aggr_type): If the type has a diagnose_as attribute, print the associated string instead of printing the original type name. (dump_simple_decl): Call dump_decl_name_or_diagnose_as instead of dump_decl. (dump_decl): Ditto. (lang_decl_name): Ditto. (dump_function_decl): Ensure complete replacement of the class template diagnostics if a diagnose_as attribute is present. (dump_function_name): Replace the function diagnostic output if the diagnose_as attribute is set. * name-lookup.c (handle_namespace_attrs): Handle the diagnose_as attribute. Ensure exactly one string argument. Ensure previous diagnose_as attributes used the same name. * tree.c (cxx_attribute_table): Add diagnose_as attribute to the table. (check_diagnose_as_redeclaration): New function; copied and adjusted from check_abi_tag_redeclaration. (handle_diagnose_as_attribute): New function; copied and adjusted from handle_abi_tag_attribute. If the given *node is a TYPE_DECL and the TREE_TYPE is an implicit class template instantiation, call decl_attributes to add the diagnose_as attribute to the TREE_TYPE. =2D-- gcc/c-family/c.opt | 4 ++ gcc/cp/error.c | 85 ++++++++++++++++++++++++++++--- gcc/cp/name-lookup.c | 27 ++++++++++ gcc/cp/tree.c | 117 +++++++++++++++++++++++++++++++++++++++++++ gcc/doc/extend.texi | 37 ++++++++++++++ gcc/doc/invoke.texi | 9 +++- 6 files changed, 270 insertions(+), 9 deletions(-) =2D- =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80 Dr. Matthias Kretz https://mattkretz.github.io GSI Helmholtz Centre for Heavy Ion Research https://gsi.de std::experimental::simd https://github.com/VcDevel/std-simd =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80 --nextPart3957499.YAXv53MpCN Content-Disposition: inline; filename="0001-Add-gnu-diagnose_as-attribute.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="utf-8"; name="0001-Add-gnu-diagnose_as-attribute.patch" diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 3f8b72cdc00..0cf01c6dba4 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -1582,6 +1582,10 @@ fdiagnostics-show-template-tree C++ ObjC++ Var(flag_diagnostics_show_template_tree) Init(0) Print hierarchical comparisons when template types are mismatched. +fdiagnostics-use-aliases +C++ Var(flag_diagnostics_use_aliases) Init(1) +Replace identifiers or scope names in diagnostics as defined by the diagnose_as attribute. + fdirectives-only C ObjC C++ ObjC++ Preprocess directives only. diff --git a/gcc/cp/error.c b/gcc/cp/error.c index c88d1749a0f..10b547afaa7 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see #include "internal-fn.h" #include "gcc-rich-location.h" #include "cp-name-hint.h" +#include "attribs.h" #define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',') #define pp_separate_with_semicolon(PP) pp_cxx_separate_with (PP, ';') @@ -66,6 +67,7 @@ static void dump_alias_template_specialization (cxx_pretty_printer *, tree, int) static void dump_type (cxx_pretty_printer *, tree, int); static void dump_typename (cxx_pretty_printer *, tree, int); static void dump_simple_decl (cxx_pretty_printer *, tree, tree, int); +static void dump_decl_name_or_diagnose_as (cxx_pretty_printer *, tree, int); static void dump_decl (cxx_pretty_printer *, tree, int); static void dump_template_decl (cxx_pretty_printer *, tree, int); static void dump_function_decl (cxx_pretty_printer *, tree, int); @@ -231,7 +233,15 @@ dump_scope (cxx_pretty_printer *pp, tree scope, int flags) { if (scope != global_namespace) { - dump_decl (pp, scope, f); + tree diagnose_as + = flag_diagnostics_use_aliases + ? lookup_attribute ("diagnose_as", DECL_ATTRIBUTES (scope)) + : NULL_TREE; + if (diagnose_as) + pp_cxx_ws_string ( + pp, TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (diagnose_as)))); + else + dump_decl (pp, scope, f); pp_cxx_colon_colon (pp); } } @@ -743,6 +753,7 @@ dump_aggr_type (cxx_pretty_printer *pp, tree t, int flags) tree decl = TYPE_NAME (t); + tree diagnose_as = NULL_TREE; if (decl) { typdef = (!DECL_ARTIFICIAL (decl) @@ -769,8 +780,15 @@ dump_aggr_type (cxx_pretty_printer *pp, tree t, int flags) if (! (flags & TFF_UNQUALIFIED_NAME)) dump_scope (pp, CP_DECL_CONTEXT (decl), flags | TFF_SCOPE); flags &= ~TFF_UNQUALIFIED_NAME; + + tree diagnose_as_specialized = NULL_TREE; if (tmplate) { + if (flag_diagnostics_use_aliases) + diagnose_as_specialized + = lookup_attribute ("diagnose_as", + TYPE_ATTRIBUTES (TREE_TYPE (decl))); + /* Because the template names are mangled, we have to locate the most general template, and use that name. */ tree tpl = TYPE_TI_TEMPLATE (t); @@ -779,9 +797,25 @@ dump_aggr_type (cxx_pretty_printer *pp, tree t, int flags) tpl = DECL_TI_TEMPLATE (tpl); decl = tpl; } + + if (flag_diagnostics_use_aliases) + diagnose_as = lookup_attribute ("diagnose_as", + TYPE_ATTRIBUTES (TREE_TYPE (decl))); + if (diagnose_as_specialized + && (!diagnose_as || TREE_VALUE(diagnose_as_specialized) + != TREE_VALUE(diagnose_as))) + { + pp_cxx_ws_string ( + pp, TREE_STRING_POINTER ( + TREE_VALUE (TREE_VALUE (diagnose_as_specialized)))); + return; + } } - if (LAMBDA_TYPE_P (t)) + if (diagnose_as) + pp_cxx_ws_string (pp, TREE_STRING_POINTER ( + TREE_VALUE (TREE_VALUE (diagnose_as)))); + else if (LAMBDA_TYPE_P (t)) { /* A lambda's "type" is essentially its signature. */ pp_string (pp, M_(""); } else - dump_decl (pp, DECL_NAME (t), flags); + dump_decl_name_or_diagnose_as (pp, t, flags); } else if (DECL_DECOMPOSITION_P (t)) pp_string (pp, M_("")); @@ -1147,6 +1181,25 @@ dump_decl_name (cxx_pretty_printer *pp, tree t, int flags) pp_cxx_tree_identifier (pp, t); } +/* Print the DECL_NAME of DECL unless a different string was requested by the + diagnose_as attribute. */ + +static void +dump_decl_name_or_diagnose_as (cxx_pretty_printer *pp, tree decl, int flags) +{ + if (flag_diagnostics_use_aliases) + { + tree attr = lookup_attribute ("diagnose_as", DECL_ATTRIBUTES (decl)); + if (attr) + { + pp_cxx_ws_string ( + pp, TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)))); + return; + } + } + dump_decl_name (pp, DECL_NAME (decl), flags); +} + /* Dump a human readable string for the decl T under control of FLAGS. */ static void @@ -1192,7 +1245,7 @@ dump_decl (cxx_pretty_printer *pp, tree t, int flags) || flags & TFF_CLASS_KEY_OR_ENUM)) { pp_cxx_ws_string (pp, "using"); - dump_decl (pp, DECL_NAME (t), flags); + dump_decl_name_or_diagnose_as(pp, t, flags); pp_cxx_whitespace (pp); pp_cxx_ws_string (pp, "="); pp_cxx_whitespace (pp); @@ -1374,7 +1427,7 @@ dump_decl (cxx_pretty_printer *pp, tree t, int flags) TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_PARM_INDEX)) dump_simple_decl (pp, t, TREE_TYPE (t), flags); else if (DECL_NAME (t)) - dump_decl (pp, DECL_NAME (t), flags); + dump_decl_name_or_diagnose_as (pp, t, flags); else if (DECL_INITIAL (t)) dump_expr (pp, DECL_INITIAL (t), flags | TFF_EXPR_IN_PARENS); else @@ -1393,7 +1446,7 @@ dump_decl (cxx_pretty_printer *pp, tree t, int flags) } dump_type (pp, scope, flags); pp_cxx_colon_colon (pp); - dump_decl (pp, DECL_NAME (t), flags); + dump_decl_name_or_diagnose_as (pp, t, flags); if (variadic) pp_cxx_ws_string (pp, "..."); } @@ -1657,7 +1710,13 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags) /* Pretty print template instantiations only. */ if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t) && !(flags & TFF_NO_TEMPLATE_BINDINGS) - && flag_pretty_templates) + && flag_pretty_templates + // skip the output of template parameters if the function is a member of a + // class with diagnose_as attribute: + && !(flag_diagnostics_use_aliases + && DECL_CLASS_SCOPE_P (t) + && lookup_attribute ("diagnose_as", + TYPE_ATTRIBUTES (DECL_CONTEXT (t))))) { tree tmpl; @@ -1885,6 +1944,16 @@ dump_exception_spec (cxx_pretty_printer *pp, tree t, int flags) static void dump_function_name (cxx_pretty_printer *pp, tree t, int flags) { + if (flag_diagnostics_use_aliases) + { + tree attr = lookup_attribute ("diagnose_as", DECL_ATTRIBUTES (t)); + if (attr) + { + pp_cxx_ws_string ( + pp, TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)))); + return; + } + } tree name = DECL_NAME (t); /* We can get here with a decl that was synthesized by language- @@ -3133,7 +3202,7 @@ lang_decl_name (tree decl, int v, bool translate) && TREE_CODE (decl) == NAMESPACE_DECL) dump_decl (cxx_pp, decl, TFF_PLAIN_IDENTIFIER | TFF_UNQUALIFIED_NAME); else - dump_decl (cxx_pp, DECL_NAME (decl), TFF_PLAIN_IDENTIFIER); + dump_decl_name_or_diagnose_as (cxx_pp, decl, TFF_PLAIN_IDENTIFIER); return pp_ggc_formatted_text (cxx_pp); } diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 4e84e2f9987..80637503310 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -6082,6 +6082,33 @@ handle_namespace_attrs (tree ns, tree attributes) DECL_ATTRIBUTES (ns) = tree_cons (name, args, DECL_ATTRIBUTES (ns)); } + else if (is_attribute_p ("diagnose_as", name)) + { + if (!args || TREE_CHAIN(args)) + { + error ("the %qE attribute requires exactly one argument", name); + continue; + } + if (TREE_CODE (TREE_VALUE (args)) != STRING_CST) + { + error ("the argument to the %qE attribute must be a string " + "literal", name); + continue; + } + tree existing + = lookup_attribute ("diagnose_as", DECL_ATTRIBUTES (ns)); + if (existing + && !cp_tree_equal(TREE_VALUE (args), + TREE_VALUE (TREE_VALUE (existing)))) + { + error ("the namespace %qE already uses a different diagnose_as " + "attribute value", ns); + inform (DECL_SOURCE_LOCATION (ns), "previous declaration here"); + continue; + } + DECL_ATTRIBUTES (ns) = tree_cons (name, args, + DECL_ATTRIBUTES (ns)); + } else { warning (OPT_Wattributes, "%qD attribute directive ignored", diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index a8bfd5fc053..f7b93dc89d7 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -46,6 +46,7 @@ static tree verify_stmt_tree_r (tree *, int *, void *); static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *); static tree handle_abi_tag_attribute (tree *, tree, tree, int, bool *); +static tree handle_diagnose_as_attribute (tree *, tree, tree, int, bool *); /* If REF is an lvalue, returns the kind of lvalue that REF is. Otherwise, returns clk_none. */ @@ -4860,6 +4861,8 @@ const struct attribute_spec cxx_attribute_table[] = handle_init_priority_attribute, NULL }, { "abi_tag", 1, -1, false, false, false, true, handle_abi_tag_attribute, NULL }, + { "diagnose_as", 1, 1, false, false, false, false, + handle_diagnose_as_attribute, NULL }, { NULL, 0, 0, false, false, false, false, NULL, NULL } }; @@ -5128,6 +5131,120 @@ handle_abi_tag_attribute (tree* node, tree name, tree args, return NULL_TREE; } +static bool +check_diagnose_as_redeclaration (const_tree decl, const_tree old, + const_tree new_) +{ + if (!old) + return true; + if (TREE_CODE (TREE_VALUE (old)) == TREE_LIST) + old = TREE_VALUE (old); + if (TREE_CODE (TREE_VALUE (new_)) == TREE_LIST) + new_ = TREE_VALUE (new_); + tree old_value = TREE_VALUE (old); + tree new_value = TREE_VALUE (new_); + if (cp_tree_equal (old_value, new_value)) + return true; + error ("conflicting declaration of % attribute on %qD would " + "overwrite %qE with %qE", decl, old_value, new_value); + return false; +} + +static tree +handle_diagnose_as_attribute (tree* node, tree name, tree args, + int flags, bool* no_add_attrs) +{ + tree decl = NULL_TREE; + if (!args || TREE_CHAIN (args)) + { + error ("the %qE attribute requires exactly one argument", name); + goto fail; + } + if (TREE_CODE (TREE_VALUE (args)) != STRING_CST) + { + error ("the argument to the %qE attribute must be a string literal", + name); + goto fail; + } + if (TREE_CODE (*node) == TYPE_DECL) + { + // Apply the attribute to the type alias itself. + decl = *node; + tree type = TREE_TYPE (*node); + if (CLASS_TYPE_P (type) && CLASSTYPE_IMPLICIT_INSTANTIATION (type)) + { + if (COMPLETE_OR_OPEN_TYPE_P (type)) + warning (OPT_Wattributes, "%qE attribute cannot be applied to %qT " + "after its instantiation", name, type); + else + { + type = strip_typedefs(type, nullptr, 0); + // And apply the attribute to the specialization on the RHS. + tree attributes = tree_cons (name, args, NULL_TREE); + decl_attributes (&type, attributes, + ATTR_FLAG_TYPE_IN_PLACE, NULL_TREE); + } + } + } + else if (TYPE_P (*node)) + { + if (!OVERLOAD_TYPE_P (*node)) + { + error ("%qE attribute applied to non-class, non-enum type %qT", + name, *node); + goto fail; + } + else if (!(flags & (int)ATTR_FLAG_TYPE_IN_PLACE)) + { + error ("%qE attribute applied to %qT after its definition", + name, *node); + goto fail; + } + decl = TYPE_NAME (*node); + } + else + { + if (!VAR_OR_FUNCTION_DECL_P (*node)) + { + error ("%qE attribute applied to non-function, non-variable %qD", + name, *node); + goto fail; + } + else if (DECL_LANGUAGE (*node) == lang_c) + { + error ("%qE attribute applied to extern \"C\" declaration %qD", + name, *node); + goto fail; + } + decl = *node; + } + + // Make sure all declarations have the same diagnose_as string. + if (DECL_SOURCE_LOCATION (decl) != input_location) + { + tree attributes = TYPE_P (*node) ? TYPE_ATTRIBUTES (*node) + : DECL_ATTRIBUTES (decl); + if (!check_diagnose_as_redeclaration ( + decl, lookup_attribute ("diagnose_as", attributes), args)) + goto fail; + } + else if (CLASS_TYPE_P (*node) && CLASSTYPE_IMPLICIT_INSTANTIATION (*node)) + { + // The above branch (different source location) is taken for declarations + // of type aliases that modify an implicit template specialization on the + // RHS. This branch is taken when the template is instantiated via + // instantiate_class_template_1, in which case the attribute either + // already has the value from the general template or from a type alias. + goto fail; + } + + return NULL_TREE; + + fail: + *no_add_attrs = true; + return NULL_TREE; +} + /* Return a new PTRMEM_CST of the indicated TYPE. The MEMBER is the thing pointed to by the constant. */ diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index c8caf36f293..7976e3a72d4 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -2865,6 +2865,43 @@ types (@pxref{Variable Attributes}, @pxref{Type Attributes}.) The message attached to the attribute is affected by the setting of the @option{-fmessage-length} option. +@item diagnose_as ("@var{string}") +@cindex @code{diagnose_as} function attribute +The @code{diagnose_as} attribute modifies how the entity the attribute +appertains to is diagnosed in compiler messages and __FUNCTION__ / +__PRETTY_FUNCTION__ macros. If the attribute is applied to a @code{namespace}, +the specified string replaces the complete enclosing scope. The effect of the +@code{diagnose_as} attribute can be disabled with the +@option{-fno-diagnostics-use-aliases} command line option. + +@smallexample +namespace Foo @{ + namespace Bar @{ + inline namespace v1 [[gnu::diagnose_as("Foobar")]] @{ + int f() @{ + // __PRETTY_FUNCTION__ == "void Foobar::f()" + @} + @} + @} +@} +// In function 'int Foobar::f()': +// warning: no return statement in function returning non-void [-Wreturn-type] +@end smallexample + +The @code{diagnose_as} attribute can be used with namespaces, functions, +variables, alias declarations (but not alias templates), and user-defined types +(classes, unions, and enums). If the alias declaration aliases an implicit class +template specialization, the attribute is additionally applied to the class +template specialization. + +@smallexample +template struct basic_string @{@}; +using string [[gnu::diagnose_as("string")]] = basic_string; +int f(basic_string) @{@} +// In function 'int f(string)': +// warning: no return statement in function returning non-void [-Wreturn-type] +@end smallexample + @item error ("@var{message}") @itemx warning ("@var{message}") @cindex @code{error} function attribute diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index f5a9dc33819..84c19344c89 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -311,7 +311,8 @@ Objective-C and Objective-C++ Dialects}. -fdiagnostics-show-path-depths @gol -fno-show-column @gol -fdiagnostics-column-unit=@r{[}display@r{|}byte@r{]} @gol --fdiagnostics-column-origin=@var{origin}} +-fdiagnostics-column-origin=@var{origin} @gol +-fno-diagnostics-aliases} @item Warning Options @xref{Warning Options,,Options to Request or Suppress Warnings}. @@ -5077,6 +5078,12 @@ first column. The default value of 1 corresponds to traditional GCC behavior and to the GNU style guide. Some utilities may perform better with an origin of 0; any non-negative value may be specified. +@item -fno-diagnostics-use-aliases +@opindex fno-diagnostics-use-aliases +@opindex fdiagnostics-use-aliases +Do not replace identifiers or scope names with the aliases defined with the +@code{[[gnu::diagnose_as("alias")]]} attribute. + @item -fdiagnostics-format=@var{FORMAT} @opindex fdiagnostics-format Select a different format for printing diagnostics. --nextPart3957499.YAXv53MpCN--