aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/ast/rust-path.h6
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-path.cc89
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.cc90
-rw-r--r--gcc/testsuite/rust/compile/self-path1.rs12
-rw-r--r--gcc/testsuite/rust/compile/self-path2.rs21
-rw-r--r--gcc/testsuite/rust/execute/torture/issue-1231.rs36
6 files changed, 188 insertions, 66 deletions
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index 36f1c04..c6485c0 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -50,6 +50,8 @@ public:
std::string as_string () const { return segment_name; }
+ Location get_locus () const { return locus; }
+
bool is_super_segment () const { return as_string ().compare ("super") == 0; }
bool is_crate_segment () const { return as_string ().compare ("crate") == 0; }
bool is_lower_self () const { return as_string ().compare ("self") == 0; }
@@ -691,6 +693,10 @@ public:
return get_ident_segment ().is_super_segment ();
}
bool is_big_self_seg () const { return get_ident_segment ().is_big_self (); }
+ bool is_lower_self_seg () const
+ {
+ return get_ident_segment ().is_lower_self ();
+ }
};
// Segment used in type path with generic args
diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc
index 3c69b65..9bd836a 100644
--- a/gcc/rust/resolve/rust-ast-resolve-path.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-path.cc
@@ -59,6 +59,18 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
bool is_first_segment = i == 0;
resolved_node_id = UNKNOWN_NODEID;
+ bool in_middle_of_path = i > 0;
+ if (in_middle_of_path && segment.is_lower_self_seg ())
+ {
+ // error[E0433]: failed to resolve: `self` in paths can only be used
+ // in start position
+ rust_error_at (segment.get_locus (),
+ "failed to resolve: %<%s%> in paths can only be used "
+ "in start position",
+ segment.as_string ().c_str ());
+ return;
+ }
+
NodeId crate_scope_id = resolver->peek_crate_module_scope ();
if (segment.is_crate_path_seg ())
{
@@ -118,7 +130,43 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
//
// can only use old resolution when previous segment is unkown
- if (previous_resolved_node_id == module_scope_id)
+ if (is_first_segment)
+ {
+ // name scope first
+ NodeId resolved_node = UNKNOWN_NODEID;
+ const CanonicalPath path
+ = CanonicalPath::new_seg (segment.get_node_id (),
+ ident_seg.as_string ());
+ if (resolver->get_name_scope ().lookup (path, &resolved_node))
+ {
+ resolver->insert_resolved_name (segment.get_node_id (),
+ resolved_node);
+ resolved_node_id = resolved_node;
+ }
+ // check the type scope
+ else if (resolver->get_type_scope ().lookup (path, &resolved_node))
+ {
+ resolver->insert_resolved_type (segment.get_node_id (),
+ resolved_node);
+ resolved_node_id = resolved_node;
+ }
+ else if (segment.is_lower_self_seg ())
+ {
+ module_scope_id = crate_scope_id;
+ previous_resolved_node_id = module_scope_id;
+ resolver->insert_resolved_name (segment.get_node_id (),
+ module_scope_id);
+ continue;
+ }
+ else
+ {
+ // no error handling here since we might be able to resolve via
+ // the module hierarchy and handle errors at the end
+ }
+ }
+
+ if (resolved_node_id == UNKNOWN_NODEID
+ && previous_resolved_node_id == module_scope_id)
{
Optional<CanonicalPath &> resolved_child
= mappings->lookup_module_child (module_scope_id,
@@ -150,36 +198,8 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
}
}
- if (resolved_node_id == UNKNOWN_NODEID && is_first_segment)
- {
- // name scope first
- NodeId resolved_node = UNKNOWN_NODEID;
- const CanonicalPath path
- = CanonicalPath::new_seg (segment.get_node_id (),
- ident_seg.as_string ());
- if (resolver->get_name_scope ().lookup (path, &resolved_node))
- {
- resolver->insert_resolved_name (segment.get_node_id (),
- resolved_node);
- }
- // check the type scope
- else if (resolver->get_type_scope ().lookup (path, &resolved_node))
- {
- resolver->insert_resolved_type (segment.get_node_id (),
- resolved_node);
- }
- else
- {
- rust_error_at (segment.get_locus (),
- "Cannot find path %<%s%> in this scope",
- segment.as_string ().c_str ());
- return;
- }
-
- resolved_node_id = resolved_node;
- }
-
- if (resolved_node_id != UNKNOWN_NODEID)
+ bool did_resolve_segment = resolved_node_id != UNKNOWN_NODEID;
+ if (did_resolve_segment)
{
if (mappings->node_is_module (resolved_node_id))
{
@@ -187,6 +207,13 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
}
previous_resolved_node_id = resolved_node_id;
}
+ else if (is_first_segment)
+ {
+ rust_error_at (segment.get_locus (),
+ "Cannot find path %<%s%> in this scope",
+ segment.as_string ().c_str ());
+ return;
+ }
}
resolved_node = resolved_node_id;
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc
index a823543..d444e37 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-type.cc
@@ -95,6 +95,18 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id)
bool is_first_segment = i == 0;
resolved_node_id = UNKNOWN_NODEID;
+ bool in_middle_of_path = i > 0;
+ if (in_middle_of_path && segment->is_lower_self_seg ())
+ {
+ // error[E0433]: failed to resolve: `self` in paths can only be used
+ // in start position
+ rust_error_at (segment->get_locus (),
+ "failed to resolve: %<%s%> in paths can only be used "
+ "in start position",
+ segment->as_string ().c_str ());
+ return false;
+ }
+
NodeId crate_scope_id = resolver->peek_crate_module_scope ();
if (segment->is_crate_path_seg ())
{
@@ -129,10 +141,7 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id)
= static_cast<AST::TypePathSegmentGeneric *> (segment.get ());
if (s->has_generic_args ())
{
- for (auto &gt : s->get_generic_args ().get_type_args ())
- {
- ResolveType::go (gt.get ());
- }
+ ResolveType::type_resolve_generic_args (s->get_generic_args ());
}
}
break;
@@ -146,8 +155,39 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id)
break;
}
- if (previous_resolved_node_id == module_scope_id
- && path.get_segments ().size () > 1)
+ if (is_first_segment)
+ {
+ // name scope first
+ NodeId resolved_node = UNKNOWN_NODEID;
+ const CanonicalPath path
+ = CanonicalPath::new_seg (segment->get_node_id (),
+ ident_seg.as_string ());
+ if (resolver->get_type_scope ().lookup (path, &resolved_node))
+ {
+ resolver->insert_resolved_type (segment->get_node_id (),
+ resolved_node);
+ resolved_node_id = resolved_node;
+ }
+ else if (resolver->get_name_scope ().lookup (path, &resolved_node))
+ {
+ resolver->insert_resolved_name (segment->get_node_id (),
+ resolved_node);
+ resolved_node_id = resolved_node;
+ }
+ else if (segment->is_lower_self_seg ())
+ {
+ // what is the current crate scope node id?
+ module_scope_id = crate_scope_id;
+ previous_resolved_node_id = module_scope_id;
+ resolver->insert_resolved_name (segment->get_node_id (),
+ module_scope_id);
+
+ continue;
+ }
+ }
+
+ if (resolved_node_id == UNKNOWN_NODEID
+ && previous_resolved_node_id == module_scope_id)
{
Optional<CanonicalPath &> resolved_child
= mappings->lookup_module_child (module_scope_id,
@@ -179,35 +219,8 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id)
}
}
- if (resolved_node_id == UNKNOWN_NODEID && is_first_segment)
- {
- // name scope first
- NodeId resolved_node = UNKNOWN_NODEID;
- const CanonicalPath path
- = CanonicalPath::new_seg (segment->get_node_id (),
- ident_seg.as_string ());
- if (resolver->get_type_scope ().lookup (path, &resolved_node))
- {
- resolver->insert_resolved_type (segment->get_node_id (),
- resolved_node);
- }
- else if (resolver->get_name_scope ().lookup (path, &resolved_node))
- {
- resolver->insert_resolved_name (segment->get_node_id (),
- resolved_node);
- }
- else
- {
- rust_error_at (segment->get_locus (),
- "failed to resolve TypePath: %s in this scope",
- segment->as_string ().c_str ());
- return false;
- }
-
- resolved_node_id = resolved_node;
- }
-
- if (resolved_node_id != UNKNOWN_NODEID)
+ bool did_resolve_segment = resolved_node_id != UNKNOWN_NODEID;
+ if (did_resolve_segment)
{
if (mappings->node_is_module (resolved_node_id))
{
@@ -215,6 +228,13 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id)
}
previous_resolved_node_id = resolved_node_id;
}
+ else if (is_first_segment)
+ {
+ rust_error_at (segment->get_locus (),
+ "failed to resolve TypePath: %s in this scope",
+ segment->as_string ().c_str ());
+ return false;
+ }
}
if (resolved_node_id != UNKNOWN_NODEID)
diff --git a/gcc/testsuite/rust/compile/self-path1.rs b/gcc/testsuite/rust/compile/self-path1.rs
new file mode 100644
index 0000000..425ba84
--- /dev/null
+++ b/gcc/testsuite/rust/compile/self-path1.rs
@@ -0,0 +1,12 @@
+// { dg-additional-options "-w" }
+struct foo;
+
+fn bar() -> self::foo {
+ crate::foo
+}
+
+fn baz() {
+ let a: foo = self::bar();
+
+ crate::bar();
+}
diff --git a/gcc/testsuite/rust/compile/self-path2.rs b/gcc/testsuite/rust/compile/self-path2.rs
new file mode 100644
index 0000000..b9b82ca
--- /dev/null
+++ b/gcc/testsuite/rust/compile/self-path2.rs
@@ -0,0 +1,21 @@
+// { dg-additional-options "-w" }
+struct foo;
+
+fn bar() -> self::foo {
+ crate::foo
+}
+
+fn baz() {
+ let a: foo = self::bar();
+
+ crate::bar();
+
+ crate::self::foo();
+ // { dg-error "failed to resolve: .self. in paths can only be used in start position" "" { target *-*-* } .-1 }
+}
+
+type a = foo;
+type b = crate::foo;
+type c = self::foo;
+type d = crate::self::foo;
+// { dg-error "failed to resolve: .self. in paths can only be used in start position" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/rust/execute/torture/issue-1231.rs b/gcc/testsuite/rust/execute/torture/issue-1231.rs
new file mode 100644
index 0000000..970e86f
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1231.rs
@@ -0,0 +1,36 @@
+// { dg-additional-options "-w" }
+// { dg-output "outer\ninner\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn machin() {
+ unsafe {
+ let a = "outer\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, 123);
+ }
+}
+
+fn bidule() {
+ fn machin() {
+ unsafe {
+ let a = "inner\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, 123);
+ }
+ }
+
+ self::machin();
+ machin();
+}
+
+fn main() -> i32 {
+ bidule();
+
+ 0
+}