Commit 7be6eea8 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Fix some bugs

- Inherit simple_destructor from base classes
- Handle unreachable code better
- Call reprICAsString instead of reprIC
- Fix self-assignment checking bug
parent 3c0d99cf
...@@ -64,6 +64,8 @@ private: ...@@ -64,6 +64,8 @@ private:
CFGBlock* curblock; CFGBlock* curblock;
ScopingAnalysis* scoping_analysis; ScopingAnalysis* scoping_analysis;
friend CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body);
public: public:
CFGVisitor(SourceInfo* source, AST_TYPE::AST_TYPE root_type, FutureFlags future_flags, CFGVisitor(SourceInfo* source, AST_TYPE::AST_TYPE root_type, FutureFlags future_flags,
ScopingAnalysis* scoping_analysis, CFG* cfg) ScopingAnalysis* scoping_analysis, CFG* cfg)
...@@ -138,6 +140,7 @@ private: ...@@ -138,6 +140,7 @@ private:
void doReturn(AST_expr* value) { void doReturn(AST_expr* value) {
assert(value); assert(value);
assert(curblock);
for (auto& region : llvm::make_range(regions.rbegin(), regions.rend())) { for (auto& region : llvm::make_range(regions.rbegin(), regions.rend())) {
if (region.return_dest) { if (region.return_dest) {
...@@ -166,6 +169,7 @@ private: ...@@ -166,6 +169,7 @@ private:
} }
void doContinue() { void doContinue() {
assert(curblock);
for (auto& region : llvm::make_range(regions.rbegin(), regions.rend())) { for (auto& region : llvm::make_range(regions.rbegin(), regions.rend())) {
if (region.continue_dest) { if (region.continue_dest) {
if (region.say_why) { if (region.say_why) {
...@@ -186,6 +190,7 @@ private: ...@@ -186,6 +190,7 @@ private:
} }
void doBreak() { void doBreak() {
assert(curblock);
for (auto& region : llvm::make_range(regions.rbegin(), regions.rend())) { for (auto& region : llvm::make_range(regions.rbegin(), regions.rend())) {
if (region.break_dest) { if (region.break_dest) {
if (region.say_why) { if (region.say_why) {
...@@ -229,6 +234,8 @@ private: ...@@ -229,6 +234,8 @@ private:
} }
template <typename ResultASTType, typename CompType> AST_expr* remapComprehension(CompType* node) { template <typename ResultASTType, typename CompType> AST_expr* remapComprehension(CompType* node) {
assert(curblock);
InternedString rtn_name = nodeName(node); InternedString rtn_name = nodeName(node);
pushAssign(rtn_name, new ResultASTType()); pushAssign(rtn_name, new ResultASTType());
std::vector<CFGBlock*> exit_blocks; std::vector<CFGBlock*> exit_blocks;
...@@ -606,6 +613,8 @@ private: ...@@ -606,6 +613,8 @@ private:
} }
AST_expr* remapBoolOp(AST_BoolOp* node) { AST_expr* remapBoolOp(AST_BoolOp* node) {
assert(curblock);
InternedString name = nodeName(node); InternedString name = nodeName(node);
CFGBlock* starting_block = curblock; CFGBlock* starting_block = curblock;
...@@ -701,6 +710,8 @@ private: ...@@ -701,6 +710,8 @@ private:
} }
AST_expr* remapCompare(AST_Compare* node) { AST_expr* remapCompare(AST_Compare* node) {
assert(curblock);
// special case unchained comparisons to avoid generating a unnecessary complex cfg. // special case unchained comparisons to avoid generating a unnecessary complex cfg.
if (node->ops.size() == 1) { if (node->ops.size() == 1) {
AST_Compare* rtn = new AST_Compare(); AST_Compare* rtn = new AST_Compare();
...@@ -896,6 +907,8 @@ private: ...@@ -896,6 +907,8 @@ private:
} }
AST_expr* remapIfExp(AST_IfExp* node) { AST_expr* remapIfExp(AST_IfExp* node) {
assert(curblock);
InternedString rtn_name = nodeName(node); InternedString rtn_name = nodeName(node);
AST_Branch* br = new AST_Branch(); AST_Branch* br = new AST_Branch();
...@@ -1432,6 +1445,8 @@ public: ...@@ -1432,6 +1445,8 @@ public:
bool visit_pass(AST_Pass* node) override { return true; } bool visit_pass(AST_Pass* node) override { return true; }
bool visit_assert(AST_Assert* node) override { bool visit_assert(AST_Assert* node) override {
assert(curblock);
AST_Branch* br = new AST_Branch(); AST_Branch* br = new AST_Branch();
br->test = callNonzero(remapExpr(node->test)); br->test = callNonzero(remapExpr(node->test));
push_back(br); push_back(br);
...@@ -1695,6 +1710,8 @@ public: ...@@ -1695,6 +1710,8 @@ public:
} }
bool visit_return(AST_Return* node) override { bool visit_return(AST_Return* node) override {
assert(curblock);
if (root_type != AST_TYPE::FunctionDef && root_type != AST_TYPE::Lambda && root_type != AST_TYPE::Expression) { if (root_type != AST_TYPE::FunctionDef && root_type != AST_TYPE::Lambda && root_type != AST_TYPE::Expression) {
raiseExcHelper(SyntaxError, "'return' outside function"); raiseExcHelper(SyntaxError, "'return' outside function");
} }
...@@ -1710,8 +1727,7 @@ public: ...@@ -1710,8 +1727,7 @@ public:
} }
bool visit_if(AST_If* node) override { bool visit_if(AST_If* node) override {
if (!curblock) assert(curblock);
return true;
AST_Branch* br = new AST_Branch(); AST_Branch* br = new AST_Branch();
br->col_offset = node->col_offset; br->col_offset = node->col_offset;
...@@ -1730,6 +1746,8 @@ public: ...@@ -1730,6 +1746,8 @@ public:
curblock = iftrue; curblock = iftrue;
for (int i = 0; i < node->body.size(); i++) { for (int i = 0; i < node->body.size(); i++) {
node->body[i]->accept(this); node->body[i]->accept(this);
if (!curblock)
break;
} }
if (curblock) { if (curblock) {
AST_Jump* jtrue = new AST_Jump(); AST_Jump* jtrue = new AST_Jump();
...@@ -1746,6 +1764,8 @@ public: ...@@ -1746,6 +1764,8 @@ public:
curblock = iffalse; curblock = iffalse;
for (int i = 0; i < node->orelse.size(); i++) { for (int i = 0; i < node->orelse.size(); i++) {
node->orelse[i]->accept(this); node->orelse[i]->accept(this);
if (!curblock)
break;
} }
if (curblock) { if (curblock) {
AST_Jump* jfalse = new AST_Jump(); AST_Jump* jfalse = new AST_Jump();
...@@ -1765,8 +1785,7 @@ public: ...@@ -1765,8 +1785,7 @@ public:
} }
bool visit_break(AST_Break* node) override { bool visit_break(AST_Break* node) override {
if (!curblock) assert(curblock);
return true;
doBreak(); doBreak();
assert(!curblock); assert(!curblock);
...@@ -1774,8 +1793,7 @@ public: ...@@ -1774,8 +1793,7 @@ public:
} }
bool visit_continue(AST_Continue* node) override { bool visit_continue(AST_Continue* node) override {
if (!curblock) assert(curblock);
return true;
doContinue(); doContinue();
assert(!curblock); assert(!curblock);
...@@ -1785,8 +1803,7 @@ public: ...@@ -1785,8 +1803,7 @@ public:
bool visit_exec(AST_Exec* node) override { raiseExcHelper(SyntaxError, "'exec' currently not supported"); } bool visit_exec(AST_Exec* node) override { raiseExcHelper(SyntaxError, "'exec' currently not supported"); }
bool visit_while(AST_While* node) override { bool visit_while(AST_While* node) override {
if (!curblock) assert(curblock);
return true;
CFGBlock* test_block = cfg->addBlock(); CFGBlock* test_block = cfg->addBlock();
test_block->info = "while_test"; test_block->info = "while_test";
...@@ -1815,6 +1832,8 @@ public: ...@@ -1815,6 +1832,8 @@ public:
curblock = body; curblock = body;
for (int i = 0; i < node->body.size(); i++) { for (int i = 0; i < node->body.size(); i++) {
node->body[i]->accept(this); node->body[i]->accept(this);
if (!curblock)
break;
} }
if (curblock) { if (curblock) {
AST_Jump* jbody = makeJump(); AST_Jump* jbody = makeJump();
...@@ -1831,6 +1850,8 @@ public: ...@@ -1831,6 +1850,8 @@ public:
curblock = orelse; curblock = orelse;
for (int i = 0; i < node->orelse.size(); i++) { for (int i = 0; i < node->orelse.size(); i++) {
node->orelse[i]->accept(this); node->orelse[i]->accept(this);
if (!curblock)
break;
} }
if (curblock) { if (curblock) {
AST_Jump* jend = makeJump(); AST_Jump* jend = makeJump();
...@@ -1851,8 +1872,7 @@ public: ...@@ -1851,8 +1872,7 @@ public:
} }
bool visit_for(AST_For* node) override { bool visit_for(AST_For* node) override {
if (!curblock) assert(curblock);
return true;
// TODO this is so complicated because I tried doing loop inversion; // TODO this is so complicated because I tried doing loop inversion;
// is it really worth it? It got so bad because all the edges became // is it really worth it? It got so bad because all the edges became
...@@ -1916,6 +1936,8 @@ public: ...@@ -1916,6 +1936,8 @@ public:
for (int i = 0; i < node->body.size(); i++) { for (int i = 0; i < node->body.size(); i++) {
node->body[i]->accept(this); node->body[i]->accept(this);
if (!curblock)
break;
} }
popRegion(); popRegion();
...@@ -1950,6 +1972,8 @@ public: ...@@ -1950,6 +1972,8 @@ public:
for (int i = 0; i < node->orelse.size(); i++) { for (int i = 0; i < node->orelse.size(); i++) {
node->orelse[i]->accept(this); node->orelse[i]->accept(this);
if (!curblock)
break;
} }
if (curblock) { if (curblock) {
AST_Jump* else_jump = makeJump(); AST_Jump* else_jump = makeJump();
...@@ -1970,6 +1994,8 @@ public: ...@@ -1970,6 +1994,8 @@ public:
} }
bool visit_raise(AST_Raise* node) override { bool visit_raise(AST_Raise* node) override {
assert(curblock);
AST_Raise* remapped = new AST_Raise(); AST_Raise* remapped = new AST_Raise();
remapped->col_offset = node->col_offset; remapped->col_offset = node->col_offset;
remapped->lineno = node->lineno; remapped->lineno = node->lineno;
...@@ -1991,6 +2017,8 @@ public: ...@@ -1991,6 +2017,8 @@ public:
} }
bool visit_tryexcept(AST_TryExcept* node) override { bool visit_tryexcept(AST_TryExcept* node) override {
assert(curblock);
// The pypa parser will generate a tryexcept node inside a try-finally block with // The pypa parser will generate a tryexcept node inside a try-finally block with
// no except clauses // no except clauses
if (node->handlers.size() == 0) { if (node->handlers.size() == 0) {
...@@ -1999,6 +2027,8 @@ public: ...@@ -1999,6 +2027,8 @@ public:
for (AST_stmt* subnode : node->body) { for (AST_stmt* subnode : node->body) {
subnode->accept(this); subnode->accept(this);
if (!curblock)
break;
} }
return true; return true;
} }
...@@ -2013,12 +2043,18 @@ public: ...@@ -2013,12 +2043,18 @@ public:
for (AST_stmt* subnode : node->body) { for (AST_stmt* subnode : node->body) {
subnode->accept(this); subnode->accept(this);
if (!curblock)
break;
} }
exc_handlers.pop_back(); exc_handlers.pop_back();
for (AST_stmt* subnode : node->orelse) { if (curblock) {
subnode->accept(this); for (AST_stmt* subnode : node->orelse) {
subnode->accept(this);
if (!curblock)
break;
}
} }
CFGBlock* join_block = cfg->addDeferredBlock(); CFGBlock* join_block = cfg->addDeferredBlock();
...@@ -2080,6 +2116,8 @@ public: ...@@ -2080,6 +2116,8 @@ public:
for (AST_stmt* subnode : exc_handler->body) { for (AST_stmt* subnode : exc_handler->body) {
subnode->accept(this); subnode->accept(this);
if (!curblock)
break;
} }
if (curblock) { if (curblock) {
...@@ -2119,6 +2157,8 @@ public: ...@@ -2119,6 +2157,8 @@ public:
} }
bool visit_tryfinally(AST_TryFinally* node) override { bool visit_tryfinally(AST_TryFinally* node) override {
assert(curblock);
CFGBlock* exc_handler_block = cfg->addDeferredBlock(); CFGBlock* exc_handler_block = cfg->addDeferredBlock();
InternedString exc_type_name = nodeName(node, "type"); InternedString exc_type_name = nodeName(node, "type");
InternedString exc_value_name = nodeName(node, "value"); InternedString exc_value_name = nodeName(node, "value");
...@@ -2131,6 +2171,8 @@ public: ...@@ -2131,6 +2171,8 @@ public:
for (AST_stmt* subnode : node->body) { for (AST_stmt* subnode : node->body) {
subnode->accept(this); subnode->accept(this);
if (!curblock)
break;
} }
exc_handlers.pop_back(); exc_handlers.pop_back();
...@@ -2167,6 +2209,8 @@ public: ...@@ -2167,6 +2209,8 @@ public:
for (AST_stmt* subnode : node->finalbody) { for (AST_stmt* subnode : node->finalbody) {
subnode->accept(this); subnode->accept(this);
if (!curblock)
break;
} }
if (curblock) { if (curblock) {
...@@ -2271,6 +2315,8 @@ public: ...@@ -2271,6 +2315,8 @@ public:
} }
bool visit_with(AST_With* node) override { bool visit_with(AST_With* node) override {
assert(curblock);
char ctxmgrname_buf[80]; char ctxmgrname_buf[80];
snprintf(ctxmgrname_buf, 80, "#ctxmgr_%p", node); snprintf(ctxmgrname_buf, 80, "#ctxmgr_%p", node);
InternedString ctxmgrname = internString(ctxmgrname_buf); InternedString ctxmgrname = internString(ctxmgrname_buf);
...@@ -2310,6 +2356,8 @@ public: ...@@ -2310,6 +2356,8 @@ public:
for (int i = 0; i < node->body.size(); i++) { for (int i = 0; i < node->body.size(); i++) {
node->body[i]->accept(this); node->body[i]->accept(this);
if (!curblock)
break;
} }
popRegion(); // for the retrun popRegion(); // for the retrun
...@@ -2441,6 +2489,8 @@ CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body) { ...@@ -2441,6 +2489,8 @@ CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body) {
} }
for (int i = (skip_first ? 1 : 0); i < body.size(); i++) { for (int i = (skip_first ? 1 : 0); i < body.size(); i++) {
if (!visitor.curblock)
break;
body[i]->accept(&visitor); body[i]->accept(&visitor);
} }
......
...@@ -340,6 +340,7 @@ void runCollection() { ...@@ -340,6 +340,7 @@ void runCollection() {
for (auto o : weakly_referenced) { for (auto o : weakly_referenced) {
PyWeakReference** list = (PyWeakReference**)PyObject_GET_WEAKREFS_LISTPTR(o); PyWeakReference** list = (PyWeakReference**)PyObject_GET_WEAKREFS_LISTPTR(o);
while (PyWeakReference* head = *list) { while (PyWeakReference* head = *list) {
assert(isValidGCObject(head));
if (head->wr_object != Py_None) { if (head->wr_object != Py_None) {
_PyWeakref_ClearRef(head); _PyWeakref_ClearRef(head);
if (head->wr_callback) { if (head->wr_callback) {
......
...@@ -68,7 +68,10 @@ extern "C" Box* listRepr(BoxedList* self) { ...@@ -68,7 +68,10 @@ extern "C" Box* listRepr(BoxedList* self) {
if (i > 0) if (i > 0)
os << ", "; os << ", ";
BoxedString* s = static_cast<BoxedString*>(self->elts->elts[i]->reprIC()); Box* r = self->elts->elts[i]->reprICAsString();
assert(r->cls == str_cls);
BoxedString* s = static_cast<BoxedString*>(r);
os << s->s; os << s->s;
} }
os << ']'; os << ']';
...@@ -282,7 +285,11 @@ extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) { ...@@ -282,7 +285,11 @@ extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) {
} else if (isSubclass(v->cls, list_cls)) { } else if (isSubclass(v->cls, list_cls)) {
BoxedList* lv = static_cast<BoxedList*>(v); BoxedList* lv = static_cast<BoxedList*>(v);
v_size = lv->size; v_size = lv->size;
v_elts = lv->elts->elts; // If lv->size is 0, lv->elts->elts is garbage
if (v_size)
v_elts = lv->elts->elts;
else
v_elts = NULL;
} else if (isSubclass(v->cls, tuple_cls)) { } else if (isSubclass(v->cls, tuple_cls)) {
BoxedTuple* tv = static_cast<BoxedTuple*>(v); BoxedTuple* tv = static_cast<BoxedTuple*>(v);
v_size = tv->elts.size(); v_size = tv->elts.size();
...@@ -291,7 +298,9 @@ extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) { ...@@ -291,7 +298,9 @@ extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) {
RELEASE_ASSERT(0, "unsupported type for list slice assignment: '%s'", getTypeName(v)); RELEASE_ASSERT(0, "unsupported type for list slice assignment: '%s'", getTypeName(v));
} }
RELEASE_ASSERT(!v_elts || self->elts->elts != v_elts, "Slice self-assignment currently unsupported"); // If self->size is 0, self->elts->elts is garbage
RELEASE_ASSERT(self->size == 0 || !v_elts || self->elts->elts != v_elts,
"Slice self-assignment currently unsupported");
int delts = v_size - (stop - start); int delts = v_size - (stop - start);
int remaining_elts = self->size - stop; int remaining_elts = self->size - stop;
......
...@@ -3918,6 +3918,17 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) { ...@@ -3918,6 +3918,17 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
else else
made->tp_alloc = PyType_GenericAlloc; made->tp_alloc = PyType_GenericAlloc;
assert(!made->simple_destructor);
for (auto b : bases->elts) {
if (!isSubclass(b->cls, type_cls))
continue;
BoxedClass* b_cls = static_cast<BoxedClass*>(b);
RELEASE_ASSERT(made->simple_destructor == base->simple_destructor || made->simple_destructor == NULL
|| base->simple_destructor == NULL,
"Conflicting simple destructors!");
made->simple_destructor = base->simple_destructor;
}
return made; return made;
} }
......
...@@ -243,6 +243,11 @@ Box* Box::reprIC() { ...@@ -243,6 +243,11 @@ Box* Box::reprIC() {
BoxedString* Box::reprICAsString() { BoxedString* Box::reprICAsString() {
Box* r = this->reprIC(); Box* r = this->reprIC();
if (isSubclass(r->cls, unicode_cls)) {
r = PyUnicode_AsASCIIString(r);
checkAndThrowCAPIException();
}
if (r->cls != str_cls) { if (r->cls != str_cls) {
raiseExcHelper(TypeError, "__repr__ did not return a string!"); raiseExcHelper(TypeError, "__repr__ did not return a string!");
} }
......
def f():
return True
1 or 2
[i for i in xrange(5)]
while True:
pass
try:
raise Exception()
finally:
pass
f()
# Make sure that subclasses of str have their memory reclaimed
class S(str):
pass
def f():
base = "." * 10000000
for i in xrange(100):
s = S(base)
f()
...@@ -136,3 +136,8 @@ print type(str(CustomRepr(MyStr("hi")))) ...@@ -136,3 +136,8 @@ print type(str(CustomRepr(MyStr("hi"))))
print type(MyStr("hi").__str__()) print type(MyStr("hi").__str__())
print type(str(MyStr("hi"))) print type(str(MyStr("hi")))
class C(object):
def __repr__(self):
return u"hello world"
print [C()], set([C()]), {1:C()}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment