aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-04-13 14:17:42 +0000
committerGitHub <noreply@github.com>2022-04-13 14:17:42 +0000
commit60324125c3dbfd2f1551ec41dcfd4322ca80d6fa (patch)
tree5b14afb96ad6767da71274de0547328cc5227969
parent497ee70b776574aa3559c7d49a5cc7cf359d320e (diff)
parenta125901c55ea18dc7aa1d34b5d938d1e8352d5f1 (diff)
downloadgcc-60324125c3dbfd2f1551ec41dcfd4322ca80d6fa.zip
gcc-60324125c3dbfd2f1551ec41dcfd4322ca80d6fa.tar.gz
gcc-60324125c3dbfd2f1551ec41dcfd4322ca80d6fa.tar.bz2
Merge #1088
1088: rust-session-manager: better crate name handling logic r=philberty a=liushuyu - rust-session-manager: set and validate crate name properly - testsuite/rust: fix the testcases and add more testcases for testing crate name handling Co-authored-by: liushuyu <liushuyu011@gmail.com>
-rw-r--r--gcc/rust/rust-lang.cc1
-rw-r--r--gcc/rust/rust-session-manager.cc133
-rw-r--r--gcc/rust/rust-session-manager.h14
-rw-r--r--gcc/testsuite/rust/compile/bad-crate-name.rs4
-rw-r--r--gcc/testsuite/rust/compile/bad=file-name.rs7
-rw-r--r--gcc/testsuite/rust/compile/bad_file_name.txt.rs3
-rw-r--r--gcc/testsuite/rust/compile/canonical_paths1.rs2
-rw-r--r--gcc/testsuite/rust/compile/infer-crate-name.rs7
-rw-r--r--gcc/testsuite/rust/compile/specify-crate-name.rs7
-rw-r--r--gcc/testsuite/rust/compile/torture/struct_decl.rs2
-rw-r--r--gcc/testsuite/rust/compile/traits9.rs1
11 files changed, 170 insertions, 11 deletions
diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc
index c746941..4584c93 100644
--- a/gcc/rust/rust-lang.cc
+++ b/gcc/rust/rust-lang.cc
@@ -458,6 +458,7 @@ run_rust_tests ()
simple_assert ();
rust_cfg_parser_test ();
rust_privacy_ctx_test ();
+ rust_crate_name_validation_test ();
}
} // namespace selftest
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index ec99be7..bdab0d8 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -35,6 +35,7 @@
#include "diagnostic.h"
#include "input.h"
#include "rust-target.h"
+#include "selftest.h"
extern bool
saw_errors (void);
@@ -54,7 +55,65 @@ const char *kHIRDumpFile = "gccrs.hir.dump";
const char *kHIRTypeResolutionDumpFile = "gccrs.type-resolution.dump";
const char *kTargetOptionsDumpFile = "gccrs.target-options.dump";
-const std::string kDefaultCrateName = "example";
+const std::string kDefaultCrateName = "rust_out";
+const size_t kMaxNameLength = 64;
+
+static std::string
+infer_crate_name (const std::string &filename)
+{
+ if (filename == "-")
+ return kDefaultCrateName;
+
+ std::string crate = std::string (filename);
+ size_t path_sep = crate.find_last_of (file_separator);
+
+ // find the base filename
+ if (path_sep != std::string::npos)
+ crate.erase (0, path_sep + 1);
+
+ // find the file stem name (remove file extension)
+ size_t ext_position = crate.find_last_of ('.');
+ if (ext_position != std::string::npos)
+ crate.erase (ext_position);
+
+ // Replace all the '-' symbols with '_' per Rust rules
+ for (auto &c : crate)
+ {
+ if (c == '-')
+ c = '_';
+ }
+ return crate;
+}
+
+/* Validate the crate name using the ASCII rules
+ TODO: Support Unicode version of the rules */
+
+static bool
+validate_crate_name (const std::string &crate_name, Error &error)
+{
+ if (crate_name.empty ())
+ {
+ error = Error (Location (), "crate name cannot be empty");
+ return false;
+ }
+ if (crate_name.length () > kMaxNameLength)
+ {
+ error = Error (Location (), "crate name cannot exceed %ld characters",
+ kMaxNameLength);
+ return false;
+ }
+ for (auto &c : crate_name)
+ {
+ if (!(ISALNUM (c) || c == '_'))
+ {
+ error = Error (Location (),
+ "invalid character %<%c%> in crate name: %<%s%>", c,
+ crate_name.c_str ());
+ return false;
+ }
+ }
+ return true;
+}
// Implicitly enable a target_feature (and recursively enable dependencies).
void
@@ -311,10 +370,6 @@ Session::init ()
// setup backend to GCC GIMPLE
backend = rust_get_backend ();
-
- // set the default crate name if crate name was unset
- if (options.crate_name.empty ())
- options.set_crate_name (kDefaultCrateName);
}
/* Initialise default options. Actually called before handle_option, unlike init
@@ -347,7 +402,16 @@ Session::handle_option (
case OPT_frust_crate_:
// set the crate name
if (arg != nullptr)
- ret = options.set_crate_name (arg);
+ {
+ auto error = Error (Location (), std::string ());
+ if ((ret = validate_crate_name (arg, error)))
+ options.set_crate_name (arg);
+ else
+ {
+ rust_assert (!error.message.empty ());
+ error.emit_error ();
+ }
+ }
else
ret = false;
break;
@@ -479,6 +543,32 @@ Session::enable_dump (std::string arg)
void
Session::parse_files (int num_files, const char **files)
{
+ if (options.crate_name.empty ())
+ {
+ /* HACK: We use the first file to infer the crate name, which might be
+ * incorrect: since rustc only allows one file to be supplied in the
+ * command-line */
+ auto filename = "-";
+ if (num_files > 0)
+ filename = files[0];
+
+ auto crate_name = infer_crate_name (filename);
+ Error error ((Location ()), std::string ());
+ rust_debug ("inferred crate name: %s", crate_name.c_str ());
+ if (!validate_crate_name (crate_name, error))
+ {
+ // fake a linemapping so that we can show the filename
+ linemap->start_file (filename, 0);
+ linemap->start_line (0, 1);
+ error.emit_error ();
+ rust_inform (linemap->get_location (0),
+ "crate name inferred from this file");
+ linemap->stop ();
+ return;
+ }
+ options.set_crate_name (crate_name);
+ }
+
auto mappings = Analysis::Mappings::get ();
CrateNum crate_num = mappings->setup_crate_mappings (options.crate_name);
mappings->set_current_crate (crate_num);
@@ -1121,3 +1211,34 @@ TargetOptions::enable_implicit_feature_reqs (std::string feature)
* - code generation
* - link */
} // namespace Rust
+
+#if CHECKING_P
+namespace selftest {
+void
+rust_crate_name_validation_test (void)
+{
+ auto error = Rust::Error (Location (), std::string ());
+ ASSERT_TRUE (Rust::validate_crate_name ("example", error));
+ ASSERT_TRUE (Rust::validate_crate_name ("abcdefg_1234", error));
+ ASSERT_TRUE (Rust::validate_crate_name ("1", error));
+ // FIXME: The next test does not pass as of current implementation
+ // ASSERT_TRUE (Rust::CompileOptions::validate_crate_name ("惊吓"));
+ // NOTE: - is not allowed in the crate name ...
+
+ ASSERT_FALSE (Rust::validate_crate_name ("abcdefg-1234", error));
+ ASSERT_FALSE (Rust::validate_crate_name ("a+b", error));
+ ASSERT_FALSE (Rust::validate_crate_name ("/a+b/", error));
+
+ /* Tests for crate name inference */
+ ASSERT_EQ (Rust::infer_crate_name ("c.rs"), "c");
+ // NOTE: ... but - is allowed when in the filename
+ ASSERT_EQ (Rust::infer_crate_name ("a-b.rs"), "a_b");
+ ASSERT_EQ (Rust::infer_crate_name ("book.rs.txt"), "book.rs");
+#if defined(HAVE_DOS_BASED_FILE_SYSTEM)
+ ASSERT_EQ (Rust::infer_crate_name ("a\\c\\a-b.rs"), "a_b");
+#else
+ ASSERT_EQ (Rust::infer_crate_name ("a/c/a-b.rs"), "a_b");
+#endif
+}
+} // namespace selftest
+#endif // CHECKING_P
diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h
index 8fcc5dd..6fa83d9 100644
--- a/gcc/rust/rust-session-manager.h
+++ b/gcc/rust/rust-session-manager.h
@@ -22,6 +22,7 @@
#include "rust-linemap.h"
#include "rust-backend.h"
+#include "safe-ctype.h"
#include "config.h"
#include "rust-system.h"
@@ -212,11 +213,11 @@ struct CompileOptions
enable_dump_option (DumpOption::TYPE_RESOLUTION_DUMP);
}
- bool set_crate_name (std::string name)
+ void set_crate_name (std::string name)
{
- // TODO: validate the crate name?
+ rust_assert (!name.empty ());
+
crate_name = std::move (name);
- return true;
}
void set_edition (int raw_edition)
@@ -304,4 +305,11 @@ private:
};
} // namespace Rust
+#if CHECKING_P
+namespace selftest {
+extern void
+rust_crate_name_validation_test (void);
+}
+#endif // CHECKING_P
+
#endif
diff --git a/gcc/testsuite/rust/compile/bad-crate-name.rs b/gcc/testsuite/rust/compile/bad-crate-name.rs
new file mode 100644
index 0000000..6c59c255
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad-crate-name.rs
@@ -0,0 +1,4 @@
+// { dg-additional-options "-frust-crate=bad+name" }
+// { dg-excess-errors "invalid crate name: ...." }
+// { dg-excess-errors "unrecognized command-line option ...." }
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/bad=file-name.rs b/gcc/testsuite/rust/compile/bad=file-name.rs
new file mode 100644
index 0000000..cfbebb0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad=file-name.rs
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fdump-tree-gimple -frust-crate=good_name" }
+pub fn does_nothing() {}
+fn main() {
+ does_nothing()
+}
+// { dg-final { scan-tree-dump-times {good_name::does_nothing} 2 gimple } }
+// { dg-final { scan-tree-dump-times {good_name::main} 1 gimple } }
diff --git a/gcc/testsuite/rust/compile/bad_file_name.txt.rs b/gcc/testsuite/rust/compile/bad_file_name.txt.rs
new file mode 100644
index 0000000..56e2093
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad_file_name.txt.rs
@@ -0,0 +1,3 @@
+// { dg-excess-errors "invalid crate name: ...." }
+// { dg-bogus "unrecognized command-line option ...." }
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/canonical_paths1.rs b/gcc/testsuite/rust/compile/canonical_paths1.rs
index af547ef..193e7b5 100644
--- a/gcc/testsuite/rust/compile/canonical_paths1.rs
+++ b/gcc/testsuite/rust/compile/canonical_paths1.rs
@@ -1,4 +1,4 @@
-// { dg-additional-options "-w -fdump-tree-gimple" }
+// { dg-additional-options "-w -fdump-tree-gimple -frust-crate=example" }
struct Foo(i32);
trait TR {
diff --git a/gcc/testsuite/rust/compile/infer-crate-name.rs b/gcc/testsuite/rust/compile/infer-crate-name.rs
new file mode 100644
index 0000000..b0c0086
--- /dev/null
+++ b/gcc/testsuite/rust/compile/infer-crate-name.rs
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fdump-tree-gimple" }
+pub fn does_nothing() {}
+fn main() {
+ does_nothing()
+}
+// { dg-final { scan-tree-dump-times {infer_crate_name::does_nothing} 2 gimple } }
+// { dg-final { scan-tree-dump-times {infer_crate_name::main} 1 gimple } }
diff --git a/gcc/testsuite/rust/compile/specify-crate-name.rs b/gcc/testsuite/rust/compile/specify-crate-name.rs
new file mode 100644
index 0000000..a867915
--- /dev/null
+++ b/gcc/testsuite/rust/compile/specify-crate-name.rs
@@ -0,0 +1,7 @@
+// { dg-additional-options "-frust-crate=fancy_crate_name -fdump-tree-gimple" }
+pub fn does_nothing() {}
+fn main() {
+ does_nothing()
+}
+// { dg-final { scan-tree-dump-times {fancy_crate_name::does_nothing} 2 gimple } }
+// { dg-final { scan-tree-dump-times {fancy_crate_name::main} 1 gimple } }
diff --git a/gcc/testsuite/rust/compile/torture/struct_decl.rs b/gcc/testsuite/rust/compile/torture/struct_decl.rs
index 965666e..9e8ea6b 100644
--- a/gcc/testsuite/rust/compile/torture/struct_decl.rs
+++ b/gcc/testsuite/rust/compile/torture/struct_decl.rs
@@ -1,4 +1,4 @@
-// { dg-additional-options -fdump-tree-gimple }
+// { dg-additional-options "-fdump-tree-gimple -frust-crate=example" }
struct Foo {
a: u16,
diff --git a/gcc/testsuite/rust/compile/traits9.rs b/gcc/testsuite/rust/compile/traits9.rs
index 7ef577a..8d81bae 100644
--- a/gcc/testsuite/rust/compile/traits9.rs
+++ b/gcc/testsuite/rust/compile/traits9.rs
@@ -1,3 +1,4 @@
+// { dg-additional-options -frust-crate=example }
struct Foo(i32);
trait Bar {
fn baz(&self);