aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/checks/errors/rust-const-checker.cc97
-rw-r--r--gcc/rust/checks/errors/rust-const-checker.h25
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.cc5
-rw-r--r--gcc/rust/lang.opt42
-rw-r--r--gcc/rust/rust-session-manager.cc36
-rw-r--r--gcc/rust/rust-session-manager.h25
-rw-r--r--gcc/testsuite/rust/compile/const_generics_7.rs17
-rw-r--r--gcc/testsuite/rust/compile/const_generics_8.rs12
-rw-r--r--gcc/testsuite/rust/compile/frust-compile-until.rs7
-rw-r--r--gcc/testsuite/rust/compile/macro44.rs34
10 files changed, 290 insertions, 10 deletions
diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc
index 35c61fe..a2a6dc2 100644
--- a/gcc/rust/checks/errors/rust-const-checker.cc
+++ b/gcc/rust/checks/errors/rust-const-checker.cc
@@ -52,6 +52,67 @@ ConstChecker::is_const_extern_fn (HIR::ExternalFunctionItem &fn)
});
}
+const char *
+ConstChecker::ctx_to_str (ConstGenericCtx ctx)
+{
+ switch (ctx)
+ {
+ case ConstGenericCtx::Function:
+ return "function";
+ case ConstGenericCtx::TypeAlias:
+ return "type alias";
+ case ConstGenericCtx::Struct:
+ return "struct";
+ case ConstGenericCtx::Enum:
+ return "enum";
+ case ConstGenericCtx::Union:
+ return "union";
+ case ConstGenericCtx::Trait:
+ return "trait";
+ case ConstGenericCtx::Impl:
+ return "impl";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+bool
+ConstChecker::ctx_allows_default (ConstGenericCtx ctx)
+{
+ switch (ctx)
+ {
+ case ConstGenericCtx::TypeAlias:
+ case ConstGenericCtx::Struct:
+ case ConstGenericCtx::Enum:
+ case ConstGenericCtx::Trait:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void
+ConstChecker::check_default_const_generics (
+ std::vector<std::unique_ptr<GenericParam>> &params, ConstGenericCtx context)
+{
+ if (ctx_allows_default (context))
+ return;
+
+ for (auto &param : params)
+ {
+ if (param->get_kind () == GenericParam::GenericKind::CONST)
+ {
+ auto const_param = static_cast<ConstGenericParam *> (param.get ());
+ if (const_param->has_default_expression ())
+ rust_error_at (
+ param->get_locus (),
+ "default values for const generic parameters are not "
+ "allowed in %qs items",
+ ctx_to_str (context));
+ }
+ }
+}
+
void
ConstChecker::visit (Lifetime &lifetime)
{}
@@ -560,6 +621,9 @@ ConstChecker::visit (Function &function)
if (const_fn)
const_context.enter (function.get_mappings ().get_hirid ());
+ check_default_const_generics (function.get_generic_params (),
+ ConstGenericCtx::Function);
+
for (auto &param : function.get_function_params ())
param.get_type ()->accept_vis (*this);
@@ -571,18 +635,27 @@ ConstChecker::visit (Function &function)
void
ConstChecker::visit (TypeAlias &type_alias)
-{}
+{
+ check_default_const_generics (type_alias.get_generic_params (),
+ ConstGenericCtx::TypeAlias);
+}
void
ConstChecker::visit (StructStruct &struct_item)
-{}
+{
+ check_default_const_generics (struct_item.get_generic_params (),
+ ConstGenericCtx::Struct);
+}
void
ConstChecker::visit (TupleStruct &tuple_struct)
-{}
+{
+ check_default_const_generics (tuple_struct.get_generic_params (),
+ ConstGenericCtx::Struct);
+}
void
-ConstChecker::visit (EnumItem &item)
+ConstChecker::visit (EnumItem &enum_item)
{}
void
@@ -605,11 +678,17 @@ ConstChecker::visit (EnumItemDiscriminant &item)
void
ConstChecker::visit (Enum &enum_item)
-{}
+{
+ check_default_const_generics (enum_item.get_generic_params (),
+ ConstGenericCtx::Enum);
+}
void
ConstChecker::visit (Union &union_item)
-{}
+{
+ check_default_const_generics (union_item.get_generic_params (),
+ ConstGenericCtx::Union);
+}
void
ConstChecker::visit (ConstantItem &const_item)
@@ -652,6 +731,9 @@ ConstChecker::visit (TraitItemType &item)
void
ConstChecker::visit (Trait &trait)
{
+ check_default_const_generics (trait.get_generic_params (),
+ ConstGenericCtx::Trait);
+
for (auto &item : trait.get_trait_items ())
item->accept_vis (*this);
}
@@ -659,6 +741,9 @@ ConstChecker::visit (Trait &trait)
void
ConstChecker::visit (ImplBlock &impl)
{
+ check_default_const_generics (impl.get_generic_params (),
+ ConstGenericCtx::Impl);
+
for (auto &item : impl.get_impl_items ())
item->accept_vis (*this);
}
diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h
index 50838d1..90b675b 100644
--- a/gcc/rust/checks/errors/rust-const-checker.h
+++ b/gcc/rust/checks/errors/rust-const-checker.h
@@ -46,6 +46,31 @@ private:
*/
void check_function_call (HirId fn_id, Location locus);
+ /* All possible const contexts */
+ enum class ConstGenericCtx
+ {
+ Function,
+ TypeAlias,
+ Struct,
+ Enum,
+ Union,
+ Trait,
+ Impl
+ };
+
+ /* Get the string representation of a const context */
+ const char *ctx_to_str (ConstGenericCtx ctx);
+
+ /* Check if a const context allows default values */
+ bool ctx_allows_default (ConstGenericCtx ctx);
+
+ /**
+ * Check that const generic parameters only contains defaults in allowed
+ * contexts
+ */
+ void check_default_const_generics (
+ std::vector<std::unique_ptr<GenericParam>> &param, ConstGenericCtx context);
+
StackedContexts<HirId> const_context;
Resolver::Resolver &resolver;
Analysis::Mappings &mappings;
diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc
index fefc938..336be5b 100644
--- a/gcc/rust/hir/rust-ast-lower-item.cc
+++ b/gcc/rust/hir/rust-ast-lower-item.cc
@@ -59,7 +59,10 @@ ASTLoweringItem::visit (AST::Module &module)
for (auto &item : module.get_items ())
{
auto transitem = translate (item.get ());
- items.push_back (std::unique_ptr<Item> (transitem));
+ // The item may be null if it doesn't need to live in the HIR - for
+ // example, macro rules definitions
+ if (transitem)
+ items.push_back (std::unique_ptr<Item> (transitem));
}
// should be lowered/copied from module.get_in/outer_attrs()
diff --git a/gcc/rust/lang.opt b/gcc/rust/lang.opt
index 1f6855e..bb3b998 100644
--- a/gcc/rust/lang.opt
+++ b/gcc/rust/lang.opt
@@ -113,6 +113,48 @@ Rust Joined RejectNegative
o
Rust Joined Separate
+
+frust-compile-until=
+Rust Joined RejectNegative Enum(frust_compile_until) Var(flag_rust_compile_until)
+-frust-compile-until=[ast|attributecheck|expansion|nameresolution|lowering|typecheck|privacy|unsafety|const|copimlation|end] When to stop in the pipeline when compiling Rust code
+
+Enum
+Name(frust_compile_until) Type(int) UnknownError(unknown rust compile-until %qs)
+
+EnumValue
+Enum(frust_compile_until) String(ast) Value(0)
+
+EnumValue
+Enum(frust_compile_until) String(attributecheck) Value(1)
+
+EnumValue
+Enum(frust_compile_until) String(expansion) Value(2)
+
+EnumValue
+Enum(frust_compile_until) String(nameresolution) Value(3)
+
+EnumValue
+Enum(frust_compile_until) String(lowering) Value(4)
+
+EnumValue
+Enum(frust_compile_until) String(typecheck) Value(5)
+
+EnumValue
+Enum(frust_compile_until) String(privacy) Value(6)
+
+EnumValue
+Enum(frust_compile_until) String(unsafety) Value(7)
+
+EnumValue
+Enum(frust_compile_until) String(const) Value(8)
+
+EnumValue
+Enum(frust_compile_until) String(compilation) Value(9)
+
+EnumValue
+Enum(frust_compile_until) String(end) Value(10)
+
+
; Documented in common.opt
; This comment is to ensure we retain the blank line above.
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index fc66b69..a6291a3 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -223,7 +223,9 @@ Session::handle_option (
case OPT_frust_edition_:
options.set_edition (flag_rust_edition);
break;
-
+ case OPT_frust_compile_until_:
+ options.set_compile_step (flag_rust_compile_until);
+ break;
case OPT_frust_metadata_output_:
options.set_metadata_output (arg);
break;
@@ -425,6 +427,8 @@ Session::compile_crate (const char *filename)
return;
}
+ auto last_step = options.get_compile_until ();
+
// parse file here
/* create lexer and parser - these are file-specific and so aren't instance
* variables */
@@ -481,7 +485,7 @@ Session::compile_crate (const char *filename)
// If -fsyntax-only was passed, we can just skip the remaining passes.
// Parsing errors are already emitted in `parse_crate()`
- if (flag_syntax_only)
+ if (flag_syntax_only || last_step == CompileOptions::CompileStep::Ast)
return;
// register plugins pipeline stage
@@ -500,8 +504,14 @@ Session::compile_crate (const char *filename)
// TODO: what do I dump here? injected crate names?
}
+ if (last_step == CompileOptions::CompileStep::AttributeCheck)
+ return;
+
Analysis::AttributeChecker ().go (parsed_crate);
+ if (last_step == CompileOptions::CompileStep::Expansion)
+ return;
+
// expansion pipeline stage
expansion (parsed_crate);
rust_debug ("\033[0;31mSUCCESSFULLY FINISHED EXPANSION \033[0m");
@@ -514,6 +524,9 @@ Session::compile_crate (const char *filename)
rust_debug ("END POST-EXPANSION AST DUMP");
}
+ if (last_step == CompileOptions::CompileStep::NameResolution)
+ return;
+
// resolution pipeline stage
Resolver::NameResolution::Resolve (parsed_crate);
if (options.dump_option_enabled (CompileOptions::RESOLUTION_DUMP))
@@ -524,6 +537,9 @@ Session::compile_crate (const char *filename)
if (saw_errors ())
return;
+ if (last_step == CompileOptions::CompileStep::Lowering)
+ return;
+
// lower AST to HIR
std::unique_ptr<HIR::Crate> lowered
= HIR::ASTLowering::Resolve (parsed_crate);
@@ -541,6 +557,9 @@ Session::compile_crate (const char *filename)
dump_hir_pretty (hir);
}
+ if (last_step == CompileOptions::CompileStep::TypeCheck)
+ return;
+
// type resolve
Resolver::TypeResolution::Resolve (hir);
if (options.dump_option_enabled (CompileOptions::TYPE_RESOLUTION_DUMP))
@@ -551,17 +570,30 @@ Session::compile_crate (const char *filename)
if (saw_errors ())
return;
+ if (last_step == CompileOptions::CompileStep::Privacy)
+ return;
+
// Various HIR error passes. The privacy pass happens before the unsafe checks
Privacy::Resolver::resolve (hir);
if (saw_errors ())
return;
+ if (last_step == CompileOptions::CompileStep::Unsafety)
+ return;
+
HIR::UnsafeChecker ().go (hir);
+
+ if (last_step == CompileOptions::CompileStep::Const)
+ return;
+
HIR::ConstChecker ().go (hir);
if (saw_errors ())
return;
+ if (last_step == CompileOptions::CompileStep::Compilation)
+ return;
+
// do compile to gcc generic
Compile::Context ctx (backend);
Compile::CompileCrate::Compile (hir, &ctx);
diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h
index b3724c5..6ecd513 100644
--- a/gcc/rust/rust-session-manager.h
+++ b/gcc/rust/rust-session-manager.h
@@ -199,6 +199,22 @@ struct CompileOptions
} edition
= Edition::E2015;
+ enum class CompileStep
+ {
+ Ast,
+ AttributeCheck,
+ Expansion,
+ NameResolution,
+ Lowering,
+ TypeCheck,
+ Privacy,
+ Unsafety,
+ Const,
+ Compilation,
+ End,
+ } compile_until
+ = CompileStep::End;
+
bool dump_option_enabled (DumpOption option) const
{
return dump_options.find (option) != dump_options.end ();
@@ -239,7 +255,14 @@ struct CompileOptions
edition = static_cast<Edition> (raw_edition);
}
- const Edition &get_edition () { return edition; }
+ const Edition &get_edition () const { return edition; }
+
+ void set_compile_step (int raw_step)
+ {
+ compile_until = static_cast<CompileStep> (raw_step);
+ }
+
+ const CompileStep &get_compile_until () const { return compile_until; }
void set_metadata_output (const std::string &path)
{
diff --git a/gcc/testsuite/rust/compile/const_generics_7.rs b/gcc/testsuite/rust/compile/const_generics_7.rs
new file mode 100644
index 0000000..2c128db
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_generics_7.rs
@@ -0,0 +1,17 @@
+struct S<const N: usize>;
+
+pub fn foo<const N: FooBar>() {} // { dg-error "failed to resolve" }
+type Foo<const N: FooBar> = S<N>; // { dg-error "failed to resolve" }
+struct Foo2<const N: FooBar>; // { dg-error "failed to resolve" }
+enum Foo3<const N: FooBar> { // { dg-error "failed to resolve" }
+ Foo,
+ Bar,
+}
+union Foo4<const N: FooBar> { // { dg-error "failed to resolve" }
+ a: usize,
+ b: i32,
+}
+trait Fooable<const N: FooBar> {} // { dg-error "failed to resolve" }
+
+trait Traitable {}
+impl<const N: FooBar> Traitable for Foo2<N> {} // { dg-error "failed to resolve" }
diff --git a/gcc/testsuite/rust/compile/const_generics_8.rs b/gcc/testsuite/rust/compile/const_generics_8.rs
new file mode 100644
index 0000000..b0bb262
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_generics_8.rs
@@ -0,0 +1,12 @@
+struct Bidule<const N: i32 = 15> {}
+enum Bidoule<const N: i32 = 15> {}
+
+// Note - missing generic parameter - needs name resolution on const generics
+type Bipboupe<const N: i32 = 15> = Bidule;
+trait Fooable<const N: i32 = 15> {}
+
+union Bidoulepe<const N: i32 = 15> {} // { dg-error "default values for const generic parameters are not allowed in .union. items" }
+fn const_default<const N: i32 = 15>() {} // { dg-error "default values for const generic parameters are not allowed in .function. items" }
+
+// Note - missing generic parameter - needs name resolution on const generics
+impl<const N: i32 = 15> Bidule {} // { dg-error "default values for const generic parameters are not allowed in .impl. items" }
diff --git a/gcc/testsuite/rust/compile/frust-compile-until.rs b/gcc/testsuite/rust/compile/frust-compile-until.rs
new file mode 100644
index 0000000..7bb3932
--- /dev/null
+++ b/gcc/testsuite/rust/compile/frust-compile-until.rs
@@ -0,0 +1,7 @@
+// { dg-additional-options "-frust-compile-until=unsafety" }
+
+unsafe fn foo() {}
+
+fn main() {
+ foo()
+}
diff --git a/gcc/testsuite/rust/compile/macro44.rs b/gcc/testsuite/rust/compile/macro44.rs
new file mode 100644
index 0000000..84b2cdb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro44.rs
@@ -0,0 +1,34 @@
+mod foo {
+ mod bar {
+ mod baz {
+ macro_rules! baz {
+ () => {{}};
+ }
+ }
+ }
+
+ macro_rules! foo {
+ () => {{}};
+ }
+
+ fn foo_f() { // { dg-warning "function is never used" }
+ foo!();
+ }
+
+ fn bar_f() { // { dg-warning "function is never used" }
+ baz!();
+ }
+}
+
+mod foo2 {
+ #[macro_export]
+ macro_rules! bar1 {
+ () => {};
+ }
+
+ macro_rules! bar2 {
+ () => {};
+ }
+}
+
+fn main() {}