aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2022-07-25 09:01:02 +0200
committerMartin Liska <mliska@suse.cz>2022-07-25 09:01:02 +0200
commit9630093982a263fd86dc7c87afbb0afed89c9d47 (patch)
treeff64cc021aaa98cc384c69716c635c42250792bc
parentbb743388df90352e5690848fc39bb9c10457b0e0 (diff)
parent718cf8d0bd32689192200d2156722167fd21a647 (diff)
downloadgcc-9630093982a263fd86dc7c87afbb0afed89c9d47.zip
gcc-9630093982a263fd86dc7c87afbb0afed89c9d47.tar.gz
gcc-9630093982a263fd86dc7c87afbb0afed89c9d47.tar.bz2
Merge branch 'master' into devel/sphinx
-rw-r--r--ChangeLog8
-rw-r--r--MAINTAINERS1
-rw-r--r--contrib/ChangeLog11
-rwxr-xr-xcontrib/git-commit-mklog.py9
-rwxr-xr-xcontrib/mklog.py26
-rwxr-xr-xcontrib/prepare-commit-msg2
-rw-r--r--gcc/ChangeLog196
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/analyzer/ChangeLog58
-rw-r--r--gcc/analyzer/region-model.cc2
-rw-r--r--gcc/analyzer/sm-fd.cc338
-rw-r--r--gcc/analyzer/store.cc1
-rw-r--r--gcc/analyzer/varargs.cc30
-rw-r--r--gcc/c-family/ChangeLog6
-rw-r--r--gcc/c-family/c-attribs.cc31
-rw-r--r--gcc/config/i386/i386-features.cc116
-rw-r--r--gcc/config/i386/i386-features.h12
-rw-r--r--gcc/config/i386/mmx.md70
-rw-r--r--gcc/config/i386/predicates.md4
-rw-r--r--gcc/config/rs6000/altivec.md26
-rw-r--r--gcc/config/rs6000/rs6000-c.cc21
-rw-r--r--gcc/config/rs6000/rs6000-protos.h5
-rw-r--r--gcc/config/rs6000/rs6000.cc102
-rw-r--r--gcc/config/rs6000/rs6000.h11
-rw-r--r--gcc/config/rs6000/rs6000.opt4
-rw-r--r--gcc/config/xtensa/xtensa.md84
-rw-r--r--gcc/cp/ChangeLog25
-rw-r--r--gcc/cp/decl.cc2
-rw-r--r--gcc/cp/init.cc1
-rw-r--r--gcc/cp/method.cc35
-rw-r--r--gcc/cp/pt.cc31
-rw-r--r--gcc/doc/extend.texi37
-rw-r--r--gcc/doc/invoke.texi28
-rw-r--r--gcc/fortran/ChangeLog4
-rw-r--r--gcc/gimple-range-cache.cc7
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/graphds.cc2
-rw-r--r--gcc/match.pd10
-rw-r--r--gcc/testsuite/ChangeLog88
-rw-r--r--gcc/testsuite/c-c++-common/attr-fd.c18
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-union7.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction112.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-eq14.C17
-rw-r--r--gcc/testsuite/g++.dg/pr94920-1.C17
-rw-r--r--gcc/testsuite/g++.dg/pr94920.C63
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/fd-4.c8
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/fd-5.c53
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/memcpy-2.c8
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr106394.c19
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/stdarg-3.c57
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/torture/stdarg-4.c329
-rw-r--r--gcc/testsuite/gcc.dg/pr106397.c17
-rw-r--r--gcc/testsuite/gcc.dg/pr23911.c3
-rw-r--r--gcc/testsuite/gcc.dg/pr94920-2.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/pr106038-1.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/pr106303.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/pr106347.c24
-rw-r--r--gcc/tree-ssa-dom.cc18
-rw-r--r--gcc/tree-ssa-loop-prefetch.cc27
-rw-r--r--gcc/tree-ssa-sccvn.cc11
-rw-r--r--gcc/tree-ssanames.cc3
-rw-r--r--gcc/tree-vect-stmts.cc5
-rw-r--r--gcc/value-query.cc10
-rw-r--r--gcc/value-range-pretty-print.cc41
-rw-r--r--gcc/value-range-pretty-print.h2
-rw-r--r--gcc/value-range-storage.h27
-rw-r--r--gcc/value-range.cc195
-rw-r--r--gcc/value-range.h194
-rw-r--r--gcc/value-relation.cc7
-rw-r--r--gcc/vr-values.cc15
-rwxr-xr-xlibgo/match.sh2
-rwxr-xr-xlibgo/testsuite/gotest2
-rw-r--r--libiberty/ChangeLog6
-rw-r--r--libiberty/_doprnt.c1
-rw-r--r--libsanitizer/ChangeLog7
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp44
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_solaris.h56
77 files changed, 2434 insertions, 414 deletions
diff --git a/ChangeLog b/ChangeLog
index 4842de2..65685ac 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2022-07-21 Sam Feifer <sfeifer@redhat.com>
+
+ * MAINTAINERS (Write After Approval): Add myself.
+
+2022-07-21 Marc Poulhiès <poulhies@adacore.com>
+
+ * MAINTAINERS: Add myself as Ada front end co-maintainer.
+
2022-07-19 Alexander Monakov <amonakov@ispras.ru>
* .gitignore: Do not ignore config.h.
diff --git a/MAINTAINERS b/MAINTAINERS
index e2db0cf..46c9e48 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -398,6 +398,7 @@ Chris Fairles <cfairles@gcc.gnu.org>
Alessandro Fanfarillo <fanfarillo.gcc@gmail.com>
Changpeng Fang <changpeng.fang@amd.com>
David Faust <david.faust@oracle.com>
+Sam Feifer <sfeifer@redhat.com>
Li Feng <nemokingdom@gmail.com>
Thomas Fitzsimmons <fitzsim@redhat.com>
Alexander Fomin <afomin.mailbox@gmail.com>
diff --git a/contrib/ChangeLog b/contrib/ChangeLog
index be06767..7df00c7 100644
--- a/contrib/ChangeLog
+++ b/contrib/ChangeLog
@@ -1,3 +1,14 @@
+2022-07-22 Martin Liska <mliska@suse.cz>
+
+ * git-commit-mklog.py: Do not parse -b argument.
+ Pass mklog_args as json environment variable.
+ * mklog.py: Parse GCC_MKLOG_ARGS and append it to sys.argv.
+ * prepare-commit-msg: Do not append GCC_MKLOG_ARGS to args.
+
+2022-07-22 Martin Liska <mliska@suse.cz>
+
+ * mklog.py: Use component: [PR xyz] only when one PR is used.
+
2022-07-04 Martin Liska <mliska@suse.cz>
* git-descr.sh: By default print revision for HEAD.
diff --git a/contrib/git-commit-mklog.py b/contrib/git-commit-mklog.py
index eda3fc4..c7e90c8 100755
--- a/contrib/git-commit-mklog.py
+++ b/contrib/git-commit-mklog.py
@@ -24,6 +24,7 @@
# to mklog.py script.
import argparse
+import json
import os
import subprocess
@@ -32,8 +33,7 @@ if __name__ == '__main__':
myenv = os.environ.copy()
parser = argparse.ArgumentParser(description='git-commit-mklog wrapped')
- parser.add_argument('-b', '--pr-numbers', action='store',
- type=lambda arg: arg.split(','), nargs='?',
+ parser.add_argument('-b', '--pr-numbers',
help='Add the specified PRs (comma separated)')
parser.add_argument('-p', '--fill-up-bug-titles', action='store_true',
help='Download title of mentioned PRs')
@@ -44,12 +44,13 @@ if __name__ == '__main__':
myenv['GCC_FORCE_MKLOG'] = '1'
mklog_args = []
if args.pr_numbers:
- mklog_args.append(f'-b {",".join(args.pr_numbers)}')
+ mklog_args += ['-b', args.pr_numbers]
if args.fill_up_bug_titles:
mklog_args.append('-p')
if mklog_args:
- myenv['GCC_MKLOG_ARGS'] = ' '.join(mklog_args)
+ # wrap mklog arguments with JSON
+ myenv['GCC_MKLOG_ARGS'] = json.dumps(mklog_args)
if args.co:
for author in args.co.split(','):
diff --git a/contrib/mklog.py b/contrib/mklog.py
index cd5ef0b..91c0dcd 100755
--- a/contrib/mklog.py
+++ b/contrib/mklog.py
@@ -28,6 +28,7 @@
import argparse
import datetime
+import json
import os
import re
import subprocess
@@ -73,8 +74,6 @@ PATCH must be generated using diff(1)'s -up or -cp options
script_folder = os.path.realpath(__file__)
root = os.path.dirname(os.path.dirname(script_folder))
-firstpr = ''
-
def find_changelog(path):
folder = os.path.split(path)[0]
@@ -157,12 +156,13 @@ def get_rel_path_if_prefixed(path, folder):
def generate_changelog(data, no_functions=False, fill_pr_titles=False,
additional_prs=None):
+ global prs
+ prs = []
+
changelogs = {}
changelog_list = []
- prs = []
out = ''
diff = PatchSet(data)
- global firstpr
if additional_prs:
for apr in additional_prs:
@@ -212,9 +212,6 @@ def generate_changelog(data, no_functions=False, fill_pr_titles=False,
if pr not in this_file_prs and pr2 not in prs:
prs.append(pr2)
- if prs:
- firstpr = prs[0]
-
if fill_pr_titles:
out += get_pr_titles(prs)
@@ -336,6 +333,10 @@ def skip_line_in_changelog(line):
if __name__ == '__main__':
+ extra_args = os.getenv('GCC_MKLOG_ARGS')
+ if extra_args:
+ sys.argv += json.loads(extra_args)
+
parser = argparse.ArgumentParser(description=help_message)
parser.add_argument('input', nargs='?',
help='Patch file (or missing, read standard input)')
@@ -372,11 +373,12 @@ if __name__ == '__main__':
end = lines[len(start):]
with open(args.changelog, 'w') as f:
if not start or not start[0]:
- # initial commit subject line 'component: [PRnnnnn]'
- m = prnum_regex.match(firstpr)
- if m:
- title = f'{m.group("comp")}: [PR{m.group("num")}]'
- start.insert(0, title)
+ if len(prs) == 1:
+ # initial commit subject line 'component: [PRnnnnn]'
+ m = prnum_regex.match(prs[0])
+ if m:
+ title = f'{m.group("comp")}: [PR{m.group("num")}]'
+ start.insert(0, title)
if start:
# append empty line
if start[-1] != '':
diff --git a/contrib/prepare-commit-msg b/contrib/prepare-commit-msg
index 5da8784..969847d 100755
--- a/contrib/prepare-commit-msg
+++ b/contrib/prepare-commit-msg
@@ -78,4 +78,4 @@ else
tee="cat"
fi
-git $cmd | $tee | git gcc-mklog $GCC_MKLOG_ARGS -c "$COMMIT_MSG_FILE"
+git $cmd | $tee | git gcc-mklog -c "$COMMIT_MSG_FILE"
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9a8bfd0..b090352 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,199 @@
+2022-07-24 Aldy Hernandez <aldyh@redhat.com>
+
+ * value-query.cc (range_query::get_value_range): Add assert.
+ * vr-values.cc (vr_values::range_of_expr): Make sure we don't ICE
+ on unsupported types in vr_values.
+ (simplify_using_ranges::simplify): Same.
+
+2022-07-24 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssanames.cc (get_nonzero_bits): Return -1 for unsupported
+ types.
+ * value-query.cc (get_ssa_name_range_info): Remove precision check.
+
+2022-07-24 Aldy Hernandez <aldyh@redhat.com>
+
+ * value-relation.cc (value_relation::set_relation): Remove assert.
+ (path_oracle::register_relation): Exit when trying to register
+ same SSA name relations.
+
+2022-07-24 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-cache.cc (ranger_cache::edge_range): Convert to vrange.
+ (ranger_cache::range_from_dom): Same.
+ * tree-ssa-dom.cc
+ (dom_opt_dom_walker::set_global_ranges_from_unreachable_edges): Same.
+
+2022-07-24 Roger Sayle <roger@nextmovesoftware.com>
+ H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/106303
+ PR target/106347
+ * config/i386/i386-features.cc (make_vector_copies): Move from
+ general_scalar_chain to scalar_chain.
+ (convert_reg): Likewise.
+ (convert_insn_common): New scalar_chain method split out from
+ general_scalar_chain convert_insn.
+ (convert_registers): Move from general_scalar_chain to
+ scalar_chain.
+ (scalar_chain::convert): Call convert_insn_common before calling
+ convert_insn.
+ (timode_remove_non_convertible_regs): Iterate until there are
+ no further changes to the candidates.
+ * config/i386/i386-features.h (scalar_chain::hash_map): Move
+ from general_scalar_chain.
+ (scalar_chain::convert_reg): Likewise.
+ (scalar_chain::convert_insn_common): New shared method.
+ (scalar_chain::make_vector_copies): Move from general_scalar_chain.
+ (scalar_chain::convert_registers): Likewise. No longer virtual.
+ (general_scalar_chain::hash_map): Delete. Moved to scalar_chain.
+ (general_scalar_chain::convert_reg): Likewise.
+ (general_scalar_chain::make_vector_copies): Likewise.
+ (general_scalar_chain::convert_registers): Delete virtual method.
+ (timode_scalar_chain::convert_registers): Likewise.
+
+2022-07-23 Immad Mir <mirimmad@outlook.com>
+
+ * doc/extend.texi: Add fd_arg, fd_arg_read and fd_arg_write under
+ "Common Function Attributes" section.
+ * doc/invoke.texi: Add docs to -Wanalyzer-fd-access-mode-mismatch,
+ -Wanalyzer-use-after-close, -Wanalyzer-fd-use-without-check that these
+ warnings may be emitted through usage of three function attributes used
+ for static analysis of file descriptors namely fd_arg, fd_arg_read and
+ fd_arg_write.
+
+2022-07-22 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp>
+
+ * config/xtensa/xtensa.md (*masktrue_const_bitcmpl):
+ Add a new insn_and_split pattern, and a few split patterns for
+ spacial cases.
+
+2022-07-22 Richard Sandiford <richard.sandiford@arm.com>
+
+ * graphds.cc (graphds_scc): Fix algorithm attribution.
+
+2022-07-22 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/106403
+ * tree-ssa-sccvn.cc (vn_reference_lookup_3): Move stored
+ value valueization after check for IFN_MASKED_STORE or
+ IFN_LEN_STORE.
+
+2022-07-22 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/106397
+ * tree-ssa-loop-prefetch.cc (emit_mfence_after_loop): Do
+ not update SSA form here.
+ (mark_nontemporal_stores): Return whether we marked any
+ non-temporal stores and inserted mfence.
+ (loop_prefetch_arrays): Note when we need to update SSA.
+ (tree_ssa_prefetch_arrays): Perform required (LC) SSA update
+ at the end of the pass.
+
+2022-07-22 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/106387
+ * tree-vect-stmts.cc (vectorizable_load): Use make_ssa_name
+ if ptr is not an SSA name.
+
+2022-07-22 liuhongt <hongtao.liu@intel.com>
+
+ PR target/106038
+ * config/i386/mmx.md (<code><mode>3): New define_expand, it's
+ original "<code><mode>3".
+ (*<code><mode>3): New define_insn, it's original
+ "<code><mode>3" be extended to handle memory and immediate
+ operand with ix86_binary_operator_ok. Also adjust define_split
+ after it.
+ (mmxinsnmode): New mode attribute.
+ (*mov<mode>_imm): Refactor with mmxinsnmode.
+ * config/i386/predicates.md
+ (register_or_x86_64_const_vector_operand): New predicate.
+
+2022-07-22 Will Schmidt <will_schmidt@vnet.ibm.com>
+
+ * config/rs6000/altivec.md:
+ (vstrir_code_<mode>): Rename to...
+ (vstrir_direct_<mode>): ... this.
+ (vstrir_p_code_<mode>): Rename to...
+ (vstrir_p_direct_<mode>): ... this.
+ (vstril_code_<mode>): Rename to...
+ (vstril_direct_<mode>): ... this.
+ (vstril_p_code_<mode>): Rename to...
+ (vstril_p_direct_<mode>): ... this.
+
+2022-07-22 Will Schmidt <will_schmidt@vnet.ibm.com>
+
+ * config/rs6000/rs6000-c.cc: Update comments.
+ (rs6000_target_modify_macros): Remove bu_mask references.
+ (rs6000_define_or_undefine_macro): Replace bu_mask reference
+ with a rs6000_cpu value check.
+ (rs6000_cpu_cpp_builtins): Remove rs6000_builtin_mask_calculate()
+ parameter from call to rs6000_target_modify_macros.
+ * config/rs6000/rs6000-protos.h (rs6000_target_modify_macros,
+ rs6000_target_modify_macros_ptr): Remove parameter from extern
+ for the prototype.
+ * config/rs6000/rs6000.cc (rs6000_target_modify_macros_ptr): Remove
+ parameter from prototype, update calls to this function.
+ (rs6000_print_builtin_options): Remove prototype, call and function.
+ (rs6000_builtin_mask_calculate): Remove function.
+ (rs6000_debug_reg_global): Remove call to rs6000_print_builtin_options.
+ (rs6000_option_override_internal): Remove rs6000_builtin_mask var
+ and builtin_mask debug output.
+ (rs6000_builtin_mask_names): Remove.
+ (rs6000_pragma_target_parse): Remove prev_bumask, cur_bumask,
+ diff_bumask references; Update calls to rs6000_target_modify_ptr.
+ * config/rs6000/rs6000.opt (rs6000_builtin_mask): Remove.
+
+2022-07-21 Sam Feifer <sfeifer@redhat.com>
+
+ PR tree-optimization/94920
+ * match.pd (x >= 0 ? x : 0) + (x <= 0 ? -x : 0): New simplification.
+ (x <= 0 ? -x : 0): New simplification.
+
+2022-07-21 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ Revert:
+ 2022-07-19 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ * tree-ssa-forwprop.cc (simplify_permutation): Use lhs type
+ instead of TREE_TYPE (arg0) as result type in folding VEC_PERM_EXPR.
+
+2022-07-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/106379
+ * match.pd (~(a ^ b) -> a == b): New pattern.
+
+2022-07-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/106378
+ * tree-ssa-dse.cc (initialize_ao_ref_for_dse): Handle
+ LEN_STORE, add mode to initialize a may-def and handle
+ MASK_STORE that way.
+ (dse_optimize_stmt): Query may-defs. Handle internal
+ functions LEN_STORE and MASK_STORE similar to how
+ we handle memory builtins but without byte tracking.
+
+2022-07-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/106365
+ * tree-ssa-sccvn.cc (pd_data::rhs_off): New field determining
+ the offset to start encoding of RHS from.
+ (vn_walk_cb_data::vn_walk_cb_data): Initialize it.
+ (vn_walk_cb_data::push_partial_def): Allow the first partial
+ definition to be fully providing the def. Offset RHS
+ before encoding if requested.
+ (vn_reference_lookup_3): Initialize def_rhs everywhere.
+ Add support for .MASK_STORE and .LEN_STORE (partial) definitions.
+
+2022-07-21 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-alias.cc (ref_maybe_used_by_call_p_1): Special-case
+ store internal functions and IFN_MASK_LOAD, IFN_LEN_LOAD
+ and IFN_MASK_LOAD_LANES.
+ (call_may_clobber_ref_p_1): Special-case IFN_MASK_STORE,
+ IFN_LEN_STORE and IFN_MASK_STORE_LANES.
+
2022-07-20 Alexander Monakov <amonakov@ispras.ru>
PR rtl-optimization/101347
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index ace4919..c35b552 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20220721
+20220725
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog
index a94593e..59642a6 100644
--- a/gcc/analyzer/ChangeLog
+++ b/gcc/analyzer/ChangeLog
@@ -1,3 +1,61 @@
+2022-07-23 Immad Mir <mirimmad@outlook.com>
+
+ * sm-fd.cc (fd_param_diagnostic): New diagnostic class.
+ (fd_access_mode_mismatch): Change inheritance from fd_diagnostic
+ to fd_param_diagnostic. Add new overloaded constructor.
+ (fd_use_after_close): Likewise.
+ (unchecked_use_of_fd): Likewise and also change name to fd_use_without_check.
+ (double_close): Change name to fd_double_close.
+ (enum access_directions): New.
+ (fd_state_machine::on_stmt): Handle calls to function with the
+ new three function attributes.
+ (fd_state_machine::check_for_fd_attrs): New.
+ (fd_state_machine::on_open): Use the new overloaded constructors
+ of diagnostic classes.
+
+2022-07-22 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/106413
+ * varargs.cc (region_model::impl_call_va_start): Avoid iterating
+ through non-existant variadic arguments by initializing the
+ impl_region to "UNKNOWN" if the va_start occurs in the top-level
+ function to the analysis.
+
+2022-07-22 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/106401
+ * store.cc (binding_cluster::binding_cluster): Remove overzealous
+ assertion; we're checking for tracked_p in
+ store::get_or_create_cluster.
+
+2022-07-22 Tim Lange <mail@tim-lange.me>
+
+ PR analyzer/106394
+ * region-model.cc (capacity_compatible_with_type): Always return true
+ if alloc_size is zero.
+
+2022-07-21 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/106383
+ * varargs.cc (region_model::impl_call_va_arg): When determining if
+ we're doing interprocedural analysis, use the stack depth of the
+ frame in which va_start was called, rather than the current stack
+ depth.
+
+2022-07-21 David Malcolm <dmalcolm@redhat.com>
+
+ * sm-taint.cc (tainted_array_index::emit): Bulletproof against
+ NULL m_arg.
+ (tainted_array_index::describe_final_event): Likewise.
+ (tainted_size::emit): Likewise.
+ (tainted_size::describe_final_event): Likewise.
+
+2022-07-21 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/106374
+ * region.cc (decl_region::get_svalue_for_initializer): Bail out on
+ untracked regions.
+
2022-07-20 David Malcolm <dmalcolm@redhat.com>
PR analyzer/106373
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 5bb7112..f7df2fc 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -2956,7 +2956,7 @@ capacity_compatible_with_type (tree cst, tree pointee_size_tree,
unsigned HOST_WIDE_INT alloc_size = TREE_INT_CST_LOW (cst);
if (is_struct)
- return alloc_size >= pointee_size;
+ return alloc_size == 0 || alloc_size >= pointee_size;
return alloc_size % pointee_size == 0;
}
diff --git a/gcc/analyzer/sm-fd.cc b/gcc/analyzer/sm-fd.cc
index 8e4300b..c3dac48 100644
--- a/gcc/analyzer/sm-fd.cc
+++ b/gcc/analyzer/sm-fd.cc
@@ -39,10 +39,13 @@ along with GCC; see the file COPYING3. If not see
#include "analyzer/analyzer-selftests.h"
#include "tristate.h"
#include "selftest.h"
+#include "stringpool.h"
+#include "attribs.h"
#include "analyzer/call-string.h"
#include "analyzer/program-point.h"
#include "analyzer/store.h"
#include "analyzer/region-model.h"
+#include "bitmap.h"
#if ENABLE_ANALYZER
@@ -59,6 +62,13 @@ enum access_mode
WRITE_ONLY
};
+enum access_directions
+{
+ DIRS_READ_WRITE,
+ DIRS_READ,
+ DIRS_WRITE
+};
+
class fd_state_machine : public state_machine
{
public:
@@ -146,7 +156,7 @@ private:
void check_for_open_fd (sm_context *sm_ctxt, const supernode *node,
const gimple *stmt, const gcall *call,
const tree callee_fndecl,
- enum access_direction access_fn) const;
+ enum access_directions access_fn) const;
void make_valid_transitions_on_condition (sm_context *sm_ctxt,
const supernode *node,
@@ -156,6 +166,10 @@ private:
const supernode *node,
const gimple *stmt,
const svalue *lhs) const;
+ void check_for_fd_attrs (sm_context *sm_ctxt, const supernode *node,
+ const gimple *stmt, const gcall *call,
+ const tree callee_fndecl, const char *attr_name,
+ access_directions fd_attr_access_dir) const;
};
/* Base diagnostic class relative to fd_state_machine. */
@@ -220,6 +234,70 @@ protected:
tree m_arg;
};
+class fd_param_diagnostic : public fd_diagnostic
+{
+public:
+ fd_param_diagnostic (const fd_state_machine &sm, tree arg, tree callee_fndecl,
+ const char *attr_name, int arg_idx)
+ : fd_diagnostic (sm, arg), m_callee_fndecl (callee_fndecl),
+ m_attr_name (attr_name), m_arg_idx (arg_idx)
+ {
+ }
+
+ fd_param_diagnostic (const fd_state_machine &sm, tree arg, tree callee_fndecl)
+ : fd_diagnostic (sm, arg), m_callee_fndecl (callee_fndecl),
+ m_attr_name (NULL), m_arg_idx (-1)
+ {
+ }
+
+ bool
+ subclass_equal_p (const pending_diagnostic &base_other) const override
+ {
+ const fd_param_diagnostic &sub_other
+ = (const fd_param_diagnostic &)base_other;
+ return (same_tree_p (m_arg, sub_other.m_arg)
+ && same_tree_p (m_callee_fndecl, sub_other.m_callee_fndecl)
+ && m_arg_idx == sub_other.m_arg_idx
+ && ((m_attr_name)
+ ? (strcmp (m_attr_name, sub_other.m_attr_name) == 0)
+ : true));
+ }
+
+ void
+ inform_filedescriptor_attribute (access_directions fd_dir)
+ {
+
+ if (m_attr_name)
+ switch (fd_dir)
+ {
+ case DIRS_READ_WRITE:
+ inform (DECL_SOURCE_LOCATION (m_callee_fndecl),
+ "argument %d of %qD must be an open file descriptor, due to "
+ "%<__attribute__((%s(%d)))%>",
+ m_arg_idx + 1, m_callee_fndecl, m_attr_name, m_arg_idx + 1);
+ break;
+ case DIRS_WRITE:
+ inform (DECL_SOURCE_LOCATION (m_callee_fndecl),
+ "argument %d of %qD must be a readable file descriptor, due "
+ "to %<__attribute__((%s(%d)))%>",
+ m_arg_idx + 1, m_callee_fndecl, m_attr_name, m_arg_idx + 1);
+ break;
+ case DIRS_READ:
+ inform (DECL_SOURCE_LOCATION (m_callee_fndecl),
+ "argument %d of %qD must be a writable file descriptor, due "
+ "to %<__attribute__((%s(%d)))%>",
+ m_arg_idx + 1, m_callee_fndecl, m_attr_name, m_arg_idx + 1);
+ break;
+ }
+ }
+
+protected:
+ tree m_callee_fndecl;
+ const char *m_attr_name;
+ /* ARG_IDX is 0-based. */
+ int m_arg_idx;
+};
+
class fd_leak : public fd_diagnostic
{
public:
@@ -290,18 +368,26 @@ private:
diagnostic_event_id_t m_open_event;
};
-class fd_access_mode_mismatch : public fd_diagnostic
+class fd_access_mode_mismatch : public fd_param_diagnostic
{
public:
fd_access_mode_mismatch (const fd_state_machine &sm, tree arg,
- enum access_direction fd_dir,
- const tree callee_fndecl)
- : fd_diagnostic (sm, arg), m_fd_dir (fd_dir),
- m_callee_fndecl (callee_fndecl)
+ enum access_directions fd_dir,
+ const tree callee_fndecl, const char *attr_name,
+ int arg_idx)
+ : fd_param_diagnostic (sm, arg, callee_fndecl, attr_name, arg_idx),
+ m_fd_dir (fd_dir)
{
}
+ fd_access_mode_mismatch (const fd_state_machine &sm, tree arg,
+ enum access_directions fd_dir,
+ const tree callee_fndecl)
+ : fd_param_diagnostic (sm, arg, callee_fndecl), m_fd_dir (fd_dir)
+ {
+ }
+
const char *
get_kind () const final override
{
@@ -317,29 +403,25 @@ public:
bool
emit (rich_location *rich_loc) final override
{
+ bool warned;
switch (m_fd_dir)
{
- case DIR_READ:
- return warning_at (rich_loc, get_controlling_option (),
- "%qE on %<read-only%> file descriptor %qE",
+ case DIRS_READ:
+ warned = warning_at (rich_loc, get_controlling_option (),
+ "%qE on read-only file descriptor %qE",
m_callee_fndecl, m_arg);
- case DIR_WRITE:
- return warning_at (rich_loc, get_controlling_option (),
- "%qE on %<write-only%> file descriptor %qE",
+ break;
+ case DIRS_WRITE:
+ warned = warning_at (rich_loc, get_controlling_option (),
+ "%qE on write-only file descriptor %qE",
m_callee_fndecl, m_arg);
+ break;
default:
gcc_unreachable ();
}
- }
-
- bool
- subclass_equal_p (const pending_diagnostic &base_other) const override
- {
- const fd_access_mode_mismatch &sub_other
- = (const fd_access_mode_mismatch &)base_other;
- return (same_tree_p (m_arg, sub_other.m_arg)
- && m_callee_fndecl == sub_other.m_callee_fndecl
- && m_fd_dir == sub_other.m_fd_dir);
+ if (warned)
+ inform_filedescriptor_attribute (m_fd_dir);
+ return warned;
}
label_text
@@ -347,11 +429,11 @@ public:
{
switch (m_fd_dir)
{
- case DIR_READ:
- return ev.formatted_print ("%qE on %<read-only%> file descriptor %qE",
+ case DIRS_READ:
+ return ev.formatted_print ("%qE on read-only file descriptor %qE",
m_callee_fndecl, m_arg);
- case DIR_WRITE:
- return ev.formatted_print ("%qE on %<write-only%> file descriptor %qE",
+ case DIRS_WRITE:
+ return ev.formatted_print ("%qE on write-only file descriptor %qE",
m_callee_fndecl, m_arg);
default:
gcc_unreachable ();
@@ -359,21 +441,20 @@ public:
}
private:
- enum access_direction m_fd_dir;
- const tree m_callee_fndecl;
+ enum access_directions m_fd_dir;
};
-class double_close : public fd_diagnostic
+class fd_double_close : public fd_diagnostic
{
public:
- double_close (const fd_state_machine &sm, tree arg) : fd_diagnostic (sm, arg)
+ fd_double_close (const fd_state_machine &sm, tree arg) : fd_diagnostic (sm, arg)
{
}
const char *
get_kind () const final override
{
- return "double_close";
+ return "fd_double_close";
}
int
@@ -418,12 +499,19 @@ private:
diagnostic_event_id_t m_first_close_event;
};
-class fd_use_after_close : public fd_diagnostic
+class fd_use_after_close : public fd_param_diagnostic
{
public:
fd_use_after_close (const fd_state_machine &sm, tree arg,
+ const tree callee_fndecl, const char *attr_name,
+ int arg_idx)
+ : fd_param_diagnostic (sm, arg, callee_fndecl, attr_name, arg_idx)
+ {
+ }
+
+ fd_use_after_close (const fd_state_machine &sm, tree arg,
const tree callee_fndecl)
- : fd_diagnostic (sm, arg), m_callee_fndecl (callee_fndecl)
+ : fd_param_diagnostic (sm, arg, callee_fndecl)
{
}
@@ -442,9 +530,13 @@ public:
bool
emit (rich_location *rich_loc) final override
{
- return warning_at (rich_loc, get_controlling_option (),
+ bool warned;
+ warned = warning_at (rich_loc, get_controlling_option (),
"%qE on closed file descriptor %qE", m_callee_fndecl,
m_arg);
+ if (warned)
+ inform_filedescriptor_attribute (DIRS_READ_WRITE);
+ return warned;
}
label_text
@@ -466,32 +558,38 @@ public:
describe_final_event (const evdesc::final_event &ev) final override
{
if (m_first_close_event.known_p ())
- return ev.formatted_print (
- "%qE on closed file descriptor %qE; %qs was at %@", m_callee_fndecl,
- m_arg, "close", &m_first_close_event);
- else
- return ev.formatted_print ("%qE on closed file descriptor %qE",
- m_callee_fndecl, m_arg);
+ return ev.formatted_print (
+ "%qE on closed file descriptor %qE; %qs was at %@", m_callee_fndecl,
+ m_arg, "close", &m_first_close_event);
+ else
+ return ev.formatted_print ("%qE on closed file descriptor %qE",
+ m_callee_fndecl, m_arg);
}
private:
diagnostic_event_id_t m_first_close_event;
- const tree m_callee_fndecl;
};
-class unchecked_use_of_fd : public fd_diagnostic
+class fd_use_without_check : public fd_param_diagnostic
{
public:
- unchecked_use_of_fd (const fd_state_machine &sm, tree arg,
- const tree callee_fndecl)
- : fd_diagnostic (sm, arg), m_callee_fndecl (callee_fndecl)
+ fd_use_without_check (const fd_state_machine &sm, tree arg,
+ const tree callee_fndecl, const char *attr_name,
+ int arg_idx)
+ : fd_param_diagnostic (sm, arg, callee_fndecl, attr_name, arg_idx)
+ {
+ }
+
+ fd_use_without_check (const fd_state_machine &sm, tree arg,
+ const tree callee_fndecl)
+ : fd_param_diagnostic (sm, arg, callee_fndecl)
{
}
const char *
get_kind () const final override
{
- return "unchecked_use_of_fd";
+ return "fd_use_without_check";
}
int
@@ -503,18 +601,13 @@ public:
bool
emit (rich_location *rich_loc) final override
{
- return warning_at (rich_loc, get_controlling_option (),
- "%qE on possibly invalid file descriptor %qE",
- m_callee_fndecl, m_arg);
- }
-
- bool
- subclass_equal_p (const pending_diagnostic &base_other) const override
- {
- const unchecked_use_of_fd &sub_other
- = (const unchecked_use_of_fd &)base_other;
- return (same_tree_p (m_arg, sub_other.m_arg)
- && m_callee_fndecl == sub_other.m_callee_fndecl);
+ bool warned;
+ warned = warning_at (rich_loc, get_controlling_option (),
+ "%qE on possibly invalid file descriptor %qE",
+ m_callee_fndecl, m_arg);
+ if (warned)
+ inform_filedescriptor_attribute (DIRS_READ_WRITE);
+ return warned;
}
label_text
@@ -541,8 +634,7 @@ public:
}
private:
- diagnostic_event_id_t m_first_open_event;
- const tree m_callee_fndecl;
+ diagnostic_event_id_t m_first_open_event;
};
fd_state_machine::fd_state_machine (logger *logger)
@@ -647,12 +739,118 @@ fd_state_machine::on_stmt (sm_context *sm_ctxt, const supernode *node,
on_read (sm_ctxt, node, stmt, call, callee_fndecl);
return true;
} // "read"
+
+
+ {
+ // Handle __attribute__((fd_arg))
+
+ check_for_fd_attrs (sm_ctxt, node, stmt, call, callee_fndecl,
+ "fd_arg", DIRS_READ_WRITE);
+
+ // Handle __attribute__((fd_arg_read))
+
+ check_for_fd_attrs (sm_ctxt, node, stmt, call, callee_fndecl,
+ "fd_arg_read", DIRS_READ);
+
+ // Handle __attribute__((fd_arg_write))
+
+ check_for_fd_attrs (sm_ctxt, node, stmt, call, callee_fndecl,
+ "fd_arg_write", DIRS_WRITE);
+ }
}
return false;
}
void
+fd_state_machine::check_for_fd_attrs (
+ sm_context *sm_ctxt, const supernode *node, const gimple *stmt,
+ const gcall *call, const tree callee_fndecl, const char *attr_name,
+ access_directions fd_attr_access_dir) const
+{
+
+ tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (callee_fndecl));
+ attrs = lookup_attribute (attr_name, attrs);
+ if (!attrs)
+ return;
+
+ if (!TREE_VALUE (attrs))
+ return;
+
+ auto_bitmap argmap;
+
+ for (tree idx = TREE_VALUE (attrs); idx; idx = TREE_CHAIN (idx))
+ {
+ unsigned int val = TREE_INT_CST_LOW (TREE_VALUE (idx)) - 1;
+ bitmap_set_bit (argmap, val);
+ }
+ if (bitmap_empty_p (argmap))
+ return;
+
+ for (unsigned arg_idx = 0; arg_idx < gimple_call_num_args (call); arg_idx++)
+ {
+ tree arg = gimple_call_arg (call, arg_idx);
+ tree diag_arg = sm_ctxt->get_diagnostic_tree (arg);
+ state_t state = sm_ctxt->get_state (stmt, arg);
+ bool bit_set = bitmap_bit_p (argmap, arg_idx);
+ if (TREE_CODE (TREE_TYPE (arg)) != INTEGER_TYPE)
+ continue;
+ if (bit_set) // Check if arg_idx is marked by any of the file descriptor
+ // attributes
+ {
+
+ if (is_closed_fd_p (state))
+ {
+
+ sm_ctxt->warn (node, stmt, arg,
+ new fd_use_after_close (*this, diag_arg,
+ callee_fndecl, attr_name,
+ arg_idx));
+ continue;
+ }
+
+ if (!(is_valid_fd_p (state) || (state == m_stop)))
+ {
+ if (!is_constant_fd_p (state))
+ sm_ctxt->warn (node, stmt, arg,
+ new fd_use_without_check (*this, diag_arg,
+ callee_fndecl, attr_name,
+ arg_idx));
+ }
+
+ switch (fd_attr_access_dir)
+ {
+ case DIRS_READ_WRITE:
+ break;
+ case DIRS_READ:
+
+ if (is_writeonly_fd_p (state))
+ {
+ sm_ctxt->warn (
+ node, stmt, arg,
+ new fd_access_mode_mismatch (*this, diag_arg, DIRS_WRITE,
+ callee_fndecl, attr_name, arg_idx));
+ }
+
+ break;
+ case DIRS_WRITE:
+
+ if (is_readonly_fd_p (state))
+ {
+ sm_ctxt->warn (
+ node, stmt, arg,
+ new fd_access_mode_mismatch (*this, diag_arg, DIRS_READ,
+ callee_fndecl, attr_name, arg_idx));
+ }
+
+ break;
+ }
+ }
+ }
+}
+
+
+void
fd_state_machine::on_open (sm_context *sm_ctxt, const supernode *node,
const gimple *stmt, const gcall *call) const
{
@@ -706,7 +904,7 @@ fd_state_machine::on_close (sm_context *sm_ctxt, const supernode *node,
if (is_closed_fd_p (state))
{
- sm_ctxt->warn (node, stmt, arg, new double_close (*this, diag_arg));
+ sm_ctxt->warn (node, stmt, arg, new fd_double_close (*this, diag_arg));
sm_ctxt->set_next_state (stmt, arg, m_stop);
}
}
@@ -715,21 +913,21 @@ fd_state_machine::on_read (sm_context *sm_ctxt, const supernode *node,
const gimple *stmt, const gcall *call,
const tree callee_fndecl) const
{
- check_for_open_fd (sm_ctxt, node, stmt, call, callee_fndecl, DIR_READ);
+ check_for_open_fd (sm_ctxt, node, stmt, call, callee_fndecl, DIRS_READ);
}
void
fd_state_machine::on_write (sm_context *sm_ctxt, const supernode *node,
const gimple *stmt, const gcall *call,
const tree callee_fndecl) const
{
- check_for_open_fd (sm_ctxt, node, stmt, call, callee_fndecl, DIR_WRITE);
+ check_for_open_fd (sm_ctxt, node, stmt, call, callee_fndecl, DIRS_WRITE);
}
void
fd_state_machine::check_for_open_fd (
sm_context *sm_ctxt, const supernode *node, const gimple *stmt,
const gcall *call, const tree callee_fndecl,
- enum access_direction callee_fndecl_dir) const
+ enum access_directions callee_fndecl_dir) const
{
tree arg = gimple_call_arg (call, 0);
tree diag_arg = sm_ctxt->get_diagnostic_tree (arg);
@@ -748,30 +946,32 @@ fd_state_machine::check_for_open_fd (
if (!is_constant_fd_p (state))
sm_ctxt->warn (
node, stmt, arg,
- new unchecked_use_of_fd (*this, diag_arg, callee_fndecl));
+ new fd_use_without_check (*this, diag_arg, callee_fndecl));
}
switch (callee_fndecl_dir)
{
- case DIR_READ:
+ case DIRS_READ:
if (is_writeonly_fd_p (state))
{
tree diag_arg = sm_ctxt->get_diagnostic_tree (arg);
sm_ctxt->warn (node, stmt, arg,
new fd_access_mode_mismatch (
- *this, diag_arg, DIR_WRITE, callee_fndecl));
+ *this, diag_arg, DIRS_WRITE, callee_fndecl));
}
break;
- case DIR_WRITE:
+ case DIRS_WRITE:
if (is_readonly_fd_p (state))
{
tree diag_arg = sm_ctxt->get_diagnostic_tree (arg);
sm_ctxt->warn (node, stmt, arg,
new fd_access_mode_mismatch (
- *this, diag_arg, DIR_READ, callee_fndecl));
+ *this, diag_arg, DIRS_READ, callee_fndecl));
}
break;
+ default:
+ gcc_unreachable ();
}
}
}
diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc
index e3dabf3..0b3fb37 100644
--- a/gcc/analyzer/store.cc
+++ b/gcc/analyzer/store.cc
@@ -1107,7 +1107,6 @@ binding_cluster::binding_cluster (const region *base_region)
: m_base_region (base_region), m_map (),
m_escaped (false), m_touched (false)
{
- gcc_assert (base_region->tracked_p ());
}
/* binding_cluster's copy ctor. */
diff --git a/gcc/analyzer/varargs.cc b/gcc/analyzer/varargs.cc
index c92a56d..9400086 100644
--- a/gcc/analyzer/varargs.cc
+++ b/gcc/analyzer/varargs.cc
@@ -667,11 +667,27 @@ region_model::impl_call_va_start (const call_details &cd)
const svalue *ptr_to_impl_reg = m_mgr->get_ptr_svalue (NULL_TREE, impl_reg);
set_value (out_reg, ptr_to_impl_reg, cd.get_ctxt ());
- /* "*(&IMPL_REGION) = VA_LIST_VAL (0);". */
- const region *init_var_arg_reg
- = m_mgr->get_var_arg_region (get_current_frame (), 0);
- const svalue *ap_sval = m_mgr->get_ptr_svalue (NULL_TREE, init_var_arg_reg);
- set_value (impl_reg, ap_sval, cd.get_ctxt ());
+ if (get_stack_depth () > 1)
+ {
+ /* The interprocedural case: the frame containing the va_start call
+ will have been populated with any variadic aruguments.
+ Initialize IMPL_REGION with a ptr to var_arg_region 0. */
+ const region *init_var_arg_reg
+ = m_mgr->get_var_arg_region (get_current_frame (), 0);
+ const svalue *ap_sval
+ = m_mgr->get_ptr_svalue (NULL_TREE, init_var_arg_reg);
+ set_value (impl_reg, ap_sval, cd.get_ctxt ());
+ }
+ else
+ {
+ /* The frame containing va_start is an entry-point to the analysis,
+ so there won't be any specific var_arg_regions populated within it.
+ Initialize IMPL_REGION as the UNKNOWN_SVALUE to avoid state
+ explosions on repeated calls to va_arg. */
+ const svalue *unknown_sval
+ = m_mgr->get_or_create_unknown_svalue (NULL_TREE);
+ set_value (impl_reg, unknown_sval, cd.get_ctxt ());
+ }
}
/* Handle the on_call_pre part of "__builtin_va_copy". */
@@ -971,7 +987,7 @@ region_model::impl_call_va_arg (const call_details &cd)
const frame_region *frame_reg = arg_reg->get_frame_region ();
unsigned next_arg_idx = arg_reg->get_index ();
- if (get_stack_depth () > 1)
+ if (frame_reg->get_stack_depth () > 1)
{
/* The interprocedural case: the called frame will have been
populated with any variadic aruguments.
@@ -1009,7 +1025,7 @@ region_model::impl_call_va_arg (const call_details &cd)
any specific var_arg_regions populated within it.
We already have a conjured_svalue for the result, so leave
it untouched. */
- gcc_assert (get_stack_depth () == 1);
+ gcc_assert (frame_reg->get_stack_depth () == 1);
}
if (saw_problem)
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index ade553f..9e5f83c 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,9 @@
+2022-07-23 Immad Mir <mirimmad@outlook.com>
+
+ * c-attribs.cc: (c_common_attribute_table): add three new attributes
+ namely: fd_arg, fd_arg_read and fd_arg_write.
+ (handle_fd_arg_attribute): New.
+
2022-07-15 Marek Polacek <polacek@redhat.com>
PR c++/104477
diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index c8d9672..e4f1d35 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -173,6 +173,7 @@ static tree handle_objc_nullability_attribute (tree *, tree, tree, int, bool *);
static tree handle_signed_bool_precision_attribute (tree *, tree, tree, int,
bool *);
static tree handle_retain_attribute (tree *, tree, tree, int, bool *);
+static tree handle_fd_arg_attribute (tree *, tree, tree, int, bool *);
/* Helper to define attribute exclusions. */
#define ATTR_EXCL(name, function, type, variable) \
@@ -555,6 +556,12 @@ const struct attribute_spec c_common_attribute_table[] =
handle_dealloc_attribute, NULL },
{ "tainted_args", 0, 0, true, false, false, false,
handle_tainted_args_attribute, NULL },
+ { "fd_arg", 1, 1, false, true, true, false,
+ handle_fd_arg_attribute, NULL},
+ { "fd_arg_read", 1, 1, false, true, true, false,
+ handle_fd_arg_attribute, NULL},
+ { "fd_arg_write", 1, 1, false, true, true, false,
+ handle_fd_arg_attribute, NULL},
{ NULL, 0, 0, false, false, false, false, NULL, NULL }
};
@@ -4521,6 +4528,30 @@ handle_nonnull_attribute (tree *node, tree name,
return NULL_TREE;
}
+/* Handle the "fd_arg", "fd_arg_read" and "fd_arg_write" attributes */
+
+static tree
+handle_fd_arg_attribute (tree *node, tree name, tree args,
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ tree type = *node;
+ if (!args)
+ {
+ if (!prototype_p (type))
+ {
+ error ("%qE attribute without arguments on a non-prototype", name);
+ *no_add_attrs = true;
+ }
+ return NULL_TREE;
+ }
+
+ if (positional_argument (*node, name, TREE_VALUE (args), INTEGER_TYPE))
+ return NULL_TREE;
+
+ *no_add_attrs = true;
+ return NULL_TREE;
+}
+
/* Handle the "nonstring" variable attribute. */
static tree
diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc
index 813b203..aa5de71 100644
--- a/gcc/config/i386/i386-features.cc
+++ b/gcc/config/i386/i386-features.cc
@@ -708,7 +708,7 @@ gen_gpr_to_xmm_move_src (enum machine_mode vmode, rtx gpr)
and replace its uses in a chain. */
void
-general_scalar_chain::make_vector_copies (rtx_insn *insn, rtx reg)
+scalar_chain::make_vector_copies (rtx_insn *insn, rtx reg)
{
rtx vreg = *defs_map.get (reg);
@@ -772,7 +772,7 @@ general_scalar_chain::make_vector_copies (rtx_insn *insn, rtx reg)
scalar uses outside of the chain. */
void
-general_scalar_chain::convert_reg (rtx_insn *insn, rtx dst, rtx src)
+scalar_chain::convert_reg (rtx_insn *insn, rtx dst, rtx src)
{
start_sequence ();
if (!TARGET_INTER_UNIT_MOVES_FROM_VEC)
@@ -973,10 +973,10 @@ scalar_chain::convert_compare (rtx op1, rtx op2, rtx_insn *insn)
UNSPEC_PTEST);
}
-/* Convert INSN to vector mode. */
+/* Helper function for converting INSN to vector mode. */
void
-general_scalar_chain::convert_insn (rtx_insn *insn)
+scalar_chain::convert_insn_common (rtx_insn *insn)
{
/* Generate copies for out-of-chain uses of defs and adjust debug uses. */
for (df_ref ref = DF_INSN_DEFS (insn); ref; ref = DF_REF_NEXT_LOC (ref))
@@ -1037,7 +1037,13 @@ general_scalar_chain::convert_insn (rtx_insn *insn)
XEXP (note, 0) = *vreg;
*DF_REF_REAL_LOC (ref) = *vreg;
}
+}
+
+/* Convert INSN to vector mode. */
+void
+general_scalar_chain::convert_insn (rtx_insn *insn)
+{
rtx def_set = single_set (insn);
rtx src = SET_SRC (def_set);
rtx dst = SET_DEST (def_set);
@@ -1475,7 +1481,7 @@ timode_scalar_chain::convert_insn (rtx_insn *insn)
Also populates defs_map which is used later by convert_insn. */
void
-general_scalar_chain::convert_registers ()
+scalar_chain::convert_registers ()
{
bitmap_iterator bi;
unsigned id;
@@ -1510,7 +1516,9 @@ scalar_chain::convert ()
EXECUTE_IF_SET_IN_BITMAP (insns, 0, id, bi)
{
- convert_insn (DF_INSN_UID_GET (id)->insn);
+ rtx_insn *insn = DF_INSN_UID_GET (id)->insn;
+ convert_insn_common (insn);
+ convert_insn (insn);
converted_insns++;
}
@@ -1843,56 +1851,62 @@ timode_remove_non_convertible_regs (bitmap candidates)
bitmap_iterator bi;
unsigned id;
bitmap regs = BITMAP_ALLOC (NULL);
+ bool changed;
- EXECUTE_IF_SET_IN_BITMAP (candidates, 0, id, bi)
- {
- rtx def_set = single_set (DF_INSN_UID_GET (id)->insn);
- rtx dest = SET_DEST (def_set);
- rtx src = SET_SRC (def_set);
-
- if ((!REG_P (dest)
- || bitmap_bit_p (regs, REGNO (dest))
- || HARD_REGISTER_P (dest))
- && (!REG_P (src)
- || bitmap_bit_p (regs, REGNO (src))
- || HARD_REGISTER_P (src)))
- continue;
-
- if (REG_P (dest))
- timode_check_non_convertible_regs (candidates, regs,
- REGNO (dest));
-
- if (REG_P (src))
- timode_check_non_convertible_regs (candidates, regs,
- REGNO (src));
- }
+ do {
+ changed = false;
+ EXECUTE_IF_SET_IN_BITMAP (candidates, 0, id, bi)
+ {
+ rtx def_set = single_set (DF_INSN_UID_GET (id)->insn);
+ rtx dest = SET_DEST (def_set);
+ rtx src = SET_SRC (def_set);
+
+ if ((!REG_P (dest)
+ || bitmap_bit_p (regs, REGNO (dest))
+ || HARD_REGISTER_P (dest))
+ && (!REG_P (src)
+ || bitmap_bit_p (regs, REGNO (src))
+ || HARD_REGISTER_P (src)))
+ continue;
+
+ if (REG_P (dest))
+ timode_check_non_convertible_regs (candidates, regs,
+ REGNO (dest));
+
+ if (REG_P (src))
+ timode_check_non_convertible_regs (candidates, regs,
+ REGNO (src));
+ }
- EXECUTE_IF_SET_IN_BITMAP (regs, 0, id, bi)
- {
- for (df_ref def = DF_REG_DEF_CHAIN (id);
- def;
- def = DF_REF_NEXT_REG (def))
- if (bitmap_bit_p (candidates, DF_REF_INSN_UID (def)))
- {
- if (dump_file)
- fprintf (dump_file, "Removing insn %d from candidates list\n",
- DF_REF_INSN_UID (def));
+ EXECUTE_IF_SET_IN_BITMAP (regs, 0, id, bi)
+ {
+ for (df_ref def = DF_REG_DEF_CHAIN (id);
+ def;
+ def = DF_REF_NEXT_REG (def))
+ if (bitmap_bit_p (candidates, DF_REF_INSN_UID (def)))
+ {
+ if (dump_file)
+ fprintf (dump_file, "Removing insn %d from candidates list\n",
+ DF_REF_INSN_UID (def));
- bitmap_clear_bit (candidates, DF_REF_INSN_UID (def));
- }
+ bitmap_clear_bit (candidates, DF_REF_INSN_UID (def));
+ changed = true;
+ }
- for (df_ref ref = DF_REG_USE_CHAIN (id);
- ref;
- ref = DF_REF_NEXT_REG (ref))
- if (bitmap_bit_p (candidates, DF_REF_INSN_UID (ref)))
- {
- if (dump_file)
- fprintf (dump_file, "Removing insn %d from candidates list\n",
- DF_REF_INSN_UID (ref));
+ for (df_ref ref = DF_REG_USE_CHAIN (id);
+ ref;
+ ref = DF_REF_NEXT_REG (ref))
+ if (bitmap_bit_p (candidates, DF_REF_INSN_UID (ref)))
+ {
+ if (dump_file)
+ fprintf (dump_file, "Removing insn %d from candidates list\n",
+ DF_REF_INSN_UID (ref));
- bitmap_clear_bit (candidates, DF_REF_INSN_UID (ref));
- }
- }
+ bitmap_clear_bit (candidates, DF_REF_INSN_UID (ref));
+ changed = true;
+ }
+ }
+ } while (changed);
BITMAP_FREE (regs);
}
diff --git a/gcc/config/i386/i386-features.h b/gcc/config/i386/i386-features.h
index 88b222d..3d88a88 100644
--- a/gcc/config/i386/i386-features.h
+++ b/gcc/config/i386/i386-features.h
@@ -149,6 +149,7 @@ class scalar_chain
bitmap defs_conv;
bitmap insns_conv;
+ hash_map<rtx, rtx> defs_map;
unsigned n_sse_to_integer;
unsigned n_integer_to_sse;
@@ -161,12 +162,15 @@ class scalar_chain
void emit_conversion_insns (rtx insns, rtx_insn *pos);
rtx convert_compare (rtx op1, rtx op2, rtx_insn *insn);
void mark_dual_mode_def (df_ref def);
+ void convert_reg (rtx_insn *insn, rtx dst, rtx src);
+ void convert_insn_common (rtx_insn *insn);
+ void make_vector_copies (rtx_insn *, rtx);
+ void convert_registers ();
private:
void add_insn (bitmap candidates, unsigned insn_uid);
void analyze_register_chain (bitmap candidates, df_ref ref);
virtual void convert_insn (rtx_insn *insn) = 0;
- virtual void convert_registers () = 0;
virtual void convert_op (rtx *op, rtx_insn *insn) = 0;
};
@@ -178,12 +182,8 @@ class general_scalar_chain : public scalar_chain
int compute_convert_gain () final override;
private:
- hash_map<rtx, rtx> defs_map;
void convert_insn (rtx_insn *insn) final override;
- void convert_reg (rtx_insn *insn, rtx dst, rtx src);
void convert_op (rtx *op, rtx_insn *insn);
- void make_vector_copies (rtx_insn *, rtx);
- void convert_registers () final override;
int vector_const_cost (rtx exp);
};
@@ -197,8 +197,6 @@ class timode_scalar_chain : public scalar_chain
void fix_debug_reg_uses (rtx reg);
void convert_insn (rtx_insn *insn) final override;
void convert_op (rtx *op, rtx_insn *insn);
- /* We don't convert registers to different size. */
- void convert_registers () final override {}
};
} // anon namespace
diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md
index 3294c1e..dda4b43 100644
--- a/gcc/config/i386/mmx.md
+++ b/gcc/config/i386/mmx.md
@@ -86,6 +86,14 @@
[(V8QI "b") (V4QI "b") (V2QI "b")
(V4HI "w") (V2HI "w") (V2SI "d") (V1DI "q")])
+;; Mapping to same size integral mode.
+(define_mode_attr mmxinsnmode
+ [(V8QI "DI") (V4QI "SI") (V2QI "HI")
+ (V4HI "DI") (V2HI "SI")
+ (V2SI "DI")
+ (V4HF "DI") (V2HF "SI")
+ (V2SF "DI")])
+
(define_mode_attr mmxdoublemode
[(V8QI "V8HI") (V4HI "V4SI")])
@@ -350,22 +358,7 @@
HOST_WIDE_INT val = ix86_convert_const_vector_to_integer (operands[1],
<MODE>mode);
operands[1] = GEN_INT (val);
- machine_mode mode;
- switch (GET_MODE_SIZE (<MODE>mode))
- {
- case 2:
- mode = HImode;
- break;
- case 4:
- mode = SImode;
- break;
- case 8:
- mode = DImode;
- break;
- default:
- gcc_unreachable ();
- }
- operands[0] = lowpart_subreg (mode, operands[0], <MODE>mode);
+ operands[0] = lowpart_subreg (<mmxinsnmode>mode, operands[0], <MODE>mode);
})
;; For TARGET_64BIT we always round up to 8 bytes.
@@ -2974,33 +2967,48 @@
(set_attr "type" "mmxadd,sselog,sselog,sselog")
(set_attr "mode" "DI,TI,TI,TI")])
-(define_insn "<code><mode>3"
- [(set (match_operand:VI_16_32 0 "register_operand" "=?r,x,x,v")
+(define_expand "<code><mode>3"
+ [(set (match_operand:VI_16_32 0 "nonimmediate_operand")
(any_logic:VI_16_32
- (match_operand:VI_16_32 1 "register_operand" "%0,0,x,v")
- (match_operand:VI_16_32 2 "register_operand" "r,x,x,v")))
- (clobber (reg:CC FLAGS_REG))]
+ (match_operand:VI_16_32 1 "nonimmediate_operand")
+ (match_operand:VI_16_32 2 "nonimmediate_or_x86_64_const_vector_operand")))]
""
+ "ix86_expand_binary_operator (<CODE>, <MODE>mode, operands); DONE;")
+
+(define_insn "*<code><mode>3"
+ [(set (match_operand:VI_16_32 0 "nonimmediate_operand" "=?r,m,x,x,v")
+ (any_logic:VI_16_32
+ (match_operand:VI_16_32 1 "nonimmediate_operand" "%0,0,0,x,v")
+ (match_operand:VI_16_32 2 "nonimmediate_or_x86_64_const_vector_operand" "r,i,x,x,v")))
+ (clobber (reg:CC FLAGS_REG))]
+ "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
"#"
- [(set_attr "isa" "*,sse2_noavx,avx,avx512vl")
- (set_attr "type" "alu,sselog,sselog,sselog")
- (set_attr "mode" "SI,TI,TI,TI")])
+ [(set_attr "isa" "*,*,sse2_noavx,avx,avx512vl")
+ (set_attr "type" "alu,alu,sselog,sselog,sselog")
+ (set_attr "mode" "SI,SI,TI,TI,TI")])
(define_split
- [(set (match_operand:VI_16_32 0 "general_reg_operand")
+ [(set (match_operand:VI_16_32 0 "nonimmediate_gr_operand")
(any_logic:VI_16_32
- (match_operand:VI_16_32 1 "general_reg_operand")
- (match_operand:VI_16_32 2 "general_reg_operand")))
+ (match_operand:VI_16_32 1 "nonimmediate_gr_operand")
+ (match_operand:VI_16_32 2 "reg_or_const_vector_operand")))
(clobber (reg:CC FLAGS_REG))]
"reload_completed"
[(parallel
[(set (match_dup 0)
- (any_logic:SI (match_dup 1) (match_dup 2)))
+ (any_logic:<mmxinsnmode> (match_dup 1) (match_dup 2)))
(clobber (reg:CC FLAGS_REG))])]
{
- operands[2] = lowpart_subreg (SImode, operands[2], <MODE>mode);
- operands[1] = lowpart_subreg (SImode, operands[1], <MODE>mode);
- operands[0] = lowpart_subreg (SImode, operands[0], <MODE>mode);
+ if (!register_operand (operands[2], <MODE>mode))
+ {
+ HOST_WIDE_INT val = ix86_convert_const_vector_to_integer (operands[2],
+ <MODE>mode);
+ operands[2] = GEN_INT (val);
+ }
+ else
+ operands[2] = lowpart_subreg (<mmxinsnmode>mode, operands[2], <MODE>mode);
+ operands[1] = lowpart_subreg (<mmxinsnmode>mode, operands[1], <MODE>mode);
+ operands[0] = lowpart_subreg (<mmxinsnmode>mode, operands[0], <MODE>mode);
})
(define_split
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 42053ea..064596d 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -1209,6 +1209,10 @@
return trunc_int_for_mode (val, SImode) == val;
})
+(define_predicate "nonimmediate_or_x86_64_const_vector_operand"
+ (ior (match_operand 0 "nonimmediate_operand")
+ (match_operand 0 "x86_64_const_vector_operand")))
+
;; Return true when OP is nonimmediate or standard SSE constant.
(define_predicate "nonimmediate_or_sse_const_operand"
(ior (match_operand 0 "nonimmediate_operand")
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index efc8ae3..2c4940f 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -886,13 +886,13 @@
"TARGET_POWER10"
{
if (BYTES_BIG_ENDIAN)
- emit_insn (gen_vstrir_code_<mode> (operands[0], operands[1]));
+ emit_insn (gen_vstrir_direct_<mode> (operands[0], operands[1]));
else
- emit_insn (gen_vstril_code_<mode> (operands[0], operands[1]));
+ emit_insn (gen_vstril_direct_<mode> (operands[0], operands[1]));
DONE;
})
-(define_insn "vstrir_code_<mode>"
+(define_insn "vstrir_direct_<mode>"
[(set (match_operand:VIshort 0 "altivec_register_operand" "=v")
(unspec:VIshort
[(match_operand:VIshort 1 "altivec_register_operand" "v")]
@@ -901,7 +901,7 @@
"vstri<wd>r %0,%1"
[(set_attr "type" "vecsimple")])
-;; This expands into same code as vstrir_<mode> followed by condition logic
+;; This expands into same code as vstrir<mode> followed by condition logic
;; so that a single vstribr. or vstrihr. or vstribl. or vstrihl. instruction
;; can, for example, satisfy the needs of a vec_strir () function paired
;; with a vec_strir_p () function if both take the same incoming arguments.
@@ -912,14 +912,14 @@
{
rtx scratch = gen_reg_rtx (<MODE>mode);
if (BYTES_BIG_ENDIAN)
- emit_insn (gen_vstrir_p_code_<mode> (scratch, operands[1]));
+ emit_insn (gen_vstrir_p_direct_<mode> (scratch, operands[1]));
else
- emit_insn (gen_vstril_p_code_<mode> (scratch, operands[1]));
+ emit_insn (gen_vstril_p_direct_<mode> (scratch, operands[1]));
emit_insn (gen_cr6_test_for_zero (operands[0]));
DONE;
})
-(define_insn "vstrir_p_code_<mode>"
+(define_insn "vstrir_p_direct_<mode>"
[(set (match_operand:VIshort 0 "altivec_register_operand" "=v")
(unspec:VIshort
[(match_operand:VIshort 1 "altivec_register_operand" "v")]
@@ -938,13 +938,13 @@
"TARGET_POWER10"
{
if (BYTES_BIG_ENDIAN)
- emit_insn (gen_vstril_code_<mode> (operands[0], operands[1]));
+ emit_insn (gen_vstril_direct_<mode> (operands[0], operands[1]));
else
- emit_insn (gen_vstrir_code_<mode> (operands[0], operands[1]));
+ emit_insn (gen_vstrir_direct_<mode> (operands[0], operands[1]));
DONE;
})
-(define_insn "vstril_code_<mode>"
+(define_insn "vstril_direct_<mode>"
[(set (match_operand:VIshort 0 "altivec_register_operand" "=v")
(unspec:VIshort
[(match_operand:VIshort 1 "altivec_register_operand" "v")]
@@ -964,14 +964,14 @@
{
rtx scratch = gen_reg_rtx (<MODE>mode);
if (BYTES_BIG_ENDIAN)
- emit_insn (gen_vstril_p_code_<mode> (scratch, operands[1]));
+ emit_insn (gen_vstril_p_direct_<mode> (scratch, operands[1]));
else
- emit_insn (gen_vstrir_p_code_<mode> (scratch, operands[1]));
+ emit_insn (gen_vstrir_p_direct_<mode> (scratch, operands[1]));
emit_insn (gen_cr6_test_for_zero (operands[0]));
DONE;
})
-(define_insn "vstril_p_code_<mode>"
+(define_insn "vstril_p_direct_<mode>"
[(set (match_operand:VIshort 0 "altivec_register_operand" "=v")
(unspec:VIshort
[(match_operand:VIshort 1 "altivec_register_operand" "v")]
diff --git a/gcc/config/rs6000/rs6000-c.cc b/gcc/config/rs6000/rs6000-c.cc
index 0d13645..4d051b9 100644
--- a/gcc/config/rs6000/rs6000-c.cc
+++ b/gcc/config/rs6000/rs6000-c.cc
@@ -335,20 +335,16 @@ rs6000_define_or_undefine_macro (bool define_p, const char *name)
}
/* Define or undefine macros based on the current target. If the user does
- #pragma GCC target, we need to adjust the macros dynamically. Note, some of
- the options needed for builtins have been moved to separate variables, so
- have both the target flags and the builtin flags as arguments. */
+ #pragma GCC target, we need to adjust the macros dynamically. */
void
-rs6000_target_modify_macros (bool define_p, HOST_WIDE_INT flags,
- HOST_WIDE_INT bu_mask)
+rs6000_target_modify_macros (bool define_p, HOST_WIDE_INT flags)
{
if (TARGET_DEBUG_BUILTIN || TARGET_DEBUG_TARGET)
fprintf (stderr,
- "rs6000_target_modify_macros (%s, " HOST_WIDE_INT_PRINT_HEX
- ", " HOST_WIDE_INT_PRINT_HEX ")\n",
+ "rs6000_target_modify_macros (%s, " HOST_WIDE_INT_PRINT_HEX ")\n",
(define_p) ? "define" : "undef",
- flags, bu_mask);
+ flags);
/* Each of the flags mentioned below controls whether certain
preprocessor macros will be automatically defined when
@@ -595,10 +591,8 @@ rs6000_target_modify_macros (bool define_p, HOST_WIDE_INT flags,
if ((flags & OPTION_MASK_FLOAT128_HW) != 0)
rs6000_define_or_undefine_macro (define_p, "__FLOAT128_HARDWARE__");
- /* options from the builtin masks. */
- /* Note that OPTION_MASK_FPRND is enabled only if
- (rs6000_cpu == PROCESSOR_CELL) (e.g. -mcpu=cell). */
- if ((bu_mask & OPTION_MASK_FPRND) != 0)
+ /* Tell the user if we are targeting CELL. */
+ if (rs6000_cpu == PROCESSOR_CELL)
rs6000_define_or_undefine_macro (define_p, "__PPU__");
/* Tell the user if we support the MMA instructions. */
@@ -616,8 +610,7 @@ void
rs6000_cpu_cpp_builtins (cpp_reader *pfile)
{
/* Define all of the common macros. */
- rs6000_target_modify_macros (true, rs6000_isa_flags,
- rs6000_builtin_mask_calculate ());
+ rs6000_target_modify_macros (true, rs6000_isa_flags);
if (TARGET_FRE)
builtin_define ("__RECIP__");
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 3ea0102..b3c16e7 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -320,9 +320,8 @@ extern void rs6000_cpu_cpp_builtins (struct cpp_reader *);
extern bool rs6000_pragma_target_parse (tree, tree);
#endif
extern void rs6000_activate_target_options (tree new_tree);
-extern void rs6000_target_modify_macros (bool, HOST_WIDE_INT, HOST_WIDE_INT);
-extern void (*rs6000_target_modify_macros_ptr) (bool, HOST_WIDE_INT,
- HOST_WIDE_INT);
+extern void rs6000_target_modify_macros (bool, HOST_WIDE_INT);
+extern void (*rs6000_target_modify_macros_ptr) (bool, HOST_WIDE_INT);
/* Declare functions in rs6000-d.cc */
extern void rs6000_d_target_versions (void);
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 3ff16b8..4b727d2 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -278,7 +278,7 @@ bool cpu_builtin_p = false;
/* Pointer to function (in rs6000-c.cc) that can define or undefine target
macros that have changed. Languages that don't support the preprocessor
don't link in rs6000-c.cc, so we can't call it directly. */
-void (*rs6000_target_modify_macros_ptr) (bool, HOST_WIDE_INT, HOST_WIDE_INT);
+void (*rs6000_target_modify_macros_ptr) (bool, HOST_WIDE_INT);
/* Simplfy register classes into simpler classifications. We assume
GPR_REG_TYPE - FPR_REG_TYPE are ordered so that we can use a simple range
@@ -1171,8 +1171,6 @@ const int INSN_NOT_AVAILABLE = -1;
static void rs6000_print_isa_options (FILE *, int, const char *,
HOST_WIDE_INT);
-static void rs6000_print_builtin_options (FILE *, int, const char *,
- HOST_WIDE_INT);
static HOST_WIDE_INT rs6000_disable_incompatible_switches (void);
static enum rs6000_reg_type register_to_reg_type (rtx, bool *);
@@ -2407,9 +2405,6 @@ rs6000_debug_reg_global (void)
rs6000_print_isa_options (stderr, 0, "rs6000_isa_flags_explicit",
rs6000_isa_flags_explicit);
- rs6000_print_builtin_options (stderr, 0, "rs6000_builtin_mask",
- rs6000_builtin_mask);
-
rs6000_print_isa_options (stderr, 0, "TARGET_DEFAULT", TARGET_DEFAULT);
fprintf (stderr, DEBUG_FMT_S, "--with-cpu default",
@@ -3372,41 +3367,6 @@ darwin_rs6000_override_options (void)
#define RS6000_DEFAULT_LONG_DOUBLE_SIZE 64
#endif
-/* Return the builtin mask of the various options used that could affect which
- builtins were used. In the past we used target_flags, but we've run out of
- bits, and some options are no longer in target_flags. */
-
-HOST_WIDE_INT
-rs6000_builtin_mask_calculate (void)
-{
- return (((TARGET_ALTIVEC) ? OPTION_MASK_ALTIVEC : 0)
- | ((TARGET_CMPB) ? OPTION_MASK_CMPB : 0)
- | ((TARGET_VSX) ? OPTION_MASK_VSX : 0)
- | ((TARGET_FRE) ? OPTION_MASK_POPCNTB : 0)
- | ((TARGET_FRES) ? OPTION_MASK_PPC_GFXOPT : 0)
- | ((TARGET_FRSQRTE) ? OPTION_MASK_PPC_GFXOPT : 0)
- | ((TARGET_FRSQRTES) ? OPTION_MASK_POPCNTB : 0)
- | ((TARGET_POPCNTD) ? OPTION_MASK_POPCNTD : 0)
- | ((rs6000_cpu == PROCESSOR_CELL) ? OPTION_MASK_FPRND : 0)
- | ((TARGET_P8_VECTOR) ? OPTION_MASK_P8_VECTOR : 0)
- | ((TARGET_P9_VECTOR) ? OPTION_MASK_P9_VECTOR : 0)
- | ((TARGET_P9_MISC) ? OPTION_MASK_P9_MISC : 0)
- | ((TARGET_MODULO) ? OPTION_MASK_MODULO : 0)
- | ((TARGET_64BIT) ? MASK_64BIT : 0)
- | ((TARGET_POWERPC64) ? MASK_POWERPC64 : 0)
- | ((TARGET_CRYPTO) ? OPTION_MASK_CRYPTO : 0)
- | ((TARGET_HTM) ? OPTION_MASK_HTM : 0)
- | ((TARGET_DFP) ? OPTION_MASK_DFP : 0)
- | ((TARGET_HARD_FLOAT) ? OPTION_MASK_SOFT_FLOAT : 0)
- | ((TARGET_LONG_DOUBLE_128
- && TARGET_HARD_FLOAT
- && !TARGET_IEEEQUAD) ? OPTION_MASK_MULTIPLE : 0)
- | ((TARGET_FLOAT128_TYPE) ? OPTION_MASK_FLOAT128_KEYWORD : 0)
- | ((TARGET_FLOAT128_HW) ? OPTION_MASK_FLOAT128_HW : 0)
- | ((TARGET_MMA) ? OPTION_MASK_MMA : 0)
- | ((TARGET_POWER10) ? OPTION_MASK_POWER10 : 0));
-}
-
/* Implement TARGET_MD_ASM_ADJUST. All asm statements are considered
to clobber the XER[CA] bit because clobbering that bit without telling
the compiler worked just fine with versions of GCC before GCC 5, and
@@ -3618,11 +3578,6 @@ glibc_supports_ieee_128bit (void)
generally defined to test the corresponding bit of the
rs6000_isa_flags variable.
- The variable rs6000_builtin_mask is set to represent the target
- options for the most current compilation efforts, consistent with
- the current contents of rs6000_isa_flags. This variable controls
- expansion of built-in functions.
-
Various other global variables and fields of global structures
(over 50 in all) are initialized to reflect the desired options
for the most current compilation efforts. */
@@ -4890,14 +4845,6 @@ rs6000_option_override_internal (bool global_init_p)
}
}
- /* Set the builtin mask of the various options used that could affect which
- builtins were used. In the past we used target_flags, but we've run out
- of bits, and some options are no longer in target_flags. */
- rs6000_builtin_mask = rs6000_builtin_mask_calculate ();
- if (TARGET_DEBUG_BUILTIN || TARGET_DEBUG_TARGET)
- rs6000_print_builtin_options (stderr, 0, "builtin mask",
- rs6000_builtin_mask);
-
/* Initialize all of the registers. */
rs6000_init_hard_regno_mode_ok (global_init_p);
@@ -24051,32 +23998,6 @@ static struct rs6000_opt_mask const rs6000_opt_masks[] =
{ "string", 0, false, false },
};
-/* Builtin mask mapping for printing the flags. */
-static struct rs6000_opt_mask const rs6000_builtin_mask_names[] =
-{
- { "altivec", OPTION_MASK_ALTIVEC, false, false },
- { "vsx", OPTION_MASK_VSX, false, false },
- { "fre", OPTION_MASK_POPCNTB, false, false },
- { "fres", OPTION_MASK_PPC_GFXOPT, false, false },
- { "frsqrte", OPTION_MASK_PPC_GFXOPT, false, false },
- { "frsqrtes", OPTION_MASK_POPCNTB, false, false },
- { "popcntd", OPTION_MASK_POPCNTD, false, false },
- { "cell", OPTION_MASK_FPRND, false, false },
- { "power8-vector", OPTION_MASK_P8_VECTOR, false, false },
- { "power9-vector", OPTION_MASK_P9_VECTOR, false, false },
- { "power9-misc", OPTION_MASK_P9_MISC, false, false },
- { "crypto", OPTION_MASK_CRYPTO, false, false },
- { "htm", OPTION_MASK_HTM, false, false },
- { "hard-dfp", OPTION_MASK_DFP, false, false },
- { "hard-float", OPTION_MASK_SOFT_FLOAT, false, false },
- { "long-double-128", OPTION_MASK_MULTIPLE, false, false },
- { "powerpc64", MASK_POWERPC64, false, false },
- { "float128", OPTION_MASK_FLOAT128_KEYWORD, false, false },
- { "float128-hw", OPTION_MASK_FLOAT128_HW,false, false },
- { "mma", OPTION_MASK_MMA, false, false },
- { "power10", OPTION_MASK_POWER10, false, false },
-};
-
/* Option variables that we want to support inside attribute((target)) and
#pragma GCC target operations. */
@@ -24431,7 +24352,6 @@ rs6000_pragma_target_parse (tree args, tree pop_target)
tree cur_tree;
struct cl_target_option *prev_opt, *cur_opt;
HOST_WIDE_INT prev_flags, cur_flags, diff_flags;
- HOST_WIDE_INT prev_bumask, cur_bumask, diff_bumask;
if (TARGET_DEBUG_TARGET)
{
@@ -24483,27 +24403,22 @@ rs6000_pragma_target_parse (tree args, tree pop_target)
if (rs6000_target_modify_macros_ptr)
{
prev_opt = TREE_TARGET_OPTION (prev_tree);
- prev_bumask = prev_opt->x_rs6000_builtin_mask;
prev_flags = prev_opt->x_rs6000_isa_flags;
cur_opt = TREE_TARGET_OPTION (cur_tree);
cur_flags = cur_opt->x_rs6000_isa_flags;
- cur_bumask = cur_opt->x_rs6000_builtin_mask;
- diff_bumask = (prev_bumask ^ cur_bumask);
diff_flags = (prev_flags ^ cur_flags);
- if ((diff_flags != 0) || (diff_bumask != 0))
+ if (diff_flags != 0)
{
/* Delete old macros. */
rs6000_target_modify_macros_ptr (false,
- prev_flags & diff_flags,
- prev_bumask & diff_bumask);
+ prev_flags & diff_flags);
/* Define new macros. */
rs6000_target_modify_macros_ptr (true,
- cur_flags & diff_flags,
- cur_bumask & diff_bumask);
+ cur_flags & diff_flags);
}
}
@@ -24734,15 +24649,6 @@ rs6000_print_isa_options (FILE *file, int indent, const char *string,
ARRAY_SIZE (rs6000_opt_masks));
}
-static void
-rs6000_print_builtin_options (FILE *file, int indent, const char *string,
- HOST_WIDE_INT flags)
-{
- rs6000_print_options_internal (file, indent, string, flags, "",
- &rs6000_builtin_mask_names[0],
- ARRAY_SIZE (rs6000_builtin_mask_names));
-}
-
/* If the user used -mno-vsx, we need turn off all of the implicit ISA 2.06,
2.07, and 3.0 options that relate to the vector unit (-mdirect-move,
-mupper-regs-df, etc.).
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 7d04556..ad9bf0f 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -81,12 +81,15 @@
# define SUBTARGET_DRIVER_SELF_SPECS ""
#endif
-/* Only for use in the testsuite: -mdejagnu-cpu= simply overrides -mcpu=.
+/* Only for use in the testsuite: -mdejagnu-cpu=<value> filters out all
+ -mcpu= as well as -mtune= options then simply adds -mcpu=<value>,
+ while -mdejagnu-tune=<value> filters out all -mtune= options then
+ simply adds -mtune=<value>.
With older versions of Dejagnu the command line arguments you set in
- RUNTESTFLAGS override those set in the testcases; with this option,
- the testcase will always win. Ditto for -mdejagnu-tune=. */
+ RUNTESTFLAGS override those set in the testcases; with these options,
+ the testcase will always win. */
#define DRIVER_SELF_SPECS \
- "%{mdejagnu-cpu=*: %<mcpu=* -mcpu=%*}", \
+ "%{mdejagnu-cpu=*: %<mcpu=* %<mtune=* -mcpu=%*}", \
"%{mdejagnu-tune=*: %<mtune=* -mtune=%*}", \
"%{mdejagnu-*: %<mdejagnu-*}", \
SUBTARGET_DRIVER_SELF_SPECS
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index 4931d78..b227bf9 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -96,10 +96,6 @@ enum rs6000_cmodel rs6000_current_cmodel = CMODEL_SMALL
TargetVariable
unsigned int rs6000_recip_control
-;; Mask of what builtin functions are allowed
-TargetVariable
-HOST_WIDE_INT rs6000_builtin_mask
-
;; Debug flags
TargetVariable
unsigned int rs6000_debug
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index c02f1a5..899ce27 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -1714,6 +1714,90 @@
(set_attr "mode" "none")
(set_attr "length" "3")])
+(define_insn_and_split "*masktrue_const_bitcmpl"
+ [(set (pc)
+ (if_then_else (match_operator 3 "boolean_operator"
+ [(and:SI (not:SI (match_operand:SI 0 "register_operand" "r"))
+ (match_operand:SI 1 "const_int_operand" "i"))
+ (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "exact_log2 (INTVAL (operands[1])) < 0"
+ "#"
+ "&& can_create_pseudo_p ()"
+ [(set (match_dup 4)
+ (match_dup 1))
+ (set (pc)
+ (if_then_else (match_op_dup 3
+ [(and:SI (not:SI (match_dup 0))
+ (match_dup 4))
+ (const_int 0)])
+ (label_ref (match_dup 2))
+ (pc)))]
+{
+ operands[4] = gen_reg_rtx (SImode);
+}
+ [(set_attr "type" "jump")
+ (set_attr "mode" "none")
+ (set (attr "length")
+ (if_then_else (match_test "TARGET_DENSITY
+ && IN_RANGE (INTVAL (operands[1]), -32, 95)")
+ (const_int 5)
+ (if_then_else (match_test "xtensa_simm12b (INTVAL (operands[1]))")
+ (const_int 6)
+ (const_int 10))))])
+
+(define_split
+ [(set (pc)
+ (if_then_else (match_operator 2 "boolean_operator"
+ [(subreg:HQI (not:SI (match_operand:SI 0 "register_operand")) 0)
+ (const_int 0)])
+ (label_ref (match_operand 1 ""))
+ (pc)))]
+ "!BYTES_BIG_ENDIAN"
+ [(set (pc)
+ (if_then_else (match_op_dup 2
+ [(and:SI (not:SI (match_dup 0))
+ (match_dup 3))
+ (const_int 0)])
+ (label_ref (match_dup 1))
+ (pc)))]
+{
+ operands[3] = GEN_INT ((1 << GET_MODE_BITSIZE (<MODE>mode)) - 1);
+})
+
+(define_split
+ [(set (pc)
+ (if_then_else (match_operator 2 "boolean_operator"
+ [(subreg:HI (not:SI (match_operand:SI 0 "register_operand")) 2)
+ (const_int 0)])
+ (label_ref (match_operand 1 ""))
+ (pc)))]
+ "BYTES_BIG_ENDIAN"
+ [(set (pc)
+ (if_then_else (match_op_dup 2
+ [(and:SI (not:SI (match_dup 0))
+ (const_int 65535))
+ (const_int 0)])
+ (label_ref (match_dup 1))
+ (pc)))])
+
+(define_split
+ [(set (pc)
+ (if_then_else (match_operator 2 "boolean_operator"
+ [(subreg:QI (not:SI (match_operand:SI 0 "register_operand")) 3)
+ (const_int 0)])
+ (label_ref (match_operand 1 ""))
+ (pc)))]
+ "BYTES_BIG_ENDIAN"
+ [(set (pc)
+ (if_then_else (match_op_dup 2
+ [(and:SI (not:SI (match_dup 0))
+ (const_int 255))
+ (const_int 0)])
+ (label_ref (match_dup 1))
+ (pc)))])
+
(define_insn_and_split "*masktrue_const_pow2_minus_one"
[(set (pc)
(if_then_else (match_operator 4 "boolean_operator"
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2664940..f5ff8de 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,28 @@
+2022-07-22 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/106366
+ * pt.cc (do_class_deduction): Don't consider TYPE_HAS_LIST_CTOR
+ when setting try_list_ctor. Reset args even when try_list_ctor
+ is true and there are no list candidates. Call resolve_args on
+ the reset args. Rename try_list_ctor to try_list_cand.
+
+2022-07-22 Martin Liska <mliska@suse.cz>
+
+ PR other/106370
+ * init.cc (sort_mem_initializers): Remove continue as last stmt
+ in a loop.
+
+2022-07-21 Jason Merrill <jason@redhat.com>
+
+ PR c++/106361
+ * decl.cc (move_fn_p): Remove assert.
+
+2022-07-21 Jason Merrill <jason@redhat.com>
+
+ DR 2084
+ PR c++/98423
+ * method.cc (walk_field_subobs): Fix DMI in union case.
+
2022-07-19 Patrick Palka <ppalka@redhat.com>
PR c++/94894
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index aa6cf3c..70ad681 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -15022,8 +15022,6 @@ copy_fn_p (const_tree d)
bool
move_fn_p (const_tree d)
{
- gcc_assert (DECL_FUNCTION_MEMBER_P (d));
-
if (cxx_dialect == cxx98)
/* There are no move constructors if we are in C++98 mode. */
return false;
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index a4a0a0a..edca843 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -1436,7 +1436,6 @@ sort_mem_initializers (tree t, tree mem_inits)
continue;
splice:
*p = TREE_CHAIN (*p);
- continue;
}
}
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index f2050f6..573ef01 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -2315,8 +2315,19 @@ walk_field_subobs (tree fields, special_function_kind sfk, tree fnname,
bool diag, int flags, tsubst_flags_t complain,
bool dtor_from_ctor)
{
- tree field;
- for (field = fields; field; field = DECL_CHAIN (field))
+ if (!fields)
+ return;
+
+ tree ctx = DECL_CONTEXT (fields);
+
+ /* CWG2084: A defaulted default ctor for a union with a DMI only initializes
+ that member, so don't check other members. */
+ enum { unknown, no, yes }
+ only_dmi_mem = (sfk == sfk_constructor && TREE_CODE (ctx) == UNION_TYPE
+ ? unknown : no);
+
+ again:
+ for (tree field = fields; field; field = DECL_CHAIN (field))
{
tree mem_type, argtype, rval;
@@ -2331,9 +2342,18 @@ walk_field_subobs (tree fields, special_function_kind sfk, tree fnname,
asking if this is deleted, don't even look up the function; we don't
want an error about a deleted function we aren't actually calling. */
if (sfk == sfk_destructor && deleted_p == NULL
- && TREE_CODE (DECL_CONTEXT (field)) == UNION_TYPE)
+ && TREE_CODE (ctx) == UNION_TYPE)
break;
+ if (only_dmi_mem != no)
+ {
+ if (DECL_INITIAL (field))
+ only_dmi_mem = yes;
+ else
+ /* Don't check this until we know there's no DMI. */
+ continue;
+ }
+
mem_type = strip_array_types (TREE_TYPE (field));
if (SFK_ASSIGN_P (sfk))
{
@@ -2416,7 +2436,7 @@ walk_field_subobs (tree fields, special_function_kind sfk, tree fnname,
if (constexpr_p
&& cxx_dialect < cxx20
&& !CLASS_TYPE_P (mem_type)
- && TREE_CODE (DECL_CONTEXT (field)) != UNION_TYPE)
+ && TREE_CODE (ctx) != UNION_TYPE)
{
*constexpr_p = false;
if (diag)
@@ -2465,6 +2485,13 @@ walk_field_subobs (tree fields, special_function_kind sfk, tree fnname,
process_subob_fn (rval, sfk, spec_p, trivial_p, deleted_p,
constexpr_p, diag, field, dtor_from_ctor);
}
+
+ /* We didn't find a DMI in this union, now check all the members. */
+ if (only_dmi_mem == unknown)
+ {
+ only_dmi_mem = no;
+ goto again;
+ }
}
/* Base walker helper for synthesized_method_walk. Inspect a direct
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 718dfa5..c415db3 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -30240,7 +30240,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
tree type = TREE_TYPE (tmpl);
- bool try_list_ctor = false;
+ bool try_list_cand = false;
bool list_init_p = false;
releasing_vec rv_args = NULL;
@@ -30250,8 +30250,8 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
else if (BRACE_ENCLOSED_INITIALIZER_P (init))
{
list_init_p = true;
- try_list_ctor = TYPE_HAS_LIST_CTOR (type);
- if (try_list_ctor && CONSTRUCTOR_NELTS (init) == 1
+ try_list_cand = true;
+ if (CONSTRUCTOR_NELTS (init) == 1
&& !CONSTRUCTOR_IS_DESIGNATED_INIT (init))
{
/* As an exception, the first phase in 16.3.1.7 (considering the
@@ -30261,9 +30261,9 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
specialization of C. */
tree elt = CONSTRUCTOR_ELT (init, 0)->value;
if (is_spec_or_derived (TREE_TYPE (elt), tmpl))
- try_list_ctor = false;
+ try_list_cand = false;
}
- if (try_list_ctor || is_std_init_list (type))
+ if (try_list_cand || is_std_init_list (type))
args = make_tree_vector_single (init);
else
args = make_tree_vector_from_ctor (init);
@@ -30310,26 +30310,25 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
tree fndecl = error_mark_node;
- /* If this is list-initialization and the class has a list constructor, first
+ /* If this is list-initialization and the class has a list guide, first
try deducing from the list as a single argument, as [over.match.list]. */
- tree list_cands = NULL_TREE;
- if (try_list_ctor && cands)
- for (lkp_iterator iter (cands); iter; ++iter)
- {
- tree dg = *iter;
+ if (try_list_cand)
+ {
+ tree list_cands = NULL_TREE;
+ for (tree dg : lkp_range (cands))
if (is_list_ctor (dg))
list_cands = lookup_add (dg, list_cands);
- }
- if (list_cands)
- {
- fndecl = perform_dguide_overload_resolution (list_cands, args, tf_none);
-
+ if (list_cands)
+ fndecl = perform_dguide_overload_resolution (list_cands, args, tf_none);
if (fndecl == error_mark_node)
{
/* That didn't work, now try treating the list as a sequence of
arguments. */
release_tree_vector (args);
args = make_tree_vector_from_ctor (init);
+ args = resolve_args (args, complain);
+ if (args == NULL)
+ return error_mark_node;
}
}
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index e39f522..b54b972 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -3002,6 +3002,43 @@ produced by @command{gold}.
For other linkers that cannot generate resolution file,
explicit @code{externally_visible} attributes are still necessary.
+@item fd_arg
+@itemx fd_arg (@var{N})
+@cindex @code{fd_arg} function attribute
+The @code{fd_arg} attribute may be applied to a function that takes an open
+file descriptor at referenced argument @var{N}.
+
+It indicates that the passed filedescriptor must not have been closed.
+Therefore, when the analyzer is enabled with @option{-fanalyzer}, the
+analyzer may emit a @option{-Wanalyzer-fd-use-after-close} diagnostic
+if it detects a code path in which a function with this attribute is
+called with a closed file descriptor.
+
+The attribute also indicates that the file descriptor must have been checked for
+validity before usage. Therefore, analyzer may emit
+@option{-Wanalyzer-fd-use-without-check} diagnostic if it detects a code path in
+which a function with this attribute is called with a file descriptor that has
+not been checked for validity.
+
+@item fd_arg_read
+@itemx fd_arg_read (@var{N})
+@cindex @code{fd_arg_read} function attribute
+The @code{fd_arg_read} is identical to @code{fd_arg}, but with the additional
+requirement that it might read from the file descriptor, and thus, the file
+descriptor must not have been opened as write-only.
+
+The analyzer may emit a @option{-Wanalyzer-access-mode-mismatch}
+diagnostic if it detects a code path in which a function with this
+attribute is called on a file descriptor opened with @code{O_WRONLY}.
+
+@item fd_arg_write
+@itemx fd_arg_write (@var{N})
+@cindex @code{fd_arg_write} function attribute
+The @code{fd_arg_write} is identical to @code{fd_arg_read} except that the
+analyzer may emit a @option{-Wanalyzer-access-mode-mismatch} diagnostic if
+it detects a code path in which a function with this attribute is called on a
+file descriptor opened with @code{O_RDONLY}.
+
@item flatten
@cindex @code{flatten} function attribute
Generally, inlining into a function is limited. For a function marked with
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index ed629ca..5fb4844 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -9810,8 +9810,14 @@ This warning requires @option{-fanalyzer}, which enables it; use
@option{-Wno-analyzer-fd-access-mode-mismatch}
to disable it.
-This diagnostic warns for paths through code in which a
-@code{read} on a write-only file descriptor is attempted, or vice versa
+This diagnostic warns for paths through code in which a
+@code{read} on a write-only file descriptor is attempted, or vice versa.
+
+This diagnostic also warns for code paths in a which a function with attribute
+@code{fd_arg_read (N)} is called with a file descriptor opened with
+@code{O_WRONLY} at referenced argument @code{N} or a function with attribute
+@code{fd_arg_write (N)} is called with a file descriptor opened with
+@code{O_RDONLY} at referenced argument @var{N}.
@item -Wno-analyzer-fd-double-close
@opindex Wanalyzer-fd-double-close
@@ -9820,7 +9826,7 @@ This warning requires @option{-fanalyzer}, which enables it; use
@option{-Wno-analyzer-fd-double-close}
to disable it.
-This diagnostic warns for paths through code in which a
+This diagnostic warns for paths through code in which a
file descriptor can be closed more than once.
@item -Wno-analyzer-fd-leak
@@ -9830,7 +9836,7 @@ This warning requires @option{-fanalyzer}, which enables it; use
@option{-Wno-analyzer-fd-leak}
to disable it.
-This diagnostic warns for paths through code in which an
+This diagnostic warns for paths through code in which an
open file descriptor is leaked.
@item -Wno-analyzer-fd-use-after-close
@@ -9840,9 +9846,14 @@ This warning requires @option{-fanalyzer}, which enables it; use
@option{-Wno-analyzer-fd-use-after-close}
to disable it.
-This diagnostic warns for paths through code in which a
+This diagnostic warns for paths through code in which a
read or write is called on a closed file descriptor.
+This diagnostic also warns for paths through code in which
+a function with attribute @code{fd_arg (N)} or @code{fd_arg_read (N)}
+or @code{fd_arg_write (N)} is called with a closed file descriptor at
+referenced argument @code{N}.
+
@item -Wno-analyzer-fd-use-without-check
@opindex Wanalyzer-fd-use-without-check
@opindex Wno-analyzer-fd-use-without-check
@@ -9850,9 +9861,14 @@ This warning requires @option{-fanalyzer}, which enables it; use
@option{-Wno-analyzer-fd-use-without-check}
to disable it.
-This diagnostic warns for paths through code in which a
+This diagnostic warns for paths through code in which a
file descriptor is used without being checked for validity.
+This diagnostic also warns for paths through code in which
+a function with attribute @code{fd_arg (N)} or @code{fd_arg_read (N)}
+or @code{fd_arg_write (N)} is called with a file descriptor, at referenced
+argument @code{N}, without being checked for validity.
+
@item -Wno-analyzer-file-leak
@opindex Wanalyzer-file-leak
@opindex Wno-analyzer-file-leak
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 1109cd2..2404d85 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,7 @@
+2022-07-21 Martin Liska <mliska@suse.cz>
+
+ * intrinsic.texi: Remove trailing dots for 2 Fortran fns.
+
2022-07-20 Harald Anlauf <anlauf@gmx.de>
PR fortran/101330
diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index f3292fc..d9e160c 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -960,7 +960,7 @@ ranger_cache::edge_range (vrange &r, edge e, tree name, enum rfd_mode mode)
// If this is not an abnormal edge, check for inferred ranges on exit.
if ((e->flags & (EDGE_EH | EDGE_ABNORMAL)) == 0)
m_exit.maybe_adjust_range (r, name, e->src);
- int_range_max er;
+ Value_Range er (TREE_TYPE (name));
if (m_gori.outgoing_edge_range_p (er, e, name, *this))
r.intersect (er);
return true;
@@ -1364,7 +1364,8 @@ ranger_cache::range_from_dom (vrange &r, tree name, basic_block start_bb,
basic_block prev_bb = start_bb;
// Track any inferred ranges seen.
- int_range_max infer (TREE_TYPE (name));
+ Value_Range infer (TREE_TYPE (name));
+ infer.set_varying (TREE_TYPE (name));
// Range on entry to the DEF block should not be queried.
gcc_checking_assert (start_bb != def_bb);
@@ -1431,7 +1432,7 @@ ranger_cache::range_from_dom (vrange &r, tree name, basic_block start_bb,
// Now process any blocks wit incoming edges that nay have adjustemnts.
while (m_workback.length () > start_limit)
{
- int_range_max er;
+ Value_Range er (TREE_TYPE (name));
prev_bb = m_workback.pop ();
if (!single_pred_p (prev_bb))
{
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 5ea0406..2f2fafd 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-ff68b1a147eb60082fd60c198db0ef5477ade938
+a62f20ae78ddd41be682dde8cab075ca4f5dbb2a
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/graphds.cc b/gcc/graphds.cc
index f4c83e8..91a2ca5 100644
--- a/gcc/graphds.cc
+++ b/gcc/graphds.cc
@@ -276,7 +276,7 @@ graphds_dfs (struct graph *g, int *qs, int nq, vec<int> *qt,
}
/* Determines the strongly connected components of G, using the algorithm of
- Tarjan -- first determine the postorder dfs numbering in reversed graph,
+ Kosaraju -- first determine the postorder dfs numbering in reversed graph,
then run the dfs on the original graph in the order given by decreasing
numbers assigned by the previous pass. If SUBGRAPH is not NULL, it
specifies the subgraph of G whose strongly connected components we want
diff --git a/gcc/match.pd b/gcc/match.pd
index 88a1a5a..9736393 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -339,6 +339,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@0)))
(COPYSIGN_ALL (negate @0) @1)))
+/* (x >= 0 ? x : 0) + (x <= 0 ? -x : 0) -> abs x. */
+(simplify
+ (plus:c (max @0 integer_zerop) (max (negate @0) integer_zerop))
+ (abs @0))
+
/* X * 1, X / 1 -> X. */
(for op (mult trunc_div ceil_div floor_div round_div exact_div)
(simplify
@@ -3425,6 +3430,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& (GIMPLE || !TREE_SIDE_EFFECTS (@1)))
(cond (convert:boolean_type_node @2) @1 @0)))
+/* (x <= 0 ? -x : 0) -> max(-x, 0). */
+(simplify
+ (cond (le @0 integer_zerop@1) (negate@2 @0) integer_zerop@1)
+ (max @2 @1))
+
/* Simplifications of shift and rotates. */
(for rotate (lrotate rrotate)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 44d6ee2..054c92f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,91 @@
+2022-07-24 Roger Sayle <roger@nextmovesoftware.com>
+ H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/106303
+ PR target/106347
+ * gcc.target/i386/pr106303.c: New test case.
+ * gcc.target/i386/pr106347.c: New test case.
+
+2022-07-23 Immad Mir <mirimmad@outlook.com>
+
+ * gcc.dg/analyzer/fd-5.c: New test.
+ * gcc.dg/analyzer/fd-4.c: Remove quotes around 'read-only' and
+ 'write-only'.
+ * c-c++-common/attr-fd.c: New test.
+
+2022-07-22 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/106413
+ * gcc.dg/analyzer/torture/stdarg-4.c: New test.
+
+2022-07-22 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/106401
+ * gcc.dg/analyzer/memcpy-2.c: New test.
+
+2022-07-22 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/106366
+ * g++.dg/cpp1z/class-deduction112.C: New test.
+
+2022-07-22 Tim Lange <mail@tim-lange.me>
+
+ PR analyzer/106394
+ * gcc.dg/analyzer/pr106394.c: New test.
+
+2022-07-22 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/106397
+ * gcc.dg/pr106397.c: New testcase.
+
+2022-07-22 liuhongt <hongtao.liu@intel.com>
+
+ PR tree-optimization/106010
+ * gcc.dg/pr23911.c: Scan IMAGPART/REALPART_EXPR = ** instead
+ of __complex__ since COMPLEX_CST is lower to scalars.
+
+2022-07-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/pr106038-1.c: New test.
+
+2022-07-21 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/106383
+ * gcc.dg/analyzer/stdarg-3.c: New test.
+
+2022-07-21 Sam Feifer <sfeifer@redhat.com>
+
+ PR tree-optimization/94920
+ * g++.dg/pr94920-1.C: New test.
+ * g++.dg/pr94920.C: New test.
+ * gcc.dg/pr94920-2.c: New test.
+
+2022-07-21 Jason Merrill <jason@redhat.com>
+
+ PR c++/106361
+ * g++.dg/cpp2a/spaceship-eq14.C: New test.
+
+2022-07-21 Jason Merrill <jason@redhat.com>
+
+ DR 2084
+ PR c++/94823
+ * g++.dg/cpp0x/nsdmi-union7.C: New test.
+
+2022-07-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/106379
+ * gcc.dg/pr106379-1.c: New testcase.
+
+2022-07-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/106365
+ * gcc.target/i386/vec-maskstore-vn.c: New testcase.
+
+2022-07-21 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/106374
+ * gcc.dg/analyzer/untracked-2.c: New test.
+
2022-07-20 David Malcolm <dmalcolm@redhat.com>
PR analyzer/106373
diff --git a/gcc/testsuite/c-c++-common/attr-fd.c b/gcc/testsuite/c-c++-common/attr-fd.c
new file mode 100644
index 0000000..e4bb4ed
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-fd.c
@@ -0,0 +1,18 @@
+
+int not_a_fn __attribute__ ((fd_arg(1))); /* { dg-warning "'fd_arg' attribute only applies to function types" } */
+
+void f (char *p) __attribute__ ((fd_arg(1))); /* { dg-warning "'fd_arg' attribute argument value '1' refers to parameter type 'char ?\\\*'" } */
+
+
+int not_a_fn_b __attribute__ ((fd_arg_read(1))); /* { dg-warning "'fd_arg_read' attribute only applies to function types" } */
+
+void g (char *p) __attribute__ ((fd_arg_read(1))); /* { dg-warning "'fd_arg_read' attribute argument value '1' refers to parameter type 'char ?\\\*'" } */
+
+
+int not_a_fn_c __attribute__ ((fd_arg_write(1))); /* { dg-warning "'fd_arg_write' attribute only applies to function types" } */
+
+void f (char *p) __attribute__ ((fd_arg_write(1))); /* { dg-warning "'fd_arg_write' attribute argument value '1' refers to parameter type 'char ?\\\*'" } */
+
+
+void fn_a (int fd) __attribute__ ((fd_arg(0))); /* { dg-warning "'fd_arg' attribute argument value '0' does not refer to a function parameter" } */
+void fd_a_1 (int fd) __attribute__ ((fd_arg("notint"))); /* { dg-warning "'fd_arg' attribute argument has type ('char\\\[7\\\]'|'const char\\\*')" } */
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-union7.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-union7.C
new file mode 100644
index 0000000..e2e46f4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-union7.C
@@ -0,0 +1,13 @@
+// PR c++/98423
+// { dg-do compile { target c++11 } }
+
+struct A{
+ A(){}
+};
+union C{
+ A a;
+ int b = 0;
+};
+int main(){
+ C c;
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction112.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction112.C
new file mode 100644
index 0000000..8da5868
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction112.C
@@ -0,0 +1,14 @@
+// PR c++/106366
+// { dg-do compile { target c++17 } }
+
+#include <initializer_list>
+
+template<class T>
+struct A { A(...); };
+
+template<typename T>
+A(std::initializer_list<T>) -> A<T>;
+
+A a{1,2,3};
+using type = decltype(a);
+using type = A<int>;
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-eq14.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq14.C
new file mode 100644
index 0000000..896e523
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq14.C
@@ -0,0 +1,17 @@
+// PR c++/106361
+// { dg-do compile { target c++20 } }
+
+struct foo {
+ int x;
+};
+
+struct bar {
+ foo f; // { dg-error "operator==" }
+ friend bool operator==(const bar& a, const bar& b);
+};
+
+bool operator==(const bar& a, const bar& b) = default;
+
+int main() {
+ return bar{} == bar{}; // { dg-error "deleted" }
+}
diff --git a/gcc/testsuite/g++.dg/pr94920-1.C b/gcc/testsuite/g++.dg/pr94920-1.C
new file mode 100644
index 0000000..6c6483e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr94920-1.C
@@ -0,0 +1,17 @@
+/* PR tree-optimization/94920 */
+/* { dg-do run } */
+
+#include "pr94920.C"
+
+int main() {
+
+ if (foo(0) != 0
+ || foo(-42) != 42
+ || foo(42) != 42
+ || baz(-10) != 10
+ || baz(-10) != 10) {
+ __builtin_abort();
+ }
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/pr94920.C b/gcc/testsuite/g++.dg/pr94920.C
new file mode 100644
index 0000000..925ec4f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr94920.C
@@ -0,0 +1,63 @@
+/* PR tree-optimization/94920 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+typedef int __attribute__((vector_size(4*sizeof(int)))) vint;
+
+/* Same form as PR. */
+__attribute__((noipa)) unsigned int foo(int x) {
+ return (x >= 0 ? x : 0) + (x <= 0 ? -x : 0);
+}
+
+/* Test for forward propogation. */
+__attribute__((noipa)) unsigned int corge(int x) {
+ int w = (x >= 0 ? x : 0);
+ int y = -x;
+ int z = (y >= 0 ? y : 0);
+ return w + z;
+}
+
+/* Vector case. */
+__attribute__((noipa)) vint thud(vint x) {
+ vint t = (x >= 0 ? x : 0) ;
+ vint xx = -x;
+ vint t1 = (xx >= 0 ? xx : 0);
+ return t + t1;
+}
+
+/* Signed function. */
+__attribute__((noipa)) int bar(int x) {
+ return (x >= 0 ? x : 0) + (x <= 0 ? -x : 0);
+}
+
+/* Commutative property. */
+__attribute__((noipa)) unsigned int baz(int x) {
+ return (x <= 0 ? -x : 0) + (x >= 0 ? x : 0);
+}
+
+/* Flipped order for max expressions. */
+__attribute__((noipa)) unsigned int quux(int x) {
+ return (0 <= x ? x : 0) + (0 >= x ? -x : 0);
+}
+
+/* Not zero so should not optimize. */
+__attribute__((noipa)) unsigned int waldo(int x) {
+ return (x >= 4 ? x : 4) + (x <= 4 ? -x : 4);
+}
+
+/* Not zero so should not optimize. */
+__attribute__((noipa)) unsigned int fred(int x) {
+ return (x >= -4 ? x : -4) + (x <= -4 ? -x : -4);
+}
+
+/* Incorrect pattern. */
+__attribute__((noipa)) unsigned int goo(int x) {
+ return (x <= 0 ? x : 0) + (x >= 0 ? -x : 0);
+}
+
+/* Incorrect pattern. */
+__attribute__((noipa)) int qux(int x) {
+ return (x >= 0 ? x : 0) + (x >= 0 ? x : 0);
+}
+
+/* { dg-final {scan-tree-dump-times " ABS_EXPR " 6 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-4.c b/gcc/testsuite/gcc.dg/analyzer/fd-4.c
index fcfa616..4126346 100644
--- a/gcc/testsuite/gcc.dg/analyzer/fd-4.c
+++ b/gcc/testsuite/gcc.dg/analyzer/fd-4.c
@@ -17,9 +17,9 @@ test_1 (const char *path, void *buf)
if (fd >= 0) /* { dg-message "assuming 'fd' is a valid file descriptor \\(>= 0\\)" "event1" } */
/* { dg-message "following 'true' branch \\(when 'fd >= 0'\\)..." "event2" { target *-*-* } .-1 } */
{
- write (fd, buf, 1); /* { dg-warning "'write' on 'read-only' file descriptor 'fd'" "warning" } */
+ write (fd, buf, 1); /* { dg-warning "'write' on read-only file descriptor 'fd'" "warning" } */
/* { dg-message "\\(4\\) ...to here" "event1" { target *-*-* } .-1 } */
- /* { dg-message "\\(5\\) 'write' on 'read-only' file descriptor 'fd'" "event2" { target *-*-* } .-2 } */
+ /* { dg-message "\\(5\\) 'write' on read-only file descriptor 'fd'" "event2" { target *-*-* } .-2 } */
close (fd);
}
}
@@ -31,9 +31,9 @@ test_2 (const char *path, void *buf)
if (fd >= 0) /* { dg-message "assuming 'fd' is a valid file descriptor \\(>= 0\\)" "event1" } */
/* { dg-message "following 'true' branch \\(when 'fd >= 0'\\)..." "event2" { target *-*-* } .-1 } */
{
- read (fd, buf, 1); /* { dg-warning "'read' on 'write-only' file descriptor 'fd'" "warning" } */
+ read (fd, buf, 1); /* { dg-warning "'read' on write-only file descriptor 'fd'" "warning" } */
/* { dg-message "\\(4\\) ...to here" "event1" { target *-*-* } .-1 } */
- /* { dg-message "\\(5\\) 'read' on 'write-only' file descriptor 'fd'" "event2" { target *-*-* } .-2 } */
+ /* { dg-message "\\(5\\) 'read' on write-only file descriptor 'fd'" "event2" { target *-*-* } .-2 } */
close (fd);
}
}
diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-5.c b/gcc/testsuite/gcc.dg/analyzer/fd-5.c
new file mode 100644
index 0000000..8f29c11
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/fd-5.c
@@ -0,0 +1,53 @@
+int open(const char *, int mode);
+void close(int fd);
+int write (int fd, void *buf, int nbytes);
+int read (int fd, void *buf, int nbytes);
+
+#define O_RDONLY 0
+#define O_WRONLY 1
+#define O_RDWR 2
+
+void f (int fd) __attribute__((fd_arg(1))); /* { dg-message "argument 1 of 'f' must be an open file descriptor, due to '__attribute__\\(\\(fd_arg\\(1\\)\\)\\)'" } */
+
+void
+test_1 (const char *path)
+{
+ int fd = open (path, O_RDWR);
+ close(fd);
+ f(fd); /* { dg-warning "'f' on closed file descriptor 'fd'" } */
+ /* { dg-message "\\(3\\) 'f' on closed file descriptor 'fd'; 'close' was at \\(2\\)" "" { target *-*-* } .-1 } */
+}
+
+void g (int fd) __attribute__((fd_arg_read(1))); /* { dg-message "argument 1 of 'g' must be a readable file descriptor, due to '__attribute__\\(\\(fd_arg_read\\(1\\)\\)\\)'" } */
+
+void
+test_2 (const char *path)
+{
+ int fd = open (path, O_WRONLY);
+ if (fd != -1)
+ {
+ g (fd); /* { dg-warning "'g' on write-only file descriptor 'fd'" } */
+ }
+ close (fd);
+}
+
+void h (int fd) __attribute__((fd_arg_write(1))); /* { dg-message "argument 1 of 'h' must be a writable file descriptor, due to '__attribute__\\(\\(fd_arg_write\\(1\\)\\)\\)'" } */
+void
+test_3 (const char *path)
+{
+ int fd = open (path, O_RDONLY);
+ if (fd != -1)
+ {
+ h (fd); /* { dg-warning "'h' on read-only file descriptor 'fd'" } */
+ }
+ close(fd);
+}
+
+void ff (int fd) __attribute__((fd_arg(1))); /* { dg-message "argument 1 of 'ff' must be an open file descriptor, due to '__attribute__\\(\\(fd_arg\\(1\\)\\)\\)'" } */
+
+void test_4 (const char *path)
+{
+ int fd = open (path, O_RDWR);
+ ff (fd); /* { dg-warning "'ff' on possibly invalid file descriptor 'fd'" } */
+ close(fd);
+} \ No newline at end of file
diff --git a/gcc/testsuite/gcc.dg/analyzer/memcpy-2.c b/gcc/testsuite/gcc.dg/analyzer/memcpy-2.c
new file mode 100644
index 0000000..88ec84c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/memcpy-2.c
@@ -0,0 +1,8 @@
+/* { dg-additional-options "-Wno-stringop-overflow" } */
+
+void
+main (int c, void *v)
+{
+ static char a[] = "";
+ __builtin_memcpy (v, a, -1);
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr106394.c b/gcc/testsuite/gcc.dg/analyzer/pr106394.c
new file mode 100644
index 0000000..96bb175
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr106394.c
@@ -0,0 +1,19 @@
+struct msm_gpu {
+ // [...snip...]
+ const struct msm_gpu_perfcntr *perfcntrs;
+ // [...snip...]
+};
+
+struct msm_gpu_perfcntr {
+ // [...snip...]
+ const char *name;
+};
+
+static const struct msm_gpu_perfcntr perfcntrs[] = {};
+
+struct msm_gpu *test(struct msm_gpu *gpu) {
+ // [...snip...]
+ gpu->perfcntrs = perfcntrs;
+ // [...snip...]
+ return gpu;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/stdarg-3.c b/gcc/testsuite/gcc.dg/analyzer/stdarg-3.c
new file mode 100644
index 0000000..6814614
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/stdarg-3.c
@@ -0,0 +1,57 @@
+typedef __builtin_va_list va_list;
+
+struct printf_spec {
+ unsigned int type;
+};
+
+int
+format_decode(const char *fmt, struct printf_spec *spec);
+
+static int vbin_printf(const char *fmt, va_list args) {
+ struct printf_spec spec;
+ int width = 0;
+
+ while (*fmt) {
+ int read = format_decode(fmt, &spec);
+
+ fmt += read;
+
+ switch (spec.type) {
+ case 0:
+ break;
+ case 1:
+ width = __builtin_va_arg(args, int); /* { dg-bogus "-Wanalyzer-va-list-exhausted" } */
+ break;
+ }
+ }
+
+ return width;
+}
+
+int bprintf(const char *fmt, ...) {
+ va_list args;
+ int ret;
+
+ __builtin_va_start(args, fmt);
+ ret = vbin_printf(fmt, args);
+ __builtin_va_end(args);
+
+ return ret;
+}
+
+static int called_by_test_2 (va_list args)
+{
+ return __builtin_va_arg(args, int); /* { dg-bogus "-Wanalyzer-va-list-exhausted" } */
+}
+
+int test_2 (const char *fmt, ...)
+{
+ va_list args;
+ int ret;
+
+ __builtin_va_start (args, fmt);
+ ret = called_by_test_2 (args);
+ __builtin_va_end (args);
+
+ return ret;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/stdarg-4.c b/gcc/testsuite/gcc.dg/analyzer/torture/stdarg-4.c
new file mode 100644
index 0000000..8275b0f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/torture/stdarg-4.c
@@ -0,0 +1,329 @@
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
+
+#include "../analyzer-decls.h"
+
+/* va_arg in loop, with no caller to function containing va_start. */
+
+int test_1a (const char *fmt, ...)
+{
+ __builtin_va_list args;
+ int sum = 0;
+ char ch;
+
+ __builtin_va_start(args, fmt);
+
+ while (ch = *fmt++)
+ if (ch == '%')
+ sum += __builtin_va_arg(args, int);
+
+ __builtin_va_end(args);
+
+ return sum;
+}
+
+/* va_arg in loop, with no caller to function containing va_start. */
+
+static int test_1b_callee (const char *fmt, __builtin_va_list args)
+{
+ int sum = 0;
+ char ch;
+
+ while (ch = *fmt++)
+ if (ch == '%')
+ sum += __builtin_va_arg(args, int);
+
+ return sum;
+}
+
+int test_1b_caller (const char *fmt, ...)
+{
+ __builtin_va_list args;
+ int sum = 0;
+
+ __builtin_va_start(args, fmt);
+
+ sum = test_1b_callee (fmt, args);
+
+ __builtin_va_end(args);
+
+ return sum;
+}
+
+/* va_arg in loop, with a caller to the function containing va_start,
+ with specific args. */
+
+static int
+test_1c_inner (const char *fmt, __builtin_va_list args)
+{
+ int sum = 0;
+ char ch;
+
+ while (ch = *fmt++)
+ if (ch == '%')
+ sum += __builtin_va_arg(args, int);
+
+ return sum;
+}
+
+static int
+test_1c_middle (const char *fmt, ...)
+{
+ __builtin_va_list args;
+ int sum = 0;
+
+ __builtin_va_start(args, fmt);
+
+ sum = test_1c_inner (fmt, args);
+
+ __builtin_va_end(args);
+
+ return sum;
+}
+
+void test_1c_outer (void)
+{
+ int sum = test_1c_middle ("%%", 42, 17);
+
+ __analyzer_describe (0, sum); /* { dg-message "'\\(int\\)59'" } */
+}
+
+/* va_arg in loop, with no caller to function containing va_start. */
+
+int test_2a (int count, ...)
+{
+ __builtin_va_list args;
+ int sum = 0;
+ char ch;
+
+ __builtin_va_start(args, count);
+
+ while (count-- > 0)
+ sum += __builtin_va_arg(args, int);
+
+ __builtin_va_end(args);
+
+ return sum;
+}
+
+/* va_arg in loop, with no caller to function containing va_start. */
+
+static int test_2b_callee (int count, __builtin_va_list args)
+{
+ int sum = 0;
+
+ while (count-- > 0)
+ sum += __builtin_va_arg(args, int);
+
+ return sum;
+}
+
+int test_2b_caller (int count, ...)
+{
+ __builtin_va_list args;
+ int sum = 0;
+
+ __builtin_va_start(args, count);
+
+ sum = test_2b_callee (count, args);
+
+ __builtin_va_end(args);
+
+ return sum;
+}
+
+/* va_arg in loop, with a caller to the function containing va_start,
+ with specific args. */
+
+static int test_2c_inner (int count, __builtin_va_list args)
+{
+ int sum = 0;
+
+ while (count-- > 0)
+ sum += __builtin_va_arg(args, int);
+
+ return sum;
+}
+
+int test_2c_middle (int count, ...)
+{
+ __builtin_va_list args;
+ int sum = 0;
+
+ __builtin_va_start(args, count);
+
+ sum = test_2c_inner (count, args);
+
+ __builtin_va_end(args);
+
+ return sum;
+}
+
+void test_2c_outer (void)
+{
+ int sum = test_2c_middle (2, 50, 42);
+
+ __analyzer_describe (0, sum); /* { dg-message "'\\(int\\)92'" } */
+}
+
+/* va_arg in loop, with no caller to function containing va_start. */
+
+int test_3a (int placeholder, ...)
+{
+ __builtin_va_list args;
+ int sum = 0;
+ int val;
+
+ __builtin_va_start(args, placeholder);
+
+ while (val = __builtin_va_arg(args, int))
+ sum += val;
+
+ __builtin_va_end(args);
+
+ return sum;
+}
+
+/* va_arg in loop, with no caller to function containing va_start. */
+
+static int test_3b_callee (__builtin_va_list args)
+{
+ int sum = 0;
+ int val;
+ while (val = __builtin_va_arg(args, int))
+ sum += val;
+ return sum;
+}
+
+int test_3b_caller (int placeholder, ...)
+{
+ __builtin_va_list args;
+ int sum = 0;
+
+ __builtin_va_start(args, placeholder);
+
+ sum = test_3b_callee (args);
+
+ __builtin_va_end(args);
+
+ return sum;
+}
+
+/* va_arg in loop, with a caller to the function containing va_start,
+ with specific args. */
+
+static int test_3c_inner (__builtin_va_list args)
+{
+ int sum = 0;
+ int val;
+ while (val = __builtin_va_arg(args, int))
+ sum += val;
+ return sum;
+}
+
+int test_3c_middle (int placeholder, ...)
+{
+ __builtin_va_list args;
+ int sum = 0;
+
+ __builtin_va_start(args, placeholder);
+
+ sum = test_3c_inner (args);
+
+ __builtin_va_end(args);
+
+ return sum;
+}
+
+void test_3c_outer (void)
+{
+ int sum = test_3c_middle (0, 5, 12, 0);
+ __analyzer_describe (0, sum); /* { dg-message "'\\(int\\)17'" } */
+}
+
+/* va_arg in loop, with no caller to function containing va_start,
+ with a va_copy. */
+
+static int test_3d_callee (__builtin_va_list args)
+{
+ int sum = 0;
+ int val;
+ while (val = __builtin_va_arg(args, int))
+ sum += val;
+ return sum;
+}
+
+int test_3d_caller (int placeholder, ...)
+{
+ __builtin_va_list args1, args2;
+ int sum = 0;
+
+ __builtin_va_start(args1, placeholder);
+ __builtin_va_copy (args2, args1);
+
+ sum = test_3d_callee (args1);
+ __builtin_va_end(args1);
+
+ sum += test_3d_callee (args2);
+ __builtin_va_end(args2);
+
+ return sum;
+}
+
+/* va_arg in loop, with a caller to the function containing va_start,
+ with specific args, with a va_copy. */
+
+static int test_3e_inner (__builtin_va_list args)
+{
+ int sum = 0;
+ int val;
+ while (val = __builtin_va_arg(args, int))
+ sum += val;
+ return sum;
+}
+
+int test_3e_middle (int placeholder, ...)
+{
+ __builtin_va_list args1, args2;
+ int sum = 0;
+
+ __builtin_va_start(args1, placeholder);
+ __builtin_va_copy (args2, args1);
+
+ sum = test_3e_inner (args1);
+ __builtin_va_end(args1);
+
+ sum += test_3e_inner (args2);
+ __builtin_va_end(args2);
+
+ return sum;
+}
+
+void test_3e_outer (void)
+{
+ int sum = test_3e_middle (0, 5, 6, 0);
+ __analyzer_describe (0, sum); /* { dg-message "'\\(int\\)22'" } */
+}
+
+/* va_arg in loop, with specific symbolic args. */
+
+static int test_3f_callee (int placeholder, ...)
+{
+ __builtin_va_list args;
+ int sum = 0;
+ int val;
+
+ __builtin_va_start(args, placeholder);
+
+ while (val = __builtin_va_arg(args, int))
+ sum += val;
+
+ __builtin_va_end(args);
+
+ return sum;
+}
+
+void test_3f_caller (int x, int y, int z)
+{
+ int sum = test_3f_callee (0, x, y, z, 0);
+ __analyzer_describe (0, sum); /* { dg-message "'UNKNOWN\\(int\\)'" } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr106397.c b/gcc/testsuite/gcc.dg/pr106397.c
new file mode 100644
index 0000000..a6b2e91
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr106397.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fprefetch-loop-arrays --param l2-cache-size=0 --param prefetch-latency=3 -fprefetch-loop-arrays" } */
+
+int
+bar (void)
+{
+ /* No return statement. */
+}
+
+__attribute__ ((simd)) int
+foo (void)
+{
+ if (bar ())
+ return 0;
+
+ __builtin_unreachable ();
+}
diff --git a/gcc/testsuite/gcc.dg/pr23911.c b/gcc/testsuite/gcc.dg/pr23911.c
index 3fa0412..691f350 100644
--- a/gcc/testsuite/gcc.dg/pr23911.c
+++ b/gcc/testsuite/gcc.dg/pr23911.c
@@ -16,5 +16,6 @@ test (void)
/* After DCE2 which runs after FRE, the expressions should be fully
constant folded. There should be no loads from b left. */
-/* { dg-final { scan-tree-dump-times "__complex__ \\\(1.0e\\\+0, 0.0\\\)" 2 "dce3" } } */
+/* { dg-final { scan-tree-dump-times {(?n)REALPART_EXPR.*= 1\.0e\+0} 2 "dce3" } } */
+/* { dg-final { scan-tree-dump-times {(?n)IMAGPART_EXPR.*= 0\.0} 2 "dce3" } } */
/* { dg-final { scan-tree-dump-times "= b" 0 "dce3" } } */
diff --git a/gcc/testsuite/gcc.dg/pr94920-2.c b/gcc/testsuite/gcc.dg/pr94920-2.c
new file mode 100644
index 0000000..a2d2332
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr94920-2.c
@@ -0,0 +1,15 @@
+/* PR tree-optimization/94920 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+/* Form from PR. */
+__attribute__((noipa)) unsigned int foo(int x) {
+ return x <= 0 ? -x : 0;
+}
+
+/* Changed order. */
+__attribute__((noipa)) unsigned int bar(int x) {
+ return 0 >= x ? -x : 0;
+}
+
+/* { dg-final {scan-tree-dump-times " MAX_EXPR " 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr106038-1.c b/gcc/testsuite/gcc.target/i386/pr106038-1.c
new file mode 100644
index 0000000..bb52385
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr106038-1.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-msse2 -O2" } */
+/* { dg-final { scan-assembler-not "xmm" } } */
+
+void
+foo3 (char* a, char* __restrict b)
+{
+ a[0] &= 1;
+ a[1] &= 2;
+ a[2] &= 3;
+ a[3] &= 3;
+}
+
+void
+foo4 (char* a, char* __restrict b)
+{
+ a[0] &= 1;
+ a[1] &= 2;
+}
+
+
+void
+foo1 (short* a, short* __restrict b)
+{
+ a[0] &= 1;
+ a[1] &= 2;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr106303.c b/gcc/testsuite/gcc.target/i386/pr106303.c
new file mode 100644
index 0000000..19cce40
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr106303.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-inline-small-functions" } */
+
+struct a {
+ int b;
+ int c;
+ int d;
+ int e;
+} i, j;
+int f, g, h;
+struct a k() {
+ while (f)
+ i = j;
+ if (g) {
+ for (; h; h++)
+ i = j;
+ return j;
+ }
+ return i;
+}
+int main() {
+ k();
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/pr106347.c b/gcc/testsuite/gcc.target/i386/pr106347.c
new file mode 100644
index 0000000..003dd1b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr106347.c
@@ -0,0 +1,24 @@
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2 -fno-expensive-optimizations" } */
+
+__int128 m;
+int n;
+
+__attribute__ ((noinline)) int
+return_zero (void)
+{
+ return 0;
+}
+
+void
+foo (void)
+{
+ while (m < 0)
+ {
+ if (n || return_zero ())
+ __builtin_trap ();
+
+ ++m;
+ }
+}
+
diff --git a/gcc/tree-ssa-dom.cc b/gcc/tree-ssa-dom.cc
index f5e8f57..44dc27b 100644
--- a/gcc/tree-ssa-dom.cc
+++ b/gcc/tree-ssa-dom.cc
@@ -1233,20 +1233,22 @@ dom_opt_dom_walker::set_global_ranges_from_unreachable_edges (basic_block bb)
gimple *stmt = last_stmt (pred_e->src);
tree name;
- int_range_max r;
if (stmt
&& gimple_code (stmt) == GIMPLE_COND
&& (name = gimple_cond_lhs (stmt))
&& TREE_CODE (name) == SSA_NAME
- && r.supports_type_p (TREE_TYPE (name))
&& assert_unreachable_fallthru_edge_p (pred_e)
- && all_uses_feed_or_dominated_by_stmt (name, stmt)
- && m_ranger->range_on_edge (r, pred_e, name)
- && !r.varying_p ()
- && !r.undefined_p ())
+ && all_uses_feed_or_dominated_by_stmt (name, stmt))
{
- set_range_info (name, r);
- maybe_set_nonzero_bits (pred_e, name);
+ Value_Range r (TREE_TYPE (name));
+
+ if (m_ranger->range_on_edge (r, pred_e, name)
+ && !r.varying_p ()
+ && !r.undefined_p ())
+ {
+ set_range_info (name, r);
+ maybe_set_nonzero_bits (pred_e, name);
+ }
}
}
diff --git a/gcc/tree-ssa-loop-prefetch.cc b/gcc/tree-ssa-loop-prefetch.cc
index 8f190ae..b6690b0 100644
--- a/gcc/tree-ssa-loop-prefetch.cc
+++ b/gcc/tree-ssa-loop-prefetch.cc
@@ -1308,8 +1308,6 @@ emit_mfence_after_loop (class loop *loop)
gsi_insert_before (&bsi, call, GSI_NEW_STMT);
}
-
- update_ssa (TODO_update_ssa_only_virtuals);
}
/* Returns true if we can use storent in loop, false otherwise. */
@@ -1340,23 +1338,27 @@ may_use_storent_in_loop_p (class loop *loop)
}
/* Marks nontemporal stores in LOOP. GROUPS contains the description of memory
- references in the loop. */
+ references in the loop. Returns whether we inserted any mfence call. */
-static void
+static bool
mark_nontemporal_stores (class loop *loop, struct mem_ref_group *groups)
{
struct mem_ref *ref;
bool any = false;
if (!may_use_storent_in_loop_p (loop))
- return;
+ return false;
for (; groups; groups = groups->next)
for (ref = groups->refs; ref; ref = ref->next)
any |= mark_nontemporal_store (ref);
if (any && FENCE_FOLLOWING_MOVNT != NULL_TREE)
- emit_mfence_after_loop (loop);
+ {
+ emit_mfence_after_loop (loop);
+ return true;
+ }
+ return false;
}
/* Determines whether we can profitably unroll LOOP FACTOR times, and if
@@ -1874,10 +1876,11 @@ insn_to_prefetch_ratio_too_small_p (unsigned ninsns, unsigned prefetch_count,
/* Issue prefetch instructions for array references in LOOP. Returns
- true if the LOOP was unrolled. */
+ true if the LOOP was unrolled and updates NEED_LC_SSA_UPDATE if we need
+ to update SSA for virtual operands and LC SSA for a split edge. */
static bool
-loop_prefetch_arrays (class loop *loop)
+loop_prefetch_arrays (class loop *loop, bool &need_lc_ssa_update)
{
struct mem_ref_group *refs;
unsigned ahead, ninsns, time, unroll_factor;
@@ -1952,7 +1955,7 @@ loop_prefetch_arrays (class loop *loop)
unroll_factor))
goto fail;
- mark_nontemporal_stores (loop, refs);
+ need_lc_ssa_update |= mark_nontemporal_stores (loop, refs);
/* Step 4: what to prefetch? */
if (!schedule_prefetches (refs, unroll_factor, ahead))
@@ -1980,6 +1983,7 @@ unsigned int
tree_ssa_prefetch_arrays (void)
{
bool unrolled = false;
+ bool need_lc_ssa_update = false;
int todo_flags = 0;
if (!targetm.have_prefetch ()
@@ -2028,12 +2032,15 @@ tree_ssa_prefetch_arrays (void)
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Processing loop %d:\n", loop->num);
- unrolled |= loop_prefetch_arrays (loop);
+ unrolled |= loop_prefetch_arrays (loop, need_lc_ssa_update);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\n\n");
}
+ if (need_lc_ssa_update)
+ rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa_only_virtuals);
+
if (unrolled)
{
scev_reset ();
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index 7d947b5..a1f6f30 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -3221,11 +3221,6 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
{
gcall *call = as_a <gcall *> (def_stmt);
internal_fn fn = gimple_call_internal_fn (call);
- tree def_rhs = gimple_call_arg (call,
- internal_fn_stored_value_index (fn));
- def_rhs = vn_valueize (def_rhs);
- if (TREE_CODE (def_rhs) != VECTOR_CST)
- return (void *)-1;
tree mask = NULL_TREE, len = NULL_TREE, bias = NULL_TREE;
switch (fn)
@@ -3245,6 +3240,12 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
default:
return (void *)-1;
}
+ tree def_rhs = gimple_call_arg (call,
+ internal_fn_stored_value_index (fn));
+ def_rhs = vn_valueize (def_rhs);
+ if (TREE_CODE (def_rhs) != VECTOR_CST)
+ return (void *)-1;
+
ao_ref_init_from_ptr_and_size (&lhs_ref,
vn_valueize (gimple_call_arg (call, 0)),
TYPE_SIZE_UNIT (TREE_TYPE (def_rhs)));
diff --git a/gcc/tree-ssanames.cc b/gcc/tree-ssanames.cc
index 9389454..5c5d0e3 100644
--- a/gcc/tree-ssanames.cc
+++ b/gcc/tree-ssanames.cc
@@ -489,13 +489,12 @@ get_nonzero_bits (const_tree name)
return wi::shwi (-1, precision);
}
- if (!range_info_p (name))
+ if (!range_info_p (name) || !irange::supports_p (TREE_TYPE (name)))
return wi::shwi (-1, precision);
/* Optimization to get at the nonzero bits because we know the
storage type. This saves us measurable time compared to going
through vrange_storage. */
- gcc_checking_assert (irange::supports_p (TREE_TYPE (name)));
irange_storage_slot *ri
= static_cast <irange_storage_slot *> (SSA_NAME_RANGE_INFO (name));
return ri->get_nonzero_bits ();
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index 01d982e..f582d23 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -10017,7 +10017,10 @@ vectorizable_load (vec_info *vinfo,
(NULL_TREE, BIT_AND_EXPR, ptr,
build_int_cst
(TREE_TYPE (ptr), -(HOST_WIDE_INT) align));
- ptr = copy_ssa_name (ptr, new_stmt);
+ if (TREE_CODE (ptr) == SSA_NAME)
+ ptr = copy_ssa_name (ptr, new_stmt);
+ else
+ ptr = make_ssa_name (TREE_TYPE (ptr), new_stmt);
gimple_assign_set_lhs (new_stmt, ptr);
vect_finish_stmt_generation (vinfo, stmt_info,
new_stmt, gsi);
diff --git a/gcc/value-query.cc b/gcc/value-query.cc
index 51911bd..decf5aa 100644
--- a/gcc/value-query.cc
+++ b/gcc/value-query.cc
@@ -167,6 +167,7 @@ range_query::free_value_range_equiv (value_range_equiv *v)
const class value_range_equiv *
range_query::get_value_range (const_tree expr, gimple *stmt)
{
+ gcc_checking_assert (value_range_equiv::supports_p (TREE_TYPE (expr)));
int_range_max r;
if (range_of_expr (r, const_cast<tree> (expr), stmt))
return new (equiv_alloc->allocate ()) value_range_equiv (r);
@@ -280,16 +281,13 @@ get_ssa_name_range_info (vrange &r, const_tree name)
void *ri = SSA_NAME_RANGE_INFO (name);
- // Return VR_VARYING for SSA_NAMEs with NULL RANGE_INFO or SSA_NAMEs
- // with integral types width > 2 * HOST_BITS_PER_WIDE_INT precision.
- if (!ri || (GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (TREE_TYPE (name)))
- > 2 * HOST_BITS_PER_WIDE_INT))
- r.set_varying (type);
- else
+ if (ri)
{
vrange_storage vstore (NULL);
vstore.get_vrange (ri, r, TREE_TYPE (name));
}
+ else
+ r.set_varying (type);
}
// Return nonnull attribute of pointer NAME from SSA_NAME_PTR_INFO.
diff --git a/gcc/value-range-pretty-print.cc b/gcc/value-range-pretty-print.cc
index b795e92..485612f 100644
--- a/gcc/value-range-pretty-print.cc
+++ b/gcc/value-range-pretty-print.cc
@@ -109,3 +109,44 @@ vrange_printer::print_irange_bitmasks (const irange &r) const
print_hex (nz, buf);
pp_string (pp, buf);
}
+
+// Print an frange.
+
+void
+vrange_printer::visit (const frange &r) const
+{
+ pp_string (pp, "[frange] ");
+ if (r.undefined_p ())
+ {
+ pp_string (pp, "UNDEFINED");
+ return;
+ }
+ dump_generic_node (pp, r.type (), 0, TDF_NONE, false);
+ pp_string (pp, " ");
+ if (r.varying_p ())
+ {
+ pp_string (pp, "VARYING");
+ return;
+ }
+ print_frange_prop ("NAN", r.get_nan ());
+ print_frange_prop ("INF", r.get_inf ());
+ print_frange_prop ("NINF", r.get_ninf ());
+}
+
+// Print the FP properties in an frange.
+
+void
+vrange_printer::print_frange_prop (const char *str, const fp_prop &prop) const
+{
+ if (prop.varying_p ())
+ return;
+
+ if (prop.yes_p ())
+ pp_string (pp, str);
+ else if (prop.no_p ())
+ {
+ pp_character (pp, '!');
+ pp_string (pp, str);
+ }
+ pp_character (pp, ' ');
+}
diff --git a/gcc/value-range-pretty-print.h b/gcc/value-range-pretty-print.h
index 6d2fb74..c1c7c42 100644
--- a/gcc/value-range-pretty-print.h
+++ b/gcc/value-range-pretty-print.h
@@ -27,9 +27,11 @@ public:
vrange_printer (pretty_printer *pp_) : pp (pp_) { }
void visit (const unsupported_range &) const override;
void visit (const irange &) const override;
+ void visit (const frange &) const override;
private:
void print_irange_bound (tree bound) const;
void print_irange_bitmasks (const irange &) const;
+ void print_frange_prop (const char *str, const fp_prop &) const;
pretty_printer *pp;
};
diff --git a/gcc/value-range-storage.h b/gcc/value-range-storage.h
index 7e005e4..5a3336b 100644
--- a/gcc/value-range-storage.h
+++ b/gcc/value-range-storage.h
@@ -39,6 +39,7 @@ public:
template <typename T> T *clone (const T &src);
private:
irange *alloc_irange (unsigned pairs);
+ frange *alloc_frange ();
void operator= (const vrange_allocator &) = delete;
};
@@ -142,7 +143,9 @@ vrange_allocator::alloc_vrange (tree type)
{
if (irange::supports_p (type))
return alloc_irange (2);
-
+ if (frange::supports_p (type))
+ return alloc_frange ();
+ return NULL;
gcc_unreachable ();
}
@@ -164,6 +167,13 @@ vrange_allocator::alloc_irange (unsigned num_pairs)
return new (r) irange (mem, num_pairs);
}
+inline frange *
+vrange_allocator::alloc_frange ()
+{
+ void *r = alloc (sizeof (frange));
+ return new (r) frange ();
+}
+
// Return a clone of an irange.
template <>
@@ -175,6 +185,17 @@ vrange_allocator::clone <irange> (const irange &src)
return r;
}
+// Return a clone of an frange.
+
+template <>
+inline frange *
+vrange_allocator::clone <frange> (const frange &src)
+{
+ frange *r = alloc_frange ();
+ *r = src;
+ return r;
+}
+
// Return a clone of a vrange.
template <>
@@ -183,7 +204,9 @@ vrange_allocator::clone <vrange> (const vrange &src)
{
if (is_a <irange> (src))
return clone <irange> (as_a <irange> (src));
-
+ if (is_a <frange> (src))
+ return clone <frange> (as_a <frange> (src));
+ return NULL;
gcc_unreachable ();
}
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 525e192..e49b06d 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -195,12 +195,12 @@ vrange &
vrange::operator= (const vrange &src)
{
if (is_a <irange> (src))
- {
- as_a <irange> (*this) = as_a <irange> (src);
- return *this;
- }
+ as_a <irange> (*this) = as_a <irange> (src);
+ else if (is_a <frange> (src))
+ as_a <frange> (*this) = as_a <frange> (src);
else
gcc_unreachable ();
+ return *this;
}
// Equality operator for generic ranges.
@@ -210,6 +210,8 @@ vrange::operator== (const vrange &src) const
{
if (is_a <irange> (src))
return as_a <irange> (*this) == as_a <irange> (src);
+ if (is_a <frange> (src))
+ return as_a <frange> (*this) == as_a <frange> (src);
gcc_unreachable ();
}
@@ -252,6 +254,191 @@ unsupported_range::unsupported_range ()
set_undefined ();
}
+void
+frange::accept (const vrange_visitor &v) const
+{
+ v.visit (*this);
+}
+
+// Setter for franges. Currently only singletons are supported.
+
+void
+frange::set (tree min, tree max, value_range_kind kind)
+{
+ gcc_checking_assert (kind == VR_RANGE);
+ gcc_checking_assert (operand_equal_p (min, max));
+ gcc_checking_assert (TREE_CODE (min) == REAL_CST);
+
+ m_kind = kind;
+ m_type = TREE_TYPE (min);
+
+ REAL_VALUE_TYPE *const cst = TREE_REAL_CST_PTR (min);
+ if (real_isnan (cst))
+ m_props.nan_set_yes ();
+ else
+ m_props.nan_set_no ();
+
+ if (real_isinf (cst))
+ {
+ if (real_isneg (cst))
+ {
+ m_props.inf_set_no ();
+ m_props.ninf_set_yes ();
+ }
+ else
+ {
+ m_props.inf_set_yes ();
+ m_props.ninf_set_no ();
+ }
+ }
+ else
+ {
+ m_props.inf_set_no ();
+ m_props.ninf_set_no ();
+ }
+
+ if (flag_checking)
+ verify_range ();
+}
+
+// Normalize range to VARYING or UNDEFINED, or vice versa.
+//
+// A range with no known properties can be dropped to VARYING.
+// Similarly, a VARYING with any properties should be dropped to a
+// VR_RANGE. Normalizing ranges upon changing them ensures there is
+// only one representation for a given range.
+
+void
+frange::normalize_kind ()
+{
+ if (m_kind == VR_RANGE)
+ {
+ // No FP properties set means varying.
+ if (m_props.nan_varying_p ()
+ && m_props.inf_varying_p ()
+ && m_props.ninf_varying_p ())
+ {
+ set_varying (m_type);
+ return;
+ }
+ // Undefined is viral.
+ if (m_props.nan_undefined_p ()
+ || m_props.inf_undefined_p ()
+ || m_props.ninf_undefined_p ())
+ {
+ set_undefined ();
+ return;
+ }
+ }
+ else if (m_kind == VR_VARYING)
+ {
+ // If a VARYING has any FP properties, it's no longer VARYING.
+ if (!m_props.nan_varying_p ()
+ || !m_props.inf_varying_p ()
+ || !m_props.ninf_varying_p ())
+ m_kind = VR_RANGE;
+ }
+}
+
+bool
+frange::union_ (const vrange &v)
+{
+ const frange &r = as_a <frange> (v);
+
+ if (r.undefined_p () || varying_p ())
+ return false;
+ if (undefined_p () || r.varying_p ())
+ {
+ *this = r;
+ return true;
+ }
+
+ bool ret = m_props.union_ (r.m_props);
+ normalize_kind ();
+
+ if (flag_checking)
+ verify_range ();
+ return ret;
+}
+
+bool
+frange::intersect (const vrange &v)
+{
+ const frange &r = as_a <frange> (v);
+
+ if (undefined_p () || r.varying_p ())
+ return false;
+ if (r.undefined_p ())
+ {
+ set_undefined ();
+ return true;
+ }
+ if (varying_p ())
+ {
+ *this = r;
+ return true;
+ }
+
+ bool ret = m_props.intersect (r.m_props);
+ normalize_kind ();
+
+ if (flag_checking)
+ verify_range ();
+ return ret;
+}
+
+frange &
+frange::operator= (const frange &src)
+{
+ m_kind = src.m_kind;
+ m_type = src.m_type;
+ m_props = src.m_props;
+
+ if (flag_checking)
+ verify_range ();
+ return *this;
+}
+
+bool
+frange::operator== (const frange &src) const
+{
+ if (m_kind == src.m_kind)
+ {
+ if (undefined_p ())
+ return true;
+
+ if (varying_p ())
+ return types_compatible_p (m_type, src.m_type);
+
+ return m_props == src.m_props;
+ }
+ return false;
+}
+
+bool
+frange::supports_type_p (tree type) const
+{
+ return supports_p (type);
+}
+
+void
+frange::verify_range ()
+{
+ if (undefined_p ())
+ {
+ gcc_checking_assert (m_props.undefined_p ());
+ return;
+ }
+ else if (varying_p ())
+ {
+ gcc_checking_assert (m_props.varying_p ());
+ return;
+ }
+
+ gcc_checking_assert (m_kind == VR_RANGE);
+ gcc_checking_assert (!m_props.varying_p () && !m_props.undefined_p ());
+}
+
// Here we copy between any two irange's. The ranges can be legacy or
// multi-ranges, and copying between any combination works correctly.
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 4af92fd..e43fbe3 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -45,6 +45,8 @@ enum value_range_discriminator
{
// Range holds an integer or pointer.
VR_IRANGE,
+ // Floating point range.
+ VR_FRANGE,
// Range holds an unsupported type.
VR_UNKNOWN
};
@@ -252,6 +254,117 @@ public:
virtual void accept (const vrange_visitor &v) const override;
};
+// Floating point property to represent possible values of a NAN, INF, etc.
+
+class fp_prop
+{
+public:
+ enum kind {
+ UNDEFINED = 0x0, // Prop is impossible.
+ YES = 0x1, // Prop is definitely set.
+ NO = 0x2, // Prop is definitely not set.
+ VARYING = (YES | NO) // Prop may hold.
+ };
+ fp_prop (kind f) : m_kind (f) { }
+ bool varying_p () const { return m_kind == VARYING; }
+ bool undefined_p () const { return m_kind == UNDEFINED; }
+ bool yes_p () const { return m_kind == YES; }
+ bool no_p () const { return m_kind == NO; }
+private:
+ unsigned char m_kind : 2;
+};
+
+// Accessors for individual FP properties.
+
+#define FP_PROP_ACCESSOR(NAME) \
+ void NAME##_set_varying () { u.bits.NAME = fp_prop::VARYING; } \
+ void NAME##_set_yes () { u.bits.NAME = fp_prop::YES; } \
+ void NAME##_set_no () { u.bits.NAME = fp_prop::NO; } \
+ bool NAME##_varying_p () const { return u.bits.NAME == fp_prop::VARYING; } \
+ bool NAME##_undefined_p () const { return u.bits.NAME == fp_prop::UNDEFINED; } \
+ bool NAME##_yes_p () const { return u.bits.NAME == fp_prop::YES; } \
+ bool NAME##_no_p () const { return u.bits.NAME == fp_prop::NO; } \
+ fp_prop get_##NAME () const \
+ { return fp_prop ((fp_prop::kind) u.bits.NAME); } \
+ void set_##NAME (fp_prop::kind f) { u.bits.NAME = f; }
+
+// Aggregate of all the FP properties in an frange packed into one
+// structure to save space. Using explicit fp_prop's in the frange,
+// would take one byte per property because of padding. Instead, we
+// can save all properties into one byte.
+
+class frange_props
+{
+public:
+ frange_props () { set_varying (); }
+ void set_varying () { u.bytes = 0xff; }
+ void set_undefined () { u.bytes = 0; }
+ bool varying_p () { return u.bytes == 0xff; }
+ bool undefined_p () { return u.bytes == 0; }
+ bool union_ (const frange_props &other);
+ bool intersect (const frange_props &other);
+ bool operator== (const frange_props &other) const;
+ FP_PROP_ACCESSOR(nan)
+ FP_PROP_ACCESSOR(inf)
+ FP_PROP_ACCESSOR(ninf)
+private:
+ union {
+ struct {
+ unsigned char nan : 2;
+ unsigned char inf : 2;
+ unsigned char ninf : 2;
+ } bits;
+ unsigned char bytes;
+ } u;
+};
+
+// Accessors for getting/setting all FP properties at once.
+
+#define FRANGE_PROP_ACCESSOR(NAME) \
+ fp_prop get_##NAME () const { return m_props.get_##NAME (); } \
+ void set_##NAME (fp_prop::kind f) \
+ { \
+ m_props.set_##NAME (f); \
+ normalize_kind (); \
+ }
+
+// A floating point range.
+
+class frange : public vrange
+{
+ friend class frange_storage_slot;
+public:
+ frange ();
+ frange (const frange &);
+ static bool supports_p (tree type)
+ {
+ // Disabled until floating point range-ops come live.
+ return 0 && SCALAR_FLOAT_TYPE_P (type);
+ }
+ virtual tree type () const override;
+ virtual void set (tree, tree, value_range_kind = VR_RANGE) override;
+ virtual void set_varying (tree type) override;
+ virtual void set_undefined () override;
+ virtual bool union_ (const vrange &) override;
+ virtual bool intersect (const vrange &) override;
+ virtual bool supports_type_p (tree type) const override;
+ virtual void accept (const vrange_visitor &v) const override;
+ frange& operator= (const frange &);
+ bool operator== (const frange &) const;
+ bool operator!= (const frange &r) const { return !(*this == r); }
+
+ // Each fp_prop can be accessed with get_PROP() and set_PROP().
+ FRANGE_PROP_ACCESSOR(nan)
+ FRANGE_PROP_ACCESSOR(inf)
+ FRANGE_PROP_ACCESSOR(ninf)
+private:
+ void verify_range ();
+ void normalize_kind ();
+
+ frange_props m_props;
+ tree m_type;
+};
+
// is_a<> and as_a<> implementation for vrange.
// Anything we haven't specialized is a hard fail.
@@ -297,10 +410,18 @@ is_a <irange> (vrange &v)
return v.m_discriminator == VR_IRANGE;
}
+template <>
+inline bool
+is_a <frange> (vrange &v)
+{
+ return v.m_discriminator == VR_FRANGE;
+}
+
class vrange_visitor
{
public:
virtual void visit (const irange &) const { }
+ virtual void visit (const frange &) const { }
virtual void visit (const unsupported_range &) const { }
};
@@ -360,6 +481,7 @@ private:
unsupported_range m_unsupported;
vrange *m_vrange;
int_range_max m_irange;
+ frange m_frange;
};
inline
@@ -401,6 +523,8 @@ Value_Range::init (tree type)
if (irange::supports_p (type))
m_vrange = &m_irange;
+ else if (frange::supports_p (type))
+ m_vrange = &m_frange;
else
m_vrange = &m_unsupported;
}
@@ -426,6 +550,11 @@ Value_Range::operator= (const vrange &r)
m_irange = as_a <irange> (r);
m_vrange = &m_irange;
}
+ else if (is_a <frange> (r))
+ {
+ m_frange = as_a <frange> (r);
+ m_vrange = &m_frange;
+ }
else
gcc_unreachable ();
@@ -461,7 +590,7 @@ Value_Range::operator const vrange &() const
inline bool
Value_Range::supports_type_p (tree type)
{
- return irange::supports_p (type);
+ return irange::supports_p (type) || frange::supports_p (type);
}
// Returns true for an old-school value_range as described above.
@@ -881,6 +1010,69 @@ irange::normalize_kind ()
}
}
+
+// Supporting methods for frange.
+
+inline bool
+frange_props::operator== (const frange_props &other) const
+{
+ return u.bytes == other.u.bytes;
+}
+
+inline bool
+frange_props::union_ (const frange_props &other)
+{
+ unsigned char saved = u.bytes;
+ u.bytes |= other.u.bytes;
+ return u.bytes != saved;
+}
+
+inline bool
+frange_props::intersect (const frange_props &other)
+{
+ unsigned char saved = u.bytes;
+ u.bytes &= other.u.bytes;
+ return u.bytes != saved;
+}
+
+inline
+frange::frange ()
+{
+ m_discriminator = VR_FRANGE;
+ m_type = nullptr;
+ set_undefined ();
+}
+
+inline
+frange::frange (const frange &src)
+{
+ m_discriminator = VR_FRANGE;
+ *this = src;
+}
+
+inline tree
+frange::type () const
+{
+ return m_type;
+}
+
+inline void
+frange::set_varying (tree type)
+{
+ m_kind = VR_VARYING;
+ m_type = type;
+ m_props.set_varying ();
+}
+
+inline void
+frange::set_undefined ()
+{
+ m_kind = VR_UNDEFINED;
+ m_type = NULL;
+ m_props.set_undefined ();
+}
+
+
// Return the maximum value for TYPE.
inline tree
diff --git a/gcc/value-relation.cc b/gcc/value-relation.cc
index bd34425..a447021 100644
--- a/gcc/value-relation.cc
+++ b/gcc/value-relation.cc
@@ -667,8 +667,6 @@ private:
inline void
value_relation::set_relation (relation_kind r, tree n1, tree n2)
{
- gcc_checking_assert (SSA_NAME_VERSION (n1) != SSA_NAME_VERSION (n2)
- || r == VREL_EQ);
related = r;
name1 = n1;
name2 = n2;
@@ -1449,6 +1447,11 @@ void
path_oracle::register_relation (basic_block bb, relation_kind k, tree ssa1,
tree ssa2)
{
+ // If the 2 ssa_names are the same, do nothing. An equivalence is implied,
+ // and no other relation makes sense.
+ if (ssa1 == ssa2)
+ return;
+
if (dump_file && (dump_flags & TDF_DETAILS))
{
value_relation vr (k, ssa1, ssa2);
diff --git a/gcc/vr-values.cc b/gcc/vr-values.cc
index 6b9c630..626a918 100644
--- a/gcc/vr-values.cc
+++ b/gcc/vr-values.cc
@@ -188,6 +188,17 @@ vr_values::range_of_expr (vrange &r, tree expr, gimple *stmt)
r = *vr;
else
{
+ if (!vr->supports_type_p (TREE_TYPE (expr)))
+ {
+ // vr_values::extract_range_basic() use of ranger's
+ // fold_range() can create a situation where we are
+ // asked for the range of an unsupported legacy type.
+ // Since get_value_range() above will return varying for
+ // such types, avoid copying incompatible range types.
+ gcc_checking_assert (vr->varying_p ());
+ r.set_varying (TREE_TYPE (expr));
+ return true;
+ }
value_range tmp = *vr;
tmp.normalize_symbolics ();
r = tmp;
@@ -4375,7 +4386,9 @@ simplify_using_ranges::simplify (gimple_stmt_iterator *gsi)
case MIN_EXPR:
case MAX_EXPR:
- return simplify_min_or_max_using_ranges (gsi, stmt);
+ if (INTEGRAL_TYPE_P (TREE_TYPE (rhs1)))
+ return simplify_min_or_max_using_ranges (gsi, stmt);
+ break;
case RSHIFT_EXPR:
{
diff --git a/libgo/match.sh b/libgo/match.sh
index 7ed587f..e5ed98d 100755
--- a/libgo/match.sh
+++ b/libgo/match.sh
@@ -111,7 +111,7 @@ gobuild() {
if test "$goarch" != "386"; then
line=$(echo "$line" | sed -e "s/\\(${wrap}\\)386\\(${wrap}\\)/\10\2/g")
fi
- (($line))
+ return $((!($line)))
}
matched=
diff --git a/libgo/testsuite/gotest b/libgo/testsuite/gotest
index 04e4267..0a0a7e1 100755
--- a/libgo/testsuite/gotest
+++ b/libgo/testsuite/gotest
@@ -302,7 +302,7 @@ gobuild() {
if test "$goarch" != "386"; then
line=$(echo "$line" | sed -e "s/\\(${wrap}\\)386\\(${wrap}\\)/\10\2/g")
fi
- (($line))
+ return $((!($line)))
}
case "x$gofiles" in
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 45fd827..242625b 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,9 @@
+2022-07-22 Martin Liska <mliska@suse.cz>
+
+ PR other/106370
+ * _doprnt.c: Remove continue as last stmt
+ in a loop.
+
2022-07-14 Martin Liska <mliska@suse.cz>
* functions.texi: Replace strtoul with strtoull.
diff --git a/libiberty/_doprnt.c b/libiberty/_doprnt.c
index cebaa16..c7232d8 100644
--- a/libiberty/_doprnt.c
+++ b/libiberty/_doprnt.c
@@ -55,7 +55,6 @@ Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
putc(CHAR, stream); \
ptr++; \
total_printed++; \
- continue; \
} while (0)
#define PRINT_TYPE(TYPE) \
diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog
index 52050be..fa39965 100644
--- a/libsanitizer/ChangeLog
+++ b/libsanitizer/ChangeLog
@@ -1,3 +1,10 @@
+2022-07-22 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR sanitizer/105531
+ * sanitizer_common/sanitizer_linux_libcdep.cpp,
+ sanitizer_common/sanitizer_solaris.h:: Cherry-pick
+ llvm-project revision 3776db9a4fd2080d23d6a5f52e405eea44558761.
+
2022-05-05 Martin Liska <mliska@suse.cz>
* LOCAL_PATCHES: Update.
diff --git a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp
index 620267c..6dd2740 100644
--- a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp
@@ -27,6 +27,7 @@
#include "sanitizer_linux.h"
#include "sanitizer_placement_new.h"
#include "sanitizer_procmaps.h"
+#include "sanitizer_solaris.h"
#if SANITIZER_NETBSD
#define _RTLD_SOURCE // for __lwp_gettcb_fast() / __lwp_getprivate_fast()
@@ -62,6 +63,7 @@
#endif
#if SANITIZER_SOLARIS
+#include <stddef.h>
#include <stdlib.h>
#include <thread.h>
#endif
@@ -350,19 +352,43 @@ static uptr TlsGetOffset(uptr ti_module, uptr ti_offset) {
extern "C" void *__tls_get_addr(size_t *);
#endif
+static size_t main_tls_modid;
+
static int CollectStaticTlsBlocks(struct dl_phdr_info *info, size_t size,
void *data) {
- if (!info->dlpi_tls_modid)
+ size_t tls_modid;
+#if SANITIZER_SOLARIS
+ // dlpi_tls_modid is only available since Solaris 11.4 SRU 10. Use
+ // dlinfo(RTLD_DI_LINKMAP) instead which works on all of Solaris 11.3,
+ // 11.4, and Illumos. The tlsmodid of the executable was changed to 1 in
+ // 11.4 to match other implementations.
+ if (size >= offsetof(dl_phdr_info_test, dlpi_tls_modid))
+ main_tls_modid = 1;
+ else
+ main_tls_modid = 0;
+ g_use_dlpi_tls_data = 0;
+ Rt_map *map;
+ dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &map);
+ tls_modid = map->rt_tlsmodid;
+#else
+ main_tls_modid = 1;
+ tls_modid = info->dlpi_tls_modid;
+#endif
+
+ if (tls_modid < main_tls_modid)
return 0;
- uptr begin = (uptr)info->dlpi_tls_data;
+ uptr begin;
+#if !SANITIZER_SOLARIS
+ begin = (uptr)info->dlpi_tls_data;
+#endif
if (!g_use_dlpi_tls_data) {
// Call __tls_get_addr as a fallback. This forces TLS allocation on glibc
// and FreeBSD.
#ifdef __s390__
begin = (uptr)__builtin_thread_pointer() +
- TlsGetOffset(info->dlpi_tls_modid, 0);
+ TlsGetOffset(tls_modid, 0);
#else
- size_t mod_and_off[2] = {info->dlpi_tls_modid, 0};
+ size_t mod_and_off[2] = {tls_modid, 0};
begin = (uptr)__tls_get_addr(mod_and_off);
#endif
}
@@ -370,7 +396,7 @@ static int CollectStaticTlsBlocks(struct dl_phdr_info *info, size_t size,
if (info->dlpi_phdr[i].p_type == PT_TLS) {
static_cast<InternalMmapVector<TlsBlock> *>(data)->push_back(
TlsBlock{begin, begin + info->dlpi_phdr[i].p_memsz,
- info->dlpi_phdr[i].p_align, info->dlpi_tls_modid});
+ info->dlpi_phdr[i].p_align, tls_modid});
break;
}
return 0;
@@ -382,11 +408,11 @@ __attribute__((unused)) static void GetStaticTlsBoundary(uptr *addr, uptr *size,
dl_iterate_phdr(CollectStaticTlsBlocks, &ranges);
uptr len = ranges.size();
Sort(ranges.begin(), len);
- // Find the range with tls_modid=1. For glibc, because libc.so uses PT_TLS,
- // this module is guaranteed to exist and is one of the initially loaded
- // modules.
+ // Find the range with tls_modid == main_tls_modid. For glibc, because
+ // libc.so uses PT_TLS, this module is guaranteed to exist and is one of
+ // the initially loaded modules.
uptr one = 0;
- while (one != len && ranges[one].tls_modid != 1) ++one;
+ while (one != len && ranges[one].tls_modid != main_tls_modid) ++one;
if (one == len) {
// This may happen with musl if no module uses PT_TLS.
*addr = 0;
diff --git a/libsanitizer/sanitizer_common/sanitizer_solaris.h b/libsanitizer/sanitizer_common/sanitizer_solaris.h
new file mode 100644
index 0000000..2a21693
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_solaris.h
@@ -0,0 +1,56 @@
+//===-- sanitizer_solaris.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer runtime. It contains Solaris-specific
+// definitions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_SOLARIS_H
+#define SANITIZER_SOLARIS_H
+
+#include "sanitizer_internal_defs.h"
+
+#if SANITIZER_SOLARIS
+
+#include <link.h>
+
+namespace __sanitizer {
+
+// Beginning of declaration from OpenSolaris/Illumos
+// $SRC/cmd/sgs/include/rtld.h.
+struct Rt_map {
+ Link_map rt_public;
+ const char *rt_pathname;
+ ulong_t rt_padstart;
+ ulong_t rt_padimlen;
+ ulong_t rt_msize;
+ uint_t rt_flags;
+ uint_t rt_flags1;
+ ulong_t rt_tlsmodid;
+};
+
+// Structure matching the Solaris 11.4 struct dl_phdr_info used to determine
+// presence of dlpi_tls_modid field at runtime. Cf. Solaris 11.4
+// dl_iterate_phdr(3C), Example 2.
+struct dl_phdr_info_test {
+ ElfW(Addr) dlpi_addr;
+ const char *dlpi_name;
+ const ElfW(Phdr) * dlpi_phdr;
+ ElfW(Half) dlpi_phnum;
+ u_longlong_t dlpi_adds;
+ u_longlong_t dlpi_subs;
+ size_t dlpi_tls_modid;
+ void *dlpi_tls_data;
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_SOLARIS
+
+#endif // SANITIZER_SOLARIS_H