mirror of https://github.com/ecmwf/eccodes.git
Fixed sizeof parse bug
This commit is contained in:
parent
0d3692512e
commit
5999f9001b
|
@ -508,6 +508,7 @@ class AstParser:
|
|||
return literal.Literal(tokens[0])
|
||||
|
||||
def parse_PAREN_EXPR(self, node):
|
||||
|
||||
children = list(node.get_children())
|
||||
assert len(children) == 1, f"Expected exactly one child for paren expression"
|
||||
expression = children[0]
|
||||
|
@ -521,16 +522,20 @@ class AstParser:
|
|||
keyword = node.spelling
|
||||
if not keyword:
|
||||
# Some unary expressions (e.g. sizeof) give an empty keyword, but we can extract it
|
||||
# from the first token. In this case we have no child nodes and have to extract
|
||||
# the expression from the tokens as well
|
||||
# from the first token.
|
||||
tokens = [token.spelling for token in node.get_tokens()]
|
||||
keyword = tokens[0]
|
||||
assert keyword == "sizeof", f"Unexpected keyword [{keyword}] - not able to parse this (yet!)"
|
||||
|
||||
children = list(node.get_children())
|
||||
child_count = len(children)
|
||||
|
||||
if child_count == 0:
|
||||
# No child nodes so extract expression from tokens...
|
||||
expression_text = literal.Literal(" ".join([t for t in tokens[2:-1]]))
|
||||
expression = paren_expression.ParenExpression(expression_text)
|
||||
else:
|
||||
children = list(node.get_children())
|
||||
assert len(children) == 1, f"Expected exactly one child for unary expression, got [{len(children)}]"
|
||||
assert child_count == 1, f"Expected a maximum of one child for unary expression, got [{child_count}]"
|
||||
expression = self.parse_ast_node(children[0])
|
||||
|
||||
c_unary_expr = unary_expression.UnaryExpression(keyword, expression)
|
||||
|
@ -677,6 +682,9 @@ class AstParser:
|
|||
|
||||
def parse_CSTYLE_CAST_EXPR(self, node):
|
||||
|
||||
debug.line("parse_CSTYLE_CAST_EXPR", f"Node dump:")
|
||||
ast_utils.dump_node(node)
|
||||
|
||||
tokens = [token.spelling for token in node.get_tokens()]
|
||||
assert tokens[0] == "("
|
||||
|
||||
|
@ -687,9 +695,10 @@ class AstParser:
|
|||
|
||||
children = list(node.get_children())
|
||||
child_count = len(children)
|
||||
assert child_count == 1, f"Expected exactly one child node for cast expression, but got [{child_count}]"
|
||||
if child_count != 1:
|
||||
debug.line("parse_CSTYLE_CAST_EXPR", f"Expected exactly one child node for cast expression, but got [{child_count}] - we'll process the last node as the expression")
|
||||
|
||||
cexpression = self.parse_ast_node(children[0])
|
||||
cexpression = self.parse_ast_node(children[-1])
|
||||
|
||||
ccast_expression = cast_expression.CastExpression("C", ccast_value, cexpression)
|
||||
|
||||
|
|
|
@ -9,31 +9,44 @@ from code_object.array_access import ArrayAccess
|
|||
from code_object.struct_member_access import StructMemberAccess
|
||||
from code_object.value_declaration_reference import ValueDeclarationReference
|
||||
from code_object.unary_operation import UnaryOperation
|
||||
from code_object.unary_expression import UnaryExpression
|
||||
from code_object.paren_expression import ParenExpression
|
||||
|
||||
# Try to extract a name value from the object, else return ""
|
||||
def extract_name(cpp_obj):
|
||||
|
||||
debug.line("extract_name", f"[IN] cpp_obj=[{debug.as_debug_string(cpp_obj)}] type=[{type(cpp_obj)}]")
|
||||
|
||||
assert isinstance(cpp_obj, CodeInterface), f"Expected CodeInterfacce, got [{type(cpp_obj).__name__}]"
|
||||
|
||||
cppname = ""
|
||||
|
||||
if isinstance(cpp_obj, Literal):
|
||||
return cpp_obj.value
|
||||
cppname = cpp_obj.value
|
||||
elif isinstance(cpp_obj, Arg):
|
||||
return cpp_obj.name
|
||||
cppname = cpp_obj.name
|
||||
elif isinstance(cpp_obj, StructArg):
|
||||
return cpp_obj.name
|
||||
cppname = cpp_obj.name
|
||||
elif isinstance(cpp_obj, VariableDeclaration):
|
||||
return cpp_obj.variable
|
||||
cppname = cpp_obj.variable
|
||||
elif isinstance(cpp_obj, ArrayAccess):
|
||||
return cpp_obj.name
|
||||
cppname = cpp_obj.name
|
||||
elif isinstance(cpp_obj, StructMemberAccess):
|
||||
return cpp_obj.name
|
||||
cppname = cpp_obj.name
|
||||
elif isinstance(cpp_obj, ValueDeclarationReference):
|
||||
return cpp_obj.value
|
||||
cppname = cpp_obj.value
|
||||
elif isinstance(cpp_obj, UnaryOperation):
|
||||
# Operand will a CodeInterface, so we need to recurse!
|
||||
return extract_name(cpp_obj.operand)
|
||||
cppname = extract_name(cpp_obj.operand)
|
||||
elif isinstance(cpp_obj, UnaryExpression):
|
||||
# expression will a CodeInterface, so we need to recurse!
|
||||
cppname = extract_name(cpp_obj.expression)
|
||||
elif isinstance(cpp_obj, ParenExpression):
|
||||
# expression will a paren_expression, so we need to recurse!
|
||||
cppname = extract_name(cpp_obj.expression)
|
||||
|
||||
return ""
|
||||
debug.line("extract_name", f"[OUT] cpp_obj=[{debug.as_debug_string(cpp_obj)}] -> cppname=[{cppname}]")
|
||||
return cppname
|
||||
|
||||
# If the code_object has an Arg representation, then this will be returned,
|
||||
# otherwise None
|
||||
|
@ -42,9 +55,11 @@ def to_cpparg(cpp_obj, conversion_data):
|
|||
|
||||
assert isinstance(cpp_obj, CodeInterface), f"Expected CodeInterfacce, got [{type(cpp_obj).__name__}]"
|
||||
|
||||
cppname = extract_name(cpp_obj)
|
||||
if cppname:
|
||||
cpparg = conversion_data.cpparg_for_cppname(cppname)
|
||||
name = extract_name(cpp_obj)
|
||||
if name:
|
||||
cpparg = conversion_data.cpparg_for_cppname(name)
|
||||
if not cpparg:
|
||||
cpparg = conversion_data.cpparg_for_cname(name)
|
||||
|
||||
assert cpparg is None or isinstance(cpparg, Arg), f"cpparg should be Arg, not [{type(cpparg).__name__}]"
|
||||
|
||||
|
|
|
@ -78,10 +78,10 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation):
|
|||
|
||||
if cppunary_expression.keyword == "sizeof":
|
||||
assert isinstance(cppunary_expression.expression, paren_expression.ParenExpression)
|
||||
cpparg = arg_utils.to_cpparg(cppunary_expression.expression.expression, self._conversion_data)
|
||||
cpparg = arg_utils.to_cpparg(cppunary_expression.expression, self._conversion_data)
|
||||
if cpparg and self._conversion_data.is_container_type(cpparg.decl_spec.type):
|
||||
cpp_size_call = literal.Literal(f"{cpparg.name}.size()")
|
||||
debug.line("validate_unary_operation", f"Updating size evaluation: [{debug.as_debug_string(cppunary_expression)}]->[{debug.as_debug_string(cpp_size_call)}]")
|
||||
debug.line("validate_unary_expression", f"Updating size evaluation: [{debug.as_debug_string(cppunary_expression)}]->[{debug.as_debug_string(cpp_size_call)}]")
|
||||
return cpp_size_call
|
||||
|
||||
return cppunary_expression
|
||||
|
@ -94,9 +94,14 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation):
|
|||
|
||||
if cpparg:
|
||||
if self._conversion_data.is_container_type(cpparg.decl_spec.type):
|
||||
# C++ variable is a container, so we'll strip the *
|
||||
debug.line("validate_unary_operation", f"Stripping [*] from cppunary_operation=[{debug.as_debug_string(cppunary_operation)}]")
|
||||
return cppunary_operation.operand
|
||||
if cppunary_operation.unary_op.value == "!":
|
||||
cpp_empty_call = literal.Literal(f"{cpparg.name}.empty()")
|
||||
debug.line("validate_unary_operation", f"Updating empty evaluation: [{debug.as_debug_string(cppunary_operation)}]->[{debug.as_debug_string(cpp_empty_call)}]")
|
||||
return cpp_empty_call
|
||||
else:
|
||||
# C++ variable is a container, so we'll strip the *
|
||||
debug.line("validate_unary_operation", f"Stripping [*] from cppunary_operation=[{debug.as_debug_string(cppunary_operation)}]")
|
||||
return cppunary_operation.operand
|
||||
elif cpparg.decl_spec.pointer == "&":
|
||||
debug.line("validate_unary_operation", f"Stripping [*] from ref type: current cppunary_operation=[{debug.as_debug_string(cppunary_operation)}]")
|
||||
return cppunary_operation.operand
|
||||
|
|
Loading…
Reference in New Issue