From 0a2278f12a4e0c9c2d7722f134d6bc150e153bc4 Mon Sep 17 00:00:00 2001 From: Olof Kraigher Date: Mon, 13 Nov 2023 17:59:42 +0100 Subject: [PATCH] Handle ambigous argument to 'val attribute --- vhdl_lang/src/analysis/expression.rs | 34 -------------------------- vhdl_lang/src/analysis/names.rs | 36 ++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/vhdl_lang/src/analysis/expression.rs b/vhdl_lang/src/analysis/expression.rs index 56f44d09..b3eb7d97 100644 --- a/vhdl_lang/src/analysis/expression.rs +++ b/vhdl_lang/src/analysis/expression.rs @@ -638,40 +638,6 @@ impl<'a> AnalyzeContext<'a> { } } - /// An expression of any integer type - pub fn integer_expr( - &self, - scope: &Scope<'a>, - expr: &mut WithPos, - diagnostics: &mut dyn DiagnosticHandler, - ) -> FatalResult { - if let Some(types) = as_fatal(self.expr_type(scope, expr, diagnostics))? { - match types { - ExpressionType::Unambiguous(typ) => { - if !typ.base().is_any_integer() { - diagnostics.error( - &expr.pos, - format!("Expected integer type, got {}", typ.describe()), - ) - } - } - ExpressionType::Ambiguous(types) => { - // @TODO does not check if type is ambiguous - if types.iter().any(|typ| !typ.is_any_integer()) { - diagnostics.error(&expr.pos, "Expected integer type") - } - } - ExpressionType::String | ExpressionType::Null | ExpressionType::Aggregate => { - diagnostics.error( - &expr.pos, - format!("Expected integer type, got {}", types.describe()), - ) - } - } - } - Ok(()) - } - /// An expression that is either boolean or implicitly boolean via ?? operator pub fn boolean_expr( &self, diff --git a/vhdl_lang/src/analysis/names.rs b/vhdl_lang/src/analysis/names.rs index d9860185..ad0667a2 100644 --- a/vhdl_lang/src/analysis/names.rs +++ b/vhdl_lang/src/analysis/names.rs @@ -846,7 +846,12 @@ impl<'a> AnalyzeContext<'a> { if typ.base().is_discrete() { if let Some(ref mut expr) = check_single_argument(name_pos, attr, diagnostics) { - self.integer_expr(scope, expr, diagnostics)?; + self.expr_with_ttyp( + scope, + self.universal_integer().into(), + expr, + diagnostics, + )?; } Ok(AttrResolveResult::Value(typ.base())) } else { @@ -2554,7 +2559,7 @@ constant c0 : arr_t := (others => 0); diagnostics, vec![Diagnostic::error( code.s1("'a'"), - "Expected integer type, got type 'CHARACTER'", + "character literal does not match type universal_integer", )], ); @@ -2591,6 +2596,33 @@ constant c0 : arr_t := (others => 0); ); } + /// This is a regression test + #[test] + fn val_attribute_with_overloaded_name() { + let test = TestSetup::new(); + + test.declarative_part( + " +impure function pop return integer is +begin +end function; + +impure function pop return boolean is +begin +end function; + +type enum_t is (alpha, beta); + ", + ); + let code = test.snippet("enum_t'val(pop)"); + assert_eq!( + test.name_resolve(&code, None, &mut NoDiagnostics), + Ok(ResolvedName::Expression(DisambiguatedType::Unambiguous( + test.lookup_type("enum_t") + ))) + ); + } + #[test] fn signal_attributes_on_non_signal() { let test = TestSetup::new();