Download newer versions of GMP, MPFR and MPC (the latest); besides the usual
bug fixes and smaller features, MPFR adds new functions for C23, some of
which are already used in GCC in the middle (fold-const-call.cc) and in
Fortran 2023 for the 'pi' trignonometric functions, if MPFR is new enough.
Jakub Jelinek [Thu, 7 Aug 2025 06:53:23 +0000 (08:53 +0200)]
c++: Add testcase for CWG2577 [PR120778]
And here is the last part of the paper. Contrary what the paper claims
(clearly they haven't tried -pedantic nor -pedantic-errors), I think we
already diagnose everything we should.
2025-08-07 Jakub Jelinek <jakub@redhat.com>
PR preprocessor/120778
* g++.dg/DRs/dr2577-1.C: New test.
* g++.dg/DRs/dr2577-2.C: New test.
* g++.dg/DRs/dr2577-2.h: New file.
* g++.dg/DRs/dr2577-3.C: New test.
* g++.dg/DRs/dr2577-3.h: New file.
Jakub Jelinek [Thu, 7 Aug 2025 06:52:38 +0000 (08:52 +0200)]
c++: Add testcase for CWG2575 [PR120778]
From the paper it isn't clear what caused the decision changes, not to drop
the "the token defined is generated as a result of this replacement process or"
part and make [cpp.cond]/10 violations IFNDR rather than ill-formed (the
latter maybe so that the extension to handle e.g. !A(A) below etc. can be
accepted).
Anyway, because that case hasn't been dropped and we pedwarn on it already,
and diagnose everything else the way it should, the following patch just
adds testcase for it.
2025-08-07 Jakub Jelinek <jakub@redhat.com>
PR preprocessor/120778
* g++.dg/DRs/dr2575.C: New test.
Jakub Jelinek [Thu, 7 Aug 2025 06:51:00 +0000 (08:51 +0200)]
c++: Add testcase for CWG2576 [PR120778]
Another part of the C++26 P2843R3, this time in https://eel.is/c++draft/cpp.include#7
changing former (compile time) undefined behavior to IFNDR.
With IFNDR we wouldn't have to test anything I guess, but this still adds
the cases from the 3.4 section of the paper plus related tests.
The paper wonders about implementation divergence between most compilers and
gcc in the case of glueing tokens together with <> around from multiple
macros, GCC doesn't add CPP_PADDING macros in that case (and even if it
would, it would ignore them through get_token_no_padding).
But I think this behavior is allowed by
https://eel.is/c++draft/cpp.include#7.sentence-3
and changing it now after 25+ years of such behavior might break real-world
stuff, especially making it really hard to construct the <> includes from
some name and adding < and > from some other macro around that. We handle
#define A <cstd def>
#include A
like clang++ and try to open 'cstd def' file. But not adding spaces for
all the padding means handling even stuff where nothing else can help,
while for cstd def coming from different macros one can use token pasting
to combine them together, e.g. < and following identifier or identifier
followed by . or . followed by identifier or identifier followed by > can't
be pasted together.
2025-08-07 Jakub Jelinek <jakub@redhat.com>
PR preprocessor/120778
* g++.dg/DRs/dr2576.C: New test.
Jakub Jelinek [Thu, 7 Aug 2025 06:47:44 +0000 (08:47 +0200)]
c++, c: Introduce -Wkeyword-macro warning/pedwarn - part of C++26 P2843R3 [PR120778]
The following patch introduces a -Wkeyword-macro warning that clang has
since 2014 to implement part of C++26 P2843R3 Preprocessing is never undefined
paper.
The relevant change in the paper is moving [macro.names]/2 paragraph to
https://eel.is/c++draft/cpp.replace.general#9 :
"A translation unit shall not #define or #undef names lexically identical to
keywords, to the identifiers listed in Table 4, or to the attribute-tokens
described in [dcl.attr], except that the names likely and unlikely may be
defined as function-like macros."
Now, my understanding of the paper is that in [macro.names] and surrounding
sections the word shall bears different meaning from [cpp.replace.general],
where only the latter location implies ill-formed, diagnostic required.
The warning in clang when introduced diagnosed all #define/#undef directives
on keywords, but shortly after introduction has been changed not to
diagnose #undef at all (with "#undef a keyword is generally harmless but used
often in configuration scripts" message) and later on even the #define
part tweaked - not warn about say
#define inline
(or const, extern, static), or
#define keyword keyword
or
#define keyword __keyword
or
#define keyword __keyword__
Later on the warning has been moved to be only pedantic diagnostic unless
requested by users. Clearly some code in the wild does e.g.
#define private public
and similar games, or e.g. Linux kernel (sure, C) does
#define inline __inline__ __attribute__((__always_inline__))
etc.
Now, I believe at least with the current C++26 wording such exceptions
aren't allowed (unless it is changed to IFNDR). But given that this is just
pedantic stuff, the following patch makes the warning off by default for
C and C++ before C++26 and even for C++26 it enables it by default only
if -pedantic/-pedantic-errors (in that case it pedwarns, otherwise it
warns). And it diagnoses both #define and #undef without exceptions.
From what I can see, all the current NODE_WARN cases are macros starting
with __ with one exception (_Pragma). As the NODE_* flags seem to be a
limited resource, I chose to just use NODE_WARN as well and differentiate
on the node names (if they don't start with __ or _P, they are considered
to be -Wkeyword-macro registered ones, otherwise old NODE_WARN cases,
typically builtin macros or __STDC* macros).
2025-08-07 Jakub Jelinek <jakub@redhat.com>
PR preprocessor/120778
gcc/
* doc/invoke.texi (Wkeyword-macro): Document.
gcc/c-family/
* c.opt (Wkeyword-macro): New option.
* c.opt.urls: Regenerate.
* c-common.h (cxx_dialect): Comment formatting fix.
* c-opts.cc (c_common_post_options): Default to
-Wkeyword-macro for C++26 if pedantic.
gcc/c/
* c-decl.cc (c_init_decl_processing): Mark cpp nodes corresponding
to keywords as NODE_WARN if warn_keyword_macro.
gcc/cp/
* lex.cc (cxx_init): Mark cpp nodes corresponding
to keywords, identifiers with special meaning and standard
attribute identifiers as NODE_WARN if warn_keyword_macro.
gcc/testsuite/
* gcc.dg/Wkeyword-macro-1.c: New test.
* gcc.dg/Wkeyword-macro-2.c: New test.
* gcc.dg/Wkeyword-macro-3.c: New test.
* gcc.dg/Wkeyword-macro-4.c: New test.
* gcc.dg/Wkeyword-macro-5.c: New test.
* gcc.dg/Wkeyword-macro-6.c: New test.
* gcc.dg/Wkeyword-macro-7.c: New test.
* gcc.dg/Wkeyword-macro-8.c: New test.
* gcc.dg/Wkeyword-macro-9.c: New test.
* g++.dg/warn/Wkeyword-macro-1.C: New test.
* g++.dg/warn/Wkeyword-macro-2.C: New test.
* g++.dg/warn/Wkeyword-macro-3.C: New test.
* g++.dg/warn/Wkeyword-macro-4.C: New test.
* g++.dg/warn/Wkeyword-macro-5.C: New test.
* g++.dg/warn/Wkeyword-macro-6.C: New test.
* g++.dg/warn/Wkeyword-macro-7.C: New test.
* g++.dg/warn/Wkeyword-macro-8.C: New test.
* g++.dg/warn/Wkeyword-macro-9.C: New test.
* g++.dg/warn/Wkeyword-macro-10.C: New test.
* g++.dg/opt/pr82577.C: Don't #define register to nothing for
C++17 and later. Instead define reg macro to nothing for C++17
and later or to register and use it instead of register.
* g++.dg/modules/atom-preamble-3.C: Add -Wno-keyword-macro to
dg-additional-options.
* g++.dg/template/sfinae17.C (static_assert): Rename macro to ...
(my_static_assert): ... this.
(main): Use my_static_assert instead of static_assert.
libcpp/
* include/cpplib.h (struct cpp_options): Add cpp_warn_keyword_macro.
(enum cpp_warning_reason): Add CPP_W_KEYWORD_MACRO enumerator.
(cpp_keyword_p): New inline function.
* directives.cc (do_undef): Support -Wkeyword-macro diagnostics.
* macro.cc (warn_of_redefinition): Ignore NODE_WARN flag on nodes
registered for -Wkeyword-macro.
(_cpp_create_definition): Support -Wkeyword-macro diagnostics.
Formatting fixes.
* gcc.target/s390/bitint-1.c: New test.
* gcc.target/s390/bitint-2.c: New test.
* gcc.target/s390/bitint-3.c: New test.
* gcc.target/s390/bitint-4.c: New test.
* config.host: Include makefiles t-softfp for -m64.
* config/s390/sfp-exceptions.c: New file.
* config/s390/sfp-machine.h: New file.
* config/s390/t-softfp: New file.
Sam James [Wed, 6 Aug 2025 22:25:48 +0000 (23:25 +0100)]
testsuite: fix escaping of square brackets
This fails for me as:
+ERROR: g++.dg/cpp26/constexpr-new3.C -std=c++26: unknown dg option: 2 for "
dg-error 40 "accessing value of 'int [2]' object through a 'long int' glvalue in a constant expression" "
otherwise.
Escape '[' and ']'.
gcc/testsuite/ChangeLog:
* g++.dg/cpp26/constexpr-new3.C: Escape '[' and ']'.
matches any mode of (and ...) on input, but hard-codes (and:SI ...)
in the output. This causes an ICE if the incoming (and ...) is DImode
rather than SImode.
Co-developed-by: Richard Sandiford <richard.sandiford@arm.com>
PR target/96226
gcc/ChangeLog:
* config/i386/predicates.md (and_operator): New operator.
* config/i386/i386.md (splitter after *<rotate_insn><mode>3_mask):
Use and_operator to match AND RTX and use its mode
in the split pattern.
Alexandre Oliva [Wed, 6 Aug 2025 19:31:50 +0000 (16:31 -0300)]
[hardbool] implement OP=, ++ and --, volatile and atomics
hardbools didn't behave quite like bools when incremented,
decremented, or otherwise modified using their previous value, as in
+= et al. Fix that.
Also fix some checking errors that come up when using qualified base
types.
for gcc/c-family/ChangeLog
* c-attribs.cc (handle_hardbool_attribute): Create distinct
enumeration types, with structural equality. Handle
base type qualifiers.
for gcc/c/ChangeLog
* c-tree.h (C_BOOLEAN_TYPE_P): Cover hardbools as well.
* c-typeck.cc (convert_lvalue_to_rvalue): New overload and
wrapper.
(build_atomic_assign, build_modify_expr): Use it.
(build_asm_expr, handle_omp-array_sections_1): Simplify with
it.
(build_unary_op): Handle hardbools.
i386: Add missing PTA_POPCNT and PTA_LZCNT with PTA_ABM
This patch adds the missing PTA_POPCNT and PTA_LZCNT with the PTA_ABM
bitmask definition for the bdver1, btver1, and lujiazui architectures
in the i386 architecture configuration file.
Although these two features were not present in the original definition,
their absence does not affect the functionality of these architectures
because the POPCNT and LZCNT bits are set when ABM is enabled in the
ix86_option_override_internal function. However, including them in these
definitions improves consistency and clarity. This issue was discovered
while writing a script to extract these bitmasks from the i386.h file
referenced in [1].
Additionally, the PTA_YONGFENG bitmask appears incorrect as it includes
PTA_LZCNT while already inheriting PTA_ABM from PTA_LUJIAZUI. This seems
to be a typo and should be corrected.
[1] https://github.com/cyyself/x86-pta
gcc/ChangeLog:
* config/i386/i386.h (PTA_BDVER1):
Add missing PTA_POPCNT and PTA_LZCNT with PTA_ABM.
(PTA_ZNVER1): Ditto.
(PTA_BTVER1): Ditto.
(PTA_LUJIAZUI): Ditto.
(PTA_YONGFENG): Do not include extra PTA_LZCNT.
Martin Uecker [Sat, 17 Dec 2022 14:34:30 +0000 (15:34 +0100)]
c2y: Evaluate size expression only in the active branch of conditional operator [PR108931]
For size expressions in the branches of the conditional operator should
be evaluated only for the active branch. To achieve this, construct
also the size expressions for the composite type as conditional
expressions depending on the condition of the conditional operator.
The change avoids some undefined behavior removed by N3652, but the
new constraints for C2Y are not yet implemented.
PR c/108931
gcc/c/ChangeLog:
* c-typeck.cc (composite_type_cond): Renamed from
composite_type with argument for condition
(composite_type): New function.
(composite_type_internal): Implement new logic.
(build_conditional_expr): Pass condition.
(common_pointer_type): Adapt.
(pointer_diff): Adapt.
(build_binary_op): Adapt.
gcc/testsuite/ChangeLog:
* gcc.dg/vla-tert-1.c: New test.
Matthieu Longo [Mon, 4 Aug 2025 10:04:13 +0000 (11:04 +0100)]
libiberty: disable logging of list content for doubly-linked list tests
When the doubly-linked list tests were introduced, the tests were
printing the content of the list forward and backward. However, this
printing is not needed outside of debugging, and confuses people because
the output is not only composed of PASS: lines.
This patch disables the printing of the list content by default. If
one wants to re-enable it for debugging, he can set the macro DUMP_LIST
to 1.
libiberty/ChangeLog:
* testsuite/test-doubly-linked-list.c: disable debug logging on
stdout.
Richard Biener [Wed, 6 Aug 2025 07:38:55 +0000 (09:38 +0200)]
Simplify vect_supportable_dr_alignment
The following simplifies vect_supportable_dr_alignment based on
the observation that we always dereference dr_info so it cannot
be NULL, likewise we always dereference dr so that cannot be NULL
either.
* tree-vect-data-refs.cc (vect_supportable_dr_alignment):
Prune dead code.
Here the results of A::make(0, 0, 1), (0, 1, 0) and (1, 0, 0) are each
represented as a single-element CONSTRUCTOR with CONSTRUCTOR_NO_CLEARING
cleared, and when used as as a class NTTP argument we end up mangling them
all as A{1}, i.e. eliding both the implicit initial and trailing zeros.
Mangling them all the same seems clearly wrong since they're logically
different values.
It turns out the mangling also omits intermediate zeros, e.g.
A::make(1, 0, 1) is mangled as A{1, 1}, the same as A::make(1, 1, 0).
It seems we can't omit both trailing and non-trailing implicit zeros
without introducing mangling ambiguities. This patch makes us include
non-trailing zeros in these manglings (while continuing to omit trailing
zeros).
This also manifests as a wrong-code bug where the specializations table
would conflate different specializations that are in terms of different
class NTTP arguments, since the identity of such arguments is tied to
their mangling.
PR c++/121231
PR c++/119688
PR c++/94511
gcc/ChangeLog:
* common.opt: Document additional ABI version 21 change.
* doc/invoke.texi: Likewise.
gcc/cp/ChangeLog:
* mangle.cc (write_expression): Write out implicit non-trailing
zeroes of a CONSTRUCTOR when the ABI version is at least 21.
gcc/testsuite/ChangeLog:
* g++.dg/abi/mangle82.C: New test.
* g++.dg/cpp2a/nontype-class73.C: New test.
Jason Merrill [Tue, 22 Jul 2025 04:12:12 +0000 (00:12 -0400)]
c++: improve constexpr type mismatch diagnostic
This diagnostic failed to specify the actual type of the object being
accessed through a glvalue of an incompatible type, and could also use to
indicate where that object comes from.
Richard Biener [Mon, 4 Aug 2025 09:27:54 +0000 (11:27 +0200)]
Record gather/scatter scale and base in the SLP tree
The main gather/scatter discovery happens at SLP discovery time,
the base address and the offset scale are currently not explicitly
represented in the SLP tree. This requires re-discovery of them
during vectorizable_store/load. The following fixes this by
recording this info into the SLP tree. This allows the main
vect_check_gather_scatter call to be elided from get_load_store_type
and replaced with target support checks for IFN/decl or fallback
emulated mode.
There's vect_check_gather_scatter left in the path using gather/scatter
for strided load/store. I hope to deal with this later.
* tree-vectorizer.h (_slp_tree::gs_scale): New.
(_slp_tree::gs_base): Likewise.
(SLP_TREE_GS_SCALE): Likewise.
(SLP_TREE_GS_BASE): Likewise.
(vect_describe_gather_scatter_call): Declare.
* tree-vect-slp.cc (_slp_tree::_slp_tree): Initialize
new members.
(vect_build_slp_tree_2): Record gather/scatter base and scale.
(vect_get_and_check_slp_defs): For gather/scatter IFNs
describe the call to first_gs_info.
* tree-vect-data-refs.cc (vect_gather_scatter_fn_p): Add
mode of operation with fixed offset vector type.
(vect_describe_gather_scatter_call): Export.
* tree-vect-stmts.cc (get_load_store_type): Do not call
vect_check_gather_scatter to fill gs_info, instead populate
from the SLP tree. Check which of, IFN, decl or fallback
is supported and record that decision.
Richard Biener [Wed, 6 Aug 2025 07:41:26 +0000 (09:41 +0200)]
Use proper alias type for gather/scatter with SLP
Both vectorizable_load and vectorizable_store compute an alias
type commoning differences between SLP lanes. The following
makes sure to use that for gather/scatter rather than the
random one from the representative created during scalar stmt
gather/scatter analysis.
* tree-vect-stmts.cc (vectorizable_store): Build proper
alias + align pointer value for gather/scatter and SLP
and use it.
(vectorizable_load): Likewise.
Richard Biener [Tue, 5 Aug 2025 12:55:18 +0000 (14:55 +0200)]
Allow fully masked loops with legacy gather/scatter
The following removes the redundant check on supported gather/scatter
IFN in check_load_store_for_partial_vectors which is already done
and adjusts those to check the recorded ifn, also allowing legacy
gather/scatter which all handle masking.
* tree-vect-stmts.cc (check_load_store_for_partial_vectors):
Remove redundant gather/scatter target support check, instead
check the recorded ifns. Also allow legacy gather/scatter
with loop masking.
Jakub Jelinek [Wed, 6 Aug 2025 10:52:47 +0000 (12:52 +0200)]
bitint: Fix build [PR121413]
Sorry, my bootstrap failed last night because of this, I've fixed it
up and it bootstrapped/regtested fine overnight, but in the morning
forgot to adjust the patch before committing.
Without this there is
.../gimple-lower-bitint.cc:7678:36: error: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Werror=sign-compare]
7678 | if (min_prec > limb_prec && abi_limb_prec > limb_prec)
| ~~~~~~~~~^~~~~~~~~~~
2025-08-06 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/121413
* gimple-lower-bitint.cc (gimple_lower_bitint): Fix up last
commit, cast limb_prec to unsigned before comparison.
Yang Yujie [Wed, 6 Aug 2025 10:04:51 +0000 (12:04 +0200)]
bitint: Do not optimize away conversion to _BitInt before a VCE
A _BitInt value may rely on a conversion to become properly extended.
So a conversion to _BitInt is not trivially removable even if the
types of the result and the operand have the same precision and size.
This patch fixes gcc.dg/torture/bitint-64.c at -O2 on LoongArch,
which fails because extension of the result is dropped in a
compare-and-swap loop generated for incrementing an _Atomic _BitInt,
causing an ABI violation.
* match.pd: Preserve conversion to _BitInt before a VCE
if the _BitInt is extended.
Yang Yujie [Wed, 6 Aug 2025 10:03:39 +0000 (12:03 +0200)]
bitint: Zero-extend the result of a signed->unsigned widening cast
A widening cast from a signed _BitInt operand to an unsigned _BitInt
type involves filling the extra limb(s) with sign extension.
On a target that wants _BitInts extended in memory, if this unsigned
type has a partial limb, the unused part of it should be zeroed.
e.g. Assuming limb_mode == E_DImode, at the end of
the most significant limb of *t should be masked with 0x7f.
This patch also fixes gcc.dg/torture/bitint-16.c, which aborts at -O2
when the extension on load is optimized away.
* gimple-lower-bitint.cc (bitint_large_huge::lower_mergeable_stmt):
Zero-extend the partial limb of any unsigned _BitInt LHS assigned
with a widening sign-extension.
Yang Yujie [Wed, 6 Aug 2025 10:02:44 +0000 (12:02 +0200)]
bitint: Make sure BEXTC checks extension when optimized
In BEXTC, whether a _BitInt object is properly extended is examined
by a value comparison against a copied object in a wider _BitInt
type that utilizes all of the partial limb.
Since the (implicit) conversion to the wider type may be optimized
away now and cause the result of the comparison to always be true,
we need to cast the copied object down to the original type to
force a extension, so that it can serve as our reference.
* gcc.dg/bitintext.h (BEXTC1): Define. Convert the copied
object back to the original type before comparison.
(BEXTC): Use BEXTC1 for both the signed and the unsigned case.
Yang Yujie [Wed, 6 Aug 2025 10:01:33 +0000 (12:01 +0200)]
bitint: Avoid extending ABI-extended large/huge _BitInts on load
This patch also make casts of ABI-extended large/huge _BitInts
behave the same as the small/middle case, i.e. no-op for casts
to a higher precision _BitInt with the same number of limbs /
extension for casts that turns a full top limb into a partial limb.
This conveniently helps keep some code with implementation-specific
extension semantics (e.g. BEXTC from gcc.dg/bitintext.h) the same
for _BitInts of any precision.
* gimple-lower-bitint.cc (bitint_large_huge::limb_access):
Add a parameter abi_load_p. If set, load a limb directly
in its actual precision without casting from m_limb_type.
(struct bitint_large_huge): Same.
(bitint_large_huge::handle_load): Use.
aarch64 for some strange reason unconditionally enables -Werror for libgcc
building and this particular file for some strange reason contains
a useless static forward declaration of a function only defined in the
#if defined __sun__ && defined __svr4__
block and not otherwise (with __attribute__((constructor))).
And we warn (with -Werror error) in the non-__sun__/__svr4__ case because
it declares a static function that is never defined.
The forward declaration makes no sense to me, for static functions
forward declarations shouldn't be needed even for -Wstrict-prototypes,
and AFAIK we don't warn on static __attribute__((constructor)) void foo (void) {}
being unused. And the function isn't used before being defined.
So, the following patch just removes the forward declaration.
Jakub Jelinek [Wed, 6 Aug 2025 09:30:08 +0000 (11:30 +0200)]
bitint: Fix up INTEGER_CST PHI handling [PR121413]
The following testcase is miscompiled on aarch64-linux.
The problem is in the optimization to shorten large constants
in PHI arguments.
In a couple of places during bitint lowering we compute
minimal precision of constant and if it is significantly
smaller than the precision of the type, store smaller constant
in memory and extend it at runtime (zero or all ones).
Now, in most places that works fine, we handle the stored number
of limbs by loading them from memory and then the rest is
extended. In the PHI INTEGER_CST argument handling we do
it differently, we don't form there any loops (because we
insert stmt sequences on the edges).
The problem is that we copy the whole _BitInt variable from
memory to the PHI VAR_DECL + initialize the rest to = {} or
memset to -1. It has
min_prec = CEIL (min_prec, limb_prec) * limb_prec;
precision, so e.g. on x86_64 there is no padding and it works
just fine. But on aarch64 which has abi_limb_mode TImode
and limb_mode DImode it doesn't in some cases.
In the testcase the constant has 408 bits min precision, rounded up
to limb_prec (64) is 448, i.e. 7 limbs. But aarch64 with TImode
abi_limb_mode will actually allocate 8 limbs and the most significant
limb is solely padding. As we want to extend the constant with all
ones, copying the padding (from memory, so 0s) will result in
64 0 bits where 1 bits were needed.
The following patch fixes it by detecting this case and setting
min_prec to a multiple of abi limb precision so that it has
no padding.
2025-08-06 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/121413
* gimple-lower-bitint.cc (abi_limb_prec): New variable
(bitint_precision_kind): Initialize it.
(gimple_lower_bitint): Clear it at the start. For
min_prec > limb_prec descreased precision vars for
INTEGER_CST PHI arguments ensure min_prec is either
prec or multiple of abi_limb_prec.
Jakub Jelinek [Wed, 6 Aug 2025 09:28:37 +0000 (11:28 +0200)]
bitint: Fix up handling of uninitialized mul/div/float cast operands [PR121127]
handle_operand_addr (used for the cases where we use libgcc APIs, so
multiplication, division, modulo, casts of _BitInt to float/dfp) when it
sees default definition of an SSA_NAME which is not PARM_DECL (i.e.
uninitialized one) just allocates single uninitialized limb, there is no
need to waste more memory on it, it can just tell libgcc that it has
64-bit precision, not say 1024 bit etc.
Unfortunately, doing this runs into some asserts when we have a narrowing
cast of the uninitialized SSA_NAME (but still large/huge _BitInt).
The following patch fixes that by using a magic value in *prec_stored
for the uninitialized cases (0) and just don't do any *prec tweaks for
narrowing casts from that. precs still needs to be maintained as before,
that one is used for big endian adjustment.
2025-08-06 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/121127
* gimple-lower-bitint.cc (bitint_large_huge::handle_operand_addr): For
uninitialized SSA_NAME, set *prec_stored to 0 rather than *prec.
Handle that case in narrowing casts. If prec_stored is non-NULL,
set *prec_stored to prec_stored_val.
Jakub Jelinek [Wed, 6 Aug 2025 09:27:00 +0000 (11:27 +0200)]
gengtype: Include system.h earlier in gengtype-lex.cc [PR121386]
OpenBSD headers apparently instead of just
#define SIZE_MAX something
do
#ifndef SIZE_MAX
#define SIZE_MAX something
#endif
This causes problem with gengtype-lex.cc, where the flex generated
code has
#ifndef SIZE_MAX
#define SIZE_MAX (~(size_t)0)
#endif
and system.h is included only after that and since my changes for
host size_t *printf printing SIZE_MAX is used in preprocessor
expressions,
#if SIZE_MAX <= UINT_MAX
etc.
In the preprocessor, identifiers are replaced with 0 and so
it is (~(0)0) <= 0xffffffffU
or so and thus invalid.
Now, normally we want to include system.h early, ideally immediately
after config.h or bconfig.h, but in gengtype-lex.cc case we have
#ifdef HOST_GENERATOR_FILE
#include "config.h"
#define GENERATOR_FILE 1
#else
#include "bconfig.h"
#endif
As I'm not sure what flex we require for building gcc (%top{} which COBOL FE
*.l uses is only in flex from 2003-04-01), the patch keeps using the %top{}
done by hand in Makefile.in, but includes system.h in the top part, with
FLEX_SCANNER temporarily defined (I'm undefining it afterwards because
flex generated code defines it again and I don't want to guarantee it is
defined to the same value) so that malloc/realloc poisoning doesn't happen
and #define malloc xmalloc and realloc xrealloc are done in system.h.
Note, system.h already includes all the 5 headers flex generated code
includes.
2025-08-06 Jakub Jelinek <jakub@redhat.com>
PR bootstrap/121386
* Makefile.in (gengtype-lex.cc): Append #define FLEX_SCANNER,
#include "system.h" and #undef FLEX_SCANNER to the prepended lines.
* gengtype-lex.l: Remove inclusion of config.h or bconfig.h, system.h
and definition of malloc/realloc from %{} section.
Yuao Ma [Mon, 4 Aug 2025 12:19:27 +0000 (20:19 +0800)]
fortran: cleanup duplicate tests for c_f_pointer_shape_driver
tests_2_driver and tests_4_driver are identical, and tests_4_driver is not used
at all. This patch clean this up, and format the driver with gcc style.
gcc/testsuite/ChangeLog:
* gfortran.dg/c_f_pointer_shape_tests_2.f03: Use the new driver.
* gfortran.dg/c_f_pointer_shape_tests_4.f03: Ditto.
* gfortran.dg/c_f_pointer_shape_tests_4_driver.c: Removed.
* gfortran.dg/c_f_pointer_shape_tests_2_driver.c: Renamed to ...
* gfortran.dg/c_f_pointer_shape_tests_driver.c: ... this; format
with gcc style.
Jakub Jelinek [Wed, 6 Aug 2025 08:44:09 +0000 (10:44 +0200)]
c++: Add test for vt/ff in line comments
P2843R3 dropped the
"If there is a form-feed or a vertical-tab character in such a comment, only
whitespace characters shall appear between it and the new-line that terminates
the comment; no diagnostic is required."
sentence from [lex.comment]. AFAIK we've never diagnosed nor checked for
that and C23 doesn't have anything like that, so the following testcase
merely tests that we don't diagnose anything on it.
2025-08-06 Jakub Jelinek <jakub@redhat.com>
PR preprocessor/120778
* c-c++-common/cpp/comment-ff-1.c: New test.
* c-c++-common/cpp/comment-vtab-1.c: New test.
Martin Uecker [Mon, 28 Jul 2025 11:12:14 +0000 (13:12 +0200)]
c: Fix ICE on invalid code involving bit fields [PR121217]
Under some error condition we can end up with NULL_TREEs for
the type of bitfields, which can cause an ICE when testing for
type compatibility. Add the missing check.
Kito Cheng [Thu, 31 Jul 2025 08:25:52 +0000 (16:25 +0800)]
RISC-V: Read extension data from riscv-ext*.def for arch-canonicalize
Previously, arch-canonicalize used hardcoded data to handle IMPLIED_EXT.
But this data often got out of sync with the actual C++ implementation.
Earlier, we introduced riscv-ext.def to keep track of all extension info
and generate docs. Now, arch-canonicalize also uses this same data to handle
extension implication rules directly.
One limitation is that conditional implication rules still need to be written
manually. Luckily, there aren't many of them for now, so it's still manageable.
I really wanted to avoid writing a C++ + Python binding or trying to parse C++
logic in Python...
This version also adds a `--selftest` option to run some unit tests.
gcc/ChangeLog:
* config/riscv/arch-canonicalize: Read extension data from
riscv-ext*.def and adding unittest.
Kito Cheng [Mon, 28 Jul 2025 12:49:39 +0000 (20:49 +0800)]
RISC-V: Support -march=unset
This patch introduces a new `-march=unset` option for RISC-V GCC that
allows users to explicitly ignore previous `-march` options and derive
the architecture string from the `-mcpu` option instead.
This feature is particularly useful for build systems and toolchain
configurations where you want to ensure the architecture is always
derived from the CPU specification rather than relying on potentially
conflicting `-march` options.
* gcc.target/riscv/arch-unset-1.c: New test.
* gcc.target/riscv/arch-unset-2.c: New test.
* gcc.target/riscv/arch-unset-3.c: New test.
* gcc.target/riscv/arch-unset-4.c: New test.
* gcc.target/riscv/arch-unset-5.c: New test.
* gimplify.cc (remove_unused_omp_iterator_vars): Display unused
variable warning for 'to' and 'from' clauses.
(gimplify_scan_omp_clauses): Add argument for iterator loop sequence.
Gimplify the clause decl and size into the iterator loop if iterators
are used.
(gimplify_omp_workshare): Add argument for iterator loops sequence
in call to gimplify_scan_omp_clauses.
(gimplify_omp_target_update): Call remove_unused_omp_iterator_vars and
build_omp_iterators_loops. Add loop sequence as argument when calling
gimplify_scan_omp_clauses, gimplify_adjust_omp_clauses and building
the Gimple statement.
* tree-pretty-print.cc (dump_omp_clause): Call dump_omp_iterators
for to/from clauses with iterators.
* tree.cc (omp_clause_num_ops): Add extra operand for OMP_CLAUSE_FROM
and OMP_CLAUSE_TO.
* tree.h (OMP_CLAUSE_HAS_ITERATORS): Add check for OMP_CLAUSE_TO and
OMP_CLAUSE_FROM.
(OMP_CLAUSE_ITERATORS): Likewise.
openmp: Add support for iterators in map clauses (C/C++)
This adds preliminary support for iterators in map clauses within OpenMP
'target' constructs (which includes constructs such as 'target enter data').
Iterators with non-constant loop bounds are not currently supported.
gcc/c/
* c-parser.cc (c_parser_omp_variable_list): Use location of the
map expression as the clause location.
(c_parser_omp_clause_map): Parse 'iterator' modifier.
* c-typeck.cc (c_finish_omp_clauses): Finish iterators. Apply
iterators to generated clauses.
* gimple-pretty-print.cc (dump_gimple_omp_target): Print expanded
iterator loops.
* gimple.cc (gimple_build_omp_target): Add argument for iterator
loops sequence. Initialize iterator loops field.
* gimple.def (GIMPLE_OMP_TARGET): Set GSS symbol to GSS_OMP_TARGET.
* gimple.h (gomp_target): Set GSS symbol to GSS_OMP_TARGET. Add extra
field for iterator loops.
(gimple_build_omp_target): Add argument for iterator loops sequence.
(gimple_omp_target_iterator_loops): New.
(gimple_omp_target_iterator_loops_ptr): New.
(gimple_omp_target_set_iterator_loops): New.
* gimplify.cc (find_var_decl): New.
(copy_omp_iterator): New.
(remap_omp_iterator_var_1): New.
(remap_omp_iterator_var): New.
(remove_unused_omp_iterator_vars): New.
(struct iterator_loop_info_t): New type.
(iterator_loop_info_map_t): New type.
(build_omp_iterators_loops): New.
(enter_omp_iterator_loop_context_1): New.
(enter_omp_iterator_loop_context): New.
(enter_omp_iterator_loop_context): New.
(exit_omp_iterator_loop_context): New.
(gimplify_adjust_omp_clauses): Add argument for iterator loop
sequence. Gimplify the clause decl and size into the iterator
loop if iterators are used.
(gimplify_omp_workshare): Call remove_unused_omp_iterator_vars and
build_omp_iterators_loops for OpenMP target expressions. Add
loop sequence as argument when calling gimplify_adjust_omp_clauses
and building the Gimple statement.
* gimplify.h (enter_omp_iterator_loop_context): New prototype.
(exit_omp_iterator_loop_context): New prototype.
* gsstruct.def (GSS_OMP_TARGET): New.
* omp-low.cc (lower_omp_map_iterator_expr): New.
(lower_omp_map_iterator_size): New.
(finish_omp_map_iterators): New.
(lower_omp_target): Add sorry if iterators used with deep mapping.
Call lower_omp_map_iterator_expr before assigning to sender ref.
Call lower_omp_map_iterator_size before setting the size. Insert
iterator loop sequence before the statements for the target clause.
* tree-nested.cc (convert_nonlocal_reference_stmt): Walk the iterator
loop sequence of OpenMP target statements.
(convert_local_reference_stmt): Likewise.
(convert_tramp_reference_stmt): Likewise.
* tree-pretty-print.cc (dump_omp_iterators): Dump extra iterator
information if present.
(dump_omp_clause): Call dump_omp_iterators for iterators in map
clauses.
* tree.cc (omp_clause_num_ops): Add operand for OMP_CLAUSE_MAP.
(walk_tree_1): Do not walk last operand of OMP_CLAUSE_MAP.
* tree.h (OMP_CLAUSE_HAS_ITERATORS): New.
(OMP_CLAUSE_ITERATORS): New.
Jason Merrill [Tue, 5 Aug 2025 22:16:50 +0000 (15:16 -0700)]
c++: clobber object on placement new [PR121068]
My r16-2432 patch addressed the original testcase involving an array of
scalars, but not this additional testcase involving an array of classes.
This patch addresses the issue more thoroughly, by having placement new
first clobber the new object, and improving cxx_eval_store_expression to
implement initial clobbers as well.
My earlier attempt to do this clobbered the array as a whole, which broke
construct_at after the resolution of LWG3436 due to trying to create a
multidimensional array over the top of a single-dimensional array. To
side-step that issue, this patch instead clobbers the individual elements of
an array, taking advantage of the earlier change to let that activate the
array member of a union.
PR c++/121068
gcc/cp/ChangeLog:
* constexpr.cc (cxx_eval_store_expression): Handle clobbers.
(potential_constant_expression_1): Handle clobbers more.
* decl.cc (build_clobber_this): Use INIT_EXPR for initial clobber.
* init.cc (build_new_1): Clobber on placement new.
(build_vec_init): Don't clean up after clobber.
Mikael Morin [Tue, 5 Aug 2025 12:58:02 +0000 (14:58 +0200)]
fortran: Remove array bound update after constructor expansion
The array constructor expansion extends the size of the array
dynamically, and sets the upper bound appropriately every time it
does. There is no need to do it again at the end of expansion.
gcc/fortran/ChangeLog:
* trans-array.cc (trans_array_constructor): Remove the update of
the array descriptor upper bound after array constructor
expansion.
Mikael Morin [Tue, 5 Aug 2025 12:58:01 +0000 (14:58 +0200)]
fortran: Remove premature initialization of a function result's span
Setting just the span in an otherwise uninitialized array descriptor to
pass to a function that will use the descriptor for its result (thus do
the initialization) doesn't seem to be useful.
gcc/fortran/ChangeLog:
* trans-array.cc (gfc_conv_expr_descriptor): Remove
isolated initialization of the span field before passing to
the function that will do the initialization.
Mikael Morin [Tue, 5 Aug 2025 12:58:00 +0000 (14:58 +0200)]
fortran: Remove default initialization of local pointers's span
A pointer has no default initialization; it is invalid to use it before
it is associated to a target. We can just as well leave its span field
uninitialized, and wait for the first pointer association to define a
span value. The value of zero was an invalid span value anyway.
gcc/fortran/ChangeLog:
* trans-decl.cc (gfc_trans_deferred_vars): Don't default
initialize the span of local pointer arrays.
Mikael Morin [Tue, 5 Aug 2025 12:57:59 +0000 (14:57 +0200)]
fortran: Remove redundant initialisation of associate variable span
In the initialization of associate variable array descriptors, remove
an overwrite of the span field. The descriptor that is returned by
gfc_conv_expr_descriptor should already be usable without it.
The range of cases where the code was in effect is not completely
clear. The span overwrite looks redundant, and the conditional guarding
it seems to make it dead. However, the conditions governing
gfc_conv_expr_descriptor, gfc_get_array_span and trans_associate_var
make it difficult to track what is possible and what isn't. Trying to
investigate the case where the target is an array subreference wrapped
in parenthesis, I encountered a wrong-code issue, PR121384. Let's
remove all this and see what happens.
gcc/fortran/ChangeLog:
* trans-stmt.cc (trans_associate_var): Remove overwrite of the
span field of the associate variable's array descriptor.
Mikael Morin [Tue, 5 Aug 2025 12:57:58 +0000 (14:57 +0200)]
fortran: Remove span overwrite with pointer assignments
Remove an overwrite of the array descriptor span field when pointer-
assigning from a polymorphic function result to a non-polymorphic
pointer. That overwrite doesn't make sense because the span is
determined by the memory layout of the array; we can't change it
without also changing the data pointer.
gcc/fortran/ChangeLog:
* trans-expr.cc (gfc_trans_pointer_assignment): Remove overwrite
of the span after assignment of the array descriptor in the
polymorphic function result to non-polymorphic pointer case.
gets the widest vector mode from MOVE_MAX. But for memset, it should
use STORE_MAX_PIECES.
gcc/
PR target/121410
* config/i386/i386-expand.cc (ix86_expand_set_or_cpymem): Use
STORE_MAX_PIECES to get the widest vector mode in vector loop
for memset.
gcc/testsuite/
PR target/121410
* gcc.target/i386/pr121410.c: New test.
AVR: Allow combination of sign_extend with ashift.
gcc/
* config/avr/avr.cc (avr_rtx_costs_1) [SIGN_EXTEND]: Adjust cost.
* config/avr/avr.md (*sext.ashift<QIPSI:mode><HISI:mode>2): New
insn and a cc split.
* Make-lang.in (rust-readonly-check2.cc):
Add read-only check on HIR
* checks/errors/rust-readonly-check2.cc (ReadonlyChecker):
Add read-only check on HIR
* checks/errors/rust-readonly-check2.h (ReadonlyChecker):
Add read-only check on HIR
* expand/rust-macro-builtins-helpers.cc
(try_extract_string_literal_from_fragment): Perform static_cast
to AST::LiteralExpr only after it's verified that an AST::Expr
is a literal.
This doesn't handle rustc_args_required_const, but it does allow us to
recognize it as a valid attribute.
gcc/rust/ChangeLog:
* util/rust-attribute-values.h
(Attributes::RUSTC_ARGS_REQUIRED_CONST): New constexpr variable.
* util/rust-attributes.cc (__definitions): New entry for
RUSTC_ARGS_REQUIRED_CONST.
Philip Herron [Fri, 1 Aug 2025 10:54:52 +0000 (11:54 +0100)]
gccrs: Remove more calls to the old TyTy::BaseType::can_eq interface
This old can_eq interface was an old method to try and check if types can match up
by taking into account generics but its not maintained properly and we already have
a new wrapper Resolver::types_compatable (type, type, locus, emit_errors) which
just calls unify_site_and infer with commit false. There are only a few places left
to update.
One minor downside is that i need to remove const in some places because the unify
interface is non const. Ideally we would want to avoid writing a seperate const unify
anyway so i think this is not ideal but fine for us.
gccrs: Add rest pattern support for AST::SlicePattern
The main change can be found in ast/rust-pattern.h, which introduces 2 item types for
AST::SlicePattern - one without rest pattern (SlicePatternItemsNoRest) & the other with
it (SlicePatternItemsHasRest). This led to a number of cascading changes as seen in the
changelog.
gcc/rust/ChangeLog:
* ast/rust-ast-collector.cc: Add support for the 2 new classes.
* ast/rust-ast-collector.h: Header file update for above.
* ast/rust-ast-full-decls.h: Add forward decls for the 2 new classes.
* ast/rust-ast-visitor.cc: Add visit support for the 2 new classes.
* ast/rust-ast-visitor.h: Header file update for above.
* ast/rust-pattern.cc: Implementation of certain methods for the 2 new classes.
* ast/rust-pattern.h: Define the 2 new classes. Update SlicePattern to be able to hold
2 kinds of items - SlicePatternItemsNoRest or SlicePatternItemsRest.
* expand/rust-cfg-strip.cc: Add support for the 2 new classes.
* expand/rust-cfg-strip.h: Header file update for above.
* expand/rust-derive.h: Add visits for the 2 new classes.
* hir/rust-ast-lower-base.cc: Add visits for the 2 new classes.
* hir/rust-ast-lower-base.h: Header file update for above.
* hir/rust-ast-lower-pattern.cc: Update lowering of SlicePattern to support
SlicePatternItemsNoRest.
* parse/rust-parse-impl.h (parse_slice_pattern()): Add support for parsing DOT_DOT into
respective SlicePatternItems.
* resolve/rust-ast-resolve-base.cc: Add visits for the 2 new classes.
* resolve/rust-ast-resolve-base.h: Header file update for above.
* resolve/rust-ast-resolve-pattern.cc: Update SlicePattern resolution to support new
classes.
Philip Herron [Thu, 31 Jul 2025 20:18:56 +0000 (21:18 +0100)]
gccrs: Support const generic inference variables
We already support const infer so this just creates a fresh tyty::infer_var
for the const element type and then a ConstKind::Infer type for the const
type wrapper and the existing plumbing handles this.
Philip Herron [Sun, 27 Jul 2025 20:47:54 +0000 (21:47 +0100)]
gccrs: Add initial support for const generics
In order to support const generics we map the declarations to a ConstType this
means we reuse all our existing type coercion, unification code and generic
substitutions code to support this with minimal impact.
This patch adds support for:
1. Default const generics
2. Infer const generics
3. ADTType suport
4. unconstrained checks
5. ensure types of the const generic and default
6. validation if passing a const argument to a type argument
Lots of test cases now work and new ones added. More work is needed to support this
on functions and method resolution of impls like Foo<1> vs Foo<2> once thats in we
can look to support some of the const generic array impls next.
gcc/rust/ChangeLog:
* backend/rust-compile-base.cc: useful debug
* backend/rust-compile-stmt.cc (CompileStmt::visit): likewise
* backend/rust-compile-type.cc (TyTyResolveCompile::visit): fold the capacity into ConstType
* hir/tree/rust-hir-generic-param.h: make const
* hir/tree/rust-hir-path.h: take into account const arguments now
* typecheck/rust-hir-type-check-base.cc (TypeCheckBase::resolve_literal): needs const
* typecheck/rust-hir-type-check-base.h: add error handling for const supported locations
* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): const type the arrays
* typecheck/rust-hir-type-check-implitem.cc (TypeCheckTopLevelExternItem::visit): update
(TypeCheckImplItem::visit): likewise
* typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): likewise
(TypeCheckItem::resolve_impl_block_substitutions): likewise
* typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): wrap up const type
* typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): likewise
(TypeResolveGenericParam::visit): likewise
(TypeResolveGenericParam::apply_trait_bounds): remove HIR::Generic from Param
* typecheck/rust-hir-type-check.cc (TraitItemReference::get_type_from_fn): cleanup
* typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::SubstitutionParamMapping):
handle const generics
(SubstitutionParamMapping::get_type_representation): likewise
(SubstitutionParamMapping::param_has_default_ty): likewise
(SubstitutionParamMapping::get_default_ty): likewise
(SubstitutionRef::infer_substitions): likewise
* typecheck/rust-tyty-subst.h: likewise
* typecheck/rust-tyty-util.cc (TyVar::get_implicit_const_infer_var): new helper
* typecheck/rust-tyty-util.h (class ConstType): likewise
* typecheck/rust-tyty.cc (BaseType::is_concrete): check for array const concrete
(ArrayType::as_string): update to const
(ArrayType::handle_substitions): likewise
(ParamType::ParamType): likewise
(ParamType::get_generic_param): likewise
(ParamType::clone): likewise
(ConstType::ConstType): likewise
(ConstType::set_value): likewise
(ConstType::clone): likewise
(ConstType::get_generic_param): likewise
(generate_tree_str): new helper to pretty print gimple
(ConstType::get_name): uses the generate_tree_str
(ConstType::handle_substitions): handle const infer's
* typecheck/rust-tyty.h (RUST_TYTY): likewise
* typecheck/rust-unify.cc (UnifyRules::expect_array): likewise
(UnifyRules::expect_const): likewise
gcc/testsuite/ChangeLog:
* rust/compile/const_generics_3.rs: this works now
* rust/compile/const_generics_5.rs: likewise
* rust/compile/const_generics_8.rs: move the failure to another test case
* rust/compile/const_generics_10.rs: New test.
* rust/compile/const_generics_11.rs: New test.
* rust/compile/const_generics_12.rs: New test.
* rust/compile/const_generics_13.rs: New test.
* rust/compile/const_generics_14.rs: New test.
* rust/compile/const_generics_15.rs: New test.
* rust/compile/const_generics_16.rs: New test.
* rust/compile/const_generics_9.rs: New test.
Signed-off-by: Philip Herron <herron.philip@googlemail.com>
Philip Herron [Sun, 27 Jul 2025 19:19:41 +0000 (20:19 +0100)]
gccrs: Add ConstType boiler plate to handle const generics
This patch is all about just putting in the boiler plate for the new
BaseGeneric TyTy::ConstType. Nothing is really change but just the
nessecary cogs added to the machine.
Philip Herron [Fri, 25 Jul 2025 16:49:15 +0000 (17:49 +0100)]
gccrs: Refactor the ParamType to a BaseGeneric base-type
In order to support const generics we need to abstract away some of the specific
ParamType to a BaseGeneric type so we can easily reuse our existing substitution
bits for const generics which will mean creating a TyTy::ConstType to wrap up
the gcc tree but also represent a const inference and the const decl.
Philip Herron [Fri, 25 Jul 2025 15:56:17 +0000 (16:56 +0100)]
gccrs: Refactor substitution param mapping to be more abstract
This is an initial patch required to refactor our generics code to be
simpler and more abstract so we return the HIR::GenericParam in ParamMappings
instead of assuming its a TypeParam so we can slowly introduce ConstGenericParam
into this same flow.
gcc/rust/ChangeLog:
* typecheck/rust-hir-type-check-base.cc: check for type param
* typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::SubstitutionParamMapping):
return HIR::GenericParam base class
(SubstitutionParamMapping::get_generic_param): likewise
(SubstitutionParamMapping::get_type_representation): new helper
(SubstitutionParamMapping::param_has_default_ty): check for param type
(SubstitutionParamMapping::get_default_ty): likewise
* typecheck/rust-tyty-subst.h: get the locus from the subst HIR::GenericParam now
* typecheck/rust-tyty-variance-analysis.cc (GenericTyPerCrateCtx::debug_print_solutions):
likwise
(GenericTyVisitorCtx::process_type): likewise
Signed-off-by: Philip Herron <herron.philip@googlemail.com>
Philip Herron [Thu, 31 Jul 2025 20:46:42 +0000 (21:46 +0100)]
gccrs: Fix ICE during const eval of const capacity
We assert that struct expressions during code-gen must be of TyTy::ADTType
but we can simply just check for this and return error_mark_node to make
this safe.
Fixes Rust-GCC#3960
gcc/rust/ChangeLog:
* backend/rust-compile-expr.cc (CompileExpr::visit): check for ADTType instead of assert
gcc/testsuite/ChangeLog:
* rust/compile/issue-3960.rs: New test.
Signed-off-by: Philip Herron <herron.philip@googlemail.com>