aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-12-04 14:51:32 -0800
committerIan Lance Taylor <iant@golang.org>2020-12-04 14:51:32 -0800
commit945ae3ab27757d3261d99446f96105c5ebe70247 (patch)
treea8a120ef5393206d3bc9d2b5882bac1562824836
parentf012991e2db06cc95f7aac8ecb74a1ac5f51f3d2 (diff)
parent918a5b84a2c51dc9d011d39461cc276e6558069d (diff)
downloadgcc-945ae3ab27757d3261d99446f96105c5ebe70247.zip
gcc-945ae3ab27757d3261d99446f96105c5ebe70247.tar.gz
gcc-945ae3ab27757d3261d99446f96105c5ebe70247.tar.bz2
Merge from trunk revision 918a5b84a2c51dc9d011d39461cc276e6558069d
-rwxr-xr-xcontrib/check-params-in-docs.py12
-rw-r--r--gcc/ChangeLog186
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/builtins.c423
-rw-r--r--gcc/builtins.h10
-rw-r--r--gcc/c-family/ChangeLog15
-rw-r--r--gcc/c-family/c-attribs.c180
-rw-r--r--gcc/c-family/c.opt10
-rw-r--r--gcc/calls.c4
-rw-r--r--gcc/cfgexpand.c7
-rw-r--r--gcc/common.opt8
-rw-r--r--gcc/config/i386/i386.md32
-rw-r--r--gcc/config/rs6000/rs6000.c6
-rw-r--r--gcc/cp/ChangeLog67
-rw-r--r--gcc/cp/cp-gimplify.c2
-rw-r--r--gcc/cp/cp-tree.h134
-rw-r--r--gcc/cp/decl2.c2
-rw-r--r--gcc/cp/parser.c6
-rw-r--r--gcc/cp/pt.c35
-rw-r--r--gcc/cp/tree.c55
-rw-r--r--gcc/cp/typeck.c19
-rw-r--r--gcc/doc/extend.texi61
-rw-r--r--gcc/doc/implement-c.texi5
-rw-r--r--gcc/doc/invoke.texi145
-rw-r--r--gcc/doc/tm.texi38
-rw-r--r--gcc/dwarf2out.c306
-rw-r--r--gcc/fold-const.c10
-rw-r--r--gcc/fortran/ChangeLog6
-rw-r--r--gcc/gimple.c3
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/ipa-sra.c2
-rw-r--r--gcc/opts.c119
-rw-r--r--gcc/opts.h6
-rw-r--r--gcc/target.def38
-rw-r--r--gcc/target.h14
-rw-r--r--gcc/testsuite/ChangeLog145
-rw-r--r--gcc/testsuite/g++.dg/asan/asan_test.cc2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/bit-cast6.C31
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-nodiscard1.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class40.C79
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/srcloc1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/srcloc15.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/srcloc17.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/srcloc2.C2
-rw-r--r--gcc/testsuite/g++.dg/opt/pr98130.C25
-rw-r--r--gcc/testsuite/g++.dg/template/pr98116.C6
-rw-r--r--gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-2.C274
-rw-r--r--gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.C124
-rw-r--r--gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.s0
-rw-r--r--gcc/testsuite/g++.dg/warn/Wmismatched-dealloc-2.C185
-rw-r--r--gcc/testsuite/g++.dg/warn/Wmismatched-dealloc.C27
-rw-r--r--gcc/testsuite/g++.dg/warn/Wmismatched-new-delete.C212
-rw-r--r--gcc/testsuite/g++.dg/warn/delete-array-1.C6
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/delete2.C2
-rw-r--r--gcc/testsuite/gcc.dg/Wfree-nonheap-object-2.c279
-rw-r--r--gcc/testsuite/gcc.dg/Wfree-nonheap-object-3.c57
-rw-r--r--gcc/testsuite/gcc.dg/Wfree-nonheap-object.c273
-rw-r--r--gcc/testsuite/gcc.dg/Wmismatched-dealloc.c252
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/malloc-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/attr-malloc.c75
-rw-r--r--gcc/testsuite/gcc.dg/free-1.c18
-rw-r--r--gcc/testsuite/gcc.dg/free-2.c18
-rw-r--r--gcc/testsuite/gcc.dg/pr98099.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr71816.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-4.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-6.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-8.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr96226.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/pr98100.c9
-rw-r--r--gcc/testsuite/gnat.dg/opt91.adb11
-rw-r--r--gcc/testsuite/gnat.dg/opt91.ads10
-rw-r--r--gcc/testsuite/gnat.dg/opt91_pkg.adb12
-rw-r--r--gcc/testsuite/gnat.dg/opt91_pkg.ads19
-rw-r--r--gcc/toplev.c176
-rw-r--r--gcc/tree.c2
-rw-r--r--gcc/varasm.c48
-rw-r--r--gcc/vec.h10
-rw-r--r--libgcc/ChangeLog18
-rw-r--r--libgo/runtime/go-fieldtrack.c2
-rw-r--r--libstdc++-v3/ChangeLog54
-rw-r--r--libstdc++-v3/testsuite/18_support/source_location/1.cc16
-rw-r--r--libstdc++-v3/testsuite/18_support/source_location/consteval.cc16
-rw-r--r--libstdc++-v3/testsuite/ext/vstring/modifiers/clear/56166.cc8
84 files changed, 3847 insertions, 681 deletions
diff --git a/contrib/check-params-in-docs.py b/contrib/check-params-in-docs.py
index dfbfa3d..440549f 100755
--- a/contrib/check-params-in-docs.py
+++ b/contrib/check-params-in-docs.py
@@ -23,6 +23,7 @@
#
import argparse
+import sys
from itertools import dropwhile, takewhile
@@ -42,7 +43,7 @@ parser.add_argument('params_output')
args = parser.parse_args()
-ignored = set(['logical-op-non-short-circuit'])
+ignored = {'logical-op-non-short-circuit'}
params = {}
for line in open(args.params_output).readlines():
@@ -58,15 +59,21 @@ texi = list(texi)[1:]
token = '@item '
texi = [x[len(token):] for x in texi if x.startswith(token)]
+# skip digits
+texi = [x for x in texi if not x[0].isdigit()]
+# skip aarch64 params
+texi = [x for x in texi if not x.startswith('aarch64')]
sorted_texi = sorted(texi)
texi_set = set(texi) - ignored
params_set = set(params.keys()) - ignored
+success = True
extra = texi_set - params_set
if len(extra):
print('Extra:')
print(extra)
+ success = False
missing = params_set - texi_set
if len(missing):
@@ -75,6 +82,9 @@ if len(missing):
print('@item ' + m)
print(params[m])
print()
+ success = False
if texi != sorted_texi:
print('WARNING: not sorted alphabetically!')
+
+sys.exit(0 if success else 1)
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7e76b2f..44dadd3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,189 @@
+2020-12-03 Martin Sebor <msebor@redhat.com>
+
+ PR c++/90629
+ PR middle-end/94527
+ * builtins.c (access_ref::access_ref): Initialize new member.
+ (compute_objsize): Use access_ref::deref. Handle simple pointer
+ assignment.
+ (expand_builtin): Remove handling of the free built-in.
+ (call_dealloc_argno): Same.
+ (find_assignment_location): New function.
+ (fndecl_alloc_p): Same.
+ (gimple_call_alloc_p): Same.
+ (call_dealloc_p): Same.
+ (matching_alloc_calls_p): Same.
+ (warn_dealloc_offset): Same.
+ (maybe_emit_free_warning): Same.
+ * builtins.h (struct access_ref): Declare new member.
+ (maybe_emit_free_warning): Make extern. Make use of access_ref.
+ Handle -Wmismatched-new-delete.
+ * calls.c (initialize_argument_information): Call
+ maybe_emit_free_warning.
+ * doc/extend.texi (attribute malloc): Update.
+ * doc/invoke.texi (-Wfree-nonheap-object): Expand documentation.
+ (-Wmismatched-new-delete): Document new option.
+ (-Wmismatched-dealloc): Document new option.
+
+2020-12-03 Alexandre Oliva <oliva@adacore.com>
+
+ * tree.c (build_common_builtin_nodes): Declare
+ __builtin___clear_cache for all languages.
+ * builtins.c (maybe_emit_call_builtin___clear_cache): Accept
+ Pmode arguments.
+
+2020-12-03 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * config/arm/t-rtems: Add "-mthumb -mcpu=cortex-r52
+ -mfloat-abi=hard" multilib.
+
+2020-12-03 Uroš Bizjak <ubizjak@gmail.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR target/98086
+ * config/i386/i386.c (ix86_md_asm_adjustmd): Rewrite
+ zero-extension part to use convert_to_mode.
+
+2020-12-03 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * config/s390/s390.md ("@probe_stack2<mode>"): Change mode
+ iterator to W.
+
+2020-12-03 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-sve-builtins-base.cc (svundef_impl::fold):
+ Delete.
+
+2020-12-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR middle-end/98099
+ * expmed.c (flip_storage_order): In the case of a non-integer mode,
+ sorry out if the integer mode to be used instead is not supported.
+
+2020-12-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR middle-end/98082
+ * function.c (use_register_for_decl): Also return true for a result
+ if cfun->tail_call_marked is true.
+
+2020-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR libstdc++/93121
+ * fold-const.h (native_encode_initializer): Add mask argument
+ defaulted to nullptr.
+ (find_bitfield_repr_type): Declare.
+ (native_interpret_aggregate): Declare.
+ * fold-const.c (find_bitfield_repr_type): New function.
+ (native_encode_initializer): Add mask argument and support for
+ filling it. Handle also some bitfields without integral
+ DECL_BIT_FIELD_REPRESENTATIVE.
+ (native_interpret_aggregate): New function.
+ * gimple-fold.h (clear_type_padding_in_mask): Declare.
+ * gimple-fold.c (struct clear_padding_struct): Add clear_in_mask
+ member.
+ (clear_padding_flush): Handle buf->clear_in_mask.
+ (clear_padding_union): Copy clear_in_mask. Don't error if
+ buf->clear_in_mask is set.
+ (clear_padding_type): Don't error if buf->clear_in_mask is set.
+ (clear_type_padding_in_mask): New function.
+ (gimple_fold_builtin_clear_padding): Set buf.clear_in_mask to false.
+ * doc/extend.texi (__builtin_bit_cast): Document.
+
+2020-12-03 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * tree-ssa-threadedge.c (record_temporary_equivalences_from_stmts_at_dest):
+ Do not allow __builtin_constant_p on a threading path.
+
+2020-12-03 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * tree-ssa-strlen.c (printf_strlen_execute): Avoid division by
+ 0.
+
+2020-12-03 Kito Cheng <kito.cheng@sifive.com>
+
+ * config/riscv/multilib-generator (arch_canonicalize): Move
+ code to arch-canonicalize, and call that script to canonicalize arch
+ string.
+ (canonical_order): Move code to arch-canonicalize.
+ (LONG_EXT_PREFIXES): Ditto.
+ (IMPLIED_EXT): Ditto.
+ * config/riscv/arch-canonicalize: New.
+ * config.gcc (riscv*-*-*): Canonicalize --with-arch.
+
+2020-12-03 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/aarch64/aarch64-option-extensions.def
+ (AARCH64_OPT_EXTENSION): New +flagm option in -march for AArch64.
+ * config/aarch64/aarch64.h (AARCH64_FL_FLAGM): Add new flagm extension bit
+ mask.
+ (AARCH64_FL_FOR_ARCH8_4): Add flagm to Armv8.4-A.
+ * doc/invoke.texi: Update docs with +flagm.
+
+2020-12-03 liuhongt <hongtao.liu@intel.com>
+
+ PR target/96906
+ * config/i386/sse.md
+ (<avx512>_ucmp<mode>3<mask_scalar_merge_name>): Add a new
+ define_split after this insn.
+
+2020-12-03 liuhongt <hongtao.liu@intel.com>
+
+ PR target/97642
+ * config/i386/i386-expand.c
+ (ix86_expand_special_args_builtin): Don't move all-ones mask
+ operands into register.
+ * config/i386/sse.md (UNSPEC_MASKLOAD): New unspec.
+ (*<avx512>_load<mode>_mask): New define_insns for masked load
+ instructions.
+ (<avx512>_load<mode>_mask): Changed to define_expands which
+ specifically handle memory or all-ones mask operands.
+ (<avx512>_blendm<mode>): Changed to define_insns which are same
+ as original <avx512>_load<mode>_mask with adjustment of
+ operands order.
+ (*<avx512>_load<mode>): New define_insn_and_split which is
+ used to optimize for masked load with all one mask.
+
+2020-12-03 Hongyu Wang <hongyu.wang@intel.com>
+
+ PR target/97770
+ * config/i386/sse.md (popcount<mode>2): New expander
+ for SI/DI vector modes.
+ (popcount<mode>2): Likewise for QI/HI vector modes.
+
+2020-12-03 Alexandre Oliva <oliva@adacore.com>
+
+ * builtins.c (default_emit_call_builtin___clear_cache): New.
+ (maybe_emit_call_builtin___clear_cache): New.
+ (expand_builtin___clear_cache): Split into the above.
+ (expand_builtin): Do not issue clear_cache call any more.
+ * builtins.h (maybe_emit_call_builtin___clear_cache): Declare.
+ * config/aarch64/aarch64.c (aarch64_trampoline_init): Use
+ maybe_emit_call_builtin___clear_cache.
+ * config/arc/arc.c (arc_trampoline_init): Likewise.
+ * config/arm/arm.c (arm_trampoline_init): Likewise.
+ * config/c6x/c6x.c (c6x_initialize_trampoline): Likewise.
+ * config/csky/csky.c (csky_trampoline_init): Likewise.
+ * config/m68k/linux.h (FInALIZE_TRAMPOLINE): Likewise.
+ * config/tilegx/tilegx.c (tilegx_trampoline_init): Likewise.
+ * config/tilepro/tilepro.c (tilepro_trampoline_init): Ditto.
+ * config/vxworks.c: Include rtl.h, memmodel.h, and optabs.h.
+ (vxworks_emit_call_builtin___clear_cache): New.
+ * config/vxworks.h (CLEAR_INSN_CACHE): Drop.
+ (TARGET_EMIT_CALL_BUILTIN___CLEAR_CACHE): Define.
+ * target.def (trampoline_init): In the documentation, refer to
+ maybe_emit_call_builtin___clear_cache.
+ (emit_call_builtin___clear_cache): New.
+ * doc/tm.texi.in: Add new hook point.
+ (CLEAR_CACHE_INSN): Remove duplicate 'both'.
+ * doc/tm.texi: Rebuilt.
+ * targhooks.h (default_meit_call_builtin___clear_cache):
+ Declare.
+ * tree.h (BUILTIN_ASM_NAME_PTR): New.
+
+2020-12-03 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * tree-ssa-threadbackward.c (thread_jumps::profitable_jump_thread_path):
+ Do not allow __builtin_constant_p on a threading path.
+
2020-12-02 Jakub Jelinek <jakub@redhat.com>
* dwarf2out.c (add_scalar_info): Only use add_AT_wide for 128-bit
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 81e21c8..3fac2aa 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20201203
+20201204
diff --git a/gcc/builtins.c b/gcc/builtins.c
index cd30de8..bd12659 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -73,6 +73,7 @@ along with GCC; see the file COPYING3. If not see
#include "gomp-constants.h"
#include "omp-general.h"
#include "tree-dfa.h"
+#include "gimple-iterator.h"
#include "gimple-ssa.h"
#include "tree-ssa-live.h"
#include "tree-outof-ssa.h"
@@ -182,7 +183,6 @@ static rtx expand_builtin_memory_chk (tree, rtx, machine_mode,
enum built_in_function);
static void maybe_emit_chk_warning (tree, enum built_in_function);
static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
-static void maybe_emit_free_warning (tree);
static tree fold_builtin_object_size (tree, tree);
static bool check_read_access (tree, tree, tree = NULL_TREE, int = 1);
static bool compute_objsize_r (tree, int, access_ref *, ssa_name_limit_t &,
@@ -201,8 +201,8 @@ static void expand_builtin_sync_synchronize (void);
access_ref::access_ref (tree bound /* = NULL_TREE */,
bool minaccess /* = false */)
-: ref (), eval ([](tree x){ return x; }), trail1special (true), base0 (true),
- parmarray ()
+: ref (), eval ([](tree x){ return x; }), deref (), trail1special (true),
+ base0 (true), parmarray ()
{
/* Set to valid. */
offrng[0] = offrng[1] = 0;
@@ -5313,7 +5313,10 @@ compute_objsize_r (tree ptr, int ostype, access_ref *pref,
const bool addr = TREE_CODE (ptr) == ADDR_EXPR;
if (addr)
- ptr = TREE_OPERAND (ptr, 0);
+ {
+ --pref->deref;
+ ptr = TREE_OPERAND (ptr, 0);
+ }
if (DECL_P (ptr))
{
@@ -5421,6 +5424,8 @@ compute_objsize_r (tree ptr, int ostype, access_ref *pref,
if (code == ARRAY_REF || code == MEM_REF)
{
+ ++pref->deref;
+
tree ref = TREE_OPERAND (ptr, 0);
tree reftype = TREE_TYPE (ref);
if (!addr && code == ARRAY_REF
@@ -5544,6 +5549,10 @@ compute_objsize_r (tree ptr, int ostype, access_ref *pref,
if (!compute_objsize_r (ref, ostype, pref, snlim, qry))
return false;
+ /* Clear DEREF since the offset is being applied to the target
+ of the dereference. */
+ pref->deref = 0;
+
offset_int orng[2];
tree off = pref->eval (TREE_OPERAND (ptr, 1));
if (get_offset_range (off, NULL, orng, rvals))
@@ -10630,11 +10639,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
maybe_emit_sprintf_chk_warning (exp, fcode);
break;
- case BUILT_IN_FREE:
- if (warn_free_nonheap_object)
- maybe_emit_free_warning (exp);
- break;
-
case BUILT_IN_THREAD_POINTER:
return expand_builtin_thread_pointer (exp, target);
@@ -12944,30 +12948,403 @@ maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
access_write_only);
}
-/* Emit warning if a free is called with address of a variable. */
+/* Return true if STMT is a call to an allocation function. Unless
+ ALL_ALLOC is set, consider only functions that return dynmamically
+ allocated objects. Otherwise return true even for all forms of
+ alloca (including VLA). */
-static void
+static bool
+fndecl_alloc_p (tree fndecl, bool all_alloc)
+{
+ if (!fndecl)
+ return false;
+
+ /* A call to operator new isn't recognized as one to a built-in. */
+ if (DECL_IS_OPERATOR_NEW_P (fndecl))
+ return true;
+
+ if (fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
+ {
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ case BUILT_IN_ALLOCA:
+ case BUILT_IN_ALLOCA_WITH_ALIGN:
+ return all_alloc;
+ case BUILT_IN_CALLOC:
+ case BUILT_IN_MALLOC:
+ case BUILT_IN_REALLOC:
+ case BUILT_IN_STRDUP:
+ case BUILT_IN_STRNDUP:
+ return true;
+ default:
+ break;
+ }
+ }
+
+ /* A function is considered an allocation function if it's declared
+ with attribute malloc with an argument naming its associated
+ deallocation function. */
+ tree attrs = DECL_ATTRIBUTES (fndecl);
+ if (!attrs)
+ return false;
+
+ for (tree allocs = attrs;
+ (allocs = lookup_attribute ("malloc", allocs));
+ allocs = TREE_CHAIN (allocs))
+ {
+ tree args = TREE_VALUE (allocs);
+ if (!args)
+ continue;
+
+ if (TREE_VALUE (args))
+ return true;
+ }
+
+ return false;
+}
+
+/* Return true if STMT is a call to an allocation function. A wrapper
+ around fndecl_alloc_p. */
+
+static bool
+gimple_call_alloc_p (gimple *stmt, bool all_alloc = false)
+{
+ return fndecl_alloc_p (gimple_call_fndecl (stmt), all_alloc);
+}
+
+/* Return the zero-based number corresponding to the argument being
+ deallocated if STMT is a call to a deallocation function or UINT_MAX
+ if it isn't. */
+
+static unsigned
+call_dealloc_argno (tree exp)
+{
+ tree fndecl = get_callee_fndecl (exp);
+ if (!fndecl)
+ return UINT_MAX;
+
+ /* A call to operator delete isn't recognized as one to a built-in. */
+ if (DECL_IS_OPERATOR_DELETE_P (fndecl))
+ return 0;
+
+ /* TODO: Handle user-defined functions with attribute malloc? Handle
+ known non-built-ins like fopen? */
+ if (fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
+ {
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ case BUILT_IN_FREE:
+ case BUILT_IN_REALLOC:
+ return 0;
+ default:
+ break;
+ }
+ return UINT_MAX;
+ }
+
+ tree attrs = DECL_ATTRIBUTES (fndecl);
+ if (!attrs)
+ return UINT_MAX;
+
+ for (tree atfree = attrs;
+ (atfree = lookup_attribute ("*dealloc", atfree));
+ atfree = TREE_CHAIN (atfree))
+ {
+ tree alloc = TREE_VALUE (atfree);
+ if (!alloc)
+ continue;
+
+ tree pos = TREE_CHAIN (alloc);
+ if (!pos)
+ return 0;
+
+ pos = TREE_VALUE (pos);
+ return TREE_INT_CST_LOW (pos) - 1;
+ }
+
+ return UINT_MAX;
+}
+
+/* Return true if STMT is a call to a deallocation function. */
+
+static inline bool
+call_dealloc_p (tree exp)
+{
+ return call_dealloc_argno (exp) != UINT_MAX;
+}
+
+/* ALLOC_DECL and DEALLOC_DECL are pair of allocation and deallocation
+ functions. Return true if the latter is suitable to deallocate objects
+ allocated by calls to the former. */
+
+static bool
+matching_alloc_calls_p (tree alloc_decl, tree dealloc_decl)
+{
+ if (DECL_IS_OPERATOR_NEW_P (alloc_decl))
+ {
+ if (DECL_IS_OPERATOR_DELETE_P (dealloc_decl))
+ {
+ /* Return true iff both functions are of the same array or
+ singleton form and false otherwise. */
+ tree alloc_id = DECL_NAME (alloc_decl);
+ tree dealloc_id = DECL_NAME (dealloc_decl);
+ const char *alloc_fname = IDENTIFIER_POINTER (alloc_id);
+ const char *dealloc_fname = IDENTIFIER_POINTER (dealloc_id);
+ return !strchr (alloc_fname, '[') == !strchr (dealloc_fname, '[');
+ }
+
+ /* Return false for deallocation functions that are known not
+ to match. */
+ if (fndecl_built_in_p (dealloc_decl, BUILT_IN_FREE)
+ || fndecl_built_in_p (dealloc_decl, BUILT_IN_REALLOC))
+ return false;
+ /* Otherwise proceed below to check the deallocation function's
+ "*dealloc" attributes to look for one that mentions this operator
+ new. */
+ }
+ else if (fndecl_built_in_p (alloc_decl, BUILT_IN_NORMAL))
+ {
+ switch (DECL_FUNCTION_CODE (alloc_decl))
+ {
+ case BUILT_IN_ALLOCA:
+ case BUILT_IN_ALLOCA_WITH_ALIGN:
+ return false;
+
+ case BUILT_IN_CALLOC:
+ case BUILT_IN_MALLOC:
+ case BUILT_IN_REALLOC:
+ case BUILT_IN_STRDUP:
+ case BUILT_IN_STRNDUP:
+ if (DECL_IS_OPERATOR_DELETE_P (dealloc_decl))
+ return false;
+
+ if (fndecl_built_in_p (dealloc_decl, BUILT_IN_FREE)
+ || fndecl_built_in_p (dealloc_decl, BUILT_IN_REALLOC))
+ return true;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* If DEALLOC_DECL has internal "*dealloc" attribute scan the list of
+ its associated allocation functions for ALLOC_DECL. If it's found
+ they are a matching pair, otherwise they're not. */
+ tree attrs = DECL_ATTRIBUTES (dealloc_decl);
+ if (!attrs)
+ return false;
+
+ for (tree funs = attrs;
+ (funs = lookup_attribute ("*dealloc", funs));
+ funs = TREE_CHAIN (funs))
+ {
+ tree args = TREE_VALUE (funs);
+ if (!args)
+ continue;
+
+ tree fname = TREE_VALUE (args);
+ if (!fname)
+ continue;
+
+ if (fname == DECL_NAME (alloc_decl))
+ return true;
+ }
+
+ return false;
+}
+
+/* Return true if DEALLOC_DECL is a function suitable to deallocate
+ objectes allocated by the ALLOC call. */
+
+static bool
+matching_alloc_calls_p (gimple *alloc, tree dealloc_decl)
+{
+ tree alloc_decl = gimple_call_fndecl (alloc);
+ if (!alloc_decl)
+ return true;
+
+ return matching_alloc_calls_p (alloc_decl, dealloc_decl);
+}
+
+/* Diagnose a call to FNDECL to deallocate a pointer referenced by
+ AREF that includes a nonzero offset. Such a pointer cannot refer
+ to the beginning of an allocated object. A negative offset may
+ refer to it only if the target pointer is unknown. */
+
+static bool
+warn_dealloc_offset (location_t loc, tree exp, tree fndecl,
+ const access_ref &aref)
+{
+ char offstr[80];
+ offstr[0] = '\0';
+ if (wi::fits_shwi_p (aref.offrng[0]))
+ {
+ if (aref.offrng[0] == aref.offrng[1]
+ || !wi::fits_shwi_p (aref.offrng[1]))
+ sprintf (offstr, " %lli",
+ (long long)aref.offrng[0].to_shwi ());
+ else
+ sprintf (offstr, " [%lli, %lli]",
+ (long long)aref.offrng[0].to_shwi (),
+ (long long)aref.offrng[1].to_shwi ());
+ }
+
+ if (!warning_at (loc, OPT_Wfree_nonheap_object,
+ "%K%qD called on pointer %qE with nonzero offset%s",
+ exp, fndecl, aref.ref, offstr))
+ return false;
+
+ if (DECL_P (aref.ref))
+ inform (DECL_SOURCE_LOCATION (aref.ref), "declared here");
+ else if (TREE_CODE (aref.ref) == SSA_NAME)
+ {
+ gimple *def_stmt = SSA_NAME_DEF_STMT (aref.ref);
+ if (is_gimple_call (def_stmt))
+ {
+ tree alloc_decl = gimple_call_fndecl (def_stmt);
+ inform (gimple_location (def_stmt),
+ "returned from a call to %qD", alloc_decl);
+ }
+ }
+
+ return true;
+}
+
+/* Issue a warning if a deallocation function such as free, realloc,
+ or C++ operator delete is called with an argument not returned by
+ a matching allocation function such as malloc or the corresponding
+ form of C++ operatorn new. */
+
+void
maybe_emit_free_warning (tree exp)
{
- if (call_expr_nargs (exp) != 1)
+ tree fndecl = get_callee_fndecl (exp);
+ if (!fndecl)
return;
- tree arg = CALL_EXPR_ARG (exp, 0);
+ unsigned argno = call_dealloc_argno (exp);
+ if ((unsigned) call_expr_nargs (exp) <= argno)
+ return;
- STRIP_NOPS (arg);
- if (TREE_CODE (arg) != ADDR_EXPR)
+ tree ptr = CALL_EXPR_ARG (exp, argno);
+ if (integer_zerop (ptr))
return;
- arg = get_base_address (TREE_OPERAND (arg, 0));
- if (arg == NULL || INDIRECT_REF_P (arg) || TREE_CODE (arg) == MEM_REF)
+ access_ref aref;
+ if (!compute_objsize (ptr, 0, &aref))
return;
- if (SSA_VAR_P (arg))
- warning_at (tree_nonartificial_location (exp), OPT_Wfree_nonheap_object,
- "%Kattempt to free a non-heap object %qD", exp, arg);
- else
- warning_at (tree_nonartificial_location (exp), OPT_Wfree_nonheap_object,
- "%Kattempt to free a non-heap object", exp);
+ tree ref = aref.ref;
+ if (integer_zerop (ref))
+ return;
+
+ tree dealloc_decl = get_callee_fndecl (exp);
+ location_t loc = tree_nonartificial_location (exp);
+ loc = expansion_point_location_if_in_system_header (loc);
+
+ if (DECL_P (ref) || EXPR_P (ref))
+ {
+ /* Diagnose freeing a declared object. */
+ if (aref.ref_declared ()
+ && warning_at (loc, OPT_Wfree_nonheap_object,
+ "%K%qD called on unallocated object %qD",
+ exp, dealloc_decl, ref))
+ {
+ inform (DECL_SOURCE_LOCATION (ref),
+ "declared here");
+ return;
+ }
+
+ /* Diagnose freeing a pointer that includes a positive offset.
+ Such a pointer cannot refer to the beginning of an allocated
+ object. A negative offset may refer to it. */
+ if (!aref.deref
+ && aref.sizrng[0] != aref.sizrng[1]
+ && aref.offrng[0] > 0 && aref.offrng[1] > 0
+ && warn_dealloc_offset (loc, exp, dealloc_decl, aref))
+ return;
+ }
+ else if (CONSTANT_CLASS_P (ref))
+ {
+ if (warning_at (loc, OPT_Wfree_nonheap_object,
+ "%K%qD called on a pointer to an unallocated "
+ "object %qE", exp, dealloc_decl, ref))
+ {
+ if (TREE_CODE (ptr) == SSA_NAME)
+ {
+ gimple *def_stmt = SSA_NAME_DEF_STMT (ptr);
+ if (is_gimple_assign (def_stmt))
+ {
+ location_t loc = gimple_location (def_stmt);
+ inform (loc, "assigned here");
+ }
+ }
+ return;
+ }
+ }
+ else if (TREE_CODE (ref) == SSA_NAME)
+ {
+ /* Also warn if the pointer argument refers to the result
+ of an allocation call like alloca or VLA. */
+ gimple *def_stmt = SSA_NAME_DEF_STMT (ref);
+ if (is_gimple_call (def_stmt))
+ {
+ bool warned = false;
+ if (gimple_call_alloc_p (def_stmt))
+ {
+ if (matching_alloc_calls_p (def_stmt, dealloc_decl))
+ {
+ if (!aref.deref
+ && aref.offrng[0] > 0 && aref.offrng[1] > 0
+ && warn_dealloc_offset (loc, exp, dealloc_decl, aref))
+ return;
+ }
+ else
+ {
+ tree alloc_decl = gimple_call_fndecl (def_stmt);
+ int opt = (DECL_IS_OPERATOR_NEW_P (alloc_decl)
+ || DECL_IS_OPERATOR_DELETE_P (dealloc_decl)
+ ? OPT_Wmismatched_new_delete
+ : OPT_Wmismatched_dealloc);
+ warned = warning_at (loc, opt,
+ "%K%qD called on pointer returned "
+ "from a mismatched allocation "
+ "function", exp, dealloc_decl);
+ }
+ }
+ else if (gimple_call_builtin_p (def_stmt, BUILT_IN_ALLOCA)
+ || gimple_call_builtin_p (def_stmt,
+ BUILT_IN_ALLOCA_WITH_ALIGN))
+ warned = warning_at (loc, OPT_Wfree_nonheap_object,
+ "%K%qD called on pointer to "
+ "an unallocated object",
+ exp, dealloc_decl);
+ else if (!aref.deref
+ && aref.offrng[0] > 0 && aref.offrng[1] > 0
+ && warn_dealloc_offset (loc, exp, dealloc_decl, aref))
+ return;
+
+ if (warned)
+ {
+ tree fndecl = gimple_call_fndecl (def_stmt);
+ inform (gimple_location (def_stmt),
+ "returned from a call to %qD", fndecl);
+ return;
+ }
+ }
+ else if (gimple_nop_p (def_stmt))
+ {
+ ref = SSA_NAME_VAR (ref);
+ /* Diagnose freeing a pointer that includes a positive offset. */
+ if (TREE_CODE (ref) == PARM_DECL
+ && !aref.deref
+ && aref.sizrng[0] != aref.sizrng[1]
+ && aref.offrng[0] > 0 && aref.offrng[1] > 0
+ && warn_dealloc_offset (loc, exp, dealloc_decl, aref))
+ return;
+ }
+ }
}
/* Fold a call to __builtin_object_size with arguments PTR and OST,
diff --git a/gcc/builtins.h b/gcc/builtins.h
index 09379e8..6429232 100644
--- a/gcc/builtins.h
+++ b/gcc/builtins.h
@@ -220,6 +220,12 @@ struct access_ref
argument to the minimum. */
offset_int size_remaining (offset_int * = NULL) const;
+ /* Return true if *THIS is an access to a declared object. */
+ bool ref_declared () const
+ {
+ return DECL_P (ref) && base0 && deref < 1;
+ }
+
/* Set the size range to the maximum. */
void set_max_size_range ()
{
@@ -261,6 +267,9 @@ struct access_ref
/* Used to fold integer expressions when called from front ends. */
tree (*eval)(tree);
+ /* Positive when REF is dereferenced, negative when its address is
+ taken. */
+ int deref;
/* Set if trailing one-element arrays should be treated as flexible
array members. */
bool trail1special;
@@ -350,5 +359,6 @@ extern tree compute_objsize (tree, int, tree * = NULL, tree * = NULL,
range_query * = NULL);
extern bool check_access (tree, tree, tree, tree, tree,
access_mode, const access_data * = NULL);
+extern void maybe_emit_free_warning (tree);
#endif /* GCC_BUILTINS_H */
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 0421c98..2e88f20 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,18 @@
+2020-12-03 Martin Sebor <msebor@redhat.com>
+
+ PR c++/90629
+ PR middle-end/94527
+ * c-attribs.c (handle_dealloc_attribute): New function.
+ (handle_malloc_attribute): Handle argument forms of attribute.
+ * c.opt (-Wmismatched-dealloc): New option.
+ (-Wmismatched-new-delete): New option.
+
+2020-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR libstdc++/93121
+ * c-common.h (enum rid): Add RID_BUILTIN_BIT_CAST.
+ * c-common.c (c_common_reswords): Add __builtin_bit_cast.
+
2020-12-01 JeanHeyd Meneide <phdofthehouse@gmail.com>
* c-cppbuiltin.c (c_cpp_builtins): Add predefined
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 99b6630..f7dad7a 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -113,6 +113,7 @@ static tree handle_no_instrument_function_attribute (tree *, tree,
static tree handle_no_profile_instrument_function_attribute (tree *, tree,
tree, int, bool *);
static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
+static tree handle_dealloc_attribute (tree *, tree, tree, int, bool *);
static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
bool *);
@@ -364,7 +365,7 @@ const struct attribute_spec c_common_attribute_table[] =
{ "no_profile_instrument_function", 0, 0, true, false, false, false,
handle_no_profile_instrument_function_attribute,
NULL },
- { "malloc", 0, 0, true, false, false, false,
+ { "malloc", 0, 2, true, false, false, false,
handle_malloc_attribute, attr_alloc_exclusions },
{ "returns_twice", 0, 0, true, false, false, false,
handle_returns_twice_attribute,
@@ -524,6 +525,8 @@ const struct attribute_spec c_common_attribute_table[] =
handle_objc_root_class_attribute, NULL },
{ "objc_nullability", 1, 1, true, false, false, false,
handle_objc_nullability_attribute, NULL },
+ { "*dealloc", 1, 2, true, false, false, false,
+ handle_dealloc_attribute, NULL },
{ NULL, 0, 0, false, false, false, false, NULL, NULL }
};
@@ -3127,20 +3130,179 @@ handle_no_profile_instrument_function_attribute (tree *node, tree name, tree,
return NULL_TREE;
}
-/* Handle a "malloc" attribute; arguments as in
- struct attribute_spec.handler. */
+/* Handle the "malloc" attribute. */
static tree
-handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+handle_malloc_attribute (tree *node, tree name, tree args,
int ARG_UNUSED (flags), bool *no_add_attrs)
{
- if (TREE_CODE (*node) == FUNCTION_DECL
- && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))))
- DECL_IS_MALLOC (*node) = 1;
- else
+ tree fndecl = *node;
+
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored; valid only "
+ "for functions",
+ name);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ tree rettype = TREE_TYPE (TREE_TYPE (*node));
+ if (!POINTER_TYPE_P (rettype))
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored on functions "
+ "returning %qT; valid only for pointer return types",
+ name, rettype);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ if (!args)
+ {
+ /* Only the form of the attribute with no arguments declares
+ a function malloc-like. */
+ DECL_IS_MALLOC (*node) = 1;
+ return NULL_TREE;
+ }
+
+ tree dealloc = TREE_VALUE (args);
+ if (error_operand_p (dealloc))
+ {
+ /* If the argument is in error it will have already been diagnosed.
+ Avoid issuing redundant errors here. */
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ /* In C++ the argument may be wrapped in a cast to disambiguate one
+ of a number of overloads (such as operator delete). Strip it. */
+ STRIP_NOPS (dealloc);
+ if (TREE_CODE (dealloc) == ADDR_EXPR)
+ dealloc = TREE_OPERAND (dealloc, 0);
+
+ if (TREE_CODE (dealloc) != FUNCTION_DECL)
+ {
+ if (TREE_CODE (dealloc) == OVERLOAD)
+ {
+ /* Handle specially the common case of specifying one of a number
+ of overloads, such as operator delete. */
+ error ("%qE attribute argument 1 is ambiguous", name);
+ inform (input_location,
+ "use a cast to the expected type to disambiguate");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ error ("%qE attribute argument 1 does not name a function", name);
+ if (DECL_P (dealloc))
+ inform (DECL_SOURCE_LOCATION (dealloc),
+ "argument references a symbol declared here");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ /* Mentioning the deallocation function qualifies as its use. */
+ TREE_USED (dealloc) = 1;
+
+ tree fntype = TREE_TYPE (dealloc);
+ tree argpos = TREE_CHAIN (args) ? TREE_VALUE (TREE_CHAIN (args)) : NULL_TREE;
+ if (!argpos)
+ {
+ tree argtypes = TYPE_ARG_TYPES (fntype);
+ if (!argtypes)
+ {
+ /* Reject functions without a prototype. */
+ error ("%qE attribute argument 1 must take a pointer "
+ "type as its first argument", name);
+ inform (DECL_SOURCE_LOCATION (dealloc),
+ "refernced symbol declared here" );
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ tree argtype = TREE_VALUE (argtypes);
+ if (TREE_CODE (argtype) != POINTER_TYPE)
+ {
+ /* Reject functions that don't take a pointer as their first
+ argument. */
+ error ("%qE attribute argument 1 must take a pointer type "
+ "as its first argument; have %qT", name, argtype);
+ inform (DECL_SOURCE_LOCATION (dealloc),
+ "referenced symbol declared here" );
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ *no_add_attrs = false;
+ tree attr_free = build_tree_list (NULL_TREE, DECL_NAME (fndecl));
+ attr_free = build_tree_list (get_identifier ("*dealloc"), attr_free);
+ decl_attributes (&dealloc, attr_free, 0);
+ return NULL_TREE;
+ }
+
+ /* Validate the positional argument. */
+ argpos = positional_argument (fntype, name, argpos, POINTER_TYPE);
+ if (!argpos)
{
- warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ /* It's valid to declare the same function with multiple instances
+ of attribute malloc, each naming the same or different deallocator
+ functions, and each referencing either the same or a different
+ positional argument. */
+ *no_add_attrs = false;
+ tree attr_free = tree_cons (NULL_TREE, argpos, NULL_TREE);
+ attr_free = tree_cons (NULL_TREE, DECL_NAME (fndecl), attr_free);
+ attr_free = build_tree_list (get_identifier ("*dealloc"), attr_free);
+ decl_attributes (&dealloc, attr_free, 0);
+ return NULL_TREE;
+}
+
+/* Handle the internal "*dealloc" attribute added for functions declared
+ with the one- and two-argument forms of attribute malloc. Add it
+ to *NODE unless it's already there with the same arguments. */
+
+static tree
+handle_dealloc_attribute (tree *node, tree name, tree args, int,
+ bool *no_add_attrs)
+{
+ tree fndecl = *node;
+
+ tree attrs = DECL_ATTRIBUTES (fndecl);
+ if (!attrs)
+ return NULL_TREE;
+
+ tree arg_fname = TREE_VALUE (args);
+ args = TREE_CHAIN (args);
+ tree arg_pos = args ? TREE_VALUE (args) : NULL_TREE;
+
+ gcc_checking_assert (TREE_CODE (arg_fname) == IDENTIFIER_NODE);
+
+ const char* const namestr = IDENTIFIER_POINTER (name);
+ for (tree at = attrs; (at = lookup_attribute (namestr, at));
+ at = TREE_CHAIN (at))
+ {
+ tree alloc = TREE_VALUE (at);
+ if (!alloc)
+ continue;
+
+ tree pos = TREE_CHAIN (alloc);
+ alloc = TREE_VALUE (alloc);
+ pos = pos ? TREE_VALUE (pos) : NULL_TREE;
+ gcc_checking_assert (TREE_CODE (alloc) == IDENTIFIER_NODE);
+
+ if (alloc == arg_fname
+ && ((!pos && !arg_pos)
+ || (pos && arg_pos && tree_int_cst_equal (pos, arg_pos))))
+ {
+ /* The function already has the attribute either without any
+ arguments or with the same arguments as the attribute that's
+ being added. Return without adding another copy. */
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
}
return NULL_TREE;
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 059f6c3..7947828 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -793,6 +793,16 @@ Wmisleading-indentation
C C++ Common Var(warn_misleading_indentation) Warning LangEnabledBy(C C++,Wall)
Warn when the indentation of the code does not reflect the block structure.
+Wmismatched-dealloc
+C ObjC C++ ObjC++ Var(warn_mismatched_alloc) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn for deallocation calls with arguments returned from mismatched allocation
+functions.
+
+Wmismatched-new-delete
+C++ ObjC++ Var(warn_mismatched_new_delete) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn for mismatches between calls to operator new or delete and the corrsponding
+call to the allocation or deallocation function.
+
Wmismatched-tags
C++ ObjC++ Var(warn_mismatched_tags) Warning
Warn when a class is redeclared or referenced using a mismatched class-key.
diff --git a/gcc/calls.c b/gcc/calls.c
index a93d4bf..4114bf5 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -2623,6 +2623,10 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
/* Check attribute access arguments. */
maybe_warn_rdwr_sizes (&rdwr_idx, fndecl, fntype, exp);
+
+ /* Check calls to operator new for mismatched forms and attempts
+ to deallocate unallocated objects. */
+ maybe_emit_free_warning (exp);
}
/* Update ARGS_SIZE to contain the total size for the argument block.
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 7e0bdd5..f7b4091 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -5919,7 +5919,7 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
&& !target_for_debug_bind (var))
goto delink_debug_stmt;
- if (DECL_P (var))
+ if (DECL_P (var) && !VECTOR_TYPE_P (TREE_TYPE (var)))
mode = DECL_MODE (var);
else
mode = TYPE_MODE (TREE_TYPE (var));
@@ -5936,7 +5936,10 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
value = gimple_debug_source_bind_get_value (stmt);
- mode = DECL_MODE (var);
+ if (!VECTOR_TYPE_P (TREE_TYPE (var)))
+ mode = DECL_MODE (var);
+ else
+ mode = TYPE_MODE (TREE_TYPE (var));
val = gen_rtx_VAR_LOCATION (mode, var, (rtx)value,
VAR_INIT_STATUS_UNINITIALIZED);
diff --git a/gcc/common.opt b/gcc/common.opt
index 582e2aa..6645539 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -3178,6 +3178,14 @@ gdwarf-
Common Driver Joined UInteger Var(dwarf_version) Init(4) Negative(gstabs)
Generate debug information in DWARF v2 (or later) format.
+gdwarf32
+Common Driver Var(dwarf_offset_size,4) Init(4) RejectNegative
+Use 32-bit DWARF format when emitting DWARF debug information.
+
+gdwarf64
+Common Driver Var(dwarf_offset_size,8) RejectNegative
+Use 64-bit DWARF format when emitting DWARF debug information.
+
ggdb
Common Driver JoinedOrMissing
Generate debug information in default extended format.
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 76e9499..129d47b 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -11975,6 +11975,23 @@
(clobber (reg:CC FLAGS_REG))])]
"operands[2] = gen_lowpart (QImode, operands[2]);")
+(define_split
+ [(set (match_operand:SWI48 0 "register_operand")
+ (any_rotate:SWI48
+ (match_operand:SWI48 1 "const_int_operand")
+ (subreg:QI
+ (and:SI
+ (match_operand:SI 2 "register_operand")
+ (match_operand:SI 3 "const_int_operand")) 0)))]
+ "(INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1))
+ == GET_MODE_BITSIZE (<MODE>mode) - 1"
+ [(set (match_dup 4) (match_dup 1))
+ (set (match_dup 0)
+ (any_rotate:SWI48 (match_dup 4)
+ (subreg:QI
+ (and:SI (match_dup 2) (match_dup 3)) 0)))]
+ "operands[4] = gen_reg_rtx (<MODE>mode);")
+
(define_insn_and_split "*<rotate_insn><mode>3_mask_1"
[(set (match_operand:SWI48 0 "nonimmediate_operand")
(any_rotate:SWI48
@@ -11995,6 +12012,21 @@
(match_dup 2)))
(clobber (reg:CC FLAGS_REG))])])
+(define_split
+ [(set (match_operand:SWI48 0 "register_operand")
+ (any_rotate:SWI48
+ (match_operand:SWI48 1 "const_int_operand")
+ (and:QI
+ (match_operand:QI 2 "register_operand")
+ (match_operand:QI 3 "const_int_operand"))))]
+ "(INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1))
+ == GET_MODE_BITSIZE (<MODE>mode) - 1"
+ [(set (match_dup 4) (match_dup 1))
+ (set (match_dup 0)
+ (any_rotate:SWI48 (match_dup 4)
+ (and:QI (match_dup 2) (match_dup 3))))]
+ "operands[4] = gen_reg_rtx (<MODE>mode);")
+
;; Implement rotation using two double-precision
;; shift instructions and a scratch register.
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index c661f7a..f26fc13 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -3864,6 +3864,12 @@ rs6000_option_override_internal (bool global_init_p)
if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
rs6000_print_isa_options (stderr, 0, "before defaults", rs6000_isa_flags);
+#ifdef XCOFF_DEBUGGING_INFO
+ /* For AIX default to 64-bit DWARF. */
+ if (!global_options_set.x_dwarf_offset_size)
+ dwarf_offset_size = POINTER_SIZE_UNITS;
+#endif
+
/* Handle explicit -mno-{altivec,vsx,power8-vector,power9-vector} and turn
off all of the options that depend on those flags. */
ignore_masks = rs6000_disable_incompatible_switches ();
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6728ea1..1bf50cd 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,70 @@
+2020-12-03 Jason Merrill <jason@redhat.com>
+
+ * cp-tree.h (releasing_vec::operator[]): Change parameter type to
+ ptrdiff_t.
+
+2020-12-03 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (OVL_EXPORT): New.
+ (class ovl_iterator): Add get_using, exporting_p.
+ * tree.c (ovl_insert): Extend using_or_hidden meaning to include
+ an exported using.
+
+2020-12-03 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (DECL_UNINSTANTIATED_TEMPLATE_FRIEND): New.
+ * pt.c (push_template_decl): Set it.
+ (tsubst_friend_function): Clear it.
+
+2020-12-03 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (make_unbound_class_template_raw): Declare.
+ (canonical_type_parameter): Declare.
+ * decl.c (make_unbound_class_template_raw): Break out of ...
+ (make_unboud_class_template): ... here. Call it.
+ * pt.c (canonical_type_parameter): Externalize. Refactor & set
+ structural_equality for type parms.
+
+2020-12-03 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/98107
+ * tree.c (build_cplus_array_type): Mark dependency of new variant.
+ (cp_build_qualified_type_real, strip_typedefs): Assert
+ TYPE_DEPENDENT_P_VALID, or not a dependent type.
+
+2020-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR libstdc++/93121
+ * cp-tree.h (cp_build_bit_cast): Declare.
+ * cp-tree.def (BIT_CAST_EXPR): New tree code.
+ * cp-objcp-common.c (names_builtin_p): Handle RID_BUILTIN_BIT_CAST.
+ (cp_common_init_ts): Handle BIT_CAST_EXPR.
+ * cxx-pretty-print.c (cxx_pretty_printer::postfix_expression):
+ Likewise.
+ * parser.c (cp_parser_postfix_expression): Handle
+ RID_BUILTIN_BIT_CAST.
+ * semantics.c (cp_build_bit_cast): New function.
+ * tree.c (cp_tree_equal): Handle BIT_CAST_EXPR.
+ (cp_walk_subtrees): Likewise.
+ * pt.c (tsubst_copy): Likewise.
+ * constexpr.c (check_bit_cast_type, cxx_eval_bit_cast): New functions.
+ (cxx_eval_constant_expression): Handle BIT_CAST_EXPR.
+ (potential_constant_expression_1): Likewise.
+ * cp-gimplify.c (cp_genericize_r): Likewise.
+
+2020-12-03 Jason Merrill <jason@redhat.com>
+
+ * parser.c (cp_parser_primary_expression): Distinguish
+ parms from vars in error.
+ (cp_parser_late_parsing_default_args): Pushdecl parms
+ as we go.
+
+2020-12-03 Jason Merrill <jason@redhat.com>
+
+ * name-lookup.c (begin_scope): Set immediate_fn_ctx_p.
+ * parser.c (cp_parser_late_parsing_default_args): Push
+ sk_function_parms scope.
+
2020-12-03 Peter Bergner <bergner@linux.ibm.com>
PR c++/97947
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index bafcaf5..8bbcf01 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -3005,7 +3005,7 @@ fold_builtin_source_location (location_t loc)
const char *name = "";
if (current_function_decl)
- name = cxx_printable_name (current_function_decl, 0);
+ name = cxx_printable_name (current_function_decl, 2);
val = build_string_literal (strlen (name) + 1, name);
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 69f8ed5..00901fe 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -488,10 +488,9 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
CALL_EXPR_ORDERED_ARGS (in CALL_EXPR, AGGR_INIT_EXPR)
DECLTYPE_FOR_REF_CAPTURE (in DECLTYPE_TYPE)
CONSTRUCTOR_C99_COMPOUND_LITERAL (in CONSTRUCTOR)
- DECL_MODULE_EXPORT_P (in _DECL)
OVL_NESTED_P (in OVERLOAD)
LAMBDA_EXPR_INSTANTIATED (in LAMBDA_EXPR)
- Reserved for DECL_MODULE_EXPORT (in DECL_)
+ DECL_MODULE_EXPORT_P (in _DECL)
4: IDENTIFIER_MARKED (IDENTIFIER_NODEs)
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
CALL_EXPR, or FIELD_DECL).
@@ -503,6 +502,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
FUNCTION_RVALUE_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE)
CALL_EXPR_REVERSE_ARGS (in CALL_EXPR, AGGR_INIT_EXPR)
CONSTRUCTOR_PLACEHOLDER_BOUNDARY (in CONSTRUCTOR)
+ OVL_EXPORT_P (in OVERLOAD)
6: TYPE_MARKED_P (in _TYPE)
DECL_NONTRIVIALLY_INITIALIZED_P (in VAR_DECL)
RANGE_FOR_IVDEP (in RANGE_FOR_STMT)
@@ -545,6 +545,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
DECL_ANON_UNION_VAR_P (in a VAR_DECL)
DECL_SELF_REFERENCE_P (in a TYPE_DECL)
DECL_INVALID_OVERRIDER_P (in a FUNCTION_DECL)
+ DECL_UNINSTANIATED_TEMPLATE_FRIEND_P (in TEMPLATE_DECL)
5: DECL_INTERFACE_KNOWN.
6: DECL_THIS_STATIC (in VAR_DECL, FUNCTION_DECL or PARM_DECL)
DECL_FIELD_IS_BASE (in FIELD_DECL)
@@ -779,6 +780,8 @@ typedef struct ptrmem_cst * ptrmem_cst_t;
#define OVL_NESTED_P(NODE) TREE_LANG_FLAG_3 (OVERLOAD_CHECK (NODE))
/* If set, this overload was constructed during lookup. */
#define OVL_LOOKUP_P(NODE) TREE_LANG_FLAG_4 (OVERLOAD_CHECK (NODE))
+/* If set, this OVL_USING_P overload is exported. */
+#define OVL_EXPORT_P(NODE) TREE_LANG_FLAG_5 (OVERLOAD_CHECK (NODE))
/* The first decl of an overload. */
#define OVL_FIRST(NODE) ovl_first (NODE)
@@ -838,6 +841,11 @@ class ovl_iterator {
return fn;
}
+ tree get_using () const
+ {
+ gcc_checking_assert (using_p ());
+ return ovl;
+ }
public:
/* Whether this overload was introduced by a using decl. */
@@ -846,6 +854,12 @@ class ovl_iterator {
return (TREE_CODE (ovl) == USING_DECL
|| (TREE_CODE (ovl) == OVERLOAD && OVL_USING_P (ovl)));
}
+ /* Whether this using is being exported. */
+ bool exporting_p () const
+ {
+ return OVL_EXPORT_P (get_using ());
+ }
+
bool hidden_p () const
{
return TREE_CODE (ovl) == OVERLOAD && OVL_HIDDEN_P (ovl);
@@ -961,8 +975,10 @@ public:
operator vec_t *() const { return v; }
vec_t ** operator& () { return &v; }
- /* Breaks pointer/value consistency for convenience. */
- tree& operator[] (unsigned i) const { return (*v)[i]; }
+ /* Breaks pointer/value consistency for convenience. This takes ptrdiff_t
+ rather than unsigned to avoid ambiguity with the built-in operator[]
+ (bootstrap/91828). */
+ tree& operator[] (ptrdiff_t i) const { return (*v)[i]; }
~releasing_vec() { release_tree_vector (v); }
private:
@@ -3161,6 +3177,13 @@ struct GTY(()) lang_decl {
(DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE)) \
->u.base.friend_or_tls)
+/* True of a TEMPLATE_DECL that is a template class friend. Such
+ decls are not pushed until instantiated (as they may depend on
+ parameters of the befriending class). DECL_CHAIN is the
+ befriending class. */
+#define DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P(NODE) \
+ (DECL_LANG_FLAG_4 (TEMPLATE_DECL_CHECK (NODE)))
+
/* Nonzero if the thread-local variable was declared with __thread as
opposed to thread_local. */
#define DECL_GNU_TLS_P(NODE) \
@@ -5399,10 +5422,6 @@ extern int function_depth;
in structrual_comptypes. */
extern int comparing_specializations;
-/* Nonzero if we are inside eq_specializations, which affects
- resolving of typenames in structural_comptypes. */
-extern int comparing_typenames;
-
/* In parser.c. */
/* Nonzero if we are parsing an unevaluated operand: an operand to
@@ -6863,6 +6882,103 @@ extern bool ctor_omit_inherited_parms (tree);
extern tree locate_ctor (tree);
extern tree implicitly_declare_fn (special_function_kind, tree,
bool, tree, tree);
+/* In module.cc */
+class module_state; /* Forward declare. */
+inline bool modules_p () { return flag_modules != 0; }
+
+/* The kind of module or part thereof that we're in. */
+enum module_kind_bits
+{
+ MK_MODULE = 1 << 0, /* This TU is a module. */
+ MK_GLOBAL = 1 << 1, /* Entities are in the global module. */
+ MK_INTERFACE = 1 << 2, /* This TU is an interface. */
+ MK_PARTITION = 1 << 3, /* This TU is a partition. */
+ MK_EXPORTING = 1 << 4, /* We are in an export region. */
+};
+
+/* We do lots of bit-manipulation, so an unsigned is easier. */
+extern unsigned module_kind;
+
+/* MK_MODULE & MK_GLOBAL have the following combined meanings:
+ MODULE GLOBAL
+ 0 0 not a module
+ 0 1 GMF of named module (we've not yet seen module-decl)
+ 1 0 purview of named module
+ 1 1 header unit. */
+
+inline bool module_purview_p ()
+{ return module_kind & MK_MODULE; }
+inline bool global_purview_p ()
+{ return module_kind & MK_GLOBAL; }
+
+inline bool not_module_p ()
+{ return (module_kind & (MK_MODULE | MK_GLOBAL)) == 0; }
+inline bool named_module_p ()
+{ /* This is a named module if exactly one of MODULE and GLOBAL is
+ set. */
+ /* The divides are constant shifts! */
+ return ((module_kind / MK_MODULE) ^ (module_kind / MK_GLOBAL)) & 1;
+}
+inline bool header_module_p ()
+{ return (module_kind & (MK_MODULE | MK_GLOBAL)) == (MK_MODULE | MK_GLOBAL); }
+inline bool named_module_purview_p ()
+{ return (module_kind & (MK_MODULE | MK_GLOBAL)) == MK_MODULE; }
+inline bool module_interface_p ()
+{ return module_kind & MK_INTERFACE; }
+inline bool module_partition_p ()
+{ return module_kind & MK_PARTITION; }
+inline bool module_has_cmi_p ()
+{ return module_kind & (MK_INTERFACE | MK_PARTITION); }
+
+/* We're currently exporting declarations. */
+inline bool module_exporting_p ()
+{ return module_kind & MK_EXPORTING; }
+
+extern module_state *get_module (tree name, module_state *parent = NULL,
+ bool partition = false);
+extern bool module_may_redeclare (tree decl);
+
+extern int module_initializer_kind ();
+extern void module_add_import_initializers ();
+
+/* Where the namespace-scope decl was originally declared. */
+extern void set_originating_module (tree, bool friend_p = false);
+extern tree get_originating_module_decl (tree) ATTRIBUTE_PURE;
+extern int get_originating_module (tree, bool for_mangle = false) ATTRIBUTE_PURE;
+extern unsigned get_importing_module (tree, bool = false) ATTRIBUTE_PURE;
+
+/* Where current instance of the decl got declared/defined/instantiated. */
+extern void set_instantiating_module (tree);
+extern void set_defining_module (tree);
+extern void maybe_attach_decl (tree ctx, tree decl);
+
+extern void mangle_module (int m, bool include_partition);
+extern void mangle_module_fini ();
+extern void lazy_load_binding (unsigned mod, tree ns, tree id,
+ binding_slot *bslot);
+extern void lazy_load_specializations (tree tmpl);
+extern void lazy_load_members (tree decl);
+extern bool lazy_specializations_p (unsigned, bool, bool);
+extern module_state *preprocess_module (module_state *, location_t,
+ bool in_purview,
+ bool is_import, bool export_p,
+ cpp_reader *reader);
+extern void preprocessed_module (cpp_reader *reader);
+extern void import_module (module_state *, location_t, bool export_p,
+ tree attr, cpp_reader *);
+extern void declare_module (module_state *, location_t, bool export_p,
+ tree attr, cpp_reader *);
+extern void init_modules (cpp_reader *);
+extern void fini_modules ();
+extern void maybe_check_all_macros (cpp_reader *);
+extern void finish_module_processing (cpp_reader *);
+extern char const *module_name (unsigned, bool header_ok);
+extern bitmap get_import_bitmap ();
+extern bitmap module_visible_instantiation_path (bitmap *);
+extern void module_begin_main_file (cpp_reader *, line_maps *,
+ const line_map_ordinary *);
+extern void module_preprocess_options (cpp_reader *);
+extern bool handle_module_option (unsigned opt, const char *arg, int value);
/* In optimize.c */
extern bool maybe_clone_body (tree);
@@ -7443,7 +7559,7 @@ extern bool is_local_temp (tree);
extern tree build_aggr_init_expr (tree, tree);
extern tree get_target_expr (tree);
extern tree get_target_expr_sfinae (tree, tsubst_flags_t);
-extern tree build_cplus_array_type (tree, tree, int is_dep = -1);
+extern tree build_cplus_array_type (tree, tree);
extern tree build_array_of_n_type (tree, int);
extern bool array_of_runtime_bound_p (tree);
extern bool vla_type_p (tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 1bc7b7e..46069cb 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1928,7 +1928,7 @@ static void
clear_consteval_vfns (vec<tree> &consteval_vtables)
{
for (tree vtable : consteval_vtables)
- for (constructor_elt &elt : *CONSTRUCTOR_ELTS (DECL_INITIAL (vtable)))
+ for (constructor_elt &elt : CONSTRUCTOR_ELTS (DECL_INITIAL (vtable)))
{
tree fn = cp_get_fndecl_from_callee (elt.value, /*fold*/false);
if (fn && DECL_IMMEDIATE_FUNCTION_P (fn))
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 103567c..cc3da15 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -30611,9 +30611,6 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
{
tree default_arg = TREE_PURPOSE (parm);
tree parsed_arg;
- vec<tree, va_gc> *insts;
- tree copy;
- unsigned ix;
tree parmdecl = parms[i];
pushdecl (parmdecl);
@@ -30633,8 +30630,7 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
TREE_PURPOSE (parm) = parsed_arg;
/* Update any instantiations we've already created. */
- for (insts = DEFPARSE_INSTANTIATIONS (default_arg), ix = 0;
- vec_safe_iterate (insts, ix, &copy); ix++)
+ for (tree copy : DEFPARSE_INSTANTIATIONS (default_arg))
TREE_PURPOSE (copy) = parsed_arg;
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3ca2813..2d3ab92 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -22,7 +22,9 @@ along with GCC; see the file COPYING3. If not see
/* Known bugs or deficiencies include:
all methods must be provided in header files; can't use a source
- file that contains only the method templates and "just win". */
+ file that contains only the method templates and "just win".
+
+ Fixed by: C++20 modules. */
#include "config.h"
#include "system.h"
@@ -1702,19 +1704,16 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
return spec;
}
-/* Restricts tree and type comparisons. */
-int comparing_specializations;
-int comparing_typenames;
-
/* Returns true iff two spec_entry nodes are equivalent. */
+int comparing_specializations;
+
bool
spec_hasher::equal (spec_entry *e1, spec_entry *e2)
{
int equal;
++comparing_specializations;
- ++comparing_typenames;
equal = (e1->tmpl == e2->tmpl
&& comp_template_args (e1->args, e2->args));
if (equal && flag_concepts
@@ -1730,7 +1729,6 @@ spec_hasher::equal (spec_entry *e1, spec_entry *e2)
equal = equivalent_constraints (c1, c2);
}
--comparing_specializations;
- --comparing_typenames;
return equal;
}
@@ -6044,6 +6042,14 @@ push_template_decl (tree decl, bool is_friend)
tmpl = NULL_TREE;
}
}
+ else if (is_friend)
+ {
+ /* Record this decl as belonging to the current class. It's
+ not chained onto anything else. */
+ DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (tmpl) = true;
+ gcc_checking_assert (!DECL_CHAIN (tmpl));
+ DECL_CHAIN (tmpl) = current_scope ();
+ }
}
else if (tmpl)
/* The type may have been completed, or (erroneously) changed. */
@@ -8260,7 +8266,7 @@ convert_template_argument (tree parm,
/* When determining whether an argument pack expansion is a template,
look at the pattern. */
- if (TREE_CODE (arg) == TYPE_PACK_EXPANSION)
+ if (PACK_EXPANSION_P (arg))
arg = PACK_EXPANSION_PATTERN (arg);
/* Deal with an injected-class-name used as a template template arg. */
@@ -11053,6 +11059,7 @@ tsubst_friend_function (tree decl, tree args)
DECL_USE_TEMPLATE (new_friend) = 0;
if (TREE_CODE (new_friend) == TEMPLATE_DECL)
{
+ DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (new_friend) = false;
DECL_USE_TEMPLATE (DECL_TEMPLATE_RESULT (new_friend)) = 0;
DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (new_friend))
= DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (decl));
@@ -29006,6 +29013,12 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))
return ptype;
+ /* Initializing one placeholder from another. */
+ if (init && TREE_CODE (init) == TEMPLATE_PARM_INDEX
+ && is_auto (TREE_TYPE (init))
+ && CLASS_PLACEHOLDER_TEMPLATE (TREE_TYPE (init)) == tmpl)
+ return cp_build_qualified_type (TREE_TYPE (init), cp_type_quals (ptype));
+
/* Look through alias templates that just rename another template. */
tmpl = get_underlying_template (tmpl);
if (!ctad_template_p (tmpl))
@@ -29022,10 +29035,6 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
"with %<-std=c++20%> or %<-std=gnu++20%>");
}
- if (init && TREE_TYPE (init) == ptype)
- /* Using the template parm as its own argument. */
- return ptype;
-
tree type = TREE_TYPE (tmpl);
bool try_list_ctor = false;
@@ -29273,7 +29282,7 @@ do_auto_deduction (tree type, tree init, tree auto_node,
/* We don't recurse here because we can't deduce from a nested
initializer_list. */
if (CONSTRUCTOR_ELTS (init))
- for (constructor_elt &elt : *CONSTRUCTOR_ELTS (init))
+ for (constructor_elt &elt : CONSTRUCTOR_ELTS (init))
elt.value = resolve_nondeduced_context (elt.value, complain);
}
else
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8d7df60..4e6bf9a 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -998,7 +998,7 @@ build_min_array_type (tree elt_type, tree index_type)
build_cplus_array_type. */
static void
-set_array_type_canon (tree t, tree elt_type, tree index_type, bool dep)
+set_array_type_canon (tree t, tree elt_type, tree index_type)
{
/* Set the canonical type for this new node. */
if (TYPE_STRUCTURAL_EQUALITY_P (elt_type)
@@ -1009,33 +1009,30 @@ set_array_type_canon (tree t, tree elt_type, tree index_type, bool dep)
TYPE_CANONICAL (t)
= build_cplus_array_type (TYPE_CANONICAL (elt_type),
index_type
- ? TYPE_CANONICAL (index_type) : index_type,
- dep);
+ ? TYPE_CANONICAL (index_type) : index_type);
else
TYPE_CANONICAL (t) = t;
}
/* Like build_array_type, but handle special C++ semantics: an array of a
variant element type is a variant of the array of the main variant of
- the element type. IS_DEPENDENT is -ve if we should determine the
- dependency. Otherwise its bool value indicates dependency. */
+ the element type. */
tree
-build_cplus_array_type (tree elt_type, tree index_type, int dependent)
+build_cplus_array_type (tree elt_type, tree index_type)
{
tree t;
if (elt_type == error_mark_node || index_type == error_mark_node)
return error_mark_node;
- if (dependent < 0)
- dependent = (uses_template_parms (elt_type)
- || (index_type && uses_template_parms (index_type)));
+ bool dependent = (uses_template_parms (elt_type)
+ || (index_type && uses_template_parms (index_type)));
if (elt_type != TYPE_MAIN_VARIANT (elt_type))
/* Start with an array of the TYPE_MAIN_VARIANT. */
t = build_cplus_array_type (TYPE_MAIN_VARIANT (elt_type),
- index_type, dependent);
+ index_type);
else if (dependent)
{
/* Since type_hash_canon calls layout_type, we need to use our own
@@ -1065,20 +1062,13 @@ build_cplus_array_type (tree elt_type, tree index_type, int dependent)
*e = t;
/* Set the canonical type for this new node. */
- set_array_type_canon (t, elt_type, index_type, dependent);
-
- /* Mark it as dependent now, this saves time later. */
- TYPE_DEPENDENT_P_VALID (t) = true;
- TYPE_DEPENDENT_P (t) = true;
+ set_array_type_canon (t, elt_type, index_type);
}
}
else
{
bool typeless_storage = is_byte_access_type (elt_type);
t = build_array_type (elt_type, index_type, typeless_storage);
-
- /* Mark as non-dependenty now, this will save time later. */
- TYPE_DEPENDENT_P_VALID (t) = true;
}
/* Now check whether we already have this array variant. */
@@ -1093,10 +1083,7 @@ build_cplus_array_type (tree elt_type, tree index_type, int dependent)
if (!t)
{
t = build_min_array_type (elt_type, index_type);
- /* Mark dependency now, this saves time later. */
- TYPE_DEPENDENT_P_VALID (t) = true;
- TYPE_DEPENDENT_P (t) = dependent;
- set_array_type_canon (t, elt_type, index_type, dependent);
+ set_array_type_canon (t, elt_type, index_type);
if (!dependent)
{
layout_type (t);
@@ -1332,10 +1319,7 @@ cp_build_qualified_type_real (tree type,
if (!t)
{
- gcc_checking_assert (TYPE_DEPENDENT_P_VALID (type)
- || !dependent_type_p (type));
- t = build_cplus_array_type (element_type, TYPE_DOMAIN (type),
- TYPE_DEPENDENT_P (type));
+ t = build_cplus_array_type (element_type, TYPE_DOMAIN (type));
/* Keep the typedef name. */
if (TYPE_NAME (t) != TYPE_NAME (type))
@@ -1571,9 +1555,7 @@ strip_typedefs (tree t, bool *remove_attributes, unsigned int flags)
case ARRAY_TYPE:
type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags);
t0 = strip_typedefs (TYPE_DOMAIN (t), remove_attributes, flags);
- gcc_checking_assert (TYPE_DEPENDENT_P_VALID (t)
- || !dependent_type_p (t));
- result = build_cplus_array_type (type, t0, TYPE_DEPENDENT_P (t));
+ result = build_cplus_array_type (type, t0);
break;
case FUNCTION_TYPE:
case METHOD_TYPE:
@@ -2272,10 +2254,11 @@ ovl_make (tree fn, tree next)
return result;
}
-/* Add FN to the (potentially NULL) overload set OVL. USING_OR_HIDDEN
- is > 0, if FN is via a using declaration. USING_OR_HIDDEN is < 0,
- if FN is hidden. (A decl cannot be both using and hidden.) We
- keep the hidden decls first, but remaining ones are unordered. */
+/* Add FN to the (potentially NULL) overload set OVL. USING_OR_HIDDEN is >
+ zero if this is a using-decl. It is > 1 if we're exporting the
+ using decl. USING_OR_HIDDEN is < 0, if FN is hidden. (A decl
+ cannot be both using and hidden.) We keep the hidden decls first,
+ but remaining ones are unordered. */
tree
ovl_insert (tree fn, tree maybe_ovl, int using_or_hidden)
@@ -2299,7 +2282,11 @@ ovl_insert (tree fn, tree maybe_ovl, int using_or_hidden)
if (using_or_hidden < 0)
OVL_HIDDEN_P (maybe_ovl) = true;
if (using_or_hidden > 0)
- OVL_DEDUP_P (maybe_ovl) = OVL_USING_P (maybe_ovl) = true;
+ {
+ OVL_DEDUP_P (maybe_ovl) = OVL_USING_P (maybe_ovl) = true;
+ if (using_or_hidden > 1)
+ OVL_EXPORT_P (maybe_ovl) = true;
+ }
}
else
maybe_ovl = fn;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 6294a78..267b284 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1256,15 +1256,16 @@ structural_comptypes (tree t1, tree t2, int strict)
gcc_assert (TYPE_P (t1) && TYPE_P (t2));
- /* TYPENAME_TYPEs should be resolved if the qualifying scope is the
- current instantiation, and we don't care about typename
- structural equality. The comparing_typenames check is after the
- code check, in order to early-out the common case. */
- if (TREE_CODE (t1) == TYPENAME_TYPE && !comparing_typenames)
- t1 = resolve_typename_type (t1, /*only_current_p=*/true);
-
- if (TREE_CODE (t2) == TYPENAME_TYPE && !comparing_typenames)
- t2 = resolve_typename_type (t2, /*only_current_p=*/true);
+ if (!comparing_specializations)
+ {
+ /* TYPENAME_TYPEs should be resolved if the qualifying scope is the
+ current instantiation. */
+ if (TREE_CODE (t1) == TYPENAME_TYPE)
+ t1 = resolve_typename_type (t1, /*only_current_p=*/true);
+
+ if (TREE_CODE (t2) == TYPENAME_TYPE)
+ t2 = resolve_typename_type (t2, /*only_current_p=*/true);
+ }
if (TYPE_PTRMEMFUNC_P (t1))
t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 195bb21..4357615 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -3233,20 +3233,63 @@ this reason the attribute is not allowed on types to annotate indirect
calls.
@item malloc
+@item malloc (@var{deallocator})
+@item malloc (@var{deallocator}, @var{ptr-index})
@cindex @code{malloc} function attribute
@cindex functions that behave like malloc
-This tells the compiler that a function is @code{malloc}-like, i.e.,
-that the pointer @var{P} returned by the function cannot alias any
+Attribute @code{malloc} indicates that a function is @code{malloc}-like,
+i.e., that the pointer @var{P} returned by the function cannot alias any
other pointer valid when the function returns, and moreover no
pointers to valid objects occur in any storage addressed by @var{P}.
-Using this attribute can improve optimization. Compiler predicts
-that a function with the attribute returns non-null in most cases.
-Functions like
-@code{malloc} and @code{calloc} have this property because they return
-a pointer to uninitialized or zeroed-out storage. However, functions
-like @code{realloc} do not have this property, as they can return a
-pointer to storage containing pointers.
+Independently, the form of the attribute with one or two arguments
+associates @code{deallocator} as a suitable deallocation function for
+pointers returned from the @code{malloc}-like function. @var{ptr-index}
+denotes the positional argument to which when the pointer is passed in
+calls to @code{deallocator} has the effect of deallocating it.
+
+Using the attribute with no arguments is designed to improve optimization.
+The compiler predicts that a function with the attribute returns non-null
+in most cases. Functions like @code{malloc} and @code{calloc} have this
+property because they return a pointer to uninitialized or zeroed-out
+storage. However, functions like @code{realloc} do not have this property,
+as they may return pointers to storage containing pointers to existing
+objects.
+
+Associating a function with a @var{deallocator} helps detect calls to
+mismatched allocation and deallocation functions and diagnose them
+under the control of options such as @option{-Wmismatched-dealloc}.
+To indicate that an allocation function both satisifies the nonaliasing
+property and has a deallocator associated with it, both the plain form
+of the attribute and the one with the @var{deallocator} argument must
+be used.
+
+For example, besides stating that the functions return pointers that do
+not alias any others, the following declarations make the @code{fclose}
+and @code{frepen} functions suitable deallocators for pointers returned
+from all the functions that return them, and the @code{pclose} function
+as the only other suitable deallocator besides @code{freopen} for pointers
+returned from @code{popen}. The deallocator functions must declared
+before they can be referenced in the attribute.
+
+@smallexample
+int fclose (FILE*);
+FILE* freopen (const char*, const char*, FILE*);
+int pclose (FILE*);
+
+__attribute__ ((malloc, malloc (fclose), malloc (freopen, 3)))
+ FILE* fdopen (int);
+__attribute__ ((malloc, malloc (fclose), malloc (freopen, 3)))
+ FILE* fopen (const char*, const char*);
+__attribute__ ((malloc, malloc (fclose), malloc (freopen, 3)))
+ FILE* fmemopen(void *, size_t, const char *);
+__attribute__ ((malloc, malloc (fclose), malloc (freopen, 3)))
+ FILE* freopen (const char*, const char*, FILE*);
+__attribute__ ((malloc, malloc (pclose), malloc (freopen, 3)))
+ FILE* popen (const char*, const char*);
+__attribute__ ((malloc, malloc (fclose), malloc (freopen, 3)))
+ FILE* tmpfile (void);
+@end smallexample
@item no_icf
@cindex @code{no_icf} function attribute
diff --git a/gcc/doc/implement-c.texi b/gcc/doc/implement-c.texi
index 692297b..d7433ba 100644
--- a/gcc/doc/implement-c.texi
+++ b/gcc/doc/implement-c.texi
@@ -576,6 +576,11 @@ are of scalar types, the expression is interpreted by GCC as a read of
the volatile object; in the other cases, the expression is only evaluated
for its side effects.
+When an object of an aggregate type, with the same size and alignment as a
+scalar type @code{S}, is the subject of a volatile access by an assignment
+expression or an atomic function, the access to it is performed as if the
+object's declared type were @code{volatile S}.
+
@end itemize
@node Declarators implementation
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 35cd3dc..671b297 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -242,7 +242,8 @@ in the following sections.
-Wno-deprecated-enum-enum-conversion -Wno-deprecated-enum-float-conversion @gol
-Weffc++ -Wno-exceptions -Wextra-semi -Wno-inaccessible-base @gol
-Wno-inherited-variadic-ctor -Wno-init-list-lifetime @gol
--Wno-invalid-offsetof -Wno-literal-suffix -Wmismatched-tags @gol
+-Wno-invalid-offsetof -Wno-literal-suffix @gol
+-Wno-mismatched-new-delete -Wmismatched-tags @gol
-Wmultiple-inheritance -Wnamespaces -Wnarrowing @gol
-Wnoexcept -Wnoexcept-type -Wnon-virtual-dtor @gol
-Wpessimizing-move -Wno-placement-new -Wplacement-new=@var{n} @gol
@@ -452,7 +453,7 @@ Objective-C and Objective-C++ Dialects}.
-gstabs -gstabs+ -gstrict-dwarf -gno-strict-dwarf @gol
-gas-loc-support -gno-as-loc-support @gol
-gas-locview-support -gno-as-locview-support @gol
--gcolumn-info -gno-column-info @gol
+-gcolumn-info -gno-column-info -gdwarf32 -gdwarf64 @gol
-gstatement-frontiers -gno-statement-frontiers @gol
-gvariable-location-views -gno-variable-location-views @gol
-ginternal-reset-location-views -gno-internal-reset-location-views @gol
@@ -3859,6 +3860,40 @@ The warning is inactive inside a system header file, such as the STL, so
one can still use the STL. One may also instantiate or specialize
templates.
+@item -Wno-mismatched-new-delete @r{(C++ and Objective-C++ only)}
+@opindex Wmismatched-new-delete
+@opindex Wno-mismatched-new-delete
+Warn for mismatches between calls to @code{operator new} or @code{operator
+delete} and the corresponding call to the allocation or deallocation function.
+This includes invocations of C++ @code{operator delete} with pointers
+returned from either mismatched forms of @code{operator new}, or from other
+functions that allocate objects for which the @code{operator delete} isn't
+a suitable deallocator, as well as calls to other deallocation functions
+with pointers returned from @code{operator new} for which the deallocation
+function isn't suitable.
+
+For example, the @code{delete} expression in the function below is diagnosed
+because it doesn't match the array form of the @code{new} expression
+the pointer argument was returned from. Similarly, the call to @code{free}
+is also diagnosed.
+
+@smallexample
+void f ()
+@{
+ int *a = new int[n];
+ delete a; // warning: mismatch in array forms of expressions
+
+ char *p = new char[n];
+ free (p); // warning: mismatch between new and free
+@}
+@end smallexample
+
+The related option @option{-Wmismatched-dealloc} diagnoses mismatches
+involving allocation and deallocation functions other than @code{operator
+new} and @code{operator delete}.
+
+@option{-Wmismatched-new-delete} is enabled by default.
+
@item -Wmismatched-tags @r{(C++ and Objective-C++ only)}
@opindex Wmismatched-tags
@opindex Wno-mismatched-tags
@@ -6287,6 +6322,41 @@ Ignoring the warning can result in poorly optimized code.
disable the warning, but this is not recommended and should be done only
when non-existent profile data is justified.
+@item -Wno-mismatched-dealloc
+@opindex Wmismatched-dealloc
+@opindex Wno-mismatched-dealloc
+
+Warn for calls to deallocation functions with pointer arguments returned
+from from allocations functions for which the former isn't a suitable
+deallocator. A pair of functions can be associated as matching allocators
+and deallocators by use of attribute @code{malloc}. Unless disabled by
+the @option{-fno-builtin} option the standard functions @code{calloc},
+@code{malloc}, @code{realloc}, and @code{free}, as well as the corresponding
+forms of C++ @code{operator new} and @code{operator delete} are implicitly
+associated as matching allocators and deallocators. In the following
+example @code{mydealloc} is the deallocator for pointers returned from
+@code{myalloc}.
+
+@smallexample
+void mydealloc (void*);
+
+__attribute__ ((malloc (mydealloc, 1))) void*
+myalloc (size_t);
+
+void f (void)
+@{
+ void *p = myalloc (32);
+ // @dots{}use p@dots{}
+ free (p); // warning: not a matching deallocator for myalloc
+ mydealloc (p); // ok
+@}
+@end smallexample
+
+In C++, the related option @option{-Wmismatched-new-delete} diagnoses
+mismatches involving either @code{operator new} or @code{operator delete}.
+
+Option @option{-Wmismatched-dealloc} is enabled by default.
+
@item -Wmultistatement-macros
@opindex Wmultistatement-macros
@opindex Wno-multistatement-macros
@@ -7778,8 +7848,23 @@ to @option{-Wframe-larger-than=}@samp{SIZE_MAX} or larger.
@item -Wno-free-nonheap-object
@opindex Wno-free-nonheap-object
@opindex Wfree-nonheap-object
-Do not warn when attempting to free an object that was not allocated
-on the heap.
+Warn when attempting to deallocate an object that was either not allocated
+on the heap, or by using a pointer that was not returned from a prior call
+to the corresponding allocation function. For example, because the call
+to @code{stpcpy} returns a pointer to the terminating nul character and
+not to the begginning of the object, the call to @code{free} below is
+diagnosed.
+
+@smallexample
+void f (char *p)
+@{
+ p = stpcpy (p, "abc");
+ // ...
+ free (p); // warning
+@}
+@end smallexample
+
+@option{-Wfree-nonheap-object} is enabled by default.
@item -Wstack-usage=@var{byte-size}
@opindex Wstack-usage
@@ -9569,6 +9654,18 @@ information as possible into a separate output file with the extension
debug information. To be useful, this option requires a debugger capable of
reading @file{.dwo} files.
+@item -gdwarf32
+@itemx -gdwarf64
+@opindex gdwarf32
+@opindex gdwarf64
+If DWARF debugging information is enabled, the @option{-gdwarf32} selects
+the 32-bit DWARF format and the @option{-gdwarf64} selects the 64-bit
+DWARF format. The default is target specific, on most targets it is
+@option{-gdwarf32} though. The 32-bit DWARF format is smaller, but
+can't support more than 2GiB of debug information in any of the DWARF
+debug information sections. The 64-bit DWARF format allows larger debug
+information and might not be well supported by all consumers yet.
+
@item -gdescribe-dies
@opindex gdescribe-dies
Add description attributes to some DWARF DIEs that have no name attribute,
@@ -12956,6 +13053,9 @@ growth limit is needed to avoid exponential explosion of code size. Thus for
smaller units, the size is increased to @option{--param large-unit-insns}
before applying @option{--param inline-unit-growth}.
+@item lazy-modules
+Maximum number of concurrently open C++ module files when lazy loading.
+
@item inline-unit-growth
Specifies maximal overall growth of the compilation unit caused by inlining.
For example, parameter value 20 limits unit growth to 1.2 times the original
@@ -12967,6 +13067,9 @@ Specifies maximal overall growth of the compilation unit caused by
interprocedural constant propagation. For example, parameter value 10 limits
unit growth to 1.1 times the original size.
+@item ipa-cp-large-unit-insns
+The size of translation unit that IPA-CP pass considers large.
+
@item large-stack-frame
The limit specifying large stack frames. While inlining the algorithm is trying
to not grow past this limit too much.
@@ -13021,19 +13124,19 @@ Deeper chains are still handled by late inlining.
Probability (in percent) that C++ inline function with comdat visibility
are shared across multiple compilation units.
-@item ipa-modref-max-bases
-@item ipa-modref-max-refs
-@item ipa-modref-max-accesses
+@item modref-max-bases
+@item modref-max-refs
+@item modref-max-accesses
Specifies the maximal number of base pointers, referneces and accesses stored
for a single function by mod/ref analysis.
-@item ipa-modref-max-tests
+@item modref-max-tests
Specifies the maxmal number of tests alias oracle can perform to disambiguate
memory locations using the mod/ref information. This parameter ought to be
-bigger than @option{--param ipa-modref-max-bases} and @option{--param
-ipa-modref-max-refs}.
+bigger than @option{--param modref-max-bases} and @option{--param
+modref-max-refs}.
-@item ipa-modref-max-depth
+@item modref-max-depth
Specifies the maximum depth of DFS walk used by modref escape analysis.
Setting to 0 disables the analysis completely.
@@ -13881,6 +13984,12 @@ If the size of a local variable in bytes is smaller or equal to this
number, directly poison (or unpoison) shadow memory instead of using
run-time callbacks.
+@item tsan-distinguish-volatile
+Emit special instrumentation for accesses to volatiles.
+
+@item tsan-instrument-func-entry-exit
+Emit instrumentation calls to __tsan_func_entry() and __tsan_func_exit().
+
@item max-fsm-thread-path-insns
Maximum number of instructions to copy when duplicating blocks on a
finite state automaton jump thread path.
@@ -13920,6 +14029,9 @@ we may be able to devirtualize speculatively.
The maximum number of assertions to add along the default edge of a switch
statement during VRP.
+@item evrp-mode
+Specifies the mode Early VRP should operate in.
+
@item unroll-jam-min-percent
The minimum percentage of memory references that must be optimized
away for the unroll-and-jam transformation to be considered profitable.
@@ -14084,15 +14196,26 @@ Maximum number of VALUEs handled during a single find_base_term call.
The maximum number of exploded nodes per program point within
the analyzer, before terminating analysis of that point.
+@item analyzer-max-constraints
+The maximum number of constraints per state.
+
@item analyzer-min-snodes-for-call-summary
The minimum number of supernodes within a function for the
analyzer to consider summarizing its effects at call sites.
+@item analyzer-max-enodes-for-full-dump
+The maximum depth of exploded nodes that should appear in a dot dump
+before switching to a less verbose format.
+
@item analyzer-max-recursion-depth
The maximum number of times a callsite can appear in a call stack
within the analyzer, before terminating analysis of a call that would
recurse deeper.
+@item analyzer-max-svalue-depth
+The maximum depth of a symbolic value, before approximating
+the value as unknown.
+
@item gimple-fe-computed-hot-bb-threshold
The number of executions of a basic block which is considered hot.
The parameter is used only in GIMPLE FE.
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index f507765..d9b855c 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -8090,43 +8090,9 @@ need to override this if your target has special flags that might be
set via @code{__attribute__}.
@end deftypefn
-@deftypefn {Target Hook} int TARGET_ASM_RECORD_GCC_SWITCHES (print_switch_type @var{type}, const char *@var{text})
+@deftypefn {Target Hook} void TARGET_ASM_RECORD_GCC_SWITCHES (const char *@var{})
Provides the target with the ability to record the gcc command line
-switches that have been passed to the compiler, and options that are
-enabled. The @var{type} argument specifies what is being recorded.
-It can take the following values:
-
-@table @gcctabopt
-@item SWITCH_TYPE_PASSED
-@var{text} is a command line switch that has been set by the user.
-
-@item SWITCH_TYPE_ENABLED
-@var{text} is an option which has been enabled. This might be as a
-direct result of a command line switch, or because it is enabled by
-default or because it has been enabled as a side effect of a different
-command line switch. For example, the @option{-O2} switch enables
-various different individual optimization passes.
-
-@item SWITCH_TYPE_DESCRIPTIVE
-@var{text} is either NULL or some descriptive text which should be
-ignored. If @var{text} is NULL then it is being used to warn the
-target hook that either recording is starting or ending. The first
-time @var{type} is SWITCH_TYPE_DESCRIPTIVE and @var{text} is NULL, the
-warning is for start up and the second time the warning is for
-wind down. This feature is to allow the target hook to make any
-necessary preparations before it starts to record switches and to
-perform any necessary tidying up after it has finished recording
-switches.
-
-@item SWITCH_TYPE_LINE_START
-This option can be ignored by this target hook.
-
-@item SWITCH_TYPE_LINE_END
-This option can be ignored by this target hook.
-@end table
-
-The hook's return value must be zero. Other return values may be
-supported in the future.
+switches provided as argument.
By default this hook is set to NULL, but an example implementation is
provided for ELF based targets. Called @var{elf_record_gcc_switches},
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index c23a3ca..7b340ba 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -182,14 +182,14 @@ static GTY(()) section *debug_frame_section;
bytes.
However, the SGI/MIPS ABI uses an initial length which is equal to
- DWARF_OFFSET_SIZE. It is defined (elsewhere) accordingly. */
+ dwarf_offset_size. It is defined (elsewhere) accordingly. */
#ifndef DWARF_INITIAL_LENGTH_SIZE
-#define DWARF_INITIAL_LENGTH_SIZE (DWARF_OFFSET_SIZE == 4 ? 4 : 12)
+#define DWARF_INITIAL_LENGTH_SIZE (dwarf_offset_size == 4 ? 4 : 12)
#endif
#ifndef DWARF_INITIAL_LENGTH_SIZE_STR
-#define DWARF_INITIAL_LENGTH_SIZE_STR (DWARF_OFFSET_SIZE == 4 ? "-4" : "-12")
+#define DWARF_INITIAL_LENGTH_SIZE_STR (dwarf_offset_size == 4 ? "-4" : "-12")
#endif
/* Round SIZE up to the nearest BOUNDARY. */
@@ -199,7 +199,7 @@ static GTY(()) section *debug_frame_section;
/* CIE identifier. */
#if HOST_BITS_PER_WIDE_INT >= 64
#define DWARF_CIE_ID \
- (unsigned HOST_WIDE_INT) (DWARF_OFFSET_SIZE == 4 ? DW_CIE_ID : DW64_CIE_ID)
+ (unsigned HOST_WIDE_INT) (dwarf_offset_size == 4 ? DW_CIE_ID : DW64_CIE_ID)
#else
#define DWARF_CIE_ID DW_CIE_ID
#endif
@@ -287,8 +287,8 @@ static GTY(()) bool do_eh_frame = false;
static unsigned int rnglist_idx;
/* Data and reference forms for relocatable data. */
-#define DW_FORM_data (DWARF_OFFSET_SIZE == 8 ? DW_FORM_data8 : DW_FORM_data4)
-#define DW_FORM_ref (DWARF_OFFSET_SIZE == 8 ? DW_FORM_ref8 : DW_FORM_ref4)
+#define DW_FORM_data (dwarf_offset_size == 8 ? DW_FORM_data8 : DW_FORM_data4)
+#define DW_FORM_ref (dwarf_offset_size == 8 ? DW_FORM_ref8 : DW_FORM_ref4)
#ifndef DEBUG_FRAME_SECTION
#define DEBUG_FRAME_SECTION ".debug_frame"
@@ -602,10 +602,10 @@ output_fde (dw_fde_ref fde, bool for_eh, bool second,
ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + j);
if (!XCOFF_DEBUGGING_INFO || for_eh)
{
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4 && !for_eh)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4 && !for_eh)
dw2_asm_output_data (4, 0xffffffff, "Initial length escape value"
" indicating 64-bit DWARF extension");
- dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
+ dw2_asm_output_delta (for_eh ? 4 : dwarf_offset_size, l2, l1,
"FDE Length");
}
ASM_OUTPUT_LABEL (asm_out_file, l1);
@@ -613,7 +613,7 @@ output_fde (dw_fde_ref fde, bool for_eh, bool second,
if (for_eh)
dw2_asm_output_delta (4, l1, section_start_label, "FDE CIE offset");
else
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, section_start_label,
+ dw2_asm_output_offset (dwarf_offset_size, section_start_label,
debug_frame_section, "FDE CIE offset");
begin = second ? fde->dw_fde_second_begin : fde->dw_fde_begin;
@@ -806,17 +806,17 @@ output_call_frame_info (int for_eh)
ASM_GENERATE_INTERNAL_LABEL (l2, CIE_END_LABEL, for_eh);
if (!XCOFF_DEBUGGING_INFO || for_eh)
{
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4 && !for_eh)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4 && !for_eh)
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating 64-bit DWARF extension");
- dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
+ dw2_asm_output_delta (for_eh ? 4 : dwarf_offset_size, l2, l1,
"Length of Common Information Entry");
}
ASM_OUTPUT_LABEL (asm_out_file, l1);
/* Now that the CIE pointer is PC-relative for EH,
use 0 to identify the CIE. */
- dw2_asm_output_data ((for_eh ? 4 : DWARF_OFFSET_SIZE),
+ dw2_asm_output_data ((for_eh ? 4 : dwarf_offset_size),
(for_eh ? 0 : DWARF_CIE_ID),
"CIE Identifier Tag");
@@ -1623,7 +1623,7 @@ loc_list_plus_const (dw_loc_list_ref list_head, poly_int64 offset)
}
#define DWARF_REF_SIZE \
- (dwarf_version == 2 ? DWARF2_ADDR_SIZE : DWARF_OFFSET_SIZE)
+ (dwarf_version == 2 ? DWARF2_ADDR_SIZE : dwarf_offset_size)
/* The number of bits that can be encoded by largest DW_FORM_dataN.
In DWARF4 and earlier it is DW_FORM_data8 with 64 bits, in DWARF5
@@ -3229,33 +3229,33 @@ skeleton_chain_node;
/* Fixed size portion of the DWARF compilation unit header. */
#define DWARF_COMPILE_UNIT_HEADER_SIZE \
- (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE \
+ (DWARF_INITIAL_LENGTH_SIZE + dwarf_offset_size \
+ (dwarf_version >= 5 ? 4 : 3))
/* Fixed size portion of the DWARF comdat type unit header. */
#define DWARF_COMDAT_TYPE_UNIT_HEADER_SIZE \
(DWARF_COMPILE_UNIT_HEADER_SIZE \
- + DWARF_TYPE_SIGNATURE_SIZE + DWARF_OFFSET_SIZE)
+ + DWARF_TYPE_SIGNATURE_SIZE + dwarf_offset_size)
/* Fixed size portion of the DWARF skeleton compilation unit header. */
#define DWARF_COMPILE_UNIT_SKELETON_HEADER_SIZE \
(DWARF_COMPILE_UNIT_HEADER_SIZE + (dwarf_version >= 5 ? 8 : 0))
/* Fixed size portion of public names info. */
-#define DWARF_PUBNAMES_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2)
+#define DWARF_PUBNAMES_HEADER_SIZE (2 * dwarf_offset_size + 2)
/* Fixed size portion of the address range info. */
#define DWARF_ARANGES_HEADER_SIZE \
- (DWARF_ROUND (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4, \
+ (DWARF_ROUND (DWARF_INITIAL_LENGTH_SIZE + dwarf_offset_size + 4, \
DWARF2_ADDR_SIZE * 2) \
- DWARF_INITIAL_LENGTH_SIZE)
/* Size of padding portion in the address range info. It must be
aligned to twice the pointer size. */
#define DWARF_ARANGES_PAD_SIZE \
- (DWARF_ROUND (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4, \
+ (DWARF_ROUND (DWARF_INITIAL_LENGTH_SIZE + dwarf_offset_size + 4, \
DWARF2_ADDR_SIZE * 2) \
- - (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4))
+ - (DWARF_INITIAL_LENGTH_SIZE + dwarf_offset_size + 4))
/* Use assembler line directives if available. */
#ifndef DWARF2_ASM_LINE_DEBUG_INFO
@@ -4787,7 +4787,7 @@ find_string_form (struct indirect_string_node *node)
/* If the string is shorter or equal to the size of the reference, it is
always better to put it inline. */
- if (len <= DWARF_OFFSET_SIZE || node->refcount == 0)
+ if (len <= (unsigned) dwarf_offset_size || node->refcount == 0)
return node->form = DW_FORM_string;
/* If we cannot expect the linker to merge strings in .debug_str
@@ -4795,7 +4795,7 @@ find_string_form (struct indirect_string_node *node)
single module. */
if (DWARF2_INDIRECT_STRING_SUPPORT_MISSING_ON_TARGET
|| ((debug_str_section->common.flags & SECTION_MERGE) == 0
- && (len - DWARF_OFFSET_SIZE) * node->refcount <= len))
+ && (len - dwarf_offset_size) * node->refcount <= len))
return node->form = DW_FORM_string;
set_indirect_string (node);
@@ -8892,7 +8892,7 @@ output_loclists_offsets (dw_die_ref die)
dw_loc_list_ref l = AT_loc_list (a);
if (l->offset_emitted)
continue;
- dw2_asm_output_delta (DWARF_OFFSET_SIZE, l->ll_symbol,
+ dw2_asm_output_delta (dwarf_offset_size, l->ll_symbol,
loc_section_label, NULL);
gcc_assert (l->hash == loc_list_idx);
loc_list_idx++;
@@ -9400,7 +9400,7 @@ size_of_die (dw_die_ref die)
size += DWARF2_ADDR_SIZE;
break;
case dw_val_class_offset:
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
break;
case dw_val_class_loc:
{
@@ -9421,10 +9421,10 @@ size_of_die (dw_die_ref die)
size += size_of_uleb128 (AT_loc_list (a)->hash);
}
else
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
break;
case dw_val_class_view_list:
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
break;
case dw_val_class_range_list:
if (value_format (a) == DW_FORM_rnglistx)
@@ -9434,7 +9434,7 @@ size_of_die (dw_die_ref die)
size += size_of_uleb128 (r->idx);
}
else
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
break;
case dw_val_class_const:
size += size_of_sleb128 (AT_int (a));
@@ -9508,13 +9508,13 @@ size_of_die (dw_die_ref die)
else if (dwarf_version == 2)
size += DWARF2_ADDR_SIZE;
else
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
}
else
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
break;
case dw_val_class_fde_ref:
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
break;
case dw_val_class_lbl_id:
if (dwarf_split_debug_info && AT_index (a) != NOT_INDEXED)
@@ -9528,12 +9528,12 @@ size_of_die (dw_die_ref die)
case dw_val_class_lineptr:
case dw_val_class_macptr:
case dw_val_class_loclistsptr:
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
break;
case dw_val_class_str:
form = AT_string_form (a);
if (form == DW_FORM_strp || form == DW_FORM_line_strp)
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
else if (form == dwarf_FORM (DW_FORM_strx))
size += size_of_uleb128 (AT_index (a));
else
@@ -9546,7 +9546,7 @@ size_of_die (dw_die_ref die)
size += 8;
break;
case dw_val_class_vms_delta:
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
break;
case dw_val_class_high_pc:
size += DWARF2_ADDR_SIZE;
@@ -9724,9 +9724,9 @@ size_of_pubnames (vec<pubname_entry, va_gc> *names)
size = DWARF_PUBNAMES_HEADER_SIZE;
FOR_EACH_VEC_ELT (*names, i, p)
if (include_pubname_in_output (names, p))
- size += strlen (p->name) + DWARF_OFFSET_SIZE + 1 + space_for_flags;
+ size += strlen (p->name) + dwarf_offset_size + 1 + space_for_flags;
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
return size;
}
@@ -9823,7 +9823,7 @@ value_format (dw_attr_node *a)
/* FALLTHRU */
case dw_val_class_vms_delta:
case dw_val_class_offset:
- switch (DWARF_OFFSET_SIZE)
+ switch (dwarf_offset_size)
{
case 4:
return DW_FORM_data4;
@@ -10525,7 +10525,7 @@ output_range_list_offset (dw_attr_node *a)
if (dwarf_version >= 5)
{
dw_ranges *r = &(*ranges_table)[a->dw_attr_val.v.val_offset];
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, r->label,
+ dw2_asm_output_offset (dwarf_offset_size, r->label,
debug_ranges_section, "%s", name);
}
else
@@ -10533,7 +10533,7 @@ output_range_list_offset (dw_attr_node *a)
char *p = strchr (ranges_section_label, '\0');
sprintf (p, "+" HOST_WIDE_INT_PRINT_HEX,
a->dw_attr_val.v.val_offset * 2 * DWARF2_ADDR_SIZE);
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, ranges_section_label,
+ dw2_asm_output_offset (dwarf_offset_size, ranges_section_label,
debug_ranges_section, "%s", name);
*p = '\0';
}
@@ -10545,7 +10545,7 @@ output_range_list_offset (dw_attr_node *a)
dw2_asm_output_data_uleb128 (r->idx, "%s", name);
}
else
- dw2_asm_output_data (DWARF_OFFSET_SIZE,
+ dw2_asm_output_data (dwarf_offset_size,
a->dw_attr_val.v.val_offset * 2 * DWARF2_ADDR_SIZE,
"%s (offset from %s)", name, ranges_section_label);
}
@@ -10559,7 +10559,7 @@ output_loc_list_offset (dw_attr_node *a)
gcc_assert (sym);
if (!dwarf_split_debug_info)
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, sym, debug_loc_section,
+ dw2_asm_output_offset (dwarf_offset_size, sym, debug_loc_section,
"%s", dwarf_attr_name (a->dw_attr));
else if (dwarf_version >= 5)
{
@@ -10569,7 +10569,7 @@ output_loc_list_offset (dw_attr_node *a)
sym);
}
else
- dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym, loc_section_label,
+ dw2_asm_output_delta (dwarf_offset_size, sym, loc_section_label,
"%s", dwarf_attr_name (a->dw_attr));
}
@@ -10582,10 +10582,10 @@ output_view_list_offset (dw_attr_node *a)
gcc_assert (sym);
if (dwarf_split_debug_info)
- dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym, loc_section_label,
+ dw2_asm_output_delta (dwarf_offset_size, sym, loc_section_label,
"%s", dwarf_attr_name (a->dw_attr));
else
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, sym, debug_loc_section,
+ dw2_asm_output_offset (dwarf_offset_size, sym, debug_loc_section,
"%s", dwarf_attr_name (a->dw_attr));
}
@@ -10663,7 +10663,7 @@ output_die (dw_die_ref die)
break;
case dw_val_class_offset:
- dw2_asm_output_data (DWARF_OFFSET_SIZE, a->dw_attr_val.v.val_offset,
+ dw2_asm_output_data (dwarf_offset_size, a->dw_attr_val.v.val_offset,
"%s", name);
break;
@@ -10857,7 +10857,7 @@ output_die (dw_die_ref die)
if (dwarf_version == 2)
size = DWARF2_ADDR_SIZE;
else
- size = DWARF_OFFSET_SIZE;
+ size = dwarf_offset_size;
/* ??? We cannot unconditionally output die_offset if
non-zero - others might create references to those
DIEs via symbols.
@@ -10877,7 +10877,7 @@ output_die (dw_die_ref die)
else
{
gcc_assert (AT_ref (a)->die_offset);
- dw2_asm_output_data (DWARF_OFFSET_SIZE, AT_ref (a)->die_offset,
+ dw2_asm_output_data (dwarf_offset_size, AT_ref (a)->die_offset,
"%s", name);
}
break;
@@ -10888,18 +10888,18 @@ output_die (dw_die_ref die)
ASM_GENERATE_INTERNAL_LABEL (l1, FDE_LABEL,
a->dw_attr_val.v.val_fde_index * 2);
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, l1, debug_frame_section,
+ dw2_asm_output_offset (dwarf_offset_size, l1, debug_frame_section,
"%s", name);
}
break;
case dw_val_class_vms_delta:
#ifdef ASM_OUTPUT_DWARF_VMS_DELTA
- dw2_asm_output_vms_delta (DWARF_OFFSET_SIZE,
+ dw2_asm_output_vms_delta (dwarf_offset_size,
AT_vms_delta2 (a), AT_vms_delta1 (a),
"%s", name);
#else
- dw2_asm_output_delta (DWARF_OFFSET_SIZE,
+ dw2_asm_output_delta (dwarf_offset_size,
AT_vms_delta2 (a), AT_vms_delta1 (a),
"%s", name);
#endif
@@ -10910,28 +10910,28 @@ output_die (dw_die_ref die)
break;
case dw_val_class_lineptr:
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, AT_lbl (a),
+ dw2_asm_output_offset (dwarf_offset_size, AT_lbl (a),
debug_line_section, "%s", name);
break;
case dw_val_class_macptr:
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, AT_lbl (a),
+ dw2_asm_output_offset (dwarf_offset_size, AT_lbl (a),
debug_macinfo_section, "%s", name);
break;
case dw_val_class_loclistsptr:
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, AT_lbl (a),
+ dw2_asm_output_offset (dwarf_offset_size, AT_lbl (a),
debug_loc_section, "%s", name);
break;
case dw_val_class_str:
if (a->dw_attr_val.v.val_str->form == DW_FORM_strp)
- dw2_asm_output_offset (DWARF_OFFSET_SIZE,
+ dw2_asm_output_offset (dwarf_offset_size,
a->dw_attr_val.v.val_str->label,
debug_str_section,
"%s: \"%s\"", name, AT_string (a));
else if (a->dw_attr_val.v.val_str->form == DW_FORM_line_strp)
- dw2_asm_output_offset (DWARF_OFFSET_SIZE,
+ dw2_asm_output_offset (dwarf_offset_size,
a->dw_attr_val.v.val_str->label,
debug_line_str_section,
"%s: \"%s\"", name, AT_string (a));
@@ -11048,10 +11048,10 @@ output_compilation_unit_header (enum dwarf_unit_type ut)
{
if (!XCOFF_DEBUGGING_INFO)
{
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating 64-bit DWARF extension");
- dw2_asm_output_data (DWARF_OFFSET_SIZE,
+ dw2_asm_output_data (dwarf_offset_size,
next_die_offset - DWARF_INITIAL_LENGTH_SIZE,
"Length of Compilation Unit Info");
}
@@ -11071,7 +11071,7 @@ output_compilation_unit_header (enum dwarf_unit_type ut)
dw2_asm_output_data (1, ut, "%s", name);
dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
}
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, abbrev_section_label,
+ dw2_asm_output_offset (dwarf_offset_size, abbrev_section_label,
debug_abbrev_section,
"Offset Into Abbrev. Section");
if (dwarf_version < 5)
@@ -11261,12 +11261,12 @@ output_skeleton_debug_sections (dw_die_ref comp_unit,
/* Produce the skeleton compilation-unit header. This one differs enough from
a normal CU header that it's better not to call output_compilation_unit
header. */
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating 64-bit "
"DWARF extension");
- dw2_asm_output_data (DWARF_OFFSET_SIZE,
+ dw2_asm_output_data (dwarf_offset_size,
DWARF_COMPILE_UNIT_SKELETON_HEADER_SIZE
- DWARF_INITIAL_LENGTH_SIZE
+ size_of_die (comp_unit),
@@ -11277,7 +11277,7 @@ output_skeleton_debug_sections (dw_die_ref comp_unit,
dw2_asm_output_data (1, DW_UT_skeleton, "DW_UT_skeleton");
dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
}
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_abbrev_section_label,
+ dw2_asm_output_offset (dwarf_offset_size, debug_skeleton_abbrev_section_label,
debug_skeleton_abbrev_section,
"Offset Into Abbrev. Section");
if (dwarf_version < 5)
@@ -11362,7 +11362,7 @@ output_comdat_type_unit (comdat_type_node *node,
output_compilation_unit_header (dwarf_split_debug_info
? DW_UT_split_type : DW_UT_type);
output_signature (node->signature, "Type Signature");
- dw2_asm_output_data (DWARF_OFFSET_SIZE, node->type_die->die_offset,
+ dw2_asm_output_data (dwarf_offset_size, node->type_die->die_offset,
"Offset to Type DIE");
output_die (node->root_die);
@@ -11491,7 +11491,7 @@ output_pubname (dw_offset die_offset, pubname_entry *entry)
dw_die_ref die = entry->die;
int is_static = get_AT_flag (die, DW_AT_external) ? 0 : 1;
- dw2_asm_output_data (DWARF_OFFSET_SIZE, die_offset, "DIE offset");
+ dw2_asm_output_data (dwarf_offset_size, die_offset, "DIE offset");
if (debug_generate_pub_sections == 2)
{
@@ -11565,10 +11565,10 @@ output_pubnames (vec<pubname_entry, va_gc> *names)
if (!XCOFF_DEBUGGING_INFO)
{
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating 64-bit DWARF extension");
- dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length,
+ dw2_asm_output_data (dwarf_offset_size, pubnames_length,
"Pub Info Length");
}
@@ -11576,14 +11576,14 @@ output_pubnames (vec<pubname_entry, va_gc> *names)
dw2_asm_output_data (2, 2, "DWARF pubnames/pubtypes version");
if (dwarf_split_debug_info)
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_info_section_label,
+ dw2_asm_output_offset (dwarf_offset_size, debug_skeleton_info_section_label,
debug_skeleton_info_section,
"Offset of Compilation Unit Info");
else
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label,
+ dw2_asm_output_offset (dwarf_offset_size, debug_info_section_label,
debug_info_section,
"Offset of Compilation Unit Info");
- dw2_asm_output_data (DWARF_OFFSET_SIZE, next_die_offset,
+ dw2_asm_output_data (dwarf_offset_size, next_die_offset,
"Compilation Unit Length");
FOR_EACH_VEC_ELT (*names, i, pub)
@@ -11614,7 +11614,7 @@ output_pubnames (vec<pubname_entry, va_gc> *names)
}
}
- dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, NULL);
+ dw2_asm_output_data (dwarf_offset_size, 0, NULL);
}
/* Output public names and types tables if necessary. */
@@ -11647,21 +11647,21 @@ output_aranges (void)
if (!XCOFF_DEBUGGING_INFO)
{
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating 64-bit DWARF extension");
- dw2_asm_output_data (DWARF_OFFSET_SIZE, aranges_length,
+ dw2_asm_output_data (dwarf_offset_size, aranges_length,
"Length of Address Ranges Info");
}
/* Version number for aranges is still 2, even up to DWARF5. */
dw2_asm_output_data (2, 2, "DWARF aranges version");
if (dwarf_split_debug_info)
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_info_section_label,
+ dw2_asm_output_offset (dwarf_offset_size, debug_skeleton_info_section_label,
debug_skeleton_info_section,
"Offset of Compilation Unit Info");
else
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label,
+ dw2_asm_output_offset (dwarf_offset_size, debug_info_section_label,
debug_info_section,
"Offset of Compilation Unit Info");
dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Size of Address");
@@ -11936,11 +11936,11 @@ output_rnglists (unsigned generation)
2 + generation * 4);
ASM_GENERATE_INTERNAL_LABEL (l2, DEBUG_RANGES_SECTION_LABEL,
3 + generation * 4);
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating "
"64-bit DWARF extension");
- dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1,
+ dw2_asm_output_delta (dwarf_offset_size, l2, l1,
"Length of Range Lists");
ASM_OUTPUT_LABEL (asm_out_file, l1);
output_dwarf_version ();
@@ -11959,7 +11959,7 @@ output_rnglists (unsigned generation)
ASM_OUTPUT_LABEL (asm_out_file, ranges_base_label);
FOR_EACH_VEC_SAFE_ELT (ranges_table, i, r)
if (r->label)
- dw2_asm_output_delta (DWARF_OFFSET_SIZE, r->label,
+ dw2_asm_output_delta (dwarf_offset_size, r->label,
ranges_base_label, NULL);
}
@@ -12219,7 +12219,7 @@ output_line_string (enum dwarf_form form, const char *str,
node = find_AT_string_in_table (str, debug_line_str_hash);
set_indirect_string (node);
node->form = form;
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, node->label,
+ dw2_asm_output_offset (dwarf_offset_size, node->label,
debug_line_str_section, "%s: %#x: \"%s\"",
entry_kind, 0, node->str);
break;
@@ -12728,10 +12728,10 @@ output_line_info (bool prologue_only)
if (!XCOFF_DEBUGGING_INFO)
{
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating 64-bit DWARF extension");
- dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1,
+ dw2_asm_output_delta (dwarf_offset_size, l2, l1,
"Length of Source Line Info");
}
@@ -12743,7 +12743,7 @@ output_line_info (bool prologue_only)
dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Address Size");
dw2_asm_output_data (1, 0, "Segment Size");
}
- dw2_asm_output_delta (DWARF_OFFSET_SIZE, p2, p1, "Prolog Length");
+ dw2_asm_output_delta (dwarf_offset_size, p2, p1, "Prolog Length");
ASM_OUTPUT_LABEL (asm_out_file, p1);
/* Define the architecture-dependent minimum instruction length (in bytes).
@@ -24438,115 +24438,6 @@ gen_ptr_to_mbr_type_die (tree type, dw_die_ref context_die)
static char *producer_string;
-/* Return a heap allocated producer string including command line options
- if -grecord-gcc-switches. */
-
-static char *
-gen_producer_string (void)
-{
- size_t j;
- auto_vec<const char *> switches;
- const char *language_string = lang_hooks.name;
- char *producer, *tail;
- const char *p;
- size_t len = dwarf_record_gcc_switches ? 0 : 3;
- size_t plen = strlen (language_string) + 1 + strlen (version_string);
-
- for (j = 1; dwarf_record_gcc_switches && j < save_decoded_options_count; j++)
- switch (save_decoded_options[j].opt_index)
- {
- case OPT_o:
- case OPT_d:
- case OPT_dumpbase:
- case OPT_dumpbase_ext:
- case OPT_dumpdir:
- case OPT_quiet:
- case OPT_version:
- case OPT_v:
- case OPT_w:
- case OPT_L:
- case OPT_D:
- case OPT_I:
- case OPT_U:
- case OPT_SPECIAL_unknown:
- case OPT_SPECIAL_ignore:
- case OPT_SPECIAL_warn_removed:
- case OPT_SPECIAL_program_name:
- case OPT_SPECIAL_input_file:
- case OPT_grecord_gcc_switches:
- case OPT__output_pch_:
- case OPT_fdiagnostics_show_location_:
- case OPT_fdiagnostics_show_option:
- case OPT_fdiagnostics_show_caret:
- case OPT_fdiagnostics_show_labels:
- case OPT_fdiagnostics_show_line_numbers:
- case OPT_fdiagnostics_color_:
- case OPT_fdiagnostics_format_:
- case OPT_fverbose_asm:
- case OPT____:
- case OPT__sysroot_:
- case OPT_nostdinc:
- case OPT_nostdinc__:
- case OPT_fpreprocessed:
- case OPT_fltrans_output_list_:
- case OPT_fresolution_:
- case OPT_fdebug_prefix_map_:
- case OPT_fmacro_prefix_map_:
- case OPT_ffile_prefix_map_:
- case OPT_fcompare_debug:
- case OPT_fchecking:
- case OPT_fchecking_:
- /* Ignore these. */
- continue;
- case OPT_flto_:
- {
- const char *lto_canonical = "-flto";
- switches.safe_push (lto_canonical);
- len += strlen (lto_canonical) + 1;
- break;
- }
- default:
- if (cl_options[save_decoded_options[j].opt_index].flags
- & CL_NO_DWARF_RECORD)
- continue;
- gcc_checking_assert (save_decoded_options[j].canonical_option[0][0]
- == '-');
- switch (save_decoded_options[j].canonical_option[0][1])
- {
- case 'M':
- case 'i':
- case 'W':
- continue;
- case 'f':
- if (strncmp (save_decoded_options[j].canonical_option[0] + 2,
- "dump", 4) == 0)
- continue;
- break;
- default:
- break;
- }
- switches.safe_push (save_decoded_options[j].orig_option_with_args_text);
- len += strlen (save_decoded_options[j].orig_option_with_args_text) + 1;
- break;
- }
-
- producer = XNEWVEC (char, plen + 1 + len + 1);
- tail = producer;
- sprintf (tail, "%s %s", language_string, version_string);
- tail += plen;
-
- FOR_EACH_VEC_ELT (switches, j, p)
- {
- len = strlen (p);
- *tail = ' ';
- memcpy (tail + 1, p, len);
- tail += len + 1;
- }
-
- *tail = '\0';
- return producer;
-}
-
/* Given a C and/or C++ language/version string return the "highest".
C++ is assumed to be "higher" than C in this case. Used for merging
LTO translation unit languages. */
@@ -28317,7 +28208,7 @@ output_macinfo_op (macinfo_entry *ref)
case DW_MACINFO_undef:
len = strlen (ref->info) + 1;
if (!dwarf_strict
- && len > DWARF_OFFSET_SIZE
+ && len > (size_t) dwarf_offset_size
&& !DWARF2_INDIRECT_STRING_SUPPORT_MISSING_ON_TARGET
&& (debug_str_section->common.flags & SECTION_MERGE) != 0)
{
@@ -28358,7 +28249,7 @@ output_macinfo_op (macinfo_entry *ref)
dw2_asm_output_data_uleb128 (ref->lineno, "At line number %lu",
(unsigned long) ref->lineno);
if (node->form == DW_FORM_strp)
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, node->label,
+ dw2_asm_output_offset (dwarf_offset_size, node->label,
debug_str_section, "The macro: \"%s\"",
ref->info);
else
@@ -28370,7 +28261,7 @@ output_macinfo_op (macinfo_entry *ref)
ASM_GENERATE_INTERNAL_LABEL (label,
DEBUG_MACRO_SECTION_LABEL,
ref->lineno + macinfo_label_base);
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, label, NULL, NULL);
+ dw2_asm_output_offset (dwarf_offset_size, label, NULL, NULL);
break;
default:
fprintf (asm_out_file, "%s unrecognized macinfo code %lu\n",
@@ -28454,7 +28345,7 @@ optimize_macinfo_range (unsigned int idx, vec<macinfo_entry, va_gc> *files,
/* The group name format is: wmN.[<encoded filename>.]<lineno>.<md5sum> */
grp_name = XALLOCAVEC (char, 4 + encoded_filename_len + linebuf_len + 1
+ 16 * 2 + 1);
- memcpy (grp_name, DWARF_OFFSET_SIZE == 4 ? "wm4." : "wm8.", 4);
+ memcpy (grp_name, dwarf_offset_size == 4 ? "wm4." : "wm8.", 4);
tail = grp_name + 4;
if (encoded_filename_len)
{
@@ -28525,7 +28416,7 @@ save_macinfo_strings (void)
case DW_MACINFO_undef:
len = strlen (ref->info) + 1;
if (!dwarf_strict
- && len > DWARF_OFFSET_SIZE
+ && len > (unsigned) dwarf_offset_size
&& !DWARF2_INDIRECT_STRING_SUPPORT_MISSING_ON_TARGET
&& (debug_str_section->common.flags & SECTION_MERGE) != 0)
set_indirect_string (find_AT_string (ref->info));
@@ -28578,11 +28469,11 @@ output_macinfo (const char *debug_line_label, bool early_lto_debug)
{
dw2_asm_output_data (2, dwarf_version >= 5 ? 5 : 4,
"DWARF macro version number");
- if (DWARF_OFFSET_SIZE == 8)
+ if (dwarf_offset_size == 8)
dw2_asm_output_data (1, 3, "Flags: 64-bit, lineptr present");
else
dw2_asm_output_data (1, 2, "Flags: 32-bit, lineptr present");
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_line_label,
+ dw2_asm_output_offset (dwarf_offset_size, debug_line_label,
debug_line_section, NULL);
}
@@ -28671,7 +28562,7 @@ output_macinfo (const char *debug_line_label, bool early_lto_debug)
ref->info = NULL;
dw2_asm_output_data (2, dwarf_version >= 5 ? 5 : 4,
"DWARF macro version number");
- if (DWARF_OFFSET_SIZE == 8)
+ if (dwarf_offset_size == 8)
dw2_asm_output_data (1, 1, "Flags: 64-bit");
else
dw2_asm_output_data (1, 0, "Flags: 32-bit");
@@ -29008,7 +28899,7 @@ output_index_string_offset (indirect_string_node **h, unsigned int *offset)
/* Assert that this node has been assigned an index. */
gcc_assert (node->index != NO_INDEX_ASSIGNED
&& node->index != NOT_INDEXED);
- dw2_asm_output_data (DWARF_OFFSET_SIZE, *offset,
+ dw2_asm_output_data (dwarf_offset_size, *offset,
"indexed string 0x%x: %s", node->index, node->str);
*offset += strlen (node->str) + 1;
}
@@ -29102,11 +28993,11 @@ output_indirect_strings (void)
debug_str_hash->traverse_noresize
<unsigned int *, count_index_strings> (&last_idx);
- str_offsets_length = last_idx * DWARF_OFFSET_SIZE + 4;
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ str_offsets_length = last_idx * dwarf_offset_size + 4;
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
dw2_asm_output_data (4, 0xffffffff,
"Escape value for 64-bit DWARF extension");
- dw2_asm_output_data (DWARF_OFFSET_SIZE, str_offsets_length,
+ dw2_asm_output_data (dwarf_offset_size, str_offsets_length,
"Length of string offsets unit");
dw2_asm_output_data (2, 5, "DWARF string offsets version");
dw2_asm_output_data (2, 0, "Header zero padding");
@@ -29196,10 +29087,10 @@ output_addr_table (void)
<unsigned int *, count_index_addrs> (&last_idx);
addrs_length = last_idx * DWARF2_ADDR_SIZE + 4;
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
dw2_asm_output_data (4, 0xffffffff,
"Escape value for 64-bit DWARF extension");
- dw2_asm_output_data (DWARF_OFFSET_SIZE, addrs_length,
+ dw2_asm_output_data (dwarf_offset_size, addrs_length,
"Length of Address Unit");
dw2_asm_output_data (2, 5, "DWARF addr version");
dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Size of Address");
@@ -31758,11 +31649,11 @@ dwarf2out_finish (const char *filename)
{
ASM_GENERATE_INTERNAL_LABEL (l1, DEBUG_LOC_SECTION_LABEL, 2);
ASM_GENERATE_INTERNAL_LABEL (l2, DEBUG_LOC_SECTION_LABEL, 3);
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating "
"64-bit DWARF extension");
- dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1,
+ dw2_asm_output_delta (dwarf_offset_size, l2, l1,
"Length of Location Lists");
ASM_OUTPUT_LABEL (asm_out_file, l1);
output_dwarf_version ();
@@ -32157,7 +32048,14 @@ dwarf2out_early_finish (const char *filename)
header compilation, so always fill it with empty string initially
and overwrite only here. */
dw_attr_node *producer = get_AT (comp_unit_die (), DW_AT_producer);
- producer_string = gen_producer_string ();
+
+ if (dwarf_record_gcc_switches)
+ producer_string = gen_producer_string (lang_hooks.name,
+ save_decoded_options,
+ save_decoded_options_count);
+ else
+ producer_string = concat (lang_hooks.name, " ", version_string, NULL);
+
producer->dw_attr_val.v.val_str->refcount--;
producer->dw_attr_val.v.val_str = find_AT_string (producer_string);
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index e77d74e..1241b13 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -8104,11 +8104,12 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
{
if (valueinit == -1)
{
- tree zero = build_constructor (TREE_TYPE (type), NULL);
+ tree zero = build_zero_cst (TREE_TYPE (type));
r = native_encode_initializer (zero, ptr + curpos,
fieldsize, 0,
mask + curpos);
- ggc_free (zero);
+ if (TREE_CODE (zero) == CONSTRUCTOR)
+ ggc_free (zero);
if (!r)
return 0;
valueinit = curpos;
@@ -8255,8 +8256,9 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
{
cnt--;
field = fld;
- val = build_constructor (TREE_TYPE (fld), NULL);
- to_free = val;
+ val = build_zero_cst (TREE_TYPE (fld));
+ if (TREE_CODE (val) == CONSTRUCTOR)
+ to_free = val;
}
}
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index a8e8bbb..1826640 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,9 @@
+2020-12-03 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/95342
+ * decl.c (gfc_match_function_decl): Avoid NULL pointer dereference.
+ (gfc_match_subroutine): Likewise.
+
2020-11-30 Tobias Burnus <tobias@codesourcery.com>
PR fortran/98011
diff --git a/gcc/gimple.c b/gcc/gimple.c
index e8246b7..bb13458 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -1514,11 +1514,12 @@ gimple_call_fnspec (const gcall *stmt)
such operator, then we can treat it as free. */
if (fndecl
&& DECL_IS_OPERATOR_DELETE_P (fndecl)
+ && DECL_IS_REPLACEABLE_OPERATOR (fndecl)
&& gimple_call_from_new_or_delete (stmt))
return ".co ";
/* Similarly operator new can be treated as malloc. */
if (fndecl
- && DECL_IS_OPERATOR_NEW_P (fndecl)
+ && DECL_IS_REPLACEABLE_OPERATOR_NEW_P (fndecl)
&& gimple_call_from_new_or_delete (stmt))
return "mC";
return "";
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index cd1a396..019aafd 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-b3a0b068f7fa2d65ba781271b2c0479d103b7d7b
+342e5f0b349553a69d7c99a18162ae2a1e6e5775
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/ipa-sra.c b/gcc/ipa-sra.c
index 82acc6a..7adc4b6 100644
--- a/gcc/ipa-sra.c
+++ b/gcc/ipa-sra.c
@@ -1480,7 +1480,7 @@ verify_access_tree_1 (gensum_param_access *access, HOST_WIDE_INT parent_offset,
{
while (access)
{
- gcc_assert (access->offset >= 0 && access->size > 0);
+ gcc_assert (access->offset >= 0 && access->size >= 0);
if (parent_size != 0)
{
diff --git a/gcc/opts.c b/gcc/opts.c
index cc1d0cc..3db08b3 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see
#include "spellcheck.h"
#include "opt-suggestions.h"
#include "diagnostic-color.h"
+#include "version.h"
#include "selftest.h"
static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff);
@@ -3266,6 +3267,124 @@ get_option_url (diagnostic_context *, int option_index)
return NULL;
}
+/* Return a heap allocated producer with command line options. */
+
+char *
+gen_command_line_string (cl_decoded_option *options,
+ unsigned int options_count)
+{
+ auto_vec<const char *> switches;
+ char *options_string, *tail;
+ const char *p;
+ size_t len = 0;
+
+ for (unsigned i = 0; i < options_count; i++)
+ switch (options[i].opt_index)
+ {
+ case OPT_o:
+ case OPT_d:
+ case OPT_dumpbase:
+ case OPT_dumpdir:
+ case OPT_quiet:
+ case OPT_version:
+ case OPT_v:
+ case OPT_w:
+ case OPT_L:
+ case OPT_D:
+ case OPT_I:
+ case OPT_U:
+ case OPT_SPECIAL_unknown:
+ case OPT_SPECIAL_ignore:
+ case OPT_SPECIAL_warn_removed:
+ case OPT_SPECIAL_program_name:
+ case OPT_SPECIAL_input_file:
+ case OPT_grecord_gcc_switches:
+ case OPT_frecord_gcc_switches:
+ case OPT__output_pch_:
+ case OPT_fdiagnostics_show_location_:
+ case OPT_fdiagnostics_show_option:
+ case OPT_fdiagnostics_show_caret:
+ case OPT_fdiagnostics_show_labels:
+ case OPT_fdiagnostics_show_line_numbers:
+ case OPT_fdiagnostics_color_:
+ case OPT_fdiagnostics_format_:
+ case OPT_fverbose_asm:
+ case OPT____:
+ case OPT__sysroot_:
+ case OPT_nostdinc:
+ case OPT_nostdinc__:
+ case OPT_fpreprocessed:
+ case OPT_fltrans_output_list_:
+ case OPT_fresolution_:
+ case OPT_fdebug_prefix_map_:
+ case OPT_fmacro_prefix_map_:
+ case OPT_ffile_prefix_map_:
+ case OPT_fcompare_debug:
+ case OPT_fchecking:
+ case OPT_fchecking_:
+ /* Ignore these. */
+ continue;
+ case OPT_flto_:
+ {
+ const char *lto_canonical = "-flto";
+ switches.safe_push (lto_canonical);
+ len += strlen (lto_canonical) + 1;
+ break;
+ }
+ default:
+ if (cl_options[options[i].opt_index].flags
+ & CL_NO_DWARF_RECORD)
+ continue;
+ gcc_checking_assert (options[i].canonical_option[0][0] == '-');
+ switch (options[i].canonical_option[0][1])
+ {
+ case 'M':
+ case 'i':
+ case 'W':
+ continue;
+ case 'f':
+ if (strncmp (options[i].canonical_option[0] + 2,
+ "dump", 4) == 0)
+ continue;
+ break;
+ default:
+ break;
+ }
+ switches.safe_push (options[i].orig_option_with_args_text);
+ len += strlen (options[i].orig_option_with_args_text) + 1;
+ break;
+ }
+
+ options_string = XNEWVEC (char, len + 1);
+ tail = options_string;
+
+ unsigned i;
+ FOR_EACH_VEC_ELT (switches, i, p)
+ {
+ len = strlen (p);
+ memcpy (tail, p, len);
+ tail += len;
+ if (i != switches.length () - 1)
+ {
+ *tail = ' ';
+ ++tail;
+ }
+ }
+
+ *tail = '\0';
+ return options_string;
+}
+
+/* Return a heap allocated producer string including command line options. */
+
+char *
+gen_producer_string (const char *language_string, cl_decoded_option *options,
+ unsigned int options_count)
+{
+ return concat (language_string, " ", version_string, " ",
+ gen_command_line_string (options, options_count), NULL);
+}
+
#if CHECKING_P
namespace selftest {
diff --git a/gcc/opts.h b/gcc/opts.h
index d62bfcf..b36c0d1 100644
--- a/gcc/opts.h
+++ b/gcc/opts.h
@@ -482,6 +482,12 @@ extern void parse_options_from_collect_gcc_options (const char *, obstack *,
extern void prepend_xassembler_to_collect_as_options (const char *, obstack *);
+extern char *gen_command_line_string (cl_decoded_option *options,
+ unsigned int options_count);
+extern char *gen_producer_string (const char *language_string,
+ cl_decoded_option *options,
+ unsigned int options_count);
+
/* Set OPTION in OPTS to VALUE if the option is not set in OPTS_SET. */
#define SET_OPTION_IF_UNSET(OPTS, OPTS_SET, OPTION, VALUE) \
diff --git a/gcc/target.def b/gcc/target.def
index a0ea853..acdc694 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -757,41 +757,7 @@ directive to annotate @var{symbol} as used. The Darwin target uses the\n\
DEFHOOK
(record_gcc_switches,
"Provides the target with the ability to record the gcc command line\n\
-switches that have been passed to the compiler, and options that are\n\
-enabled. The @var{type} argument specifies what is being recorded.\n\
-It can take the following values:\n\
-\n\
-@table @gcctabopt\n\
-@item SWITCH_TYPE_PASSED\n\
-@var{text} is a command line switch that has been set by the user.\n\
-\n\
-@item SWITCH_TYPE_ENABLED\n\
-@var{text} is an option which has been enabled. This might be as a\n\
-direct result of a command line switch, or because it is enabled by\n\
-default or because it has been enabled as a side effect of a different\n\
-command line switch. For example, the @option{-O2} switch enables\n\
-various different individual optimization passes.\n\
-\n\
-@item SWITCH_TYPE_DESCRIPTIVE\n\
-@var{text} is either NULL or some descriptive text which should be\n\
-ignored. If @var{text} is NULL then it is being used to warn the\n\
-target hook that either recording is starting or ending. The first\n\
-time @var{type} is SWITCH_TYPE_DESCRIPTIVE and @var{text} is NULL, the\n\
-warning is for start up and the second time the warning is for\n\
-wind down. This feature is to allow the target hook to make any\n\
-necessary preparations before it starts to record switches and to\n\
-perform any necessary tidying up after it has finished recording\n\
-switches.\n\
-\n\
-@item SWITCH_TYPE_LINE_START\n\
-This option can be ignored by this target hook.\n\
-\n\
-@item SWITCH_TYPE_LINE_END\n\
-This option can be ignored by this target hook.\n\
-@end table\n\
-\n\
-The hook's return value must be zero. Other return values may be\n\
-supported in the future.\n\
+switches provided as argument.\n\
\n\
By default this hook is set to NULL, but an example implementation is\n\
provided for ELF based targets. Called @var{elf_record_gcc_switches},\n\
@@ -799,7 +765,7 @@ it records the switches as ASCII text inside a new, string mergeable\n\
section in the assembler output file. The name of the new section is\n\
provided by the @code{TARGET_ASM_RECORD_GCC_SWITCHES_SECTION} target\n\
hook.",
- int, (print_switch_type type, const char *text),
+ void, (const char *),
NULL)
/* The name of the section that the example ELF implementation of
diff --git a/gcc/target.h b/gcc/target.h
index 440cd25..9601880 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -68,16 +68,6 @@ union cumulative_args_t { void *p; };
#endif /* !CHECKING_P */
-/* Types used by the record_gcc_switches() target function. */
-enum print_switch_type
-{
- SWITCH_TYPE_PASSED, /* A switch passed on the command line. */
- SWITCH_TYPE_ENABLED, /* An option that is currently enabled. */
- SWITCH_TYPE_DESCRIPTIVE, /* Descriptive text, not a switch or option. */
- SWITCH_TYPE_LINE_START, /* Please emit any necessary text at the start of a line. */
- SWITCH_TYPE_LINE_END /* Please emit a line terminator. */
-};
-
/* Types of memory operation understood by the "by_pieces" infrastructure.
Used by the TARGET_USE_BY_PIECES_INFRASTRUCTURE_P target hook and
internally by the functions in expr.c. */
@@ -96,10 +86,8 @@ extern unsigned HOST_WIDE_INT by_pieces_ninsns (unsigned HOST_WIDE_INT,
unsigned int,
by_pieces_operation);
-typedef int (* print_switch_fn_type) (print_switch_type, const char *);
-
/* An example implementation for ELF targets. Defined in varasm.c */
-extern int elf_record_gcc_switches (print_switch_type type, const char *);
+extern void elf_record_gcc_switches (const char *);
/* Some places still assume that all pointer or address modes are the
standard Pmode and ptr_mode. These optimizations become invalid if
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3339d70..0e91a06 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,148 @@
+2020-12-03 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp2a/concepts-nodiscard1.C: XFAIL.
+
+2020-12-03 Martin Sebor <msebor@redhat.com>
+
+ PR c++/90629
+ PR middle-end/94527
+ * g++.dg/asan/asan_test.cc: Fix a bug.
+ * g++.dg/warn/delete-array-1.C: Add expected warning.
+ * g++.old-deja/g++.other/delete2.C: Add expected warning.
+ * g++.dg/warn/Wfree-nonheap-object-2.C: New test.
+ * g++.dg/warn/Wfree-nonheap-object.C: New test.
+ * g++.dg/warn/Wmismatched-new-delete.C: New test.
+ * g++.dg/warn/Wmismatched-dealloc-2.C: New test.
+ * g++.dg/warn/Wmismatched-dealloc.C: New test.
+ * gcc.dg/Wmismatched-dealloc.c: New test.
+ * gcc.dg/analyzer/malloc-1.c: Prune out expected warning.
+ * gcc.dg/attr-malloc.c: New test.
+ * gcc.dg/free-1.c: Adjust text of expected warning.
+ * gcc.dg/free-2.c: Same.
+ * gcc.dg/torture/pr71816.c: Prune out expected warning.
+ * gcc.dg/tree-ssa/pr19831-2.c: Add an expected warning.
+ * gcc.dg/Wfree-nonheap-object-2.c: New test.
+ * gcc.dg/Wfree-nonheap-object-3.c: New test.
+ * gcc.dg/Wfree-nonheap-object.c: New test.
+ * g++.dg/warn/Wfree-nonheap-object.s: New file.
+
+2020-12-03 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/95342
+ * gfortran.dg/pr95342.f90: New test.
+
+2020-12-03 Ian Lance Taylor <iant@golang.org>
+
+ * go.test/go-test.exp (go-gc-tests): Add -I. when building all
+ sources in a directory (errorcheckdir, compiledir, rundir,
+ rundircmpout).
+
+2020-12-03 Jason Merrill <jason@redhat.com>
+
+ PR c++/98019
+ * g++.dg/cpp2a/concepts-nodiscard1.C: New test.
+
+2020-12-03 Uroš Bizjak <ubizjak@gmail.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR target/98086
+ * gcc.target/i386/pr98086.c: New test.
+
+2020-12-03 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/98115
+ PR c++/98116
+ * g++.dg/template/pr98115.C: New.
+ * g++.dg/template/pr98116.C: New.
+
+2020-12-03 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * gcc.target/s390/stack-clash-4.c: New test.
+
+2020-12-03 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/acle/general/undef_1.c: New test.
+
+2020-12-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/pr98099.c: New test.
+
+2020-12-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * g++.dg/cpp2a/pr98082.C: New test.
+
+2020-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR libstdc++/93121
+ * g++.dg/cpp2a/bit-cast1.C: New test.
+ * g++.dg/cpp2a/bit-cast2.C: New test.
+ * g++.dg/cpp2a/bit-cast3.C: New test.
+ * g++.dg/cpp2a/bit-cast4.C: New test.
+ * g++.dg/cpp2a/bit-cast5.C: New test.
+
+2020-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/cpp2a/consteval-defarg2.C: New test.
+
+2020-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98104
+ * g++.dg/warn/pr98104.C: New test.
+
+2020-12-03 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512bw-pr96906-1.c: New test.
+ * gcc.target/i386/pr96906-1.c: Add -mno-avx512f.
+
+2020-12-03 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512bw-vmovdqu16-1.c: Adjust testcase to
+ make sure only masked load instruction is generated.
+ * gcc.target/i386/avx512bw-vmovdqu8-1.c: Ditto.
+ * gcc.target/i386/avx512f-vmovapd-1.c: Ditto.
+ * gcc.target/i386/avx512f-vmovaps-1.c: Ditto.
+ * gcc.target/i386/avx512f-vmovdqa32-1.c: Ditto.
+ * gcc.target/i386/avx512f-vmovdqa64-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vmovapd-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vmovaps-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vmovdqa32-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vmovdqa64-1.c: Ditto.
+ * gcc.target/i386/pr97642-1.c: New test.
+ * gcc.target/i386/pr97642-2.c: New test.
+
+2020-12-03 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/parse/defarg17.C: New test.
+
+2020-12-03 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp2a/consteval-defarg1.C: New test.
+
+2020-12-03 Hongyu Wang <hongyu.wang@intel.com>
+
+ PR target/97770
+ * gcc.target/i386/avx512bitalg-pr97770-1.c: New test.
+ * gcc.target/i386/avx512vpopcntdq-pr97770-1.c: Likewise.
+ * gcc.target/i386/avx512vpopcntdq-pr97770-2.c: Likewise.
+ * gcc.target/i386/avx512vpopcntdqvl-pr97770-1.c: Likewise.
+
+2020-12-03 Alexandre Oliva <oliva@adacore.com>
+
+ * lib/options.exp (check_for_options_with_filter): Detect
+ unavailable compiler for the selected language, and bail out
+ as unsupported.
+
+2020-12-03 Martin Sebor <msebor@redhat.com>
+
+ * gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Adjust expected warnings
+ to correctly reflect the maximum object size.
+ * gcc.dg/tree-ssa/builtin-sprintf-warn-11.c: Same.
+ * gcc.dg/tree-ssa/builtin-sprintf-warn-18.c: Same.
+
+2020-12-03 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * gcc.target/s390/builtin-constant-p-threading.c: New test.
+
2020-12-03 Peter Bergner <bergner@linux.ibm.com>
PR c++/97947
diff --git a/gcc/testsuite/g++.dg/asan/asan_test.cc b/gcc/testsuite/g++.dg/asan/asan_test.cc
index 5f2e2c2..dbf1a6a 100644
--- a/gcc/testsuite/g++.dg/asan/asan_test.cc
+++ b/gcc/testsuite/g++.dg/asan/asan_test.cc
@@ -829,7 +829,7 @@ NOINLINE static int LargeFunction(bool do_bad_access) {
x[18]++;
x[19]++;
- delete x;
+ delete[] x;
return res;
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast6.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast6.C
new file mode 100644
index 0000000..4b70da1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast6.C
@@ -0,0 +1,31 @@
+// PR libstd++/93121
+// { dg-do compile { target c++20 } }
+
+namespace std
+{
+enum class byte : unsigned char {};
+template <typename To, typename From>
+constexpr To
+bit_cast (const From &from)
+{
+ return __builtin_bit_cast (To, from);
+}
+}
+
+struct S { unsigned short s[2]; };
+constexpr std::byte from1[sizeof (S)]{};
+constexpr auto to1 = std::bit_cast<S>(from1);
+constexpr unsigned char from2[sizeof (S)]{};
+constexpr auto to2 = std::bit_cast<S>(from2);
+
+constexpr bool
+cmp (const S &s1, const S &s2)
+{
+ for (int i = 0; i < sizeof (s1.s) / sizeof (s1.s[0]); i++)
+ if (s1.s[i] != s2.s[i])
+ return false;
+ return true;
+}
+
+static_assert (cmp (to1, S{}));
+static_assert (cmp (to2, S{}));
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-nodiscard1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-nodiscard1.C
index 28ce29b..907e68b 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-nodiscard1.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-nodiscard1.C
@@ -1,5 +1,6 @@
// PR c++/98019
// { dg-do compile { target c++20 } }
+// { dg-excess-errors *-*-* }
template <class T, class U> concept same_as = __is_same_as (T, U);
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class40.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class40.C
new file mode 100644
index 0000000..d193544
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class40.C
@@ -0,0 +1,79 @@
+// PR c++/93083
+// { dg-do compile { target c++20 } }
+
+template<unsigned N>
+struct FixedString
+{
+ char buf[N + 1]{};
+ constexpr FixedString(char const* s) {
+ for (unsigned i = 0; i != N; ++i) buf[i] = s[i];
+ }
+
+ auto operator<=>(const FixedString&) const = default;
+ constexpr operator char const*() const { return buf; }
+ constexpr static unsigned size() noexcept { return N; }
+};
+
+template<unsigned N> FixedString(char const (&)[N]) -> FixedString<N - 1>;
+
+template <FixedString... names>
+struct name_list
+{
+ template <FixedString name>
+ using add_name = name_list<
+ names...,
+ FixedString<name.size()>{ name }
+ >;
+};
+
+
+int main()
+{
+ using names =
+ name_list<>
+ ::add_name<"Zaphod Beeblebrox">;
+
+}
+
+// ----------------
+
+template <int N> struct literal {
+ constexpr literal(const char (&input)[N]) noexcept { }
+ constexpr literal(const literal &) noexcept { }
+};
+
+template <literal Name, int id> struct field { };
+
+template <literal Name> struct field<Name, 1u> { };
+
+// ----------------
+
+template <int N>
+struct use_as_nttp {};
+
+template <use_as_nttp Value>
+struct has_nttp {};
+
+template <use_as_nttp Value>
+using has_nttp_2 = has_nttp<Value>;
+
+// ----------------
+
+using size_t = decltype(sizeof(0));
+
+template <size_t N>
+struct string_literal
+{
+ constexpr string_literal(const char*) {}
+ string_literal(string_literal const&) = default;
+};
+template <size_t N>
+string_literal(const char (&)[N]) -> string_literal<N - 1>;
+
+template <string_literal Str>
+struct type_string { };
+
+template <string_literal Str>
+void foo() {
+ type_string<Str>{};
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/srcloc1.C b/gcc/testsuite/g++.dg/cpp2a/srcloc1.C
index 6e19ff7..029a037 100644
--- a/gcc/testsuite/g++.dg/cpp2a/srcloc1.C
+++ b/gcc/testsuite/g++.dg/cpp2a/srcloc1.C
@@ -88,7 +88,7 @@ quux ()
const char *file1 = source_location::current ().file_name ();
const char *file2 = __FILE__;
const char *function1 = source_location::current ().function_name ();
- const char *function2 = __FUNCTION__;
+ const char *function2 = __PRETTY_FUNCTION__;
int line1 = source_location::current ().line ();
int line2 = __LINE__ - 1;
int column
diff --git a/gcc/testsuite/g++.dg/cpp2a/srcloc15.C b/gcc/testsuite/g++.dg/cpp2a/srcloc15.C
index 30e5845..d02617e 100644
--- a/gcc/testsuite/g++.dg/cpp2a/srcloc15.C
+++ b/gcc/testsuite/g++.dg/cpp2a/srcloc15.C
@@ -44,12 +44,12 @@ struct S {
source_location loc = source_location::current ();
constexpr S (int l, source_location loc = source_location::current ())
- : func(__FUNCTION__), line(l), loc(loc)
+ : func(__PRETTY_FUNCTION__), line(l), loc(loc)
{}
constexpr S (double)
- : func(__FUNCTION__), line(__LINE__)
- // ^ column 38
+ : func(__PRETTY_FUNCTION__), line(__LINE__)
+ // ^ column 45
{}
};
@@ -73,7 +73,7 @@ bar ()
// ^ column 49
const source_location *d[3] = { &a, &b, &c };
const char *file1 = __FILE__;
- const char *function1 = __FUNCTION__;
+ const char *function1 = __PRETTY_FUNCTION__;
for (int j = 0; j < 3; j++)
{
int i= 0;
@@ -104,7 +104,7 @@ bar ()
return false;
if (e.loc.column () != 9)
return false;
- if (f.loc.column () != 38)
+ if (f.loc.column () != 45)
return false;
return true;
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/srcloc17.C b/gcc/testsuite/g++.dg/cpp2a/srcloc17.C
index 16704d0..a02ea48 100644
--- a/gcc/testsuite/g++.dg/cpp2a/srcloc17.C
+++ b/gcc/testsuite/g++.dg/cpp2a/srcloc17.C
@@ -46,12 +46,12 @@ struct S {
source_location loc = source_location::current ();
constexpr S (int l, source_location loc = source_location::current ())
- : func(__FUNCTION__), line(l), loc(loc)
+ : func(__PRETTY_FUNCTION__), line(l), loc(loc)
{}
constexpr S (double)
- : func(__FUNCTION__), line(__LINE__)
- // ^ column 38
+ : func(__PRETTY_FUNCTION__), line(__LINE__)
+ // ^ column 45
{}
};
@@ -76,7 +76,7 @@ bar ()
// ^ column 48
const source_location *d[3] = { &a, &b, &c };
const char *file1 = __FILE__;
- const char *function1 = b.function_name ();
+ const char *function1 = __PRETTY_FUNCTION__;
for (int j = 0; j < 3; j++)
{
int i= 0;
@@ -107,7 +107,7 @@ bar ()
return false;
if (e.loc.column () != 8)
return false;
- if (f.loc.column () != 38)
+ if (f.loc.column () != 45)
return false;
return true;
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/srcloc2.C b/gcc/testsuite/g++.dg/cpp2a/srcloc2.C
index 5ef09bb..4e0b960 100644
--- a/gcc/testsuite/g++.dg/cpp2a/srcloc2.C
+++ b/gcc/testsuite/g++.dg/cpp2a/srcloc2.C
@@ -92,7 +92,7 @@ quux ()
const char *file1 = source_location::current ().file_name ();
const char *file2 = __FILE__;
const char *function1 = source_location::current ().function_name ();
- const char *function2 = __FUNCTION__;
+ const char *function2 = __PRETTY_FUNCTION__;
int line1 = source_location::current ().line ();
int line2 = __LINE__ - 1;
int column
diff --git a/gcc/testsuite/g++.dg/opt/pr98130.C b/gcc/testsuite/g++.dg/opt/pr98130.C
new file mode 100644
index 0000000..0af55ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr98130.C
@@ -0,0 +1,25 @@
+// PR c++/98130
+// { dg-do run { target c++11 } }
+// { dg-options "-O2" }
+
+#include <new>
+
+typedef int *T;
+
+static unsigned char storage[sizeof (T)] alignas (T);
+static T *p = (T *) storage;
+
+static inline __attribute__((__always_inline__)) void
+foo (T value)
+{
+ new (p) T(value);
+}
+
+int
+main ()
+{
+ int a;
+ foo (&a);
+ if (!*p)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/template/pr98116.C b/gcc/testsuite/g++.dg/template/pr98116.C
index d3398d2..874c590 100644
--- a/gcc/testsuite/g++.dg/template/pr98116.C
+++ b/gcc/testsuite/g++.dg/template/pr98116.C
@@ -1,5 +1,11 @@
// PR 98116, ICE with stripping typedef array type
// { dg-do compile { target c++11 } }
+// { dg-additional-options {--param=hash-table-verification-limit=10000000 -fchecking=2} }
+// { dg-ice "spec_hasher::equal" }
+
+// We get confused by alias templates that alias the same type.
+// { dg-prune-output "hash table checking failed" }
+
namespace std {
struct is_convertible;
template <typename _Tp> using remove_pointer_t = typename _Tp ::type;
diff --git a/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-2.C b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-2.C
new file mode 100644
index 0000000..9d4d2a3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-2.C
@@ -0,0 +1,274 @@
+/* PR ????? - No warning on attempts to access free object
+ Verify that freeing unallocated objects referenced either directly
+ or through pointers is diagnosed.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wfree-nonheap-object" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __SIZE_TYPE__ size_t;
+
+extern "C"
+{
+ void free (void*);
+ extern void* malloc (size_t);
+ extern void* realloc (void *p, size_t);
+}
+
+void sink (void*, ...);
+#define sink(...) sink (0, __VA_ARGS__)
+
+extern char ecarr[];
+extern void* eparr[];
+
+extern char *eptr;
+
+void* source (void);
+
+void nowarn_free (void *p, void **pp, size_t n, intptr_t iptr)
+{
+ free (p);
+
+ p = 0;
+ free (p);
+
+ p = malloc (n);
+ sink (p);
+ free (p);
+
+ p = malloc (n);
+ sink (p);
+
+ p = realloc (p, n * 2);
+ sink (p);
+ free (p);
+
+ free ((void*)iptr);
+
+ p = source ();
+ free (p);
+
+ p = source ();
+ p = (char*)p - 1;
+ free (p);
+
+ free (*pp);
+}
+
+void warn_free_extern_arr (void)
+{
+ free (ecarr); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_extern_arr_offset (int i)
+{
+ char *p = ecarr + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_cstint (void)
+{
+ void *p = (void*)1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_func (void)
+{
+ void *p = (void*)warn_free_func;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_string (int i)
+{
+ {
+ char *p = (char*)"123";
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char *p = (char*)"234" + 1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char *p = (char*)"345" + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+
+ if (i >= 0)
+ {
+ char *p = (char*)"456" + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+void warn_free_local_arr (int i)
+{
+ {
+ char a[4];
+ sink (a);
+ free (a); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char b[5];
+ sink (b);
+
+ char *p = b + 1;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char c[6];
+ sink (c);
+
+ char *p = c + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+
+void warn_free_vla (int n, int i)
+{
+ {
+ int vla[n], *p = vla;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+
+ {
+ int vla[n + 1], *p = vla + 1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ int vla[n + 2], *p = vla + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+
+void nowarn_free_extern_ptrarr (void)
+{
+ free (*eparr);
+}
+
+void nowarn_free_extern_ptrarr_offset (int i)
+{
+ void *p = eparr[i];
+ free (p);
+}
+
+
+void warn_free_extern_ptrarr (void)
+{
+ free (eparr); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_extern_ptrarr_offset (int i)
+{
+ void *p = &eparr[i];
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void nowarn_free_local_ptrarr (int i)
+{
+ void* a[4];
+ sink (a);
+ free (a[0]);
+ free (a[1]);
+ free (a[i]);
+}
+
+
+void nowarn_free_extern_ptr (void)
+{
+ free (eptr);
+}
+
+void nowarn_free_extern_ptr_offset (int i)
+{
+ char *p = eptr + i;
+ free (p);
+}
+
+void warn_free_extern_ptr_pos_offset (int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *q = eptr + i;
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void nowarn_free_parm_offset (char *p, int i)
+{
+ char *q = p + i;
+ free (q);
+}
+
+void nowarn_free_parm_neg_offset (char *p, int i)
+{
+ if (i >= 0)
+ i = -1;
+
+ char *q = p + i;
+ free (q);
+}
+
+void warn_free_parm_pos_offset (char *p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *q = p + i;
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+struct Members
+{
+ char a[4], *p, *q;
+};
+
+extern struct Members em;
+
+void nowarn_free_member_ptr (struct Members *pm, int i)
+{
+ char *p = em.p;
+ free (p);
+ p = em.q + i;
+ free (p);
+
+ free (pm->q);
+ p = pm->p;
+ free (pm);
+ free (p);
+}
+
+void nowarn_free_struct_cast (intptr_t *p)
+{
+ struct Members *q = (struct Members*)*p;
+ if (q->p == 0)
+ free (q); // { dg-bogus "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_member_array (void)
+{
+ char *p = em.a;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_member_array_off (int i)
+{
+ char *p = em.a + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.C b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.C
new file mode 100644
index 0000000..82b081a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.C
@@ -0,0 +1,124 @@
+/* PR ????? - No warning on attempts to access free object
+ Verify that attempts to deallocate objects by pointers with nonzero
+ offsets is diagnosed.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wfree-nonheap-object" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __SIZE_TYPE__ size_t;
+
+void sink (void*, ...);
+
+extern char ecarr[];
+extern void* eparr[];
+
+extern char *eptr;
+
+char* source (void);
+
+void nowarn_op_delete (void *p, void ***ppp, size_t n, intptr_t iptr)
+{
+ operator delete (p);
+
+ p = 0;
+ operator delete (p);
+
+ p = operator new (n);
+ sink (p);
+ operator delete (p);
+
+ p = operator new (n);
+ sink (p);
+
+ operator delete ((void*)iptr);
+
+ p = source ();
+ operator delete (p);
+
+ p = source ();
+ p = (char*)p - 1;
+ operator delete (p);
+
+ operator delete (**ppp);
+ operator delete (*ppp);
+ operator delete (ppp);
+}
+
+void warn_op_delete_cstaddr (void *p)
+{
+ operator delete (p);
+ p = (void*)~0;
+ operator delete (p); // { dg-warning "called on a pointer to an unallocated object" } */
+}
+
+void warn_op_delete_funcaddr ()
+{
+ void *p = (void*)&warn_op_delete_funcaddr;
+ operator delete (p); // { dg-warning "called on unallocated object 'void warn_op_delete_funcaddr()" } */
+}
+
+void warn_op_delete_string (void *p)
+{
+ operator delete (p);
+ p = (void*)"";
+ operator delete (p); // { dg-warning "called on a pointer to an unallocated object" } */
+}
+
+void warn_op_delete_ptr_to_self (void *p)
+{
+ operator delete (p);
+ p = &p;
+ operator delete (p); // { dg-warning "called on unallocated object 'p'" } */
+}
+
+void nowarn_op_new_delete (size_t n)
+{
+ void *p = operator new (n);
+ sink (p);
+ operator delete (p);
+}
+
+void nowarn_op_new_delete_ptr_plus (size_t n)
+{
+ void *p0_1 = operator new (n);
+ void *p1 = (char*)p0_1 + 1;
+ sink (p0_1, p1);
+ void *p0_2 = (char*)p1 - 1;
+ sink (p0_1, p1, p0_2);
+ operator delete (p0_2);
+}
+
+void warn_op_new_delete_cstoff (size_t n)
+{
+ void *p = operator new (n);
+ void *q = (char*)p + 1;
+ sink (p, q);
+ operator delete (q); // { dg-warning "'void operator delete\\\(void\\\*\\\)' called on pointer '\[^'\]+' with nonzero offset 1" }
+}
+
+void warn_op_new_delete_ptr_plus (size_t n)
+{
+ char *p = (char*)operator new (n);
+ sink (++p);
+ operator delete (p); // { dg-warning "called on pointer '\[^']+' with nonzero offset 1" }
+}
+
+void warn_op_delete_funcret_plus (size_t n)
+{
+ char *p = source ();
+ sink (++p);
+ operator delete (p); // { dg-warning "called on pointer '\[^']+' with nonzero offset 1" }
+}
+
+void warn_op_delete_eptr_plus (int i)
+{
+ extern char *ecp;
+
+ if (i < 1)
+ i = 1;
+
+ char *p = ecp + i;
+ sink (p);
+
+ operator delete (p); // { dg-warning "called on pointer '\[^']+' with nonzero offset \\\[1, \\d+]" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.s b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.s
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.s
diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-dealloc-2.C b/gcc/testsuite/g++.dg/warn/Wmismatched-dealloc-2.C
new file mode 100644
index 0000000..7ecc99a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmismatched-dealloc-2.C
@@ -0,0 +1,185 @@
+/* PR middle-end/94527 - Add an attribute that marks a function as freeing
+ an object
+ The detection doesn't require optimization.
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+#define A(...) __attribute__ ((malloc (__VA_ARGS__)))
+
+typedef __SIZE_TYPE__ size_t;
+
+extern "C" {
+ void free (void *);
+ void* realloc (void *, size_t);
+}
+
+void sink (void *);
+
+void mydealloc (int, void*);
+void* A (mydealloc, 2) myalloc (void*);
+
+
+void my_delete (const char*, void*);
+void my_array_delete (const char*, void*);
+
+typedef void OpDelete1 (void*);
+typedef void OpDelete2 (void*, size_t);
+
+A ((OpDelete1*)operator delete, 1)
+#if __cplusplus >= 201402L
+A ((OpDelete2*)operator delete, 1)
+#endif
+A (my_delete, 2)
+int* my_new (size_t);
+
+A ((OpDelete1*)operator delete[], 1)
+#if __cplusplus >= 201402L
+A ((OpDelete2*)operator delete[], 1)
+#endif
+A (my_array_delete, 2)
+int* my_array_new (size_t);
+
+
+void test_my_new ()
+{
+ {
+ void *p = my_new (1);
+ operator delete (p);
+ }
+ {
+ void *p = my_new (1);
+ sink (p);
+ operator delete (p);
+ }
+ {
+ int *p = my_new (1);
+ sink (p);
+ delete p;
+ }
+
+ {
+ void *p = my_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ operator delete[] (p);
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function \\\[-Wmismatched-new-delete" "" { target *-*-* } .-1 }
+ }
+ {
+ void *p = my_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ operator delete[] (p);
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function \\\[-Wmismatched-new-delete" "" { target *-*-* } .-1 }
+ }
+ {
+ int *p = my_new (1);
+ sink (p);
+ delete[] p;
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function \\\[-Wmismatched-new-delete" "" { target *-*-* } .-1 }
+ }
+
+ {
+ void *p = my_new (1);
+ my_delete ("1", p);
+ }
+ {
+ void *p = my_new (1);
+ sink (p);
+ my_delete ("2", p);
+ }
+
+ {
+ void *p = my_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ my_array_delete ("3", p);
+ // { dg-warning "'void my_array_delete\\\(const char\\\*, void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ void *p = my_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ free (p);
+ // { dg-warning "'void free\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ void *p = my_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ p = realloc (p, 123);
+ // { dg-warning "'void\\\* realloc\\\(void\\\*, size_t\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
+
+
+void test_my_array_new ()
+{
+ {
+ void *p = my_array_new (1);
+ operator delete[] (p);
+ }
+ {
+ void *p = my_array_new (1);
+ sink (p);
+ operator delete[] (p);
+ }
+ {
+ int *p = my_array_new (1);
+ sink (p);
+ delete[] p;
+ }
+
+ {
+ void *p = my_array_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_array_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ operator delete (p);
+ // { dg-warning "'void operator delete\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function \\\[-Wmismatched-new-delete" "" { target *-*-* } .-1 }
+ }
+ {
+ void *p = my_array_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_array_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ operator delete (p);
+ // { dg-warning "'void operator delete\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function \\\[-Wmismatched-new-delete" "" { target *-*-* } .-1 }
+ }
+ {
+ int *p = my_array_new (1);
+ sink (p);
+ delete p;
+ // { dg-warning "'void operator delete\\\(void\\\*\[^\)\]*\\\)' called on pointer returned from a mismatched allocation function \\\[-Wmismatched-new-delete" "" { target *-*-* } .-1 }
+ }
+
+ {
+ void *p = my_array_new (1);
+ my_array_delete ("1", p);
+ }
+ {
+ void *p = my_array_new (1);
+ sink (p);
+ my_array_delete ("2", p);
+ }
+ {
+ void *p = my_array_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_array_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ my_delete ("3", p);
+ // { dg-warning "'void my_delete\\\(const char\\\*, void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ void *p = my_array_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_array_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ free (p);
+ // { dg-warning "'void free\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ void *p = my_array_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_array_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ p = realloc (p, 123);
+ // { dg-warning "'void\\\* realloc\\\(void\\\*, size_t\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-dealloc.C b/gcc/testsuite/g++.dg/warn/Wmismatched-dealloc.C
new file mode 100644
index 0000000..682db6f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmismatched-dealloc.C
@@ -0,0 +1,27 @@
+/* PR middle-end/94527 - Add an attribute that marks a function as freeing
+ an object
+ { dg-do compile { target c++11 } }
+ { dg-options "-Wall" } */
+
+#define A(...) __attribute__ ((malloc (__VA_ARGS__)))
+
+typedef __SIZE_TYPE__ size_t;
+
+void mydealloc (int, void*);
+void* A (mydealloc, 2) myalloc (void*);
+
+
+void* A (operator delete, 1)
+ bad_new (size_t); // { dg-error "attribute argument 1 is ambiguous" }
+void* A (operator delete[], 1)
+ bad_array_new (size_t); // { dg-error "attribute argument 1 is ambiguous" }
+
+void my_delete (const char*, void*);
+void my_array_delete (const char*, void*);
+
+typedef void OpDelete (void*);
+
+int* A ((OpDelete*)operator delete, 1) A (my_delete, 2)
+ my_new (size_t);
+int* A ((OpDelete*)operator delete[], 1) A (my_array_delete, 2)
+ my_array_new (size_t);
diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete.C b/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete.C
new file mode 100644
index 0000000..ed1090b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete.C
@@ -0,0 +1,212 @@
+/* PR c++/90629 - Support for -Wmismatched-new-delete
+ The detection doesn't require optimization.
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern "C" {
+ void free (void *);
+ void* malloc (size_t);
+ void* realloc (void *, size_t);
+ char* strdup (const char *);
+ char* strndup (const char *, size_t);
+}
+
+void sink (void *);
+
+void nowarn_op_new_delete (int n)
+{
+ void *p = operator new (n);
+ sink (p);
+ operator delete (p);
+}
+
+void nowarn_new_delete (int n)
+{
+ {
+ char *p = new char;
+ sink (p);
+ delete p;
+ }
+
+ {
+ char *p = new char[n];
+ sink (p);
+ delete[] p;
+ }
+}
+
+/* Verify a warning for calls to free() with a pointer returned from
+ a call to operator new() or the new expressopm. */
+
+void warn_new_free (int n)
+{
+ {
+ void *p = operator new (n);
+ // { dg-message "returned from a call to 'void\\\* operator new\\\(" "note" { target *-*-* } .-1 }
+ sink (p);
+ free (p);
+ // { dg-warning "'void free\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+ {
+ char *p = new char[n];
+ // { dg-message "returned from a call to 'void\\\* operator new \\\[" "note" { target *-*-* } .-1 }
+ sink (p);
+ free (p);
+ // { dg-warning "'void free\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
+
+
+/* Verify a warning for calls to realloc() with a pointer returned from
+ a call to operator new() or the new expressopm. */
+
+void warn_new_realloc (int n)
+{
+ {
+ void *p = operator new (n);
+ // { dg-message "returned from a call to 'void\\\* operator new\\\(" "note" { target *-*-* } .-1 }
+ sink (p);
+ p = realloc (p, n * 2);
+ // { dg-warning "'void\\\* realloc\\\(\[^)\]+\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ sink (p);
+ }
+ {
+ void *p = new char[n];
+ // { dg-message "returned from a call to 'void\\\* operator new \\\[" "note" { target *-*-* } .-1 }
+ sink (p);
+ p = realloc (p, n * 2);
+ // { dg-warning "'void\\\* realloc\\\(\[^)\]+\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ sink (p);
+ }
+}
+
+
+/* Verify a warning for a call to operator_delete() with a pointer returned
+ from a call to malloc(). */
+
+void warn_malloc_op_delete (int n)
+{
+ char *p = (char *)malloc (n);
+ // { dg-message "returned from a call to 'void\\\* malloc\\\(" "note" { target *-*-* } .-1 }
+ sink (p);
+ operator delete (p);
+ // { dg-warning "'void operator delete\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+}
+
+
+/* Verify a warning for an invocation of either form of the delete
+ expression with a pointer returned from a call to malloc(). */
+
+void warn_malloc_delete (int n)
+{
+ {
+ char *p = (char *)malloc (n);
+ // { dg-message "returned from a call to 'void\\\* malloc\\\(" "note" { target *-*-* } .-1 }
+ sink (p);
+ /* C++98 calls operator delete (void*) but later versions call
+ operator delete (void*, size_t). The difference doesn't matter
+ here so verify just that some operator delete is called. */
+ delete p;
+ // { dg-warning "'void operator delete\\\(\[^)\]+\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ char *p = (char *)malloc (n);
+ // { dg-message "returned from a call to 'void\\\* malloc\\\(" "note" { target *-*-* } .-1 }
+ sink (p);
+ delete[] p;
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
+
+
+/* Verify a warning for an invocation of either form of the delete
+ expression with a pointer returned from a call to realloc(). */
+
+void warn_realloc_delete (void *p1, void *p2, int n)
+{
+ {
+ char *q = (char *)realloc (p1, n);
+ // { dg-message "returned from a call to 'void\\\* realloc\\\(" "note" { target *-*-* } .-1 }
+ sink (q);
+ /* C++98 calls operator delete (void*) but later versions call
+ operator delete (void*, size_t). The difference doesn't matter
+ here so verify just that some operator delete is called. */
+ delete q;
+ // { dg-warning "'void operator delete\\\(\[^)\]+\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ char *q = (char *)realloc (p2, n);
+ // { dg-message "returned from a call to 'void\\\* realloc\\\(" "note" { target *-*-* } .-1 }
+ sink (q);
+ delete[] q;
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
+
+
+/* Verify a warning for an invocation of either form of the delete
+ expression with a pointer returned from a call to strdup(). */
+
+void warn_strdup_delete (const char *s1, const char *s2)
+{
+ {
+ char *q = strdup (s1);
+ // { dg-message "returned from a call to 'char\\\* strdup\\\(" "note" { target *-*-* } .-1 }
+ sink (q);
+ /* C++98 calls operator delete (void*) but later versions call
+ operator delete (void*, size_t). The difference doesn't matter
+ here so verify just that some operator delete is called. */
+ delete q;
+ // { dg-warning "'void operator delete\\\(\[^)\]+\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ char *q = strdup (s2);
+ // { dg-message "returned from a call to 'char\\\* strdup\\\(" "note" { target *-*-* } .-1 }
+ sink (q);
+ delete[] q;
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
+
+
+
+/* Verify a warning for an invocation of either form of the delete
+ expression with a pointer returned from a call to strndup(). */
+
+void warn_strdup_delete (const char *s1, const char *s2, size_t n)
+{
+ {
+ char *q = strndup (s1, n);
+ // { dg-message "returned from a call to 'char\\\* strndup\\\(" "note" { target *-*-* } .-1 }
+ sink (q);
+ /* C++98 calls operator delete (void*) but later versions call
+ operator delete (void*, size_t). The difference doesn't matter
+ here so verify just that some operator delete is called. */
+ delete q;
+ // { dg-warning "'void operator delete\\\(\[^)\]+\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ char *q = strndup (s2, n);
+ // { dg-message "returned from a call to 'char\\\* strndup\\\(" "note" { target *-*-* } .-1 }
+ sink (q);
+ delete[] q;
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
+
+
+struct Base { virtual ~Base (); };
+struct Derived: Base { };
+
+void warn_new_free_base_derived ()
+{
+ Base *p = new Derived ();
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wmismatched-new-delete" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/delete-array-1.C b/gcc/testsuite/g++.dg/warn/delete-array-1.C
index c3af713..95fa7d4 100644
--- a/gcc/testsuite/g++.dg/warn/delete-array-1.C
+++ b/gcc/testsuite/g++.dg/warn/delete-array-1.C
@@ -5,7 +5,7 @@ struct S { int a [1]; } s;
void foo (S *p)
{
- delete a; // { dg-warning "deleting array" }
- delete s.a; // { dg-warning "deleting array" }
- delete p->a; // { dg-warning "deleting array" }
+ delete a; // { dg-warning "deleting array|-Wfree-nonheap-object" }
+ delete s.a; // { dg-warning "deleting array|-Wfree-nonheap-object" }
+ delete p->a; // { dg-warning "deleting array|-Wfree-nonheap-object" }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/delete2.C b/gcc/testsuite/g++.old-deja/g++.other/delete2.C
index 1d0554f..76ae355 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/delete2.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/delete2.C
@@ -9,5 +9,7 @@ void bar(foo a) {
delete[] a; // should be accepted
char b[1];
delete b; // { dg-warning "deleting array" } expecting pointer type
+ // { dg-warning "-Wfree-nonheap-object" "" { target *-*-* } .-1 }
delete[] b; // { dg-warning "deleting array" } expecting pointer type
+ // { dg-warning "-Wfree-nonheap-object" "" { target *-*-* } .-1 }
}
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-2.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-2.c
new file mode 100644
index 0000000..2b00d77
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-2.c
@@ -0,0 +1,279 @@
+/* PR ????? - No warning on attempts to access free object
+ Verify that attempting to reallocate unallocated objects referenced
+ either directly or through pointers is diagnosed.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wfree-nonheap-object" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern void free (void*);
+extern void* alloca (size_t);
+extern void* realloc (void*, size_t);
+
+void sink (void*, ...);
+
+extern void* eparr[];
+extern char *eptr;
+
+extern size_t n;
+
+
+void nowarn_realloc (void *p, size_t n)
+{
+ char *q = realloc (p, n);
+ sink (q);
+
+ q = realloc (0, n);
+ sink (q);
+
+ q = realloc (q, n * 2);
+ sink (q);
+}
+
+/* Verify that calling realloc on a pointer to an unknown object minus
+ some nonzero offset isn't diagnosed, but a pointer plus a positive
+ offset is (a positive offset cannot point at the beginning). */
+
+void test_realloc_offset (char *p1, char *p2, char *p3, size_t n, int i)
+{
+ char *q;
+ q = realloc (p1 - 1, n);
+ sink (q);
+
+ q = realloc (p2 + 1, n); // { dg-warning "'realloc' called on pointer 'p2' with nonzero offset 1" }
+ sink (q);
+
+ q = realloc (p3 + i, n);
+ sink (q);
+}
+
+void warn_realloc_extern_arr (void)
+{
+ extern char ecarr[]; // { gg-message "declared here" }
+ char *p = ecarr;
+ char *q = realloc (p, n); // { dg-warning "'realloc' called on unallocated object 'ecarr'" }
+ sink (q);
+}
+
+void warn_realloc_extern_arr_offset (int i)
+{
+ extern char ecarr[];
+ char *p = ecarr + i;
+ char *q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+
+void warn_realloc_string (int i)
+{
+ char *p, *q;
+ {
+ p = "123";
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+ {
+ p = "234" + 1;
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+ {
+ p = "123" + i;
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+}
+
+
+void warn_realloc_alloca (int n, int i)
+{
+ char *p, *q;
+ {
+ p = alloca (n);
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+ {
+ p = (char*)alloca (n + 1);
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+ {
+ p = (char*)alloca (n + 2) + i;
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+}
+
+
+void warn_realloc_local_arr (int i)
+{
+ char *q;
+ {
+ char a[4];
+ sink (a);
+ q = realloc (a, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char b[5];
+ sink (b);
+ q = realloc (b + 1, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char c[6];
+ sink (c);
+ q = realloc (&c[2], n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char d[7];
+ sink (d);
+ q = realloc (&d[i], n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+}
+
+void warn_realloc_vla (int n1, int n2, int i)
+{
+ char *q;
+ {
+ char vla[n1];
+ sink (vla);
+ q = realloc (vla, n2); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char vlb[n1 + 1];
+ sink (vlb);
+ q = realloc (vlb + 1, n2);// { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char vlc[n1 + 2];
+ sink (vlc);
+ q = realloc (&vlc[2], n2);// { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char vld[7];
+ sink (vld);
+ q = realloc (&vld[i], n2);// { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+}
+
+void nowarn_realloc_extern_ptrarr (void)
+{
+ char *q = realloc (*eparr, n);
+ sink (q);
+}
+
+void nowarn_realloc_extern_ptrarr_offset (int i)
+{
+ char *p = eparr[i];
+ char *q = realloc (p, n);
+ sink (q);
+}
+
+
+void warn_realloc_extern_ptrarr (void)
+{
+ char *q = realloc (eparr, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+void warn_realloc_extern_ptrarr_offset (int i)
+{
+ void *p = eparr + i;
+ void *q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+
+void nowarn_realloc_extern_ptr (void)
+{
+ char *q = realloc (eptr, n);
+ sink (q);
+}
+
+void nowarn_realloc_extern_ptr_offset (int i)
+{
+ char *p = eptr + i;
+ char *q = realloc (p, n);
+ sink (q);
+}
+
+
+void warn_realloc_extern_ptr_pos_offset (int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *p = eptr + i;
+ char *q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+
+void nowarn_realloc_parm_offset (char *p, int i)
+{
+ char *q = p + i;
+ q = realloc (q, n);
+ sink (q);
+}
+
+void nowarn_realloc_parm_neg_offset (char *p, int i)
+{
+ if (i >= 0)
+ i = -1;
+
+ char *q = p + i;
+ q = realloc (q, n);
+ sink (q);
+}
+
+void warn_realloc_parm_pos_offset (char *p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *q = p + i;
+ q = realloc (q, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+void nowarn_realloc_deref_parm_pos_offset (void **p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ // The offset is from p, not *p.
+ void *q = *(p + i);
+ q = realloc (q, n);
+ sink (q);
+}
+
+void warn_realloc_deref_parm_pos_offset (void **p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ // Unlike in the function above the offset is from *p.
+ void *q = *p + i;
+ q = realloc (q, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-3.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-3.c
new file mode 100644
index 0000000..a472b93
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-3.c
@@ -0,0 +1,57 @@
+/* PR ????? - No warning on attempts to access free object
+ Verify that freeing unallocated objects referenced indirectly through
+ pointers obtained from function calls is diagnosed.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wfree-nonheap-object" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern void free (void*);
+extern char* memchr (const void*, int, size_t);
+extern char* strchr (const char*, int);
+
+void sink (void*, ...);
+
+extern char ecarr[];
+extern void* eparr[];
+
+extern char *eptr;
+
+
+void warn_free_memchr_ecarr (int x, size_t n)
+{
+ char *p = memchr (ecarr, x, n);
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_memchr_ecarr_offset (int i, int j, int x, size_t n)
+{
+ char *p = memchr (ecarr + i, x, n);
+ char *q = p + j;
+ sink (p, q);
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_memchr_local_arr (int x, size_t n)
+{
+ char a[8];
+ sink (a);
+
+ char *p = memchr (a, x, n);
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_memchr_local_arr_offset (int i, int j, int x, size_t n)
+{
+ char a[8];
+ sink (a);
+
+ char *p = memchr (a + i, x, n);
+ char *q = p + j;
+ sink (p, q);
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object.c
new file mode 100644
index 0000000..bb222cc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object.c
@@ -0,0 +1,273 @@
+/* PR ????? - No warning on attempts to access free object
+ Verify that freeing unallocated objects referenced either directly
+ or through pointers is diagnosed. In most cases this doesn't require
+ optimization.
+ { dg-do compile }
+ { dg-options "-Wall -Wfree-nonheap-object" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __SIZE_TYPE__ size_t;
+
+extern void free (void*);
+extern void* malloc (size_t);
+extern void* realloc (void *p, size_t);
+
+void sink (void*, ...);
+
+extern char ecarr[];
+extern void* eparr[];
+
+extern char *eptr;
+
+void* source (void);
+
+void nowarn_free (void *p, void **pp, size_t n, intptr_t iptr)
+{
+ free (p);
+
+ p = 0;
+ free (p);
+
+ p = malloc (n);
+ sink (p);
+ free (p);
+
+ p = malloc (n);
+ sink (p);
+
+ p = realloc (p, n * 2);
+ sink (p);
+ free (p);
+
+ free ((void*)iptr);
+
+ p = source ();
+ free (p);
+
+ p = source ();
+ p = (char*)p - 1;
+ free (p);
+
+ free (*pp);
+}
+
+void warn_free_extern_arr (void)
+{
+ free (ecarr); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_extern_arr_offset (int i)
+{
+ char *p = ecarr + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_cstint (void)
+{
+ void *p = (void*)1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_func (void)
+{
+ void *p = warn_free_func;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_string (int i)
+{
+ {
+ char *p = "123";
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char *p = "234" + 1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char *p = "345" + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+
+ if (i >= 0)
+ {
+ char *p = "456" + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+void warn_free_local_arr (int i)
+{
+ {
+ char a[4];
+ sink (a);
+ free (a); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char b[5];
+ sink (b);
+
+ char *p = b + 1;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char c[6];
+ sink (c);
+
+ char *p = c + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+
+void warn_free_vla (int n, int i)
+{
+ {
+ int vla[n], *p = vla;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+
+ {
+ int vla[n + 1], *p = vla + 1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ int vla[n + 2], *p = vla + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+
+void nowarn_free_extern_ptrarr (void)
+{
+ free (*eparr);
+}
+
+void nowarn_free_extern_ptrarr_offset (int i)
+{
+ char *p = eparr[i];
+ free (p);
+}
+
+
+void warn_free_extern_ptrarr (void)
+{
+ free (eparr); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_extern_ptrarr_offset (int i)
+{
+ void *p = &eparr[i];
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void nowarn_free_local_ptrarr (int i)
+{
+ void* a[4];
+ sink (a);
+ free (a[0]);
+ free (a[1]);
+ free (a[i]);
+}
+
+
+void nowarn_free_extern_ptr (void)
+{
+ free (eptr);
+}
+
+void nowarn_free_extern_ptr_offset (int i)
+{
+ char *p = eptr + i;
+ free (p);
+}
+
+void nowarn_free_parm_offset (char *p, int i)
+{
+ char *q = p + i;
+ free (q);
+}
+
+void nowarn_free_parm_neg_offset (char *p, int i)
+{
+ if (i >= 0)
+ i = -1;
+
+ char *q = p + i;
+ free (q);
+}
+
+struct Members
+{
+ char a[4], *p, *q;
+};
+
+extern struct Members em;
+
+void nowarn_free_member_ptr (struct Members *pm, int i)
+{
+ char *p = em.p;
+ free (p);
+ p = em.q + i;
+ free (p);
+
+ free (pm->q);
+ p = pm->p;
+ free (pm);
+ free (p);
+}
+
+void nowarn_free_struct_cast (intptr_t *p)
+{
+ struct Members *q = (struct Members*)*p;
+ if (q->p == 0)
+ free (q); // { dg-bogus "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_member_array (void)
+{
+ char *p = em.a;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_member_array_off (int i)
+{
+ char *p = em.a + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+// Range information requires optimization.
+#pragma GCC optimize "1"
+
+void warn_free_extern_ptr_pos_offset (int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *q = eptr + i;
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_parm_pos_offset (char *p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *q = p + i;
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wmismatched-dealloc.c b/gcc/testsuite/gcc.dg/Wmismatched-dealloc.c
new file mode 100644
index 0000000..7c5d6ac
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wmismatched-dealloc.c
@@ -0,0 +1,252 @@
+/* PR middle-end/94527 - Add an attribute that marks a function as freeing
+ an object
+ Verify that attribute malloc with one or two arguments has the expected
+ effect on diagnostics.
+ { dg-options "-Wall -ftrack-macro-expansion=0" } */
+
+#define A(...) __attribute__ ((malloc (__VA_ARGS__)))
+
+typedef struct FILE FILE;
+typedef __SIZE_TYPE__ size_t;
+
+void free (void*);
+void* malloc (size_t);
+void* realloc (void*, size_t);
+
+int fclose (FILE*);
+FILE* freopen (const char*, const char*, FILE*);
+int pclose (FILE*);
+
+A (fclose) A (freopen, 3)
+ FILE* fdopen (int);
+A (fclose) A (freopen, 3)
+ FILE* fopen (const char*, const char*);
+A (fclose) A (freopen, 3)
+ FILE* fmemopen(void *, size_t, const char *);
+A (fclose) A (freopen, 3)
+ FILE* freopen (const char*, const char*, FILE*);
+A (pclose) A (freopen, 3)
+ FILE* popen (const char*, const char*);
+A (fclose) A (freopen, 3)
+ FILE* tmpfile (void);
+
+void sink (FILE*);
+
+
+ void release (void*);
+A (release) FILE* acquire (void);
+
+void nowarn_fdopen (void)
+{
+ {
+ FILE *q = fdopen (0);
+ if (!q)
+ return;
+
+ fclose (q);
+ }
+
+ {
+ FILE *q = fdopen (0);
+ if (!q)
+ return;
+
+ q = freopen ("1", "r", q);
+ fclose (q);
+ }
+
+ {
+ FILE *q = fdopen (0);
+ if (!q)
+ return;
+
+ sink (q);
+ }
+}
+
+
+void warn_fdopen (void)
+{
+ {
+ FILE *q = fdopen (0); // { dg-message "returned from a call to 'fdopen'" "note" }
+ sink (q);
+ release (q); // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
+ }
+ {
+ FILE *q = fdopen (0); // { dg-message "returned from a call to 'fdopen'" "note" }
+ sink (q);
+ free (q); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *q = fdopen (0); // { dg-message "returned from a call to 'fdopen'" "note" }
+ sink (q);
+ q = realloc (q, 7); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
+ sink (q);
+ }
+}
+
+
+void nowarn_fopen (void)
+{
+ {
+ FILE *q = fopen ("1", "r");
+ sink (q);
+ fclose (q);
+ }
+
+ {
+ FILE *q = fopen ("2", "r");
+ sink (q);
+ q = freopen ("3", "r", q);
+ sink (q);
+ fclose (q);
+ }
+
+ {
+ FILE *q = fopen ("4", "r");
+ sink (q);
+ }
+}
+
+
+void warn_fopen (void)
+{
+ {
+ FILE *q = fopen ("1", "r");
+ sink (q);
+ release (q); // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
+ }
+ {
+ FILE *q = fdopen (0);
+ sink (q);
+ free (q); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *q = fdopen (0);
+ sink (q);
+ q = realloc (q, 7); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
+ sink (q);
+ }
+}
+
+
+void test_popen (void)
+{
+ {
+ FILE *p = popen ("1", "r");
+ sink (p);
+ pclose (p);
+ }
+
+ {
+ FILE *p;
+ p = popen ("2", "r"); // { dg-message "returned from a call to 'popen'" "note" }
+ sink (p);
+ fclose (p); // { dg-warning "'fclose' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ /* freopen() can close a stream open by popen() but pclose() can't
+ close the stream returned from freopen(). */
+ FILE *p = popen ("2", "r");
+ sink (p);
+ p = freopen ("3", "r", p); // { dg-message "returned from a call to 'freopen'" "note" }
+ sink (p);
+ pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
+ }
+}
+
+
+void test_tmpfile (void)
+{
+ {
+ FILE *p = tmpfile ();
+ sink (p);
+ fclose (p);
+ }
+
+ {
+ FILE *p = tmpfile ();
+ sink (p);
+ p = freopen ("1", "r", p);
+ sink (p);
+ fclose (p);
+ }
+
+ {
+ FILE *p = tmpfile (); // { dg-message "returned from a call to 'tmpfile'" "note" }
+ sink (p);
+ pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
+ }
+}
+
+
+void warn_malloc (void)
+{
+ {
+ FILE *p = malloc (100); // { dg-message "returned from a call to 'malloc'" "note" }
+ sink (p);
+ fclose (p); // { dg-warning "'fclose' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = malloc (100); // { dg-message "returned from a call to 'malloc'" "note" }
+ sink (p);
+ p = freopen ("1", "r", p);// { dg-warning "'freopen' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = malloc (100); // { dg-message "returned from a call to 'malloc'" "note" }
+ sink (p);
+ pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
+ }
+}
+
+
+void test_acquire (void)
+{
+ {
+ FILE *p = acquire ();
+ release (p);
+ }
+
+ {
+ FILE *p = acquire ();
+ sink (p);
+ release (p);
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from a call to 'acquire'" "note" }
+ sink (p);
+ fclose (p); // { dg-warning "'fclose' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from a call to 'acquire'" "note" }
+ sink (p);
+ pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from a call to 'acquire'" "note" }
+ sink (p);
+ p = freopen ("1", "r", p); // { dg-warning "'freopen' called on pointer returned from a mismatched allocation function" }
+ sink (p);
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from a call to 'acquire'" "note" }
+ sink (p);
+ free (p); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from a call to 'acquire'" "note" }
+ sink (p);
+ p = realloc (p, 123); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
+ sink (p);
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c
index c5bf1227c..26d8288 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c
@@ -609,3 +609,5 @@ int test_49 (int i)
*p = 1; /* { dg-warning "dereference of NULL 'p' \\\[CWE-476\\\]" } */
return x;
}
+
+/* { dg-prune-output "\\\[-Wfree-nonheap-object" } */
diff --git a/gcc/testsuite/gcc.dg/attr-malloc.c b/gcc/testsuite/gcc.dg/attr-malloc.c
new file mode 100644
index 0000000..14f1980
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-malloc.c
@@ -0,0 +1,75 @@
+/* PR middle-end/94527 - Add an attribute that marks a function as freeing
+ an object
+ Verify that attribute malloc with one or two arguments is accepted where
+ intended and rejected where it's invalid.
+ { dg-options "-Wall -ftrack-macro-expansion=0" } */
+
+#define A(...) __attribute__ ((malloc (__VA_ARGS__)))
+
+A (0) void* alloc_zero (int); // { dg-error "'malloc' attribute argument 1 does not name a function" }
+
+A ("") void* alloc_string (int); // { dg-error "'malloc' attribute argument 1 does not name a function" }
+
+int var;
+A (var) void* alloc_var (int); // { dg-error "'malloc' attribute argument 1 does not name a function" }
+
+typedef struct Type { int i; } Type;
+A (Type) void* alloc_type (int); // { dg-error "expected expression|identifier" }
+
+A (unknown) void* alloc_unknown (int); // { dg-error "'unknown' undeclared" }
+
+void fv_ (); // { dg-message "declared here" }
+A (fv_) void* alloc_fv_ (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument" }
+
+void fvi (int); // { dg-message "declared here" }
+A (fvi) void* alloc_fvi (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument; have 'int'" }
+
+void fvv (void); // { dg-message "declared here" }
+A (fvv) void* alloc_fvv (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument; have 'void'" }
+
+void fvi_ (int, ...); // { dg-message "declared here" }
+A (fvi_) void* alloc_fvi_ (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument; have 'int'" }
+
+void fvi_vp (Type, void*); // { dg-message "declared here" }
+A (fvi_vp) void* alloc_fvi_vp (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument; have 'Type'" }
+
+
+void fpv (void*);
+A (fpv) void* alloc_fpv (int);
+
+void fpv_i (void*, int);
+A (fpv_i) void* alloc_fpv_i (int);
+
+void fpv_pv (void*, void*);
+A (fpv_i) void* alloc_fpv_pv (int);
+
+
+void gpc (char*);
+void hpi (int*);
+A (fpv) A (gpc) A (hpi) Type* alloc_fpv_gpv (int);
+
+
+/* Verify that the attribute can be applied to <stdio.h> functions. */
+typedef struct FILE FILE;
+typedef __SIZE_TYPE__ size_t;
+
+int fclose (FILE*);
+FILE* fdopen (int);
+FILE* fopen (const char*, const char*);
+FILE* freopen (const char*, const char*, FILE*);
+int pclose (FILE*);
+FILE* popen (const char*, const char*);
+FILE* tmpfile (void);
+
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* fdopen (int);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* fopen (const char*, const char*);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* fmemopen(void *, size_t, const char *);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* freopen (const char*, const char*, FILE*);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* popen (const char*, const char*);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* tmpfile (void);
diff --git a/gcc/testsuite/gcc.dg/free-1.c b/gcc/testsuite/gcc.dg/free-1.c
index 5496c84..ad49d78 100644
--- a/gcc/testsuite/gcc.dg/free-1.c
+++ b/gcc/testsuite/gcc.dg/free-1.c
@@ -13,14 +13,14 @@ void foo (void)
static char buf4[10], e;
char *q = buf;
free (p);
- free (q); /* { dg-warning "attempt to free a non-heap object" } */
- free (buf2); /* { dg-warning "attempt to free a non-heap object" } */
- free (&c); /* { dg-warning "attempt to free a non-heap object" } */
- free (buf3); /* { dg-warning "attempt to free a non-heap object" } */
- free (&d); /* { dg-warning "attempt to free a non-heap object" } */
- free (buf4); /* { dg-warning "attempt to free a non-heap object" } */
- free (&e); /* { dg-warning "attempt to free a non-heap object" } */
+ free (q); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf2); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&c); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf3); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&d); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf4); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&e); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
free (&r->a);
- free ("abcd"); /* { dg-warning "attempt to free a non-heap object" } */
- free (L"abcd"); /* { dg-warning "attempt to free a non-heap object" } */
+ free ("abcd"); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (L"abcd"); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
}
diff --git a/gcc/testsuite/gcc.dg/free-2.c b/gcc/testsuite/gcc.dg/free-2.c
index eb94651..edbcdc7 100644
--- a/gcc/testsuite/gcc.dg/free-2.c
+++ b/gcc/testsuite/gcc.dg/free-2.c
@@ -13,14 +13,14 @@ void foo (void)
static char buf4[10], e;
char *q = buf;
free (p);
- free (q); /* At -O0 no warning is reported here. */
- free (buf2); /* { dg-warning "attempt to free a non-heap object" } */
- free (&c); /* { dg-warning "attempt to free a non-heap object" } */
- free (buf3); /* { dg-warning "attempt to free a non-heap object" } */
- free (&d); /* { dg-warning "attempt to free a non-heap object" } */
- free (buf4); /* { dg-warning "attempt to free a non-heap object" } */
- free (&e); /* { dg-warning "attempt to free a non-heap object" } */
+ free (q); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf2); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&c); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf3); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&d); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf4); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&e); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
free (&r->a);
- free ("abcd"); /* { dg-warning "attempt to free a non-heap object" } */
- free (L"abcd"); /* { dg-warning "attempt to free a non-heap object" } */
+ free ("abcd"); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (L"abcd"); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
}
diff --git a/gcc/testsuite/gcc.dg/pr98099.c b/gcc/testsuite/gcc.dg/pr98099.c
index 34909f2..12e52f2 100644
--- a/gcc/testsuite/gcc.dg/pr98099.c
+++ b/gcc/testsuite/gcc.dg/pr98099.c
@@ -1,7 +1,7 @@
/* PR middle-end/98099 */
/* Reported by G. Steinmetz <gscfq@t-online.de> */
-/* { dg-do compile } */
+/* { dg-do compile { target dfp } } */
/* { dg-options "-fsso-struct=big-endian" } */
struct S { _Decimal128 a; };
diff --git a/gcc/testsuite/gcc.dg/torture/pr71816.c b/gcc/testsuite/gcc.dg/torture/pr71816.c
index be37ad9..cc143fa 100644
--- a/gcc/testsuite/gcc.dg/torture/pr71816.c
+++ b/gcc/testsuite/gcc.dg/torture/pr71816.c
@@ -20,3 +20,7 @@ struct ext2_icount_el *insert_icount_el() {
ext2fs_resize_mem(&insert_icount_el_icount_1);
return 0;
}
+
+/* Passing the address of a declared object to realloc triggers
+ -Wfree-nonheap-object unless -flto is used.
+ { dg-prune-output "\\\[-Wfree-nonheap-object" } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-4.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-4.c
index 6a03588..e6dd4be 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-4.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */
+/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized --param case-values-threshold=5" } */
int global;
int foo ();
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-6.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-6.c
index 464b1fb..b164067 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-6.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-6.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */
+/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized --param case-values-threshold=5" } */
int global;
int foo ();
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-8.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-8.c
index f43ce7d..f4d06fe 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-8.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-8.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */
+/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized --param case-values-threshold=5" } */
int global;
int global1;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c
index 55b4fd0..df4120d 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c
@@ -5,7 +5,7 @@ void test1(void)
{
int *p = __builtin_malloc (sizeof (int) * 4);
*p++ = 4;
- __builtin_free (p);
+ __builtin_free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
}
/* Undefined. We can't do anything here. */
diff --git a/gcc/testsuite/gcc.target/i386/pr96226.c b/gcc/testsuite/gcc.target/i386/pr96226.c
new file mode 100644
index 0000000..cc010fa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr96226.c
@@ -0,0 +1,16 @@
+/* PR target/96226 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-times "\troll\t" 4 } } */
+/* { dg-final { scan-assembler-times "\trolq\t" 4 { target { ! ia32 } } } } */
+
+int f1 (int x) { return ~(1U << (x & 0x1f)); }
+int f2 (int x) { return ~(1U << x); }
+int f3 (unsigned char *x) { return ~(1U << (x[0] & 0x1f)); }
+int f4 (unsigned char *x) { return ~(1U << x[0]); }
+#ifdef __x86_64__
+long int f5 (int x) { return ~(1ULL << (x & 0x3f)); }
+long int f6 (int x) { return ~(1ULL << x); }
+long int f7 (unsigned char *x) { return ~(1ULL << (x[0] & 0x3f)); }
+long int f8 (unsigned char *x) { return ~(1ULL << x[0]); }
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/pr98100.c b/gcc/testsuite/gcc.target/i386/pr98100.c
new file mode 100644
index 0000000..4deda1a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr98100.c
@@ -0,0 +1,9 @@
+/* PR target/98100 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-avx -fvar-tracking-assignments -g0" } */
+
+__attribute__((target_clones("default","avx2"))) void
+foo ()
+{
+ __attribute__((__vector_size__(8 * sizeof(int)))) int b = {};
+}
diff --git a/gcc/testsuite/gnat.dg/opt91.adb b/gcc/testsuite/gnat.dg/opt91.adb
new file mode 100644
index 0000000..b0132f8
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt91.adb
@@ -0,0 +1,11 @@
+-- { dg-do compile }
+-- { dg-options "-O2 -fchecking=1" }
+
+package body Opt91 is
+
+ function Custom_Image (Self : True_Relation_Rec) return String is
+ begin
+ return "<True>";
+ end;
+
+end Opt91;
diff --git a/gcc/testsuite/gnat.dg/opt91.ads b/gcc/testsuite/gnat.dg/opt91.ads
new file mode 100644
index 0000000..b31aa8d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt91.ads
@@ -0,0 +1,10 @@
+with Opt91_Pkg; use Opt91_Pkg;
+
+package Opt91 is
+
+ type True_Relation_Rec is null record;
+ function Custom_Image (Self : True_Relation_Rec) return String;
+
+ package True_Relation is new Pure_Relation (Ty => True_Relation_Rec);
+
+end Opt91;
diff --git a/gcc/testsuite/gnat.dg/opt91_pkg.adb b/gcc/testsuite/gnat.dg/opt91_pkg.adb
new file mode 100644
index 0000000..5b95fb2e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt91_pkg.adb
@@ -0,0 +1,12 @@
+package body Opt91_Pkg is
+
+ package body Pure_Relation is
+
+ overriding function Custom_Image (Self : Rel) return String is
+ begin
+ return Custom_Image (Self.Rel);
+ end Custom_Image;
+
+ end Pure_Relation;
+
+end Opt91_Pkg;
diff --git a/gcc/testsuite/gnat.dg/opt91_pkg.ads b/gcc/testsuite/gnat.dg/opt91_pkg.ads
new file mode 100644
index 0000000..9bfd0f0
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt91_pkg.ads
@@ -0,0 +1,19 @@
+package Opt91_Pkg is
+
+ type Base_Relation is abstract tagged null record;
+
+ function Custom_Image (Self : Base_Relation) return String is abstract;
+
+ generic
+ type Ty is private;
+ with function Custom_Image (Self : Ty) return String is <>;
+ package Pure_Relation is
+
+ type Rel is new Base_Relation with record
+ Rel : Ty;
+ end record;
+
+ overriding function Custom_Image (Self : Rel) return String;
+ end Pure_Relation;
+
+end Opt91_Pkg;
diff --git a/gcc/toplev.c b/gcc/toplev.c
index cb4ae77..93a4194 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -116,9 +116,6 @@ static void compile_file (void);
/* True if we don't need a backend (e.g. preprocessing only). */
static bool no_backend;
-/* Length of line when printing switch values. */
-#define MAX_LINE 75
-
/* Decoded options, and number of such options. */
struct cl_decoded_option *save_decoded_options;
unsigned int save_decoded_options_count;
@@ -687,148 +684,7 @@ print_version (FILE *file, const char *indent, bool show_global_state)
}
}
-static int
-print_to_asm_out_file (print_switch_type type, const char * text)
-{
- bool prepend_sep = true;
-
- switch (type)
- {
- case SWITCH_TYPE_LINE_END:
- putc ('\n', asm_out_file);
- return 1;
-
- case SWITCH_TYPE_LINE_START:
- fputs (ASM_COMMENT_START, asm_out_file);
- return strlen (ASM_COMMENT_START);
-
- case SWITCH_TYPE_DESCRIPTIVE:
- if (ASM_COMMENT_START[0] == 0)
- prepend_sep = false;
- /* FALLTHRU */
- case SWITCH_TYPE_PASSED:
- case SWITCH_TYPE_ENABLED:
- if (prepend_sep)
- fputc (' ', asm_out_file);
- fputs (text, asm_out_file);
- /* No need to return the length here as
- print_single_switch has already done it. */
- return 0;
-
- default:
- return -1;
- }
-}
-
-static int
-print_to_stderr (print_switch_type type, const char * text)
-{
- switch (type)
- {
- case SWITCH_TYPE_LINE_END:
- putc ('\n', stderr);
- return 1;
-
- case SWITCH_TYPE_LINE_START:
- return 0;
-
- case SWITCH_TYPE_PASSED:
- case SWITCH_TYPE_ENABLED:
- fputc (' ', stderr);
- /* FALLTHRU */
-
- case SWITCH_TYPE_DESCRIPTIVE:
- fputs (text, stderr);
- /* No need to return the length here as
- print_single_switch has already done it. */
- return 0;
-
- default:
- return -1;
- }
-}
-
-/* Print an option value and return the adjusted position in the line.
- ??? print_fn doesn't handle errors, eg disk full; presumably other
- code will catch a disk full though. */
-
-static int
-print_single_switch (print_switch_fn_type print_fn,
- int pos,
- print_switch_type type,
- const char * text)
-{
- /* The ultrix fprintf returns 0 on success, so compute the result
- we want here since we need it for the following test. The +1
- is for the separator character that will probably be emitted. */
- int len = strlen (text) + 1;
-
- if (pos != 0
- && pos + len > MAX_LINE)
- {
- print_fn (SWITCH_TYPE_LINE_END, NULL);
- pos = 0;
- }
-
- if (pos == 0)
- pos += print_fn (SWITCH_TYPE_LINE_START, NULL);
-
- print_fn (type, text);
- return pos + len;
-}
-
-/* Print active target switches using PRINT_FN.
- POS is the current cursor position and MAX is the size of a "line".
- Each line begins with INDENT and ends with TERM.
- Each switch is separated from the next by SEP. */
-static void
-print_switch_values (print_switch_fn_type print_fn)
-{
- int pos = 0;
- size_t j;
-
- /* Print the options as passed. */
- pos = print_single_switch (print_fn, pos,
- SWITCH_TYPE_DESCRIPTIVE, _("options passed: "));
-
- for (j = 1; j < save_decoded_options_count; j++)
- {
- switch (save_decoded_options[j].opt_index)
- {
- case OPT_o:
- case OPT_d:
- case OPT_dumpbase:
- case OPT_dumpbase_ext:
- case OPT_dumpdir:
- case OPT_quiet:
- case OPT_version:
- /* Ignore these. */
- continue;
- }
-
- pos = print_single_switch (print_fn, pos, SWITCH_TYPE_PASSED,
- save_decoded_options[j].orig_option_with_args_text);
- }
-
- if (pos > 0)
- print_fn (SWITCH_TYPE_LINE_END, NULL);
-
- /* Print the -f and -m options that have been enabled.
- We don't handle language specific options but printing argv
- should suffice. */
- pos = print_single_switch (print_fn, 0,
- SWITCH_TYPE_DESCRIPTIVE, _("options enabled: "));
-
- unsigned lang_mask = lang_hooks.option_lang_mask ();
- for (j = 0; j < cl_options_count; j++)
- if (cl_options[j].cl_report
- && option_enabled (j, lang_mask, &global_options) > 0)
- pos = print_single_switch (print_fn, pos,
- SWITCH_TYPE_ENABLED, cl_options[j].opt_text);
-
- print_fn (SWITCH_TYPE_LINE_END, NULL);
-}
/* Open assembly code output file. Do this even if -fsyntax-only is
on, because then the driver will have provided the name of a
@@ -875,14 +731,11 @@ init_asm_output (const char *name)
{
if (targetm.asm_out.record_gcc_switches)
{
- /* Let the target know that we are about to start recording. */
- targetm.asm_out.record_gcc_switches (SWITCH_TYPE_DESCRIPTIVE,
- NULL);
- /* Now record the switches. */
- print_switch_values (targetm.asm_out.record_gcc_switches);
- /* Let the target know that the recording is over. */
- targetm.asm_out.record_gcc_switches (SWITCH_TYPE_DESCRIPTIVE,
- NULL);
+ const char *str
+ = gen_producer_string (lang_hooks.name,
+ save_decoded_options,
+ save_decoded_options_count);
+ targetm.asm_out.record_gcc_switches (str);
}
else
inform (UNKNOWN_LOCATION,
@@ -892,11 +745,13 @@ init_asm_output (const char *name)
if (flag_verbose_asm)
{
- /* Print the list of switches in effect
- into the assembler file as comments. */
print_version (asm_out_file, ASM_COMMENT_START, true);
- print_switch_values (print_to_asm_out_file);
- putc ('\n', asm_out_file);
+ fputs (ASM_COMMENT_START, asm_out_file);
+ fputs (" options passed: ", asm_out_file);
+ fputs (gen_command_line_string (save_decoded_options,
+ save_decoded_options_count),
+ asm_out_file);
+ fputc ('\n', asm_out_file);
}
}
}
@@ -1526,8 +1381,13 @@ process_options (void)
if (version_flag)
{
print_version (stderr, "", true);
- if (! quiet_flag)
- print_switch_values (print_to_stderr);
+ if (!quiet_flag)
+ {
+ fputs ("options passed: ", stderr);
+ fputs (gen_command_line_string (save_decoded_options,
+ save_decoded_options_count), stderr);
+ fputc ('\n', stderr);
+ }
}
if (flag_syntax_only)
diff --git a/gcc/tree.c b/gcc/tree.c
index 72311005..02ce5dd 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -2185,7 +2185,7 @@ build_constructor_from_vec (tree type, const vec<tree, va_gc> *vals)
{
vec<constructor_elt, va_gc> *v = NULL;
- for (tree t : *vals)
+ for (tree t : vals)
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
return build_constructor (type, v);
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 961d2d6..0fac368 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see
#include "fold-const.h"
#include "stor-layout.h"
#include "varasm.h"
+#include "version.h"
#include "flags.h"
#include "stmt.h"
#include "expr.h"
@@ -58,6 +59,8 @@ along with GCC; see the file COPYING3. If not see
#include "rtl-iter.h"
#include "file-prefix-map.h" /* remap_debug_filename() */
#include "alloc-pool.h"
+#include "toplev.h"
+#include "opts.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h" /* Needed for external data declarations. */
@@ -8053,45 +8056,14 @@ output_object_blocks (void)
we want to emit NUL strings terminators into the object file we have to use
ASM_OUTPUT_SKIP. */
-int
-elf_record_gcc_switches (print_switch_type type, const char * name)
+void
+elf_record_gcc_switches (const char *options)
{
- switch (type)
- {
- case SWITCH_TYPE_PASSED:
- ASM_OUTPUT_ASCII (asm_out_file, name, strlen (name));
- ASM_OUTPUT_SKIP (asm_out_file, HOST_WIDE_INT_1U);
- break;
-
- case SWITCH_TYPE_DESCRIPTIVE:
- if (name == NULL)
- {
- /* Distinguish between invocations where name is NULL. */
- static bool started = false;
-
- if (!started)
- {
- section * sec;
-
- sec = get_section (targetm.asm_out.record_gcc_switches_section,
- SECTION_DEBUG
- | SECTION_MERGE
- | SECTION_STRINGS
- | (SECTION_ENTSIZE & 1),
- NULL);
- switch_to_section (sec);
- started = true;
- }
- }
-
- default:
- break;
- }
-
- /* The return value is currently ignored by the caller, but must be 0.
- For -fverbose-asm the return value would be the number of characters
- emitted into the assembler file. */
- return 0;
+ section *sec = get_section (targetm.asm_out.record_gcc_switches_section,
+ SECTION_DEBUG | SECTION_MERGE
+ | SECTION_STRINGS | (SECTION_ENTSIZE & 1), NULL);
+ switch_to_section (sec);
+ ASM_OUTPUT_ASCII (asm_out_file, options, strlen (options) + 1);
}
/* Emit text to declare externally defined symbols. It is needed to
diff --git a/gcc/vec.h b/gcc/vec.h
index 9090451..09166f1 100644
--- a/gcc/vec.h
+++ b/gcc/vec.h
@@ -419,6 +419,16 @@ struct GTY((user)) vec
{
};
+/* Allow C++11 range-based 'for' to work directly on vec<T>*. */
+template<typename T, typename A, typename L>
+T* begin (vec<T,A,L> *v) { return v ? v->begin () : nullptr; }
+template<typename T, typename A, typename L>
+T* end (vec<T,A,L> *v) { return v ? v->end () : nullptr; }
+template<typename T, typename A, typename L>
+const T* begin (const vec<T,A,L> *v) { return v ? v->begin () : nullptr; }
+template<typename T, typename A, typename L>
+const T* end (const vec<T,A,L> *v) { return v ? v->end () : nullptr; }
+
/* Generic vec<> debug helpers.
These need to be instantiated for each vec<TYPE> used throughout
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 20b77fd..9b95f55 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,21 @@
+2020-12-03 Michael Meissner <meissner@linux.ibm.com>
+
+ PR libgcc/97543
+ PR libgcc/97643
+ * config/rs6000/t-linux (IBM128_STATIC_OBJS): New make variable.
+ (IBM128_SHARED_OBJS): New make variable.
+ (IBM128_OBJS): New make variable. Set all objects to use the
+ explicit IBM format, and disable gnu attributes.
+ (IBM128_CFLAGS): New make variable.
+ (gcc_s_compile): Add -mno-gnu-attribute to all shared library
+ modules.
+
+2020-12-03 Alexandre Oliva <oliva@adacore.com>
+
+ * config/t-vxworks (LIB2ADD): Drop.
+ * config/t-vxworks7 (LIB2ADD): Likewise.
+ * config/vxcache.c: Remove.
+
2020-11-30 Stefan Kanthak <stefan.kanthak@nexgo.de>
* libgcc2.c (bswapsi2): Make constants unsigned.
diff --git a/libgo/runtime/go-fieldtrack.c b/libgo/runtime/go-fieldtrack.c
index 22f091b..80be27c 100644
--- a/libgo/runtime/go-fieldtrack.c
+++ b/libgo/runtime/go-fieldtrack.c
@@ -31,7 +31,7 @@ extern void *mapassign (const struct maptype *, void *hmap, const void *key)
// The type descriptor for map[string] bool. */
extern const char map_string_bool[] __attribute__ ((weak));
extern const char map_string_bool[]
- __asm__ (GOSYM_PREFIX "type..map.6string.7bool");
+ __asm__ (GOSYM_PREFIX "type..map_6string_7bool");
void runtime_Fieldtrack (void *) __asm__ (GOSYM_PREFIX "runtime.Fieldtrack");
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 6b1c345..ed9c82c 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,57 @@
+2020-12-03 Martin Sebor <msebor@redhat.com>
+
+ * testsuite/ext/vstring/modifiers/clear/56166.cc: Suppress a false
+ positive warning.
+
+2020-12-03 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/26_numerics/bit/bit.cast/bit_cast.cc: Remove stray
+ word from copy&paste.
+ * testsuite/26_numerics/bit/bit.cast/version.cc: Likewise.
+
+2020-12-03 Jonathan Wakely <jwakely@redhat.com>
+
+ * doc/xml/manual/status_cxx2020.xml: Update C++20 status.
+ * doc/html/*: Regenerate.
+
+2020-12-03 JeanHeyd Meneide <phdofthehouse@gmail.com>
+
+ * doc/doxygen/user.cfg.in (INPUT): Add <source_location>.
+ * include/Makefile.am: Add <source_location>.
+ * include/Makefile.in: Regenerate.
+ * include/std/version (__cpp_lib_source_location): Define.
+ * include/std/source_location: New file.
+ * testsuite/18_support/source_location/1.cc: New test.
+ * testsuite/18_support/source_location/consteval.cc: New test.
+ * testsuite/18_support/source_location/srcloc.h: New test.
+ * testsuite/18_support/source_location/version.cc: New test.
+
+2020-12-03 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/93121
+ * include/std/bit (__cpp_lib_bit_cast, bit_cast): Define.
+ * include/std/version (__cpp_lib_bit_cast): Define.
+ * testsuite/26_numerics/bit/bit.cast/bit_cast.cc: New test.
+ * testsuite/26_numerics/bit/bit.cast/version.cc: New test.
+
+2020-12-03 Jonathan Wakely <jwakely@redhat.com>
+
+ * config/abi/post/powerpc-linux-gnu/baseline_symbols.txt:
+ Update.
+ * config/abi/post/powerpc64-linux-gnu/32/baseline_symbols.txt:
+ Update.
+
+2020-12-03 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/array (array::operator[](size_t) const, array::front() const)
+ (array::back() const) [__cplusplus == 201103]: Disable
+ assertions.
+ * testsuite/23_containers/array/element_access/constexpr_element_access.cc:
+ Check for correct values.
+ * testsuite/23_containers/array/tuple_interface/get_neg.cc:
+ Adjust dg-error line numbers.
+ * testsuite/23_containers/array/debug/constexpr_c++11.cc: New test.
+
2020-12-02 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/65480
diff --git a/libstdc++-v3/testsuite/18_support/source_location/1.cc b/libstdc++-v3/testsuite/18_support/source_location/1.cc
index c945aaa..c9cb743 100644
--- a/libstdc++-v3/testsuite/18_support/source_location/1.cc
+++ b/libstdc++-v3/testsuite/18_support/source_location/1.cc
@@ -89,7 +89,7 @@ int main ()
VERIFY(main_sl.line() == main_sl_line);
// closing paren of call
VERIFY(main_sl.column() == 64);
- VERIFY(main_sl_fn_name.ends_with("main"sv));
+ VERIFY(main_sl_fn_name.ends_with("main()"sv));
VERIFY(main_sl_fi_name.ends_with("1.cc"sv));
std::string_view f_arg_sl_fn_name(f_arg_sl.function_name());
@@ -97,28 +97,28 @@ int main ()
VERIFY(f_arg_sl.line() == f_arg_sl_line);
// closing paren of call
VERIFY(f_arg_sl.column() == 64);
- VERIFY(f_arg_sl_fn_name.ends_with("main"sv));
+ VERIFY(f_arg_sl_fn_name.ends_with("main()"sv));
VERIFY(f_arg_sl_fi_name.ends_with("1.cc"sv));
std::string_view g_sl_fn_name(g_sl.function_name());
std::string_view g_sl_fi_name(g_sl.file_name());
VERIFY(g_sl.line() == g_sl_line);
VERIFY(g_sl.column() == 58); // closing paren of call
- VERIFY(g_sl_fn_name.ends_with("g"sv));
+ VERIFY(g_sl_fn_name.ends_with("g()"sv));
VERIFY(g_sl_fi_name.ends_with("1.cc"sv));
std::string_view h_sl_fn_name(h_sl.function_name());
std::string_view h_sl_fi_name(h_sl.file_name());
VERIFY(h_sl.line() == 23);
VERIFY(h_sl.column() == 58); // closing paren of call
- VERIFY(h_sl_fn_name.ends_with("h"sv));
+ VERIFY(h_sl_fn_name.ends_with("h()"sv));
VERIFY(h_sl_fi_name.ends_with("srcloc.h"sv));
std::string_view member_main_sl_fn_name(member_main_sl.member.function_name());
std::string_view member_main_sl_fi_name(member_main_sl.member.file_name());
VERIFY(member_main_sl.member.line() == main_sl_line);
VERIFY(member_main_sl.member.column() == 64);
- VERIFY(member_main_sl_fn_name.ends_with("main"sv));
+ VERIFY(member_main_sl_fn_name.ends_with("main()"sv));
VERIFY(member_main_sl_fi_name.ends_with("1.cc"sv));
std::string_view member_defaulted_sl_fi_name(
@@ -128,9 +128,7 @@ int main ()
VERIFY(member_defaulted_sl.member.line() == 46);
// closing paren of constructor declaration
VERIFY(member_defaulted_sl.member.column() == 25);
-#if 0
VERIFY(member_defaulted_sl_fn_name.starts_with("s::s(int)"sv));
-#endif
VERIFY(member_defaulted_sl_fi_name.ends_with("1.cc"sv));
std::string_view member_sl_fi_name(
@@ -140,7 +138,7 @@ int main ()
VERIFY(member_sl.member.line() == member_sl_line);
// closing brace/paren of constructor
VERIFY(member_sl.member.column() == 19);
- VERIFY(member_sl_fn_name.starts_with("main"sv));
+ VERIFY(member_sl_fn_name.starts_with("int main()"sv));
VERIFY(member_sl_fi_name.ends_with("1.cc"sv));
std::string_view f_sl_fi_name(f_sl.file_name());
@@ -148,7 +146,7 @@ int main ()
VERIFY(f_sl.line() == f_sl_line);
// closing paren of call
VERIFY(f_sl.column() == 33);
- VERIFY(f_sl_fn_name.ends_with("main"sv));
+ VERIFY(f_sl_fn_name.ends_with("main()"sv));
VERIFY(f_sl_fi_name.ends_with("1.cc"sv));
return 0;
diff --git a/libstdc++-v3/testsuite/18_support/source_location/consteval.cc b/libstdc++-v3/testsuite/18_support/source_location/consteval.cc
index 9b137f8..51c8fb2 100644
--- a/libstdc++-v3/testsuite/18_support/source_location/consteval.cc
+++ b/libstdc++-v3/testsuite/18_support/source_location/consteval.cc
@@ -83,7 +83,7 @@ int main ()
static_assert(main_sl.line() == main_sl_line);
// closing paren of call
static_assert(main_sl.column() == 74);
- static_assert(main_sl_fn_name.ends_with("main"sv));
+ static_assert(main_sl_fn_name.ends_with("main()"sv));
static_assert(main_sl_fi_name.ends_with("consteval.cc"sv));
constexpr std::string_view f_arg_sl_fn_name(f_arg_sl.function_name());
@@ -91,28 +91,28 @@ int main ()
static_assert(f_arg_sl.line() == f_arg_sl_line);
// closing paren of call
static_assert(f_arg_sl.column() == 74);
- static_assert(f_arg_sl_fn_name.ends_with("main"sv));
+ static_assert(f_arg_sl_fn_name.ends_with("main()"sv));
static_assert(f_arg_sl_fi_name.ends_with("consteval.cc"sv));
constexpr std::string_view g_sl_fn_name(g_sl.function_name());
constexpr std::string_view g_sl_fi_name(g_sl.file_name());
static_assert(g_sl.line() == g_sl_line);
static_assert(g_sl.column() == 58); // closing paren of call
- static_assert(g_sl_fn_name.ends_with("g"sv));
+ static_assert(g_sl_fn_name.ends_with("g()"sv));
static_assert(g_sl_fi_name.ends_with("consteval.cc"sv));
constexpr std::string_view h_sl_fn_name(h_sl.function_name());
constexpr std::string_view h_sl_fi_name(h_sl.file_name());
static_assert(h_sl.line() == 23);
static_assert(h_sl.column() == 58); // closing paren of call
- static_assert(h_sl_fn_name.ends_with("h"sv));
+ static_assert(h_sl_fn_name.ends_with("h()"sv));
static_assert(h_sl_fi_name.ends_with("srcloc.h"sv));
constexpr std::string_view member_main_sl_fn_name(member_main_sl.member.function_name());
constexpr std::string_view member_main_sl_fi_name(member_main_sl.member.file_name());
static_assert(member_main_sl.member.line() == main_sl_line);
static_assert(member_main_sl.member.column() == 74);
- static_assert(member_main_sl_fn_name.ends_with("main"sv));
+ static_assert(member_main_sl_fn_name.ends_with("main()"sv));
static_assert(member_main_sl_fi_name.ends_with("consteval.cc"sv));
constexpr std::string_view member_defaulted_sl_fi_name(
@@ -122,9 +122,7 @@ int main ()
static_assert(member_defaulted_sl.member.line() == 36);
// closing paren of constructor declaration
static_assert(member_defaulted_sl.member.column() == 25);
-#if 0
static_assert(member_defaulted_sl_fn_name.ends_with("s::s(int)"sv));
-#endif
static_assert(member_defaulted_sl_fi_name.ends_with("consteval.cc"sv));
constexpr std::string_view member_sl_fi_name(
@@ -134,7 +132,7 @@ int main ()
static_assert(member_sl.member.line() == member_sl_line);
// closing brace/paren of constructor
static_assert(member_sl.member.column() == 29);
- static_assert(member_sl_fn_name.starts_with("main"sv));
+ static_assert(member_sl_fn_name.starts_with("int main()"sv));
static_assert(member_sl_fi_name.ends_with("consteval.cc"sv));
constexpr std::string_view f_sl_fi_name(f_sl.file_name());
@@ -142,7 +140,7 @@ int main ()
static_assert(f_sl.line() == f_sl_line);
// closing paren of call
static_assert(f_sl.column() == 43);
- static_assert(f_sl_fn_name.ends_with("main"sv));
+ static_assert(f_sl_fn_name.ends_with("main()"sv));
static_assert(f_sl_fi_name.ends_with("consteval.cc"sv));
return 0;
diff --git a/libstdc++-v3/testsuite/ext/vstring/modifiers/clear/56166.cc b/libstdc++-v3/testsuite/ext/vstring/modifiers/clear/56166.cc
index 84dd79e..b5ce78d 100644
--- a/libstdc++-v3/testsuite/ext/vstring/modifiers/clear/56166.cc
+++ b/libstdc++-v3/testsuite/ext/vstring/modifiers/clear/56166.cc
@@ -56,12 +56,12 @@ template<typename T>
throw std::bad_alloc();
}
}
- return (T*)new char[n * sizeof(T)];
+ return (T*)operator new (n * sizeof(T));
}
void deallocate(T* p, size_type)
{
- delete[] (char*)p;
+ operator delete (p);
}
};
@@ -94,3 +94,7 @@ int main()
}
}
}
+
+// The __versa_string destructor triggers a bogus -Wfree-nonheap-object
+// due to pr54202.
+// { dg-prune-output "\\\[-Wfree-nonheap-object" }