Bug 92010 - [8/9 Regression] gcc internal error since 8x on warning write-strings
Summary: [8/9 Regression] gcc internal error since 8x on warning write-strings
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 9.2.0
: P2 normal
Target Milestone: 8.5
Assignee: Patrick Palka
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2019-10-07 08:08 UTC by Mikołaj
Modified: 2021-10-05 22:08 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-10-07 00:00:00


Attachments
internal compiler error with casting const char* to char* (189 bytes, text/plain)
2019-10-07 08:08 UTC, Mikołaj
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Mikołaj 2019-10-07 08:08:04 UTC
Created attachment 47002 [details]
internal compiler error with casting const char* to char*

In version 7.4 the code results with warning "warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]"
https://godbolt.org/z/WKFPDA

Since 8.x (tested with all versions available on godbolt, and with 8.3.0 on local machine - Windows Subsystem for Linux).
Attached file and console output are from local machine - Windows Subsystem for Linux.


console output:


Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/8/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 8.3.0-6ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-8/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-8 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 8.3.0 (Ubuntu 8.3.0-6ubuntu1) 
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-Wextra' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/8/cc1plus -E -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE bug.cpp -mtune=generic -march=x86-64 -Wall -Wextra -fpch-preprocess -fstack-protector-strong -Wformat-security -o bug.ii
ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/8"
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/8/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/include/c++/8
 /usr/include/x86_64-linux-gnu/c++/8
 /usr/include/c++/8/backward
 /usr/lib/gcc/x86_64-linux-gnu/8/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/8/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-Wextra' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/8/cc1plus -fpreprocessed bug.ii -quiet -dumpbase bug.cpp -mtune=generic -march=x86-64 -auxbase bug -Wall -Wextra -version -fstack-protector-strong -Wformat-security -o bug.s
GNU C++14 (Ubuntu 8.3.0-6ubuntu1) version 8.3.0 (x86_64-linux-gnu)
	compiled by GNU C version 8.3.0, GMP version 6.1.2, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.20-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
GNU C++14 (Ubuntu 8.3.0-6ubuntu1) version 8.3.0 (x86_64-linux-gnu)
	compiled by GNU C version 8.3.0, GMP version 6.1.2, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.20-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 1110442b7b958f151ae10a1cb5af9032
bug.cpp: In function ‘int main()’:
bug.cpp:8:35: internal compiler error: in tsubst_default_argument, at cp/pt.c:12712
      TriggerInternalCompilerError();
                                   ^
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-8/README.Bugs> for instructions.
Comment 1 Jakub Jelinek 2019-10-07 09:00:22 UTC
Started with r251422.
Comment 2 Marek Polacek 2020-02-12 17:18:04 UTC
template <typename T = char[3]>
void foo(const T t = "; ")
{
}

int main()
{
  foo ();
}

$ ./cc1plus -quiet 92010.C
92010.C: In function ‘int main()’:
92010.C:8:8: internal compiler error: in tsubst_default_argument, at cp/pt.c:13356
    8 |   foo ();
      |        ^
0xbc86f1 tsubst_default_argument(tree_node*, int, tree_node*, tree_node*, int)
	/home/mpolacek/src/gcc/gcc/cp/pt.c:13356
0x938263 convert_default_arg(tree_node*, tree_node*, tree_node*, int, int)
	/home/mpolacek/src/gcc/gcc/cp/call.c:8044
0x93b170 build_over_call
	/home/mpolacek/src/gcc/gcc/cp/call.c:8751
0x92b2ca build_new_function_call(tree_node*, vec<tree_node*, va_gc, vl_embed>**, int)
	/home/mpolacek/src/gcc/gcc/cp/call.c:4587
0xc3b4ce finish_call_expr(tree_node*, vec<tree_node*, va_gc, vl_embed>**, bool, bool, int)
	/home/mpolacek/src/gcc/gcc/cp/semantics.c:2671
0xb2cdd1 cp_parser_postfix_expression
	/home/mpolacek/src/gcc/gcc/cp/parser.c:7427
0xb2f71e cp_parser_unary_expression
	/home/mpolacek/src/gcc/gcc/cp/parser.c:8525
0xb30b88 cp_parser_cast_expression
	/home/mpolacek/src/gcc/gcc/cp/parser.c:9416
0xb30c75 cp_parser_binary_expression
	/home/mpolacek/src/gcc/gcc/cp/parser.c:9519
