From cc45a5893f142bfd9b73efb04aa73c63c76aa0ff Mon Sep 17 00:00:00 2001 From: splasky Date: Wed, 9 May 2018 13:44:41 +0800 Subject: [PATCH] Prohibit function parameter redefinition --- shivyc/tree/nodes.py | 29 +++++++++++++++++++++++-- tests/feature_tests/error_declaration.c | 3 +++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/shivyc/tree/nodes.py b/shivyc/tree/nodes.py index 434e291..a529cd7 100644 --- a/shivyc/tree/nodes.py +++ b/shivyc/tree/nodes.py @@ -1,5 +1,4 @@ """Nodes in the AST which represent statements or declarations.""" - import shivyc.ctypes as ctypes import shivyc.il_cmds.control as control_cmds import shivyc.il_cmds.value as value_cmds @@ -479,7 +478,7 @@ def get_linkage(self, symbol_table, c): def get_defined(self, symbol_table, c): """Determine whether this is a definition.""" if (c.is_global and self.storage in {None, self.STATIC} - and self.ctype.is_object() and not self.init): + and self.ctype.is_object() and not self.init): return symbol_table.TENTATIVE elif self.storage == self.EXTERN and not (self.init or self.body): return symbol_table.UNDEFINED @@ -598,9 +597,35 @@ def _generate_array_ctype(self, decl, prev_ctype): else: return ArrayCType(prev_ctype, None) + def _check_redefinition(self, decl): + """ + If identifier is redefinition inside function arguments, raise error + :param decl:declaration of function arguments + """ + # Save identifiers + identifiers = [decl_info.identifier for param + in decl.args for decl_info in + self.get_decl_infos(param)] + + # Remove None inside identifiers + identifiers = [str(x) for x in identifiers if x is not None] + + # Exit if no identifiers exist + if len(identifiers) == 0: + return + + # Check duplicate identifier + for identifier in identifiers: + if identifiers.count(identifier) > 1: + err = f"redefinition of '{identifier}'" + raise CompilerError(err, self.r) + def _generate_func_ctype(self, decl, prev_ctype): """Generate a function ctype from a given a decl_node.""" + # Prohibit redefinition of identifer + self._check_redefinition(decl) + # Prohibit storage class specifiers in parameters. for param in decl.args: decl_info = self.get_decl_infos(param)[0] diff --git a/tests/feature_tests/error_declaration.c b/tests/feature_tests/error_declaration.c index cd770ef..2c721a5 100644 --- a/tests/feature_tests/error_declaration.c +++ b/tests/feature_tests/error_declaration.c @@ -22,6 +22,9 @@ int var1; // error: redeclared 'var1' with different linkage static int var1; +// error: redefinition of 'a' +void repeat_param(int a, int a); + int main() { // error: variable of incomplete type declared void a;