mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2026-09-10 07:46:51 -04:00
compile.el: Handle GCC 16 nested notes
* lisp/progmodes/compile.el (compilation-error-regexp-alist-alist): New gcc-nested-notes entry (bug#81308). * etc/compilation.txt (GCC nested notes): New section.
This commit is contained in:
parent
959c103af3
commit
5d128bf355
|
|
@ -322,6 +322,251 @@ In file included from /usr/include/c++/3.3/backward/warn.h:4,
|
||||||
from /usr/include/c++/3.3/backward/iostream.h:31:0,
|
from /usr/include/c++/3.3/backward/iostream.h:31:0,
|
||||||
from test_clt.cc:1:
|
from test_clt.cc:1:
|
||||||
|
|
||||||
|
* GCC nested notes
|
||||||
|
|
||||||
|
symbol: gcc-nested-notes
|
||||||
|
|
||||||
|
Example from https://developers.redhat.com/articles/2026/04/28/gcc-16-improved-error-messages-sarif-output#new_c___error_improvements with and without Unicode
|
||||||
|
|
||||||
|
test.cc:8:6: error: no declaration matches 'void foo::test(int, int, const void*, int)'
|
||||||
|
8 | void foo::test(int i, int j, const void *ptr, int k)
|
||||||
|
| ^~~
|
||||||
|
* there is 1 candidate
|
||||||
|
* candidate is: 'void foo::test(int, int, void*, int)'
|
||||||
|
test.cc:4:10:
|
||||||
|
4 | void test(int i, int j, void *ptr, int k);
|
||||||
|
| ^~~~
|
||||||
|
* parameter 3 of candidate has type 'void*'...
|
||||||
|
test.cc:4:35:
|
||||||
|
4 | void test(int i, int j, void *ptr, int k);
|
||||||
|
| ~~~~~~^~~
|
||||||
|
* ...which does not match type 'const void*'
|
||||||
|
test.cc:8:42:
|
||||||
|
8 | void foo::test(int i, int j, const void *ptr, int k)
|
||||||
|
| ~~~~~~~~~~~~^~~
|
||||||
|
test.cc:1:7: note: 'class foo' defined here
|
||||||
|
1 | class foo
|
||||||
|
| ^~~
|
||||||
|
|
||||||
|
test.cc:8:6: error: no declaration matches ‘void foo::test(int, int, const void*, int)’
|
||||||
|
8 | void foo::test(int i, int j, const void *ptr, int k)
|
||||||
|
| ^~~
|
||||||
|
• there is 1 candidate
|
||||||
|
• candidate is: ‘void foo::test(int, int, void*, int)’
|
||||||
|
test.cc:4:10:
|
||||||
|
4 | void test(int i, int j, void *ptr, int k);
|
||||||
|
| ^~~~
|
||||||
|
• parameter 3 of candidate has type ‘void*’...
|
||||||
|
test.cc:4:35:
|
||||||
|
4 | void test(int i, int j, void *ptr, int k);
|
||||||
|
| ~~~~~~^~~
|
||||||
|
• ...which does not match type ‘const void*’
|
||||||
|
test.cc:8:42:
|
||||||
|
8 | void foo::test(int i, int j, const void *ptr, int k)
|
||||||
|
| ~~~~~~~~~~~~^~~
|
||||||
|
test.cc:1:7: note: ‘class foo’ defined here
|
||||||
|
1 | class foo
|
||||||
|
| ^~~
|
||||||
|
|
||||||
|
../../gcc/gcc/cp/module.cc: In member function ‘void {anonymous}::trees_out::type_node(tree)’:
|
||||||
|
../../gcc/gcc/cp/module.cc:9628:40: error: cannot convert ‘qualifier_set’ to ‘int’ in initialization
|
||||||
|
9628 | int quals = type_memfn_quals (type);
|
||||||
|
| ~~~~~~~~~~~~~~~~~^~~~~~
|
||||||
|
| |
|
||||||
|
| qualifier_set
|
||||||
|
../../gcc/gcc/cp/module.cc:9635:24: error: no match for ‘operator!=’ (operand types are ‘int’ and ‘qualifier_set’)
|
||||||
|
9635 | || quals != type_memfn_quals (root)
|
||||||
|
| ~~~~~ ^~ ~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
| | |
|
||||||
|
| int qualifier_set
|
||||||
|
• there are 3 candidates
|
||||||
|
../../gcc/gcc/cp/module.cc:9635:24:
|
||||||
|
9635 | || quals != type_memfn_quals (root)
|
||||||
|
| ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
In file included from ../../gcc/gcc/cp/module.cc:215:
|
||||||
|
• candidate 1: ‘bool operator==(const cp_expr&, tree)’ (reversed)
|
||||||
|
../../gcc/gcc/cp/cp-tree.h:126:1:
|
||||||
|
126 | operator == (const cp_expr &lhs, tree rhs)
|
||||||
|
| ^~~~~~~~
|
||||||
|
• no known conversion for argument 1 from ‘qualifier_set’ to ‘const cp_expr&’
|
||||||
|
../../gcc/gcc/cp/cp-tree.h:126:29:
|
||||||
|
126 | operator == (const cp_expr &lhs, tree rhs)
|
||||||
|
| ~~~~~~~~~~~~~~~^~~
|
||||||
|
In file included from ../../gcc/gcc/coretypes.h:479,
|
||||||
|
from ../../gcc/gcc/cp/module.cc:214:
|
||||||
|
• candidate 2: ‘template<class T1, class T2> typename wi::binary_traits<T1, T2>::predicate_result operator!=(const T1&, const T2&)’
|
||||||
|
../../gcc/gcc/wide-int.h:3853:19:
|
||||||
|
3853 | BINARY_PREDICATE (operator !=, ne_p)
|
||||||
|
| ^~~~~~~~
|
||||||
|
• in definition of macro ‘BINARY_PREDICATE’
|
||||||
|
3829 | OP (const T1 &x, const T2 &y) \
|
||||||
|
| ^~
|
||||||
|
• template argument deduction/substitution failed:
|
||||||
|
• in definition of macro ‘BINARY_PREDICATE’
|
||||||
|
3829 | OP (const T1 &x, const T2 &y) \
|
||||||
|
| ^~
|
||||||
|
• ../../gcc/gcc/wide-int.h: In substitution of ‘template<class T1, class T2> typename wi::binary_traits<T1, T2>::predicate_result operator!=(const T1&, const T2&) [with T1 = int; T2 = qualifier_set]’:
|
||||||
|
• required from here
|
||||||
|
../../gcc/gcc/cp/module.cc:9635:42:
|
||||||
|
9635 | || quals != type_memfn_quals (root)
|
||||||
|
| ^
|
||||||
|
• error: incomplete type ‘wi::int_traits<qualifier_set>’ used in nested name specifier
|
||||||
|
../../gcc/gcc/wide-int.h:3853:19:
|
||||||
|
3853 | BINARY_PREDICATE (operator !=, ne_p)
|
||||||
|
| ^~~~~~~~
|
||||||
|
• in definition of macro ‘BINARY_PREDICATE’
|
||||||
|
3829 | OP (const T1 &x, const T2 &y) \
|
||||||
|
| ^~
|
||||||
|
In file included from ../../gcc/gcc/input.h:24,
|
||||||
|
from ../../gcc/gcc/coretypes.h:507:
|
||||||
|
• candidate 3: ‘bool operator!=(const expanded_location&, const expanded_location&)’
|
||||||
|
../../gcc/gcc/../libcpp/include/line-map.h:1313:1:
|
||||||
|
1313 | operator!= (const expanded_location &a,
|
||||||
|
| ^~~~~~~~
|
||||||
|
• no known conversion for argument 1 from ‘int’ to ‘const expanded_location&’
|
||||||
|
../../gcc/gcc/../libcpp/include/line-map.h:1313:38:
|
||||||
|
1313 | operator!= (const expanded_location &a,
|
||||||
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~^
|
||||||
|
../../gcc/gcc/c/c-typeck.cc:8719:38: error: no match for ‘operator|’ (operand types are ‘qualifier_set’ and ‘qualifier_set’)
|
||||||
|
8719 | : ((lquals | rquals) == lquals)))
|
||||||
|
| ~~~~~~ ^ ~~~~~~
|
||||||
|
| | |
|
||||||
|
| | qualifier_set
|
||||||
|
| qualifier_set
|
||||||
|
• there are 6 candidates
|
||||||
|
../../gcc/gcc/c/c-typeck.cc:8719:38:
|
||||||
|
8719 | : ((lquals | rquals) == lquals)))
|
||||||
|
| ~~~~~~~^~~~~~~~
|
||||||
|
• candidate 1: ‘template<class T1, class T2> typename wi::binary_traits<T1, T2>::operator_result operator|(const T1&, const T2&)’
|
||||||
|
../../gcc/gcc/wide-int.h:3855:18:
|
||||||
|
3855 | BINARY_OPERATOR (operator |, bit_or)
|
||||||
|
| ^~~~~~~~
|
||||||
|
• in definition of macro ‘BINARY_OPERATOR’
|
||||||
|
3837 | OP (const T1 &x, const T2 &y) \
|
||||||
|
| ^~
|
||||||
|
• template argument deduction/substitution failed:
|
||||||
|
• in definition of macro ‘BINARY_OPERATOR’
|
||||||
|
3837 | OP (const T1 &x, const T2 &y) \
|
||||||
|
| ^~
|
||||||
|
• ../../gcc/gcc/wide-int.h: In substitution of ‘template<class T1, class T2> typename wi::binary_traits<T1, T2>::operator_result operator|(const T1&, const T2&) [with T1 = qualifier_set; T2 = qualifier_set]’:
|
||||||
|
• required from here
|
||||||
|
../../gcc/gcc/c/c-typeck.cc:8719:19:
|
||||||
|
8719 | : ((lquals | rquals) == lquals)))
|
||||||
|
| ^~~~~~
|
||||||
|
• error: incomplete type ‘wi::int_traits<qualifier_set>’ used in nested name specifier
|
||||||
|
../../gcc/gcc/wide-int.h:3855:18:
|
||||||
|
3855 | BINARY_OPERATOR (operator |, bit_or)
|
||||||
|
| ^~~~~~~~
|
||||||
|
• in definition of macro ‘BINARY_OPERATOR’
|
||||||
|
3837 | OP (const T1 &x, const T2 &y) \
|
||||||
|
| ^~
|
||||||
|
• candidate 2: ‘dump_flags_t operator|(dump_flags_t, dump_flags_t)’
|
||||||
|
../../gcc/gcc/dumpfile.h:212:1:
|
||||||
|
212 | operator| (dump_flags_t lhs, dump_flags_t rhs)
|
||||||
|
| ^~~~~~~~
|
||||||
|
• no known conversion for argument 1 from ‘qualifier_set’ to ‘dump_flags_t’ {aka ‘dump_flag’}
|
||||||
|
../../gcc/gcc/dumpfile.h:212:25:
|
||||||
|
212 | operator| (dump_flags_t lhs, dump_flags_t rhs)
|
||||||
|
| ~~~~~~~~~~~~~^~~
|
||||||
|
• candidate 3: ‘optgroup_flags_t operator|(optgroup_flags_t, optgroup_flags_t)’
|
||||||
|
../../gcc/gcc/dumpfile.h:280:1:
|
||||||
|
280 | operator| (optgroup_flags_t lhs, optgroup_flags_t rhs)
|
||||||
|
| ^~~~~~~~
|
||||||
|
• no known conversion for argument 1 from ‘qualifier_set’ to ‘optgroup_flags_t’ {aka ‘optgroup_flag’}
|
||||||
|
../../gcc/gcc/dumpfile.h:280:29:
|
||||||
|
280 | operator| (optgroup_flags_t lhs, optgroup_flags_t rhs)
|
||||||
|
| ~~~~~~~~~~~~~~~~~^~~
|
||||||
|
• candidate 4: ‘constexpr cv_qualifier operator|(cv_qualifier, cv_qualifier)’
|
||||||
|
../../gcc/gcc/tree-core.h:716:1:
|
||||||
|
716 | operator| (cv_qualifier l, cv_qualifier r)
|
||||||
|
| ^~~~~~~~
|
||||||
|
• no known conversion for argument 1 from ‘qualifier_set’ to ‘cv_qualifier’
|
||||||
|
../../gcc/gcc/tree-core.h:716:25:
|
||||||
|
716 | operator| (cv_qualifier l, cv_qualifier r)
|
||||||
|
| ~~~~~~~~~~~~~^
|
||||||
|
• candidate 5: ‘constexpr qualifier_set operator|(qualifier_set, cv_qualifier)’
|
||||||
|
../../gcc/gcc/tree.h:2816:1:
|
||||||
|
2816 | operator| (qualifier_set qs, cv_qualifier cvs)
|
||||||
|
| ^~~~~~~~
|
||||||
|
• no known conversion for argument 2 from ‘qualifier_set’ to ‘cv_qualifier’
|
||||||
|
../../gcc/gcc/tree.h:2816:43:
|
||||||
|
2816 | operator| (qualifier_set qs, cv_qualifier cvs)
|
||||||
|
| ~~~~~~~~~~~~~^~~
|
||||||
|
• candidate 6: ‘constexpr qualifier_set operator|(cv_qualifier, qualifier_set)’
|
||||||
|
../../gcc/gcc/tree.h:2822:1:
|
||||||
|
2822 | operator| (cv_qualifier cvs, qualifier_set qs)
|
||||||
|
| ^~~~~~~~
|
||||||
|
• no known conversion for argument 1 from ‘qualifier_set’ to ‘cv_qualifier’
|
||||||
|
../../gcc/gcc/tree.h:2822:25:
|
||||||
|
2822 | operator| (cv_qualifier cvs, qualifier_set qs)
|
||||||
|
| ~~~~~~~~~~~~~^~~
|
||||||
|
|
||||||
|
The g++.dg/diagnostic/pr100716.C example has some more complex cases:
|
||||||
|
|
||||||
|
pr100716.C: In function ‘int main()’:
|
||||||
|
pr100716.C:34:13: error: no matching function for call to ‘A<int>::f(int)’
|
||||||
|
34 | A<int>().f(0); // { dg-error "no matching function for call to 'A<int>::f\\(int\\)'" }
|
||||||
|
| ~~~~~~~~~~^~~
|
||||||
|
• there is 1 candidate
|
||||||
|
• candidate 1: ‘template<class U> void A<T>::f() [with T = int]’
|
||||||
|
pr100716.C:7:12:
|
||||||
|
7 | void f() {} // { dg-line Af }
|
||||||
|
| ^
|
||||||
|
• candidate expects 0 arguments, 1 provided
|
||||||
|
pr100716.C:37:13: error: no matching function for call to ‘A<int>::g()’
|
||||||
|
37 | A<int>().g(); // { dg-error "no matching function for call to 'A<int>::g\\(\\)'" }
|
||||||
|
| ~~~~~~~~~~^~
|
||||||
|
• there is 1 candidate
|
||||||
|
• candidate 1: ‘template<class U> void A<T>::g(U) [with T = int]’
|
||||||
|
pr100716.C:10:12:
|
||||||
|
10 | void g(U) {} // { dg-line Ag }
|
||||||
|
| ^
|
||||||
|
• candidate expects 1 argument, 0 provided
|
||||||
|
pr100716.C:40:13: error: no matching function for call to ‘B<int>::f()’
|
||||||
|
40 | B<int>().f(); // { dg-error "no matching function for call to 'B<int>::f\\(\\)'" }
|
||||||
|
| ~~~~~~~~~~^~
|
||||||
|
• there is 1 candidate
|
||||||
|
• candidate 1: ‘template<class U> void B<T>::f(U) [with T = int]’
|
||||||
|
pr100716.C:17:12:
|
||||||
|
17 | void f(U) {} // { dg-line Bf }
|
||||||
|
| ^
|
||||||
|
• candidate expects 1 argument, 0 provided
|
||||||
|
pr100716.C:43:13: error: no matching function for call to ‘B<int>::g()’
|
||||||
|
43 | B<int>().g(); // { dg-error "no matching function for call to 'B<int>::g\\(\\)'" }
|
||||||
|
| ~~~~~~~~~~^~
|
||||||
|
• there is 1 candidate
|
||||||
|
• candidate 1: ‘template<class U> void B<T>::g(U, T) [with T = int]’
|
||||||
|
pr100716.C:20:12:
|
||||||
|
20 | void g(U, T) {} // { dg-line Bg }
|
||||||
|
| ^
|
||||||
|
• candidate expects 2 arguments, 0 provided
|
||||||
|
pr100716.C:46:15: error: no matching function for call to ‘B<float>::g(int)’
|
||||||
|
46 | B<float>().g(0); // { dg-error "no matching function for call to 'B<float>::g\\(int\\)'" }
|
||||||
|
| ~~~~~~~~~~~~^~~
|
||||||
|
• there is 1 candidate
|
||||||
|
• candidate 1: ‘template<class U> void B<T>::g(U, T) [with T = float]’
|
||||||
|
pr100716.C:20:12:
|
||||||
|
20 | void g(U, T) {} // { dg-line Bg }
|
||||||
|
| ^
|
||||||
|
• candidate expects 2 arguments, 1 provided
|
||||||
|
pr100716.C:49:8: error: no matching function for call to ‘C::f()’
|
||||||
|
49 | C().f(); // { dg-error "no matching function for call to 'C::f\\(\\)'" }
|
||||||
|
| ~~~~~^~
|
||||||
|
• there is 1 candidate
|
||||||
|
• candidate 1: ‘template<class U> void C::f(U)’
|
||||||
|
pr100716.C:26:10:
|
||||||
|
26 | void f(U) {} // { dg-line Cf }
|
||||||
|
| ^
|
||||||
|
• candidate expects 1 argument, 0 provided
|
||||||
|
pr100716.C:52:8: error: no matching function for call to ‘C::g(int)’
|
||||||
|
52 | C().g(0); // { dg-error "no matching function for call to 'C::g\\(int\\)'" }
|
||||||
|
| ~~~~~^~~
|
||||||
|
• there is 1 candidate
|
||||||
|
• candidate 1: ‘template<class U> void C::g()’
|
||||||
|
pr100716.C:29:10:
|
||||||
|
29 | void g() {} // { dg-line Cg }
|
||||||
|
| ^
|
||||||
|
• candidate expects 0 arguments, 1 provided
|
||||||
|
|
||||||
* GNU style
|
* GNU style
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -476,6 +476,54 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
|
||||||
;; so don't try to match it.
|
;; so don't try to match it.
|
||||||
": \\*\\*\\* \\[\\(\\(.+?\\):\\([0-9]+\\): .+\\)\\]" 2 3 nil 0 1)
|
": \\*\\*\\* \\[\\(\\(.+?\\):\\([0-9]+\\): .+\\)\\]" 2 3 nil 0 1)
|
||||||
|
|
||||||
|
(gcc-nested-notes
|
||||||
|
;; GCC 16 and onwards can produce messages that have structured and
|
||||||
|
;; elaborate nested notes. These messages are, in fact,
|
||||||
|
;; informative, and not errors unto themselves.
|
||||||
|
;;
|
||||||
|
;; The issue is that these messages can include locations (and
|
||||||
|
;; indeed do include a location by default), which Emacs may
|
||||||
|
;; misconstrue as a new diagnostic. So, catch it early, to
|
||||||
|
;; consider it an informative message.
|
||||||
|
,(rx
|
||||||
|
bol
|
||||||
|
;; The structure of these messages is something like:
|
||||||
|
;; INDENT BULLET MESSAGE \n
|
||||||
|
;; INDENT LOCATION
|
||||||
|
;; ... where INDENT are spaces, BULLET is either an ASCII star or
|
||||||
|
;; a Unicode bullet (U+2022), MESSAGE is informative text and
|
||||||
|
;; LOCATION is the usual FILE:LINE:COL coordinate.
|
||||||
|
;;
|
||||||
|
;; Sample:
|
||||||
|
;; • candidate is: ‘void foo::test(int, int, void*, int)’
|
||||||
|
;; test.cc:4:10:
|
||||||
|
;; 4 | void test(int i, int j, void *ptr, int k);
|
||||||
|
|
||||||
|
;; Match first line.
|
||||||
|
(group-n 9 (+ " ")) (| ?* ?\N{BULLET}) space (* nonl) (+ (any "\r\n"))
|
||||||
|
|
||||||
|
;; Match second line.
|
||||||
|
(backref 9) " "
|
||||||
|
;; File name group, from `gnu' rule.
|
||||||
|
(group-n 1
|
||||||
|
;; Avoid matching the file name as a program in the pattern
|
||||||
|
;; above by disallowing file names entirely composed of digits.
|
||||||
|
;; Do not allow file names beginning with a space.
|
||||||
|
(| (not (in "0-9" "\n\t "))
|
||||||
|
(: (+ (in "0-9"))
|
||||||
|
(not (in "0-9" "\n"))))
|
||||||
|
;; A file name can be composed of any non-newline char, but
|
||||||
|
;; rule out some valid but unlikely cases, such as a trailing
|
||||||
|
;; space or a space followed by a -, or a colon followed by a
|
||||||
|
;; space.
|
||||||
|
(*? (| (not (in "\n :"))
|
||||||
|
(: " " (not (in ?- "/\n")))
|
||||||
|
(: ":" (not (in " \n"))))))
|
||||||
|
?: (group-n 2 (+ (in "0-9"))) ; Line
|
||||||
|
?: (group-n 3 (+ (in "0-9"))) ; Column
|
||||||
|
?:)
|
||||||
|
1 2 3 0)
|
||||||
|
|
||||||
(gnu
|
(gnu
|
||||||
;; The `gnu' message syntax is
|
;; The `gnu' message syntax is
|
||||||
;; [PROGRAM:]FILE:LINE[-ENDLINE]:[COL[-ENDCOL]:] MESSAGE
|
;; [PROGRAM:]FILE:LINE[-ENDLINE]:[COL[-ENDCOL]:] MESSAGE
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue