diff options
-rw-r--r-- | gcc/rust/backend/rust-mangle.cc | 16 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-builtins.cc | 69 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-builtins.h | 3 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-autoderef.cc | 2 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h | 25 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-path-probe.h | 5 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty-bounds.cc | 5 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty-cmp.h | 26 | ||||
-rw-r--r-- | gcc/rust/util/rust-hir-map.cc | 1 | ||||
-rw-r--r-- | gcc/rust/util/rust-mapping-common.h | 9 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/builtin_macro_concat.rs | 15 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/generics7.rs | 2 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/generics8.rs | 2 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/torture/issue-1075.rs | 42 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/builtin_macro_concat.rs | 23 |
15 files changed, 202 insertions, 43 deletions
diff --git a/gcc/rust/backend/rust-mangle.cc b/gcc/rust/backend/rust-mangle.cc index eaf7814..82f643a 100644 --- a/gcc/rust/backend/rust-mangle.cc +++ b/gcc/rust/backend/rust-mangle.cc @@ -11,6 +11,9 @@ static const std::string kMangledSubstBegin = "$LT$"; static const std::string kMangledSubstEnd = "$GT$"; static const std::string kMangledSpace = "$u20$"; static const std::string kMangledRef = "$RF$"; +static const std::string kMangledPtr = "$BP$"; +static const std::string kMangledLeftSqParen = "$u5b$"; // [ +static const std::string kMangledRightSqParen = "$u5d$"; // ] static const std::string kQualPathBegin = "_" + kMangledSubstBegin; namespace Rust { @@ -29,8 +32,15 @@ legacy_mangle_name (const std::string &name) // <example::Bar as example::A>::fooA: // _ZN43_$LT$example..Bar$u20$as$u20$example..A$GT$4fooA17hfc615fa76c7db7a0E: // + // core::ptr::const_ptr::<impl *const T>::cast: + // _ZN4core3ptr9const_ptr33_$LT$impl$u20$$BP$const$u20$T$GT$4cast17hb79f4617226f1d55E: + // + // core::ptr::const_ptr::<impl *const [T]>::as_ptr: + // _ZN4core3ptr9const_ptr43_$LT$impl$u20$$BP$const$u20$$u5b$T$u5d$$GT$6as_ptr17he16e0dcd9473b04fE: + // // example::Foo<T>::new: // _ZN7example12Foo$LT$T$GT$3new17h9a2aacb7fd783515E: + std::string buffer; for (size_t i = 0; i < name.size (); i++) { @@ -47,6 +57,12 @@ legacy_mangle_name (const std::string &name) m = kMangledSubstBegin; else if (c == '>') m = kMangledSubstEnd; + else if (c == '*') + m = kMangledPtr; + else if (c == '[') + m = kMangledLeftSqParen; + else if (c == ']') + m = kMangledRightSqParen; else if (c == ':') { rust_assert (i + 1 < name.size ()); diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc index 3cd6e43..85520ec 100644 --- a/gcc/rust/expand/rust-macro-builtins.cc +++ b/gcc/rust/expand/rust-macro-builtins.cc @@ -34,17 +34,12 @@ make_string (Location locus, std::string value) PrimitiveCoreType::CORETYPE_STR, {}, locus)); } -/* Parse a single string literal from the given delimited token tree, - and return the LiteralExpr for it. Allow for an optional trailing comma, - but otherwise enforce that these are the only tokens. */ +/* Match the end token of a macro given the start delimiter of the macro */ -std::unique_ptr<AST::LiteralExpr> -parse_single_string_literal (AST::DelimTokenTree &invoc_token_tree, - Location invoc_locus) +static inline TokenId +macro_end_token (AST::DelimTokenTree &invoc_token_tree, + Parser<MacroInvocLexer> &parser) { - MacroInvocLexer lex (invoc_token_tree.to_token_stream ()); - Parser<MacroInvocLexer> parser (std::move (lex)); - auto last_token_id = TokenId::RIGHT_CURLY; switch (invoc_token_tree.get_delim_type ()) { @@ -63,6 +58,22 @@ parse_single_string_literal (AST::DelimTokenTree &invoc_token_tree, break; } + return last_token_id; +} + +/* Parse a single string literal from the given delimited token tree, + and return the LiteralExpr for it. Allow for an optional trailing comma, + but otherwise enforce that these are the only tokens. */ + +std::unique_ptr<AST::LiteralExpr> +parse_single_string_literal (AST::DelimTokenTree &invoc_token_tree, + Location invoc_locus) +{ + MacroInvocLexer lex (invoc_token_tree.to_token_stream ()); + Parser<MacroInvocLexer> parser (std::move (lex)); + + auto last_token_id = macro_end_token (invoc_token_tree, parser); + std::unique_ptr<AST::LiteralExpr> lit_expr = nullptr; if (parser.peek_current_token ()->get_id () == STRING_LITERAL) @@ -252,4 +263,44 @@ MacroBuiltin::compile_error (Location invoc_locus, AST::MacroInvocData &invoc) return AST::ASTFragment::create_error (); } +/* Expand builtin macro concat!(), which joins all the literal parameters + into a string with no delimiter. */ + +AST::ASTFragment +MacroBuiltin::concat (Location invoc_locus, AST::MacroInvocData &invoc) +{ + auto invoc_token_tree = invoc.get_delim_tok_tree (); + MacroInvocLexer lex (invoc_token_tree.to_token_stream ()); + Parser<MacroInvocLexer> parser (std::move (lex)); + auto str = std::string (); + bool has_error = false; + + auto last_token_id = macro_end_token (invoc_token_tree, parser); + + /* NOTE: concat! could accept no argument, so we don't have any checks here */ + while (parser.peek_current_token ()->get_id () != last_token_id) + { + auto lit_expr = parser.parse_literal_expr (); + if (lit_expr) + { + str += lit_expr->as_string (); + } + else + { + rust_error_at (parser.peek_current_token ()->get_locus (), + "argument must be a constant literal"); + has_error = true; + } + parser.maybe_skip_token (COMMA); + } + + parser.skip_token (last_token_id); + + if (has_error) + return AST::ASTFragment::create_error (); + + auto node = AST::SingleASTNode (make_string (invoc_locus, str)); + return AST::ASTFragment ({node}); +} + } // namespace Rust diff --git a/gcc/rust/expand/rust-macro-builtins.h b/gcc/rust/expand/rust-macro-builtins.h index b119466..a581af4 100644 --- a/gcc/rust/expand/rust-macro-builtins.h +++ b/gcc/rust/expand/rust-macro-builtins.h @@ -80,6 +80,9 @@ public: static AST::ASTFragment compile_error (Location invoc_locus, AST::MacroInvocData &invoc); + + static AST::ASTFragment concat (Location invoc_locus, + AST::MacroInvocData &invoc); }; } // namespace Rust diff --git a/gcc/rust/typecheck/rust-autoderef.cc b/gcc/rust/typecheck/rust-autoderef.cc index 67c1908..986ff46 100644 --- a/gcc/rust/typecheck/rust-autoderef.cc +++ b/gcc/rust/typecheck/rust-autoderef.cc @@ -116,7 +116,7 @@ Adjuster::try_unsize_type (const TyTy::BaseType *ty) TyTy::TyVar (slice_elem->get_ref ())); context->insert_implicit_type (slice); - return Adjustment (Adjustment::AdjustmentType::INDIRECTION, slice); + return Adjustment (Adjustment::AdjustmentType::UNSIZE, slice); } static bool diff --git a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h index 2908a4b..9abf872 100644 --- a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h +++ b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h @@ -123,7 +123,26 @@ public: continue; if (query->can_eq (candidate, false)) - possible_collision (it->second, iy->second); + { + // we might be in the case that we have: + // + // *const T vs *const [T] + // + // so lets use an equality check when the + // candidates are both generic to be sure we dont emit a false + // positive + + bool a = query->is_concrete (); + bool b = candidate->is_concrete (); + bool both_generic = !a && !b; + if (both_generic) + { + if (!query->is_equal (*candidate)) + continue; + } + + possible_collision (it->second, iy->second); + } } } } @@ -152,8 +171,8 @@ public: void collision_detected (HIR::ImplItem *query, HIR::ImplItem *dup, const std::string &name) { - RichLocation r (query->get_locus ()); - r.add_range (dup->get_locus ()); + RichLocation r (dup->get_locus ()); + r.add_range (query->get_locus ()); rust_error_at (r, "duplicate definitions with name %s", name.c_str ()); } diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h index 3c1858c..fda505a 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.h +++ b/gcc/rust/typecheck/rust-hir-path-probe.h @@ -284,7 +284,10 @@ protected: return; if (!receiver->can_eq (impl_block_ty, false)) - return; + { + if (!impl_block_ty->can_eq (receiver, false)) + return; + } // lets visit the impl_item item->accept_vis (*this); diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index a7ec42c..b34db3b 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -41,7 +41,10 @@ TypeBoundsProbe::scan () return true; if (!receiver->can_eq (impl_type, false)) - return true; + { + if (!impl_type->can_eq (receiver, false)) + return true; + } possible_trait_paths.push_back ({impl->get_trait_ref ().get (), impl}); return true; diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h index afc928da..34c8963 100644 --- a/gcc/rust/typecheck/rust-tyty-cmp.h +++ b/gcc/rust/typecheck/rust-tyty-cmp.h @@ -886,8 +886,6 @@ public: ok = true; } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const ArrayType *base; @@ -916,8 +914,6 @@ public: ok = true; } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const SliceType *base; @@ -939,8 +935,6 @@ public: ok = type.get_infer_kind () == InferType::InferTypeKind::GENERAL; } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const BoolType *base; @@ -965,8 +959,6 @@ public: ok = type.get_int_kind () == base->get_int_kind (); } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const IntType *base; @@ -991,8 +983,6 @@ public: ok = type.get_uint_kind () == base->get_uint_kind (); } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const UintType *base; @@ -1017,8 +1007,6 @@ public: ok = type.get_float_kind () == base->get_float_kind (); } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const FloatType *base; @@ -1120,8 +1108,6 @@ public: ok = true; } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const TupleType *base; @@ -1143,8 +1129,6 @@ public: void visit (const USizeType &type) override { ok = true; } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const USizeType *base; @@ -1166,8 +1150,6 @@ public: void visit (const ISizeType &type) override { ok = true; } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const ISizeType *base; @@ -1189,8 +1171,6 @@ public: void visit (const CharType &type) override { ok = true; } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const CharType *base; @@ -1365,8 +1345,6 @@ public: void visit (const StrType &type) override { ok = true; } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const StrType *base; @@ -1383,8 +1361,6 @@ public: void visit (const NeverType &type) override { ok = true; } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const NeverType *base; @@ -1478,8 +1454,6 @@ public: ok = base->bounds_compatible (type, ref_locus, false); } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index 47f9175..7bacc4c 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -754,6 +754,7 @@ Mappings::insert_macro_def (AST::MacroRulesDefinition *macro) {"include_bytes", MacroBuiltin::include_bytes}, {"include_str", MacroBuiltin::include_str}, {"compile_error", MacroBuiltin::compile_error}, + {"concat", MacroBuiltin::concat}, }; auto builtin = builtin_macros.find (macro->get_rule_name ()); diff --git a/gcc/rust/util/rust-mapping-common.h b/gcc/rust/util/rust-mapping-common.h index 42a4e8e..27faa7f 100644 --- a/gcc/rust/util/rust-mapping-common.h +++ b/gcc/rust/util/rust-mapping-common.h @@ -50,6 +50,15 @@ struct DefId return ((uint64_t) this->crateNum << 32 | this->localDefId) < ((uint64_t) other.crateNum << 32 | other.localDefId); } + + std::string as_string () const + { + std::string buf; + buf += std::to_string (crateNum); + buf += " "; // or anything else + buf += std::to_string (localDefId); + return buf; + } }; #define UNKNOWN_CREATENUM ((uint32_t) (0)) diff --git a/gcc/testsuite/rust/compile/builtin_macro_concat.rs b/gcc/testsuite/rust/compile/builtin_macro_concat.rs new file mode 100644 index 0000000..1fcd65f --- /dev/null +++ b/gcc/testsuite/rust/compile/builtin_macro_concat.rs @@ -0,0 +1,15 @@ +macro_rules! concat { + () => {{}}; +} + +fn main () { + let not_literal = "identifier"; + concat! (); + concat! (,); // { dg-error "argument must be a constant literal" } + concat! (not_literal); // { dg-error "argument must be a constant literal" } + concat! ("message"); + concat! ("message",); + concat! ("message",1, true, false, 1.0, 10usize, 2000u64); + concat! ("message",1, true, false, 1.0, 10usize, 2000u64,); + concat! ("m", not_literal); // { dg-error "argument must be a constant literal" } +} diff --git a/gcc/testsuite/rust/compile/generics7.rs b/gcc/testsuite/rust/compile/generics7.rs index 78b6149..2a41632 100644 --- a/gcc/testsuite/rust/compile/generics7.rs +++ b/gcc/testsuite/rust/compile/generics7.rs @@ -15,7 +15,7 @@ impl Foo<char> { } impl<T> Foo<T> { - fn bar(self) -> T { // { dg-error "duplicate definitions with name bar" } + fn bar(self) -> T { self.a } } diff --git a/gcc/testsuite/rust/compile/generics8.rs b/gcc/testsuite/rust/compile/generics8.rs index 70bad1a..ceefc5d 100644 --- a/gcc/testsuite/rust/compile/generics8.rs +++ b/gcc/testsuite/rust/compile/generics8.rs @@ -1,7 +1,7 @@ struct Foo<A, B>(A, B); impl<T> Foo<i32, T> { - fn test(a: T) -> T { // { dg-error "duplicate definitions with name test" } + fn test(a: T) -> T { a } } diff --git a/gcc/testsuite/rust/compile/torture/issue-1075.rs b/gcc/testsuite/rust/compile/torture/issue-1075.rs new file mode 100644 index 0000000..3bd6321 --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/issue-1075.rs @@ -0,0 +1,42 @@ +// { dg-additional-options "-w" } +extern "rust-intrinsic" { + pub fn offset<T>(dst: *const T, offset: isize) -> *const T; +} + +struct FatPtr<T> { + data: *const T, + len: usize, +} + +union Repr<T> { + rust: *const [T], + rust_mut: *mut [T], + raw: FatPtr<T>, +} + +impl<T> *const [T] { + pub const fn len(self) -> usize { + // SAFETY: this is safe because `*const [T]` and `FatPtr<T>` have the same layout. + // Only `std` can make this guarantee. + let a = unsafe { Repr { rust: self }.raw }; + a.len + } + + pub const fn as_ptr(self) -> *const T { + self as *const T + } +} + +impl<T> *const T { + pub const unsafe fn offset(self, count: isize) -> *const T { + unsafe { offset(self, count) } + } + + pub const unsafe fn add(self, count: usize) -> Self { + unsafe { self.offset(count as isize) } + } + + pub const fn as_ptr(self) -> *const T { + self as *const T + } +} diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_concat.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_concat.rs new file mode 100644 index 0000000..ca40585 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/builtin_macro_concat.rs @@ -0,0 +1,23 @@ +// { dg-output "\ntest10btrue2.15\ntest10bfalse2.151\n" } +macro_rules! concat { + () => {{}}; +} + +extern "C" { + fn printf(fmt: *const i8, ...); +} + +fn print(s: &str) { + printf("%s\n" as *const str as *const i8, s as *const str as *const i8); +} + +fn main() -> i32 { + let a = concat!(); + let b = concat!("test", 10, 'b', true, 2.15); + let c = concat!("test", 10, 'b', false, 2.15, 1u64); + print(a); + print(b); + print(c); + + 0 +} |