From 5075d2ac12f655f8f83f6f3be27e2c1141e1ce99 Mon Sep 17 00:00:00 2001 From: Bernhard Reutner-Fischer Date: Sun, 20 Nov 2022 18:06:04 +0100 Subject: [PATCH] c++: Set the locus of the function result decl To: gcc-patches@gcc.gnu.org gcc/cp/ChangeLog: * decl.cc (grokdeclarator): Build RESULT_DECL. (start_preparsed_function): Copy location from template. gcc/ChangeLog: * function.cc (init_function_start): Use DECL_RESULT location for -Waggregate-return warning. * ipa-pure-const.cc (suggest_attribute): Add fixit-hint for the noreturn attribute. gcc/testsuite/ChangeLog: * c-c++-common/pr68833-1.c: Adjust noreturn warning line number. * gcc.dg/noreturn-1.c: Likewise. * g++.dg/diagnostic/return-type-loc1.C: New test. * g++.dg/other/resultdecl-1.C: New test. Co-authored-by: Jason Merrill --- gcc/cp/decl.cc | 26 +++++++++++++-- gcc/function.cc | 3 +- gcc/ipa-pure-const.cc | 14 +++++++- gcc/testsuite/c-c++-common/pr68833-1.c | 2 +- .../g++.dg/diagnostic/return-type-loc1.C | 20 ++++++++++++ gcc/testsuite/g++.dg/other/resultdecl-1.C | 32 +++++++++++++++++++ gcc/testsuite/gcc.dg/noreturn-1.c | 2 +- 7 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/diagnostic/return-type-loc1.C create mode 100644 gcc/testsuite/g++.dg/other/resultdecl-1.C diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 544efdc9914..2c5cd930e0a 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -14774,6 +14774,18 @@ grokdeclarator (const cp_declarator *declarator, else if (constinit_p) DECL_DECLARED_CONSTINIT_P (decl) = true; } + else if (TREE_CODE (decl) == FUNCTION_DECL) + { + location_t loc = smallest_type_location (declspecs); + if (loc != UNKNOWN_LOCATION) + { + tree restype = TREE_TYPE (TREE_TYPE (decl)); + tree resdecl = build_decl (loc, RESULT_DECL, 0, restype); + DECL_ARTIFICIAL (resdecl) = 1; + DECL_IGNORED_P (resdecl) = 1; + DECL_RESULT (decl) = resdecl; + } + } /* Record constancy and volatility on the DECL itself . There's no need to do this when processing a template; we'll do this @@ -17328,9 +17340,19 @@ start_preparsed_function (tree decl1, tree attrs, int flags) if (DECL_RESULT (decl1) == NULL_TREE) { - tree resdecl; + /* In a template instantiation, copy the return type location. When + parsing, the location will be set in grokdeclarator. */ + location_t loc = input_location; + if (DECL_TEMPLATE_INSTANTIATION (decl1) + && !DECL_CXX_CONSTRUCTOR_P (decl1) + && !DECL_CXX_DESTRUCTOR_P (decl1)) + { + tree tmpl = template_for_substitution (decl1); + tree res = DECL_RESULT (DECL_TEMPLATE_RESULT (tmpl)); + loc = DECL_SOURCE_LOCATION (res); + } - resdecl = build_decl (input_location, RESULT_DECL, 0, restype); + tree resdecl = build_decl (loc, RESULT_DECL, 0, restype); DECL_ARTIFICIAL (resdecl) = 1; DECL_IGNORED_P (resdecl) = 1; DECL_RESULT (decl1) = resdecl; diff --git a/gcc/function.cc b/gcc/function.cc index 9c8773bbc59..dc333c27e92 100644 --- a/gcc/function.cc +++ b/gcc/function.cc @@ -4997,7 +4997,8 @@ init_function_start (tree subr) /* Warn if this value is an aggregate type, regardless of which calling convention we are using for it. */ if (AGGREGATE_TYPE_P (TREE_TYPE (DECL_RESULT (subr)))) - warning (OPT_Waggregate_return, "function returns an aggregate"); + warning_at (DECL_SOURCE_LOCATION (DECL_RESULT (subr)), + OPT_Waggregate_return, "function returns an aggregate"); } /* Expand code to verify the stack_protect_guard. This is invoked at diff --git a/gcc/ipa-pure-const.cc b/gcc/ipa-pure-const.cc index 572a6da274f..8f6e8f63d91 100644 --- a/gcc/ipa-pure-const.cc +++ b/gcc/ipa-pure-const.cc @@ -63,6 +63,7 @@ along with GCC; see the file COPYING3. If not see #include "ipa-fnsummary.h" #include "symtab-thunks.h" #include "dbgcnt.h" +#include "gcc-rich-location.h" /* Lattice values for const and pure functions. Everything starts out being const, then may drop to pure and then neither depending on @@ -212,7 +213,18 @@ suggest_attribute (int option, tree decl, bool known_finite, if (warned_about->contains (decl)) return warned_about; warned_about->add (decl); - warning_at (DECL_SOURCE_LOCATION (decl), + + gcc_rich_location richloc (option == OPT_Wsuggest_attribute_noreturn + ? DECL_SOURCE_LOCATION (DECL_RESULT (decl)) + : DECL_SOURCE_LOCATION (decl)); + if (option == OPT_Wsuggest_attribute_noreturn) + { + richloc.add_fixit_replace + (IDENTIFIER_POINTER (TYPE_IDENTIFIER (void_type_node))); + richloc.add_fixit_insert_before (DECL_SOURCE_LOCATION (decl), + " __attribute__((__noreturn__)) "); + } + warning_at (&richloc, option, known_finite ? G_("function might be candidate for attribute %qs") diff --git a/gcc/testsuite/c-c++-common/pr68833-1.c b/gcc/testsuite/c-c++-common/pr68833-1.c index a6aefad5c98..b27b783d61a 100644 --- a/gcc/testsuite/c-c++-common/pr68833-1.c +++ b/gcc/testsuite/c-c++-common/pr68833-1.c @@ -15,7 +15,7 @@ f1 (const char *fmt) extern void f2 (void); void -f2 (void) /* { dg-error "candidate for attribute 'noreturn'" "detect noreturn candidate" } */ +f2 (void) /* { dg-error "candidate for attribute 'noreturn'" "detect noreturn candidate" { target *-*-* } .-1 } */ { __builtin_exit (0); } diff --git a/gcc/testsuite/g++.dg/diagnostic/return-type-loc1.C b/gcc/testsuite/g++.dg/diagnostic/return-type-loc1.C new file mode 100644 index 00000000000..f96179ed4d5 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/return-type-loc1.C @@ -0,0 +1,20 @@ +// { dg-do compile { target c++11 } } +// { dg-additional-options -Waggregate-return } + +struct B { int i,j; }; + +template +struct A +{ + template + U // { dg-warning "aggregate" } + f() { return {}; } +}; + +int main() +{ + A().f(); // { dg-warning "aggregate" } +} + +B // { dg-warning "aggregate" } +g() { return {}; } diff --git a/gcc/testsuite/g++.dg/other/resultdecl-1.C b/gcc/testsuite/g++.dg/other/resultdecl-1.C new file mode 100644 index 00000000000..e3951c339a9 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/resultdecl-1.C @@ -0,0 +1,32 @@ +/* Verify correct result decl location. */ +// { dg-options "-fdiagnostics-generate-patch -O1 -fipa-pure-const -Wsuggest-attribute=noreturn" } +// +// foo4: rem int, add: void attribute((noreturn)) + + + +int +foo4(void) +{ while (1); } + + +#if 0 +// { dg-warning "function might be candidate for attribute .noreturn." "" { target *-*-* } .-6 } // the fnname is at line .-5 though +// prune the diff path.. +/* { dg-regexp "\\-\\-\\- .*" } */ +/* { dg-regexp "\\+\\+\\+ .*" } */ +{ dg-begin-multiline-output "" } +@@ -5,8 +5,8 @@ + + + +-int +-foo4(void) ++void ++ __attribute__((__noreturn__)) foo4(void) + { while (1); } + + +{ dg-end-multiline-output "" } +#endif + diff --git a/gcc/testsuite/gcc.dg/noreturn-1.c b/gcc/testsuite/gcc.dg/noreturn-1.c index cdbfb8dd667..a713ee924fc 100644 --- a/gcc/testsuite/gcc.dg/noreturn-1.c +++ b/gcc/testsuite/gcc.dg/noreturn-1.c @@ -25,7 +25,7 @@ foo3(void) extern void foo4(void); void -foo4(void) /* { dg-warning "candidate for attribute 'noreturn'" "detect noreturn candidate" } */ +foo4(void) /* { dg-warning "candidate for attribute 'noreturn'" "detect noreturn candidate" { target *-*-* } .-1 } */ { exit(0); } -- 2.31.1