Skip to content

Commit 56ad8d1

Browse files
committed
Add check for presence of signature in alias declarations.
1 parent cded313 commit 56ad8d1

File tree

7 files changed

+119
-39
lines changed

7 files changed

+119
-39
lines changed

vhdl_lang/src/analysis/declarative.rs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -124,22 +124,31 @@ impl<'a> AnalyzeContext<'a> {
124124
if subtype_indication.is_some() {
125125
NamedEntityKind::OtherAlias
126126
} else {
127-
let named_entity = if signature.is_some() {
128-
// @TODO use signature to select named entity
129-
resolved_name
130-
.and_then(|resolved| resolved.into_known())
131-
.map(|entities| entities.first().clone())
132-
} else {
133-
resolved_name.and_then(|resolved| resolved.into_non_overloaded())
134-
};
127+
if let Some(named_entities) =
128+
resolved_name.and_then(|name| name.into_known())
129+
{
130+
let ent = match named_entities {
131+
NamedEntities::Single(ent) => {
132+
if let Some(signature) = signature {
133+
diagnostics.error(signature, "Alias should only have a signature for subprograms and enum literals");
134+
}
135+
ent
136+
}
137+
NamedEntities::Overloaded(overloaded) => {
138+
if signature.is_none() {
139+
diagnostics.error(name, "Signature required for alias of subprogram and enum literals");
140+
}
141+
// @TODO use signature to determine variant
142+
overloaded.first().clone()
143+
}
144+
};
135145

136-
if let Some(named_entity) = named_entity {
137146
region.add_implicit_declaration_aliases(
138147
Some(&designator.pos),
139-
&named_entity,
148+
&ent,
140149
diagnostics,
141150
);
142-
NamedEntityKind::AliasOf(named_entity)
151+
NamedEntityKind::AliasOf(ent)
143152
} else {
144153
NamedEntityKind::OtherAlias
145154
}
@@ -505,10 +514,10 @@ impl<'a> AnalyzeContext<'a> {
505514
pub fn analyze_signature(
506515
&self,
507516
region: &Region<'_>,
508-
signature: &mut Signature,
517+
signature: &mut WithPos<Signature>,
509518
diagnostics: &mut dyn DiagnosticHandler,
510519
) -> FatalNullResult {
511-
match signature {
520+
match &mut signature.item {
512521
Signature::Function(ref mut args, ref mut ret) => {
513522
for arg in args.iter_mut() {
514523
if let Err(err) = self.resolve_selected_name(region, arg) {

vhdl_lang/src/analysis/tests/resolves_names.rs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,7 @@ begin
10611061
blk: block (ent_in = 1) is
10621062
generic( gen : integer := 0 );
10631063
generic map ( gen => 1);
1064-
port(
1064+
port(
10651065
prt_in : in integer := 0;
10661066
prt_out : out integer := 0
10671067
);
@@ -1076,3 +1076,55 @@ end architecture;
10761076
",
10771077
);
10781078
}
1079+
1080+
#[test]
1081+
fn error_on_signature_for_non_overloaded_alias() {
1082+
let mut builder = LibraryBuilder::new();
1083+
let code = builder.code(
1084+
"libname",
1085+
"
1086+
package pkg is
1087+
type enum_t is (alpha, beta);
1088+
alias alias_t is enum_t[return integer];
1089+
end package;
1090+
",
1091+
);
1092+
1093+
let diagnostics = builder.analyze();
1094+
check_diagnostics(
1095+
diagnostics,
1096+
vec![Diagnostic::error(
1097+
code.s1("[return integer]"),
1098+
"Alias should only have a signature for subprograms and enum literals",
1099+
)],
1100+
);
1101+
}
1102+
1103+
#[test]
1104+
fn error_on_non_signature_for_overloaded_alias() {
1105+
let mut builder = LibraryBuilder::new();
1106+
let code = builder.code(
1107+
"libname",
1108+
"
1109+
package pkg is
1110+
end package;
1111+
1112+
package body pkg is
1113+
procedure subpgm(arg: natural) is
1114+
begin
1115+
end;
1116+
1117+
alias alias_t is subpgm;
1118+
end package body;
1119+
",
1120+
);
1121+
1122+
let diagnostics = builder.analyze();
1123+
check_diagnostics(
1124+
diagnostics,
1125+
vec![Diagnostic::error(
1126+
code.s("subpgm", 2),
1127+
"Signature required for alias of subprogram and enum literals",
1128+
)],
1129+
);
1130+
}

vhdl_lang/src/ast.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ pub enum Binary {
9999
#[derive(PartialEq, Debug, Clone)]
100100
pub struct AttributeName {
101101
pub name: WithPos<Name>,
102-
pub signature: Option<Signature>,
102+
pub signature: Option<WithPos<Signature>>,
103103
pub attr: Ident,
104104
pub expr: Option<Box<WithPos<Expression>>>,
105105
}
@@ -381,7 +381,7 @@ pub struct AliasDeclaration {
381381
pub designator: WithPos<Designator>,
382382
pub subtype_indication: Option<SubtypeIndication>,
383383
pub name: WithPos<Name>,
384-
pub signature: Option<Signature>,
384+
pub signature: Option<WithPos<Signature>>,
385385
}
386386

387387
/// LRM 6.7 Attribute declarations
@@ -395,7 +395,7 @@ pub struct AttributeDeclaration {
395395
#[derive(PartialEq, Debug, Clone)]
396396
pub struct EntityTag {
397397
pub designator: WithPos<Designator>,
398-
pub signature: Option<Signature>,
398+
pub signature: Option<WithPos<Signature>>,
399399
}
400400

401401
/// LRM 7.2 Attribute specification

vhdl_lang/src/ast/search.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,9 @@ impl Search for Declaration {
828828
return_if_found!(searcher.search_decl_pos(&designator.pos).or_not_found());
829829
return_if_found!(subtype_indication.search(searcher));
830830
return_if_found!(name.search(searcher));
831-
return_if_found!(signature.search(searcher));
831+
if let Some(signature) = signature {
832+
return_if_found!(signature.item.search(searcher));
833+
}
832834
}
833835
Declaration::Use(use_clause) => return_if_found!(searcher
834836
.search_with_pos(&use_clause.pos)

vhdl_lang/src/syntax/names.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ fn parse_function_call(
191191
fn parse_attribute_name(
192192
stream: &mut TokenStream,
193193
name: WithPos<Name>,
194-
signature: Option<Signature>,
194+
signature: Option<WithPos<Signature>>,
195195
) -> ParseResult<WithPos<Name>> {
196196
let attr = stream.expect_ident_or_range()?;
197197

vhdl_lang/src/syntax/subprogram.rs

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@ use super::tokens::{Kind::*, TokenStream};
1313
use crate::ast::*;
1414
use crate::data::*;
1515

16-
pub fn parse_signature(stream: &mut TokenStream) -> ParseResult<Signature> {
17-
stream.expect_kind(LeftSquare)?;
16+
pub fn parse_signature(stream: &mut TokenStream) -> ParseResult<WithPos<Signature>> {
17+
let left_square = stream.expect_kind(LeftSquare)?;
18+
let start_pos = left_square.pos;
1819
let mut type_marks = Vec::new();
1920
let mut return_mark = None;
2021
let mut errmsg = None;
21-
loop {
22+
23+
let pos = loop {
2224
let token = stream.peek_expect()?;
2325

2426
try_token_kind!(
@@ -32,7 +34,7 @@ pub fn parse_signature(stream: &mut TokenStream) -> ParseResult<Signature> {
3234
sep_token,
3335
Comma => {},
3436
RightSquare => {
35-
break;
37+
break start_pos.combine(&sep_token.pos);
3638
},
3739
Return => {
3840
let new_return_mark = Some(parse_selected_name(stream)?);
@@ -55,19 +57,22 @@ pub fn parse_signature(stream: &mut TokenStream) -> ParseResult<Signature> {
5557
},
5658
RightSquare => {
5759
stream.move_after(&token);
58-
break;
60+
break start_pos.combine(&token.pos);
5961
}
6062
)
61-
}
63+
};
64+
6265
if let Some(diagnostic) = errmsg {
6366
// @TODO recoverable error should not return Err
6467
return Err(diagnostic);
6568
}
6669

67-
Ok(match return_mark {
70+
let signature = match return_mark {
6871
Some(return_mark) => Signature::Function(type_marks, return_mark),
6972
None => Signature::Procedure(type_marks),
70-
})
73+
};
74+
75+
Ok(WithPos::new(signature, pos))
7176
}
7277

7378
fn parse_designator(stream: &mut TokenStream) -> ParseResult<WithPos<SubprogramDesignator>> {
@@ -316,7 +321,10 @@ function foo(foo : natural) return lib.foo.natural;
316321
let code = Code::new("[return bar.type_mark]");
317322
assert_eq!(
318323
code.with_stream(parse_signature),
319-
Signature::Function(vec![], code.s1("bar.type_mark").selected_name())
324+
WithPos::new(
325+
Signature::Function(vec![], code.s1("bar.type_mark").selected_name()),
326+
code.pos()
327+
)
320328
);
321329
}
322330

@@ -325,9 +333,12 @@ function foo(foo : natural) return lib.foo.natural;
325333
let code = Code::new("[foo.type_mark return bar.type_mark]");
326334
assert_eq!(
327335
code.with_stream(parse_signature),
328-
Signature::Function(
329-
vec![code.s1("foo.type_mark").selected_name()],
330-
code.s1("bar.type_mark").selected_name()
336+
WithPos::new(
337+
Signature::Function(
338+
vec![code.s1("foo.type_mark").selected_name()],
339+
code.s1("bar.type_mark").selected_name()
340+
),
341+
code.pos()
331342
)
332343
);
333344
}
@@ -337,7 +348,10 @@ function foo(foo : natural) return lib.foo.natural;
337348
let code = Code::new("[foo.type_mark]");
338349
assert_eq!(
339350
code.with_stream(parse_signature),
340-
Signature::Procedure(vec![code.s1("foo.type_mark").selected_name()])
351+
WithPos::new(
352+
Signature::Procedure(vec![code.s1("foo.type_mark").selected_name()]),
353+
code.pos()
354+
)
341355
);
342356
}
343357

@@ -346,12 +360,15 @@ function foo(foo : natural) return lib.foo.natural;
346360
let code = Code::new("[foo.type_mark, foo2.type_mark return bar.type_mark]");
347361
assert_eq!(
348362
code.with_stream(parse_signature),
349-
Signature::Function(
350-
vec![
351-
code.s1("foo.type_mark").selected_name(),
352-
code.s1("foo2.type_mark").selected_name()
353-
],
354-
code.s1("bar.type_mark").selected_name()
363+
WithPos::new(
364+
Signature::Function(
365+
vec![
366+
code.s1("foo.type_mark").selected_name(),
367+
code.s1("foo2.type_mark").selected_name()
368+
],
369+
code.s1("bar.type_mark").selected_name()
370+
),
371+
code.pos()
355372
)
356373
);
357374
}

vhdl_lang/src/syntax/test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ impl Code {
325325
self.parse_ok(parse_selected_name)
326326
}
327327

328-
pub fn signature(&self) -> Signature {
328+
pub fn signature(&self) -> WithPos<Signature> {
329329
self.parse_ok(parse_signature)
330330
}
331331

0 commit comments

Comments
 (0)