From: Lewis Hyatt <lhyatt@gmail.com>
To: Richard Biener <richard.guenther@gmail.com>
Cc: Jan Hubicka <hubicka@ucw.cz>, gcc-patches@gcc.gnu.org
Subject: Re: [PATCH] diagnostics: Allow FEs to keep customizations for middle end [PR101551, PR106274]
Date: Thu, 3 Nov 2022 16:07:04 -0400 [thread overview]
Message-ID: <20221103200704.GA86831@ldh-imac.local> (raw)
In-Reply-To: <CAFiYyc3zvMGT1ukYoqiJJQtj=437LPts1B5RtGKZf3HmUcQxag@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2889 bytes --]
On Fri, Oct 28, 2022 at 10:28:21AM +0200, Richard Biener wrote:
> Yes, the idea was also to free up memory but then that part never
> really materialized - the idea was to always run free-lang-data, not
> just when later outputting LTO bytecode. The reason is probably
> mainly the diagnostic regressions you observe.
>
> Maybe a better strathegy than your patch would be to work towards
> that goal but reduce the number of "freeings", instead adjusting the
> LTO streamer to properly ignore frontend specific bits where clearing
> conflicts with the intent to preserve accurate diagnostics throughout
> the compilation.
>
> If you see bits that when not freed would fix some of the observed
> issues we can see to replicate the freeing in the LTO output machinery.
>
> Richard.
Thanks again for the suggestions. I took a look and it seems pretty doable to
just stop resetting all the diagnostics hooks in free-lang-data. Once that's
done, the only problematic part that I have been able to identify is here in
ipa-free-lang-data.c around line 674:
====
/* We need to keep field decls associated with their trees. Otherwise tree
merging may merge some fields and keep others disjoint which in turn will
not do well with TREE_CHAIN pointers linking them.
Also do not drop containing types for virtual methods and tables because
these are needed by devirtualization.
C++ destructors are special because C++ frontends sometimes produces
virtual destructor as an alias of non-virtual destructor. In
devirutalization code we always walk through aliases and we need
context to be preserved too. See PR89335 */
if (TREE_CODE (decl) != FIELD_DECL
&& ((TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
|| (!DECL_VIRTUAL_P (decl)
&& (TREE_CODE (decl) != FUNCTION_DECL
|| !DECL_CXX_DESTRUCTOR_P (decl)))))
DECL_CONTEXT (decl) = fld_decl_context (DECL_CONTEXT (decl));
====
The C++ implementations of the decl_printable_name langhook and the diagnostic
starter callback do not work as-is when the DECL_CONTEXT for class member
functions disappears. So I did have a patch that changes the C++
implementations to work in this case, but attached here is a new one along the
lines of what you suggested, rather changing the above part of free-lang-data
so it doesn't activate as often. The patch is pretty complete (other than
missing a commit message) and bootstrap + regtest all languages looks good
with no regressions. I tried the same with BUILD_CONFIG=bootstrap-lto as well,
and that also looked good when it eventually finished. I added testcases for
several frontends to verify that the diagnostics still work with -flto. I am
not sure what are the implications for LTO itself, of changing this part of
the pass, so I would have to ask you to weigh in on that aspect please. Thanks!
-Lewis
[-- Attachment #2: free-lang-data-diag.txt --]
[-- Type: text/plain, Size: 17061 bytes --]
[PATCH] middle-end: Preserve frontend diagnostics in free-lang-data [PR101551, PR106274]
gcc/ChangeLog:
PR lto/106274
PR middle-end/101551
* ipa-free-lang-data.cc (free_lang_data_in_decl): Preserve
DECL_CONTEXT for class member functions.
(free_lang_data): Do not reset frontend diagnostics customizations.
gcc/testsuite/ChangeLog:
PR lto/106274
PR middle-end/101551
* c-c++-common/diag-after-fld-1.c: New test.
* g++.dg/diag-after-fld-1.C: New test.
* g++.dg/diag-after-fld-2.C: New test.
* gfortran.dg/allocatable_uninitialized_2.f90: New test.
* objc.dg/diag-after-fld-1.m: New test.
diff --git a/gcc/ipa-free-lang-data.cc b/gcc/ipa-free-lang-data.cc
index ccdbf849c25..391b7689639 100644
--- a/gcc/ipa-free-lang-data.cc
+++ b/gcc/ipa-free-lang-data.cc
@@ -682,10 +682,8 @@ free_lang_data_in_decl (tree decl, class free_lang_data_d *fld)
devirutalization code we always walk through aliases and we need
context to be preserved too. See PR89335 */
if (TREE_CODE (decl) != FIELD_DECL
- && ((TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
- || (!DECL_VIRTUAL_P (decl)
- && (TREE_CODE (decl) != FUNCTION_DECL
- || !DECL_CXX_DESTRUCTOR_P (decl)))))
+ && TREE_CODE (decl) != VAR_DECL
+ && TREE_CODE (decl) != FUNCTION_DECL)
DECL_CONTEXT (decl) = fld_decl_context (DECL_CONTEXT (decl));
}
@@ -1115,7 +1113,6 @@ free_lang_data (void)
/* Reset some langhooks. Do not reset types_compatible_p, it may
still be used indirectly via the get_alias_set langhook. */
lang_hooks.dwarf_name = lhd_dwarf_name;
- lang_hooks.decl_printable_name = gimple_decl_printable_name;
lang_hooks.gimplify_expr = lhd_gimplify_expr;
lang_hooks.overwrite_decl_assembler_name = lhd_overwrite_decl_assembler_name;
lang_hooks.print_xnode = lhd_print_tree_nothing;
@@ -1141,9 +1138,6 @@ free_lang_data (void)
make sure we never call decl_assembler_name on local symbols and
devise a separate, middle-end private scheme for it. */
- /* Reset diagnostic machinery. */
- tree_diagnostics_defaults (global_dc);
-
rebuild_type_inheritance_graph ();
delete fld_incomplete_types;
diff --git a/gcc/testsuite/c-c++-common/diag-after-fld-1.c b/gcc/testsuite/c-c++-common/diag-after-fld-1.c
new file mode 100644
index 00000000000..c1fc87a03f3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/diag-after-fld-1.c
@@ -0,0 +1,25 @@
+/* Make sure that post-ipa-free-lang-data diagnostics expand macros as
+ expected. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target lto } */
+/* { dg-options "-flto -O2 -Wnonnull-compare" } */
+
+#define X(p) p == 0 /* { dg-warning {-Wnonnull-compare} } */
+int f (void *) __attribute__((nonnull));
+int f (void *p)
+{
+ return X (p); /* { dg-note {in expansion of macro 'X'} } */
+}
+
+#define X2(p) p == 0 /* { dg-warning {-Wnonnull-compare} } */
+#define Y2(p) X2(p) /* { dg-note {in expansion of macro 'X2'} } */
+
+#define MAKE_F2 \
+ int f2 (void *) __attribute__((nonnull)); \
+ int f2 (void *p) \
+ { \
+ return Y2 (p); /* { dg-note {in expansion of macro 'Y2'} } */ \
+ }
+
+MAKE_F2 /* { dg-note {in expansion of macro 'MAKE_F2'} } */
diff --git a/gcc/testsuite/g++.dg/diag-after-fld-1.C b/gcc/testsuite/g++.dg/diag-after-fld-1.C
new file mode 100644
index 00000000000..0f8d10b7848
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diag-after-fld-1.C
@@ -0,0 +1,470 @@
+/* Based on 20090121-1.C; verify these middle-end diagnostics work fine after
+ ipa-free-lang data pass. Try to exercise most code paths in cp/error.cc:
+ dump_function_decl(), i.e. various combinations of templates and member
+ functions. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target lto } */
+/* { dg-options "-flto -Wuninitialized -O2" } */
+
+int y;
+
+int w1 (int)
+{
+ struct S
+ {
+ S () /* { dg-regexp {.*: In constructor 'w1\(int\)::S::S\(\)':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+ };
+ return S(), y;
+}
+
+template<typename T>
+int w2 (T)
+{
+ struct S
+ {
+ S () /* { dg-regexp {.*: In constructor 'w2\(T\)::S::S\(\) \[with T = char\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+ };
+ return S (), y;
+}
+int w2a ()
+{
+ return w2('\0');
+}
+
+int w3 (int)
+{
+ struct S
+ {
+ void f2 () /* { dg-regexp {.*: In member function 'void w3\(int\)::S::f2\(\)':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+ };
+ return S().f2 (), y;
+}
+
+template<typename T>
+int w4 (T)
+{
+ struct S
+ {
+ void f2 () /* { dg-regexp {.*: In member function 'void w4\(T\)::S::f2\(\) \[with T = char\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+ };
+ return S().f2 (), y;
+}
+int w4a ()
+{
+ return w4 ('\0');
+}
+
+struct A1
+{
+ A1 () /* { dg-regexp {.*: In constructor 'A1::A1\(\)':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ void f2 () /* { dg-regexp {.*: In member function 'void A1::f2\(\)':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ template<typename T>
+ void f3 () /* { dg-regexp {.*: In member function 'void A1::f3\(\) \[with T = char\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ static int f4() /* { dg-regexp {.*: In static member function 'static int A1::f4\(\)':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ return y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ operator int () /* { dg-regexp {.*: In member function 'A1::operator int\(\)':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ return y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ template<typename T>
+ operator T* () /* { dg-regexp {.*: In member function 'A1::operator T\*\(\) \[with T = char\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ return 0;
+ }
+};
+
+int f1 ()
+{
+ return A1 (), y;
+}
+
+int f2 ()
+{
+ return A1 ().f2 (), y;
+}
+
+int f3 ()
+{
+ return A1 ().f3<char> (), y;
+}
+
+int f4 ()
+{
+ return A1 ().f4 ();
+}
+
+int f5 ()
+{
+ return A1 ();
+}
+
+int f6 ()
+{
+ char *s = A1 ();
+ return y;
+}
+
+template<typename T>
+struct A2
+{
+ A2 () /* { dg-regexp {.*: In constructor 'A2<T>::A2\(\) \[with T = void\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ void f2 () /* { dg-regexp {.*: In member function 'void A2<T>::f2\(\) \[with T = void\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ template<typename U>
+ void f3 () /* { dg-regexp {.*: In member function 'void A2<T>::f3\(\) \[with U = char; T = void\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ static int f4() /* { dg-regexp {.*: In static member function 'static int A2<T>::f4\(\) \[with T = void\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ return y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ operator int () /* { dg-regexp {.*: In member function 'A2<T>::operator int\(\) \[with T = void\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ return y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ template<typename U>
+ operator U* () /* { dg-regexp {.*: In member function 'A2<T>::operator U\*\(\) \[with U = char; T = void\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ return 0;
+ }
+};
+
+int g1 ()
+{
+ return A2<void> (), y;
+}
+
+int g2 ()
+{
+ return A2<void> ().f2 (), y;
+}
+
+int g3 ()
+{
+ return A2<void> ().f3<char> (), y;
+}
+
+int g4 ()
+{
+ return A2<void> ().f4 ();
+}
+
+int g5 ()
+{
+ return A2<void> ();
+}
+
+int g6 ()
+{
+ char *s = A2<void> ();
+ return y;
+}
+
+struct A3
+{
+ ~A3 () /* { dg-regexp {.*: In destructor 'A3::~A3\(\)':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+};
+
+int h1 ()
+{
+ {
+ A3 a;
+ }
+ return y;
+}
+
+/* Let's do it all again inside a namespace too. */
+namespace N {
+
+int w1 (int)
+{
+ struct S
+ {
+ S () /* { dg-regexp {.*: In constructor 'N::w1\(int\)::S::S\(\)':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+ };
+ return S(), y;
+}
+
+template<typename T>
+int w2 (T)
+{
+ struct S
+ {
+ S () /* { dg-regexp {.*: In constructor 'N::w2\(T\)::S::S\(\) \[with T = char\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+ };
+ return S (), y;
+}
+int w2a ()
+{
+ return w2('\0');
+}
+
+int w3 (int)
+{
+ struct S
+ {
+ void f2 () /* { dg-regexp {.*: In member function 'void N::w3\(int\)::S::f2\(\)':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+ };
+ return S().f2 (), y;
+}
+
+template<typename T>
+int w4 (T)
+{
+ struct S
+ {
+ void f2 () /* { dg-regexp {.*: In member function 'void N::w4\(T\)::S::f2\(\) \[with T = char\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+ };
+ return S().f2 (), y;
+}
+int w4a ()
+{
+ return w4 ('\0');
+}
+
+struct A1
+{
+ A1 () /* { dg-regexp {.*: In constructor 'N::A1::A1\(\)':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ void f2 () /* { dg-regexp {.*: In member function 'void N::A1::f2\(\)':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ template<typename T>
+ void f3 () /* { dg-regexp {.*: In member function 'void N::A1::f3\(\) \[with T = char\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ static int f4() /* { dg-regexp {.*: In static member function 'static int N::A1::f4\(\)':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ return y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ operator int () /* { dg-regexp {.*: In member function 'N::A1::operator int\(\)':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ return y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ template<typename T>
+ operator T* () /* { dg-regexp {.*: In member function 'N::A1::operator T\*\(\) \[with T = char\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ return 0;
+ }
+
+};
+
+int f1 ()
+{
+ return A1 (), y;
+}
+
+int f2 ()
+{
+ return A1 ().f2 (), y;
+}
+
+int f3 ()
+{
+ return A1 ().f3<char> (), y;
+}
+
+int f4 ()
+{
+ return A1 ().f4 ();
+}
+
+int f5 ()
+{
+ return A1 ();
+}
+
+int f6 ()
+{
+ char *s = A1 ();
+ return y;
+}
+
+template<typename T>
+struct A2
+{
+ A2 () /* { dg-regexp {.*: In constructor 'N::A2<T>::A2\(\) \[with T = void\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ void f2 () /* { dg-regexp {.*: In member function 'void N::A2<T>::f2\(\) \[with T = void\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ template<typename U>
+ void f3 () /* { dg-regexp {.*: In member function 'void N::A2<T>::f3\(\) \[with U = char; T = void\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ static int f4() /* { dg-regexp {.*: In static member function 'static int N::A2<T>::f4\(\) \[with T = void\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ return y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ operator int () /* { dg-regexp {.*: In member function 'N::A2<T>::operator int\(\) \[with T = void\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ return y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+
+ template<typename U>
+ operator U* () /* { dg-regexp {.*: In member function 'N::A2<T>::operator U\*\(\) \[with U = char; T = void\]':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ return 0;
+ }
+
+};
+
+int g1 ()
+{
+ return A2<void> (), y;
+}
+
+int g2 ()
+{
+ return A2<void> ().f2 (), y;
+}
+
+int g3 ()
+{
+ return A2<void> ().f3<char> (), y;
+}
+
+int g4 ()
+{
+ return A2<void> ().f4 ();
+}
+
+int g5 ()
+{
+ return A2<void> ();
+}
+
+int g6 ()
+{
+ char *s = A2<void> ();
+ return y;
+}
+
+struct A3
+{
+ ~A3 () /* { dg-regexp {.*: In destructor 'N::A3::~A3\(\)':} } */
+ {
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {'x' is used uninitialized} } */
+ }
+};
+
+int h1 ()
+{
+ {
+ A3 a;
+ }
+ return y;
+}
+
+
+} /* namespace N */
diff --git a/gcc/testsuite/g++.dg/diag-after-fld-2.C b/gcc/testsuite/g++.dg/diag-after-fld-2.C
new file mode 100644
index 00000000000..ffc5ae5c635
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diag-after-fld-2.C
@@ -0,0 +1,27 @@
+/* Continuation of diag-after-fld-1.C for C++11 features. */
+/* { dg-do compile { target c++11 } } */
+/* { dg-require-effective-target lto } */
+/* { dg-options "-flto -Wuninitialized -O2" } */
+
+int y;
+
+int f1 (int)
+{
+ return [] () { /* { dg-regexp {.*: In lambda function:} } */
+ int x; /* { dg-note {'x' was declared here} } */
+ return y = x; /* { dg-warning {'x' is used uninitialized} } */
+ } ();
+}
+
+template<typename T>
+int f2 (T)
+{
+ return [] () { /* { dg-regexp {.*: In lambda function:} } */
+ int x; /* { dg-note {'x' was declared here} } */
+ return y = x; /* { dg-warning {'x' is used uninitialized} } */
+ } ();
+}
+int f2a ()
+{
+ return f2('\0');
+}
diff --git a/gcc/testsuite/gfortran.dg/allocatable_uninitialized_2.f90 b/gcc/testsuite/gfortran.dg/allocatable_uninitialized_2.f90
new file mode 100644
index 00000000000..9664ad63ba9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/allocatable_uninitialized_2.f90
@@ -0,0 +1,17 @@
+! { dg-do compile }
+! { dg-require-effective-target lto }
+! { dg-options "-O -Wall -flto" }
+! { dg-additional-options "-fdiagnostics-show-caret -fdiagnostics-show-line-numbers" }
+
+program main
+ real,allocatable:: a(:),b(:)
+
+ a(1)=2*b(1)
+
+end
+
+! { dg-allow-blank-lines-in-output 1 }
+! { dg-regexp {.*allocatable_uninitialized_2\.f90:9:14:\n\n 9 \| a\(1\)=2\*b\(1\)\n \| \^\nWarning: 'b.offset' is used uninitialized \[-Wuninitialized\]\n} }
+! { dg-regexp {.*allocatable_uninitialized_2\.f90:7:30:\n\n 7 \| real,allocatable:: a\(:\),b\(:\)\n \| \^\nnote: 'b' declared here\n} }
+! { dg-regexp {.*allocatable_uninitialized_2\.f90:9:14:\n\n 9 \| a\(1\)=2\*b\(1\)\n \| \^\nWarning: 'a.offset' is used uninitialized \[-Wuninitialized\]\n} }
+! { dg-regexp {.*allocatable_uninitialized_2\.f90:7:25:\n\n 7 \| real,allocatable:: a\(:\),b\(:\)\n \| \^\nnote: 'a' declared here\n} }
diff --git a/gcc/testsuite/objc.dg/diag-after-fld-1.m b/gcc/testsuite/objc.dg/diag-after-fld-1.m
new file mode 100644
index 00000000000..3bc4aa18997
--- /dev/null
+++ b/gcc/testsuite/objc.dg/diag-after-fld-1.m
@@ -0,0 +1,24 @@
+/* Make sure that post-ipa-free-lang-data diagnostics call objc_printable_name
+ as expected. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target lto } */
+/* { dg-options "-flto -O2 -Wuninitialized" } */
+
+#include "../objc-obj-c++-shared/TestsuiteObject.m"
+
+@interface T : TestsuiteObject
++ (void) f;
+@end
+
+int y;
+
+@implementation T
+/* This dg-regexp is the main test; prior to this patch, we output the mangled
+ name '_c_T__f' here. */
++ (void) f /* { dg-regexp {.*: In function '\+\[T f\]':} } */
+{
+ int x; /* { dg-note {'x' was declared here} } */
+ y = x; /* { dg-warning {-Wuninitialized} } */
+}
+@end
next prev parent reply other threads:[~2022-11-03 20:07 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-19 23:08 [PATCH] diagnostics: Allow FEs to keep customizations for middle end [PR101551,PR106274] Lewis Hyatt
2022-10-25 11:35 ` [PATCH] diagnostics: Allow FEs to keep customizations for middle end [PR101551, PR106274] Richard Biener
2022-10-25 21:05 ` Lewis Hyatt
2022-10-28 8:28 ` Richard Biener
2022-11-03 20:07 ` Lewis Hyatt [this message]
2022-11-08 14:22 ` Richard Biener
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221103200704.GA86831@ldh-imac.local \
--to=lhyatt@gmail.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=hubicka@ucw.cz \
--cc=richard.guenther@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).