diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6911885471..9f16838bfc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -110,6 +110,9 @@ jobs: env: IGNORE_TESTS: ${{ matrix.ignore_tests }} + - name: Run glsl-lang-pp/additional tests + run: cargo test -p glsl-lang-pp --test additional --features full + - name: Run glsl-lang-pp/glslang tests run: cargo test -p glsl-lang-pp --test glslang --features full diff --git a/lang-pp/src/processor/expand.rs b/lang-pp/src/processor/expand.rs index 3cc68496e3..5914cc8c3a 100644 --- a/lang-pp/src/processor/expand.rs +++ b/lang-pp/src/processor/expand.rs @@ -417,7 +417,12 @@ impl ExpandOne { errors.push(ProcessingErrorKind::DirectiveElif(error)); } - value + if !self.if_stack.none() { + // Always false if the last if state was activated once + false + } else { + value + } } else { // Do not evaluate if the group is not active true diff --git a/lang-pp/src/processor/expand/if_stack.rs b/lang-pp/src/processor/expand/if_stack.rs index 86f90ae63e..8c3873fd3e 100644 --- a/lang-pp/src/processor/expand/if_stack.rs +++ b/lang-pp/src/processor/expand/if_stack.rs @@ -20,6 +20,10 @@ impl IfState { } } + pub fn none(&self) -> bool { + matches!(self, Self::None) + } + pub fn active(&self) -> bool { matches!(self, Self::Active { .. }) } @@ -95,6 +99,10 @@ impl IfStack { self.stack.last().map(|top| top.active()).unwrap_or(true) } + pub fn none(&self) -> bool { + self.stack.last().map(|top| top.none()).unwrap_or(false) + } + pub fn on_if_like(&mut self, expr: bool) { if self.active() && expr { self.stack.push(IfState::Active { else_seen: false }); diff --git a/lang-pp/tests/additional.rs b/lang-pp/tests/additional.rs new file mode 100644 index 0000000000..d5765d4d19 --- /dev/null +++ b/lang-pp/tests/additional.rs @@ -0,0 +1,55 @@ +#![cfg(feature = "full")] + +use std::path::PathBuf; + +use glsl_lang_pp::{ + exts::DEFAULT_REGISTRY, + last::{Event, TokenState}, + types::Token, +}; + +#[test] +fn test_issue_61() { + // See https://github.com/alixinne/glsl-lang/pull/61 + let path: PathBuf = "../lang-pp/tests/issue_61.glsl".into(); + let mut pp = glsl_lang_pp::processor::fs::StdProcessor::default(); + + let parsed = match pp.parse(&path) { + Ok(inner) => Ok(inner), + Err(err) => { + if err.kind() == std::io::ErrorKind::InvalidData { + std::fs::read(&path).map(|value| { + pp.parse_source( + encoding_rs::WINDOWS_1252.decode(&value).0.as_ref(), + path.parent().unwrap(), + ) + }) + } else { + Err(err) + } + } + } + .expect("failed to open file"); + + assert_eq!( + parsed + .into_iter() + .tokenize(300, false, &DEFAULT_REGISTRY) + .filter_map(|token| { + // Extract float constants which are not excluded by the preprocessor + if let Ok(Event::Token { + state: TokenState::Active, + token_kind: Token::FLOAT_CONST(val), + .. + }) = token + { + return Some(val); + } + + return None; + }) + .collect::>(), + // Only one pp branch should be active, so only one constant is produced + vec![1.0] + ); +} diff --git a/lang-pp/tests/issue_61.glsl b/lang-pp/tests/issue_61.glsl new file mode 100644 index 0000000000..a77b6beaee --- /dev/null +++ b/lang-pp/tests/issue_61.glsl @@ -0,0 +1,16 @@ +#version 300 es +#define CS1 +#define CS2 +#define CS3 + +vec3 test() { +#if defined(CS1) + return 1.0; +#elif defined(CS2) + return 2.0; +#elif defined(CS3) + return 3.0; +#else + return 4.0; +#endif +}