diff options
Diffstat (limited to 'gcc/rust/util/rust-attributes.cc')
| -rw-r--r-- | gcc/rust/util/rust-attributes.cc | 128 |
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 |