0xb31aba cp_parser_assignment_expression
	/home/mpolacek/src/gcc/gcc/cp/parser.c:9824
0xb31e71 cp_parser_expression
	/home/mpolacek/src/gcc/gcc/cp/parser.c:9992
0xb35acb cp_parser_expression_statement
	/home/mpolacek/src/gcc/gcc/cp/parser.c:11642
0xb35398 cp_parser_statement
	/home/mpolacek/src/gcc/gcc/cp/parser.c:11438
0xb3603f cp_parser_statement_seq_opt
	/home/mpolacek/src/gcc/gcc/cp/parser.c:11789
0xb35f23 cp_parser_compound_statement
	/home/mpolacek/src/gcc/gcc/cp/parser.c:11739
0xb4bcd6 cp_parser_function_body
	/home/mpolacek/src/gcc/gcc/cp/parser.c:22981
0xb4bffa cp_parser_ctor_initializer_opt_and_function_body
	/home/mpolacek/src/gcc/gcc/cp/parser.c:23032
0xb57904 cp_parser_function_definition_after_declarator
	/home/mpolacek/src/gcc/gcc/cp/parser.c:28880
0xb5772b cp_parser_function_definition_from_specifiers_and_declarator
	/home/mpolacek/src/gcc/gcc/cp/parser.c:28796
0xb4700e cp_parser_init_declarator
	/home/mpolacek/src/gcc/gcc/cp/parser.c:20596
Comment 3 Jakub Jelinek 2020-03-04 09:39:46 UTC
GCC 8.4.0 has been released, adjusting target milestone.
Comment 4 Patrick Palka 2020-03-12 15:29:40 UTC
Looking into it.
Comment 5 Patrick Palka 2020-03-12 22:54:11 UTC
The ICE seems to be revealing a latent issue:  In the following example (which GCC accepts), according to the static_assert labelled (1), the type of t is const int*, but according to the static_assert labelled (2), the type of t is int *const.



template <typename T>
void foo(const T t)
{
  static_assert(__is_same(decltype(t), const int*));  // (1)
}

static_assert(__is_same(decltype(foo<int[]>), void(int *)));  // (2)

