From: Pierre-Emmanuel Patry <[email protected]>
Attribute have always been a bit weird, they were part of the AST but did
not have any visitor function, this create a lot of friction around them
as their input which may be an expression, a literal and even an
expression in the future didn't get visited properly during the different
passes of the compiler.
gcc/rust/ChangeLog:
* ast/rust-ast-full-decls.h (struct Attribute): Change from here...
(class Attribute): ...to a class here.
* ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Add a default
visit function for the attributes.
* ast/rust-ast-visitor.h: Add a proper visit function declaration for
attributes.
* ast/rust-ast.cc (Attribute::accept_vis): Add a function to accept a
visitor within the attributes.
* ast/rust-ast.h (struct Attribute): Add the accept_vis function
prototype.
(class Attribute): Rename from struct to class.
* expand/rust-derive.h: Add an empty implementation for visits to
prevent the visitor from recursing into the attributes.
* hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Add missing
implementation for attribute visit function. Add a check for derive
attributes that would have slipped through the passes.
* hir/rust-ast-lower-base.h: Add function prototype.
* resolve/rust-early-name-resolver-2.0.cc (Early::visit_attributes):
Split the function into two halves.
(Early::visit_derive_attribute): Specialized function from
visit_attribute for derive attributes.
(Early::visit_non_builtin_attribute): Likewise for non builtin
attributes.
(Early::visit): Rename visit_attributes to visit.
* resolve/rust-early-name-resolver-2.0.h (class Early): Update function
prototypes.
gcc/testsuite/ChangeLog:
* rust/compile/issue-4212.rs: Update test with the new errors.
Signed-off-by: Pierre-Emmanuel Patry <[email protected]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github:
https://github.com/Rust-GCC/gccrs/commit/b4d43073858164ff3d0585fb58650d2595f04355
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4425
gcc/rust/ast/rust-ast-full-decls.h | 2 +-
gcc/rust/ast/rust-ast-visitor.cc | 8 ++
gcc/rust/ast/rust-ast-visitor.h | 3 +-
gcc/rust/ast/rust-ast.cc | 6 +
gcc/rust/ast/rust-ast.h | 5 +-
gcc/rust/expand/rust-derive.h | 3 +-
gcc/rust/hir/rust-ast-lower-base.cc | 11 ++
gcc/rust/hir/rust-ast-lower-base.h | 1 +
.../resolve/rust-early-name-resolver-2.0.cc | 115 ++++++++++--------
.../resolve/rust-early-name-resolver-2.0.h | 6 +
gcc/testsuite/rust/compile/issue-4212.rs | 2 +
11 files changed, 108 insertions(+), 54 deletions(-)
diff --git a/gcc/rust/ast/rust-ast-full-decls.h
b/gcc/rust/ast/rust-ast-full-decls.h
index f839348c7..f90b93145 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -34,7 +34,7 @@ class DelimTokenTree;
class PathSegment;
class SimplePathSegment;
class SimplePath;
-struct Attribute;
+class Attribute;
class MetaItemInner;
class AttrInputMetaItemContainer;
class MetaItem;
diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index 6973d65bc..e04ee4dff 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -194,6 +194,14 @@ DefaultASTVisitor::visit (AST::LiteralExpr &expr)
visit_outer_attrs (expr);
}
+void
+DefaultASTVisitor::visit (AST::Attribute &attribute)
+{
+ visit (attribute.get_path ());
+ if (attribute.has_attr_input ())
+ visit (attribute.get_attr_input ());
+}
+
void
DefaultASTVisitor::visit (AST::AttrInputLiteral &attr_input)
{
diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
index 07ba1e185..fee25e463 100644
--- a/gcc/rust/ast/rust-ast-visitor.h
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -39,6 +39,7 @@ public:
// rust-ast.h
// virtual void visit(AttrInput& attr_input) = 0;
+ virtual void visit (AST::Attribute &attribute) = 0;
// virtual void visit(TokenTree& token_tree) = 0;
// virtual void visit(MacroMatch& macro_match) = 0;
virtual void visit (Token &tok) = 0;
@@ -444,7 +445,7 @@ public:
virtual void visit (AST::StructPatternElements &spe);
virtual void visit (AST::MaybeNamedParam ¶m);
- void visit (AST::Attribute &attribute) {}
+ virtual void visit (AST::Attribute &attribute) override;
template <typename T> void visit_outer_attrs (T &node)
{
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index e571fc8ea..ec25ba268 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -253,6 +253,12 @@ Attribute::as_string () const
return path_str + attr_input->as_string ();
}
+void
+Attribute::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
bool
Attribute::is_derive () const
{
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 0f78f01e1..349318540 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -566,9 +566,8 @@ protected:
// aka Attr
// Attribute AST representation
-struct Attribute
+class Attribute : Visitable
{
-private:
SimplePath path;
// bool has_attr_input;
@@ -686,7 +685,7 @@ public:
bool is_inner_attribute () const { return inner_attribute; }
- // no visitor pattern as not currently polymorphic
+ void accept_vis (ASTVisitor &vis) override;
const SimplePath &get_path () const { return path; }
SimplePath &get_path () { return path; }
diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h
index 7a7019544..9cfd311f6 100644
--- a/gcc/rust/expand/rust-derive.h
+++ b/gcc/rust/expand/rust-derive.h
@@ -256,10 +256,11 @@ private:
virtual void visit (FunctionParam ¶m) override final{};
virtual void visit (VariadicParam ¶m) override final{};
virtual void visit (FormatArgs ¶m) override final{};
+ virtual void visit (Attribute &attribute) override final{};
virtual void visit (OffsetOf ¶m) override final{};
};
} // namespace AST
} // namespace Rust
-#endif // DERIVE_VISITOR_H
\ No newline at end of file
+#endif // DERIVE_VISITOR_H
diff --git a/gcc/rust/hir/rust-ast-lower-base.cc
b/gcc/rust/hir/rust-ast-lower-base.cc
index 639c95245..814b851ae 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -67,6 +67,17 @@ ASTLoweringBase::visit (AST::WhileLetLoopExpr &expr)
rust_unreachable ();
}
+void
+ASTLoweringBase::visit (AST::Attribute &attribute)
+{
+ auto &path = attribute.get_path ();
+ if (path.as_string () == "derive")
+ {
+ rust_fatal_error (attribute.get_locus (),
+ "missing desugar for attribute");
+ }
+}
+
void
ASTLoweringBase::visit (AST::Token &)
{}
diff --git a/gcc/rust/hir/rust-ast-lower-base.h
b/gcc/rust/hir/rust-ast-lower-base.h
index 46b1b91f0..94cef480e 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -71,6 +71,7 @@ public:
// visitor impl
// rust-ast.h
+ virtual void visit (AST::Attribute &attribute) override;
// virtual void visit(AttrInput& attr_input);
// virtual void visit(TokenTree& token_tree);
// virtual void visit(MacroMatch& macro_match);
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 fe40bcd7f..1ee8e4ac1 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -314,65 +314,84 @@ Early::visit (AST::MacroInvocation &invoc)
}
void
-Early::visit_attributes (std::vector<AST::Attribute> &attrs)
+Early::visit_derive_attribute (AST::Attribute &attr,
+ Analysis::Mappings &mappings)
{
- auto &mappings = Analysis::Mappings::get ();
+ auto traits = attr.get_traits_to_derive ();
+ for (auto &trait : traits)
+ {
+ auto definition = ctx.resolve_path (trait.get (), Namespace::Macros);
+ if (!definition.has_value ())
+ {
+ // FIXME: Change to proper error message
+ // FIXME: Change locus to trait locus instead of attribute locus
+ collect_error (Error (attr.get_locus (),
+ "could not resolve trait %qs",
+ trait.get ().as_string ().c_str ()));
+ continue;
+ }
- for (auto &attr : attrs)
+ auto pm_def
+ = mappings.lookup_derive_proc_macro_def (definition->get_node_id ());
+
+ if (pm_def.has_value ())
+ mappings.insert_derive_proc_macro_invocation (trait, pm_def.value ());
+ }
+}
+
+void
+Early::visit_non_builtin_attribute (AST::Attribute &attr,
+ Analysis::Mappings &mappings,
+ std::string &name)
+{
+ auto definition = ctx.resolve_path (attr.get_path (), Namespace::Macros);
+ if (!definition.has_value ())
{
- auto name = attr.get_path ().get_segments ().at (0).get_segment_name ();
+ // FIXME: Change to proper error message
+ collect_error (Error (attr.get_locus (),
+ "could not resolve attribute macro invocation %qs",
+ name.c_str ()));
+ return;
+ }
+ auto pm_def
+ = mappings.lookup_attribute_proc_macro_def (definition->get_node_id ());
- if (attr.is_derive ())
- {
- auto traits = attr.get_traits_to_derive ();
- for (auto &trait : traits)
- {
- auto definition
- = ctx.resolve_path (trait.get (), Namespace::Macros);
- if (!definition.has_value ())
- {
- // FIXME: Change to proper error message
- collect_error (Error (trait.get ().get_locus (),
- "could not resolve trait %qs",
- trait.get ().as_string ().c_str ()));
- continue;
- }
+ if (!pm_def.has_value ())
+ return;
- auto pm_def = mappings.lookup_derive_proc_macro_def (
- definition->get_node_id ());
+ mappings.insert_attribute_proc_macro_invocation (attr.get_path (),
+ pm_def.value ());
+}
- if (pm_def.has_value ())
- mappings.insert_derive_proc_macro_invocation (trait,
- pm_def.value ());
- }
- }
- else if (Analysis::BuiltinAttributeMappings::get ()
- ->lookup_builtin (name)
- .is_error ()) // Do not resolve builtins
- {
- auto definition
- = ctx.resolve_path (attr.get_path (), Namespace::Macros);
- if (!definition.has_value ())
- {
- // FIXME: Change to proper error message
- collect_error (
- Error (attr.get_locus (),
- "could not resolve attribute macro invocation %qs",
- name.c_str ()));
- return;
- }
- auto pm_def = mappings.lookup_attribute_proc_macro_def (
- definition->get_node_id ());
+void
+Early::visit (AST::Attribute &attr)
+{
+ auto &mappings = Analysis::Mappings::get ();
- if (!pm_def.has_value ())
- return;
+ auto name = attr.get_path ().get_segments ().at (0).get_segment_name ();
+ auto is_not_builtin = [&name] (AST::Attribute &attr) {
+ return Analysis::BuiltinAttributeMappings::get ()
+ ->lookup_builtin (name)
+ .is_error ();
+ };
- mappings.insert_attribute_proc_macro_invocation (attr.get_path (),
- pm_def.value ());
- }
+ if (attr.is_derive ())
+ {
+ visit_derive_attribute (attr, mappings);
+ }
+ else if (is_not_builtin (attr)) // Do not resolve builtins
+ {
+ visit_non_builtin_attribute (attr, mappings, name);
}
}
+void
+Early::visit_attributes (std::vector<AST::Attribute> &attrs)
+{
+ for (auto &attr : attrs)
+ visit (attr);
+}
+
void
Early::visit (AST::Function &fn)
{
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 02a395be2..e2415dd0c 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
@@ -37,6 +37,10 @@ class Early : public DefaultResolver
TopLevel toplevel;
bool dirty;
+ void visit_derive_attribute (AST::Attribute &, Analysis::Mappings &);
+ void visit_non_builtin_attribute (AST::Attribute &, Analysis::Mappings &,
+ std::string &name);
+
public:
Early (NameResolutionContext &ctx);
@@ -63,6 +67,8 @@ public:
void visit (AST::UseDeclaration &) override;
void visit (AST::UseTreeList &) override;
+ void visit (AST::Attribute &) override;
+
struct ImportData
{
enum class Kind
diff --git a/gcc/testsuite/rust/compile/issue-4212.rs
b/gcc/testsuite/rust/compile/issue-4212.rs
index a633b0d83..c33b66b56 100644
--- a/gcc/testsuite/rust/compile/issue-4212.rs
+++ b/gcc/testsuite/rust/compile/issue-4212.rs
@@ -3,6 +3,8 @@
#![derive(PartialOrd, PartialEq)]
// { dg-error "attribute cannot be used at crate level" "" { target *-*-* }
.-1 }
+// { dg-error "could not resolve trait .PartialOrd." "" { target *-*-* } .-2 }
+// { dg-error "could not resolve trait .PartialEq." "" { target *-*-* } .-3 }
pub fn check_ge(a: i32, b: i32) -> bool {
a >= b
}
--
2.53.0