about summary refs log tree commit diff
path: root/compiler/rustc_session/src
diff options
context:
space:
mode:
authorLoïc BRANSTETT <lolo.branstett@numericable.fr>2021-09-29 02:39:30 +0200
committerLoïc BRANSTETT <lolo.branstett@numericable.fr>2022-02-16 13:03:12 +0100
commit3a73ca587bb8a8fb52d6045fbe31d50d5a56ff19 (patch)
tree37a0d4e25436b3524bb8e1b876f009dad1824f64 /compiler/rustc_session/src
parent6499c5e7fc173a3f55b7a3bd1e6a50e9edef782d (diff)
downloadrust-3a73ca587bb8a8fb52d6045fbe31d50d5a56ff19.tar.gz
rust-3a73ca587bb8a8fb52d6045fbe31d50d5a56ff19.zip
Implement --check-cfg option (RFC 3013)
Co-authored-by: Urgau <lolo.branstett@numericable.fr>
Co-authored-by: Marcelina Kościelnicka <mwk@0x04.net>
Diffstat (limited to 'compiler/rustc_session/src')
-rw-r--r--compiler/rustc_session/src/config.rs89
-rw-r--r--compiler/rustc_session/src/parse.rs4
2 files changed, 92 insertions, 1 deletions
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 8630ffec241..f90766875d2 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -16,7 +16,7 @@ use rustc_target::spec::{LinkerFlavor, SplitDebuginfo, Target, TargetTriple, Tar
 
 use rustc_serialize::json;
 
-use crate::parse::CrateConfig;
+use crate::parse::{CrateCheckConfig, CrateConfig};
 use rustc_feature::UnstableFeatures;
 use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION};
 use rustc_span::source_map::{FileName, FilePathMapping};
@@ -921,6 +921,7 @@ pub const fn default_lib_output() -> CrateType {
 }
 
 fn default_configuration(sess: &Session) -> CrateConfig {
+    // NOTE: This should be kept in sync with `CrateCheckConfig::fill_well_known` below.
     let end = &sess.target.endian;
     let arch = &sess.target.arch;
     let wordsz = sess.target.pointer_width.to_string();
@@ -1005,6 +1006,91 @@ pub fn to_crate_config(cfg: FxHashSet<(String, Option<String>)>) -> CrateConfig
     cfg.into_iter().map(|(a, b)| (Symbol::intern(&a), b.map(|b| Symbol::intern(&b)))).collect()
 }
 
+/// The parsed `--check-cfg` options
+pub struct CheckCfg<T = String> {
+    /// Set if `names()` checking is enabled
+    pub names_checked: bool,
+    /// The union of all `names()`
+    pub names_valid: FxHashSet<T>,
+    /// The set of names for which `values()` was used
+    pub values_checked: FxHashSet<T>,
+    /// The set of all (name, value) pairs passed in `values()`
+    pub values_valid: FxHashSet<(T, T)>,
+}
+
+impl<T> Default for CheckCfg<T> {
+    fn default() -> Self {
+        CheckCfg {
+            names_checked: false,
+            names_valid: FxHashSet::default(),
+            values_checked: FxHashSet::default(),
+            values_valid: FxHashSet::default(),
+        }
+    }
+}
+
+impl<T> CheckCfg<T> {
+    fn map_data<O: Eq + Hash>(&self, f: impl Fn(&T) -> O) -> CheckCfg<O> {
+        CheckCfg {
+            names_checked: self.names_checked,
+            names_valid: self.names_valid.iter().map(|a| f(a)).collect(),
+            values_checked: self.values_checked.iter().map(|a| f(a)).collect(),
+            values_valid: self.values_valid.iter().map(|(a, b)| (f(a), f(b))).collect(),
+        }
+    }
+}
+
+/// Converts the crate `--check-cfg` options from `String` to `Symbol`.
+/// `rustc_interface::interface::Config` accepts this in the compiler configuration,
+/// but the symbol interner is not yet set up then, so we must convert it later.
+pub fn to_crate_check_config(cfg: CheckCfg) -> CrateCheckConfig {
+    cfg.map_data(|s| Symbol::intern(s))
+}
+
+impl CrateCheckConfig {
+    /// Fills a `CrateCheckConfig` with well-known configuration names.
+    pub fn fill_well_known(&mut self) {
+        // NOTE: This should be kept in sync with `default_configuration`
+        const WELL_KNOWN_NAMES: &[Symbol] = &[
+            sym::unix,
+            sym::windows,
+            sym::target_os,
+            sym::target_family,
+            sym::target_arch,
+            sym::target_endian,
+            sym::target_pointer_width,
+            sym::target_env,
+            sym::target_abi,
+            sym::target_vendor,
+            sym::target_thread_local,
+            sym::target_has_atomic_load_store,
+            sym::target_has_atomic,
+            sym::target_has_atomic_equal_alignment,
+            sym::panic,
+            sym::sanitize,
+            sym::debug_assertions,
+            sym::proc_macro,
+            sym::test,
+            sym::doc,
+            sym::doctest,
+            sym::feature,
+        ];
+        for &name in WELL_KNOWN_NAMES {
+            self.names_valid.insert(name);
+        }
+    }
+
+    /// Fills a `CrateCheckConfig` with configuration names and values that are actually active.
+    pub fn fill_actual(&mut self, cfg: &CrateConfig) {
+        for &(k, v) in cfg {
+            self.names_valid.insert(k);
+            if let Some(v) = v {
+                self.values_valid.insert((k, v));
+            }
+        }
+    }
+}
+
 pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateConfig {
     // Combine the configuration requested by the session (command line) with
     // some default and generated configuration items.
@@ -1148,6 +1234,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
     vec![
         opt::flag_s("h", "help", "Display this message"),
         opt::multi_s("", "cfg", "Configure the compilation environment", "SPEC"),
+        opt::multi("", "check-cfg", "Provide list of valid cfg options for checking", "SPEC"),
         opt::multi_s(
             "L",
             "",
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index d5b520325e5..7113f9b0a2f 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -1,6 +1,7 @@
 //! Contains `ParseSess` which holds state living beyond what one `Parser` might.
 //! It also serves as an input to the parser itself.
 
+use crate::config::CheckCfg;
 use crate::lint::{BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId};
 use rustc_ast::node_id::NodeId;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -18,6 +19,7 @@ use std::str;
 /// The set of keys (and, optionally, values) that define the compilation
 /// environment of the crate, used to drive conditional compilation.
 pub type CrateConfig = FxHashSet<(Symbol, Option<Symbol>)>;
+pub type CrateCheckConfig = CheckCfg<Symbol>;
 
 /// Collected spans during parsing for places where a certain feature was
 /// used and should be feature gated accordingly in `check_crate`.
@@ -117,6 +119,7 @@ pub struct ParseSess {
     pub span_diagnostic: Handler,
     pub unstable_features: UnstableFeatures,
     pub config: CrateConfig,
+    pub check_config: CrateCheckConfig,
     pub edition: Edition,
     pub missing_fragment_specifiers: Lock<FxHashMap<Span, NodeId>>,
     /// Places where raw identifiers were used. This is used to avoid complaining about idents
@@ -162,6 +165,7 @@ impl ParseSess {
             span_diagnostic: handler,
             unstable_features: UnstableFeatures::from_environment(None),
             config: FxHashSet::default(),
+            check_config: CrateCheckConfig::default(),
             edition: ExpnId::root().expn_data().edition,
             missing_fragment_specifiers: Default::default(),
             raw_identifier_spans: Lock::new(Vec::new()),