int
main()
{
  foo<int[]>(nullptr);
}
Comment 6 Patrick Palka 2020-03-12 23:02:00 UTC
(In reply to Patrick Palka from comment #5)
> The ICE seems to be revealing a latent issue:  In the following example
> (which GCC accepts), according to the static_assert labelled (1), the type
> of t is const int*, but according to the static_assert labelled (2), the
> type of t is int *const.
> 
> 
> 
> template <typename T>
> void foo(const T t)
> {
>   static_assert(__is_same(decltype(t), const int*));  // (1)
> }
> 
> static_assert(__is_same(decltype(foo<int[]>), void(int *)));  // (2)
> 
> int
> main()
> {
>   foo<int[]>(nullptr);
> }

So the question becomes, what should the type of t be here?  According to https://eel.is/c++draft/temp#deduct-3:

"A top-level qualifier in a function parameter declaration does not affect the function type but still affects the type of the function parameter variable within the function."

The above suggests that the type of foo<int[]> should be the same regardless of where the parameter t is const-qualified.  Going by this then, it appears that the static_assert (2) is right and (1) is wrong.  Can anyone confirm?

(On the other hand, Clang thinks (1) is right and (2) is wrong.)
Comment 7 Patrick Palka 2020-03-17 18:34:08 UTC
(In reply to Patrick Palka from comment #6)
> (In reply to Patrick Palka from comment #5)
> > The ICE seems to be revealing a latent issue:  In the following example
> > (which GCC accepts), according to the static_assert labelled (1), the type
> > of t is const int*, but according to the static_assert labelled (2), the
> > type of t is int *const.
> > 
> > 
> > 
> > template <typename T>
> > void foo(const T t)
> > {
> >   static_assert(__is_same(decltype(t), const int*));  // (1)
> > }
> > 
> > static_assert(__is_same(decltype(foo<int[]>), void(int *)));  // (2)
> > 
> > int
> > main()
> > {
> >   foo<int[]>(nullptr);
> > }
> 
> So the question becomes, what should the type of t be here?  According to
> https://eel.is/c++draft/temp#deduct-3:
> 
> "A top-level qualifier in a function parameter declaration does not affect
> the function type but still affects the type of the function parameter
> variable within the function."
> 
> The above suggests that the type of foo<int[]> should be the same regardless
> of where the parameter t is const-qualified.  Going by this then, it appears
> that the static_assert (2) is right and (1) is wrong.  Can anyone confirm?
> 
> (On the other hand, Clang thinks (1) is right and (2) is wrong.)

So I think the quoted wording from [temp.deduct]/3 applies to function parameter types _after_ substitution.  So this doesn't definitively tell us anything about the type of t.

I think the answer lies in [basic.type.qualifier]/3, which says:

"Cv-qualifiers applied to an array type attach to the underlying element type, so the notation “cv T”, where T is an array type, refers to an array whose elements are so-qualified ([dcl.array]"

So the type const T after substituting T=int[] is precisely const int[], which as a parameter type then decays to const int* according to [dcl.fct]/5.  So it seems that the static_assert (1) is right, and (2) is wrong.
Comment 8 GCC Commits 2020-04-08 14:17:19 UTC
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>:

https://gcc.gnu.org/g:12f55e030ed068d5c7b14c65a74d102db925dab2

commit r10-7622-g12f55e030ed068d5c7b14c65a74d102db925dab2
Author: Patrick Palka <ppalka@redhat.com>
Date:   Mon Mar 30 19:55:03 2020 -0400

    c++: Function type and parameter type disagreements [PR92010]
    
    This resolves parts of Core issues 1001/1322 by rebuilding the function type
    of an instantiated function template in terms of its formal parameter types
    whenever the original function type and formal parameter types disagree about
    the type of a parameter after substitution.
    
    gcc/cp/ChangeLog:
    
            Core issues 1001 and 1322
            PR c++/92010
            * pt.c (rebuild_function_or_method_type): Split function out from ...
            (tsubst_function_type): ... here.
            (maybe_rebuild_function_decl_type): New function.
            (tsubst_function_decl): Use it.
    
    gcc/testsuite/ChangeLog:
    
            Core issues 1001 and 1322
            PR c++/92010
            * g++.dg/cpp2a/lambda-uneval11.c: New test.
            * g++.dg/template/array33.C: New test.
            * g++.dg/template/array34.C: New test.
            * g++.dg/template/defarg22.C: New test.
Comment 9 Patrick Palka 2020-04-08 14:33:43 UTC
Fixed on GCC 10 so far.

The thread https://gcc.gnu.org/pipermail/gcc-patches/2020-March/542487.html which continues at https://gcc.gnu.org/pipermail/gcc-patches/2020-April/543094.html discusses this PR and the ultimate fix.
Comment 10 Patrick Palka 2021-04-21 21:25:45 UTC
This fix seems too risky to backport.
Comment 11 qingzhe huang 2021-10-05 09:55:13 UTC
The testcase g++.dg/cpp2a/lambda-uneval11.C still suffers a segment fault if run by compiler cc1plus with latest code. And gdb shows that global var "current_function_decl" is set to 0 when crashed. Should we reopen this bug?



./install/libexec/gcc/x86_64-unknown-linux-gnu/12.0.0/cc1plus -std=c++20 gcc-clone/gcc/testsuite/g++.dg/cpp2a/lambda-uneval11.C
 <lambda()> void spam(decltype (<lambda>) (*)[sizeof (T)]) void foo() <lambda()> static constexpr void<lambda()>::_FUN() constexpr<lambda()>::operator void (*)()() const <lambda()> static constexpr void<lambda()>::_FUN() constexpr<lambda()>::operator void (*)()() const <lambda()> static constexpr void<lambda()>::_FUN() constexpr<lambda()>::operator void (*)()() const <lambda()> static constexpr void<lambda()>::_FUN() constexpr<lambda()>::operator void (*)()() const constexpr<lambda()>::operator void (*)()() const <lambda()> static constexpr void<lambda()>::_FUN() constexpr<lambda()>::operator void (*)()() const
gcc-clone/gcc/testsuite/g++.dg/cpp2a/lambda-uneval11.C: In instantiation of ‘constexpr<lambda()>::operator void (*)()() const’:
gcc-clone/gcc/testsuite/g++.dg/cpp2a/lambda-uneval11.C:9:12:   required from here
gcc-clone/gcc/testsuite/g++.dg/cpp2a/lambda-uneval11.C:4:25: internal compiler error: Segmentation fault
    4 | template <class T> void spam(decltype([]{}) (*s)[sizeof(T)] = nullptr)
      |                         ^~~~
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://gcc.gnu.org/bugs/> for instructions.
Comment 12 Patrick Palka 2021-10-05 14:23:19 UTC
(In reply to qingzhe huang from comment #11)
> The testcase g++.dg/cpp2a/lambda-uneval11.C still suffers a segment fault if
> run by compiler cc1plus with latest code.

Hmm, I can't reproduce that on latest trunk.  Is your working tree clean?
Comment 13 qingzhe huang 2021-10-05 16:21:07 UTC
(In reply to Patrick Palka from comment #12)
> (In reply to qingzhe huang from comment #11)
> > The testcase g++.dg/cpp2a/lambda-uneval11.C still suffers a segment fault if
> > run by compiler cc1plus with latest code.
> 
> Hmm, I can't reproduce that on latest trunk.  Is your working tree clean?

I tested in both 10.2.x and 11.2.x and even latest 12.x with yesterday pull. It won't show anything when compiling with driver, i.e. g++, but if you run "cc1plus", it will crash. For example, ${GCC_INSTALL}/libexec/gcc/x86_64-unknown-linux-gnu/11.2.0/cc1plus -std=c++20 ./lambda-uneval11.C

Thank you
Comment 14 Patrick Palka 2021-10-05 21:05:02 UTC
(In reply to qingzhe huang from comment #13)
> (In reply to Patrick Palka from comment #12)
> > (In reply to qingzhe huang from comment #11)
> > > The testcase g++.dg/cpp2a/lambda-uneval11.C still suffers a segment fault if
> > > run by compiler cc1plus with latest code.
> > 
> > Hmm, I can't reproduce that on latest trunk.  Is your working tree clean?
> 
> I tested in both 10.2.x and 11.2.x and even latest 12.x with yesterday pull.
> It won't show anything when compiling with driver, i.e. g++, but if you run
> "cc1plus", it will crash. For example,
> ${GCC_INSTALL}/libexec/gcc/x86_64-unknown-linux-gnu/11.2.0/cc1plus
> -std=c++20 ./lambda-uneval11.C
> 
> Thank you

Ah yeah, I can reproduce the crash when invoking cc1plus directly and also when passing -Q to the driver.  Might be better to open a separate PR for this as it seems to be a latent bug.
Comment 15 qingzhe huang 2021-10-05 21:56:25 UTC
>>Might be better to open a separate PR for this as it
seems to be a latent bug.
thanks, I will file a new bug.









From: ppalka at gcc dot gnu.org <gcc-bugzilla@gcc.gnu.org>
Sent: October 5, 2021 5:05 PM
To: nickhuang99@hotmail.com <nickhuang99@hotmail.com>
Subject: [Bug c++/92010] [8/9 Regression] gcc internal error since 8x on warning write-strings 
 
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92010

--- Comment #14 from Patrick Palka <ppalka at gcc dot gnu.org> ---
(In reply to qingzhe huang from comment #13)
> (In reply to Patrick Palka from comment #12)
> > (In reply to qingzhe huang from comment #11)
> > > The testcase g++.dg/cpp2a/lambda-uneval11.C still suffers a segment fault if
> > > run by compiler cc1plus with latest code.
> > 
> > Hmm, I can't reproduce that on latest trunk.  Is your working tree clean?
> 
> I tested in both 10.2.x and 11.2.x and even latest 12.x with yesterday pull.
> It won't show anything when compiling with driver, i.e. g++, but if you run
> "cc1plus", it will crash. For example,
> ${GCC_INSTALL}/libexec/gcc/x86_64-unknown-linux-gnu/11.2.0/cc1plus
> -std=c++20 ./lambda-uneval11.C
> 
> Thank you

Ah yeah, I can reproduce the crash when invoking cc1plus directly and also when
passing -Q to the driver.  Might be better to open a separate PR for this as it
seems to be a latent bug.
Comment 16 qingzhe huang 2021-10-05 22:08:14 UTC
> Ah yeah, I can reproduce the crash when invoking cc1plus directly and also
> when
> passing -Q to the driver.  Might be better to open a separate PR for this as
> it
> seems to be a latent bug.

just opened a new bug: pr102624