aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/util/rust-attributes.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/util/rust-attributes.cc')
-rw-r--r--gcc/rust/util/rust-attributes.cc128
1 files changed, 106 insertions, 22 deletions
diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc
index 03452c7..70f26e7 100644
--- a/gcc/rust/util/rust-attributes.cc
+++ b/gcc/rust/util/rust-attributes.cc
@@ -38,6 +38,31 @@ Attributes::is_known (const std::string &attribute_path)
return !lookup.is_error ();
}
+tl::optional<std::string>
+Attributes::extract_string_literal (const AST::Attribute &attr)
+{
+ if (!attr.has_attr_input ())
+ return tl::nullopt;
+
+ auto &attr_input = attr.get_attr_input ();
+
+ if (attr_input.get_attr_input_type ()
+ != AST::AttrInput::AttrInputType::LITERAL)
+ return tl::nullopt;
+
+ auto &literal_expr
+ = static_cast<AST::AttrInputLiteral &> (attr_input).get_literal ();
+
+ auto lit_type = literal_expr.get_lit_type ();
+
+ // TODO: bring escape sequence handling out of lexing?
+ if (lit_type != AST::Literal::LitType::STRING
+ && lit_type != AST::Literal::LitType::RAW_STRING)
+ return tl::nullopt;
+
+ return literal_expr.as_string ();
+}
+
using Attrs = Values::Attributes;
// https://doc.rust-lang.org/stable/nightly-rustc/src/rustc_feature/builtin_attrs.rs.html#248
@@ -53,10 +78,12 @@ static const BuiltinAttrDefinition __definitions[]
{Attrs::DOC, HIR_LOWERING},
{Attrs::MUST_USE, STATIC_ANALYSIS},
{Attrs::LANG, HIR_LOWERING},
+ {Attrs::LINK_NAME, CODE_GENERATION},
{Attrs::LINK_SECTION, CODE_GENERATION},
{Attrs::NO_MANGLE, CODE_GENERATION},
{Attrs::REPR, CODE_GENERATION},
{Attrs::RUSTC_BUILTIN_MACRO, EXPANSION},
+ {Attrs::RUSTC_MACRO_TRANSPARENCY, EXPANSION},
{Attrs::PATH, EXPANSION},
{Attrs::MACRO_USE, NAME_RESOLUTION},
{Attrs::MACRO_EXPORT, NAME_RESOLUTION},
@@ -73,9 +100,32 @@ static const BuiltinAttrDefinition __definitions[]
{Attrs::STABLE, STATIC_ANALYSIS},
{Attrs::UNSTABLE, STATIC_ANALYSIS},
// assuming we keep these for static analysis
+ {Attrs::RUSTC_PROMOTABLE, CODE_GENERATION},
{Attrs::RUSTC_CONST_STABLE, STATIC_ANALYSIS},
{Attrs::RUSTC_CONST_UNSTABLE, STATIC_ANALYSIS},
- {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION}};
+ {Attrs::RUSTC_ALLOW_CONST_FN_UNSTABLE, STATIC_ANALYSIS},
+ {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
+ {Attrs::TRACK_CALLER, CODE_GENERATION},
+ {Attrs::RUSTC_SPECIALIZATION_TRAIT, TYPE_CHECK},
+ {Attrs::RUSTC_UNSAFE_SPECIALIZATION_MARKER, TYPE_CHECK},
+ {Attrs::RUSTC_RESERVATION_IMPL, TYPE_CHECK},
+ {Attrs::RUSTC_PAREN_SUGAR, TYPE_CHECK},
+ {Attrs::RUSTC_NONNULL_OPTIMIZATION_GUARANTEED, TYPE_CHECK},
+ {Attrs::RUSTC_LAYOUT_SCALAR_VALID_RANGE_START, CODE_GENERATION},
+ // TODO: be careful about calling functions marked with this?
+ {Attrs::RUSTC_ARGS_REQUIRED_CONST, CODE_GENERATION},
+ {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
+ {Attrs::RUSTC_DIAGNOSTIC_ITEM, STATIC_ANALYSIS},
+ {Attrs::RUSTC_ON_UNIMPLEMENTED, STATIC_ANALYSIS},
+ {Attrs::FUNDAMENTAL, TYPE_CHECK},
+ {Attrs::NON_EXHAUSTIVE, TYPE_CHECK},
+ {Attrs::RUSTFMT, EXTERNAL},
+ {Attrs::TEST, CODE_GENERATION}};
+
+static const std::set<std::string> __outer_attributes
+ = {Attrs::INLINE, Attrs::DERIVE_ATTR, Attrs::ALLOW_INTERNAL_UNSTABLE,
+ Attrs::LANG, Attrs::REPR, Attrs::PATH,
+ Attrs::TARGET_FEATURE, Attrs::TEST};
BuiltinAttributeMappings *
BuiltinAttributeMappings::get ()
@@ -118,6 +168,7 @@ AttributeChecker::go (AST::Crate &crate)
void
AttributeChecker::visit (AST::Crate &crate)
{
+ check_inner_attributes (crate.get_inner_attrs ());
check_attributes (crate.get_inner_attrs ());
for (auto &item : crate.items)
@@ -188,8 +239,8 @@ check_doc_attribute (const AST::Attribute &attribute)
{
rust_error_at (
attribute.get_locus (),
- // FIXME: Improve error message here. Rustc has a very good one
- "%<#[doc]%> cannot be an empty attribute");
+ "valid forms for the attribute are "
+ "%<#[doc(hidden|inline|...)]%> and %<#[doc = \" string \"]%>");
return;
}
@@ -201,7 +252,8 @@ check_doc_attribute (const AST::Attribute &attribute)
break;
// FIXME: Handle them as well
- case AST::AttrInput::TOKEN_TREE: {
+ case AST::AttrInput::TOKEN_TREE:
+ {
// FIXME: This doesn't check for #[doc(alias(...))]
const auto &option = static_cast<const AST::DelimTokenTree &> (
attribute.get_attr_input ());
@@ -271,8 +323,42 @@ check_proc_macro_non_root (AST::AttrVec attributes, location_t loc)
}
void
+AttributeChecker::check_inner_attribute (const AST::Attribute &attribute)
+{
+ BuiltinAttrDefinition result;
+
+ if (!is_builtin (attribute, result))
+ return;
+
+ if (__outer_attributes.find (result.name) != __outer_attributes.end ())
+ rust_error_at (attribute.get_locus (),
+ "attribute cannot be used at crate level");
+}
+
+void
+AttributeChecker::check_inner_attributes (const AST::AttrVec &attributes)
+{
+ for (auto &attr : attributes)
+ check_inner_attribute (attr);
+}
+
+void
AttributeChecker::check_attribute (const AST::Attribute &attribute)
{
+ if (!attribute.empty_input ())
+ {
+ const auto &attr_input = attribute.get_attr_input ();
+ auto type = attr_input.get_attr_input_type ();
+ if (type == AST::AttrInput::AttrInputType::TOKEN_TREE)
+ {
+ const auto &option = static_cast<const AST::DelimTokenTree &> (
+ attribute.get_attr_input ());
+ std::unique_ptr<AST::AttrInputMetaItemContainer> meta_item (
+ option.parse_to_meta_item ());
+ AST::DefaultASTVisitor::visit (meta_item);
+ }
+ }
+
BuiltinAttrDefinition result;
// This checker does not check non-builtin attributes
@@ -302,10 +388,6 @@ AttributeChecker::visit (AST::DelimTokenTree &)
{}
void
-AttributeChecker::visit (AST::AttrInputMetaItemContainer &)
-{}
-
-void
AttributeChecker::visit (AST::IdentifierExpr &)
{}
@@ -368,8 +450,16 @@ AttributeChecker::visit (AST::MetaItemLitExpr &)
{}
void
-AttributeChecker::visit (AST::MetaItemPathLit &)
-{}
+AttributeChecker::visit (AST::MetaItemPathExpr &attribute)
+{
+ if (!attribute.get_expr ().is_literal ())
+ {
+ rust_error_at (attribute.get_expr ().get_locus (),
+ "malformed %<path%> attribute input");
+ rust_inform (attribute.get_expr ().get_locus (),
+ "must be of the form: %<#[path = \"file\"]%>");
+ }
+}
void
AttributeChecker::visit (AST::BorrowExpr &)
@@ -595,6 +685,7 @@ AttributeChecker::visit (AST::TypeBoundWhereClauseItem &)
void
AttributeChecker::visit (AST::Module &module)
{
+ check_attributes (module.get_outer_attrs ());
check_proc_macro_non_function (module.get_outer_attrs ());
for (auto &item : module.get_items ())
{
@@ -747,10 +838,6 @@ AttributeChecker::visit (AST::StaticItem &item)
}
void
-AttributeChecker::visit (AST::TraitItemConst &)
-{}
-
-void
AttributeChecker::visit (AST::TraitItemType &)
{}
@@ -758,6 +845,7 @@ void
AttributeChecker::visit (AST::Trait &trait)
{
check_proc_macro_non_function (trait.get_outer_attrs ());
+ check_attributes (trait.get_outer_attrs ());
}
void
@@ -814,10 +902,6 @@ AttributeChecker::visit (AST::MetaItemPath &)
{}
void
-AttributeChecker::visit (AST::MetaItemSeq &)
-{}
-
-void
AttributeChecker::visit (AST::MetaWord &)
{}
@@ -893,11 +977,11 @@ AttributeChecker::visit (AST::StructPattern &)
// void AttributeChecker::visit(TupleStructItems& ){}
void
-AttributeChecker::visit (AST::TupleStructItemsNoRange &)
+AttributeChecker::visit (AST::TupleStructItemsNoRest &)
{}
void
-AttributeChecker::visit (AST::TupleStructItemsRange &)
+AttributeChecker::visit (AST::TupleStructItemsHasRest &)
{}
void
@@ -907,11 +991,11 @@ AttributeChecker::visit (AST::TupleStructPattern &)
// void AttributeChecker::visit(TuplePatternItems& ){}
void
-AttributeChecker::visit (AST::TuplePatternItemsMultiple &)
+AttributeChecker::visit (AST::TuplePatternItemsNoRest &)
{}
void
-AttributeChecker::visit (AST::TuplePatternItemsRanged &)
+AttributeChecker::visit (AST::TuplePatternItemsHasRest &)
{}
void