Skip to content

Commit

Permalink
[mypyc] Refactor of load_final_static, make it report NameError (pyth…
Browse files Browse the repository at this point in the history
…on#8915)

Pull out handling of of the error checks into ll_builder, and report
the right exception.

This is groundwork for fixing some potential segfaults involving
uninitialized classes.
  • Loading branch information
msullivan authored May 28, 2020
1 parent 1d7a6ae commit 5bf0fc4
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 19 deletions.
1 change: 1 addition & 0 deletions mypyc/ir/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,7 @@ class RaiseStandardError(RegisterOp):
STOP_ITERATION = 'StopIteration' # type: Final
UNBOUND_LOCAL_ERROR = 'UnboundLocalError' # type: Final
RUNTIME_ERROR = 'RuntimeError' # type: Final
NAME_ERROR = 'NameError' # type: Final

def __init__(self, class_name: str, value: Optional[Union[str, Value]], line: int) -> None:
super().__init__(line)
Expand Down
18 changes: 5 additions & 13 deletions mypyc/irbuild/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
BasicBlock, AssignmentTarget, AssignmentTargetRegister, AssignmentTargetIndex,
AssignmentTargetAttr, AssignmentTargetTuple, Environment, LoadInt, Value,
Register, Op, Assign, Branch, Unreachable, TupleGet, GetAttr, SetAttr, LoadStatic,
InitStatic, PrimitiveOp, OpDescription, NAMESPACE_MODULE, RaiseStandardError
InitStatic, PrimitiveOp, OpDescription, NAMESPACE_MODULE, RaiseStandardError,
)
from mypyc.ir.rtypes import (
RType, RTuple, RInstance, int_rprimitive, dict_rprimitive,
Expand Down Expand Up @@ -315,20 +315,12 @@ def init_final_static(self, lvalue: Lvalue, rvalue_reg: Value,

def load_final_static(self, fullname: str, typ: RType, line: int,
error_name: Optional[str] = None) -> Value:
if error_name is None:
error_name = fullname
ok_block, error_block = BasicBlock(), BasicBlock()
split_name = split_target(self.graph, fullname)
assert split_name is not None
value = self.add(LoadStatic(typ, split_name[1], split_name[0], line=line))
self.add(Branch(value, error_block, ok_block, Branch.IS_ERROR, rare=True))
self.activate_block(error_block)
self.add(RaiseStandardError(RaiseStandardError.VALUE_ERROR,
'value for final name "{}" was not set'.format(error_name),
line))
self.add(Unreachable())
self.activate_block(ok_block)
return value
module, name = split_name
return self.builder.load_static_checked(
typ, name, module, line=line,
error_msg='value for final name "{}" was not set'.format(error_name))

def load_final_literal_value(self, val: Union[int, str, bytes, float, bool],
line: int) -> Value:
Expand Down
22 changes: 20 additions & 2 deletions mypyc/irbuild/ll_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
from mypyc.ir.ops import (
BasicBlock, Environment, Op, LoadInt, Value, Register,
Assign, Branch, Goto, Call, Box, Unbox, Cast, GetAttr,
LoadStatic, MethodCall, PrimitiveOp, OpDescription, RegisterOp,
NAMESPACE_TYPE, NAMESPACE_MODULE, LoadErrorValue, CallC
LoadStatic, MethodCall, PrimitiveOp, OpDescription, RegisterOp, CallC,
RaiseStandardError, Unreachable, LoadErrorValue,
NAMESPACE_TYPE, NAMESPACE_MODULE, NAMESPACE_STATIC,
)
from mypyc.ir.rtypes import (
RType, RUnion, RInstance, optional_value_type, int_rprimitive, float_rprimitive,
Expand Down Expand Up @@ -457,6 +458,23 @@ def load_static_unicode(self, value: str) -> Value:
static_symbol = self.literal_static_name(value)
return self.add(LoadStatic(str_rprimitive, static_symbol, ann=value))

def load_static_checked(self, typ: RType, identifier: str, module_name: Optional[str] = None,
namespace: str = NAMESPACE_STATIC,
line: int = -1,
error_msg: Optional[str] = None) -> Value:
if error_msg is None:
error_msg = "name '{}' is not defined".format(identifier)
ok_block, error_block = BasicBlock(), BasicBlock()
value = self.add(LoadStatic(typ, identifier, module_name, namespace, line=line))
self.add(Branch(value, error_block, ok_block, Branch.IS_ERROR, rare=True))
self.activate_block(error_block)
self.add(RaiseStandardError(RaiseStandardError.NAME_ERROR,
error_msg,
line))
self.add(Unreachable())
self.activate_block(ok_block)
return value

def load_module(self, name: str) -> Value:
return self.add(LoadStatic(object_rprimitive, name, namespace=NAMESPACE_MODULE))

Expand Down
2 changes: 2 additions & 0 deletions mypyc/test-data/fixtures/ir.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ class TypeError(Exception): pass

class AttributeError(Exception): pass

class NameError(Exception): pass

class LookupError(Exception): pass

class KeyError(LookupError): pass
Expand Down
6 changes: 3 additions & 3 deletions mypyc/test-data/irbuild-basic.test
Original file line number Diff line number Diff line change
Expand Up @@ -3247,7 +3247,7 @@ L0:
r0 = __main__.x :: static
if is_error(r0) goto L1 else goto L2
L1:
raise ValueError('value for final name "x" was not set')
raise NameError('value for final name "x" was not set')
unreachable
L2:
r2 = 0
Expand All @@ -3271,7 +3271,7 @@ L0:
r0 = __main__.x :: static
if is_error(r0) goto L1 else goto L2
L1:
raise ValueError('value for final name "x" was not set')
raise NameError('value for final name "x" was not set')
unreachable
L2:
r2 = r0[0]
Expand All @@ -3294,7 +3294,7 @@ L0:
r0 = __main__.x :: static
if is_error(r0) goto L1 else goto L2
L1:
raise ValueError('value for final name "x" was not set')
raise NameError('value for final name "x" was not set')
unreachable
L2:
r2 = 1
Expand Down
2 changes: 1 addition & 1 deletion mypyc/test-data/run.test
Original file line number Diff line number Diff line change
Expand Up @@ -4451,7 +4451,7 @@ def f() -> int:
from native import f
try:
print(f())
except ValueError as e:
except NameError as e:
print(e.args[0])
[out]
value for final name "x" was not set
Expand Down

0 comments on commit 5bf0fc4

Please sign in to comment.