[gcc r16-180] tailc: Improve tail recursion handling [PR119493]
https://gcc.gnu.org/g:b0120fa9838f8fbeb13301d03b01cad282941569 commit r16-180-gb0120fa9838f8fbeb13301d03b01cad282941569 Author: Jakub Jelinek Date: Mon Apr 28 09:22:50 2025 +0200 tailc: Improve tail recursion handling [PR119493] Here is a patch to improve the tail recursion handling also for non-musttail calls. 2025-04-28 Jakub Jelinek PR tree-optimization/119493 * tree-tailcall.cc (find_tail_calls): Handle non-gimple_reg_type arguments which aren't just passed through for tail recursions even for non-musttail calls. Diff: --- gcc/tree-tailcall.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gcc/tree-tailcall.cc b/gcc/tree-tailcall.cc index f593363dae43..fc05928cd689 100644 --- a/gcc/tree-tailcall.cc +++ b/gcc/tree-tailcall.cc @@ -827,8 +827,7 @@ find_tail_calls (basic_block bb, struct tailcall **ret, bool only_musttail, ? !is_gimple_reg (param) : (!is_gimple_variable (param) || TREE_THIS_VOLATILE (param) -|| may_be_aliased (param) -|| !gimple_call_must_tail_p (call))) +|| may_be_aliased (param))) break; } }
[gcc r16-221] gccrs: Change error message to match expected test output
https://gcc.gnu.org/g:cd2e5bf49d7763790254ef338a263fee28f80a97 commit r16-221-gcd2e5bf49d7763790254ef338a263fee28f80a97 Author: Pierre-Emmanuel Patry Date: Wed Apr 23 17:24:04 2025 +0200 gccrs: Change error message to match expected test output gcc/rust/ChangeLog: * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Change error message. gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove passing test from exclusion list. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 4 ++-- gcc/testsuite/rust/compile/nr2/exclude | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index cd81080ce157..e0cd95151809 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -355,8 +355,8 @@ Late::visit (AST::PathInExpression &expr) if (!resolved) { if (!ctx.lookup (expr.get_segments ().front ().get_node_id ())) - rust_error_at (expr.get_locus (), - "could not resolve path expression: %qs", + rust_error_at (expr.get_locus (), ErrorCode::E0433, + "Cannot find path %qs in this scope", expr.as_simple_path ().as_string ().c_str ()); return; } diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index d3efe08a531e..ed1241bcdf6b 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -1,8 +1,6 @@ canonical_paths1.rs -cfg1.rs generics9.rs issue-3315-2.rs -lookup_err1.rs multiple_bindings1.rs multiple_bindings2.rs privacy5.rs
[gcc r16-222] gccrs: Remove error state for GenericArg
https://gcc.gnu.org/g:e905c04b3cf8b29cada17809283d088bee48306f commit r16-222-ge905c04b3cf8b29cada17809283d088bee48306f Author: Pierre-Emmanuel Patry Date: Mon Apr 7 15:59:15 2025 +0200 gccrs: Remove error state for GenericArg gcc/rust/ChangeLog: * ast/rust-ast-collector.cc (TokenCollector::visit): Remove error kind and change function call. * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Change call name. * ast/rust-path.cc (ConstGenericParam::as_string): Likewise. * ast/rust-path.h: Remove error kind. * hir/rust-ast-lower-type.cc (ASTLowerGenericParam::visit): Change call name. * parse/rust-parse-impl.h (Parser::parse_generic_param): Use optional on parsing failure. (Parser::parse_generic_arg): Likewise. (Parser::parse_path_generic_args): Likewise. * parse/rust-parse.h: Likewise. * resolve/rust-ast-resolve-type.h: Change call name. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/rust/ast/rust-ast-collector.cc | 4 +--- gcc/rust/ast/rust-ast-visitor.cc | 2 +- gcc/rust/ast/rust-path.cc| 2 +- gcc/rust/ast/rust-path.h | 28 +++-- gcc/rust/hir/rust-ast-lower-type.cc | 2 +- gcc/rust/parse/rust-parse-impl.h | 36 ++-- gcc/rust/parse/rust-parse.h | 2 +- gcc/rust/resolve/rust-ast-resolve-type.h | 4 ++-- 8 files changed, 35 insertions(+), 45 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 5a104e32b9ad..c850e965cf4d 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -491,7 +491,7 @@ TokenCollector::visit (ConstGenericParam ¶m) if (param.has_default_value ()) { push (Rust::Token::make (EQUAL, UNDEF_LOCATION)); - visit (param.get_default_value ()); + visit (param.get_default_value_unchecked ()); } } @@ -639,8 +639,6 @@ TokenCollector::visit (GenericArg &arg) push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (path))); } break; -case GenericArg::Kind::Error: - rust_unreachable (); } } diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index 61a3b8b4bf77..6862024354f2 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -82,7 +82,7 @@ DefaultASTVisitor::visit (AST::ConstGenericParam &const_param) if (const_param.has_type ()) visit (const_param.get_type ()); if (const_param.has_default_value ()) -visit (const_param.get_default_value ()); +visit (const_param.get_default_value_unchecked ()); } void diff --git a/gcc/rust/ast/rust-path.cc b/gcc/rust/ast/rust-path.cc index 69627be81af3..8e43ddf648a9 100644 --- a/gcc/rust/ast/rust-path.cc +++ b/gcc/rust/ast/rust-path.cc @@ -119,7 +119,7 @@ ConstGenericParam::as_string () const str += "const " + name.as_string () + ": " + type->as_string (); if (has_default_value ()) -str += " = " + get_default_value ().as_string (); +str += " = " + get_default_value_unchecked ().as_string (); return str; } diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 805be8e91f76..a4ba93b718e7 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -167,17 +167,11 @@ public: */ enum class Kind { -Error, Const, // A const value Type, // A type argument (not discernable during parsing) Either, // Either a type or a const value, cleared up during resolving }; - static GenericArg create_error () - { -return GenericArg (nullptr, nullptr, {""}, Kind::Error, UNDEF_LOCATION); - } - static GenericArg create_const (std::unique_ptr expression) { auto locus = expression->get_locus (); @@ -222,8 +216,6 @@ public: GenericArg (GenericArg &&other) = default; GenericArg &operator= (GenericArg &&other) = default; - bool is_error () const { return kind == Kind::Error; } - Kind get_kind () const { return kind; } location_t get_locus () const { return locus; } @@ -239,8 +231,6 @@ public: break; case Kind::Either: break; - case Kind::Error: - rust_unreachable (); } } @@ -283,8 +273,6 @@ public: { switch (get_kind ()) { - case Kind::Error: - rust_unreachable (); case Kind::Either: return "Ambiguous: " + path.as_string (); case Kind::Const: @@ -355,15 +343,15 @@ class ConstGenericParam : public GenericParam /** * Default value for the const generic parameter */ - GenericArg default_value; + tl::optional default_value; AST::AttrVec outer_attrs; location_t locus; public: ConstGenericParam (Identifier name, std::unique_ptr type, -GenericArg default_value, AST::AttrVec ou
[gcc r16-223] gccrs: Prevent forward declaration in type parameters
https://gcc.gnu.org/g:93d3fcf96c0a9df8059360c7aed42f7e43735ab3 commit r16-223-g93d3fcf96c0a9df8059360c7aed42f7e43735ab3 Author: Pierre-Emmanuel Patry Date: Wed Apr 23 14:40:22 2025 +0200 gccrs: Prevent forward declaration in type parameters gcc/rust/ChangeLog: * resolve/rust-default-resolver.cc (DefaultResolver::visit): Add visit function for TypeParam. * resolve/rust-default-resolver.h: Add function prototype. * resolve/rust-forever-stack.h: Add function to check for forward declaration ban. * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Check forward declarations. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/rust/resolve/rust-default-resolver.cc | 8 gcc/rust/resolve/rust-default-resolver.h| 2 ++ gcc/rust/resolve/rust-forever-stack.h | 15 +++ gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 8 4 files changed, 33 insertions(+) diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index 7528e7950e64..480034c89741 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -179,5 +179,13 @@ DefaultResolver::visit (AST::StaticItem &item) ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis); } +void +DefaultResolver::visit (AST::TypeParam ¶m) +{ + auto expr_vis = [this, ¶m] () { AST::DefaultASTVisitor::visit (param); }; + + ctx.scoped (Rib::Kind::ForwardTypeParamBan, param.get_node_id (), expr_vis); +} + } // namespace Resolver2_0 } // namespace Rust diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h index 587d7d458034..2a987efdf5c4 100644 --- a/gcc/rust/resolve/rust-default-resolver.h +++ b/gcc/rust/resolve/rust-default-resolver.h @@ -50,6 +50,8 @@ public: void visit (AST::InherentImpl &) override; void visit (AST::TraitImpl &) override; + void visit (AST::TypeParam &) override; + // type dec nodes, which visit their fields or variants by default void visit (AST::StructStruct &) override; void visit (AST::TupleStruct &) override; diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index 75d8c1d9b590..81468e5c386f 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -831,6 +831,21 @@ private: tl::optional dfs_node (Node &starting_point, NodeId to_find); tl::optional dfs_node (const Node &starting_point, NodeId to_find) const; + +public: + bool forward_declared (NodeId definition, NodeId usage) + { +if (peek ().kind != Rib::Kind::ForwardTypeParamBan) + return false; + +const auto &definition_rib = dfs_rib (cursor (), definition); + +if (!definition_rib) + return false; + +return (definition_rib + && definition_rib.value ().kind == Rib::Kind::ForwardTypeParamBan); + } }; } // namespace Resolver2_0 diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index e0cd95151809..48e33c097de4 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -401,6 +401,14 @@ Late::visit (AST::TypePath &type) return; } + if (ctx.types.forward_declared (resolved->get_node_id (), + type.get_node_id ())) +{ + rust_error_at (type.get_locus (), ErrorCode::E0128, +"type parameters with a default cannot use forward " +"declared identifiers"); +} + ctx.map_usage (Usage (type.get_node_id ()), Definition (resolved->get_node_id ())); }
[gcc r16-228] gccrs: Add hash function for Identifiers
https://gcc.gnu.org/g:a65c3b497fd0ca28f35cb7e63f5a1ce95baff8ad commit r16-228-ga65c3b497fd0ca28f35cb7e63f5a1ce95baff8ad Author: Pierre-Emmanuel Patry Date: Sun Apr 6 01:44:18 2025 +0200 gccrs: Add hash function for Identifiers gcc/rust/ChangeLog: * ast/rust-ast.h: Add hash function. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/rust/ast/rust-ast.h | 13 + 1 file changed, 13 insertions(+) diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 94585dc13442..aa6ad5066aa1 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -2102,6 +2102,19 @@ template <> struct less return lhs.as_string () < rhs.as_string (); } }; + +template <> struct hash +{ + std::size_t operator() (const Rust::Identifier &k) const + { +using std::hash; +using std::size_t; +using std::string; + +return hash () (k.as_string ()) ^ (hash () (k.get_locus ())); + } +}; + } // namespace std #endif
[gcc r16-216] gccrs: Adjust segment start position errors
https://gcc.gnu.org/g:2f7e712313a95835f93ffce429fabcbd8e5402ac commit r16-216-g2f7e712313a95835f93ffce429fabcbd8e5402ac Author: Owen Avery Date: Thu Apr 17 16:51:21 2025 -0400 gccrs: Adjust segment start position errors gcc/rust/ChangeLog: * resolve/rust-ast-resolve-path.cc (ResolvePath::resolve_path): Adjust error messages. * resolve/rust-ast-resolve-type.cc (ResolveRelativeTypePath::go): Likewise. * resolve/rust-forever-stack.hxx (check_leading_kw_at_start): Likewise. gcc/testsuite/ChangeLog: * rust/compile/issue-3568.rs: Adjust expected errors. * rust/compile/name_resolution9.rs: Likewise. * rust/compile/self-path2.rs: Likewise. Signed-off-by: Owen Avery Diff: --- gcc/rust/resolve/rust-ast-resolve-path.cc | 8 gcc/rust/resolve/rust-ast-resolve-type.cc | 3 +-- gcc/rust/resolve/rust-forever-stack.hxx| 7 +++ gcc/testsuite/rust/compile/issue-3568.rs | 2 +- gcc/testsuite/rust/compile/name_resolution9.rs | 4 ++-- gcc/testsuite/rust/compile/self-path2.rs | 4 ++-- 6 files changed, 13 insertions(+), 15 deletions(-) diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc index 530926d5d97a..fb6715d9528a 100644 --- a/gcc/rust/resolve/rust-ast-resolve-path.cc +++ b/gcc/rust/resolve/rust-ast-resolve-path.cc @@ -68,8 +68,7 @@ ResolvePath::resolve_path (AST::PathInExpression &expr) if (in_middle_of_path && segment.is_lower_self_seg ()) { rust_error_at (segment.get_locus (), ErrorCode::E0433, -"leading path segment %qs can only be used at the " -"beginning of a path", +"%qs in paths can only be used in start position", segment.as_string ().c_str ()); return UNKNOWN_NODEID; } @@ -372,8 +371,9 @@ ResolvePath::resolve_path (AST::SimplePath &expr) { if (!is_first_segment) { - rust_error_at (segment.get_locus (), -"% can only be used in start position"); + rust_error_at ( + segment.get_locus (), ErrorCode::E0433, + "% in paths can only be used in start position"); return UNKNOWN_NODEID; } if (module_scope_id == crate_scope_id) diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc index 606141cc8760..8fd69c3ead6a 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.cc +++ b/gcc/rust/resolve/rust-ast-resolve-type.cc @@ -176,8 +176,7 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id) if (in_middle_of_path && segment->is_lower_self_seg ()) { rust_error_at (segment->get_locus (), ErrorCode::E0433, -"leading path segment %qs can only be used at the " -"beginning of a path", +"%qs in paths can only be used in start position", segment->as_string ().c_str ()); return false; } diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 73c795668d9a..31a33016f099 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -401,10 +401,9 @@ static inline bool check_leading_kw_at_start (const S &segment, bool condition) { if (condition) -rust_error_at ( - segment.get_locus (), ErrorCode::E0433, - "leading path segment %qs can only be used at the beginning of a path", - segment.as_string ().c_str ()); +rust_error_at (segment.get_locus (), ErrorCode::E0433, + "%qs in paths can only be used in start position", + segment.as_string ().c_str ()); return condition; } diff --git a/gcc/testsuite/rust/compile/issue-3568.rs b/gcc/testsuite/rust/compile/issue-3568.rs index 222a174ef381..fef43b5d1e40 100644 --- a/gcc/testsuite/rust/compile/issue-3568.rs +++ b/gcc/testsuite/rust/compile/issue-3568.rs @@ -4,4 +4,4 @@ mod foo { } pub use foo::super::foo::S as T; -// { dg-error ".super. can only be used in start position" "" { target *-*-* } .-1 } +// { dg-error ".super. in paths can only be used in start position" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/rust/compile/name_resolution9.rs b/gcc/testsuite/rust/compile/name_resolution9.rs index 93adb46d278a..792b3bdd6b5c 100644 --- a/gcc/testsuite/rust/compile/name_resolution9.rs +++ b/gcc/testsuite/rust/compile/name_resolution9.rs @@ -6,11 +6,11 @@ pub mod foo { super::super::super::foo!(); // { dg-error "too many leading .super. keywords" } // { dg-error "could not resolve macro invocation" "" { target *-*-* }
[gcc r16-226] gccrs: Add fn_once and Sized lang items to the test
https://gcc.gnu.org/g:bbee43b64b124efc597a1534b0abdce4dc2286e9 commit r16-226-gbbee43b64b124efc597a1534b0abdce4dc2286e9 Author: Pierre-Emmanuel Patry Date: Fri Apr 4 15:35:15 2025 +0200 gccrs: Add fn_once and Sized lang items to the test gcc/testsuite/ChangeLog: * rust/compile/multiple_bindings1.rs: Add missing lang items. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/testsuite/rust/compile/multiple_bindings1.rs | 29 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/gcc/testsuite/rust/compile/multiple_bindings1.rs b/gcc/testsuite/rust/compile/multiple_bindings1.rs index e73dc2ae7d94..8a2e18c27b1b 100644 --- a/gcc/testsuite/rust/compile/multiple_bindings1.rs +++ b/gcc/testsuite/rust/compile/multiple_bindings1.rs @@ -1,29 +1,38 @@ +#[lang = "sized"] +pub trait Sized {} + +#[lang = "fn_once"] +trait FnOnce { +type Output; + +fn call_once(self, args: Args) -> Self::Output; +} + fn f1(i: i32, i: i32) {} // { dg-error "identifier .i. is bound more than once in the same parameter list .E0415." "" { target *-*-* } .-1 } trait Foo { - fn f2(i: i32, i: i32) {} - // { dg-error "identifier .i. is bound more than once in the same parameter list .E0415." "" { target *-*-* } .-1 } +fn f2(i: i32, i: i32) {} +// { dg-error "identifier .i. is bound more than once in the same parameter list .E0415." "" { target *-*-* } .-1 } } trait Bar { - fn f3(i: i32, j: i32) {} +fn f3(i: i32, j: i32) {} } struct S; impl S { - fn f4(i: i32, i: i32) {} - // { dg-error "identifier .i. is bound more than once in the same parameter list .E0415." "" { target *-*-* } .-1 } +fn f4(i: i32, i: i32) {} +// { dg-error "identifier .i. is bound more than once in the same parameter list .E0415." "" { target *-*-* } .-1 } } impl Bar for S { - fn f3(i: i32, i: i32) {} - // { dg-error "identifier .i. is bound more than once in the same parameter list .E0415." "" { target *-*-* } .-1 } +fn f3(i: i32, i: i32) {} +// { dg-error "identifier .i. is bound more than once in the same parameter list .E0415." "" { target *-*-* } .-1 } } fn main() { - let _ = |i, i| {}; - // { dg-error "identifier .i. is bound more than once in the same parameter list .E0415." "" { target *-*-* } .-1 } +let _ = |i, i| {}; +// { dg-error "identifier .i. is bound more than once in the same parameter list .E0415." "" { target *-*-* } .-1 } } -
[gcc r16-224] gccrs: Update generics9 expected error message
https://gcc.gnu.org/g:e26fa689b8ee544d1ece9f5d6ffe117f2fc22189 commit r16-224-ge26fa689b8ee544d1ece9f5d6ffe117f2fc22189 Author: Pierre-Emmanuel Patry Date: Wed Apr 23 14:41:24 2025 +0200 gccrs: Update generics9 expected error message gcc/testsuite/ChangeLog: * rust/compile/generics9.rs: Change expected error message. * rust/compile/nr2/exclude: Remove test from exclusion list. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/testsuite/rust/compile/generics9.rs | 3 ++- gcc/testsuite/rust/compile/nr2/exclude | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gcc/testsuite/rust/compile/generics9.rs b/gcc/testsuite/rust/compile/generics9.rs index 3c787aa75027..56c619833f4f 100644 --- a/gcc/testsuite/rust/compile/generics9.rs +++ b/gcc/testsuite/rust/compile/generics9.rs @@ -1,5 +1,6 @@ +// { dg-additional-options "-frust-name-resolution-2.0" } struct Foo(A, B); -// { dg-error "could not resolve type path .B." "" { target *-*-* } .-1 } +// { dg-error "type parameters with a default cannot use forward declared identifiers" "" { target *-*-* } .-1 } fn main() { let a: Foo; diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index ed1241bcdf6b..2c116be13491 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -1,5 +1,4 @@ canonical_paths1.rs -generics9.rs issue-3315-2.rs multiple_bindings1.rs multiple_bindings2.rs
[gcc r16-230] gccrs: Add pattern bindings
https://gcc.gnu.org/g:a8a422d64c5b2009172af63b6736d824a5442c65 commit r16-230-ga8a422d64c5b2009172af63b6736d824a5442c65 Author: Pierre-Emmanuel Patry Date: Sun Apr 6 18:17:41 2025 +0200 gccrs: Add pattern bindings gcc/rust/ChangeLog: * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Add binding creation in visitor. * resolve/rust-late-name-resolver-2.0.h: Add function prototypes. * resolve/rust-name-resolution-context.h: Add binding context. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 155 +++- gcc/rust/resolve/rust-late-name-resolver-2.0.h | 5 + gcc/rust/resolve/rust-name-resolution-context.h | 1 + 3 files changed, 156 insertions(+), 5 deletions(-) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 48e33c097de4..1ecf48152d84 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -128,6 +128,54 @@ Late::new_label (Identifier name, NodeId id) rust_assert (ok); } +void +Late::visit (AST::ForLoopExpr &expr) +{ + visit_outer_attrs (expr); + + ctx.bindings.new_binding (BindingSource::For); + + visit (expr.get_pattern ()); + + ctx.bindings.clear (); + + visit (expr.get_iterator_expr ()); + visit (expr.get_loop_label ()); + visit (expr.get_loop_block ()); +} + +void +Late::visit (AST::IfLetExpr &expr) +{ + visit_outer_attrs (expr); + + ctx.bindings.new_binding (BindingSource::Let); + + for (auto &pattern : expr.get_patterns ()) +visit (pattern); + + ctx.bindings.clear (); + + visit (expr.get_value_expr ()); + visit (expr.get_if_block ()); +} + +void +Late::visit (AST::MatchArm &arm) +{ + visit_outer_attrs (arm); + + ctx.bindings.new_binding (BindingSource::Match); + + for (auto &pattern : arm.get_patterns ()) +visit (pattern); + + ctx.bindings.clear (); + + if (arm.has_match_arm_guard ()) +visit (arm.get_guard_expr ()); +} + void Late::visit (AST::LetStmt &let) { @@ -138,8 +186,13 @@ Late::visit (AST::LetStmt &let) // this makes variable shadowing work properly if (let.has_init_expr ()) visit (let.get_init_expr ()); + + ctx.bindings.new_binding (BindingSource::Let); + visit (let.get_pattern ()); + ctx.bindings.clear (); + if (let.has_else_expr ()) visit (let.get_init_expr ()); @@ -167,9 +220,80 @@ Late::visit (AST::IdentifierPattern &identifier) // but values does not allow shadowing... since functions cannot shadow // do we insert functions in labels as well? - // We do want to ignore duplicated data because some situations rely on it. - std::ignore = ctx.values.insert_shadowable (identifier.get_ident (), - identifier.get_node_id ()); + if (ctx.bindings.and_binded (identifier.get_ident ())) +{ + if (ctx.bindings.get_source () == BindingSource::Param) + rust_error_at ( + identifier.get_locus (), ErrorCode::E0415, + "identifier %qs is bound more than once in the same parameter list", + identifier.as_string ().c_str ()); + else + rust_error_at ( + identifier.get_locus (), ErrorCode::E0416, + "identifier %qs is bound more than once in the same pattern", + identifier.as_string ().c_str ()); + return; +} + + ctx.bindings.insert_ident (identifier.get_ident ()); + + if (ctx.bindings.or_binded (identifier.get_ident ())) +{ + // FIXME: map usage instead + std::ignore = ctx.values.insert_shadowable (identifier.get_ident (), + identifier.get_node_id ()); +} + else +{ + // We do want to ignore duplicated data because some situations rely on + // it. + std::ignore = ctx.values.insert_shadowable (identifier.get_ident (), + identifier.get_node_id ()); +} +} + +void +Late::visit (AST::AltPattern &pattern) +{ + ctx.bindings.push (Binding::Kind::Or); + for (auto &alt : pattern.get_alts ()) +{ + ctx.bindings.push (Binding::Kind::Product); + visit (alt); + ctx.bindings.merge (); +} + ctx.bindings.merge (); +} + +void +Late::visit (AST::Function &function) +{ + auto def_fn = [this, &function] () { +visit_outer_attrs (function); +visit (function.get_visibility ()); +visit (function.get_qualifiers ()); +for (auto &generic : function.get_generic_params ()) + visit (generic); + +// We only care about params +ctx.bindings.new_binding (BindingSource::Param); + +for (auto ¶m : function.get_function_params ()) + visit (param); + +ctx.bindings.clear (); + +// Back to regular visit + +if (function.has_return_type ()) + visit (function.get_return_type ()); +if (function.has_where_clause ()) + visit (function.get_where_clau
[gcc r16-209] gccrs: Add test case to show issue is fixed
https://gcc.gnu.org/g:144e9f05c7f7e7e83fbf3f31981d0cd5a8e24218 commit r16-209-g144e9f05c7f7e7e83fbf3f31981d0cd5a8e24218 Author: Philip Herron Date: Thu Apr 17 16:04:55 2025 +0100 gccrs: Add test case to show issue is fixed This was already fixed in: bb01719f0e1 but we require fn_once lang item to be defined as we are working on libcore support still. Fixes Rust-GCC#3711 gcc/testsuite/ChangeLog: * rust/compile/issue-3711.rs: New test. Signed-off-by: Philip Herron Diff: --- gcc/testsuite/rust/compile/issue-3711.rs | 17 + 1 file changed, 17 insertions(+) diff --git a/gcc/testsuite/rust/compile/issue-3711.rs b/gcc/testsuite/rust/compile/issue-3711.rs new file mode 100644 index ..a3f9c39b4c58 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3711.rs @@ -0,0 +1,17 @@ +#[lang = "sized"] +pub trait Sized {} + +#[lang = "fn_once"] +pub trait FnOnce { +#[lang = "fn_once_output"] +type Output; + +extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +fn returns_closure() -> _ { +// { dg-error "the type placeholder ._. is not allowed within types on item signatures .E0121." "" { target *-*-* } .-1 } +|| 0 +} + +fn main() {}
[gcc r16-219] gccrs: nr2.0: Fix derive-debug1.rs
https://gcc.gnu.org/g:fe8cd8f56677daf90011d91de557f7dc461639ee commit r16-219-gfe8cd8f56677daf90011d91de557f7dc461639ee Author: Owen Avery Date: Sun Apr 6 18:48:58 2025 -0400 gccrs: nr2.0: Fix derive-debug1.rs gcc/testsuite/ChangeLog: * rust/compile/derive-debug1.rs: Adjust a path. * rust/compile/nr2/exclude: Remove derive-debug1.rs. Signed-off-by: Owen Avery Diff: --- gcc/testsuite/rust/compile/derive-debug1.rs | 2 +- gcc/testsuite/rust/compile/nr2/exclude | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/gcc/testsuite/rust/compile/derive-debug1.rs b/gcc/testsuite/rust/compile/derive-debug1.rs index 2596a3792f1f..cf2187dbce73 100644 --- a/gcc/testsuite/rust/compile/derive-debug1.rs +++ b/gcc/testsuite/rust/compile/derive-debug1.rs @@ -15,7 +15,7 @@ mod core { struct Formatter; // { dg-warning "is never constructed" } struct Error; // { dg-warning "is never constructed" } -type Result = core::result::Result<(), Error>; +type Result = crate::core::result::Result<(), Error>; trait Debug { fn fmt(&self, fmt: &mut Formatter) -> Result; diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index 12e63d884a38..f94cbe46679a 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -13,7 +13,6 @@ pub_restricted_3.rs use_1.rs issue-2905-2.rs derive_clone_enum3.rs -derive-debug1.rs derive-default1.rs derive-eq-invalid.rs torture/alt_patterns1.rs
[gcc r16-212] gccrs: Fix ICE in struct expressions
https://gcc.gnu.org/g:a79bad18a1e83a731731fa621128ca16931c72b1 commit r16-212-ga79bad18a1e83a731731fa621128ca16931c72b1 Author: Philip Herron Date: Thu Apr 17 14:38:04 2025 +0100 gccrs: Fix ICE in struct expressions The error handling here was done long ago when we didnt know how to do any error handling very well. This removed bad fatal_errors and adds in some nice rich_location error diagnostics instead. Fixes Rust-GCC#3628 gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-struct-field.h: keep reference to parent expression * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::TypeCheckStructExpr): update ctor (TypeCheckStructExpr::resolve): remove bad rust_fatal_errors (TypeCheckStructExpr::visit): cleanup errors gcc/testsuite/ChangeLog: * rust/compile/macros/mbe/macro-issue2983_2984.rs: cleanup error diagnotics * rust/compile/struct_init1.rs: likewise * rust/compile/issue-3628.rs: New test. Signed-off-by: Philip Herron Diff: --- .../typecheck/rust-hir-type-check-struct-field.h | 3 ++ gcc/rust/typecheck/rust-hir-type-check-struct.cc | 54 +++--- gcc/testsuite/rust/compile/issue-3628.rs | 10 .../compile/macros/mbe/macro-issue2983_2984.rs | 5 +- gcc/testsuite/rust/compile/struct_init1.rs | 6 +-- 5 files changed, 45 insertions(+), 33 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h index 800f7ca43901..7e3a57addecd 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h +++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h @@ -60,6 +60,9 @@ private: TyTy::BaseType *resolved_field_value_expr; std::set fields_assigned; std::map adtFieldIndexToField; + + // parent + HIR::Expr &parent; }; } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc index 40c42b279802..df1636a584a5 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc @@ -28,7 +28,7 @@ TypeCheckStructExpr::TypeCheckStructExpr (HIR::Expr &e) : TypeCheckBase (), resolved (new TyTy::ErrorType (e.get_mappings ().get_hirid ())), struct_path_resolved (nullptr), -variant (&TyTy::VariantDef::get_error_node ()) +variant (&TyTy::VariantDef::get_error_node ()), parent (e) {} TyTy::BaseType * @@ -65,7 +65,7 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) if (base_unify->get_kind () != struct_path_ty->get_kind ()) { - rust_fatal_error ( + rust_error_at ( struct_expr.get_struct_base ().get_base ().get_locus (), "incompatible types for base struct reference"); return; @@ -82,7 +82,16 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) bool ok = context->lookup_variant_definition ( struct_expr.get_struct_name ().get_mappings ().get_hirid (), &variant_id); - rust_assert (ok); + if (!ok) + { + rich_location r (line_table, struct_expr.get_locus ()); + r.add_range (struct_expr.get_struct_name ().get_locus ()); + rust_error_at ( + struct_expr.get_struct_name ().get_locus (), ErrorCode::E0574, + "expected a struct, variant or union type, found enum %qs", + struct_path_resolved->get_name ().c_str ()); + return; + } ok = struct_path_resolved->lookup_variant_by_id (variant_id, &variant); rust_assert (ok); @@ -118,29 +127,14 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) break; } - if (!ok) - { - return; - } - - if (resolved_field_value_expr == nullptr) - { - rust_fatal_error (field->get_locus (), - "failed to resolve type for field"); - ok = false; - break; - } - - context->insert_type (field->get_mappings (), resolved_field_value_expr); + if (ok) + context->insert_type (field->get_mappings (), + resolved_field_value_expr); } - // something failed setting up the fields + // something failed setting up the fields and error's emitted if (!ok) -{ - rust_error_at (struct_expr.get_locus (), -"constructor type resolution failure"); - return; -} +return; // check the arguments are all assigned and fix up the ordering std::vector missing_field_names; @@ -271,8 +265,11 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field) &field_index); if (!ok) { - rust_error_at (field.get_locus (), "unknown field"); - return
[gcc r16-220] gccrs: nr2.0: Improve error handling
https://gcc.gnu.org/g:3b2fa2a414f61dfbe60e3f96491a7d0f37f7100c commit r16-220-g3b2fa2a414f61dfbe60e3f96491a7d0f37f7100c Author: Owen Avery Date: Thu Apr 17 13:51:43 2025 -0400 gccrs: nr2.0: Improve error handling gcc/rust/ChangeLog: * resolve/rust-early-name-resolver-2.0.cc (Early::build_import_mapping): Avoid outputting an "unresolved import" error if other errors are outputted during resolution. * resolve/rust-early-name-resolver-2.0.h (Early::resolve_path_in_all_ns): Collect path resolution errors while avoiding duplicate errors for resolutions in each namespace. * resolve/rust-forever-stack.h (ForeverStack::resolve_path): Add parameter for collecting errors. (ForeverStack::find_starting_point): Likewise. (ForeverStack::resolve_segments): Likewise. * resolve/rust-forever-stack.hxx (check_leading_kw_at_start): Likewise. (ForeverStack::find_starting_point): Likewise. (ForeverStack::resolve_segments): Likewise. (ForeverStack::resolve_path): Likewise. * resolve/rust-name-resolution-context.h (NameResolutionContext::resolve_path): Add optional parameter for collecting errors. gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove entry. Signed-off-by: Owen Avery Diff: --- gcc/rust/resolve/rust-early-name-resolver-2.0.cc | 6 +- gcc/rust/resolve/rust-early-name-resolver-2.0.h | 16 +++-- gcc/rust/resolve/rust-forever-stack.h| 9 ++- gcc/rust/resolve/rust-forever-stack.hxx | 45 +++- gcc/rust/resolve/rust-name-resolution-context.h | 87 ++-- gcc/testsuite/rust/compile/nr2/exclude | 1 - 6 files changed, 115 insertions(+), 49 deletions(-) diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index 36456e10ff26..7d048ea8289c 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -141,6 +141,10 @@ Early::build_import_mapping ( // be moved into the newly created import mappings auto path = import.to_resolve; + // used to skip the "unresolved import" error + // if we output other errors during resolution + size_t old_error_count = macro_resolve_errors.size (); + switch (import.kind) { case TopLevel::ImportKind::Kind::Glob: @@ -154,7 +158,7 @@ Early::build_import_mapping ( break; } - if (!found) + if (!found && old_error_count == macro_resolve_errors.size ()) collect_error (Error (path.get_final_segment ().get_locus (), ErrorCode::E0433, "unresolved import %qs", path.as_string ().c_str ())); diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h b/gcc/rust/resolve/rust-early-name-resolver-2.0.h index c4226fe9ea8b..e78bec0199a8 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h @@ -218,7 +218,6 @@ private: std::vector> resolve_path_in_all_ns (const P &path) { -const auto &segments = path.get_segments (); std::vector> resolved; // Pair a definition with the namespace it was found in @@ -229,13 +228,22 @@ private: }; }; -ctx.resolve_path (segments, Namespace::Values) +std::vector value_errors; +std::vector type_errors; +std::vector macro_errors; + +ctx.resolve_path (path, value_errors, Namespace::Values) .map (pair_with_ns (Namespace::Values)); -ctx.resolve_path (segments, Namespace::Types) +ctx.resolve_path (path, type_errors, Namespace::Types) .map (pair_with_ns (Namespace::Types)); -ctx.resolve_path (segments, Namespace::Macros) +ctx.resolve_path (path, macro_errors, Namespace::Macros) .map (pair_with_ns (Namespace::Macros)); +if (!value_errors.empty () && !type_errors.empty () + && !macro_errors.empty ()) + for (auto &ent : value_errors) + collect_error (std::move (ent)); + return resolved; } diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index cf0265140def..75d8c1d9b590 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -673,7 +673,8 @@ public: template tl::optional resolve_path ( const std::vector &segments, bool has_opening_scope_resolution, -std::function insert_segment_resolution); +std::function insert_segment_resolution, +std::vector &collect_errors); // FIXME: Documentation tl::optional to_canonical_path (NodeId id) const; @@ -792,13 +793,15 @@ private: tl::optional> find_starting_point ( const std::vector &segments, std::reference_wrapper &
[gcc r16-213] gccrs: nr2.0: Remove unnecessary copy of Node
https://gcc.gnu.org/g:a11dbc0812be53fab04d6719fa05a26c4e43adcf commit r16-213-ga11dbc0812be53fab04d6719fa05a26c4e43adcf Author: Owen Avery Date: Thu Apr 17 19:23:12 2025 -0400 gccrs: nr2.0: Remove unnecessary copy of Node gcc/rust/ChangeLog: * resolve/rust-forever-stack.hxx (ForeverStack::resolve_path): Pass instance of Node to lambda by reference instead of by value. Signed-off-by: Owen Avery Diff: --- gcc/rust/resolve/rust-forever-stack.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 993e2d4fd2ab..73c795668d9a 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -676,7 +676,7 @@ ForeverStack::resolve_path ( insert_segment_resolution); }) .and_then ([this, &segments, &insert_segment_resolution] ( -Node final_node) -> tl::optional { +Node &final_node) -> tl::optional { // leave resolution within impl blocks to type checker if (final_node.rib.kind == Rib::Kind::TraitOrImpl) return tl::nullopt;
[gcc r16-234] gccrs: Completely duplicate path node
https://gcc.gnu.org/g:dc351dac40989afbc0601e5156017528aa905837 commit r16-234-gdc351dac40989afbc0601e5156017528aa905837 Author: Pierre-Emmanuel Patry Date: Fri Apr 25 16:02:12 2025 +0200 gccrs: Completely duplicate path node Both nodes had the same id, this led to a resolution conflict. gcc/rust/ChangeLog: * expand/rust-derive-clone.cc (DeriveClone::clone_enum_struct): Clone path to avoid using the same nodeid. gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove now passing test from exclusion list. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/rust/expand/rust-derive-clone.cc | 8 +++- gcc/testsuite/rust/compile/nr2/exclude | 1 - 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc index a955b581acd5..321fa00d2ec8 100644 --- a/gcc/rust/expand/rust-derive-clone.cc +++ b/gcc/rust/expand/rust-derive-clone.cc @@ -293,8 +293,14 @@ DeriveClone::clone_enum_struct (PathInExpression variant_path, new ReferencePattern (std::unique_ptr (new StructPattern ( variant_path, loc, pattern_elts)), false, false, loc)); + + PathInExpression new_path (variant_path.get_segments (), +variant_path.get_outer_attrs (), +variant_path.get_locus (), +variant_path.opening_scope_resolution ()); + auto expr = std::unique_ptr ( -new StructExprStructFields (variant_path, std::move (cloned_fields), loc)); +new StructExprStructFields (new_path, std::move (cloned_fields), loc)); return builder.match_case (std::move (pattern), std::move (expr)); } diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index fac66a7de2c1..c020e36fba4a 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -6,7 +6,6 @@ pub_restricted_1.rs pub_restricted_2.rs pub_restricted_3.rs issue-2905-2.rs -derive_clone_enum3.rs derive-default1.rs derive-eq-invalid.rs torture/alt_patterns1.rs
[gcc r16-237] gccrs: Fix narrowing conversion warnings
https://gcc.gnu.org/g:beced835afa3908aa94550d2ca5ee3879a620adb commit r16-237-gbeced835afa3908aa94550d2ca5ee3879a620adb Author: Owen Avery Date: Wed Apr 16 22:53:18 2025 -0400 gccrs: Fix narrowing conversion warnings Fixes PR#119641 gcc/rust/ChangeLog: * checks/errors/borrowck/rust-bir-place.h (IndexVec::size_type): Add. (IndexVec::MAX_INDEX): Add. (IndexVec::size): Change the return type to the type of the internal value used by the index type. (PlaceDB::lookup_or_add_variable): Use the return value from the PlaceDB::add_place call. * checks/errors/borrowck/rust-bir.h (struct BasicBlockId): Move this definition before the definition of the struct Function. Signed-off-by: Owen Avery Diff: --- gcc/rust/checks/errors/borrowck/rust-bir-place.h | 12 +-- gcc/rust/checks/errors/borrowck/rust-bir.h | 40 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-place.h b/gcc/rust/checks/errors/borrowck/rust-bir-place.h index 67ca90b93d02..dd9e672f4120 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-place.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-place.h @@ -204,6 +204,9 @@ template class IndexVec { std::vector internal_vector; + typedef decltype (std::declval ().value) size_type; + static constexpr auto MAX_INDEX = std::numeric_limits::max (); + public: IndexVec () = default; IndexVec (size_t size) { internal_vector.reserve (size); } @@ -219,7 +222,11 @@ public: internal_vector.emplace_back (std::forward (args)...); } - size_t size () const { return internal_vector.size (); } + size_type size () const + { +rust_assert (internal_vector.size () < MAX_INDEX); +return static_cast (internal_vector.size ()); + } std::vector &get_vector () { return internal_vector; } }; @@ -418,8 +425,7 @@ public: if (lookup != INVALID_PLACE) return lookup; -add_place ({Place::VARIABLE, id, {}, is_type_copy (tyty), tyty}); -return {places.size () - 1}; +return add_place ({Place::VARIABLE, id, {}, is_type_copy (tyty), tyty}); }; template void for_each_path_from_root (PlaceId var, FN fn) const diff --git a/gcc/rust/checks/errors/borrowck/rust-bir.h b/gcc/rust/checks/errors/borrowck/rust-bir.h index e90e508a2c71..8a5f7bea3d9a 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir.h @@ -35,6 +35,26 @@ using BasicBlocks = IndexVec; class Statement; class AbstractExpr; +/** Unique identifier for a basic block in the BIR. */ +struct BasicBlockId +{ + uint32_t value; + // some overloads for comparision + bool operator== (const BasicBlockId &rhs) const { return value == rhs.value; } + bool operator!= (const BasicBlockId &rhs) const + { +return !(operator== (rhs)); + } + bool operator< (const BasicBlockId &rhs) const { return value < rhs.value; } + bool operator> (const BasicBlockId &rhs) const { return value > rhs.value; } + bool operator<= (const BasicBlockId &rhs) const { return !(operator> (rhs)); } + bool operator>= (const BasicBlockId &rhs) const { return !(operator< (rhs)); } +}; + +static constexpr BasicBlockId INVALID_BB + = {std::numeric_limits::max ()}; +static constexpr BasicBlockId ENTRY_BASIC_BLOCK = {0}; + /** * Top-level entity of the Borrow-checker IR (BIR). * It represents a single function (method, closure, etc.), which is the @@ -132,26 +152,6 @@ public: WARN_UNUSED_RESULT location_t get_location () const { return location; } }; -/** Unique identifier for a basic block in the BIR. */ -struct BasicBlockId -{ - uint32_t value; - // some overloads for comparision - bool operator== (const BasicBlockId &rhs) const { return value == rhs.value; } - bool operator!= (const BasicBlockId &rhs) const - { -return !(operator== (rhs)); - } - bool operator< (const BasicBlockId &rhs) const { return value < rhs.value; } - bool operator> (const BasicBlockId &rhs) const { return value > rhs.value; } - bool operator<= (const BasicBlockId &rhs) const { return !(operator> (rhs)); } - bool operator>= (const BasicBlockId &rhs) const { return !(operator< (rhs)); } -}; - -static constexpr BasicBlockId INVALID_BB - = {std::numeric_limits::max ()}; -static constexpr BasicBlockId ENTRY_BASIC_BLOCK = {0}; - struct BasicBlock { // BIR "instructions".
[gcc r16-225] gccrs: Change expected error output to match nr2
https://gcc.gnu.org/g:f84a0888c14025dbef90f9c74256a3ec255cb0bd commit r16-225-gf84a0888c14025dbef90f9c74256a3ec255cb0bd Author: Pierre-Emmanuel Patry Date: Thu Apr 24 14:28:59 2025 +0200 gccrs: Change expected error output to match nr2 Name resolution 2.0 message describes the context around the unresolved items and should therefore be kept. gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove test from exclusion list. * rust/compile/use_1.rs: Change expected output and remove test from nr1. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/testsuite/rust/compile/nr2/exclude | 1 - gcc/testsuite/rust/compile/use_1.rs| 9 + 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index 2c116be13491..23f3b1bf62ca 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -7,7 +7,6 @@ privacy8.rs pub_restricted_1.rs pub_restricted_2.rs pub_restricted_3.rs -use_1.rs issue-2905-2.rs derive_clone_enum3.rs derive-default1.rs diff --git a/gcc/testsuite/rust/compile/use_1.rs b/gcc/testsuite/rust/compile/use_1.rs index 94b96321a635..e8e2037aac3f 100644 --- a/gcc/testsuite/rust/compile/use_1.rs +++ b/gcc/testsuite/rust/compile/use_1.rs @@ -1,7 +1,8 @@ +// { dg-additional-options "-frust-name-resolution-2.0" } mod frob {} -use foo::bar::baz; // { dg-error "cannot find simple path segment .foo." } -use frob::ulator; // { dg-error "cannot find simple path segment .ulator." } +use foo::bar::baz; // { dg-error "unresolved import .foo::bar::baz." } +use frob::ulator; // { dg-error "unresolved import .frob::ulator." } mod sain { mod doux {} @@ -9,8 +10,8 @@ mod sain { mod dron {} } -use not_sain::*; // { dg-error "cannot find simple path segment .not_sain." } +use not_sain::*; // { dg-error "unresolved import .not_sain." } use sain::*; use sain::{doux, dron}; -use sain::{doux, dron, graal}; // { dg-error "cannot find simple path segment .graal." } +use sain::{doux, dron, graal}; // { dg-error "unresolved import .sain::graal." }
[gcc r16-235] gccrs: Some assorted tweaks and bug fixes
https://gcc.gnu.org/g:2128f8f47de45030fde66b66e52be2ca15a1559d commit r16-235-g2128f8f47de45030fde66b66e52be2ca15a1559d Author: Owen Avery Date: Sat Jan 11 00:15:05 2025 -0500 gccrs: Some assorted tweaks and bug fixes gcc/rust/ChangeLog: * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Visit the loop labels of WhileLetLoopExpr instances before visiting their scrutinee expressions. * resolve/rust-early-name-resolver-2.0.cc (Early::resolve_glob_import): Pass the glob import's path directly to NameResolutionContext::resolve_path. * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Remove unnecessary call to Identifier::as_string. (flatten_glob): Improve handling of cases where a glob use tree has no path. Signed-off-by: Owen Avery Diff: --- gcc/rust/ast/rust-ast-visitor.cc| 2 +- gcc/rust/resolve/rust-early-name-resolver-2.0.cc| 3 +-- gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc | 5 +++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index 87e7b86573ba..dd42e39292f0 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -582,8 +582,8 @@ DefaultASTVisitor::visit (AST::WhileLetLoopExpr &expr) visit_outer_attrs (expr); for (auto &pattern : expr.get_patterns ()) visit (pattern); - visit (expr.get_scrutinee_expr ()); visit (expr.get_loop_label ()); + visit (expr.get_scrutinee_expr ()); visit (expr.get_loop_block ()); } diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index 7d048ea8289c..3390f09e2916 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -70,8 +70,7 @@ Early::go (AST::Crate &crate) bool Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob) { - auto resolved -= ctx.resolve_path (glob.to_resolve.get_segments (), Namespace::Types); + auto resolved = ctx.resolve_path (glob.to_resolve, Namespace::Types); if (!resolved.has_value ()) return false; diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc index ba37dee88faf..2f036fe40b3f 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -135,8 +135,7 @@ TopLevel::visit (AST::Module &module) void TopLevel::visit (AST::Trait &trait) { - insert_or_error_out (trait.get_identifier ().as_string (), trait, - Namespace::Types); + insert_or_error_out (trait.get_identifier (), trait, Namespace::Types); DefaultResolver::visit (trait); } @@ -548,6 +547,8 @@ flatten_glob (const AST::UseTreeGlob &glob, std::vector &paths, { if (glob.has_path ()) paths.emplace_back (glob.get_path ()); + else +paths.emplace_back (AST::SimplePath ({}, false, glob.get_locus ())); } void
[gcc r16-239] gimplefe: Simplify handling of identifier based binary operations
https://gcc.gnu.org/g:ed3374b0542e0383f03f1db1aacbeef0e693a862 commit r16-239-ged3374b0542e0383f03f1db1aacbeef0e693a862 Author: Andrew Pinski Date: Fri Apr 25 23:22:15 2025 -0700 gimplefe: Simplify handling of identifier based binary operations While looking into adding __ROTATE_LEFT and __ROTATE_RIGHT, I noticed this code is just a bunch of if statments repeated. Instead we could just use a simple lookup array to do the same thinga and it would be easier to add to the array instead of duplicating the if sequence again. Bootstrapped and tested on x86_64-linux-gnu. gcc/c/ChangeLog: * gimple-parser.cc (gimple_binary_identifier_code): New variable. (c_parser_gimple_binary_expression): Use gimple_binary_identifier_code instead of doing if statements on the strings. Signed-off-by: Andrew Pinski Diff: --- gcc/c/gimple-parser.cc | 107 ++--- 1 file changed, 29 insertions(+), 78 deletions(-) diff --git a/gcc/c/gimple-parser.cc b/gcc/c/gimple-parser.cc index 90b9beb1e9f3..34850d7c359f 100644 --- a/gcc/c/gimple-parser.cc +++ b/gcc/c/gimple-parser.cc @@ -963,6 +963,27 @@ c_parser_gimple_statement (gimple_parser &parser, gimple_seq *seq) return; } +/* A mapping between an identifier to a tree code for binary operations. */ +static const std::pair gimple_binary_identifier_code[] = + { +{"__MULT_HIGHPART", MULT_HIGHPART_EXPR}, +{"__UNLT", UNLT_EXPR}, +{"__UNLE", UNLE_EXPR}, +{"__UNGT", UNGT_EXPR}, +{"__UNGE", UNGE_EXPR}, +{"__UNEQ", UNEQ_EXPR}, +{"__UNORDERED", UNORDERED_EXPR}, +{"__ORDERED", ORDERED_EXPR}, +{"__LTGT", LTGT_EXPR}, +{"__FLOOR_DIV", FLOOR_DIV_EXPR}, +{"__ROUND_DIV", ROUND_DIV_EXPR}, +{"__EXACT_DIV", EXACT_DIV_EXPR}, +{"__CEIL_DIV", CEIL_DIV_EXPR}, +{"__FLOOR_MOD", FLOOR_MOD_EXPR}, +{"__ROUND_MOD", ROUND_MOD_EXPR}, +{"__CEIL_MOD", CEIL_MOD_EXPR}, + }; + /* Parse gimple binary expr. gimple-binary-expression: @@ -1061,86 +1082,16 @@ c_parser_gimple_binary_expression (gimple_parser &parser, tree ret_type) case CPP_NAME: { tree id = c_parser_peek_token (parser)->value; - if (strcmp (IDENTIFIER_POINTER (id), "__MULT_HIGHPART") == 0) - { - code = MULT_HIGHPART_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__UNLT") == 0) - { - code = UNLT_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__UNLE") == 0) - { - code = UNLE_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__UNGT") == 0) - { - code = UNGT_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__UNGE") == 0) - { - code = UNGE_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__UNEQ") == 0) - { - code = UNEQ_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__UNORDERED") == 0) - { - code = UNORDERED_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__ORDERED") == 0) - { - code = ORDERED_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__LTGT") == 0) + for (auto &p : gimple_binary_identifier_code) { - code = LTGT_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__FLOOR_DIV") == 0) - { - code = FLOOR_DIV_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__ROUND_DIV") == 0) - { - code = ROUND_DIV_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__EXACT_DIV") == 0) - { - code = EXACT_DIV_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__CEIL_DIV") == 0) - { - code = CEIL_DIV_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__FLOOR_MOD") == 0) - { - code = FLOOR_MOD_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__ROUND_MOD") == 0) - { - code = ROUND_MOD_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__CEIL_MOD") == 0) - { - code = CEIL_MOD_EXPR; - break; + if (strcmp (IDENTIFIER_POINTER (id), p.first) == 0) + { + code = p.second; + break; + } } + if (code != ERROR_MARK) + break; } /* Fallthru. */ default:
[gcc r16-240] gimplefe: Round trip of rotates [PR119432]
https://gcc.gnu.org/g:bfc3154375710a37969b2002dc87219dc2102a13 commit r16-240-gbfc3154375710a37969b2002dc87219dc2102a13 Author: Andrew Pinski Date: Sat Apr 26 05:49:23 2025 -0700 gimplefe: Round trip of rotates [PR119432] This adds support for rotate left/right to the GIMPLE front-end via __ROTATE_LEFT/__ROTATE_RIGHT oeprators. PR c/119432 gcc/c/ChangeLog: * gimple-parser.cc (gimple_binary_identifier_code): Add __ROTATE_LEFT and __ROTATE_RIGHT. gcc/ChangeLog: * tree-pretty-print.cc (op_symbol_code): For LROTATE_EXPR, output __ROTATE_LEFT for gimple. For RROTATE_EXPR output __ROTATE_RIGHT for gimple. gcc/testsuite/ChangeLog: * gcc.dg/gimplefe-57.c: New test. Signed-off-by: Andrew Pinski Diff: --- gcc/c/gimple-parser.cc | 2 ++ gcc/testsuite/gcc.dg/gimplefe-57.c | 11 +++ gcc/tree-pretty-print.cc | 4 ++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/gcc/c/gimple-parser.cc b/gcc/c/gimple-parser.cc index 34850d7c359f..5fd1db874530 100644 --- a/gcc/c/gimple-parser.cc +++ b/gcc/c/gimple-parser.cc @@ -982,6 +982,8 @@ static const std::pair gimple_binary_identifier_code[] {"__FLOOR_MOD", FLOOR_MOD_EXPR}, {"__ROUND_MOD", ROUND_MOD_EXPR}, {"__CEIL_MOD", CEIL_MOD_EXPR}, +{"__ROTATE_LEFT", LROTATE_EXPR}, +{"__ROTATE_RIGHT", RROTATE_EXPR}, }; /* Parse gimple binary expr. diff --git a/gcc/testsuite/gcc.dg/gimplefe-57.c b/gcc/testsuite/gcc.dg/gimplefe-57.c new file mode 100644 index ..d3eca56119d9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gimplefe-57.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple" } */ + +int __GIMPLE +foo (int a, int b) +{ + int tem; + tem = a __ROTATE_LEFT b; + tem = tem __ROTATE_RIGHT b; + return tem; +} diff --git a/gcc/tree-pretty-print.cc b/gcc/tree-pretty-print.cc index c1a21e77bd29..359359d98c20 100644 --- a/gcc/tree-pretty-print.cc +++ b/gcc/tree-pretty-print.cc @@ -4795,10 +4795,10 @@ op_symbol_code (enum tree_code code, dump_flags_t flags) return ">>"; case LROTATE_EXPR: - return "r<<"; + return (flags & TDF_GIMPLE) ? "__ROTATE_LEFT" : "r<<"; case RROTATE_EXPR: - return "r>>"; + return (flags & TDF_GIMPLE) ? "__ROTATE_RIGHT" : "r>>"; case WIDEN_LSHIFT_EXPR: return "w<<";
[gcc r16-241] gimple-verifier: Add check that comparison in GIMPLE_COND does not throw
https://gcc.gnu.org/g:4c40e3d7b9152f40e5a3d35060b6822ddc743624 commit r16-241-g4c40e3d7b9152f40e5a3d35060b6822ddc743624 Author: Andrew Pinski Date: Thu Apr 24 09:45:16 2025 -0700 gimple-verifier: Add check that comparison in GIMPLE_COND does not throw While working on PR 119903, I noticed that there is code in replace_stmt_with_simplification which makes sure that the comparison of a GIMPLE_COND does not throw (non-call exceptions and trapping math) but the gimple verifier does not verify this. So let's add it. Bootstrapped and tested on x86_64-linux-gnu. gcc/ChangeLog: * tree-cfg.cc (verify_gimple_cond): Error out if the comparison throws. Signed-off-by: Andrew Pinski Diff: --- gcc/tree-cfg.cc | 13 + 1 file changed, 13 insertions(+) diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc index ecf19d280797..6a95b82ff404 100644 --- a/gcc/tree-cfg.cc +++ b/gcc/tree-cfg.cc @@ -5104,6 +5104,19 @@ verify_gimple_cond (gcond *stmt) return true; } + tree lhs = gimple_cond_lhs (stmt); + + /* GIMPLE_CONDs condition may not throw. */ + if (flag_exceptions + && cfun->can_throw_non_call_exceptions + && operation_could_trap_p (gimple_cond_code (stmt), +FLOAT_TYPE_P (TREE_TYPE (lhs)), +false, NULL_TREE)) +{ + error ("gimple cond condition cannot throw"); + return true; +} + return verify_gimple_comparison (boolean_type_node, gimple_cond_lhs (stmt), gimple_cond_rhs (stmt),
[gcc r16-238] Add testcase for bogus Warray-bounds warning dealing with __builtin_unreachable [PR100038]
https://gcc.gnu.org/g:07a14a490b8f57dfe2a5b853fb4b88e9e124a92b commit r16-238-g07a14a490b8f57dfe2a5b853fb4b88e9e124a92b Author: Andrew Pinski Date: Sat Apr 5 04:47:59 2025 -0700 Add testcase for bogus Warray-bounds warning dealing with __builtin_unreachable [PR100038] After EVRP was switched to the ranger (r12-2305-g398572c1544d8b), we are better handling the case where __builtin_unreachable comes after a loop. Instead of removing __builtin_unreachable and having the loop become an infinite one; it is kept around longer and allows GCC to unroll the loop 2 times instead of 3 times. When GCC unrolled the loop 3 times, GCC would produce a bogus Warray-bounds warning for the 3rd iteration. This adds the testcase to make sure we don't regress on this case. It is originally extracted from LLVM source code too. PR tree-optimization/100038 gcc/testsuite/ChangeLog: * g++.dg/tree-ssa/pr100038.C: New test. Signed-off-by: Andrew Pinski Diff: --- gcc/testsuite/g++.dg/tree-ssa/pr100038.C | 17 + 1 file changed, 17 insertions(+) diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr100038.C b/gcc/testsuite/g++.dg/tree-ssa/pr100038.C new file mode 100644 index ..7024c4db2b21 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr100038.C @@ -0,0 +1,17 @@ +// { dg-do compile } +// { dg-options "-O2 -Wextra -Wall -Warray-bounds" } + +struct SparseBitVectorElement { + long Bits[2]; + int find_first() const; +}; + +// we should not get an `array subscript 2 is above array bounds of` +// warning here because we have an unreachable at that point + +int SparseBitVectorElement::find_first() const { + for (unsigned i = 0; i < 2; ++i) +if (Bits[i]) // { dg-bogus "is above array bounds of" } + return i; + __builtin_unreachable(); +}
[gcc r16-202] gccrs: Add check for placeholder (infer) type in return position
https://gcc.gnu.org/g:facff07882583e6ce853a21ada7932e38b6047e3 commit r16-202-gfacff07882583e6ce853a21ada7932e38b6047e3 Author: Philip Herron Date: Wed Apr 16 20:38:17 2025 +0100 gccrs: Add check for placeholder (infer) type in return position It is not allowed to have a declared inference variable in the return position of a function as this may never get infered you need good points of truth. Ideally if we get a student for GSoC 25 we will get the Default Hir Visitor so that we can grab the HIR::InferredType locus instead of using the ref location lookups. Fixes Rust-GCC#402 gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): add diagnostic * typecheck/rust-tyty.cc (BaseType::contains_infer): new helper to grab first infer var * typecheck/rust-tyty.h: prototype gcc/testsuite/ChangeLog: * rust/compile/issue-402.rs: New test. Signed-off-by: Philip Herron Diff: --- gcc/rust/typecheck/rust-hir-type-check-item.cc | 32 ++ gcc/rust/typecheck/rust-tyty.cc| 85 ++ gcc/rust/typecheck/rust-tyty.h | 3 + gcc/testsuite/rust/compile/issue-402.rs| 14 + 4 files changed, 134 insertions(+) diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index 177dd556293c..aaa04af628f4 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -649,6 +649,38 @@ TypeCheckItem::visit (HIR::Function &function) context->switch_to_fn_body (); auto block_expr_ty = TypeCheckExpr::Resolve (function.get_definition ()); + // emit check for + // error[E0121]: the type placeholder `_` is not allowed within types on item + const auto placeholder = ret_type->contains_infer (); + if (placeholder != nullptr && function.has_return_type ()) +{ + // FIXME + // this will be a great place for the Default Hir Visitor we want to + // grab the locations of the placeholders (HIR::InferredType) their + // location, for now maybe we can use their hirid to lookup the location + location_t placeholder_locus + = mappings.lookup_location (placeholder->get_ref ()); + location_t type_locus = function.get_return_type ().get_locus (); + rich_location r (line_table, placeholder_locus); + + bool have_expected_type + = block_expr_ty != nullptr && !block_expr_ty->is (); + if (!have_expected_type) + { + r.add_range (type_locus); + } + else + { + std::string fixit + = "replace with the correct type " + block_expr_ty->get_name (); + r.add_fixit_replace (type_locus, fixit.c_str ()); + } + + rust_error_at (r, ErrorCode::E0121, +"the type placeholder %<_%> is not allowed within types " +"on item signatures"); +} + location_t fn_return_locus = function.has_function_return_type () ? function.get_return_type ().get_locus () : function.get_locus (); diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index efad5f613228..f0f4a07e9660 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -682,6 +682,91 @@ BaseType::debug () const debug_str ().c_str ()); } +const TyTy::BaseType * +BaseType::contains_infer () const +{ + const TyTy::BaseType *x = destructure (); + + if (auto fn = x->try_as ()) +{ + for (const auto ¶m : fn->get_params ()) + { + auto infer = param.get_type ()->contains_infer (); + if (infer) + return infer; + } + return fn->get_return_type ()->contains_infer (); +} + else if (auto fn = x->try_as ()) +{ + for (const auto ¶m : fn->get_params ()) + { + auto infer = param.get_tyty ()->contains_infer (); + if (infer) + return infer; + } + return fn->get_return_type ()->contains_infer (); +} + else if (auto adt = x->try_as ()) +{ + for (auto &variant : adt->get_variants ()) + { + bool is_num_variant + = variant->get_variant_type () == VariantDef::VariantType::NUM; + if (is_num_variant) + continue; + + for (auto &field : variant->get_fields ()) + { + const BaseType *field_type = field->get_field_type (); + auto infer = (field_type->contains_infer ()); + if (infer) + return infer; + } + } + return nullptr; +} + else if (auto arr = x->try_as ()) +{ + return arr->get_element_type ()->contains_infer (); +} + else if (auto slice = x->try_as ()) +{ + return slice->get_element_type ()->contains_infer (); +} + else if
[gcc r16-204] gccrs: Add llvmInlineAsm node
https://gcc.gnu.org/g:69782437f1e016f8cde0822610662f10986dac41 commit r16-204-g69782437f1e016f8cde0822610662f10986dac41 Author: Pierre-Emmanuel Patry Date: Thu Apr 10 13:05:15 2025 +0200 gccrs: Add llvmInlineAsm node InlineAsm node does not support memory clobbers. gcc/rust/ChangeLog: * ast/rust-ast-collector.cc (TokenCollector::visit): Make visitor unreachable. * ast/rust-ast-collector.h: Add visit for LlvmInlineAsmNode. * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Add visit function for the default ast visitor. * ast/rust-ast-visitor.h: Add function prototype. * ast/rust-ast.cc (LlvmInlineAsm::accept_vis): Add accept_vis to LlvmInlineAsm node. * ast/rust-ast.h: Add LlvmInlineAsm node kind. * ast/rust-expr.h (class LlvmInlineAsm): Add LlvmInlineAsm node. * expand/rust-derive.h: Add visit function for LlvmInlineAsm node. * expand/rust-macro-builtins-asm.cc (MacroBuiltin::llvm_asm_handler): Add handler for llvm inline assembly nodes. (parse_llvm_asm): Add function to parse llvm assembly nodes. * expand/rust-macro-builtins-asm.h (parse_llvm_asm): Add function prototypes. * expand/rust-macro-builtins.cc (inline_llvm_asm_maker): Add macro transcriber. * expand/rust-macro-builtins.h: Add transcriber function prototype. * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Add visit function for LlvmInlineAsm node. * hir/rust-ast-lower-base.h: Add visit function prototype. * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Add visit function for LlvmInlineAsm node. * resolve/rust-ast-resolve-base.h: Add visit function prototype. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/rust/ast/rust-ast-collector.cc | 10 ++- gcc/rust/ast/rust-ast-collector.h | 1 + gcc/rust/ast/rust-ast-visitor.cc | 4 +++ gcc/rust/ast/rust-ast-visitor.h| 2 ++ gcc/rust/ast/rust-ast.cc | 6 gcc/rust/ast/rust-ast.h| 1 + gcc/rust/ast/rust-expr.h | 48 ++ gcc/rust/expand/rust-derive.h | 1 + gcc/rust/expand/rust-macro-builtins-asm.cc | 21 + gcc/rust/expand/rust-macro-builtins-asm.h | 7 + gcc/rust/expand/rust-macro-builtins.cc | 11 ++- gcc/rust/expand/rust-macro-builtins.h | 4 +++ gcc/rust/hir/rust-ast-lower-base.cc| 4 +++ gcc/rust/hir/rust-ast-lower-base.h | 1 + gcc/rust/resolve/rust-ast-resolve-base.cc | 4 +++ gcc/rust/resolve/rust-ast-resolve-base.h | 1 + 16 files changed, 124 insertions(+), 2 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 8ee63752f325..90ff2e362515 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -1520,7 +1520,15 @@ TokenCollector::visit (AsyncBlockExpr &expr) void TokenCollector::visit (InlineAsm &expr) -{} +{ + rust_unreachable (); +} + +void +TokenCollector::visit (LlvmInlineAsm &expr) +{ + rust_unreachable (); +} // rust-item.h diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h index b014c23ed0b8..f45e3cc51aee 100644 --- a/gcc/rust/ast/rust-ast-collector.h +++ b/gcc/rust/ast/rust-ast-collector.h @@ -303,6 +303,7 @@ public: void visit (AwaitExpr &expr); void visit (AsyncBlockExpr &expr); void visit (InlineAsm &expr); + void visit (LlvmInlineAsm &expr); // rust-item.h void visit (TypeParam ¶m); void visit (LifetimeWhereClauseItem &item); diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index 9d524c3cc4c8..beb3360c4e12 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -713,6 +713,10 @@ DefaultASTVisitor::visit (AST::InlineAsm &expr) } } +void +DefaultASTVisitor::visit (AST::LlvmInlineAsm &expr) +{} + void DefaultASTVisitor::visit (AST::TypeParam ¶m) { diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index 51661df76b49..6d243e7b063e 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -131,6 +131,7 @@ public: virtual void visit (AwaitExpr &expr) = 0; virtual void visit (AsyncBlockExpr &expr) = 0; virtual void visit (InlineAsm &expr) = 0; + virtual void visit (LlvmInlineAsm &expr) = 0; // rust-item.h virtual void visit (TypeParam ¶m) = 0; @@ -314,6 +315,7 @@ public: virtual void visit (AST::AwaitExpr &expr) override; virtual void visit (AST::AsyncBlockExpr &expr) override; virtual void visit (InlineAsm &expr) override; + virtual void visit (LlvmInlineAsm &expr) override; virtual void visit (AST::TypeParam ¶m) override
[gcc r16-198] gccrs: Implement integer representation for enums
https://gcc.gnu.org/g:491ac170145d4155370d9a8742333b34310fe886 commit r16-198-g491ac170145d4155370d9a8742333b34310fe886 Author: Zhi Heng Date: Thu Apr 3 23:02:59 2025 +0800 gccrs: Implement integer representation for enums gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-base.cc: Set enum representing type properly if repr is an integer type. * typecheck/rust-hir-type-check-item.cc: Update comments. Signed-off-by: Yap Zhi Heng Diff: --- gcc/rust/typecheck/rust-hir-type-check-base.cc | 13 ++--- gcc/rust/typecheck/rust-hir-type-check-item.cc | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc index c6bb147c1c8f..2ee0d0833e82 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc @@ -308,7 +308,7 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus) repr.pack = 0; repr.align = 0; - // FIXME handle repr types + // FIXME handle non-integer repr types bool ok = context->lookup_builtin ("isize", &repr.repr); rust_assert (ok); @@ -353,8 +353,10 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus) // manually parsing the string "packed(2)" here. size_t oparen = inline_option.find ('(', 0); - bool is_pack = false, is_align = false, is_c = false, - is_integer = false; + bool is_pack = false; + bool is_align = false; + bool is_c = false; + bool is_integer = false; unsigned char value = 1; if (oparen == std::string::npos) @@ -409,6 +411,11 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus) else if (is_integer) { repr.repr_kind = TyTy::ADTType::ReprKind::INT; + bool ok = context->lookup_builtin (inline_option, &repr.repr); + if (!ok) + { + rust_error_at (attr.get_locus (), "Invalid repr type"); + } } delete meta_items; diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index 85a9ada2b9b4..177dd556293c 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -355,7 +355,7 @@ TypeCheckItem::visit (HIR::Enum &enum_decl) variants.push_back (field_type); } - // Check for zero-variant enum compatibility before processing repr attribute + // Check for zero-variant enum compatibility if (enum_decl.is_zero_variant ()) { if (repr.repr_kind == TyTy::ADTType::ReprKind::INT
[gcc r16-200] gccrs: Fix crash in hir dump as labels are optional
https://gcc.gnu.org/g:75a57211f698242d247f5c4230b8348b236f9ded commit r16-200-g75a57211f698242d247f5c4230b8348b236f9ded Author: Philip Herron Date: Wed Apr 16 17:00:28 2025 +0100 gccrs: Fix crash in hir dump as labels are optional gcc/rust/ChangeLog: * hir/rust-hir-dump.cc (Dump::visit): add guard for optional label Signed-off-by: Philip Herron Diff: --- gcc/rust/hir/rust-hir-dump.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc index dafa8236ba10..16fce6be28e6 100644 --- a/gcc/rust/hir/rust-hir-dump.cc +++ b/gcc/rust/hir/rust-hir-dump.cc @@ -1284,7 +1284,9 @@ Dump::visit (BlockExpr &e) do_expr (e); do_inner_attrs (e); put_field ("tail_reachable", std::to_string (e.is_tail_reachable ())); - put_field ("label", e.get_label ().as_string ()); + + if (e.has_label ()) +put_field ("label", e.get_label ().as_string ()); visit_collection ("statements", e.get_statements ());
[gcc r16-199] gccrs: Update comments in repr parsing code
https://gcc.gnu.org/g:afdb4a46262ba527823ea9bbe10ffb5859a31ebd commit r16-199-gafdb4a46262ba527823ea9bbe10ffb5859a31ebd Author: Yap Zhi Heng Date: Fri Apr 4 19:37:03 2025 +0800 gccrs: Update comments in repr parsing code gcc/rust/ChangeLog: * typecheck/rust-tyty.h: Remove extra redundant comment. * typecheck/rust-hir-type-check-base.cc: Update comment on repr handling. Signed-off-by: Yap Zhi Heng Diff: --- gcc/rust/typecheck/rust-hir-type-check-base.cc | 3 ++- gcc/rust/typecheck/rust-tyty.h | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc index 2ee0d0833e82..14b8ab8635e1 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc @@ -308,7 +308,8 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus) repr.pack = 0; repr.align = 0; - // FIXME handle non-integer repr types + // Default repr for enums is isize, but we now check for other repr in the + // attributes. bool ok = context->lookup_builtin ("isize", &repr.repr); rust_assert (ok); diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 9897c30fc278..030968377524 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -719,7 +719,6 @@ public: ALIGN, PACKED, // TRANSPARENT, -// PACKED, // SIMD, // ... };
[gcc r16-201] gccrs: Fix ICE when checking shift's which are behind array refs
https://gcc.gnu.org/g:2cbb3bf90dd75f26f865eb4d9d51eaeca30f33a7 commit r16-201-g2cbb3bf90dd75f26f865eb4d9d51eaeca30f33a7 Author: Philip Herron Date: Wed Apr 16 17:13:04 2025 +0100 gccrs: Fix ICE when checking shift's which are behind array refs I copied a bad form of this check from the c front-end this updates it to ensure the rhs is an INTEGER_CST and the lhs needs checked in the first place. Fixes Rust-GCC#3664 gcc/rust/ChangeLog: * rust-gcc.cc (arithmetic_or_logical_expression): Ensure this is an integer gcc/testsuite/ChangeLog: * rust/compile/issue-3664.rs: New test. Signed-off-by: Philip Herron Diff: --- gcc/rust/rust-gcc.cc | 1 + gcc/testsuite/rust/compile/issue-3664.rs | 5 + 2 files changed, 6 insertions(+) diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 234721c585fd..e5319d320800 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -1109,6 +1109,7 @@ arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, tree left, rust_error_at (location, "division by zero"); } else if (op == ArithmeticOrLogicalOperator::LEFT_SHIFT + && TREE_CODE (right) == INTEGER_CST && (compare_tree_int (right, TYPE_PRECISION (TREE_TYPE (ret))) >= 0)) { rust_error_at (location, "left shift count >= width of type"); diff --git a/gcc/testsuite/rust/compile/issue-3664.rs b/gcc/testsuite/rust/compile/issue-3664.rs new file mode 100644 index ..c52a75805afd --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3664.rs @@ -0,0 +1,5 @@ +const ARR: [usize; 1] = [2]; + +pub fn l8() { +let _ = 5 << ARR[0]; +}
[gcc r16-197] gccrs: Implement typecheck for zero-variant enums
https://gcc.gnu.org/g:ab64d37ec6dd9ac751178efa089ddb984654e115 commit r16-197-gab64d37ec6dd9ac751178efa089ddb984654e115 Author: Zhi Heng Date: Thu Apr 3 20:23:46 2025 +0800 gccrs: Implement typecheck for zero-variant enums gcc/rust/ChangeLog: * typecheck/rust-tyty.h: Add new `ReprKind` enum to `ReprOptions`. * typecheck/rust-hir-type-check-base.cc: Handle setting of `repr_kind`. * typecheck/rust-hir-type-check-item.cc: New check for zero-variant enums. Signed-off-by: Yap Zhi Heng Diff: --- gcc/rust/typecheck/rust-hir-type-check-base.cc | 34 +++--- gcc/rust/typecheck/rust-hir-type-check-item.cc | 12 + gcc/rust/typecheck/rust-tyty.h | 17 ++--- gcc/testsuite/rust/compile/issue-3530-1.rs | 2 ++ gcc/testsuite/rust/compile/issue-3530-2.rs | 2 ++ 5 files changed, 61 insertions(+), 6 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc index beee91e79444..c6bb147c1c8f 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc @@ -353,13 +353,27 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus) // manually parsing the string "packed(2)" here. size_t oparen = inline_option.find ('(', 0); - bool is_pack = false, is_align = false; + bool is_pack = false, is_align = false, is_c = false, + is_integer = false; unsigned char value = 1; if (oparen == std::string::npos) { is_pack = inline_option.compare ("packed") == 0; is_align = inline_option.compare ("align") == 0; + is_c = inline_option.compare ("C") == 0; + is_integer = (inline_option.compare ("isize") == 0 + || inline_option.compare ("i8") == 0 + || inline_option.compare ("i16") == 0 + || inline_option.compare ("i32") == 0 + || inline_option.compare ("i64") == 0 + || inline_option.compare ("i128") == 0 + || inline_option.compare ("usize") == 0 + || inline_option.compare ("u8") == 0 + || inline_option.compare ("u16") == 0 + || inline_option.compare ("u32") == 0 + || inline_option.compare ("u64") == 0 + || inline_option.compare ("u128") == 0); } else @@ -379,9 +393,23 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus) } if (is_pack) - repr.pack = value; + { + repr.repr_kind = TyTy::ADTType::ReprKind::PACKED; + repr.pack = value; + } else if (is_align) - repr.align = value; + { + repr.repr_kind = TyTy::ADTType::ReprKind::ALIGN; + repr.align = value; + } + else if (is_c) + { + repr.repr_kind = TyTy::ADTType::ReprKind::C; + } + else if (is_integer) + { + repr.repr_kind = TyTy::ADTType::ReprKind::INT; + } delete meta_items; diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index 977492143517..85a9ada2b9b4 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -355,6 +355,18 @@ TypeCheckItem::visit (HIR::Enum &enum_decl) variants.push_back (field_type); } + // Check for zero-variant enum compatibility before processing repr attribute + if (enum_decl.is_zero_variant ()) +{ + if (repr.repr_kind == TyTy::ADTType::ReprKind::INT + || repr.repr_kind == TyTy::ADTType::ReprKind::C) + { + rust_error_at (enum_decl.get_locus (), +"unsupported representation for zero-variant enum"); + return; + } +} + // get the path tl::optional canonical_path; diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index e814f07f445c..9897c30fc278 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -711,12 +711,23 @@ public: ENUM }; + enum ReprKind + { +RUST, +C, +INT, +ALIGN, +PACKED, +// TRANSPARENT, +// PACKED, +// SIMD, +// ... + }; + // Representation options, specified via attributes e.g. #[repr(packed)] struct ReprOptions { -// bool is_c; -// bool is_transparent; -//... +ReprKind repr_kind = ReprKind::RUST; // For align and pack: 0 = unspecified. Nonzero = byte alignment. // It is an error for both to be nonzero, th
[gcc r16-196] gccrs: Fix segv in unsafe chcker
https://gcc.gnu.org/g:56408be2bdbd1e052a140ae014c8e619ecbab5d7 commit r16-196-g56408be2bdbd1e052a140ae014c8e619ecbab5d7 Author: Philip Herron Date: Fri Apr 4 16:35:13 2025 +0100 gccrs: Fix segv in unsafe chcker Trait constants were missing type resolution step, this adds that as if it was a normal constant. The unsafe checker was missing a null check. Fixes Rust-GCC#3612 gcc/rust/ChangeLog: * checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit): add null check * hir/tree/rust-hir-item.h: add has_type helper * typecheck/rust-hir-trait-resolve.cc (TraitItemReference::resolve_item): add missing type checking gcc/testsuite/ChangeLog: * rust/compile/issue-3612.rs: New test. Signed-off-by: Philip Herron Diff: --- gcc/rust/checks/errors/rust-unsafe-checker.cc | 5 + gcc/rust/hir/tree/rust-hir-item.h | 2 ++ gcc/rust/typecheck/rust-hir-trait-resolve.cc | 21 - gcc/testsuite/rust/compile/issue-3612.rs | 7 +++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc b/gcc/rust/checks/errors/rust-unsafe-checker.cc index 8aa59ee9e284..bb887a991170 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.cc +++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc @@ -481,9 +481,14 @@ UnsafeChecker::visit (MethodCallExpr &expr) TyTy::BaseType *method_type; context.lookup_type (expr.get_method_name ().get_mappings ().get_hirid (), &method_type); + if (!method_type || !method_type->is ()) +return; auto &fn = static_cast (*method_type); + // FIXME + // should probably use the defid lookup instead + // tl::optional lookup_defid (DefId id); auto method = mappings.lookup_hir_implitem (fn.get_ref ()); if (!unsafe_context.is_in_context () && method) check_unsafe_call (static_cast (method->first), diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index b9b105b2b2a9..37f599cdee4a 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -2070,6 +2070,8 @@ public: Identifier get_name () const { return name; } + bool has_type () const { return expr != nullptr; } + bool has_expr () const { return expr != nullptr; } Type &get_type () diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc index e78c19263dc1..032bb5841272 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc @@ -384,7 +384,26 @@ TraitItemReference::resolve_item (HIR::TraitItemType &type) void TraitItemReference::resolve_item (HIR::TraitItemConst &constant) { - // TODO + TyTy::BaseType *ty = nullptr; + if (constant.has_type ()) +ty = TypeCheckType::Resolve (constant.get_type ()); + + TyTy::BaseType *expr = nullptr; + if (constant.has_expr ()) +expr = TypeCheckExpr::Resolve (constant.get_expr ()); + + bool have_specified_ty = ty != nullptr && !ty->is (); + bool have_expr_ty = expr != nullptr && !expr->is (); + + if (have_specified_ty && have_expr_ty) +{ + coercion_site (constant.get_mappings ().get_hirid (), +TyTy::TyWithLocation (ty, + constant.get_type ().get_locus ()), +TyTy::TyWithLocation (expr, + constant.get_expr ().get_locus ()), +constant.get_locus ()); +} } void diff --git a/gcc/testsuite/rust/compile/issue-3612.rs b/gcc/testsuite/rust/compile/issue-3612.rs new file mode 100644 index ..5256d0ad318b --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3612.rs @@ -0,0 +1,7 @@ +trait _St1 { +pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) }; +// { dg-error "no method named .as_ptr. found in the current scope .E0599." "" { target *-*-* } .-1 } +// { dg-error "failed to resolve receiver in MethodCallExpr" "" { target *-*-* } .-2 } +} + +fn main() {}
[gcc r16-205] gccrs: Parse and lower llvm asm node
https://gcc.gnu.org/g:7f3050bd279a02830e8db13e728525af96a0b187 commit r16-205-g7f3050bd279a02830e8db13e728525af96a0b187 Author: Pierre-Emmanuel Patry Date: Tue Apr 15 11:38:29 2025 +0200 gccrs: Parse and lower llvm asm node Add a new HIR LlvmInlineAsm HIR node as well as some structures to represent it's options and operands. Lower AST::LlvmInlineAsm node to it and then create a tree from that node. gcc/rust/ChangeLog: * ast/rust-ast-collector.cc (TokenCollector::visit): Remove unreachable code. * ast/rust-expr.h (struct LlvmOperand): Add LlvmOperand struct to represent input and outputs. (class LlvmInlineAsm): Add input, output and clobber operands. (struct TupleTemplateStr): Add locus getter. * backend/rust-compile-block.h: Add visit for LlvmInlineAsm. * backend/rust-compile-expr.cc (CompileExpr::visit): Add llvm inline asm stmt compilation. * backend/rust-compile-expr.h: Add function prototype. * backend/rust-compile-asm.h (class CompileLlvmAsm): Add llvm asm hir not to gimple. * backend/rust-compile-asm.cc (CompileLlvmAsm::CompileLlvmAsm): Add constructor. (CompileLlvmAsm::construct_operands): Add function to construct operand tree. (CompileLlvmAsm::construct_clobbers): Add function to construct clobber tree. (CompileLlvmAsm::tree_codegen_asm): Generate the whole tree for a given llvm inline assembly node. * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc (ExprStmtBuilder::visit): Add visit function. * checks/errors/borrowck/rust-bir-builder-expr-stmt.h: Add function prototype. * checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h: Add visit function. * checks/errors/borrowck/rust-bir-builder-struct.h: Likewise. * checks/errors/borrowck/rust-function-collector.h: Likewise. * checks/errors/privacy/rust-privacy-reporter.cc (PrivacyReporter::visit): Likewise. * checks/errors/privacy/rust-privacy-reporter.h: Add visit function prototype. * checks/errors/rust-const-checker.cc (ConstChecker::visit): Add visit function. * checks/errors/rust-const-checker.h: Add visit function prototype. * checks/errors/rust-hir-pattern-analysis.cc (PatternChecker::visit): Add visit function. * checks/errors/rust-hir-pattern-analysis.h: Add visit function prototype. * checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit): Add visit function. * checks/errors/rust-unsafe-checker.h: Add function prototype. * expand/rust-macro-builtins-asm.cc (parse_llvm_templates): Parse templates. (parse_llvm_arguments): Add function to parse non template tokens. (parse_llvm_operands): Add function to parse operands, either input or output. (parse_llvm_outputs): Add function to parse and collect llvm asm outputs. (parse_llvm_inputs): Likewise with inputs. (parse_llvm_clobbers): Add function to parse llvm asm clobbers. (parse_llvm_options): Add function to parse llvm asm options. (parse_llvm_asm): Add function to parse llvm asm. * expand/rust-macro-builtins-asm.h (class LlvmAsmContext): Add context for llvm asm parser. (parse_llvm_outputs): Add function prototype. (parse_llvm_inputs): Likewise. (parse_llvm_clobbers): Likewise. (parse_llvm_options): Likewise. * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Lower AST llvm asm node to HIR. * hir/rust-ast-lower-expr.h: Add function prototype. * hir/rust-hir-dump.cc (Dump::visit): Add visit function. * hir/rust-hir-dump.h: Add function prototype. * hir/tree/rust-hir-expr-abstract.h: Add HIR llvm asm node kind. * hir/tree/rust-hir-expr.h (struct LlvmOperand): Add LlvmOperand type to represent input and outputs. (class LlvmInlineAsm): Add LlvmInlineAsm hir node. * hir/tree/rust-hir-full-decls.h (class LlvmInlineAsm): Add LlvmInlineAsm hir node forward declaration. * hir/tree/rust-hir-visitor.h: Add visit functions for LlvmInlineAsm hir node. * hir/tree/rust-hir.cc (LlvmInlineAsm::accept_vis): Add hir node visitor related functions. * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Type check input and output operands. * typecheck/rust-hir-type-check-expr.h: Add function prototype. * ast/rust-ast-vis
[gcc r16-206] gccrs: Add LlvmInlineAsm node dump
https://gcc.gnu.org/g:d76cbf459c19ac167f9bebe1a365a683b6d0f7f0 commit r16-206-gd76cbf459c19ac167f9bebe1a365a683b6d0f7f0 Author: Pierre-Emmanuel Patry Date: Thu Apr 17 14:27:11 2025 +0200 gccrs: Add LlvmInlineAsm node dump gcc/rust/ChangeLog: * ast/rust-ast-collector.cc (TokenCollector::visit): Dump llvm inline asm tokens. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/rust/ast/rust-ast-collector.cc | 39 +- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 4148644324a4..5a104e32b9ad 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -1524,7 +1524,44 @@ TokenCollector::visit (InlineAsm &expr) void TokenCollector::visit (LlvmInlineAsm &expr) -{} +{ + push (Rust::Token::make_identifier (expr.get_locus (), "llvm_asm")); + push (Rust::Token::make (EXCLAM, expr.get_locus ())); + push (Rust::Token::make (LEFT_PAREN, expr.get_locus ())); + for (auto &template_str : expr.get_templates ()) +push (Rust::Token::make_string (template_str.get_locus (), + std::move (template_str.symbol))); + + push (Rust::Token::make (COLON, expr.get_locus ())); + for (auto output : expr.get_outputs ()) +{ + push (Rust::Token::make_string (expr.get_locus (), + std::move (output.constraint))); + visit (output.expr); + push (Rust::Token::make (COMMA, expr.get_locus ())); +} + + push (Rust::Token::make (COLON, expr.get_locus ())); + for (auto input : expr.get_inputs ()) +{ + push (Rust::Token::make_string (expr.get_locus (), + std::move (input.constraint))); + visit (input.expr); + push (Rust::Token::make (COMMA, expr.get_locus ())); +} + + push (Rust::Token::make (COLON, expr.get_locus ())); + for (auto &clobber : expr.get_clobbers ()) +{ + push (Rust::Token::make_string (expr.get_locus (), + std::move (clobber.symbol))); + push (Rust::Token::make (COMMA, expr.get_locus ())); +} + push (Rust::Token::make (COLON, expr.get_locus ())); + // Dump options + + push (Rust::Token::make (RIGHT_PAREN, expr.get_locus ())); +} // rust-item.h
[gcc r16-203] gccrs: Emit error with old asm syntax in new asm blocks
https://gcc.gnu.org/g:4894b1e6f2e44afda930322eb4ee487d53242dbc commit r16-203-g4894b1e6f2e44afda930322eb4ee487d53242dbc Author: Pierre-Emmanuel Patry Date: Wed Apr 9 17:41:24 2025 +0200 gccrs: Emit error with old asm syntax in new asm blocks gcc/rust/ChangeLog: * expand/rust-macro-builtins-asm.cc (parse_asm_arg): Emit error message. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/rust/expand/rust-macro-builtins-asm.cc | 8 1 file changed, 8 insertions(+) diff --git a/gcc/rust/expand/rust-macro-builtins-asm.cc b/gcc/rust/expand/rust-macro-builtins-asm.cc index 4d0260447761..97f7e3cff779 100644 --- a/gcc/rust/expand/rust-macro-builtins-asm.cc +++ b/gcc/rust/expand/rust-macro-builtins-asm.cc @@ -671,6 +671,14 @@ parse_asm_arg (InlineAsmContext inline_asm_ctx) { token = parser.peek_current_token (); + if (token->get_id () == COLON || token->get_id () == SCOPE_RESOLUTION) + { + rust_error_at ( + token->get_locus (), + "the legacy LLVM-style % syntax is no longer supported"); + return tl::unexpected (COMMITTED); + } + // We accept a comma token here. if (token->get_id () != COMMA && inline_asm_ctx.consumed_comma_without_formatted_string)
[gcc r16-231] gccrs: Use stacked context for nested bindings.
https://gcc.gnu.org/g:5023cc6b829589f5a9e986a7ca601a0d3c6cd9aa commit r16-231-g5023cc6b829589f5a9e986a7ca601a0d3c6cd9aa Author: Pierre-Emmanuel Patry Date: Sun Apr 6 18:49:11 2025 +0200 gccrs: Use stacked context for nested bindings. Binding context may be stacked when a new binding group is introduced within a const expression. gcc/rust/ChangeLog: * resolve/rust-name-resolution-context.h: Use BindingLayer instead. * resolve/rust-name-resolution-context.cc (BindingLayer::BindingLayer): Add new constructor for binding layer. (BindingLayer::bind_test): Add a function to test a binding constraint. (BindingLayer::push): Push a new binding group. (BindingLayer::and_binded): Add function to test and-binding constraint. (BindingLayer::or_binded): Add function to test or-binding constraints. (BindingLayer::insert_ident): Insert a new identifier in the current binding group. (BindingLayer::merge): Merge current binding group with it's parent. (BindingLayer::get_source): Get the source of the current binding group. * resolve/rust-late-name-resolver-2.0.cc: Use stacked context for binding group. * util/rust-stacked-contexts.h: Add mutable peek function. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 44 +++ gcc/rust/resolve/rust-name-resolution-context.cc | 59 +++ gcc/rust/resolve/rust-name-resolution-context.h | 72 gcc/rust/util/rust-stacked-contexts.h| 9 ++- 4 files changed, 113 insertions(+), 71 deletions(-) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 1ecf48152d84..e26e4187b28f 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -133,11 +133,11 @@ Late::visit (AST::ForLoopExpr &expr) { visit_outer_attrs (expr); - ctx.bindings.new_binding (BindingSource::For); + ctx.bindings.enter (BindingSource::For); visit (expr.get_pattern ()); - ctx.bindings.clear (); + ctx.bindings.exit (); visit (expr.get_iterator_expr ()); visit (expr.get_loop_label ()); @@ -149,12 +149,12 @@ Late::visit (AST::IfLetExpr &expr) { visit_outer_attrs (expr); - ctx.bindings.new_binding (BindingSource::Let); + ctx.bindings.enter (BindingSource::Let); for (auto &pattern : expr.get_patterns ()) visit (pattern); - ctx.bindings.clear (); + ctx.bindings.exit (); visit (expr.get_value_expr ()); visit (expr.get_if_block ()); @@ -165,12 +165,12 @@ Late::visit (AST::MatchArm &arm) { visit_outer_attrs (arm); - ctx.bindings.new_binding (BindingSource::Match); + ctx.bindings.enter (BindingSource::Match); for (auto &pattern : arm.get_patterns ()) visit (pattern); - ctx.bindings.clear (); + ctx.bindings.exit (); if (arm.has_match_arm_guard ()) visit (arm.get_guard_expr ()); @@ -187,11 +187,11 @@ Late::visit (AST::LetStmt &let) if (let.has_init_expr ()) visit (let.get_init_expr ()); - ctx.bindings.new_binding (BindingSource::Let); + ctx.bindings.enter (BindingSource::Let); visit (let.get_pattern ()); - ctx.bindings.clear (); + ctx.bindings.exit (); if (let.has_else_expr ()) visit (let.get_init_expr ()); @@ -220,9 +220,9 @@ Late::visit (AST::IdentifierPattern &identifier) // but values does not allow shadowing... since functions cannot shadow // do we insert functions in labels as well? - if (ctx.bindings.and_binded (identifier.get_ident ())) + if (ctx.bindings.peek ().is_and_bound (identifier.get_ident ())) { - if (ctx.bindings.get_source () == BindingSource::Param) + if (ctx.bindings.peek ().get_source () == BindingSource::Param) rust_error_at ( identifier.get_locus (), ErrorCode::E0415, "identifier %qs is bound more than once in the same parameter list", @@ -235,9 +235,9 @@ Late::visit (AST::IdentifierPattern &identifier) return; } - ctx.bindings.insert_ident (identifier.get_ident ()); + ctx.bindings.peek ().insert_ident (identifier.get_ident ()); - if (ctx.bindings.or_binded (identifier.get_ident ())) + if (ctx.bindings.peek ().is_or_bound (identifier.get_ident ())) { // FIXME: map usage instead std::ignore = ctx.values.insert_shadowable (identifier.get_ident (), @@ -255,14 +255,14 @@ Late::visit (AST::IdentifierPattern &identifier) void Late::visit (AST::AltPattern &pattern) { - ctx.bindings.push (Binding::Kind::Or); + ctx.bindings.peek ().push (Binding::Kind::Or); for (auto &alt : pattern.get_alts ()) { - ctx.bindings.push (Binding::Kind::Product); + ctx.bindings.peek ().push (Binding::Kind::Product); visit (alt); - ctx.b
[gcc r16-229] gccrs: Add binding context class
https://gcc.gnu.org/g:55e8094a286be16f138d78d618ab461d2340bec5 commit r16-229-g55e8094a286be16f138d78d618ab461d2340bec5 Author: Pierre-Emmanuel Patry Date: Sun Apr 6 17:09:42 2025 +0200 gccrs: Add binding context class We need to differentiate bindings types, so the same binding cannot be reused multiple time in a product binding. gcc/rust/ChangeLog: * resolve/rust-name-resolution-context.h (struct Binding): Add Binding struct to differentiate Or and Product bindings in patterns. (enum class): Add Binding kind. (class BindingContext): Add binding context with Binding stack. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/rust/resolve/rust-name-resolution-context.h | 81 + 1 file changed, 81 insertions(+) diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index 51c08efe3df6..d0736bcd1baa 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -156,6 +156,87 @@ public: NodeId id; }; +struct Binding +{ + enum class Kind + { +Product, +Or, + } kind; + + std::unordered_set set; + + Binding (Binding::Kind kind) : kind (kind) {} +}; + +enum class BindingSource +{ + Match, + Let, + For, + Param +}; + +class BindingContext +{ + // FIXME: Use std::vector> to handle nested patterns + std::vector bindings; + + BindingSource source; + + bool bind_test (Identifier ident, Binding::Kind kind) + { +for (auto &bind : bindings) + { + if (bind.set.find (ident) != bind.set.cend () && bind.kind == kind) + { + return true; + } + } +return false; + } + +public: + bool and_binded (Identifier ident) + { +return bind_test (ident, Binding::Kind::Product); + } + + bool or_binded (Identifier ident) + { +return bind_test (ident, Binding::Kind::Or); + } + + void insert_ident (Identifier ident) { bindings.back ().set.insert (ident); } + + void push (Binding::Kind kind) { bindings.push_back (Binding (kind)); } + + void new_binding (BindingSource source) + { +rust_assert (bindings.size () == 0); +this->source = source; +push (Binding::Kind::Product); + } + + void clear () + { +rust_assert (bindings.size () == 1); +bindings.clear (); + } + + void merge () + { +auto last_binding = bindings.back (); +bindings.pop_back (); +for (auto &value : last_binding.set) + { + bindings.back ().set.insert (value); + } + } + + BindingSource get_source () const { return source; } +}; + // Now our resolver, which keeps track of all the `ForeverStack`s we could want class NameResolutionContext {
[gcc r16-210] gccrs: Add test case to show ICE is fixed
https://gcc.gnu.org/g:de9284e6da43e7abd8fb7be0df3b03520dd0ebf0 commit r16-210-gde9284e6da43e7abd8fb7be0df3b03520dd0ebf0 Author: Philip Herron Date: Thu Apr 17 16:29:05 2025 +0100 gccrs: Add test case to show ICE is fixed Fixes Rust-GCC#3662 gcc/testsuite/ChangeLog: * rust/compile/issue-3662.rs: New test. Signed-off-by: Philip Herron Diff: --- gcc/testsuite/rust/compile/issue-3662.rs | 8 1 file changed, 8 insertions(+) diff --git a/gcc/testsuite/rust/compile/issue-3662.rs b/gcc/testsuite/rust/compile/issue-3662.rs new file mode 100644 index ..88baa2e25745 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3662.rs @@ -0,0 +1,8 @@ +pub fn rlib() { +let _ = ((-1 as i8) << 8 - 1) as f32; +let _ = 0u8 as char; +let _ = true > false; +let _ = true >= false; +let _ = true < false; +let _ = true >= false; +}
[gcc r16-217] gccrs: Fix ICE with empty generic arguments
https://gcc.gnu.org/g:efb94eb85d2382c795fa7b69feeb5425590519dc commit r16-217-gefb94eb85d2382c795fa7b69feeb5425590519dc Author: Philip Herron Date: Thu Apr 17 15:53:58 2025 +0100 gccrs: Fix ICE with empty generic arguments We have an assertion when accessing generic args if there are any which is really useful so this adds the missing guards for the case where they are specified but empty. Fixes Rust-GCC#3649 gcc/rust/ChangeLog: * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): add guard * expand/rust-expand-visitor.cc (ExpandVisitor::visit): add guard gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: nr2 is missing error for this * rust/compile/issue-3649.rs: New test. Signed-off-by: Philip Herron Diff: --- gcc/rust/ast/rust-ast-visitor.cc | 3 ++- gcc/rust/expand/rust-expand-visitor.cc | 3 ++- gcc/testsuite/rust/compile/issue-3649.rs | 2 ++ gcc/testsuite/rust/compile/nr2/exclude | 1 + 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index de01a6d3531e..61a3b8b4bf77 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -108,7 +108,8 @@ DefaultASTVisitor::visit (GenericArgsBinding &binding) void DefaultASTVisitor::visit (AST::TypePathSegmentGeneric &segment) { - visit (segment.get_generic_args ()); + if (segment.has_generic_args ()) +visit (segment.get_generic_args ()); } void diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc index d4db3137565e..42df5e1ee118 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -489,7 +489,8 @@ ExpandVisitor::visit (AST::PathInExpression &path) void ExpandVisitor::visit (AST::TypePathSegmentGeneric &segment) { - expand_generic_args (segment.get_generic_args ()); + if (segment.has_generic_args ()) +expand_generic_args (segment.get_generic_args ()); } void diff --git a/gcc/testsuite/rust/compile/issue-3649.rs b/gcc/testsuite/rust/compile/issue-3649.rs new file mode 100644 index ..b85b193312ef --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3649.rs @@ -0,0 +1,2 @@ +struct T(Box<>); +// { dg-error "could not resolve type path .Box. .E0412." "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index e5911b2a6ac0..12e63d884a38 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -22,4 +22,5 @@ issue-3568.rs issue-3663.rs issue-3671.rs issue-3652.rs +issue-3649.rs # please don't delete the trailing newline
[gcc r16-208] gccrs: Add gimple test for black box intrinsic
https://gcc.gnu.org/g:8b4bb5694cbe0cdfc64fcc8b2b3b7d4048836d1c commit r16-208-g8b4bb5694cbe0cdfc64fcc8b2b3b7d4048836d1c Author: Pierre-Emmanuel Patry Date: Thu Apr 17 18:28:52 2025 +0200 gccrs: Add gimple test for black box intrinsic gcc/testsuite/ChangeLog: * rust/compile/black_box.rs: New test. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/testsuite/rust/compile/black_box.rs | 28 1 file changed, 28 insertions(+) diff --git a/gcc/testsuite/rust/compile/black_box.rs b/gcc/testsuite/rust/compile/black_box.rs new file mode 100644 index ..80615af5b5d1 --- /dev/null +++ b/gcc/testsuite/rust/compile/black_box.rs @@ -0,0 +1,28 @@ +// { dg-options "-fdump-tree-gimple" } +#![feature(rustc_attrs)] + +#[lang = "sized"] +pub trait Sized {} + +#[rustc_builtin_macro] +macro_rules! llvm_asm { +() => {}; +} + +pub fn black_box(mut dummy: T) -> T { +unsafe { +// { dg-final { scan-tree-dump-times {memory} 1 gimple } } +llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile"); +} + +dummy +} + +fn my_function(a: i32) -> i32 { +a +} + +fn main() { +let dummy: i32 = 42; +let _ = black_box(my_function(dummy)); +}
[gcc r16-207] gccrs: Add execute test for black_box intrinsic
https://gcc.gnu.org/g:93c9f9af0aa3356a2a50bf920ad32be5b07f3d59 commit r16-207-g93c9f9af0aa3356a2a50bf920ad32be5b07f3d59 Author: Pierre-Emmanuel Patry Date: Thu Apr 17 17:53:15 2025 +0200 gccrs: Add execute test for black_box intrinsic gcc/testsuite/ChangeLog: * rust/execute/black_box.rs: New test. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/testsuite/rust/execute/black_box.rs | 30 ++ 1 file changed, 30 insertions(+) diff --git a/gcc/testsuite/rust/execute/black_box.rs b/gcc/testsuite/rust/execute/black_box.rs new file mode 100644 index ..7a9920eba947 --- /dev/null +++ b/gcc/testsuite/rust/execute/black_box.rs @@ -0,0 +1,30 @@ +/* { dg-output "Value is: 42\r*\n" } */ +#![feature(rustc_attrs)] + +extern "C" { +fn printf(s: *const i8, ...); +} + +#[lang = "sized"] +pub trait Sized {} + +#[rustc_builtin_macro] +macro_rules! llvm_asm { +() => {}; +} + +pub fn black_box(mut dummy: T) -> T { +unsafe { +llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile"); +} + +dummy +} + +fn main() { +let dummy: i32 = 42; +let result = black_box(dummy); +unsafe { +printf("Value is: %i\n\0" as *const str as *const i8, result); +} +}
[gcc r16-211] gccrs: nr2.0: Handle StructPatternFieldIdent
https://gcc.gnu.org/g:201d5ac8ff38d687a89ef86f3174d744b5296a34 commit r16-211-g201d5ac8ff38d687a89ef86f3174d744b5296a34 Author: Owen Avery Date: Thu Apr 17 14:02:45 2025 -0400 gccrs: nr2.0: Handle StructPatternFieldIdent gcc/rust/ChangeLog: * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Handle StructPatternFieldIdent. * resolve/rust-late-name-resolver-2.0.h (Late::visit): Likewise. gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove entry. Signed-off-by: Owen Avery Diff: --- gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 8 gcc/rust/resolve/rust-late-name-resolver-2.0.h | 1 + gcc/testsuite/rust/compile/nr2/exclude | 1 - 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index f743e1e03f34..cd81080ce157 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -172,6 +172,14 @@ Late::visit (AST::IdentifierPattern &identifier) identifier.get_node_id ()); } +void +Late::visit (AST::StructPatternFieldIdent &field) +{ + // We do want to ignore duplicated data because some situations rely on it. + std::ignore = ctx.values.insert_shadowable (field.get_identifier (), + field.get_node_id ()); +} + void Late::visit (AST::SelfParam ¶m) { diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h index 5703b152f7e7..2be932834d43 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -42,6 +42,7 @@ public: // TODO: Do we need this? // void visit (AST::Method &) override; void visit (AST::IdentifierPattern &) override; + void visit (AST::StructPatternFieldIdent &) override; void visit (AST::SelfParam &) override; // resolutions diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index 4772517c47e4..5c52a3cababa 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -16,7 +16,6 @@ derive_clone_enum3.rs derive-debug1.rs derive-default1.rs derive-eq-invalid.rs -derive-hash1.rs torture/alt_patterns1.rs torture/name_resolve1.rs issue-3568.rs
[gcc r16-214] gccrs: Add test case to show ice is fixed
https://gcc.gnu.org/g:519b34042539796a7a836d2f5304ff7c51211ee2 commit r16-214-g519b34042539796a7a836d2f5304ff7c51211ee2 Author: Philip Herron Date: Fri Apr 18 11:37:55 2025 +0100 gccrs: Add test case to show ice is fixed Fixes Rust-GCC#3652 gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: nr2 does not error on the T it should require Self::T * rust/compile/issue-3652.rs: New test. Signed-off-by: Philip Herron Diff: --- gcc/testsuite/rust/compile/issue-3652.rs | 7 +++ gcc/testsuite/rust/compile/nr2/exclude | 1 + 2 files changed, 8 insertions(+) diff --git a/gcc/testsuite/rust/compile/issue-3652.rs b/gcc/testsuite/rust/compile/issue-3652.rs new file mode 100644 index ..537ca9f881a2 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3652.rs @@ -0,0 +1,7 @@ +trait Foo { +type T; +fn foo() -> T<::T>; +// { dg-error "could not resolve type path .T. .E0412." "" { target *-*-* } .-1 } +} + +fn foo() {} diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index 5c52a3cababa..e5911b2a6ac0 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -21,4 +21,5 @@ torture/name_resolve1.rs issue-3568.rs issue-3663.rs issue-3671.rs +issue-3652.rs # please don't delete the trailing newline
[gcc r16-227] gccrs: Add equality operator for identifiers
https://gcc.gnu.org/g:12b3858d106fb3e80ae87b95897d4903af3c11cb commit r16-227-g12b3858d106fb3e80ae87b95897d4903af3c11cb Author: Pierre-Emmanuel Patry Date: Sun Apr 6 01:43:20 2025 +0200 gccrs: Add equality operator for identifiers gcc/rust/ChangeLog: * ast/rust-ast.h: Add equality operator. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/rust/ast/rust-ast.h | 5 + 1 file changed, 5 insertions(+) diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 55f178d782c3..94585dc13442 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -57,6 +57,11 @@ public: bool empty () const { return ident.empty (); } + bool operator== (const Identifier &other) const + { +return ident == other.ident; + } + private: std::string ident; location_t loc;
[gcc r16-218] gccrs: prealloc the initilizer vector
https://gcc.gnu.org/g:e186cea1c25456cfd8006311f60363913ba803c7 commit r16-218-ge186cea1c25456cfd8006311f60363913ba803c7 Author: Philip Herron Date: Thu Apr 17 16:19:35 2025 +0100 gccrs: prealloc the initilizer vector There are two cases when initilizing an array, this is the const context which means we need to build the array ctor, which means using lots of memory, its super inefficient because we are using a big wrapper over the GCC internals here but preallocating the vectors here causes a: terminate called after throwing an instance of 'std::bad_alloc' So this is a handy error condition to rely on for this senario. Fixes Rust-GCC#3713 Fixes Rust-GCC#3727 gcc/rust/ChangeLog: * backend/rust-compile-expr.cc (CompileExpr::array_copied_expr): prealloc the vector Signed-off-by: Philip Herron Diff: --- gcc/rust/backend/rust-compile-expr.cc | 4 1 file changed, 4 insertions(+) diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 141086fc0847..dd3420f9f2fa 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -1972,8 +1972,12 @@ CompileExpr::array_copied_expr (location_t expr_locus, if (ctx->const_context_p ()) { size_t idx = 0; + std::vector indexes; std::vector constructor; + + indexes.reserve (len); + constructor.reserve (len); for (unsigned HOST_WIDE_INT i = 0; i < len; i++) { constructor.push_back (translated_expr);
[gcc/ibm/heads/gcc-12-branch] (478 commits) ibm: Merge up to top of releases/gcc-12
The branch 'ibm/heads/gcc-12-branch' was updated to point to: 1d9871af38fe... ibm: Merge up to top of releases/gcc-12 It previously pointed to: 95d8973a6f8f... ibm: Merge up to top of releases/gcc-12 Diff: Summary of changes (added commits): --- 1d9871a... ibm: Merge up to top of releases/gcc-12 023bec1... Daily bump. (*) a4f7805... Daily bump. (*) 9b57816... Daily bump. (*) d419ea3... Avoid using POINTER_DIFF_EXPR for overlap checks [PR119399] (*) a895b98... vect: Enforce dr_with_seg_len::align precondition [PR116125 (*) 8eabfcb... Daily bump. (*) b7748c3... c++: templates, attributes, #pragma target [PR114772] (*) 8528052... Daily bump. (*) 42f0556... Fortran: fix issue with impure elemental subroutine and int (*) c94d07b... Daily bump. (*) 53650c9... Daily bump. (*) 3ea4b96... Fix compilation of server.cc on hpux. (*) 0701c8d... d: Fix ICE in dwarf2out_imported_module_or_decl, at dwarf2o (*) 9b03418... Daily bump. (*) 382798a... Daily bump. (*) 9fac6ee... Daily bump. (*) 2ea39e7... libstdc++: Qualify calls to debug mode helpers (*) d143630... libstdc++: Fix infinite loop in std::istream::ignore(n, del (*) 1bfcb24... libstdc++: Fix bogus -Wstringop-overflow in std::vector::in (*) d143338... libstdc++: Fix std::deque::insert(pos, first, last) undefin (*) b517d0c... Daily bump. (*) 75fc02d... testcase: Add testcase for already fixed PR [PR118476] (*) 8aff886... match: Reject non-ssa name/min invariants in gimple_extract (*) 9d0c2f7... phiopt: Fix value_replacement for middle bb having phi node (*) df76d7b... vec-lowering: Fix ABSU lowering [PR111285] (*) a5929ef... backprop: Fix deleting of a phi node [PR116922] (*) 5347b38... phiopt: Reset the number of iterations information of a loo (*) cab0305... libstdc++: Add dg-options "-std=gnu++20" to backported test (*) 6d8ee74... libstdc++: Fix get<0> constraint for lvalue ranges::subrang (*) c0d8051... libstdc++: Skip redundant assertions in std::array equality (*) 7b0f505... libstdc++: Skip redundant assertions in std::span construct (*) 9357f7e... libstdc++: Constrain std::vector default constructor [PR113 (*) 4cb91df... libstdc++: Specialize std::disable_sized_sentinel_for for s (*) 5f3811f... libstdc++: Add missing parts of LWG 3480 for directory iter (*) 4889dad... Daily bump. (*) 31d7e07... libstdc++: Document thread-safety for COW std::string [PR21 (*) d48c5ec... Daily bump. (*) ad66eca... Daily bump. (*) 6675cf3... rtl-optimization/119689 - compare-debug failure with LRA (*) 3232e15... [PR115568][LRA]: Use more strict output reload check in rem (*) 00210d1... Daily bump. (*) bdd4952... Daily bump. (*) e616244... Daily bump. (*) 21d644b... Daily bump. (*) 1a722dc... Daily bump. (*) 82bca9a... Daily bump. (*) 0097de8... Daily bump. (*) f9d954f... Daily bump. (*) b33dad2... Daily bump. (*) bfb1b0f... tree-optimization/114246 - invalid call argument from DSE (*) b444c30... middle-end/115641 - invalid address construction (*) f1989b5... tree-optimization/116481 - avoid building function_type[] (*) c62cbe7... tree-optimization/116850 - corrupt post-dom info (*) c5e4e76... tree-optimization/117119 - ICE with int128 IV in dataref an (*) 8eeaaec... tree-optimization/117574 - bougs niter lt-to-ne (*) 5509544... tree-optimization/117912 - bogus address equivalences for _ (*) 8eca273... tree-optimization/118717 - store commoning vs. abnormals (*) b65f4fe... Ada: Fix thinko in Eigensystem for complex Hermitian matric (*) d4d63be... Daily bump. (*) 3c4fbdb... Daily bump. (*) f387888... libstdc++: Teach optimizer that empty COW strings are empty (*) 8250987... libstdc++: Avoid aliasing violation in std::valarray [PR991 (*) 813ca3d... Daily bump. (*) 0c66b2f... aarch64: Use PAUTH instead of V8_3A in some places (*) 2b200f9... Daily bump. (*) 7680651... Daily bump. (*) ff21bb4... Daily bump. (*) 5e688db... Daily bump. (*) 4b83e7c... Daily bump. (*) 8204a72... Daily bump. (*) 7f18798... Daily bump. (*) 4b3c7e3... Daily bump. (*) fadc25e... Daily bump. (*) 35406a0... Daily bump. (*) bea6943... Daily bump. (*) 33c7976... Daily bump. (*) 2f76207... Daily bump. (*) 8b36160... Daily bump. (*) 6dba189... Daily bump. (*) a4259a0... Daily bump. (*) 446c1e3... Daily bump. (*) fcf59b2... Daily bump. (*) 1942377... Daily bump. (*) 901ed4c... Daily bump. (*) be4a99f... Daily bump. (*) 8d8eb53... d: Fix regression returning from function with invariants [ (*) 587b370... Fix folding of BIT_NOT_EXPR for POLY_INT_CST [PR118976] (*) 4f61ae0... aarch64: Fix folding of degenerate svwhilele case [PR117045 (*) 8643edb... aarch64: Fix caller saves of VNx2QI [PR116238] (*) dfc6b28... Daily bump. (*) ecdf944... Daily bump. (*) 11c933c... Daily bump. (*) c5588cb... Daily bump. (*) 149b38a... arm: Handle fixed PIC register in require_pic_register (PR (*) c96a7aa... Da
[gcc(refs/vendors/ibm/heads/gcc-12-branch)] ibm: Merge up to top of releases/gcc-12
https://gcc.gnu.org/g:1d9871af38fe935a4ca3e2d1f32c876270988d13 commit 1d9871af38fe935a4ca3e2d1f32c876270988d13 Merge: 95d8973a6f8f 023bec174fe6 Author: Peter Bergner Date: Mon Apr 28 11:49:24 2025 -0500 ibm: Merge up to top of releases/gcc-12 2025-04-28 Peter Bergner Merge up to releases/gcc-12 023bec174fe6acbd4da404d6c8f6b7ff96754e6d Diff: c++tools/ChangeLog |6 + c++tools/server.cc |2 + gcc/ChangeLog | 1220 gcc/ChangeLog.ibm |4 + gcc/DATESTAMP |2 +- gcc/ada/ChangeLog | 78 ++ gcc/ada/checks.adb | 10 +- gcc/ada/exp_aggr.adb | 21 +- gcc/ada/gnatvsn.ads|3 +- gcc/ada/libgnarl/s-taprop__dummy.adb | 11 +- gcc/ada/libgnat/a-ngcoar.adb | 42 +- gcc/ada/libgnat/a-ngrear.adb | 109 +- gcc/ada/sem_res.adb|2 +- gcc/ada/sem_util.adb |3 - gcc/ada/sem_util.ads |3 + gcc/ada/version.c |5 +- gcc/auto-profile.cc|4 +- gcc/cfgexpand.cc |9 + gcc/combine.cc | 15 +- gcc/common/config/i386/cpuinfo.h | 16 + gcc/common/config/i386/i386-common.cc |6 +- gcc/common/config/i386/i386-cpuinfo.h |2 + gcc/config.gcc | 14 +- gcc/config/aarch64/aarch64-c.cc|5 + gcc/config/aarch64/aarch64-sve-builtins-base.cc| 36 +- gcc/config/aarch64/aarch64-sve.md | 20 +- gcc/config/aarch64/aarch64.cc | 76 +- gcc/config/aarch64/aarch64.md | 12 +- gcc/config/alpha/alpha.md | 10 +- gcc/config/arm/arm.cc |5 +- gcc/config/arm/arm_mve.h |4 + gcc/config/arm/arm_mve_types.h |4 + gcc/config/arm/mve.md |2 +- gcc/config/avr/avr-dimode.md | 26 +- gcc/config/avr/avr.cc | 76 +- gcc/config/avr/avr.md |7 +- gcc/config/i386/avx512dqintrin.h | 16 +- gcc/config/i386/avx512fp16intrin.h |4 +- gcc/config/i386/avx512vlbwintrin.h |4 +- gcc/config/i386/avx512vlintrin.h |2 +- gcc/config/i386/constraints.md |2 +- gcc/config/i386/driver-i386.cc |5 + gcc/config/i386/i386-builtin.def | 24 +- gcc/config/i386/i386-c.cc |7 + gcc/config/i386/i386-expand.cc | 14 + gcc/config/i386/i386-options.cc| 12 +- gcc/config/i386/i386.cc| 85 +- gcc/config/i386/i386.h |7 +- gcc/config/i386/i386.md| 14 +- gcc/config/i386/sse.md | 469 +++- gcc/config/i386/x86-tune-costs.h | 155 ++- gcc/config/i386/x86-tune-sched.cc | 61 + gcc/config/i386/x86-tune.def | 31 +- gcc/config/i386/{znver4.md => zn4zn5.md} | 817 - gcc/config/pa/pa.cc|1 + gcc/config/pa/pa.md| 38 +- gcc/config/pa/pa32-regs.h |2 +- gcc/config/rs6000/amo.h|2 +- gcc/config/rs6000/rs6000-builtin.cc| 10 +- gcc/config/rs6000/rs6000-builtins.def |4 +- gcc/config/rs6000/rs6000-logue.cc | 47 +- gcc/config/rs6000/rs6000-p8swap.cc |8 +- gcc/config/rs6000/rs6000.cc| 17 +- gcc/config/rs6000/rs6000.h |2 + gcc/config/rs6000/rs6000.md|6 +- gcc/config/s390/3931.md|7 - gcc/config/s390/s390-protos.h |1 - gcc/config/s390/s390.cc| 99 +- gcc/config/s390/s390.md| 20 +- gcc/config/s390/vector.md | 81 +- gcc/config/sh/sh.cc| 12 +- gcc/cp/ChangeLog | 54 + gcc/cp/constexpr.cc|7 + gcc/cp/name-lookup.cc |5 +- gcc/cp/parser.cc
[gcc r16-242] MAINTAINERS: Add my gcc.gnu.org username
https://gcc.gnu.org/g:45d82eb7b7389a7c668db29bf2d5ec4ed2bc4da0 commit r16-242-g45d82eb7b7389a7c668db29bf2d5ec4ed2bc4da0 Author: Kwok Cheung Yeung Date: Mon Apr 28 19:27:59 2025 +0100 MAINTAINERS: Add my gcc.gnu.org username ChangeLog: * MAINTAINERS (kcy): Add gcc.gnu.org username. Diff: --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 6ff4770ed5dc..b1e7fadf1b8e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -897,7 +897,7 @@ Canqun Yang canqun Fei Yangfyang Jeffrey Yasskin jyasskin Joey Ye jye2 -Kwok Cheung Yeung - +Kwok Cheung Yeung kcy Jonathan Yong jyong <10wa...@gmail.com> Greta Yorsh gretay Kirill Yukhin kyukhin
[gcc r16-183] libstdc++: Fix mingw build by using _M_span [PR119970]
https://gcc.gnu.org/g:1be88e43f3e93e85bef9499de905fa72d8596e7d commit r16-183-g1be88e43f3e93e85bef9499de905fa72d8596e7d Author: Tomasz Kamiński Date: Mon Apr 28 08:53:59 2025 +0200 libstdc++: Fix mingw build by using _M_span [PR119970] The r16-142-g01e5ef3e8b9128 chagned return type of _Str_sink::view() to basic_string_view<_CharT>. The mutable access is provided by _M_span function, that is now used for mingw path. PR libstdc++/119970 libstdc++-v3/ChangeLog: * include/std/ostream (vprint_unicode) [_WIN32 && !__CYGWIN__]: Call _Str_sink::_M_span instead of view. * include/std/print (vprint_unicode) [_WIN32 && !__CYGWIN__]: Call _Str_sink::_M_span instead of view. Diff: --- libstdc++-v3/include/std/ostream | 2 +- libstdc++-v3/include/std/print | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream index 644e568e8829..3a0a0d35df1d 100644 --- a/libstdc++-v3/include/std/ostream +++ b/libstdc++-v3/include/std/ostream @@ -193,7 +193,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __format::_Str_sink __buf; std::vformat_to(__buf.out(), __os.getloc(), __fmt, __args); - auto __out = __buf.view(); + auto __out = __buf._M_span(); void* __open_terminal(streambuf*); error_code __write_to_terminal(void*, span); diff --git a/libstdc++-v3/include/std/print b/libstdc++-v3/include/std/print index ea1aaac43892..92dbe118fc31 100644 --- a/libstdc++-v3/include/std/print +++ b/libstdc++-v3/include/std/print @@ -73,7 +73,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #else __format::_Str_sink __buf; std::vformat_to(__buf.out(), __fmt, __args); -auto __out = __buf.view(); +auto __out = __buf._M_span(); void* __open_terminal(FILE*); error_code __write_to_terminal(void*, span);
[gcc r16-181] libstdc++: Implement missing allocator-aware constructors for unordered containers.
https://gcc.gnu.org/g:1ecd95ea1e0b36e289061262639460d6dc5fd209 commit r16-181-g1ecd95ea1e0b36e289061262639460d6dc5fd209 Author: Tomasz Kamiński Date: Tue Mar 18 16:10:48 2025 +0100 libstdc++: Implement missing allocator-aware constructors for unordered containers. This patch implements remainder of LWG2713 (after r15-8293-g64f5c854597759) by adding missing allocator aware version of unordered associative containers constructors accepting pair of iterators or initializer_list, and corresponding deduction guides. libstdc++-v3/ChangeLog: * include/bits/unordered_map.h (unordered_map): Define constructors accepting: (_InputIterator, _InputIterator, const allocator_type&), (initializer_list, const allocator_type&), (unordered_multimap): Likewise. * include/debug/unordered_map (unordered_map): Likewise. (unordered_multimap): Likewise. * include/bits/unordered_set.h (unordered_set): Define constructors and deduction guide accepting: (_InputIterator, _InputIterator, const allocator_type&), (initializer_list, const allocator_type&), (unordered_multiset): Likewise. * include/debug/unordered_set (unordered_set): Likewise. (unordered_multiset): Likewise. * testsuite/23_containers/unordered_map/cons/66055.cc: New tests. * testsuite/23_containers/unordered_map/cons/deduction.cc: New tests. * testsuite/23_containers/unordered_multimap/cons/66055.cc: New tests. * testsuite/23_containers/unordered_multimap/cons/deduction.cc: New tests. * testsuite/23_containers/unordered_multiset/cons/66055.cc: New tests. * testsuite/23_containers/unordered_multiset/cons/deduction.cc: New tests. * testsuite/23_containers/unordered_set/cons/66055.cc: New tests. * testsuite/23_containers/unordered_set/cons/deduction.cc: New tests. Reviewed-by: Jonathan Wakely Signed-off-by: Tomasz Kamiński Diff: --- libstdc++-v3/include/bits/unordered_map.h | 30 + libstdc++-v3/include/bits/unordered_set.h | 71 ++ libstdc++-v3/include/debug/unordered_map | 22 +++ libstdc++-v3/include/debug/unordered_set | 54 .../23_containers/unordered_map/cons/66055.cc | 11 ++-- .../23_containers/unordered_map/cons/deduction.cc | 28 + .../23_containers/unordered_multimap/cons/66055.cc | 10 +-- .../unordered_multimap/cons/deduction.cc | 34 +++ .../23_containers/unordered_multiset/cons/66055.cc | 10 +-- .../unordered_multiset/cons/deduction.cc | 28 + .../23_containers/unordered_set/cons/66055.cc | 10 +-- .../23_containers/unordered_set/cons/deduction.cc | 28 + 12 files changed, 320 insertions(+), 16 deletions(-) diff --git a/libstdc++-v3/include/bits/unordered_map.h b/libstdc++-v3/include/bits/unordered_map.h index 5bc58e849ffa..fc07ffc998ca 100644 --- a/libstdc++-v3/include/bits/unordered_map.h +++ b/libstdc++-v3/include/bits/unordered_map.h @@ -251,6 +251,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER : unordered_map(__n, __hf, key_equal(), __a) { } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2713. More missing allocator-extended constructors for unordered containers + template + unordered_map(_InputIterator __first, _InputIterator __last, + const allocator_type& __a) + : unordered_map(__first, __last, 0, hasher(), key_equal(), __a) + { } + template unordered_map(_InputIterator __first, _InputIterator __last, size_type __n, @@ -271,6 +279,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER : unordered_map(__l, __n, hasher(), key_equal(), __a) { } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2713. More missing allocator-extended constructors for unordered containers + unordered_map(initializer_list __l, + const allocator_type& __a) + : unordered_map(__l, 0, hasher(), key_equal(), __a) + { } + unordered_map(initializer_list __l, size_type __n, const hasher& __hf, const allocator_type& __a) @@ -1504,6 +1519,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER : unordered_multimap(__n, __hf, key_equal(), __a) { } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2713. More missing allocator-extended constructors for unordered containers + template + unordered_multimap(_InputIterator __first, _InputIterator __last, + const allocator_type& __a) + : unordered_multimap(__first, __last, 0, hasher(), key_equal(), __a) + { } + template unordered_multimap(_InputIterator __first, _InputIterator __last,
[gcc r16-182] libstdc++: Strip reference and cv-qual in range deduction guides for maps.
https://gcc.gnu.org/g:4794340cd257ece0d197f041812c34c5ac5d50a1 commit r16-182-g4794340cd257ece0d197f041812c34c5ac5d50a1 Author: Tomasz Kamiński Date: Thu Mar 20 09:02:03 2025 +0100 libstdc++: Strip reference and cv-qual in range deduction guides for maps. This implements part of LWG4223 that adjust the deduction guides for maps types (map, unordered_map, flat_map and non-unique equivalent) from "range" (std::from_range, iterator pair), such that referience and cv qualification are stripped from the element of the pair-like value_type. In combination with r15-8296-gd50171bc07006d, the LWG4223 is fully implemented now. libstdc++-v3/ChangeLog: * include/bits/ranges_base.h (__detail::__range_key_type): Replace remove_const_t with remove_cvref_t. (__detail::__range_mapped_type): Apply remove_cvref_t. * include/bits/stl_iterator.h: (__detail::__iter_key_t): Replace remove_const_t with __remove_cvref_t. (__detail::__iter_val_t): Apply __remove_cvref_t. * testsuite/23_containers/flat_map/1.cc: New tests. * testsuite/23_containers/flat_multimap/1.cc: New tests. * testsuite/23_containers/map/cons/deduction.cc: New tests. * testsuite/23_containers/map/cons/from_range.cc: New tests. * testsuite/23_containers/multimap/cons/deduction.cc: New tests. * testsuite/23_containers/multimap/cons/from_range.cc: New tests. * testsuite/23_containers/unordered_map/cons/deduction.cc: New tests. * testsuite/23_containers/unordered_map/cons/from_range.cc: New tests. * testsuite/23_containers/unordered_multimap/cons/deduction.cc: New tests. * testsuite/23_containers/unordered_multimap/cons/from_range.cc: New tests. Reviewed-by: Jonathan Wakely Signed-off-by: Tomasz Kamiński Diff: --- libstdc++-v3/include/bits/ranges_base.h| 4 +- libstdc++-v3/include/bits/stl_iterator.h | 11 ++-- libstdc++-v3/testsuite/23_containers/flat_map/1.cc | 21 +++ .../testsuite/23_containers/flat_multimap/1.cc | 21 +++ .../testsuite/23_containers/map/cons/deduction.cc | 46 +++ .../testsuite/23_containers/map/cons/from_range.cc | 8 +-- .../23_containers/multimap/cons/deduction.cc | 46 +++ .../23_containers/multimap/cons/from_range.cc | 8 +-- .../23_containers/unordered_map/cons/deduction.cc | 69 ++ .../23_containers/unordered_map/cons/from_range.cc | 10 ++-- .../unordered_multimap/cons/deduction.cc | 69 ++ .../unordered_multimap/cons/from_range.cc | 10 ++-- 12 files changed, 279 insertions(+), 44 deletions(-) diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index 488907da4466..dde164988569 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -1103,11 +1103,11 @@ namespace __detail // 4223. Deduction guides for maps are mishandling tuples and references template using __range_key_type - = remove_const_t>>; + = remove_cvref_t>>; template using __range_mapped_type - = tuple_element_t<1, ranges::range_value_t<_Range>>; + = remove_cvref_t>>; // The allocator's value_type for map-like containers. template diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index 9203a66b2ff0..bed72955d0c4 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -3086,8 +3086,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cpp_deduction_guides >= 201606 // These helper traits are used for deduction guides // of associative containers. + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4223. Deduction guides for maps are mishandling tuples and references template -using __iter_key_t = remove_const_t< +using __iter_key_t = __remove_cvref_t< #ifdef __glibcxx_tuple_like // >= C++23 tuple_element_t<0, typename iterator_traits<_InputIterator>::value_type>>; #else @@ -3095,11 +3098,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif template -using __iter_val_t +using __iter_val_t = __remove_cvref_t< #ifdef __glibcxx_tuple_like // >= C++23 - = tuple_element_t<1, typename iterator_traits<_InputIterator>::value_type>; + tuple_element_t<1, typename iterator_traits<_InputIterator>::value_type>>; #else - = typename iterator_traits<_InputIterator>::value_type::second_type; + typename iterator_traits<_InputIterator>::value_type::second_type>; #endif template diff --git a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc index 4fd33f616f78..a4e0d867c936 100644 --- a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc +++ b/libstdc++
[gcc r16-185] Remove non-SLP vector loop transform
https://gcc.gnu.org/g:da012141c28a71a9a5efd4acc53dd14066045643 commit r16-185-gda012141c28a71a9a5efd4acc53dd14066045643 Author: Richard Biener Date: Thu Jan 30 13:45:00 2025 +0100 Remove non-SLP vector loop transform The following removes the stmt-based vectorization loop transform code. This also removes some debug stmt handling (that looked incomplete) which is also handled during peeling, and special-casing some stmts that should be killed off early and not left to DCE. Moving of dump from vect_transform_loop_stmt to vect_transform_stmt is to avoid regressing a few testcases. * tree-vect-loop.cc (vect_loop_kill_debug_uses): Remove. (maybe_set_vectorized_backedge_value): Likewise. (vect_transform_loop_stmt): Likewise. Move dump printing to vect_transform_stmt. (vect_transform_loop): Remove loop over loop stmts transforming them, but retain some DCE code still necessary. * tree-vect-stmts.cc (vect_transform_stmt): Dump that we're vectorizing a stmt. Diff: --- gcc/tree-vect-loop.cc | 303 +++-- gcc/tree-vect-stmts.cc | 4 + 2 files changed, 19 insertions(+), 288 deletions(-) diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index 5ec164bd6026..6177d62a017e 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -9600,8 +9600,7 @@ vectorizable_phi (vec_info *, vector PHI node and the permute since those together compute the vectorized value of the scalar PHI. We do not yet have the backedge value to fill in there nor into the vec_perm. Those - are filled in maybe_set_vectorized_backedge_value and - vect_schedule_scc. + are filled in vect_schedule_scc. TODO: Since the scalar loop does not have a use of the recurrence outside of the loop the natural way to implement peeling via @@ -11792,45 +11791,6 @@ vectorizable_live_operation (vec_info *vinfo, stmt_vec_info stmt_info, return true; } -/* Kill any debug uses outside LOOP of SSA names defined in STMT_INFO. */ - -static void -vect_loop_kill_debug_uses (class loop *loop, stmt_vec_info stmt_info) -{ - ssa_op_iter op_iter; - imm_use_iterator imm_iter; - def_operand_p def_p; - gimple *ustmt; - - FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt_info->stmt, op_iter, SSA_OP_DEF) -{ - FOR_EACH_IMM_USE_STMT (ustmt, imm_iter, DEF_FROM_PTR (def_p)) - { - basic_block bb; - - if (!is_gimple_debug (ustmt)) - continue; - - bb = gimple_bb (ustmt); - - if (!flow_bb_inside_loop_p (loop, bb)) - { - if (gimple_debug_bind_p (ustmt)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "killing debug use\n"); - - gimple_debug_bind_reset_value (ustmt); - update_stmt (ustmt); - } - else - gcc_unreachable (); - } - } -} -} - /* Given loop represented by LOOP_VINFO, return true if computation of LOOP_VINFO_NITERS (= LOOP_VINFO_NITERSM1 + 1) doesn't overflow, false otherwise. */ @@ -12204,126 +12164,6 @@ scale_profile_for_vect_loop (class loop *loop, edge exit_e, unsigned vf, bool fl get_likely_max_loop_iterations_int (loop)); } -/* For a vectorized stmt DEF_STMT_INFO adjust all vectorized PHI - latch edge values originally defined by it. */ - -static void -maybe_set_vectorized_backedge_value (loop_vec_info loop_vinfo, -stmt_vec_info def_stmt_info) -{ - tree def = gimple_get_lhs (vect_orig_stmt (def_stmt_info)->stmt); - if (!def || TREE_CODE (def) != SSA_NAME) -return; - stmt_vec_info phi_info; - imm_use_iterator iter; - use_operand_p use_p; - FOR_EACH_IMM_USE_FAST (use_p, iter, def) -{ - gphi *phi = dyn_cast (USE_STMT (use_p)); - if (!phi) - continue; - if (!(gimple_bb (phi)->loop_father->header == gimple_bb (phi) - && (phi_info = loop_vinfo->lookup_stmt (phi)) - && STMT_VINFO_RELEVANT_P (phi_info))) - continue; - loop_p loop = gimple_bb (phi)->loop_father; - edge e = loop_latch_edge (loop); - if (PHI_ARG_DEF_FROM_EDGE (phi, e) != def) - continue; - - if (VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (phi_info)) - && STMT_VINFO_REDUC_TYPE (phi_info) != FOLD_LEFT_REDUCTION - && STMT_VINFO_REDUC_TYPE (phi_info) != EXTRACT_LAST_REDUCTION) - { - vec &phi_defs = STMT_VINFO_VEC_STMTS (phi_info); - vec &latch_defs = STMT_VINFO_VEC_STMTS (def_stmt_info); - gcc_assert (phi_defs.length () == latch_defs.length ()); - for (unsigned i = 0; i < phi_defs.length (); ++i) - add_phi_arg (as_a (phi_defs[i]), -gimple_get_lhs (latch_defs[i]), e,
[gcc r16-186] Prune non-SLP paths from vectorizer loop analysis
https://gcc.gnu.org/g:cfeee375eccfa6c7265f166b5ce70eb65b153e4c commit r16-186-gcfeee375eccfa6c7265f166b5ce70eb65b153e4c Author: Richard Biener Date: Thu Jan 30 15:03:04 2025 +0100 Prune non-SLP paths from vectorizer loop analysis The following prunes non-SLP iteration and the parts of non-SLP stmt analysis that is no longer necessary - we need to keep the parts that bail on stmts not covered by SLP discovery or that failed SLP discovery. This will only go away when a we can build a fully covering single-lane SLP graph to fall back to. * tree-vect-loop.cc (vect_analyze_loop_operations): Prune all actual analysis and only fail when we discover a not SLP covered stmt. (vect_analyze_loop_2): Remove path trying without SLP. Diff: --- gcc/tree-vect-loop.cc | 152 ++ 1 file changed, 43 insertions(+), 109 deletions(-) diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index 6177d62a017e..3de1ea646b40 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -2120,13 +2120,9 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo) int nbbs = loop->num_nodes; int i; stmt_vec_info stmt_info; - bool need_to_vectorize = false; - bool ok; DUMP_VECT_SCOPE ("vect_analyze_loop_operations"); - auto_vec cost_vec; - for (i = 0; i < nbbs; i++) { basic_block bb = bbs[i]; @@ -2135,7 +2131,6 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo) gsi_next (&si)) { gphi *phi = si.phi (); - ok = true; stmt_info = loop_vinfo->lookup_stmt (phi); if (dump_enabled_p ()) @@ -2144,6 +2139,10 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo) if (virtual_operand_p (gimple_phi_result (phi))) continue; + /* ??? All of the below unconditional FAILs should be in +done earlier after analyzing cycles, possibly when +determining stmt relevancy? */ + /* Inner-loop loop-closed exit phi in outer-loop vectorization (i.e., a phi in the tail of the outer-loop). */ if (! is_loop_header_bb_p (bb)) @@ -2180,9 +2179,7 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo) if ((STMT_VINFO_DEF_TYPE (stmt_info) == vect_internal_def || (STMT_VINFO_DEF_TYPE (stmt_info) == vect_double_reduction_def)) - && ! PURE_SLP_STMT (stmt_info) - && !vectorizable_lc_phi (loop_vinfo, - stmt_info, NULL, NULL)) + && ! PURE_SLP_STMT (stmt_info)) return opt_result::failure_at (phi, "unsupported phi\n"); } @@ -2200,36 +2197,8 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo) "not vectorized:" " scalar dependence cycle.\n"); - if (STMT_VINFO_RELEVANT_P (stmt_info)) -{ - need_to_vectorize = true; - if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def - && ! PURE_SLP_STMT (stmt_info)) - ok = vectorizable_induction (loop_vinfo, -stmt_info, NULL, NULL, -&cost_vec); - else if ((STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def - || (STMT_VINFO_DEF_TYPE (stmt_info) - == vect_double_reduction_def) - || STMT_VINFO_DEF_TYPE (stmt_info) == vect_nested_cycle) - && ! PURE_SLP_STMT (stmt_info)) - ok = vectorizable_reduction (loop_vinfo, -stmt_info, NULL, NULL, &cost_vec); - else if ((STMT_VINFO_DEF_TYPE (stmt_info) - == vect_first_order_recurrence) - && ! PURE_SLP_STMT (stmt_info)) - ok = vectorizable_recurr (loop_vinfo, stmt_info, NULL, NULL, - &cost_vec); -} - - /* SLP PHIs are tested by vect_slp_analyze_node_operations. */ - if (ok - && STMT_VINFO_LIVE_P (stmt_info) - && !PURE_SLP_STMT (stmt_info)) - ok = vectorizable_live_operation (loop_vinfo, stmt_info, NULL, NULL, - -1, false, &cost_vec); - - if (!ok) + if (STMT_VINFO_RELEVANT_P (stmt_info) + && ! PURE_SLP_STMT (stmt_info)) return opt_result::failure_at (phi, "not vectorized: relevant phi not " "supported: %G", @@ -2243,34 +2212,18 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo) if (!gimpl
[gcc r16-184] Remove --param vect-force-slp
https://gcc.gnu.org/g:1ae9e3c88ea2fdcb28f4bb58645efb52d8b33c7a commit r16-184-g1ae9e3c88ea2fdcb28f4bb58645efb52d8b33c7a Author: Richard Biener Date: Thu Jan 30 11:42:51 2025 +0100 Remove --param vect-force-slp The following removes the ability to switch back to non SLP-only operation of the vectorizer - a requirement to start cleaning out non-SLP paths without risk of regressing that case. * params.opt (--param=vect-force-slp): Remove. * doc/invoke.texi (--param=vect-force-slp): Likewise. * tree-vect-loop.cc (vect_analyze_loop_2): Assume param_vect_force_slp is 1. * tree-vect-stmts.cc (vect_analyze_stmt): Likewise. Diff: --- gcc/doc/invoke.texi| 3 --- gcc/params.opt | 4 gcc/tree-vect-loop.cc | 2 +- gcc/tree-vect-stmts.cc | 2 +- 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index a0f60e736e18..5b1861815de0 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -17225,9 +17225,6 @@ this parameter. The default value of this parameter is 50. @item vect-induction-float Enable loop vectorization of floating point inductions. -@item vect-force-slp -Force the use of SLP when vectorizing, fail if not possible. - @item vrp-block-limit Maximum number of basic blocks before VRP switches to a lower memory algorithm. diff --git a/gcc/params.opt b/gcc/params.opt index ef19051286be..1f0abeccc4b9 100644 --- a/gcc/params.opt +++ b/gcc/params.opt @@ -1253,10 +1253,6 @@ The maximum factor which the loop vectorizer applies to the cost of statements i Common Joined UInteger Var(param_vect_induction_float) Init(1) IntegerRange(0, 1) Param Optimization Enable loop vectorization of floating point inductions. --param=vect-force-slp= -Common Joined UInteger Var(param_vect_force_slp) Init(1) IntegerRange(0, 1) Param Optimization -Force the use of SLP when vectorizing, fail if not possible. - -param=vrp-block-limit= Common Joined UInteger Var(param_vrp_block_limit) Init(15) Optimization Param Maximum number of basic blocks before VRP switches to a fast model with less memory requirements. diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index 1c9e9b040d01..5ec164bd6026 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -2934,7 +2934,7 @@ start_over: /* When we arrive here with SLP disabled and we are supposed to use SLP for everything fail vectorization. */ - if (!slp && param_vect_force_slp) + if (!slp) return opt_result::failure_at (vect_location, "may need non-SLP handling\n"); diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index 5af1973734e2..61456b1f3b70 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -14022,7 +14022,7 @@ vect_analyze_stmt (vec_info *vinfo, /* When we arrive here with a non-SLP statement and we are supposed to use SLP for everything fail vectorization. */ - if (!node && param_vect_force_slp) + if (!node) return opt_result::failure_at (stmt_info->stmt, "needs non-SLP handling\n");
[gcc r16-188] middle-end/60779 - LTO vs. -fcx-fortran-rules and -fcx-limited-range
https://gcc.gnu.org/g:e543eaa671d40868575385360d13ef37d87fb2a0 commit r16-188-ge543eaa671d40868575385360d13ef37d87fb2a0 Author: Richard Biener Date: Tue Feb 18 12:52:34 2025 +0100 middle-end/60779 - LTO vs. -fcx-fortran-rules and -fcx-limited-range The following changes how flag_complex_method is managed towards being able to record that in the optimization set so we can stream and restore it per function. Currently -fcx-fortran-rules and -fcx-limited-range are separate recorded options but saving/restoring does not restore flag_complex_method which is later used in the middle-end. The solution is to make -fcx-fortran-rules and -fcx-limited-range aliases of a new -fcx-method= switch that represents flag_complex_method directly so we can save and restore it. PR middle-end/60779 * common.opt (fcx-method=): New, map to flag_complex_method. (Enum complex_method): New. (fcx-limited-range): Alias to -fcx-method=limited-range. (fcx-fortran-rules): Alias to -fcx-medhot=fortran. * ipa-inline-transform.cc (inline_call): Check flag_complex_method. * ipa-inline.cc (can_inline_edge_by_limits_p): Likewise. * opts.cc (finish_options): Adjust. (set_fast_math_flags): Likewise. * doc/invoke.texi (fcx-method=): Document. * gcc.dg/lto/pr60779_0.c: New testcase. * gcc.dg/lto/pr60779_1.c: Likewise. Diff: --- gcc/common.opt | 28 gcc/doc/invoke.texi | 14 ++ gcc/ipa-inline-transform.cc | 8 gcc/ipa-inline.cc| 2 +- gcc/opts.cc | 16 gcc/testsuite/gcc.dg/lto/pr60779_0.c | 21 + gcc/testsuite/gcc.dg/lto/pr60779_1.c | 6 ++ 7 files changed, 66 insertions(+), 29 deletions(-) diff --git a/gcc/common.opt b/gcc/common.opt index d10a6b7e533a..3edc5907ec85 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -53,12 +53,6 @@ bool in_lto_p = false Variable enum incremental_link flag_incremental_link = INCREMENTAL_LINK_NONE -; 0 means straightforward implementation of complex divide acceptable. -; 1 means wide ranges of inputs must work for complex divide. -; 2 means C99-like requirements for complex multiply and divide. -Variable -int flag_complex_method = 1 - Variable int flag_default_complex_method = 1 @@ -1315,12 +1309,30 @@ fcse-skip-blocks Common Ignore Does nothing. Preserved for backward compatibility. +fcx-method= +Common Joined RejectNegative Enum(complex_method) Var(flag_complex_method) Optimization SetByCombined + +Enum +Name(complex_method) Type(int) + +; straightforward implementation of complex divide acceptable. +EnumValue +Enum(complex_method) String(limited-range) Value(0) + +; wide ranges of inputs must work for complex divide. +EnumValue +Enum(complex_method) String(fortran) Value(1) + +; C99-like requirements for complex multiply and divide. +EnumValue +Enum(complex_method) String(stdc) Value(2) + fcx-limited-range -Common Var(flag_cx_limited_range) Optimization SetByCombined +Common Alias(fcx-method=,limited-range,stdc) Omit range reduction step when performing complex division. fcx-fortran-rules -Common Var(flag_cx_fortran_rules) Optimization +Common Alias(fcx-method=,fortran,stdc) Complex multiplication and division follow Fortran rules. fdata-sections diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 5b1861815de0..7fcf7dee4977 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -578,7 +578,7 @@ Objective-C and Objective-C++ Dialects}. -ffold-mem-offsets -fcompare-elim -fcprop-registers -fcrossjumping -fcse-follow-jumps -fcse-skip-blocks -fcx-fortran-rules --fcx-limited-range +-fcx-limited-range -fcx-method -fdata-sections -fdce -fdelayed-branch -fdelete-null-pointer-checks -fdevirtualize -fdevirtualize-speculatively -fdevirtualize-at-ltrans -fdse @@ -15603,8 +15603,7 @@ When enabled, this option states that a range reduction step is not needed when performing complex division. Also, there is no checking whether the result of a complex multiplication or division is @code{NaN + I*NaN}, with an attempt to rescue the situation in that case. The -default is @option{-fno-cx-limited-range}, but is enabled by -@option{-ffast-math}. +option is enabled by @option{-ffast-math}. This option controls the default setting of the ISO C99 @code{CX_LIMITED_RANGE} pragma. Nevertheless, the option applies to @@ -15617,7 +15616,14 @@ reduction is done as part of complex division, but there is no checking whether the result of a complex multiplication or division is @code{NaN + I*NaN}, with an attempt to rescue the situation in that case. -The default is @option{-fno-cx-fortran-rules}. +@opindex fcx-method +@item -fcx-method=@var{method} +Complex multiplication and divisio
[gcc r16-187] middle-end/116083 - vectorizer slowness
https://gcc.gnu.org/g:b30424f43522171e8ffe587e0df0ce3627c88f6c commit r16-187-gb30424f43522171e8ffe587e0df0ce3627c88f6c Author: Richard Biener Date: Tue Dec 3 14:21:47 2024 +0100 middle-end/116083 - vectorizer slowness Turns out SLP discovery can end up doing a lot of vector type builds from scalar types. Those are all ultimatively cached but end up built and layouted first. The latter is particularly expensive because it does tree node arithmetic to compute TYPE_SIZE and TYPE_SIZE_UNIT. The following replaces this with the appropriate poly-int arithmetic which speeds up the testcase by 50%. PR middle-end/116083 * stor-layout.cc (layout_type): Compute TYPE_SIZE and TYPE_SIZE_UNIT for vector types from the component mode sizes. Diff: --- gcc/stor-layout.cc | 23 ++- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/gcc/stor-layout.cc b/gcc/stor-layout.cc index 18b5af56124d..12071c96ca79 100644 --- a/gcc/stor-layout.cc +++ b/gcc/stor-layout.cc @@ -2591,16 +2591,21 @@ layout_type (tree type) /* Several boolean vector elements may fit in a single unit. */ if (VECTOR_BOOLEAN_TYPE_P (type) && type->type_common.mode != BLKmode) - TYPE_SIZE_UNIT (type) - = size_int (GET_MODE_SIZE (type->type_common.mode)); + { + TYPE_SIZE_UNIT (type) + = size_int (GET_MODE_SIZE (type->type_common.mode)); + TYPE_SIZE (type) + = bitsize_int (GET_MODE_BITSIZE (type->type_common.mode)); + } else - TYPE_SIZE_UNIT (type) = int_const_binop (MULT_EXPR, - TYPE_SIZE_UNIT (innertype), - size_int (nunits)); - TYPE_SIZE (type) = int_const_binop - (MULT_EXPR, - bits_from_bytes (TYPE_SIZE_UNIT (type)), - bitsize_int (BITS_PER_UNIT)); + { + TYPE_SIZE_UNIT (type) + = size_int (GET_MODE_SIZE (SCALAR_TYPE_MODE (innertype)) + * nunits); + TYPE_SIZE (type) + = bitsize_int (GET_MODE_BITSIZE (SCALAR_TYPE_MODE (innertype)) +* nunits); + } /* For vector types, we do not default to the mode's alignment. Instead, query a target hook, defaulting to natural alignment.
[gcc r16-193] ipa/119973 - IPA PTA issue with global initializers
https://gcc.gnu.org/g:7a16ef443b13fff9537baa533597836c57131262 commit r16-193-g7a16ef443b13fff9537baa533597836c57131262 Author: Richard Biener Date: Mon Apr 28 11:15:53 2025 +0200 ipa/119973 - IPA PTA issue with global initializers For global initializers with IPA PTA we initialize them from the IPA reference data but that lacks references to the constant pool. The following conservatively considers the whole initializer. PR ipa/119973 * tree-ssa-structalias.cc (create_variable_info_for): Build constraints from DECL_INITIAL directly rather than the IPA reference list which is incomplete. * gcc.dg/torture/pr119973.c: New testcase. Diff: --- gcc/testsuite/gcc.dg/torture/pr119973.c | 39 + gcc/tree-ssa-structalias.cc | 10 - 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/gcc/testsuite/gcc.dg/torture/pr119973.c b/gcc/testsuite/gcc.dg/torture/pr119973.c new file mode 100644 index ..a9661a3111ae --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr119973.c @@ -0,0 +1,39 @@ +/* { dg-do run } */ +/* { dg-additional-options "-fipa-pta" } */ + +static int +is_valid_domain_name (const char *string) +{ + const char *s; + + for (s=string; *s; s++) +if (*s == '.') + { +if (string == s) + return 0; + } + + return !!*string; +} + +int +main (void) +{ + static struct + { +const char *name; +int valid; + } testtbl[] = +{ + { ".", 0 }, + { nullptr, 0 } +}; + int idx; + + for (idx=0; testtbl[idx].name; idx++) +{ + if (is_valid_domain_name (testtbl[idx].name) != testtbl[idx].valid) +__builtin_abort (); +} + return 0; +} diff --git a/gcc/tree-ssa-structalias.cc b/gcc/tree-ssa-structalias.cc index d9356a82ad12..f79b54284c64 100644 --- a/gcc/tree-ssa-structalias.cc +++ b/gcc/tree-ssa-structalias.cc @@ -6529,18 +6529,18 @@ create_variable_info_for (tree decl, const char *name, bool add_id) if (!vnode->all_refs_explicit_p ()) make_copy_constraint (vi, nonlocal_id); - /* If this is a global variable with an initializer and we are in -IPA mode generate constraints for it. */ - ipa_ref *ref; - for (unsigned idx = 0; vnode->iterate_reference (idx, ref); ++idx) + /* While we can in theory walk references for the varpool +node that does not cover zero-initialization or references +to the constant pool. */ + if (DECL_INITIAL (decl)) { auto_vec rhsc; struct constraint_expr lhs, *rhsp; unsigned i; - get_constraint_for_address_of (ref->referred->decl, &rhsc); lhs.var = vi->id; lhs.offset = 0; lhs.type = SCALAR; + get_constraint_for (DECL_INITIAL (decl), &rhsc); FOR_EACH_VEC_ELT (rhsc, i, rhsp) process_constraint (new_constraint (lhs, *rhsp)); /* If this is a variable that escapes from the unit
[gcc r16-194] x86: Properly find the maximum stack slot alignment
https://gcc.gnu.org/g:b9ea3b2ef98048f93b02fcd6ff51777bce1676c2 commit r16-194-gb9ea3b2ef98048f93b02fcd6ff51777bce1676c2 Author: H.J. Lu Date: Tue Mar 14 11:41:51 2023 -0700 x86: Properly find the maximum stack slot alignment Don't assume that stack slots can only be accessed by stack or frame registers. We first find all registers defined by stack or frame registers. Then check memory accesses by such registers, including stack and frame registers. gcc/ PR target/109780 PR target/109093 * config/i386/i386.cc (stack_access_data): New. (ix86_update_stack_alignment): Likewise. (ix86_find_all_reg_use_1): Likewise. (ix86_find_all_reg_use): Likewise. (ix86_find_max_used_stack_alignment): Also check memory accesses from registers defined by stack or frame registers. gcc/testsuite/ PR target/109780 PR target/109093 * g++.target/i386/pr109780-1.C: New test. * gcc.target/i386/pr109093-1.c: Likewise. * gcc.target/i386/pr109780-1.c: Likewise. * gcc.target/i386/pr109780-2.c: Likewise. * gcc.target/i386/pr109780-3.c: Likewise. Signed-off-by: H.J. Lu Co-Authored-By: Uros Bizjak Diff: --- gcc/config/i386/i386.cc| 195 + gcc/testsuite/g++.target/i386/pr109780-1.C | 72 +++ gcc/testsuite/gcc.target/i386/pr109093-1.c | 33 + gcc/testsuite/gcc.target/i386/pr109780-1.c | 14 +++ gcc/testsuite/gcc.target/i386/pr109780-2.c | 21 gcc/testsuite/gcc.target/i386/pr109780-3.c | 46 +++ 6 files changed, 360 insertions(+), 21 deletions(-) diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 3171d6e0ad45..dd0762421777 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -8473,6 +8473,123 @@ output_probe_stack_range (rtx reg, rtx end) return ""; } +/* Data passed to ix86_update_stack_alignment. */ +struct stack_access_data +{ + /* The stack access register. */ + const_rtx reg; + /* Pointer to stack alignment. */ + unsigned int *stack_alignment; +}; + +/* Update the maximum stack slot alignment from memory alignment in PAT. */ + +static void +ix86_update_stack_alignment (rtx, const_rtx pat, void *data) +{ + /* This insn may reference stack slot. Update the maximum stack slot + alignment if the memory is referenced by the stack access register. */ + stack_access_data *p = (stack_access_data *) data; + + subrtx_iterator::array_type array; + FOR_EACH_SUBRTX (iter, array, pat, ALL) +{ + auto op = *iter; + if (MEM_P (op) && reg_mentioned_p (p->reg, op)) + { + unsigned int alignment = MEM_ALIGN (op); + + if (alignment > *p->stack_alignment) + *p->stack_alignment = alignment; + break; + } +} +} + +/* Helper function for ix86_find_all_reg_uses. */ + +static void +ix86_find_all_reg_uses_1 (HARD_REG_SET ®set, + rtx set, unsigned int regno, + auto_bitmap &worklist) +{ + rtx dest = SET_DEST (set); + + if (!REG_P (dest)) +return; + + /* Reject non-Pmode modes. */ + if (GET_MODE (dest) != Pmode) +return; + + unsigned int dst_regno = REGNO (dest); + + if (TEST_HARD_REG_BIT (regset, dst_regno)) +return; + + const_rtx src = SET_SRC (set); + + subrtx_iterator::array_type array; + FOR_EACH_SUBRTX (iter, array, src, ALL) +{ + auto op = *iter; + + if (MEM_P (op)) + iter.skip_subrtxes (); + + if (REG_P (op) && REGNO (op) == regno) + { + /* Add this register to register set. */ + add_to_hard_reg_set (®set, Pmode, dst_regno); + bitmap_set_bit (worklist, dst_regno); + break; + } +} +} + +/* Find all registers defined with register REGNO. */ + +static void +ix86_find_all_reg_uses (HARD_REG_SET ®set, + unsigned int regno, auto_bitmap &worklist) +{ + for (df_ref ref = DF_REG_USE_CHAIN (regno); + ref != NULL; + ref = DF_REF_NEXT_REG (ref)) +{ + if (DF_REF_IS_ARTIFICIAL (ref)) + continue; + + rtx_insn *insn = DF_REF_INSN (ref); + + if (!NONJUMP_INSN_P (insn)) + continue; + + unsigned int ref_regno = DF_REF_REGNO (ref); + + rtx set = single_set (insn); + if (set) + { + ix86_find_all_reg_uses_1 (regset, set, + ref_regno, worklist); + continue; + } + + rtx pat = PATTERN (insn); + if (GET_CODE (pat) != PARALLEL) + continue; + + for (int i = 0; i < XVECLEN (pat, 0); i++) + { + rtx exp = XVECEXP (pat, 0, i); + + if (GET_CODE (exp) == SET) + ix86_find_all_reg_uses_1 (regset, exp, + ref_regno, worklist); + } +} +} + /* Set stack_frame_required to fals
[gcc r16-195] simplify-rtx: Split out native_decode_int
https://gcc.gnu.org/g:ef32bd8c866a1b8a97f627fad44a42f29757c816 commit r16-195-gef32bd8c866a1b8a97f627fad44a42f29757c816 Author: Richard Sandiford Date: Mon Apr 28 14:40:09 2025 +0100 simplify-rtx: Split out native_decode_int native_decode_rtx handles integer modes by building up a wide_int and then converting it to an rtx. This patch splits out the wide_int part, so that callers who don't want an rtx can avoid creating garbage rtl. gcc/ * rtl.h (native_decode_int): Declare. * simplify-rtx.cc (native_decode_int): New function, split out from... (native_decode_rtx): ...here. Diff: --- gcc/rtl.h | 2 ++ gcc/simplify-rtx.cc | 38 +- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/gcc/rtl.h b/gcc/rtl.h index 3b676c468805..cc25aed1f494 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2443,6 +2443,8 @@ extern void get_full_rtx_cost (rtx, machine_mode, enum rtx_code, int, struct full_rtx_costs *); extern bool native_encode_rtx (machine_mode, rtx, vec &, unsigned int, unsigned int); +extern wide_int native_decode_int (const vec &, unsigned int, + unsigned int, unsigned int); extern rtx native_decode_rtx (machine_mode, const vec &, unsigned int); extern rtx native_decode_vector_rtx (machine_mode, const vec &, diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc index 06b52ca80037..d9aa0493a186 100644 --- a/gcc/simplify-rtx.cc +++ b/gcc/simplify-rtx.cc @@ -7713,6 +7713,28 @@ native_decode_vector_rtx (machine_mode mode, const vec &bytes, return builder.build (); } +/* Extract a PRECISION-bit integer from bytes [FIRST_BYTE, FIRST_BYTE + SIZE) + of target memory image BYTES. */ + +wide_int +native_decode_int (const vec &bytes, unsigned int first_byte, + unsigned int size, unsigned int precision) +{ + /* Pull the bytes msb first, so that we can use simple + shift-and-insert wide_int operations. */ + wide_int result (wi::zero (precision)); + for (unsigned int i = 0; i < size; ++i) +{ + unsigned int lsb = (size - i - 1) * BITS_PER_UNIT; + /* Always constant because the inputs are. */ + unsigned int subbyte + = subreg_size_offset_from_lsb (1, size, lsb).to_constant (); + result <<= BITS_PER_UNIT; + result |= bytes[first_byte + subbyte]; +} + return result; +} + /* Read an rtx of mode MODE from the target memory image given by BYTES, starting at byte FIRST_BYTE. Each element of BYTES contains BITS_PER_UNIT bits and the bytes are in target memory order. The image has enough @@ -7738,19 +7760,9 @@ native_decode_rtx (machine_mode mode, const vec &bytes, if (is_a (mode, &imode) && GET_MODE_PRECISION (imode) <= MAX_BITSIZE_MODE_ANY_INT) { - /* Pull the bytes msb first, so that we can use simple -shift-and-insert wide_int operations. */ - unsigned int size = GET_MODE_SIZE (imode); - wide_int result (wi::zero (GET_MODE_PRECISION (imode))); - for (unsigned int i = 0; i < size; ++i) - { - unsigned int lsb = (size - i - 1) * BITS_PER_UNIT; - /* Always constant because the inputs are. */ - unsigned int subbyte - = subreg_size_offset_from_lsb (1, size, lsb).to_constant (); - result <<= BITS_PER_UNIT; - result |= bytes[first_byte + subbyte]; - } + auto result = native_decode_int (bytes, first_byte, + GET_MODE_SIZE (imode), + GET_MODE_PRECISION (imode)); return immed_wide_int_const (result, imode); }
[gcc r16-249] Add a Relation iterator to the relation oracle.
https://gcc.gnu.org/g:8d0ec97fc6629f2d2bac00e1926a9aea9ef81a0c commit r16-249-g8d0ec97fc6629f2d2bac00e1926a9aea9ef81a0c Author: Andrew MacLeod Date: Mon Feb 10 16:14:17 2025 -0500 Add a Relation iterator to the relation oracle. This patch adds a relation iterator to query the oracle to list either all the relations on exit to a block, or just ones involving a specified SSA_NAME. The oracle then uses this iterator internally as well. * value-relation.cc (value_relation::swap): New. (value_relation::negate): Remove. (dom_oracle::next_relation): New. (block_relation_iterator::block_relation_iterator): New. (block_relation_iterator::get_next_relation): New. (dom_oracle::dump): Use iterator. * value-relation.h (relation_oracle::next_relation): New. (dom_oracle::next_relation): New prototype. (class block_relation_iterator): New. (FOR_EACH_RELATION_BB): New. (FOR_EACH_RELATION_NAME): New. Diff: --- gcc/value-relation.cc | 90 +++ gcc/value-relation.h | 35 ++-- 2 files changed, 117 insertions(+), 8 deletions(-) diff --git a/gcc/value-relation.cc b/gcc/value-relation.cc index 08449b72d9a9..c7ced445ad76 100644 --- a/gcc/value-relation.cc +++ b/gcc/value-relation.cc @@ -780,15 +780,20 @@ equiv_oracle::dump (FILE *f) const // -- -// Negate the current relation. + +// Adjust the relation by Swapping the operands and relation. void -value_relation::negate () +value_relation::swap () { - related = relation_negate (related); + related = relation_swap (related); + tree tmp = name1; + name1 = name2; + name2 = tmp; } // Perform an intersection between 2 relations. *this &&= p. +// Return false if the relations cannot be intersected. bool value_relation::intersect (value_relation &p) @@ -951,6 +956,79 @@ public: relation_chain *m_next; }; +// Given relation record PTR in block BB, return the next relation in the +// list. If PTR is NULL, retreive the first relation in BB. +// If NAME is sprecified, return only relations which include NAME. +// Return NULL when there are no relations left. + +relation_chain * +dom_oracle::next_relation (basic_block bb, relation_chain *ptr, + tree name) const +{ + relation_chain *p; + // No value_relation pointer is used to intialize the iterator. + if (!ptr) +{ + int bbi = bb->index; + if (bbi >= (int)m_relations.length()) + return NULL; + else + p = m_relations[bbi].m_head; +} + else +p = ptr->m_next; + + if (name) +for ( ; p; p = p->m_next) + if (p->op1 () == name || p->op2 () == name) + break; + return p; +} + +// Instatiate a block relation iterator to iterate over the relations +// on exit from block BB in ORACLE. Limit this to relations involving NAME +// if specified. Return the first such relation in VR if there is one. + +block_relation_iterator::block_relation_iterator (const relation_oracle *oracle, + basic_block bb, + value_relation &vr, + tree name) +{ + m_oracle = oracle; + m_bb = bb; + m_name = name; + m_ptr = oracle->next_relation (bb, NULL, m_name); + if (m_ptr) +{ + m_done = false; + vr = *m_ptr; +} + else +m_done = true; +} + +// Retreive the next relation from the iterator and return it in VR. + +void +block_relation_iterator::get_next_relation (value_relation &vr) +{ + m_ptr = m_oracle->next_relation (m_bb, m_ptr, m_name); + if (m_ptr) +{ + vr = *m_ptr; + if (m_name) + { + if (vr.op1 () != m_name) + { + gcc_checking_assert (vr.op2 () == m_name); + vr.swap (); + } + } +} + else +m_done = true; +} + // // Find the relation between any ssa_name in B1 and any name in B2 in LIST. @@ -1441,11 +1519,11 @@ dom_oracle::dump (FILE *f, basic_block bb) const if (!m_relations[bb->index].m_names) return; - relation_chain *ptr = m_relations[bb->index].m_head; - for (; ptr; ptr = ptr->m_next) + value_relation vr; + FOR_EACH_RELATION_BB (this, bb, vr) { fprintf (f, "Relational : "); - ptr->dump (f); + vr.dump (f); fprintf (f, "\n"); } } diff --git a/gcc/value-relation.h b/gcc/value-relation.h index 23cfb41c6357..1081877ccca7 100644 --- a/gcc/value-relation.h +++ b/gcc/value-relation.h @@ -114,6 +114,11 @@ public: void debug () const; protected: friend class equiv_relation_iterator; + friend class block_relation_iterator; + virtual class relation_chain *next_relation (basic_block, +
[gcc r16-247] Do not overwrite relation in range_of_range_op.
https://gcc.gnu.org/g:b89c6f801be1c1d94833aeda75570ba4892cf261 commit r16-247-gb89c6f801be1c1d94833aeda75570ba4892cf261 Author: Andrew MacLeod Date: Tue Apr 22 13:52:45 2025 -0400 Do not overwrite relation in range_of_range_op. when registering reltions between the lhs and op1/op2, the relation between op1 and op2 is being overwritten by the result. This could result in either an incorrect relation being registered between lhs and op2, or a correct relation not being recognized. * gimple-range-fold.cc (fold_using_range::range_of_range_op): Use a new local variable for intermediate relation results. Diff: --- gcc/gimple-range-fold.cc | 14 -- 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index 3bb24d58940f..aed5c7dc21eb 100644 --- a/gcc/gimple-range-fold.cc +++ b/gcc/gimple-range-fold.cc @@ -759,15 +759,17 @@ fold_using_range::range_of_range_op (vrange &r, } if (gimple_range_ssa_p (op1)) { - rel = handler.lhs_op1_relation (r, range1, range2, rel); - if (rel != VREL_VARYING) - src.register_relation (s, rel, lhs, op1); + relation_kind rel2 = handler.lhs_op1_relation (r, range1, +range2, rel); + if (rel2 != VREL_VARYING) + src.register_relation (s, rel2, lhs, op1); } if (gimple_range_ssa_p (op2)) { - rel = handler.lhs_op2_relation (r, range1, range2, rel); - if (rel != VREL_VARYING) - src.register_relation (s, rel, lhs, op2); + relation_kind rel2 = handler.lhs_op2_relation (r, range1, +range2, rel); + if (rel2 != VREL_VARYING) + src.register_relation (s, rel2, lhs, op2); } } // Check for an existing BB, as we maybe asked to fold an
[gcc r16-258] analyzer: convert various enums to "enum class"
https://gcc.gnu.org/g:978e9dfc0a1331ba06763a95b44dacf7f0e83613 commit r16-258-g978e9dfc0a1331ba06763a95b44dacf7f0e83613 Author: David Malcolm Date: Mon Apr 28 18:21:21 2025 -0400 analyzer: convert various enums to "enum class" Modernization; no functional change intended. gcc/analyzer/ChangeLog: * access-diagram.cc: Convert enum access_direction to "enum class". * bounds-checking.cc: Likewise. * checker-event.cc: Convert enum event_kind to "enum class". * checker-event.h: Likewise. * checker-path.cc: Likewise. * common.h: Convert enum access_direction to "enum class". * constraint-manager.cc: Convert enum bound_kind to "enum class". * constraint-manager.h: Likewise. * diagnostic-manager.cc: Convert enum event_kind to "enum class". * engine.cc: Convert enum status to "enum class". * exploded-graph.h: Likewise. * infinite-loop.cc: Likewise. * kf-lang-cp.cc: Convert enum poison_kind to "enum class". * kf.cc: Likewise. * region-model-manager.cc: Likewise. * region-model.cc: Likewise; also for enum access_direction. * svalue.cc: Likewise. * svalue.h: Likewise. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_cpython_plugin.cc: Convert enum poison_kind to "enum class". Signed-off-by: David Malcolm Diff: --- gcc/analyzer/access-diagram.cc | 16 ++-- gcc/analyzer/bounds-checking.cc| 26 +++--- gcc/analyzer/checker-event.cc | 80 +- gcc/analyzer/checker-event.h | 94 +++--- gcc/analyzer/checker-path.cc | 24 +++--- gcc/analyzer/common.h | 6 +- gcc/analyzer/constraint-manager.cc | 34 gcc/analyzer/constraint-manager.h | 6 +- gcc/analyzer/diagnostic-manager.cc | 42 +- gcc/analyzer/engine.cc | 52 ++-- gcc/analyzer/exploded-graph.h | 12 +-- gcc/analyzer/infinite-loop.cc | 2 +- gcc/analyzer/kf-lang-cp.cc | 2 +- gcc/analyzer/kf.cc | 4 +- gcc/analyzer/region-model-manager.cc | 2 +- gcc/analyzer/region-model.cc | 56 ++--- gcc/analyzer/svalue.cc | 12 +-- gcc/analyzer/svalue.h | 12 +-- .../gcc.dg/plugin/analyzer_cpython_plugin.cc | 4 +- 19 files changed, 243 insertions(+), 243 deletions(-) diff --git a/gcc/analyzer/access-diagram.cc b/gcc/analyzer/access-diagram.cc index 3bef7c88a459..a45268ac5b38 100644 --- a/gcc/analyzer/access-diagram.cc +++ b/gcc/analyzer/access-diagram.cc @@ -235,7 +235,7 @@ get_access_size_str (style_manager &sm, pp_format_decoder (&pp) = default_tree_printer; if (num_bits.maybe_print_for_user (&pp, op.m_model)) { - if (op.m_dir == DIR_READ) + if (op.m_dir == access_direction::read) return fmt_styled_string (sm, _("read of %qT (%s)"), type, @@ -247,7 +247,7 @@ get_access_size_str (style_manager &sm, pp_formatted_text (&pp)); } } - if (op.m_dir == DIR_READ) + if (op.m_dir == access_direction::read) { if (auto p = num_bits.maybe_get_formatted_str (sm, op.m_model, @@ -274,13 +274,13 @@ get_access_size_str (style_manager &sm, if (type) { - if (op.m_dir == DIR_READ) + if (op.m_dir == access_direction::read) return fmt_styled_string (sm, _("read of %qT"), type); else return fmt_styled_string (sm, _("write of %qT"), type); } - if (op.m_dir == DIR_READ) + if (op.m_dir == access_direction::read) return styled_string (sm, _("read")); else return styled_string (sm, _("write")); @@ -2372,7 +2372,7 @@ private: bit_size_expr num_before_bits (invalid_before_bits.get_size (m_op.get_manager ())); std::unique_ptr label; - if (m_op.m_dir == DIR_READ) + if (m_op.m_dir == access_direction::read) label = num_before_bits.maybe_get_formatted_str (m_sm, m_op.m_model, _("under-read of %wi bit"), @@ -2413,7 +2413,7 @@ private: maybe_add_gap (w, invalid_before_bits, valid_bits); std::unique_ptr label; -if (m_op.m_dir == DIR_READ) +if (m_op.m_dir == access_direction::read) label = num_valid_bits.maybe_get_formatted_str (m_sm, m_op.m_model, _("size: %wi bit"), @@ -2449,7 +2449,7 @@ priva
[gcc r16-257] analyzer: use analyzer/common.h as a common header
https://gcc.gnu.org/g:d0500cd5e249d57960c61484094d74ffd06655fd commit r16-257-gd0500cd5e249d57960c61484094d74ffd06655fd Author: David Malcolm Date: Mon Apr 28 18:21:21 2025 -0400 analyzer: use analyzer/common.h as a common header Our headers are a major pain to work with: many require certain other headers to be included in a particular (undocumented) order in order to be includable. Simplify includes in the analyzer by renaming analyzer/analyzer.h to analyzer/common.h and have it include all the common headers needed throughout the analyzer, thus encapsulating the rules about e.g. being able to include "gimple.h" in one place in the analyzer subdirectory. Doing so also makes it easier to e.g. define INCLUDE_SET in one place, rather than in many source files. gcc/analyzer/ChangeLog: * analyzer.h: Rename to... * common.h: ...this. Add define of INCLUDE_VECTOR, includes of "config.h", "system.h", "coretypes.h", "make-unique.h", "tree.h", "function.h", "basic-block.h", "gimple.h", "options.h", "bitmap.h", "diagnostic-core.h", and "diagnostic-path.h". * access-diagram.h: Don't include "analyzer/analyzer.h". * access-diagram.cc: Reorganize includes to #include "analyzer/common.h" first, then group by subsystem, dropping redundant headers. * analysis-plan.cc: Likewise. * analyzer-language.cc: Likewise. * analyzer-pass.cc: Likewise. * analyzer-selftests.cc: Likewise. * analyzer.cc: Likewise. * bounds-checking.cc: Likewise. * call-details.cc: Likewise. * call-info.cc: Likewise. * call-string.cc: Likewise. * call-summary.cc: Likewise. * checker-event.cc: Likewise. * checker-path.cc: Likewise. * complexity.cc: Likewise. * constraint-manager.cc: Likewise. * diagnostic-manager.cc: Likewise. * engine.cc: Likewise. * feasible-graph.cc: Likewise. * infinite-loop.cc: Likewise. * infinite-recursion.cc: Likewise. * kf-analyzer.cc: Likewise. * kf-lang-cp.cc: Likewise. * kf.cc: Likewise. * known-function-manager.cc: Likewise. * pending-diagnostic.cc: Likewise. * program-point.cc: Likewise. * program-state.cc: Likewise. * ranges.cc: Likewise. * record-layout.cc: Likewise. * region-model-asm.cc: Likewise. * region-model-manager.cc: Likewise. * region-model-reachability.cc: Likewise. * region-model.cc: Likewise. * region.cc: Likewise. * sm-fd.cc: Likewise. * sm-file.cc: Likewise. * sm-malloc.cc: Likewise. * sm-pattern-test.cc: Likewise. * sm-sensitive.cc: Likewise. * sm-signal.cc: Likewise. * sm-taint.cc: Likewise. * sm.cc: Likewise. * state-purge.cc: Likewise. * store.cc: Likewise. * supergraph.cc: Likewise. * svalue.cc: Likewise. * symbol.cc: Likewise. * trimmed-graph.cc: Likewise. * varargs.cc: Likewise. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_cpython_plugin.cc: Update for renaming of analyzer/analyzer.h to analyzer/common.h. * gcc.dg/plugin/analyzer_gil_plugin.cc: Likewise. * gcc.dg/plugin/analyzer_kernel_plugin.cc: Likewise. * gcc.dg/plugin/analyzer_known_fns_plugin.cc: Likewise. Signed-off-by: David Malcolm Diff: --- gcc/analyzer/access-diagram.cc | 22 +++- gcc/analyzer/access-diagram.h | 2 +- gcc/analyzer/analysis-plan.cc | 20 +++ gcc/analyzer/analyzer-language.cc | 10 ++-- gcc/analyzer/analyzer-pass.cc | 11 ++-- gcc/analyzer/analyzer-selftests.cc | 8 ++- gcc/analyzer/analyzer.cc | 14 ++--- gcc/analyzer/bounds-checking.cc| 15 ++ gcc/analyzer/call-details.cc | 22 +++- gcc/analyzer/call-info.cc | 26 +++-- gcc/analyzer/call-string.cc| 19 +-- gcc/analyzer/call-summary.cc | 12 + gcc/analyzer/checker-event.cc | 32 --- gcc/analyzer/checker-path.cc | 32 +++ gcc/analyzer/{analyzer.h => common.h} | 21 ++-- gcc/analyzer/complexity.cc | 28 ++ gcc/analyzer/constraint-manager.cc | 23 ++-- gcc/analyzer/diagnostic-manager.cc | 36 + gcc/analyzer/engine.cc
[gcc r16-255] analyzer: add a call_details::dump (using text_art)
https://gcc.gnu.org/g:0ef00f71969f200589355eb96a393b584340c0cf commit r16-255-g0ef00f71969f200589355eb96a393b584340c0cf Author: David Malcolm Date: Mon Apr 28 18:21:20 2025 -0400 analyzer: add a call_details::dump (using text_art) Add a new function to help debugging -fanalyzer. No functional change intended. gcc/analyzer/ChangeLog: * call-details.cc (call_details::dump): New overload. (call_details::make_dump_widget): New. * call-details.h (call_details::dump): Declare new overload. (call_details::make_dump_widget): New decl. Signed-off-by: David Malcolm Diff: --- gcc/analyzer/call-details.cc | 59 gcc/analyzer/call-details.h | 4 +++ 2 files changed, 63 insertions(+) diff --git a/gcc/analyzer/call-details.cc b/gcc/analyzer/call-details.cc index 4122f84facd1..3d85c17dbcba 100644 --- a/gcc/analyzer/call-details.cc +++ b/gcc/analyzer/call-details.cc @@ -366,6 +366,65 @@ call_details::dump (bool simple) const dump_to_pp (&pp, simple); } +/* Dump a tree-like representation of this call to stderr. */ + +DEBUG_FUNCTION void +call_details::dump () const +{ + text_art::dump (*this); +} + +std::unique_ptr +call_details::make_dump_widget (const text_art::dump_widget_info &dwi) const +{ + using text_art::tree_widget; + std::unique_ptr cd_widget +(tree_widget::from_fmt (dwi, nullptr, "Call Details")); + + { +pretty_printer the_pp; +pretty_printer * const pp = &the_pp; +pp_format_decoder (pp) = default_tree_printer; +pp_string (pp, "gcall: "); +pp_gimple_stmt_1 (pp, m_call, 0 /* spc */, TDF_NONE /* flags */); +cd_widget->add_child (tree_widget::make (dwi, pp)); + } + { +pretty_printer the_pp; +pretty_printer * const pp = &the_pp; +pp_format_decoder (pp) = default_tree_printer; +pp_string (pp, "return region: "); +if (m_lhs_region) + m_lhs_region->dump_to_pp (pp, true); +else + pp_string (pp, "NULL"); +auto w = tree_widget::make (dwi, pp); +if (m_lhs_region) + w->add_child (m_lhs_region->make_dump_widget (dwi)); +cd_widget->add_child (std::move (w)); + } + if (gimple_call_num_args (m_call) > 0) +{ + std::unique_ptr args_widget + (tree_widget::from_fmt (dwi, nullptr, "Arguments")); + for (unsigned i = 0; i < gimple_call_num_args (m_call); i++) + { + pretty_printer the_pp; + pretty_printer * const pp = &the_pp; + pp_format_decoder (pp) = default_tree_printer; + const svalue *arg_sval = get_arg_svalue (i); + pp_printf (pp, "%i: ", i); + arg_sval->dump_to_pp (pp, true); + auto w = tree_widget::make (dwi, pp); + w->add_child (arg_sval->make_dump_widget (dwi)); + args_widget->add_child (std::move (w)); + } + cd_widget->add_child (std::move (args_widget)); +} + + return cd_widget; +} + /* Get a conjured_svalue for this call for REG, and purge any state already relating to that conjured_svalue. */ diff --git a/gcc/analyzer/call-details.h b/gcc/analyzer/call-details.h index fee7ad4bbcb7..0f9f400ade60 100644 --- a/gcc/analyzer/call-details.h +++ b/gcc/analyzer/call-details.h @@ -68,6 +68,10 @@ public: void dump_to_pp (pretty_printer *pp, bool simple) const; void dump (bool simple) const; + void dump () const; + + std::unique_ptr + make_dump_widget (const text_art::dump_widget_info &dwi) const; const svalue *get_or_create_conjured_svalue (const region *) const;
[gcc r16-254] pass_manager: add m_ prefix to pass fields accessed via passes.def
https://gcc.gnu.org/g:1dc8916bcbb14c859def696be9d76f25e69c9b57 commit r16-254-g1dc8916bcbb14c859def696be9d76f25e69c9b57 Author: David Malcolm Date: Mon Apr 28 18:21:19 2025 -0400 pass_manager: add m_ prefix to pass fields accessed via passes.def Make it clearer when we're accessing member data of pass_manager by adding an "m"_ prefix to the fields handled via passes.def macros. No functional change intended. gcc/ChangeLog: * pass_manager.h (class pass_manager): Add "m_" prefix to all pass fields. * passes.cc (pass_manager::execute_early_local_passes): Update for added "m_" prefix. (pass_manager::execute_pass_mode_switching): Likewise. (pass_manager::finish_optimization_passes): Likewise. (pass_manager::pass_manager): Likewise. (pass_manager::dump_profile_report): Likewise. Signed-off-by: David Malcolm Diff: --- gcc/pass_manager.h | 20 ++-- gcc/passes.cc | 34 +- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/gcc/pass_manager.h b/gcc/pass_manager.h index 5fb7b0945d38..d4f89004559b 100644 --- a/gcc/pass_manager.h +++ b/gcc/pass_manager.h @@ -67,13 +67,13 @@ public: /* Various passes are manually cloned by avr and epiphany. */ opt_pass *get_pass_split_all_insns () const { -return pass_split_all_insns_1; +return m_pass_split_all_insns_1; } opt_pass *get_pass_mode_switching () const { -return pass_mode_switching_1; +return m_pass_mode_switching_1; } - opt_pass *get_pass_peephole2 () const { return pass_peephole2_1; } - opt_pass *get_pass_profile () const { return pass_profile_1; } + opt_pass *get_pass_peephole2 () const { return m_pass_peephole2_1; } + opt_pass *get_pass_profile () const { return m_pass_profile_1; } void register_pass_name (opt_pass *pass, const char *name); @@ -81,9 +81,9 @@ public: opt_pass *get_rest_of_compilation () const { -return pass_rest_of_compilation_1; +return m_pass_rest_of_compilation_1; } - opt_pass *get_clean_slate () const { return pass_clean_state_1; } + opt_pass *get_clean_slate () const { return m_pass_clean_state_1; } public: /* The root of the compilation pass tree, once constructed. */ @@ -114,21 +114,21 @@ private: For example: NEXT_PASS (pass_build_cfg, 1); within pass-instances.def means that there is a field: - opt_pass *pass_build_cfg_1; + opt_pass *m_pass_build_cfg_1; Similarly, the various: NEXT_PASS (pass_copy_prop, 1); ... NEXT_PASS (pass_copy_prop, 8); in pass-instances.def lead to fields: -opt_pass *pass_copy_prop_1; +opt_pass *m_pass_copy_prop_1; ... -opt_pass *pass_copy_prop_8; */ +opt_pass *m_pass_copy_prop_8; */ #define INSERT_PASSES_AFTER(PASS) #define PUSH_INSERT_PASSES_WITHIN(PASS, NUM) #define POP_INSERT_PASSES() -#define NEXT_PASS(PASS, NUM) opt_pass *PASS ## _ ## NUM +#define NEXT_PASS(PASS, NUM) opt_pass *m_ ## PASS ## _ ## NUM #define NEXT_PASS_WITH_ARG(PASS, NUM, ARG) NEXT_PASS (PASS, NUM) #define NEXT_PASS_WITH_ARGS(PASS, NUM, ...) NEXT_PASS (PASS, NUM) #define TERMINATE_PASS_LIST(PASS) diff --git a/gcc/passes.cc b/gcc/passes.cc index 3c28db78f095..0482de0b198d 100644 --- a/gcc/passes.cc +++ b/gcc/passes.cc @@ -116,14 +116,14 @@ opt_pass::opt_pass (const pass_data &data, context *ctxt) void pass_manager::execute_early_local_passes () { - execute_pass_list (cfun, pass_build_ssa_passes_1->sub); - execute_pass_list (cfun, pass_local_optimization_passes_1->sub); + execute_pass_list (cfun, m_pass_build_ssa_passes_1->sub); + execute_pass_list (cfun, m_pass_local_optimization_passes_1->sub); } unsigned int pass_manager::execute_pass_mode_switching () { - return pass_mode_switching_1->execute (cfun); + return m_pass_mode_switching_1->execute (cfun); } @@ -355,9 +355,9 @@ finish_optimization_passes (void) if (coverage_instrumentation_p () || flag_test_coverage || flag_branch_probabilities) { - dumps->dump_start (pass_profile_1->static_pass_number, NULL); + dumps->dump_start (m_pass_profile_1->static_pass_number, NULL); end_branch_prob (); - dumps->dump_finish (pass_profile_1->static_pass_number); + dumps->dump_finish (m_pass_profile_1->static_pass_number); } /* Do whatever is necessary to finish printing the graphs. */ @@ -1587,7 +1587,7 @@ pass_manager::pass_manager (context *ctxt) #define INSERT_PASSES_AFTER(PASS) #define PUSH_INSERT_PASSES_WITHIN(PASS, NUM) #define POP_INSERT_PASSES() -#define NEXT_PASS(PASS, NUM) PASS ## _ ## NUM = NULL +#define NEXT_PASS(PASS, NUM) m_ ## PASS ## _ ## NUM = NULL #define NEXT_PASS_WITH_ARG(PASS, NUM, ARG) NEXT_PASS (PASS, NUM) #define NEXT_PASS_WITH_ARGS(PASS, NUM, ...) NEXT_PASS (PASS, NUM) #define TERMINATE_PASS_LIST(PASS) @@ -
[gcc r16-256] analyzer: fail if we see unexpected gimple stmt codes
https://gcc.gnu.org/g:5ecea59621c63abdfdb4c91f8c37ab68b40b5b75 commit r16-256-g5ecea59621c63abdfdb4c91f8c37ab68b40b5b75 Author: David Malcolm Date: Mon Apr 28 18:21:20 2025 -0400 analyzer: fail if we see unexpected gimple stmt codes gcc/analyzer/ChangeLog: * region-model.cc (region_model::on_stmt_pre): Use internal_error if we see an unexpected gimple stmt code. Signed-off-by: David Malcolm Diff: --- gcc/analyzer/region-model.cc | 23 --- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index 84b81e968002..9583ba6663ba 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -1570,13 +1570,15 @@ region_model::on_stmt_pre (const gimple *stmt, { switch (gimple_code (stmt)) { -default: - /* No-op for now. */ - break; - -case GIMPLE_DEBUG: - /* We should have stripped these out when building the supergraph. */ - gcc_unreachable (); +case GIMPLE_COND: +case GIMPLE_EH_DISPATCH: +case GIMPLE_GOTO: +case GIMPLE_LABEL: +case GIMPLE_NOP: +case GIMPLE_PREDICT: +case GIMPLE_RESX: +case GIMPLE_SWITCH: + /* No-ops here. */ break; case GIMPLE_ASSIGN: @@ -1611,6 +1613,13 @@ region_model::on_stmt_pre (const gimple *stmt, on_return (return_, ctxt); } break; + +/* We don't expect to see any other statement kinds in the analyzer. */ +case GIMPLE_DEBUG: // should have stripped these out when building the supergraph +default: + internal_error ("unexpected gimple stmt code: %qs", + gimple_code_name[gimple_code (stmt)]); + break; } }
[gcc r16-261] analyzer: use unique_ptr for state_machine instances
https://gcc.gnu.org/g:6f9764571d2dd1b03e41be18b0bcd4fa445b958f commit r16-261-g6f9764571d2dd1b03e41be18b0bcd4fa445b958f Author: David Malcolm Date: Mon Apr 28 18:21:22 2025 -0400 analyzer: use unique_ptr for state_machine instances gcc/analyzer/ChangeLog: * engine.cc (class plugin_analyzer_init_impl): Convert "m_checkers" to use std::vector of std::unique_ptr. Convert "m_known_fn_mgr" to a reference. (impl_run_checkers): Convert "checkers" to use std::vector of std::unique_ptr and move it into the extrinsic_state. * program-state.cc (extrinsic_state::dump_to_pp): Update for changes to m_checkers. (extrinsic_state::to_json): Likewise. (extrinsic_state::get_sm_idx_by_name): Likewise. (selftest::test_sm_state_map): Update to use std::unique_ptr for state machines. (selftest::test_program_state_1): Likewise. (selftest::test_program_state_2): Likewise. (selftest::test_program_state_merging): Likewise. (selftest::test_program_state_merging_2): Likewise. * program-state.h (class extrinsic_state): Convert "m_checkers" to use std::vector of std::unique_ptr and to be owned by this object, rather than a reference. Add ctor for use in selftests. * sm-fd.cc (make_fd_state_machine): Update to use std::unique_ptr. * sm-file.cc (make_fileptr_state_machine): Likewise. * sm-malloc.cc (make_malloc_state_machine): Likewise. * sm-pattern-test.cc (make_pattern_test_state_machine): Likewise. * sm-sensitive.cc (make_sensitive_state_machine): Likewise. * sm-signal.cc (make_signal_state_machine): Likewise. * sm-taint.cc (make_taint_state_machine): Likewise. * sm.cc: Define INCLUDE_LIST. (make_checkers): Return the vector directly, rather than pass it in by reference. Update to use std::unique_ptr throughout. Use an intermediate list, and use that to filter with flag_analyzer_checker, fixing memory leak for this case. * sm.h: (make_checkers): Return the vector directly, rather than pass it in by reference, and use std::vector of std::unique_ptr. (make_malloc_state_machine): Convert return type to use std::unique_ptr. (make_fileptr_state_machine): Likewise. (make_taint_state_machine): Likewise. (make_sensitive_state_machine): Likewise. (make_signal_state_machine): Likewise. (make_pattern_test_state_machine): Likewise. (make_va_list_state_machine): Likewise. (make_fd_state_machine): Likewise. * varargs.cc (make_va_list_state_machine): Update to use std::unique_ptr. Signed-off-by: David Malcolm Diff: --- gcc/analyzer/engine.cc | 28 +- gcc/analyzer/program-state.cc | 63 ++--- gcc/analyzer/program-state.h| 20 ++--- gcc/analyzer/sm-fd.cc | 4 +-- gcc/analyzer/sm-file.cc | 4 +-- gcc/analyzer/sm-malloc.cc | 4 +-- gcc/analyzer/sm-pattern-test.cc | 4 +-- gcc/analyzer/sm-sensitive.cc| 4 +-- gcc/analyzer/sm-signal.cc | 4 +-- gcc/analyzer/sm-taint.cc| 4 +-- gcc/analyzer/sm.cc | 44 +++- gcc/analyzer/sm.h | 22 +++--- gcc/analyzer/varargs.cc | 4 +-- 13 files changed, 108 insertions(+), 101 deletions(-) diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index f33cc0bda4d1..c04bda1e6458 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -6103,8 +6103,8 @@ dump_analyzer_json (const supergraph &sg, class plugin_analyzer_init_impl : public plugin_analyzer_init_iface { public: - plugin_analyzer_init_impl (auto_delete_vec *checkers, -known_function_manager *known_fn_mgr, + plugin_analyzer_init_impl (std::vector> &checkers, +known_function_manager &known_fn_mgr, logger *logger) : m_checkers (checkers), m_known_fn_mgr (known_fn_mgr), @@ -6114,14 +6114,14 @@ public: void register_state_machine (std::unique_ptr sm) final override { LOG_SCOPE (m_logger); -m_checkers->safe_push (sm.release ()); +m_checkers.push_back (std::move (sm)); } void register_known_function (const char *name, std::unique_ptr kf) final override { LOG_SCOPE (m_logger); -m_known_fn_mgr->add (name, std::move (kf)); +m_known_fn_mgr.add (name, std::move (kf)); } logger *get_logger () const final override @@ -6130,8 +6130,8 @@ public: } private: - auto_delete_vec *m_checkers; - known_function_manager *m_known_fn_mgr; + std::vector> &m_checkers; +
[gcc r16-250] sarif output: introduce sarif_generation_options
https://gcc.gnu.org/g:a25818cd302a77ab2ca3b27c32702b9b163d65f7 commit r16-250-ga25818cd302a77ab2ca3b27c32702b9b163d65f7 Author: David Malcolm Date: Mon Apr 28 18:21:18 2025 -0400 sarif output: introduce sarif_generation_options Signed-off-by: David Malcolm gcc/ChangeLog: * diagnostic-format-sarif.cc (sarif_builder::get_opts): New accessor. (sarif_builder::get_version): Update for... (sarif_builder::m_version): Replace this field... (sarif_builder::m_m_sarif_gen_opts): ...with this. (sarif_builder::sarif_builder): Replace version with sarif_gen_opts throughout. (sarif_builder::make_top_level_object): Use get_version. (sarif_output_format::sarif_output_format): Replace version with sarif_gen_opts throughout. (sarif_stream_output_format::sarif_stream_output_format): Likewise. (sarif_file_output_format::sarif_file_output_format): Likewise. (diagnostic_output_format_init_sarif_stderr): Drop version param and use default for sarif_generation_options instead. (diagnostic_output_format_init_sarif_file): Likewise. (diagnostic_output_format_init_sarif_stream): Likewise. (make_sarif_sink): Replace version with sarif_gen_opts throughout. (sarif_generation_options::sarif_generation_options): New. (selftest::test_sarif_diagnostic_context::test_sarif_diagnostic_context): Replace version with sarif_gen_opts throughout. (selftest::test_make_location_object): Likewise. (selftest::test_simple_log): Likewise. (selftest::test_simple_log_2): Likewise. (selftest::test_message_with_embedded_link): Likewise. (selftest::test_message_with_braces): Likewise. (selftest::test_buffering): Likewise. (selftest::run_tests_per_version): Replace with... (selftest::for_each_sarif_gen_option): ...this... (selftest::run_line_table_case_tests_per_version): ...and this. (selftest::diagnostic_format_sarif_cc_tests): Update to use for_each_sarif_gen_option and run_line_table_case_tests_per_version. * diagnostic-format-sarif.h (enum class sarif_version): Move lower down. (diagnostic_output_format_init_sarif_stderr): Drop "version" param. (diagnostic_output_format_init_sarif_file): Likewise. (diagnostic_output_format_init_sarif_stream): Likewise. (struct sarif_generation_options): New. (make_sarif_sink): Add "formatted" param. Replace version param with sarif_gen_opts. * diagnostic.cc (diagnostic_output_format_init): Drop hardcoded sarif_version::v2_1_0 arguments from calls, which instead use the default ctor for sarif_generation_options internally. * libgdiagnostics.cc (sarif_sink::sarif_sink): Replace version param with sarif_gen_opts, and update for changes to make_sarif_sink. (diagnostic_manager_add_sarif_sink): Use sarif_gen_opts rather than version. * opts-diagnostic.cc (sarif_scheme_handler::make_sink): Likewise. Pass "true" for "formatted" param. Signed-off-by: David Malcolm Diff: --- gcc/diagnostic-format-sarif.cc | 140 +++-- gcc/diagnostic-format-sarif.h | 36 +++ gcc/diagnostic.cc | 4 +- gcc/libgdiagnostics.cc | 15 ++--- gcc/opts-diagnostic.cc | 6 +- 5 files changed, 115 insertions(+), 86 deletions(-) diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc index 8dbc91ee8f32..c490d0d1785c 100644 --- a/gcc/diagnostic-format-sarif.cc +++ b/gcc/diagnostic-format-sarif.cc @@ -689,7 +689,7 @@ public: const line_maps *line_maps, const char *main_input_filename_, bool formatted, -enum sarif_version version); +const sarif_generation_options &sarif_gen_opts); ~sarif_builder (); void set_printer (pretty_printer &printer) @@ -743,7 +743,7 @@ public: diagnostic_context &get_context () const { return m_context; } pretty_printer *get_printer () const { return m_printer; } token_printer &get_token_printer () { return m_token_printer; } - enum sarif_version get_version () const { return m_version; } + enum sarif_version get_version () const { return m_sarif_gen_opts.m_version; } size_t num_results () const { return m_results_array->size (); } sarif_result &get_result (size_t idx) @@ -753,6 +753,8 @@ public: return *static_cast (element); } + const sarif_generation_options &get_opts () const { return m_sarif_gen_opts; } + private: class sarif_token_printer : public token_pri
[gcc r16-253] c, c++: use unique_ptr in name_hint to reduce naked 'new'
https://gcc.gnu.org/g:9c4336cbf0522876ca3e81a2b5a71c8294441b81 commit r16-253-g9c4336cbf0522876ca3e81a2b5a71c8294441b81 Author: David Malcolm Date: Mon Apr 28 18:21:19 2025 -0400 c,c++: use unique_ptr in name_hint to reduce naked 'new' gcc/c-family/ChangeLog: * name-hint.h (name_hint::name_hint): Use std::unique_ptr for param. gcc/c/ChangeLog: * c-decl.cc: Include "make-unique.h". (lookup_name_fuzzy): Use ::make_unique rather than "new" when making suggest_missing_header and suggest_missing_option. * c-parser.cc: Include "make-unique.h" (c_parser_error_richloc): Use ::make_unique rather than "new" when making suggest_missing_header. gcc/cp/ChangeLog: * name-lookup.cc: Include "make-unique.h". (namespace_hints::convert_candidates_to_name_hint): Use ::make_unique rather than "new" when making show_candidate_location and suggest_alternatives. (namespace_hints::maybe_decorate_with_limit): Likewise when making namespace_limit_reached. (suggest_alternatives_for_1): Likewise when making suggest_missing_option. (maybe_suggest_missing_std_header): Likewise when making missing_std_header. (macro_use_before_def::maybe_make): Use std::unique_ptr. (macro_use_before_def::macro_use_before_def): Make public. (lookup_name_fuzzy): Use ::make_unique rather than "new" when making suggest_missing_header. * parser.cc: Include "make-unique.h". (cp_parser_error_1): Use ::make_unique rather than "new" when making suggest_missing_header. Signed-off-by: David Malcolm Diff: --- gcc/c-family/name-hint.h | 6 -- gcc/c/c-decl.cc | 19 +++ gcc/c/c-parser.cc| 8 +--- gcc/cp/name-lookup.cc| 49 +++- gcc/cp/parser.cc | 9 ++--- 5 files changed, 54 insertions(+), 37 deletions(-) diff --git a/gcc/c-family/name-hint.h b/gcc/c-family/name-hint.h index 3d4f2f5e205d..13ade7123f80 100644 --- a/gcc/c-family/name-hint.h +++ b/gcc/c-family/name-hint.h @@ -85,8 +85,10 @@ class name_hint public: name_hint () : m_suggestion (NULL), m_deferred () {} - name_hint (const char *suggestion, deferred_diagnostic *deferred) - : m_suggestion (suggestion), m_deferred (deferred) + name_hint (const char *suggestion, +std::unique_ptr deferred) + : m_suggestion (suggestion), +m_deferred (std::move (deferred)) { } diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index e7aee8a0f4b2..e7765f6d9511 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -62,6 +62,7 @@ along with GCC; see the file COPYING3. If not see #include "omp-offload.h" /* For offload_vars. */ #include "c-parser.h" #include "gcc-urlifier.h" +#include "make-unique.h" #include "tree-pretty-print.h" @@ -4547,10 +4548,11 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t loc) = get_c_stdlib_header_for_name (IDENTIFIER_POINTER (name)); if (header_hint) -return name_hint (NULL, - new suggest_missing_header (loc, - IDENTIFIER_POINTER (name), - header_hint)); +return name_hint + (nullptr, + ::make_unique (loc, + IDENTIFIER_POINTER (name), + header_hint)); /* Next, look for exact matches for builtin defines that would have been defined if the user had passed a command-line option (e.g. -fopenmp @@ -4558,10 +4560,11 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t loc) diagnostic_option_id option_id = get_option_for_builtin_define (IDENTIFIER_POINTER (name)); if (option_id.m_idx > 0) -return name_hint (nullptr, - new suggest_missing_option (loc, - IDENTIFIER_POINTER (name), - option_id)); +return name_hint + (nullptr, + ::make_unique (loc, + IDENTIFIER_POINTER (name), + option_id)); /* Only suggest names reserved for the implementation if NAME begins with an underscore. */ diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 22ec0f849b74..2e7ba28f404b 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -77,6 +77,7 @@ along with GCC; see the file COPYING3. If not see #include "asan.h" #include "c-family/c-ubsan.h" #include "gcc-urlifier.h" +#include "make-unique.h" /* We need to walk over decls with incomplete struct/union/enum types after parsing the whole translation
[gcc r16-251] diagnostics: make diagnostic_context::m_abort_on_error private
https://gcc.gnu.org/g:0c5b98be0806e275685a2803c49a695328f5dd8b commit r16-251-g0c5b98be0806e275685a2803c49a695328f5dd8b Author: David Malcolm Date: Mon Apr 28 18:21:18 2025 -0400 diagnostics: make diagnostic_context::m_abort_on_error private No functional change intended. gcc/ChangeLog: * diagnostic.h (diagnostic_context::set_abort_on_error): New. (diagnostic_context::m_abort_on_error): Make private. (diagnostic_abort_on_error): Delete. * opts.cc (setup_core_dumping): Update for above changes. Signed-off-by: David Malcolm Diff: --- gcc/diagnostic.h | 16 gcc/opts.cc | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 62bffd2c6851..c679017d2850 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -772,6 +772,13 @@ public: bool supports_fnotice_on_stderr_p () const; + /* Raise SIGABRT on any diagnostic of severity DK_ERROR or higher. */ + void + set_abort_on_error (bool val) + { +m_abort_on_error = val; + } + private: void error_recursion () ATTRIBUTE_NORETURN; @@ -828,10 +835,10 @@ private: each diagnostic, if known. */ bool m_show_option_requested; -public: /* True if we should raise a SIGABRT on errors. */ bool m_abort_on_error; +public: /* True if we should show the column number on diagnostics. */ bool m_show_column; @@ -1042,13 +1049,6 @@ diagnostic_text_finalizer (diagnostic_context *context) #define diagnostic_context_auxiliary_data(DC) (DC)->m_client_aux_data #define diagnostic_info_auxiliary_data(DI) (DI)->x_data -/* Raise SIGABRT on any diagnostic of severity DK_ERROR or higher. */ -inline void -diagnostic_abort_on_error (diagnostic_context *context) -{ - context->m_abort_on_error = true; -} - /* This diagnostic_context is used by front-ends that directly output diagnostic messages without going through `error', `warning', and similar functions. */ diff --git a/gcc/opts.cc b/gcc/opts.cc index d3e3a2dc0d12..a9b9b9148a95 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -3628,7 +3628,7 @@ setup_core_dumping (diagnostic_context *dc) "setting core file size limit to maximum: %m"); } #endif - diagnostic_abort_on_error (dc); + dc->set_abort_on_error (true); } /* Parse a -d command line switch for OPTS, location LOC,
[gcc r16-252] diagnostics: use diagnostic_option_id for m_opt_permissive
https://gcc.gnu.org/g:bc39b0072f5660dd5dbacd551312be24281226ce commit r16-252-gbc39b0072f5660dd5dbacd551312be24281226ce Author: David Malcolm Date: Mon Apr 28 18:21:18 2025 -0400 diagnostics: use diagnostic_option_id for m_opt_permissive gcc/ChangeLog: * diagnostic.h (diagnostic_context::m_opt_permissive): Convert from int to diagnostic_option_id. Update comment. Signed-off-by: David Malcolm Diff: --- gcc/diagnostic.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index c679017d2850..36f4a1c8f9f3 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -848,9 +848,9 @@ public: /* True if permerrors are warnings. */ bool m_permissive; - /* The index of the option to associate with turning permerrors into - warnings. */ - int m_opt_permissive; + /* The option to associate with turning permerrors into warnings, + if any. */ + diagnostic_option_id m_opt_permissive; /* True if errors are fatal. */ bool m_fatal_errors;
gcc-cvs@gcc.gnu.org
https://gcc.gnu.org/g:4e1f545df9da1d2e6f9189c6d289a4875f1e24e3 commit r16-260-g4e1f545df9da1d2e6f9189c6d289a4875f1e24e3 Author: David Malcolm Date: Mon Apr 28 18:21:22 2025 -0400 analyzer: convert various call_summary * to call_summary & No functional change intended. gcc/analyzer/ChangeLog: * call-summary.cc (call_summary_replay::call_summary_replay): Convert "summary" from call_summary * to call_summary &. (call_summary_replay::dump_to_pp): Likewise for m_summary. * call-summary.h (call_summary_replay::call_summary_replay): Likewise for "summary". (call_summary_replay::m_summary): Likewise. * engine.cc (call_summary_edge_info::call_summary_edge_info): Likewise. (call_summary_edge_info::update_state): Likewise. (call_summary_edge_info::update_model): Likewise. (call_summary_edge_info::print_desc): Likewise for m_summary. (call_summary_edge_info::m_summary): Likewise. (exploded_node::replay_call_summaries): Update for change to replay_call_summary. (exploded_node::replay_call_summary): Convert "summary" from call_summary * to call_summary &. * exploded-graph.h (exploded_node::replay_call_summary): Likewise. Signed-off-by: David Malcolm Diff: --- gcc/analyzer/call-summary.cc | 4 ++-- gcc/analyzer/call-summary.h | 4 ++-- gcc/analyzer/engine.cc| 24 +--- gcc/analyzer/exploded-graph.h | 2 +- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/gcc/analyzer/call-summary.cc b/gcc/analyzer/call-summary.cc index 14ccba28f7e4..33de3d638f2b 100644 --- a/gcc/analyzer/call-summary.cc +++ b/gcc/analyzer/call-summary.cc @@ -157,7 +157,7 @@ call_summary::dump (const extrinsic_state &ext_state, bool simple) const call_summary_replay::call_summary_replay (const call_details &cd, const function &called_fn, - call_summary *summary, + call_summary &summary, const extrinsic_state &ext_state) : m_cd (cd), m_summary (summary), @@ -808,7 +808,7 @@ call_summary_replay::dump_to_pp (pretty_printer *pp, bool simple) const pp_newline (pp); pp_string (pp, "CALLEE SUMMARY:"); pp_newline (pp); - m_summary->dump_to_pp (m_ext_state, pp, simple); + m_summary.dump_to_pp (m_ext_state, pp, simple); /* Current state of caller (could be in mid-update). */ pp_newline (pp); diff --git a/gcc/analyzer/call-summary.h b/gcc/analyzer/call-summary.h index 297171d745fd..7280cca8bd79 100644 --- a/gcc/analyzer/call-summary.h +++ b/gcc/analyzer/call-summary.h @@ -69,7 +69,7 @@ class call_summary_replay public: call_summary_replay (const call_details &cd, const function &called_fn, - call_summary *m_summary, + call_summary &summary, const extrinsic_state &ext_state); const call_details &get_call_details () const { return m_cd; } @@ -102,7 +102,7 @@ private: const region *convert_region_from_summary_1 (const region *); const call_details &m_cd; - call_summary *m_summary; + call_summary &m_summary; const extrinsic_state &m_ext_state; // Mapping from svalues in summary to svalues for callsite: diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index 311bc5878b04..f33cc0bda4d1 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -1626,7 +1626,7 @@ class call_summary_edge_info : public call_info public: call_summary_edge_info (const call_details &cd, const function &called_fn, - call_summary *summary, + call_summary &summary, const extrinsic_state &ext_state) : call_info (cd, called_fn), m_called_fn (called_fn), @@ -1641,7 +1641,7 @@ public: /* Update STATE based on summary_end_state. */ call_details cd (get_call_details (state->m_region_model, ctxt)); call_summary_replay r (cd, m_called_fn, m_summary, m_ext_state); -const program_state &summary_end_state = m_summary->get_state (); +const program_state &summary_end_state = m_summary.get_state (); return state->replay_call_summary (r, summary_end_state); } @@ -1652,19 +1652,19 @@ public: /* Update STATE based on summary_end_state. */ call_details cd (get_call_details (model, ctxt)); call_summary_replay r (cd, m_called_fn, m_summary, m_ext_state); -const program_state &summary_end_state = m_summary->get_state (); +const program_state &summary_end_state = m_summary.get_state (); model->replay_call_summary (r, *summary_end_state.m_region_model); return true; } void print_desc (pretty_printer &pp) const final override
[gcc r16-259] analyzer: convert gcall * to gcall & in many places
https://gcc.gnu.org/g:c2f8c7ad2db225b55fb2ce53ed4a2d107b4f850c commit r16-259-gc2f8c7ad2db225b55fb2ce53ed4a2d107b4f850c Author: David Malcolm Date: Mon Apr 28 18:21:21 2025 -0400 analyzer: convert gcall * to gcall & in many places No functional change intended. gcc/analyzer/ChangeLog: * analyzer.cc: Convert gcall * to gcall & where we know the pointer must be non-null. * call-details.cc: Likewise. * call-details.h: Likewise. * call-info.cc: Likewise. * call-info.h: Likewise. * call-summary.h: Likewise. * checker-event.cc: Likewise. * checker-event.h: Likewise. * common.h: Likewise. * diagnostic-manager.cc: Likewise. * engine.cc: Likewise. * exploded-graph.h: Likewise. * kf-analyzer.cc: Likewise. * kf-lang-cp.cc: Likewise. * kf.cc: Likewise. * known-function-manager.cc: Likewise. * program-state.cc: Likewise. * program-state.h: Likewise. * region-model.cc: Likewise. * region-model.h: Likewise. * sm-fd.cc: Likewise. * sm-file.cc: Likewise. * sm-malloc.cc: Likewise. * sm-sensitive.cc: Likewise. * sm-signal.cc: Likewise. * sm-taint.cc: Likewise. * sm.h: Likewise. * store.cc: Likewise. * store.h: Likewise. * supergraph.cc: Likewise. * supergraph.h: Likewise. * svalue.h: Likewise. * varargs.cc: Likewise. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_gil_plugin.cc: Convert gcall * to gcall & where we know the pointer must be non-null. Signed-off-by: David Malcolm Diff: --- gcc/analyzer/analyzer.cc | 24 +-- gcc/analyzer/call-details.cc | 32 ++-- gcc/analyzer/call-details.h| 10 +- gcc/analyzer/call-info.cc | 2 +- gcc/analyzer/call-info.h | 4 +- gcc/analyzer/call-summary.h| 2 +- gcc/analyzer/checker-event.cc | 2 +- gcc/analyzer/checker-event.h | 4 +- gcc/analyzer/common.h | 14 +- gcc/analyzer/diagnostic-manager.cc | 12 +- gcc/analyzer/engine.cc | 71 - gcc/analyzer/exploded-graph.h | 22 +-- gcc/analyzer/kf-analyzer.cc| 2 +- gcc/analyzer/kf-lang-cp.cc | 7 +- gcc/analyzer/kf.cc | 13 +- gcc/analyzer/known-function-manager.cc | 2 +- gcc/analyzer/program-state.cc | 12 +- gcc/analyzer/program-state.h | 6 +- gcc/analyzer/region-model.cc | 83 +- gcc/analyzer/region-model.h| 26 +-- gcc/analyzer/sm-fd.cc | 174 ++--- gcc/analyzer/sm-file.cc| 6 +- gcc/analyzer/sm-malloc.cc | 64 gcc/analyzer/sm-sensitive.cc | 6 +- gcc/analyzer/sm-signal.cc | 18 +-- gcc/analyzer/sm-taint.cc | 16 +- gcc/analyzer/sm.h | 2 +- gcc/analyzer/store.cc | 6 +- gcc/analyzer/store.h | 4 +- gcc/analyzer/supergraph.cc | 22 +-- gcc/analyzer/supergraph.h | 4 +- gcc/analyzer/svalue.h | 5 +- gcc/analyzer/varargs.cc| 62 gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.cc | 25 +-- 34 files changed, 381 insertions(+), 383 deletions(-) diff --git a/gcc/analyzer/analyzer.cc b/gcc/analyzer/analyzer.cc index 97fbc5cab019..88e53c7b94a2 100644 --- a/gcc/analyzer/analyzer.cc +++ b/gcc/analyzer/analyzer.cc @@ -290,12 +290,12 @@ get_ssa_default_def (const function &fun, tree var) If LOOK_IN_STD is true, then also look for within std:: for the name. */ bool -is_special_named_call_p (const gcall *call, const char *funcname, +is_special_named_call_p (const gcall &call, const char *funcname, unsigned int num_args, bool look_in_std) { gcc_assert (funcname); - tree fndecl = gimple_call_fndecl (call); + tree fndecl = gimple_call_fndecl (&call); if (!fndecl) return false; @@ -388,7 +388,7 @@ is_std_named_call_p (const_tree fndecl, const char *funcname) bool is_named_call_p (const_tree fndecl, const char *funcname, -const gcall *call, unsigned int num_args) +const gcall &call, unsigned int n
[gcc r16-266] analyzer: handle NRVO and DECL_BY_REFERENCE [PR111536]
https://gcc.gnu.org/g:a1922f0252b3b09016df76bd5b10119206935e37 commit r16-266-ga1922f0252b3b09016df76bd5b10119206935e37 Author: David Malcolm Date: Mon Apr 28 18:21:25 2025 -0400 analyzer: handle NRVO and DECL_BY_REFERENCE [PR111536] The analyzer was issuing false warnings about uninitialized variables in C++ in places where NRVO was marking DECL_RESULT with DECL_BY_REFERENCE. Fixed thusly. gcc/analyzer/ChangeLog: PR analyzer/111536 * engine.cc (maybe_update_for_edge): Update for new call_stmt param to region_model::push_frame. * program-state.cc (program_state::push_frame): Likewise. * region-model.cc (region_model::update_for_gcall): Likewise. (region_model::push_frame): Add "call_stmt" param. Handle DECL_RESULT with DECL_BY_REFERENCE set on it by stashing the region of the lhs of the call_stmt in the caller frame, and writing a reference to it within the "result" in the callee frame. (region_model::pop_frame): Don't write back to the LHS for DECL_BY_REFERENCE results. (selftest::test_stack_frames): Update for new call_stmt param to region_model::push_frame. (selftest::test_get_representative_path_var): Likewise. (selftest::test_state_merging): Likewise. (selftest::test_alloca): Likewise. * region-model.h (region_model::push_frame): Add "call_stmt" param. * region.cc: Include "tree-ssa.h". (region::can_have_initial_svalue_p): Use ssa_defined_default_def_p for ssa names, rather than special-casing it for just parameters. This should now also cover DECL_RESULT with DECL_BY_REFERENCE and hard registers. * sm-signal.cc (update_model_for_signal_handler): Update for new call_stmt param to region_model::push_frame. * state-purge.cc (state_purge_per_decl::process_worklists): Likewise. gcc/testsuite/ChangeLog: PR analyzer/111536 * c-c++-common/analyzer/hard-reg-1.c: New test. * g++.dg/analyzer/nrvo-1.C: New test. * g++.dg/analyzer/nrvo-2.C: New test. * g++.dg/analyzer/nrvo-pr111536-1.C: New test. * g++.dg/analyzer/nrvo-pr111536-1b.C: New test. * g++.dg/analyzer/nrvo-pr111536-2.C: New test. * g++.dg/analyzer/nrvo-pr111536-2b.C: New test. Signed-off-by: David Malcolm Diff: --- gcc/analyzer/engine.cc | 2 +- gcc/analyzer/program-state.cc| 2 +- gcc/analyzer/region-model.cc | 90 gcc/analyzer/region-model.h | 4 +- gcc/analyzer/region.cc | 14 ++-- gcc/analyzer/sm-signal.cc| 2 +- gcc/analyzer/state-purge.cc | 2 +- gcc/testsuite/c-c++-common/analyzer/hard-reg-1.c | 8 +++ gcc/testsuite/g++.dg/analyzer/nrvo-1.C | 18 + gcc/testsuite/g++.dg/analyzer/nrvo-2.C | 26 +++ gcc/testsuite/g++.dg/analyzer/nrvo-pr111536-1.C | 11 +++ gcc/testsuite/g++.dg/analyzer/nrvo-pr111536-1b.C | 12 gcc/testsuite/g++.dg/analyzer/nrvo-pr111536-2.C | 10 +++ gcc/testsuite/g++.dg/analyzer/nrvo-pr111536-2b.C | 13 14 files changed, 186 insertions(+), 28 deletions(-) diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index 0917306fe38c..c3e4800f70ad 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -5343,7 +5343,7 @@ maybe_update_for_edge (logger *logger, == PK_BEFORE_SUPERNODE); function *fun = eedge->m_dest->get_function (); gcc_assert (fun); - m_model.push_frame (*fun, NULL, ctxt); + m_model.push_frame (*fun, nullptr, nullptr, ctxt); if (logger) logger->log (" pushing frame for %qD", fun->decl); } diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc index dbca0369b9a1..21f78e5b5c3c 100644 --- a/gcc/analyzer/program-state.cc +++ b/gcc/analyzer/program-state.cc @@ -1231,7 +1231,7 @@ void program_state::push_frame (const extrinsic_state &ext_state ATTRIBUTE_UNUSED, const function &fun) { - m_region_model->push_frame (fun, NULL, NULL); + m_region_model->push_frame (fun, nullptr, nullptr, nullptr); } /* Get the current function of this state. */ diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index fc586296ce5b..1ee882c98ea5 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -6270,7 +6270,7 @@ region_model::update_for_gcall (const gcall &call_stmt, } gcc_assert (callee); - push_frame (*callee, &arg_svals, ctxt); + push_frame (*callee, &call_stmt, &arg_svals, ctxt); } /* Pop the top-most frame_r
[gcc r16-265] analyzer: fix null deref false negative on std::unique_ptr [PR109366]
https://gcc.gnu.org/g:2a63dc8c65d469e1d7ac3d764179653bf0ec843f commit r16-265-g2a63dc8c65d469e1d7ac3d764179653bf0ec843f Author: David Malcolm Date: Mon Apr 28 18:21:24 2025 -0400 analyzer: fix null deref false negative on std::unique_ptr [PR109366] gcc/analyzer/ChangeLog: PR analyzer/109366 * region-model-manager.cc (region_model_manager::maybe_fold_sub_svalue): Sub-values of zero constants are zero. gcc/testsuite/ChangeLog: PR analyzer/109366 * g++.dg/analyzer/unique_ptr-1.C: New test. * g++.dg/analyzer/unique_ptr-2.C: New test. Signed-off-by: David Malcolm Diff: --- gcc/analyzer/region-model-manager.cc | 6 ++ gcc/testsuite/g++.dg/analyzer/unique_ptr-1.C | 13 + gcc/testsuite/g++.dg/analyzer/unique_ptr-2.C | 17 + 3 files changed, 36 insertions(+) diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc index 3e7d10485b4b..df92503770b3 100644 --- a/gcc/analyzer/region-model-manager.cc +++ b/gcc/analyzer/region-model-manager.cc @@ -944,6 +944,12 @@ region_model_manager::maybe_fold_sub_svalue (tree type, if (!parent_svalue->can_have_associated_state_p ()) return get_or_create_unknown_svalue (type); + /* If we have a subvalue of a zero constant, it's zero. */ + if (tree cst = parent_svalue->maybe_get_constant ()) +if (TREE_CODE (cst) == INTEGER_CST) + if (zerop (cst)) + return get_or_create_cast (type, parent_svalue); + /* If we have a subregion of a zero-fill, it's zero. */ if (const unaryop_svalue *unary = parent_svalue->dyn_cast_unaryop_svalue ()) diff --git a/gcc/testsuite/g++.dg/analyzer/unique_ptr-1.C b/gcc/testsuite/g++.dg/analyzer/unique_ptr-1.C new file mode 100644 index ..cc9cf71092ca --- /dev/null +++ b/gcc/testsuite/g++.dg/analyzer/unique_ptr-1.C @@ -0,0 +1,13 @@ +// Verify that we complain about trivial uses of NULL unique_ptr. + +// { dg-do compile { target c++11 } } + +#include + +struct A {int x; int y;}; + +int main() { + std::unique_ptr a; + a->x = 12; // { dg-warning "dereference of NULL" } + return 0; +} diff --git a/gcc/testsuite/g++.dg/analyzer/unique_ptr-2.C b/gcc/testsuite/g++.dg/analyzer/unique_ptr-2.C new file mode 100644 index ..e8d3e7ef873a --- /dev/null +++ b/gcc/testsuite/g++.dg/analyzer/unique_ptr-2.C @@ -0,0 +1,17 @@ +// { dg-do compile { target c++11 } } +// { dg-additional-options "-Wno-analyzer-too-complex" } */ + +#include + +struct A {int x; int y;}; + +extern std::unique_ptr make_ptr (); + +int test (int flag) { + std::unique_ptr a; + if (flag) +a = make_ptr (); + a->x = 12; // { dg-warning "dereference of NULL" "" { xfail *-*-*} } + // TODO: this is failing due to "too complex" warnings + return 0; +}
[gcc r16-263] analyzer, c++: add placeholder implementation of ana::translation_unit for C++
https://gcc.gnu.org/g:13f4b12393fa9813b57f5d2dff0753945a2812ce commit r16-263-g13f4b12393fa9813b57f5d2dff0753945a2812ce Author: David Malcolm Date: Mon Apr 28 18:21:23 2025 -0400 analyzer,c++: add placeholder implementation of ana::translation_unit for C++ Implement ana::translation_unit for the C++ frontend with a no-op placeholder implementation, for now. No functional change intended; a follow-up may implement things further. gcc/cp/ChangeLog: * parser.cc: Include "analyzer/analyzer-language.h". (ana::cp_translation_unit): New class. (cp_parser_translation_unit): Add call to ana::on_finish_translation_unit. Signed-off-by: David Malcolm Diff: --- gcc/cp/parser.cc | 40 1 file changed, 40 insertions(+) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index e165b2a0b1b3..1fb9e7fd8729 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see #include "contracts.h" #include "bitmap.h" #include "builtins.h" +#include "analyzer/analyzer-language.h" /* The lexer. */ @@ -286,6 +287,37 @@ static FILE *cp_lexer_debug_stream; sizeof, typeof, or alignof. */ int cp_unevaluated_operand; +#if ENABLE_ANALYZER + +namespace ana { + +/* Concrete implementation of ana::translation_unit for the C++ frontend. */ + +class cp_translation_unit : public translation_unit +{ +public: + tree lookup_constant_by_id (tree /*id*/) const final override + { +return NULL_TREE; + } + + tree + lookup_type_by_id (tree /*id*/) const final override + { +return NULL_TREE; + } + + tree + lookup_global_var_by_id (tree /*id*/) const final override + { +return NULL_TREE; + } +}; + +} // namespace ana + +#endif /* #if ENABLE_ANALYZER */ + /* Dump up to NUM tokens in BUFFER to FILE starting with token START_TOKEN. If START_TOKEN is NULL, the dump starts with the first token in BUFFER. If NUM is 0, dump all the tokens. If @@ -5471,6 +5503,14 @@ cp_parser_translation_unit (cp_parser* parser) cp_parser_toplevel_declaration (parser); } +#if ENABLE_ANALYZER + if (flag_analyzer) +{ + ana::cp_translation_unit tu; + ana::on_finish_translation_unit (tu); +} +#endif + /* Get rid of the token array; we don't need it any more. */ cp_lexer_destroy (parser->lexer); parser->lexer = NULL;
[gcc r16-245] Infer non-zero for integral division RHS.
https://gcc.gnu.org/g:9a467c2ceaa680a3b54a7bc20e6bb6c3f8a47004 commit r16-245-g9a467c2ceaa680a3b54a7bc20e6bb6c3f8a47004 Author: Andrew MacLeod Date: Tue Jan 21 11:49:12 2025 -0500 Infer non-zero for integral division RHS. Adding op2_range for operator_div allows ranger to notice the divisor is non-zero after execution. PR tree-optimization/95801 gcc/ * range-op.cc (operator_div::op2_range): New. gcc/testsuite/ * gcc.dg/tree-ssa/pr95801.c: New. Diff: --- gcc/range-op.cc | 16 gcc/testsuite/gcc.dg/tree-ssa/pr95801.c | 13 + 2 files changed, 29 insertions(+) diff --git a/gcc/range-op.cc b/gcc/range-op.cc index f72b4ae92cfd..5c0bcdc3b37d 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -2415,8 +2415,11 @@ operator_widen_mult_unsigned::wi_fold (irange &r, tree type, class operator_div : public cross_product_operator { using range_operator::update_bitmask; + using range_operator::op2_range; public: operator_div (tree_code div_kind) { m_code = div_kind; } + bool op2_range (irange &r, tree type, const irange &lhs, const irange &, + relation_trio) const; virtual void wi_fold (irange &r, tree type, const wide_int &lh_lb, const wide_int &lh_ub, @@ -2436,6 +2439,19 @@ static operator_div op_floor_div (FLOOR_DIV_EXPR); static operator_div op_round_div (ROUND_DIV_EXPR); static operator_div op_ceil_div (CEIL_DIV_EXPR); +// Set OP2 to non-zero if the LHS isn't UNDEFINED. +bool +operator_div::op2_range (irange &r, tree type, const irange &lhs, +const irange &, relation_trio) const +{ + if (!lhs.undefined_p ()) +{ + r.set_nonzero (type); + return true; +} + return false; +} + bool operator_div::wi_op_overflows (wide_int &res, tree type, const wide_int &w0, const wide_int &w1) const diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr95801.c b/gcc/testsuite/gcc.dg/tree-ssa/pr95801.c new file mode 100644 index ..c3c80a045cf6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr95801.c @@ -0,0 +1,13 @@ +// { dg-do compile } +// { dg-options "-O2 -fdump-tree-evrp" } + +int always1(int a, int b) { +if (a / b) +return b != 0; +return 1; +} + +// If b != 0 is optimized by recognizing divide by 0 cannot happen, +// there should be no PHI node. + +// { dg-final { scan-tree-dump-not "PHI" "evrp" } }
[gcc r16-244] Always reflect lower bits from mask in subranges.
https://gcc.gnu.org/g:ce489c870bf28e5e3ffd5fe6730727d1ea942b3f commit r16-244-gce489c870bf28e5e3ffd5fe6730727d1ea942b3f Author: Andrew MacLeod Date: Mon Apr 14 16:25:15 2025 -0400 Always reflect lower bits from mask in subranges. During intersection, we expand the subranges to exclude the lower values from a bitmask with trailing zeros. This leads to inconsistant evaluations and in this case of this PR, that lead to an infinite cycle. Always expand the lower subranges in set_range_from_bitmask instead. PR tree-optimization/119712 gcc/ * value-range.cc (range_bitmask::adjust_range): Delete. (irange::set_range_from_bitmask): Integrate adjust_range. (irange::update_bitmask): Do nothing if bitmask doesnt change. (irange:intersect_bitmask): Do not call adjust_range. Exit if there is no second bitmask. * value-range.h (adjust_range): Remove prototype. gcc/testsuite/ * gcc.dg/pr119712.c: New. * gcc.dg/pr83072-2.c: Adjust. * gcc.dg/tree-ssa/phi-opt-value-5.c: Adjust. * gcc.dg/tree-ssa/vrp122.c: Adjust Diff: --- gcc/testsuite/gcc.dg/pr119712.c | 27 +++ gcc/testsuite/gcc.dg/pr83072-2.c| 2 +- gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-5.c | 4 +- gcc/testsuite/gcc.dg/tree-ssa/vrp122.c | 4 +- gcc/value-range.cc | 64 - gcc/value-range.h | 1 - 6 files changed, 61 insertions(+), 41 deletions(-) diff --git a/gcc/testsuite/gcc.dg/pr119712.c b/gcc/testsuite/gcc.dg/pr119712.c new file mode 100644 index ..e845dd9ce55a --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr119712.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +int a, b, c, d, e, f; +int main() { + f--; + goto q; +j: + if (-1642776935 * c + 7 >= 0) +goto l; +m: + if (4 * a - c - 21 >= 0) +goto i; + return 0; +i: + if (d) +goto l; +q: + c = 4 * c - 3; + if (c - f) + goto m; + goto j; +l: + e = b + 1958960196 * c - 1016458303; + if (20 * e + 1 >= 0) + return 0; + goto j; +} diff --git a/gcc/testsuite/gcc.dg/pr83072-2.c b/gcc/testsuite/gcc.dg/pr83072-2.c index dff6b50b717e..485e8041381e 100644 --- a/gcc/testsuite/gcc.dg/pr83072-2.c +++ b/gcc/testsuite/gcc.dg/pr83072-2.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-evrp-details" } */ +/* { dg-options "-O2 -fdump-tree-evrp-details -fno-tree-forwprop" } */ int f1(int a, int b, int c){ if(c==0)__builtin_unreachable(); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-5.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-5.c index 12ba475b24e2..ed8ee3ab72dc 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-5.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-5.c @@ -31,9 +31,7 @@ int fdiv1(int a, int b) return a != 0 ? c : 0; } -/* fdiv1 requires until later than phiopt2 to be able to detect that - d is non-zero. to be able to remove the conditional. */ -/* { dg-final { scan-tree-dump-times "goto" 2 "phiopt2" } } */ +/* { dg-final { scan-tree-dump-not "goto" "phiopt2" } } */ /* { dg-final { scan-tree-dump-not "goto" "phiopt3" } } */ /* { dg-final { scan-tree-dump-not "goto" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp122.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp122.c index 5a4ca850beec..def2b892bd6b 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp122.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp122.c @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-O2 -fdump-tree-evrp-details" } +// { dg-options "-O2 -fdump-tree-ccp1-details" } void gg(void); int f(unsigned t) @@ -16,4 +16,4 @@ int f(unsigned t) return 0; } -// { dg-final { scan-tree-dump "Global Exported: g_.* MASK 0x1 VALUE 0x0" "evrp" } } +// { dg-final { scan-tree-dump "Global Exported: g_.*MASK.*0 VALUE 0x0" "ccp1" } } diff --git a/gcc/value-range.cc b/gcc/value-range.cc index 5136674b361a..a770b41b474a 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -2251,37 +2251,9 @@ irange::invert () verify_range (); } -// Remove trailing ranges that this bitmask indicates can't exist. - -void -irange_bitmask::adjust_range (irange &r) const -{ - if (unknown_p () || r.undefined_p ()) -return; - - int_range_max range; - tree type = r.type (); - int prec = TYPE_PRECISION (type); - // If there are trailing zeros, create a range representing those bits. - gcc_checking_assert (m_mask != 0); - int z = wi::ctz (m_mask); - if (z) -{ - wide_int ub = (wi::one (prec) << z) - 1; - range = int_range<5> (type, wi::zero (prec), ub); - // Then remove the specific value these bits contain from the range. - wide_int va
[gcc r16-248] Add lhs_op1 relation to pointer_plus
https://gcc.gnu.org/g:a76b2602808cd5a49eb88b5f993f0072f1184bf6 commit r16-248-ga76b2602808cd5a49eb88b5f993f0072f1184bf6 Author: Andrew MacLeod Date: Tue Apr 22 10:36:26 2025 -0400 Add lhs_op1 relation to pointer_plus When prange was split from irange, the functionality of lhs_op1_relation did not get ported. This patch adds that functionality back, and is also good example of how to add new dispatch patterns to range-ops as lhs_op1_relation had no prange/prange/irange combination. * range-op-ptr.cc (range_operator::lhs_op1_relation): Add prange/prange/irange (PPI) default. (pointer_plus_operator::lhs_op1_relation): New. * range-op.cc (range_op_handler::lhs_op1_relation): Add RO_PPI case. * range-op.h (range_op_handler::lhs_op1_relation): Add prototype. Diff: --- gcc/range-op-ptr.cc | 59 + gcc/range-op.cc | 4 gcc/range-op.h | 4 3 files changed, 67 insertions(+) diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc index dd51c2e0c926..36e9dfc20baf 100644 --- a/gcc/range-op-ptr.cc +++ b/gcc/range-op-ptr.cc @@ -218,6 +218,15 @@ range_operator::lhs_op1_relation (const prange &lhs ATTRIBUTE_UNUSED, return VREL_VARYING; } +relation_kind +range_operator::lhs_op1_relation (const prange &lhs ATTRIBUTE_UNUSED, + const prange &op1 ATTRIBUTE_UNUSED, + const irange &op2 ATTRIBUTE_UNUSED, + relation_kind rel ATTRIBUTE_UNUSED) const +{ + return VREL_VARYING; +} + void range_operator::update_bitmask (irange &, const prange &, @@ -293,6 +302,7 @@ class pointer_plus_operator : public range_operator using range_operator::update_bitmask; using range_operator::fold_range; using range_operator::op2_range; + using range_operator::lhs_op1_relation; public: virtual bool fold_range (prange &r, tree type, const prange &op1, @@ -302,6 +312,10 @@ public: const prange &lhs, const prange &op1, relation_trio = TRIO_VARYING) const final override; + virtual relation_kind lhs_op1_relation (const prange &lhs, + const prange &op1, + const irange &op2, + relation_kind) const; void update_bitmask (prange &r, const prange &lh, const irange &rh) const { update_known_bitmask (r, POINTER_PLUS_EXPR, lh, rh); } } op_pointer_plus; @@ -379,6 +393,51 @@ pointer_plus_operator::op2_range (irange &r, tree type, return true; } +// Return the relation between the LHS and OP1 based on the value of the +// operand being added. Pointer_plus is define to have a size_type for +// operand 2 which can be interpreted as negative, so always used SIGNED. +// Any overflow is considered UB and thus ignored. + +relation_kind +pointer_plus_operator::lhs_op1_relation (const prange &lhs, +const prange &op1, +const irange &op2, +relation_kind) const +{ + if (lhs.undefined_p () || op1.undefined_p () || op2.undefined_p ()) +return VREL_VARYING; + + unsigned prec = TYPE_PRECISION (op2.type ()); + + // LHS = OP1 + 0 indicates LHS == OP1. + if (op2.zero_p ()) +return VREL_EQ; + + tree val; + // Only deal with singletons for now. + if (TYPE_OVERFLOW_UNDEFINED (lhs.type ()) && op2.singleton_p (&val)) +{ + // Always interpret VALUE as a signed value. Positive will increase + // the pointer value, and negative will decrease the poiinter value. + // It cannot be zero or the earlier zero_p () condition will catch it. + wide_int value = wi::to_wide (val); + + // Positive op2 means lhs > op1. + if (wi::gt_p (value, wi::zero (prec), SIGNED)) + return VREL_GT; + + // Negative op2 means lhs < op1. + if (wi::lt_p (value, wi::zero (prec), SIGNED)) + return VREL_LT; +} + + // If op2 does not contain 0, then LHS and OP1 can never be equal. + if (!range_includes_zero_p (op2)) +return VREL_NE; + + return VREL_VARYING; +} + bool operator_bitwise_or::fold_range (prange &r, tree type, const prange &op1, diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 5c0bcdc3b37d..35b3e18ebed2 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -390,6 +390,10 @@ range_op_handler::lhs_op1_relation (const vrange &lhs, return m_operator->lhs_op1_relation (as_a (lhs), as_a (op1), as_a (op2), rel); + case RO_PPI: + return m_operator->lhs_op1_relation (as_a (lhs), +as_
[gcc r16-246] Use the current cache when creating inferred ranges.
https://gcc.gnu.org/g:b37738ed3b6dc731fea7ac7882a903dc47af457f commit r16-246-gb37738ed3b6dc731fea7ac7882a903dc47af457f Author: Andrew MacLeod Date: Mon Mar 31 11:18:22 2025 -0400 Use the current cache when creating inferred ranges. Infer range processing was adjusted to allow a query to be specified, but during VRP folding, ranger was not providing a query. This results in contextual ranges being missed. Pass the cache in as the query which provide a read-only query of the current state. * gimple-range-cache.cc (ranger_cache::apply_inferred_ranges): Pass 'this' as the range-query to the inferred range constructor. Diff: --- gcc/gimple-range-cache.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc index 818b801468a0..ecf03319cd4e 100644 --- a/gcc/gimple-range-cache.cc +++ b/gcc/gimple-range-cache.cc @@ -1861,7 +1861,7 @@ ranger_cache::apply_inferred_ranges (gimple *s) bool update = true; basic_block bb = gimple_bb (s); - gimple_infer_range infer(s); + gimple_infer_range infer(s, this); if (infer.num () == 0) return;
[gcc r16-267] libstdc++: centralize and improve testing of shared_ptr/weak_ptr conversions
https://gcc.gnu.org/g:0416ac5ae0a97b09b8d4ab6617ae1c7802d2aa7f commit r16-267-g0416ac5ae0a97b09b8d4ab6617ae1c7802d2aa7f Author: Giuseppe D'Angelo Date: Sat Mar 15 16:04:45 2025 +0100 libstdc++: centralize and improve testing of shared_ptr/weak_ptr conversions Since the conversions are under the same constraints, centralize the test in one file instead of two, testing both smart pointer classes, to ease future maintenance. This is used right away: more tests are added. Amends r15-8048-gdf0e6509bf7442. libstdc++-v3/ChangeLog: * testsuite/20_util/shared_ptr/requirements/1.cc: Test both shared_ptr and weak_ptr. Add more tests. * testsuite/20_util/weak_ptr/requirements/1.cc: Removed as superseded by the other test. Signed-off-by: Giuseppe D'Angelo Diff: --- .../testsuite/20_util/shared_ptr/requirements/1.cc | 111 +++-- .../testsuite/20_util/weak_ptr/requirements/1.cc | 33 -- 2 files changed, 101 insertions(+), 43 deletions(-) diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/requirements/1.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/requirements/1.cc index 8ddb5d220ac7..19090d1e860a 100644 --- a/libstdc++-v3/testsuite/20_util/shared_ptr/requirements/1.cc +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/requirements/1.cc @@ -3,31 +3,122 @@ #include #include +#include using namespace __gnu_test; +template class SmartPtr> void test01() { - std::shared_ptr ptr; - std::shared_ptr ptr2 = ptr; + SmartPtr ptr; + SmartPtr ptr2 = ptr; #if __cpp_lib_shared_ptr_arrays >= 201611L - std::shared_ptr ptr_array; - std::shared_ptr ptr_array2 = ptr_array; - std::shared_ptr ptr_array3 = ptr_array; + SmartPtr ptr_array; + SmartPtr ptr_array2 = ptr_array; + SmartPtr ptr_array3 = ptr_array; #endif } +template class SmartPtr> void test02() { - std::shared_ptr ptr; - std::shared_ptr ptr2 = ptr; + SmartPtr ptr; + SmartPtr ptr2 = ptr; #if __cpp_lib_shared_ptr_arrays >= 201611L - std::shared_ptr ptr_array; - std::shared_ptr ptr_array2 = ptr_array; - std::shared_ptr ptr_array3 = ptr_array; + SmartPtr ptr_array; + SmartPtr ptr_array2 = ptr_array; + SmartPtr ptr_array3 = ptr_array; #endif } + +template class SmartPtr> +void +test03() +{ + static_assert( std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + static_assert( std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + static_assert( std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + static_assert( std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + + static_assert( std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + static_assert( std::is_convertible, SmartPtr>::value); + static_assert( std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + static_assert( std::is_convertible, SmartPtr>::value); + static_assert( std::is_convertible, SmartPtr>::value); + + static_assert(!std::is_convertible, SmartPtr>::value); + static_assert( std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + + static_assert(!std::is_convertible, SmartPtr>::value); + static_assert( std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + + static_assert(!std::is_convertible, SmartPtr>::value); + static_assert( std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + +#if __cpp_lib_shared_ptr_arrays >= 201611L + static_assert( std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + static_assert( std::is_convertible, SmartPtr>::value); + static_assert( std::is_convertible, SmartPtr>::value); + static_assert( std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + static_assert( std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + + static_assert( std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + static_assert( std::is_convertible, SmartPtr>::value); + static_assert( std::is_convertible, SmartPtr>::value); + static_assert( std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + static_assert( std::is_convertible, SmartPtr>::value); + static_assert(!std::is_convertible, SmartPtr>::value); + + static_assert( std::is_co
[gcc r14-11695] libstdc++: Implement LWG 4027 change to possibly-const-range [PR118083]
https://gcc.gnu.org/g:d4f5243c6f5c387d9c96783d36fa6eb103a8d9ee commit r14-11695-gd4f5243c6f5c387d9c96783d36fa6eb103a8d9ee Author: Patrick Palka Date: Tue Feb 25 13:35:04 2025 -0500 libstdc++: Implement LWG 4027 change to possibly-const-range [PR118083] LWG 4027 effectively makes the const range access CPOs ranges::cfoo behave more consistently across C++23 and C++20 (pre-P2278R4) and also more consistently with the std::cfoo range accessors, as the below testcase adjustments demonstrate (which mostly consist of reverting workarounds added by r14-3771-gf12e26f3496275 and r13-7186-g0d94c6df183375). In passing fix PR118083 which reports that the input_range constraint on possibly-const-range is missing in our implementation. A consequence of this is that the const range access CPOs now consistently reject a non-range argument, and so in some our of tests we need to introduce otherwise unused begin/end members. PR libstdc++/118083 libstdc++-v3/ChangeLog: * include/bits/ranges_base.h (ranges::__access::__possibly_const_range): Adjust logic as per LWG 4027. Add missing input_range constraint. * testsuite/std/ranges/access/cbegin.cc (test05): Verify LWG 4027 testcases. * testsuite/std/ranges/access/cdata.cc: Adjust, simplify and consolidate some tests after the above. * testsuite/std/ranges/access/cend.cc: Likewise. * testsuite/std/ranges/access/crbegin.cc: Likewise. * testsuite/std/ranges/access/crend.cc: Likewise. * testsuite/std/ranges/adaptors/join.cc: Likewise. * testsuite/std/ranges/adaptors/take_while.cc: Likewise. * testsuite/std/ranges/adaptors/transform.cc: Likewise. Reviewed-by: Jonathan Wakely (cherry picked from commit 1b9e4fe2ff5f4711406cdcf0e6e183b247d9f42b) Diff: --- libstdc++-v3/include/bits/ranges_base.h| 4 +- libstdc++-v3/testsuite/std/ranges/access/cbegin.cc | 17 + libstdc++-v3/testsuite/std/ranges/access/cdata.cc | 21 ++- libstdc++-v3/testsuite/std/ranges/access/cend.cc | 30 ++- .../testsuite/std/ranges/access/crbegin.cc | 43 +- libstdc++-v3/testsuite/std/ranges/access/crend.cc | 20 ++ libstdc++-v3/testsuite/std/ranges/adaptors/join.cc | 8 ++-- .../testsuite/std/ranges/adaptors/take_while.cc| 2 - .../testsuite/std/ranges/adaptors/transform.cc | 4 -- 9 files changed, 59 insertions(+), 90 deletions(-) diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index 937fbbae12eb..481d9bb5c5d5 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -631,11 +631,11 @@ namespace ranges namespace __access { #if __glibcxx_ranges_as_const // >= C++23 -template +template constexpr auto& __possibly_const_range(_Range& __r) noexcept { - if constexpr (constant_range && !constant_range<_Range>) + if constexpr (input_range) return const_cast(__r); else return __r; diff --git a/libstdc++-v3/testsuite/std/ranges/access/cbegin.cc b/libstdc++-v3/testsuite/std/ranges/access/cbegin.cc index 9f393be38df6..7b37487bb797 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/cbegin.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/cbegin.cc @@ -116,10 +116,27 @@ test04() VERIFY(std::ranges::cbegin(std::move(c)) == std::ranges::begin(c)); } +void +test05() +{ + // LWG 4027 - possibly-const-range should prefer returning const R& + auto r = std::views::single(0) +| std::views::transform([](int) { return 0; }); + using C1 = decltype(std::ranges::cbegin(r)); + using C1 = decltype(std::cbegin(r)); + + [] (auto x) { +auto r = std::views::single(x) | std::views::lazy_split(0); +static_assert(!requires { (*std::ranges::cbegin(r)).front() = 42; }); +static_assert(!requires { (*std::cbegin(r)).front() = 42; }); + }(0); +} + int main() { test01(); test03(); test04(); + test05(); } diff --git a/libstdc++-v3/testsuite/std/ranges/access/cdata.cc b/libstdc++-v3/testsuite/std/ranges/access/cdata.cc index db708654af32..150f88434ea5 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/cdata.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/cdata.cc @@ -34,20 +34,21 @@ test01() { int i = 0; int j = 0; + +#if __cpp_lib_ranges_as_const +// These overloads mean that range and range are satisfied. +const int* begin() const { throw; } +const int* end() const { throw; } +#endif + int* data() { return &j; } const R* data() const noexcept { return nullptr; } }; static_assert( has_cdata ); static_assert( has_cdata ); R r; -#if ! __cpp_lib_ranges_as_const VERIFY( std::ranges::cdata(r) == (R*)nullptr ); static_assert( noexcept(std::range
[gcc r14-11694] c++: prev declared hidden tmpl friend inst, cont [PR119807]
https://gcc.gnu.org/g:d3cb17bed3a61a2d45ff6142bbabc633a334dc2f commit r14-11694-gd3cb17bed3a61a2d45ff6142bbabc633a334dc2f Author: Patrick Palka Date: Tue Apr 15 09:06:40 2025 -0400 c++: prev declared hidden tmpl friend inst, cont [PR119807] When remapping existing specializations of a hidden template friend from a previous declaration to the new definition, we must remap only those specializations that match this new definition, but currently we remap all specializations (since they all appear in the same DECL_TEMPLATE_INSTANTIATIONS list of the most general template). Concretely, in the first testcase below, we form two specializations of the friend A::f, one with arguments {{0},{bool}} and another with arguments {{1},{bool}}. Later when instantiating B, we need to remap these specializations. During the B<0> instantiation we only want to remap the first specialization, and during the B<1> instantiation only the second specialization, but currently we remap both specializations twice. tsubst_friend_function needs to determine if an existing specialization matches the shape of the new definition, which is tricky in general, e.g. if the outer template parameters may not match up. Fortunately we don't have to reinvent the wheel here since is_specialization_of_friend seems to do exactly what we need. We can check this unconditionally, but I think it's only necessary when dealing with specializations formed from a class template scope previous declaration, hence the TMPL_ARGS_HAVE_MULTIPLE_LEVELS check. PR c++/119807 PR c++/112288 gcc/cp/ChangeLog: * pt.cc (tsubst_friend_function): Skip remapping an existing specialization if it doesn't match the shape of the new friend definition. gcc/testsuite/ChangeLog: * g++.dg/template/friend86.C: New test. * g++.dg/template/friend87.C: New test. Reviewed-by: Jason Merrill (cherry picked from commit 369461d0749790f1291f76096064d583d2547934) Diff: --- gcc/cp/pt.cc | 4 +++ gcc/testsuite/g++.dg/template/friend86.C | 25 +++ gcc/testsuite/g++.dg/template/friend87.C | 42 3 files changed, 71 insertions(+) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 26b9df941795..b2b2fdca956a 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -11634,6 +11634,10 @@ tsubst_friend_function (tree decl, tree args) elt.args = DECL_TI_ARGS (spec); elt.spec = NULL_TREE; + if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (DECL_TI_ARGS (spec)) + && !is_specialization_of_friend (spec, new_template)) + continue; + decl_specializations->remove_elt (&elt); tree& spec_args = DECL_TI_ARGS (spec); diff --git a/gcc/testsuite/g++.dg/template/friend86.C b/gcc/testsuite/g++.dg/template/friend86.C new file mode 100644 index ..9e2c1afb351c --- /dev/null +++ b/gcc/testsuite/g++.dg/template/friend86.C @@ -0,0 +1,25 @@ +// PR c++/119807 +// { dg-do run } + +template +struct A { + template friend int f(A, T); +}; + +template struct A<0>; +template struct A<1>; + +int main() { + A<0> x; + A<1> y; + if (f(x, true) != 0) __builtin_abort(); + if (f(y, true) != 1) __builtin_abort(); +} + +template +struct B { + template friend int f(A, T) { return N; } +}; + +template struct B<0>; +template struct B<1>; diff --git a/gcc/testsuite/g++.dg/template/friend87.C b/gcc/testsuite/g++.dg/template/friend87.C new file mode 100644 index ..94c0dfc52924 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/friend87.C @@ -0,0 +1,42 @@ +// PR c++/119807 +// { dg-do compile { target c++20 } } + +using size_t = decltype(sizeof(0)); + +template +struct CounterReader { + template + friend auto counterFlag(CounterReader) noexcept; +}; + +template +struct CounterWriter { + static constexpr size_t value = current; + + template + friend auto counterFlag(CounterReader) noexcept {} +}; + +template +[[nodiscard]] constexpr size_t counterAdvance() noexcept { + if constexpr (!mask) { + return CounterWriter::value; + } else if constexpr (requires { counterFlag(CounterReader()); }) { + return counterAdvance> 1)>(); + } + else { + return counterAdvance> 1)>(); + } +} + +constexpr auto defaultCounterTag = [] {}; + +template +constexpr size_t counter() noexcept { + return counterAdvance(); +} + +int main() { + static_assert(counter() == 1); + static_assert(counter() == 2); +}
[gcc r14-11696] libstdc++: Add code comment documenting LWG 4027 change [PR118083]
https://gcc.gnu.org/g:d03c58584da3c440cc9103d6a69f6c36f16f6e97 commit r14-11696-gd03c58584da3c440cc9103d6a69f6c36f16f6e97 Author: Patrick Palka Date: Wed Feb 26 14:51:38 2025 -0500 libstdc++: Add code comment documenting LWG 4027 change [PR118083] PR libstdc++/118083 libstdc++-v3/ChangeLog: * include/bits/ranges_base.h (ranges::__access::__possibly_const_range): Mention LWG 4027. (cherry picked from commit 640697f7c2def415db81c84010ae25be0785d867) Diff: --- libstdc++-v3/include/bits/ranges_base.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index 481d9bb5c5d5..eafd982f48e2 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -635,6 +635,8 @@ namespace ranges constexpr auto& __possibly_const_range(_Range& __r) noexcept { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4027. possibly-const-range should prefer returning const R& if constexpr (input_range) return const_cast(__r); else
[gcc r14-11697] libstdc++: Improve optional's <=> constraint recursion workaround [PR104606]
https://gcc.gnu.org/g:d23d35d3b76aa2ca124e580908f56f4b249cfe3a commit r14-11697-gd23d35d3b76aa2ca124e580908f56f4b249cfe3a Author: Patrick Palka Date: Fri Feb 28 10:15:45 2025 -0500 libstdc++: Improve optional's <=> constraint recursion workaround [PR104606] It turns out the reason the behavior of this testcase changed after CWG 2369 is because validity of the substituted return type is now checked later, after constraints. So a more reliable workaround for this issue is to add a constraint to check the validity of the return type earlier, matching the pre-CWG 2369 semantics. PR libstdc++/104606 libstdc++-v3/ChangeLog: * include/std/optional (operator<=>): Revert r14-9771 change. Add constraint checking the validity of the return type compare_three_way_result_t before the three_way_comparable_with constraint. Reviewed-by: Jonathan Wakely (cherry picked from commit 815f1f27a1dba2f0acd1f02d0beafedadebe967c) Diff: --- libstdc++-v3/include/std/optional | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional index 3507c36a4d82..1c37c8c5ac81 100644 --- a/libstdc++-v3/include/std/optional +++ b/libstdc++-v3/include/std/optional @@ -1430,7 +1430,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #ifdef __cpp_lib_three_way_comparison template requires (!__is_optional_v<_Up>) - && three_way_comparable_with<_Up, _Tp> + && requires { typename compare_three_way_result_t<_Tp, _Up>; } + && three_way_comparable_with<_Tp, _Up> constexpr compare_three_way_result_t<_Tp, _Up> operator<=>(const optional<_Tp>& __x, const _Up& __v) { return bool(__x) ? *__x <=> __v : strong_ordering::less; }
[gcc r14-11689] aarch64: force operand to fresh register to avoid subreg issues [PR118892]
https://gcc.gnu.org/g:9ce381170ed40874230db05111f8837475634e4b commit r14-11689-g9ce381170ed40874230db05111f8837475634e4b Author: Tamar Christina Date: Mon Apr 28 12:58:37 2025 +0100 aarch64: force operand to fresh register to avoid subreg issues [PR118892] When the input is already a subreg and we try to make a paradoxical subreg out of it for copysign this can fail if it violates the subreg relationship. Use force_lowpart_subreg instead of lowpart_subreg to then force the results to a register instead of ICEing. gcc/ChangeLog: PR target/118892 * config/aarch64/aarch64.md (copysign3): Use force_lowpart_subreg instead of lowpart_subreg. gcc/testsuite/ChangeLog: PR target/118892 * gcc.target/aarch64/copysign-pr118892.c: New test. Diff: --- gcc/config/aarch64/aarch64.md| 2 +- gcc/testsuite/gcc.target/aarch64/copysign-pr118892.c | 11 +++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 95577b325cef..6a481059bf08 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -7210,7 +7210,7 @@ emit_insn (gen_iorv23 ( lowpart_subreg (V2mode, operands[0], mode), - lowpart_subreg (V2mode, operands[1], mode), + force_lowpart_subreg (V2mode, operands[1], mode), v_bitmask)); DONE; } diff --git a/gcc/testsuite/gcc.target/aarch64/copysign-pr118892.c b/gcc/testsuite/gcc.target/aarch64/copysign-pr118892.c new file mode 100644 index ..adfa30dc3e2d --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/copysign-pr118892.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-Ofast" } */ + +double l(); +double f() +{ + double t6[2] = {l(), l()}; + double t7[2]; + __builtin_memcpy(&t7, &t6, sizeof(t6)); + return -__builtin_fabs(t7[1]); +}
[gcc r14-11690] middle-end: fix masking for partial vectors and early break [PR119351]
https://gcc.gnu.org/g:8f4df0d836f2618933f2a3e0f14a478af52aec37 commit r14-11690-g8f4df0d836f2618933f2a3e0f14a478af52aec37 Author: Tamar Christina Date: Mon Apr 28 12:59:54 2025 +0100 middle-end: fix masking for partial vectors and early break [PR119351] The following testcase shows an incorrect masked codegen: #define N 512 #define START 1 #define END 505 int x[N] __attribute__((aligned(32))); int __attribute__((noipa)) foo (void) { int z = 0; for (unsigned int i = START; i < END; ++i) { z++; if (x[i] > 0) continue; return z; } return -1; } notice how there's a continue there instead of a break. This means we generate a control flow where success stays within the loop iteration: mask_patt_9.12_46 = vect__1.11_45 > { 0, 0, 0, 0 }; vec_mask_and_47 = mask_patt_9.12_46 & loop_mask_41; if (vec_mask_and_47 == { -1, -1, -1, -1 }) goto ; [41.48%] else goto ; [58.52%] However when loop_mask_41 is a partial mask this comparison can lead to an incorrect match. In this case the mask is: # loop_mask_41 = PHI due to peeling for alignment with masking and compiling with -msve-vector-bits=128. At codegen time we generate: ptrue p15.s, vl4 ptrue p7.b, vl1 not p7.b, p15/z, p7.b .L5: ld1wz29.s, p7/z, [x1, x0, lsl 2] cmpgt p7.s, p7/z, z29.s, #0 not p7.b, p15/z, p7.b ptest p15, p7.b b.none .L2 .. Here the basic blocks are rotated and a not is generated. But the generated not is unmasked (or predicated over an ALL true mask in this case). This has the unintended side-effect of flipping the results of the inactive lanes (which were zero'd by the cmpgt) into -1. Which then incorrectly causes us to not take the branch to .L2. This is happening because we're not comparing against the right value for the forall case. This patch gets rid of the forall case by rewriting the if(all(mask)) into if (!all(mask)) which is the same as if (any(~mask)) by negating the masks and flipping the branches. 1. For unmasked loops we simply reduce the ~mask. 2. For masked loops we reduce (~mask & loop_mask) which is the same as doing (mask & loop_mask) ^ loop_mask. For the above we now generate: .L5: ld1wz28.s, p7/z, [x1, x0, lsl 2] cmple p7.s, p7/z, z28.s, #0 ptest p15, p7.b b.none .L2 This fixes gromacs with > 1 OpenMP threads and improves performance. gcc/ChangeLog: PR tree-optimization/119351 * tree-vect-stmts.cc (vectorizable_early_exit): Mask both operands of the gcond for partial masking support. gcc/testsuite/ChangeLog: PR tree-optimization/119351 * gcc.target/aarch64/sve/pr119351.c: New test. * gcc.target/aarch64/sve/pr119351_run.c: New test. (cherry picked from commit 7cf5503e0af52f5b726da4274a148590c57a458a) Diff: --- gcc/testsuite/gcc.target/aarch64/sve/pr119351.c| 35 .../gcc.target/aarch64/sve/pr119351_run.c | 20 +++ gcc/tree-vect-stmts.cc | 64 ++ 3 files changed, 95 insertions(+), 24 deletions(-) diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr119351.c b/gcc/testsuite/gcc.target/aarch64/sve/pr119351.c new file mode 100644 index ..a5ad0bf2507c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pr119351.c @@ -0,0 +1,35 @@ +/* Fix for PR119351 alignment peeling with vectors and VLS. */ +/* { dg-do compile } */ +/* { dg-options "-Ofast -msve-vector-bits=256 --param aarch64-autovec-preference=2 -fdump-tree-vect-details" } */ +/* { dg-final { check-function-bodies "**" "" ""} } */ + +#define N 512 +#define START 0 +#define END 505 + +int x[N] __attribute__((aligned(32))); + +/* +** foo: +** ... +** orr p[0-9]+.b, p[0-9]+/z, p[0-9]+.b, p[0-9]+.b +** ... +*/ + +int __attribute__((noipa)) +foo (void) +{ + int z = 0; + for (unsigned short i = START; i < END; ++i) +{ + z++; + if (x[i] > 0) +continue; + + return z; +} + return -1; +} + +/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr119351_run.c b/gcc/testsuite/gcc.target/aarch64/sve/pr119351_run.c new file mode 100644 index ..e1838589f92b --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pr119351_run.c @@ -0,0 +1,20 @@ +/* Fix for PR119351 alignment peeling with vectors and VLS. */ +/* { dg-do run { target aarch64_sve_hw } } */ +/* { dg-options "-Ofast --param aarch64-au
[gcc r16-189] middle-end/80342 - genmatch optimize outer conversions
https://gcc.gnu.org/g:99aa410f5e0a722822698e765ca165e73ca4f637 commit r16-189-g99aa410f5e0a722822698e765ca165e73ca4f637 Author: Richard Biener Date: Tue Jan 21 13:50:26 2025 +0100 middle-end/80342 - genmatch optimize outer conversions The following improves genmatch generated code so we avoid more spurious SSA assignments to be pushed to the GIMPLE sequence or simplifications rejected when we're not supposed to produce any for outer and intermediate conversions. * genmatch.cc (::gen_transform): Add in_place parameter. Assert it isn't set in unexpected places. (possible_noop_convert): New. (expr::gen_transform): Support in_place and emit code to compute a child in-place when the operation is a conversion. (dt_simplify::gen_1): Arrange for an outermost conversion to be elided by generating the transform of the operand in-place. * match.pd (__real cepxi (x) -> cos (x)): Use single_use. Diff: --- gcc/genmatch.cc | 201 +++- gcc/match.pd| 10 +-- 2 files changed, 160 insertions(+), 51 deletions(-) diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc index 85bd77aa4cfc..c6097cd722bf 100644 --- a/gcc/genmatch.cc +++ b/gcc/genmatch.cc @@ -1485,7 +1485,7 @@ public: virtual void gen_transform (FILE *, int, const char *, bool, int, const char *, capture_info *, dt_operand ** = 0, - int = 0) + int = 0, const char * = nullptr) { gcc_unreachable (); } }; @@ -1538,8 +1538,8 @@ public: /* If non-zero, the group for optional handling. */ unsigned char opt_grp; void gen_transform (FILE *f, int, const char *, bool, int, - const char *, capture_info *, - dt_operand ** = 0, int = 0) override; + const char *, capture_info *, dt_operand ** = 0, + int = 0, const char * = nullptr) override; }; /* An operator that is represented by native C code. This is always @@ -1572,8 +1572,8 @@ public: /* The identifier replacement vector. */ vec ids; void gen_transform (FILE *f, int, const char *, bool, int, - const char *, capture_info *, - dt_operand ** = 0, int = 0) final override; + const char *, capture_info *, dt_operand ** = 0, + int = 0, const char * = nullptr) final override; }; /* A wrapper around another operand that captures its value. */ @@ -1593,8 +1593,8 @@ public: /* The captured value. */ operand *what; void gen_transform (FILE *f, int, const char *, bool, int, - const char *, capture_info *, - dt_operand ** = 0, int = 0) final override; + const char *, capture_info *, dt_operand ** = 0, + int = 0, const char * = nullptr) final override; }; /* if expression. */ @@ -3196,6 +3196,14 @@ is_conversion (id_base *op) || *op == VIEW_CONVERT_EXPR); } +bool +possible_noop_convert (id_base *op) +{ + return (*op == CONVERT_EXPR + || *op == NOP_EXPR + || *op == VIEW_CONVERT_EXPR); +} + /* Get the type to be used for generating operand POS of OP from the various sources. */ @@ -3249,7 +3257,7 @@ get_operand_type (id_base *op, unsigned pos, void expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple, int depth, const char *in_type, capture_info *cinfo, -dt_operand **indexes, int) +dt_operand **indexes, int, const char *in_place) { id_base *opr = operation; /* When we delay operator substituting during lowering of fors we @@ -3307,10 +3315,23 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple, if (!type) fatal_at (location, "cannot determine type of operand"); + bool child_in_place = (!in_place +&& gimple +&& possible_noop_convert (opr) +&& is_a (ops[0])); + fprintf_indent (f, indent, "{\n"); indent += 2; - fprintf_indent (f, indent, - "tree _o%d[%u], _r%d;\n", depth, ops.length (), depth); + if (child_in_place) +{ + fprintf_indent (f, indent, "tree _r%d;\n", depth); + fprintf_indent (f, indent, + "gimple_match_op tem_op (res_op->cond.any_else (), " + "ERROR_MARK, error_mark_node, 1);\n"); +} + else +fprintf_indent (f, indent, + "tree _o%d[%u], _r%d;\n", depth, ops.length (), depth); char op0type[64]; snprintf (op0type, sizeof (op0type), "TREE_TYPE (_o%d[0])", depth); for (unsigned i = 0; i < ops.length (); ++i) @@ -3322,7 +3343,8 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gi
[gcc r16-190] tree-optimization/119103 - missed overwidening detection for shift
https://gcc.gnu.org/g:6901d56fea2132389e9a7ae60b4d9731e6e3c65a commit r16-190-g6901d56fea2132389e9a7ae60b4d9731e6e3c65a Author: Richard Biener Date: Tue Mar 4 10:34:39 2025 +0100 tree-optimization/119103 - missed overwidening detection for shift When vectorizing a shift of u16 data by an amount that's known to be less than 16 we currently fail to emit a vector u16 shift. The first reason is that the promotion of the shift amount is hoisted only by PRE and that cannot preserve range info, the second reason is that pattern detection doesn't use range info when computing the precision required for an operation. The following addresses the first issue by making LIM hoist all expressions for the pass that runs right before PRE and the second issue by querying ranges for the shift amount. PR tree-optimization/119103 * tree-ssa-loop-im.cc (in_loop_pipeline): Globalize. (compute_invariantness): Override costing when we run right before PRE and PRE is enabled. (pass_lim::execute): Adjust. * tree-vect-patterns.cc (vect_determine_precisions_from_users): For variable shift amounts use range information. * gcc.target/i386/pr119103.c: New testcase. Diff: --- gcc/testsuite/gcc.target/i386/pr119103.c | 13 + gcc/tree-ssa-loop-im.cc | 10 -- gcc/tree-vect-patterns.cc| 26 +++--- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/gcc/testsuite/gcc.target/i386/pr119103.c b/gcc/testsuite/gcc.target/i386/pr119103.c new file mode 100644 index ..57210dc3bbe8 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr119103.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mavx2" } */ + +void lshift(unsigned short *x, unsigned char amount) +{ + if (amount > 15) +__builtin_unreachable(); + + for (int i = 0; i < 16; i++) +x[i] <<= amount; +} + +/* { dg-final { scan-assembler "vpsllw" } } */ diff --git a/gcc/tree-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc index 225964c62156..a3ca5af3e3e4 100644 --- a/gcc/tree-ssa-loop-im.cc +++ b/gcc/tree-ssa-loop-im.cc @@ -143,6 +143,8 @@ public: different modes. */ }; +static bool in_loop_pipeline; + /* We use six bits per loop in the ref->dep_loop bitmap to record the dep_kind x dep_state combinations. */ @@ -1239,7 +1241,11 @@ compute_invariantness (basic_block bb) lim_data->cost); } - if (lim_data->cost >= LIM_EXPENSIVE) + if (lim_data->cost >= LIM_EXPENSIVE + /* When we run before PRE and PRE is active hoist all expressions +since PRE would do so anyway and we can preserve range info +but PRE cannot. */ + || (flag_tree_pre && !in_loop_pipeline)) set_profitable_level (stmt); } } @@ -3759,7 +3765,7 @@ public: unsigned int pass_lim::execute (function *fun) { - bool in_loop_pipeline = scev_initialized_p (); + in_loop_pipeline = scev_initialized_p (); if (!in_loop_pipeline) loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS); diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc index 4f0a7ea162b9..ca19add83c05 100644 --- a/gcc/tree-vect-patterns.cc +++ b/gcc/tree-vect-patterns.cc @@ -6544,10 +6544,22 @@ vect_determine_precisions_from_users (stmt_vec_info stmt_info, gassign *stmt) case RSHIFT_EXPR: { tree shift = gimple_assign_rhs2 (stmt); - if (TREE_CODE (shift) != INTEGER_CST - || !wi::ltu_p (wi::to_widest (shift), precision)) + unsigned int min_const_shift, max_const_shift; + wide_int min_shift, max_shift; + if (TREE_CODE (shift) == SSA_NAME + && vect_get_range_info (shift, &min_shift, &max_shift) + && wi::ge_p (min_shift, 0, TYPE_SIGN (TREE_TYPE (shift))) + && wi::lt_p (max_shift, TYPE_PRECISION (type), +TYPE_SIGN (TREE_TYPE (shift + { + min_const_shift = min_shift.to_uhwi (); + max_const_shift = max_shift.to_uhwi (); + } + else if (TREE_CODE (shift) == INTEGER_CST +&& wi::ltu_p (wi::to_widest (shift), precision)) + min_const_shift = max_const_shift = TREE_INT_CST_LOW (shift); + else return; - unsigned int const_shift = TREE_INT_CST_LOW (shift); if (code == LSHIFT_EXPR) { /* Avoid creating an undefined shift. @@ -6559,16 +6571,16 @@ vect_determine_precisions_from_users (stmt_vec_info stmt_info, gassign *stmt) of vectorization. This sort of thing should really be handled before vectorization. */ operation_precision = MAX (stmt_info->min_output_precision, - const_shift + 1); + max_const_shift + 1);
[gcc r16-192] lto/113207 - make fld_type_variant more picky
https://gcc.gnu.org/g:83d7dcfc0e447daf93d3df824a37181a7964c2f0 commit r16-192-g83d7dcfc0e447daf93d3df824a37181a7964c2f0 Author: Richard Biener Date: Mon Feb 3 14:16:45 2025 +0100 lto/113207 - make fld_type_variant more picky The below adds additional verification to fld_type_variant that there's only one variant matching fld_type_variant_equal_p on the chain. The PR shows that variants built with build_qualified_type can be equal to others in that regard but not with regard to what build_qualified_type does. PR lto/113207 * ipa-free-lang-data.cc (fld_type_variant): Add extra checking. Diff: --- gcc/ipa-free-lang-data.cc | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gcc/ipa-free-lang-data.cc b/gcc/ipa-free-lang-data.cc index 2885975b4e08..8c4fb3c6b643 100644 --- a/gcc/ipa-free-lang-data.cc +++ b/gcc/ipa-free-lang-data.cc @@ -150,7 +150,12 @@ fld_type_variant (tree first, tree t, class free_lang_data_d *fld, return t; for (tree v = first; v; v = TYPE_NEXT_VARIANT (v)) if (fld_type_variant_equal_p (t, v, inner_type)) - return v; + { + if (flag_checking) + for (tree v2 = TYPE_NEXT_VARIANT (v); v2; v2 = TYPE_NEXT_VARIANT (v2)) + gcc_assert (!fld_type_variant_equal_p (t, v2, inner_type)); + return v; + } tree v = build_variant_type_copy (first); TYPE_READONLY (v) = TYPE_READONLY (t); TYPE_VOLATILE (v) = TYPE_VOLATILE (t);
[gcc r16-191] tree-optimization/119044 - predcom fails to preserve alias info
https://gcc.gnu.org/g:302d22f6ec4706459e12b6ca93e4ac4b5c3590e7 commit r16-191-g302d22f6ec4706459e12b6ca93e4ac4b5c3590e7 Author: Richard Biener Date: Thu Feb 27 14:51:44 2025 +0100 tree-optimization/119044 - predcom fails to preserve alias info Predictive commoning fails to preserve alias info for the refs it creates. The following adds this to see whether it fixes the observed regression in 436.cactusADM after r15-7665. PR tree-optimization/119044 * tree-predcom.cc (ref_at_iteration): Copy alias info from the original ref. Diff: --- gcc/tree-predcom.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gcc/tree-predcom.cc b/gcc/tree-predcom.cc index d45aa3857b9f..509d112a0a06 100644 --- a/gcc/tree-predcom.cc +++ b/gcc/tree-predcom.cc @@ -234,6 +234,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-affine.h" #include "builtins.h" #include "opts.h" +#include "tree-ssa-address.h" /* The maximum number of iterations between the considered memory references. */ @@ -1824,6 +1825,7 @@ ref_at_iteration (data_reference_p dr, int iter, tree type = build_aligned_type (TREE_TYPE (ref), get_object_alignment (ref)); ref = build2 (MEM_REF, type, addr, alias_ptr); + copy_ref_info (ref, DR_REF (dr)); if (ref_type) ref = build3 (ref_code, ref_type, ref, ref_op1, ref_op2); return ref;
[gcc/devel/omp/gcc-14] OpenMP, GCN: Add interop-hsa testcase
https://gcc.gnu.org/g:33e01148ab0ed5fba2a5ac380bbba2e90629d7fd commit 33e01148ab0ed5fba2a5ac380bbba2e90629d7fd Author: Andrew Stubbs Date: Thu Apr 24 16:50:08 2025 + OpenMP, GCN: Add interop-hsa testcase This testcase ensures that the interop HSA support is sufficient to run a kernel manually on the same device. libgomp/ChangeLog: * testsuite/libgomp.c/interop-hsa.c: New test. (cherry picked from commit 8d84ea28510054fbbb8a2b7441916bd75e29163f) Diff: --- libgomp/testsuite/libgomp.c/interop-hsa.c | 203 ++ 1 file changed, 203 insertions(+) diff --git a/libgomp/testsuite/libgomp.c/interop-hsa.c b/libgomp/testsuite/libgomp.c/interop-hsa.c new file mode 100644 index ..cf8bc90bb9c0 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/interop-hsa.c @@ -0,0 +1,203 @@ +/* { dg-additional-options "-ldl" } */ +/* { dg-require-effective-target offload_device_gcn } */ + +#include +#include +#include +#include +#include +#include +#include "../../../include/hsa.h" +#include "../../config/gcn/libgomp-gcn.h" + +#define STACKSIZE (100 * 1024) +#define HEAPSIZE (10 * 1024 * 1024) +#define ARENASIZE HEAPSIZE + +/* This code fragment must be optimized or else the host-fallback kernel has + * invalid ASM inserts. The rest of the file can be compiled safely at -O0. */ +#pragma omp declare target +uintptr_t __attribute__((optimize("O1"))) +get_kernel_ptr () +{ + uintptr_t val; + if (!omp_is_initial_device ()) +/* "main._omp_fn.0" is the name GCC gives the first OpenMP target + * region in the "main" function. + * The ".kd" suffix is added by the LLVM assembler when it creates the + * kernel meta-data, and this is what we need to launch a kernel. */ +asm ("s_getpc_b64 %0\n\t" +"s_add_u32 %L0, %L0, main._omp_fn.0.kd@rel32@lo+4\n\t" +"s_addc_u32 %H0, %H0, main._omp_fn.0.kd@rel32@hi+4" +: "=Sg"(val)); + return val; +} +#pragma omp end declare target + +int +main(int argc, char** argv) +{ + + /* Load the HSA runtime DLL. */ + void *hsalib = dlopen ("libhsa-runtime64.so.1", RTLD_LAZY); + assert (hsalib); + + hsa_status_t (*hsa_signal_create) (hsa_signal_value_t initial_value, +uint32_t num_consumers, +const hsa_agent_t *consumers, +hsa_signal_t *signal) += dlsym (hsalib, "hsa_signal_create"); + assert (hsa_signal_create); + + uint64_t (*hsa_queue_load_write_index_relaxed) (const hsa_queue_t *queue) += dlsym (hsalib, "hsa_queue_load_write_index_relaxed"); + assert (hsa_queue_load_write_index_relaxed); + + void (*hsa_signal_store_relaxed) (hsa_signal_t signal, + hsa_signal_value_t value) += dlsym (hsalib, "hsa_signal_store_relaxed"); + assert (hsa_signal_store_relaxed); + + hsa_signal_value_t (*hsa_signal_wait_relaxed) (hsa_signal_t signal, +hsa_signal_condition_t condition, +hsa_signal_value_t compare_value, +uint64_t timeout_hint, +hsa_wait_state_t wait_state_hint) += dlsym (hsalib, "hsa_signal_wait_relaxed"); + assert (hsa_signal_wait_relaxed); + + void (*hsa_queue_store_write_index_relaxed) (const hsa_queue_t *queue, + uint64_t value) += dlsym (hsalib, "hsa_queue_store_write_index_relaxed"); + assert (hsa_queue_store_write_index_relaxed); + + hsa_status_t (*hsa_signal_destroy) (hsa_signal_t signal) += dlsym (hsalib, "hsa_signal_destroy"); + assert (hsa_signal_destroy); + + /* Set up the device data environment. */ + int test_data_value = 0; +#pragma omp target enter data map(test_data_value) + + /* Get the interop details. */ + int device_num = omp_get_default_device(); + hsa_agent_t *gpu_agent; + hsa_queue_t *hsa_queue = NULL; + + omp_interop_t interop = omp_interop_none; +#pragma omp interop init(target, targetsync, prefer_type("hsa"): interop) device(device_num) + assert (interop != omp_interop_none); + + omp_interop_rc_t retcode; + omp_interop_fr_t fr = omp_get_interop_int (interop, omp_ipr_fr_id, &retcode); + assert (retcode == omp_irc_success); + assert (fr == omp_ifr_hsa); + + gpu_agent = omp_get_interop_ptr(interop, omp_ipr_device, &retcode); + assert (retcode == omp_irc_success); + + hsa_queue = omp_get_interop_ptr(interop, omp_ipr_targetsync, &retcode); + assert (retcode == omp_irc_success); + assert (hsa_queue); + + /* Call an offload kernel via OpenMP/libgomp. + * + * This kernel serves two purposes: + * 1) Lookup the device-side load-address of itself (thus avoiding the + * need to access the libgomp internals). + * 2) Count how many times it is called. + * We then call it once using OpenMP, and once manually, an
[gcc/devel/omp/gcc-14] libgomp.texi: Document supported OpenMP 'interop' types for nvptx and gcn
https://gcc.gnu.org/g:0572eb1918b4de3a27a24cf0a21c9b71aea7c5f7 commit 0572eb1918b4de3a27a24cf0a21c9b71aea7c5f7 Author: Tobias Burnus Date: Wed Mar 26 11:27:56 2025 +0100 libgomp.texi: Document supported OpenMP 'interop' types for nvptx and gcn Note that this commit also updates the API interface to OpenMP 6.0; while 5.1 and 5.2 use 'int *' for the the ret_code argument, OpenMP 6.0 changed this to omp_interop_rc_t *; this enum also exists in OpenMP 5.1. However, C++ does not like this change such that unless NULL is passed (i.e. the argument is ignored), OpenMP 5.x and 6.x are not compatible. Note that GCC's omp.h already follows OpenMP 6.0 and is now in sync with the documentation. libgomp/ChangeLog: * libgomp.texi (OpenMP 5.1): Add @ref to offload-target specifics for 'interop'. (OpenMP 6.0): Mark dispatch's interop clause as implemented. (omp_get_interop_int, omp_get_interop_str, omp_get_interop_ptr, omp_get_interop_type_desc): Add @ref to Offload-Target Specifics; change ret_code argument type to 'omp_interop_rc_t *'. (Offload-Target Specifics): Document the supported OpenMP interop foreign runtimes on AMD and Nvidia GPUs. (cherry picked from commit 2e7c1b589bc58be0e155098cf87d8535d41adeab) Diff: --- libgomp/libgomp.texi | 170 --- 1 file changed, 161 insertions(+), 9 deletions(-) diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi index e075cf1cfb98..42dabfc80562 100644 --- a/libgomp/libgomp.texi +++ b/libgomp/libgomp.texi @@ -313,7 +313,7 @@ The OpenMP 4.5 specification is fully supported. clauses @tab N @tab @item Indirect calls to the device version of a procedure or function in @code{target} regions @tab Y @tab -@item @code{interop} directive @tab N @tab +@item @code{interop} directive @tab Y @tab Cf. @ref{Offload-Target Specifics} @item @code{omp_interop_t} object support in runtime routines @tab Y @tab @item @code{nowait} clause in @code{taskwait} directive @tab Y @tab @item Extensions to the @code{atomic} directive @tab Y @tab @@ -516,7 +516,7 @@ Technical Report (TR) 12 is the second preview for OpenMP 6.0. @item Extension of @code{interop} operation of @code{append_args}, allowing all modifiers of the @code{init} clause @tab N @tab -@item @code{interop} clause to @code{dispatch} @tab N @tab +@item @code{interop} clause to @code{dispatch} @tab Y @tab @item @code{message} and @code{severity} clauses to @code{parallel} directive @tab N @tab @item @code{self} clause to @code{requires} directive @tab N @tab @@ -2945,7 +2945,7 @@ the initial device is unspecified. @item @emph{C/C++}: @multitable @columnfractions .20 .80 @item @emph{Prototype}: @tab @code{omp_intptr_t omp_get_interop_int(const omp_interop_t interop, - omp_interop_property_t property_id, int *ret_code)} + omp_interop_property_t property_id, omp_interop_rc_t *ret_code)} @end multitable @item @emph{Fortran}: @@ -2959,7 +2959,8 @@ the initial device is unspecified. @end multitable @item @emph{See also}: -@ref{omp_get_interop_ptr}, @ref{omp_get_interop_str}, @ref{omp_get_interop_rc_desc} +@ref{omp_get_interop_ptr}, @ref{omp_get_interop_str}, @ref{omp_get_interop_rc_desc}, +@ref{Offload-Target Specifics} @item @emph{Reference}: @uref{https://www.openmp.org, OpenMP specification v5.1}, Section 3.12.2, @@ -2990,7 +2991,7 @@ the initial device is unspecified. @item @emph{C/C++}: @multitable @columnfractions .20 .80 @item @emph{Prototype}: @tab @code{void *omp_get_interop_ptr(const omp_interop_t interop, - omp_interop_property_t property_id, int *ret_code)} + omp_interop_property_t property_id, omp_interop_rc_t *ret_code)} @end multitable @item @emph{Fortran}: @@ -3004,7 +3005,8 @@ the initial device is unspecified. @end multitable @item @emph{See also}: -@ref{omp_get_interop_int}, @ref{omp_get_interop_str}, @ref{omp_get_interop_rc_desc} +@ref{omp_get_interop_int}, @ref{omp_get_interop_str}, @ref{omp_get_interop_rc_desc}, +@ref{Offload-Target Specifics} @item @emph{Reference}: @uref{https://www.openmp.org, OpenMP specification v5.1}, Section 3.12.3, @@ -3034,7 +3036,7 @@ the initial device is unspecified. @item @emph{C/C++}: @multitable @columnfractions .20 .80 @item @emph{Prototype}: @tab @code{const char *omp_get_interop_str(const omp_interop_t interop, - omp_interop_property_t property_id, int *ret_code)} + omp_interop_property_t property_id, omp_interop_rc_t *ret_code)} @end multitable @item @emph{Fortran}: @@ -3048,7 +3050,8 @@ the initial device is unspecified. @end multitable @item @emph{See also}: -@ref{omp
[gcc/devel/omp/gcc-14] libgomp.texi: For HIP interop, mention cpp defines to set
https://gcc.gnu.org/g:fd91f571f6e986f84f09f35139ff0650caa669d6 commit fd91f571f6e986f84f09f35139ff0650caa669d6 Author: Tobias Burnus Date: Thu Apr 17 10:21:05 2025 +0200 libgomp.texi: For HIP interop, mention cpp defines to set The HIP header files recognize the used compiler, defaulting to either AMD or Nvidia/CUDA; thus, the alternative way of explicitly defining a macro is less prominently documented. With GCC, the user has to define the preprocessor macro manually. Hence, as a service to the user, mention __HIP_PLATFORM_AMD__ and __HIP_PLATFORM_NVIDIA__ in the interop documentation, even though it has only indirectly to do with GCC and its interop support. Note to commit-log readers, only: For Fortran, the hipfort modules can be used; when compiling the hipfort package (defaults to use gfortran), it generates the module (*.mod) files in include/hipfort/{amdgcn,nvidia}/ such that the choice is made by setting the respective include path. libgomp/ChangeLog: * libgomp.texi (gcn interop, nvptx interop): For HIP with C/C++, add a note about setting a preprocessor define. (cherry picked from commit 4bff3f0b89af9a9aad69b8f85859c0a3667533ae) Diff: --- libgomp/libgomp.texi | 6 ++ 1 file changed, 6 insertions(+) diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi index 42dabfc80562..32d651498afa 100644 --- a/libgomp/libgomp.texi +++ b/libgomp/libgomp.texi @@ -6828,6 +6828,9 @@ or string (str) data type, call @code{omp_get_interop_int}, Note that @code{device_num} is the OpenMP device number while @code{device} is the HIP device number or HSA device handle. +When using HIP with C and C++, the @code{__HIP_PLATFORM_AMD__} preprocessor +macro must be defined before including the HIP header files. + For the API routine call, add the prefix @code{omp_ipr_} to the property name; for instance: @smallexample @@ -6990,6 +6993,9 @@ or string (str) data type, call @code{omp_get_interop_int}, Note that @code{device_num} is the OpenMP device number while @code{device} is the CUDA, CUDA Driver, or HIP device number. +When using HIP with C and C++, the @code{__HIP_PLATFORM_NVIDIA__} preprocessor +macro must be defined before including the HIP header files. + For the API routine call, add the prefix @code{omp_ipr_} to the property name; for instance: @smallexample
[gcc r16-215] gccrs: Fix ICE when handling case of unknown field in HIR::FieldAccess
https://gcc.gnu.org/g:533c13aeb4a394853884f43ed43d53e4589108c5 commit r16-215-g533c13aeb4a394853884f43ed43d53e4589108c5 Author: Philip Herron Date: Thu Apr 17 13:50:55 2025 +0100 gccrs: Fix ICE when handling case of unknown field in HIR::FieldAccess We were wrongly adding the assertion that this must not be an enum but this is a pointless assertion we only care that there are variant in the ADT and if the field exists in the first variant. Fixes Rust-GCC#3581 gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): fix bad assertion gcc/testsuite/ChangeLog: * rust/compile/nonexistent-field.rs: fix bad error message * rust/compile/issue-3581-1.rs: New test. * rust/compile/issue-3581-2.rs: New test. Signed-off-by: Philip Herron Diff: --- gcc/rust/typecheck/rust-hir-type-check-expr.cc | 18 -- gcc/testsuite/rust/compile/issue-3581-1.rs | 12 gcc/testsuite/rust/compile/issue-3581-2.rs | 9 + gcc/testsuite/rust/compile/nonexistent-field.rs | 2 +- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index 7ddcebc731d7..cbf529a77eb9 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -1142,27 +1142,25 @@ TypeCheckExpr::visit (HIR::FieldAccessExpr &expr) bool is_valid_type = struct_base->get_kind () == TyTy::TypeKind::ADT; if (!is_valid_type) { - rust_error_at (expr.get_locus (), -"expected algebraic data type got: [%s]", -struct_base->as_string ().c_str ()); + rust_error_at (expr.get_locus (), "expected algebraic data type got %qs", +struct_base->get_name ().c_str ()); return; } TyTy::ADTType *adt = static_cast (struct_base); - rust_assert (!adt->is_enum ()); - rust_assert (adt->number_of_variants () == 1); - + rust_assert (adt->number_of_variants () > 0); TyTy::VariantDef *vaiant = adt->get_variants ().at (0); TyTy::StructFieldType *lookup = nullptr; bool found = vaiant->lookup_field (expr.get_field_name ().as_string (), &lookup, nullptr); - if (!found) + if (!found || adt->is_enum ()) { - rust_error_at (expr.get_locus (), ErrorCode::E0609, -"no field %qs on type %qs", + rich_location r (line_table, expr.get_locus ()); + r.add_range (expr.get_field_name ().get_locus ()); + rust_error_at (r, ErrorCode::E0609, "no field %qs on type %qs", expr.get_field_name ().as_string ().c_str (), -adt->as_string ().c_str ()); +adt->get_name ().c_str ()); return; } diff --git a/gcc/testsuite/rust/compile/issue-3581-1.rs b/gcc/testsuite/rust/compile/issue-3581-1.rs new file mode 100644 index ..eb2f5f033d50 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3581-1.rs @@ -0,0 +1,12 @@ +enum Foo { +Bar, +} + +struct Baz; + +fn main() { +Foo::Bar.a; +// { dg-error "no field .a. on type .Foo. .E0609." "" { target *-*-* } .-1 } +Baz.a; +// { dg-error "no field .a. on type .Baz. .E0609." "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/rust/compile/issue-3581-2.rs b/gcc/testsuite/rust/compile/issue-3581-2.rs new file mode 100644 index ..505978444652 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3581-2.rs @@ -0,0 +1,9 @@ +enum A { +X { inner: i32 }, +Y, +} + +pub fn test() { +let _ = A::Y.inner; +// { dg-error "no field .inner. on type .A. .E0609." "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/rust/compile/nonexistent-field.rs b/gcc/testsuite/rust/compile/nonexistent-field.rs index e20c49d3ebf4..9bcfb2fe84fb 100644 --- a/gcc/testsuite/rust/compile/nonexistent-field.rs +++ b/gcc/testsuite/rust/compile/nonexistent-field.rs @@ -6,7 +6,7 @@ fn main() { let s = StructWithFields { x: 0 }; s.foo; -// { dg-error "no field .foo. on type .StructWithFields.StructWithFields .x.u32... .E0609." "" { target *-*-* } .-1 } +// { dg-error "no field .foo. on type .StructWithFields. .E0609." "" { target *-*-* } .-1 } let numbers = (1, 2, 3); numbers.3;
[gcc r16-232] gccrs: Remove passing test from exclusion list
https://gcc.gnu.org/g:5fdce529993a4422010794620eba7c8a2e23d870 commit r16-232-g5fdce529993a4422010794620eba7c8a2e23d870 Author: Pierre-Emmanuel Patry Date: Sun Apr 6 19:54:06 2025 +0200 gccrs: Remove passing test from exclusion list gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove passing test from exclusion list. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/testsuite/rust/compile/nr2/exclude | 2 -- 1 file changed, 2 deletions(-) diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index 23f3b1bf62ca..fac66a7de2c1 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -1,7 +1,5 @@ canonical_paths1.rs issue-3315-2.rs -multiple_bindings1.rs -multiple_bindings2.rs privacy5.rs privacy8.rs pub_restricted_1.rs
[gcc r16-233] gccrs: Use specialized param visit function for params
https://gcc.gnu.org/g:f171589e748634e4c781ce64e4b3b2d667d17400 commit r16-233-gf171589e748634e4c781ce64e4b3b2d667d17400 Author: Pierre-Emmanuel Patry Date: Sat Apr 19 14:14:25 2025 +0200 gccrs: Use specialized param visit function for params This commit introduce a new public function to visit function parameters in the default visitor. It allows visitors derived from DefaultVisitor to override only a small part of the default visitor. gcc/rust/ChangeLog: * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit_function_params): Add specialized function to visit function parameters. (DefaultASTVisitor::visit): Remove parameter visit and call specialized function instead. * ast/rust-ast-visitor.h: Add function prototye. * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Remove function. (Late::visit_function_params): Override specialized visit function. * resolve/rust-late-name-resolver-2.0.h: Add overriden function prototype. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/rust/ast/rust-ast-visitor.cc| 12 -- gcc/rust/ast/rust-ast-visitor.h | 2 ++ gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 30 + gcc/rust/resolve/rust-late-name-resolver-2.0.h | 4 +++- 4 files changed, 20 insertions(+), 28 deletions(-) diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index 6862024354f2..87e7b86573ba 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -831,6 +831,13 @@ DefaultASTVisitor::visit (AST::UseDeclaration &use_decl) visit (use_decl.get_tree ()); } +void +DefaultASTVisitor::visit_function_params (AST::Function &function) +{ + for (auto ¶m : function.get_function_params ()) +visit (param); +} + void DefaultASTVisitor::visit (AST::Function &function) { @@ -839,8 +846,9 @@ DefaultASTVisitor::visit (AST::Function &function) visit (function.get_qualifiers ()); for (auto &generic : function.get_generic_params ()) visit (generic); - for (auto ¶m : function.get_function_params ()) -visit (param); + + visit_function_params (function); + if (function.has_return_type ()) visit (function.get_return_type ()); if (function.has_where_clause ()) diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index 6d243e7b063e..b1fc50465a1a 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -242,6 +242,8 @@ public: class DefaultASTVisitor : public ASTVisitor { public: + virtual void visit_function_params (AST::Function &function); + virtual void visit (AST::Crate &crate); virtual void visit (AST::Token &tok) override; diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index e26e4187b28f..6ec04229c8e7 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -266,34 +266,14 @@ Late::visit (AST::AltPattern &pattern) } void -Late::visit (AST::Function &function) +Late::visit_function_params (AST::Function &function) { - auto def_fn = [this, &function] () { -visit_outer_attrs (function); -visit (function.get_visibility ()); -visit (function.get_qualifiers ()); -for (auto &generic : function.get_generic_params ()) - visit (generic); - -// We only care about params -ctx.bindings.enter (BindingSource::Param); - -for (auto ¶m : function.get_function_params ()) - visit (param); - -ctx.bindings.exit (); - -// Back to regular visit + ctx.bindings.enter (BindingSource::Param); -if (function.has_return_type ()) - visit (function.get_return_type ()); -if (function.has_where_clause ()) - visit (function.get_where_clause ()); -if (function.has_body ()) - visit (*function.get_definition ()); - }; + for (auto ¶m : function.get_function_params ()) +visit (param); - ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn); + ctx.bindings.exit (); } void diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h index 9e2bfdefaad6..171d9bfe0f6e 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -37,6 +37,9 @@ public: void new_label (Identifier name, NodeId id); + // Specialized visit bits + void visit_function_params (AST::Function &function) override; + // some more label declarations void visit (AST::LetStmt &) override; // TODO: Do we need this? @@ -44,7 +47,6 @@ public: void visit (AST::IdentifierPattern &) override; void visit (AST::StructPatternFieldIdent &) override; void visit (AST::AltPattern &) override; - void visit (AST::Function &) override; void visit (AST:
[gcc r16-236] gccrs: Visit visibility in UseDeclaration
https://gcc.gnu.org/g:4ea730498d2685cf7675edf81496113fbbb95901 commit r16-236-g4ea730498d2685cf7675edf81496113fbbb95901 Author: Pierre-Emmanuel Patry Date: Mon Apr 28 13:05:49 2025 +0200 gccrs: Visit visibility in UseDeclaration Default visitor should visit all it's children. gcc/rust/ChangeLog: * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Visit visibility. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/rust/ast/rust-ast-visitor.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index dd42e39292f0..b6833f69314e 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -828,6 +828,7 @@ DefaultASTVisitor::visit (AST::UseTreeRebind &use_tree) void DefaultASTVisitor::visit (AST::UseDeclaration &use_decl) { + visit (use_decl.get_visibility ()); visit (use_decl.get_tree ()); }
[gcc/devel/omp/gcc-14] OpenMP: Silence uninitialized variable warning in C++ front end.
https://gcc.gnu.org/g:a9f1e49fa11de85cdc55ee22ea3c021157e07719 commit a9f1e49fa11de85cdc55ee22ea3c021157e07719 Author: Sandra Loosemore Date: Sat Feb 22 16:54:50 2025 + OpenMP: Silence uninitialized variable warning in C++ front end. There's no actual problem with the code here, just a false-positive warning emitted by some older GCC versions. gcc/cp/ChangeLog * parser.cc (cp_finish_omp_declare_variant): Initialize append_args_last. (cherry picked from commit c978965b445079abbb88c22ba74de1e26e9f5b81) Diff: --- gcc/cp/parser.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 2faf82ef12d4..747209fc77f1 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -51270,7 +51270,7 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, location_t varid_loc = make_location (caret_loc, start_loc, finish_loc); tree append_args_tree = NULL_TREE; - tree append_args_last; + tree append_args_last = NULL_TREE; bool has_match = false, has_adjust_args = false; location_t adjust_args_loc = UNKNOWN_LOCATION; location_t append_args_loc = UNKNOWN_LOCATION;
[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: prepare sbitmaps
https://gcc.gnu.org/g:7c51ab8bcf7707ef1f752a3fbd30f1f9edc9a2a3 commit 7c51ab8bcf7707ef1f752a3fbd30f1f9edc9a2a3 Author: Ondřej Machota Date: Mon Apr 28 20:41:18 2025 +0200 rtl-ssa-dce: prepare sbitmaps Diff: --- gcc/dce.cc | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/gcc/dce.cc b/gcc/dce.cc index e21f8bff8898..4f35875988cf 100644 --- a/gcc/dce.cc +++ b/gcc/dce.cc @@ -1511,6 +1511,7 @@ rtl_ssa_dce::mark_prelive_insn (insn_info *insn, auto_vec &worklist) if (dump_file) fprintf (dump_file, "Insn %d marked as prelive\n", insn->uid ()); + mm_marked.set_bit(insn->uid()); m_marked.emplace (insn); // debug instruction are not added to worklist not to wake up possibly dead // instructions @@ -1561,6 +1562,7 @@ rtl_ssa_dce::mark () continue; m_marked.emplace (insn); + mm_marked.set_bit(uid); use_array uses = insn->uses (); if (insn->is_phi ()) @@ -1571,6 +1573,7 @@ rtl_ssa_dce::mark () if (m_marked_phis.count (pi) > 0) continue; +mm_marked_phis.set_bit(pi_uid); m_marked_phis.emplace (pi); uses = pi->inputs (); } @@ -1742,7 +1745,8 @@ rtl_ssa_dce::propagate_dead_phis () if (dump_file) fprintf (dump_file, "Debug insns %d depends on dead phi.\n", insn->uid ()); - marked.erase (insn); + m_marked.erase (insn); +mm_marked.clear_bit(insn->uid()); // debug instructions dont have chains continue; } @@ -1750,12 +1754,12 @@ rtl_ssa_dce::propagate_dead_phis () // mark if (insn->is_phi ()) { - gcc_assert (marked_phis.count (static_cast (set)) == 0); + gcc_assert (m_marked_phis.count (static_cast (set)) == 0); visited_dead_phis.emplace (static_cast (set)); } else { - gcc_assert (marked.count (insn) == 0); + gcc_assert (m_marked.count (insn) == 0); depends_on_dead_phi.emplace (insn); }
[gcc r14-11691] c++: shortcut constexpr vector ctor [PR113835]
https://gcc.gnu.org/g:8dce1aa0579ab86a626e24c0af29455f30305595 commit r14-11691-g8dce1aa0579ab86a626e24c0af29455f30305595 Author: Jason Merrill Date: Sat Apr 12 11:35:18 2025 -0400 c++: shortcut constexpr vector ctor [PR113835] Since std::vector became usable in constant evaluation in C++20, a vector variable with static storage duration might be manifestly constant-evaluated, so we properly try to constant-evaluate its initializer. But it can never succeed since the result will always refer to the result of operator new, so trying is a waste of time. Potentially a large waste of time for a large vector, as in the testcase in the PR. So, let's recognize this case and skip trying constant-evaluation. I do this only for the case of an integer argument, as that's the case that's easy to write but slow to (fail to) evaluate. In the test, I use dg-timeout-factor to lower the default timeout from 300 seconds to 15; on my laptop, compilation without the patch takes about 20 seconds versus about 2 with the patch. is_std_class comes from r15-4953. PR c++/113835 gcc/cp/ChangeLog: * cp-tree.h (is_std_class): Declare. * constexpr.cc (is_std_class): New function. (is_std_allocator): Use it. (cxx_eval_outermost_constant_expr): Bail out early for std::vector(N). gcc/testsuite/ChangeLog: * g++.dg/cpp2a/constexpr-vector1.C: New test. (cherry picked from commit 764f02327f7b2dc6ac5abaf89038e51cf0ee6d13) Diff: --- gcc/cp/cp-tree.h | 1 + gcc/cp/constexpr.cc| 25 + gcc/testsuite/g++.dg/cpp2a/constexpr-vector1.C | 8 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index cfdfc4f9abe7..19e7b2edede3 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -8683,6 +8683,7 @@ extern bool is_rvalue_constant_expression (tree); extern bool is_nondependent_constant_expression (tree); extern bool is_nondependent_static_init_expression (tree); extern bool is_static_init_expression(tree); +extern bool is_std_class (tree, const char *); extern bool is_std_allocator (tree); extern bool potential_rvalue_constant_expression (tree); extern bool require_potential_constant_expression (tree); diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index e68202a5b5d9..6b8f6af00702 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -2356,22 +2356,30 @@ is_std_construct_at (const constexpr_call *call) && is_std_construct_at (call->fundef->decl)); } -/* True if CTX is an instance of std::allocator. */ +/* True if CTX is an instance of std::NAME class. */ bool -is_std_allocator (tree ctx) +is_std_class (tree ctx, const char *name) { if (ctx == NULL_TREE || !CLASS_TYPE_P (ctx) || !TYPE_MAIN_DECL (ctx)) return false; tree decl = TYPE_MAIN_DECL (ctx); - tree name = DECL_NAME (decl); - if (name == NULL_TREE || !id_equal (name, "allocator")) + tree dname = DECL_NAME (decl); + if (dname == NULL_TREE || !id_equal (dname, name)) return false; return decl_in_std_namespace_p (decl); } +/* True if CTX is an instance of std::allocator. */ + +bool +is_std_allocator (tree ctx) +{ + return is_std_class (ctx, "allocator"); +} + /* Return true if FNDECL is std::allocator::{,de}allocate. */ static inline bool @@ -8851,6 +8859,15 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, tree fndecl = cp_get_callee_fndecl_nofold (x); if (fndecl && DECL_IMMEDIATE_FUNCTION_P (fndecl)) is_consteval = true; + /* Don't try to evaluate a std::vector constructor taking an integer, it +will fail in the 'if (heap_var)' block below after doing all the work +(c++/113835). This will need adjustment if P3554 is accepted. Note +that evaluation of e.g. the vector default constructor can succeed, so +we don't shortcut all vector constructors. */ + if (fndecl && DECL_CONSTRUCTOR_P (fndecl) && allow_non_constant + && is_std_class (type, "vector") && call_expr_nargs (x) > 1 + && TREE_CODE (TREE_TYPE (get_nth_callarg (x, 1))) == INTEGER_TYPE) + return t; } } if (AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type)) diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-vector1.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-vector1.C new file mode 100644 index ..196c6ec51fcf --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-vector1.C @@ -0,0 +1,8 @@ +// PR c++/113835 +// { dg-timeout-factor 0.05 } +// { dg-do compile { target c++20_only } } + +#include +const std::size_t N = 1'000'000; +std::vector x(N); +int main() {}
[gcc r14-11692] c++: format attribute redeclaration [PR116954]
https://gcc.gnu.org/g:1e91580d64932dffa87831ef403f5fb7a41b6f12 commit r14-11692-g1e91580d64932dffa87831ef403f5fb7a41b6f12 Author: Jason Merrill Date: Wed Apr 16 11:15:14 2025 -0400 c++: format attribute redeclaration [PR116954] Here when merging the two decls, remove_contract_attributes loses ATTR_IS_DEPENDENT on the format attribute, so apply_late_template_attributes just returns, so the attribute doesn't get propagated to the type where the warning looks for it. Fixed by using copy_node instead of tree_cons to preserve flags. PR c++/116954 gcc/cp/ChangeLog: * contracts.cc (remove_contract_attributes): Preserve flags on the attribute list. gcc/testsuite/ChangeLog: * g++.dg/warn/Wformat-3.C: New test. (cherry picked from commit b0d7d644f3c25af9bf60c948ab26aa7b09a68787) Diff: --- gcc/cp/contracts.cc | 9 - gcc/testsuite/g++.dg/warn/Wformat-3.C | 19 +++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/gcc/cp/contracts.cc b/gcc/cp/contracts.cc index 634e3cf4fa9a..ff82ad772d06 100644 --- a/gcc/cp/contracts.cc +++ b/gcc/cp/contracts.cc @@ -870,10 +870,17 @@ cp_contract_assertion_p (const_tree attr) void remove_contract_attributes (tree fndecl) { + if (!flag_contracts) +return; + tree list = NULL_TREE; for (tree p = DECL_ATTRIBUTES (fndecl); p; p = TREE_CHAIN (p)) if (!cxx_contract_attribute_p (p)) - list = tree_cons (TREE_PURPOSE (p), TREE_VALUE (p), list); + { + tree nl = copy_node (p); + TREE_CHAIN (nl) = list; + list = nl; + } DECL_ATTRIBUTES (fndecl) = nreverse (list); } diff --git a/gcc/testsuite/g++.dg/warn/Wformat-3.C b/gcc/testsuite/g++.dg/warn/Wformat-3.C new file mode 100644 index ..e308530761c9 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wformat-3.C @@ -0,0 +1,19 @@ +// PR c++/116954 +// { dg-additional-options -Wformat } + +#ifndef WORKS +template +int fn(char (&buf)[N], const char fmt[], ...) + __attribute__ ((__format__ (__printf__, 2, 3))); +#endif + +template +__attribute__ ((__format__ (__printf__, 2, 3))) +int fn(char (&)[N], const char [], ...) +{ return 0; } + +int main() +{ + char buf[20]; + return fn(buf, "%s", 42); /* { dg-warning "Wformat" } */ +}