Error out if there are manager/managee cycles in protocol graphs. r=cjones
Error out if there are manager/managee cycles in protocol graphs. r=cjones
--- a/ipc/ipdl/ipdl/type.py
+++ b/ipc/ipdl/ipdl/type.py
@@ -941,16 +941,36 @@ class GatherDecls(TcheckVisitor):
if typespec.array:
itype = ArrayType(itype)
return itype
##-----------------------------------------------------------------------------
+def checkcycles(p, stack=None):
+ cycles = []
+
+ if stack is None:
+ stack = []
+
+ for cp in p.manages:
+ if cp in stack:
+ return [stack + [p, cp]]
+ cycles += checkcycles(cp, stack + [p])
+
+ return cycles
+
+def formatcycles(cycles):
+ r = []
+ for cycle in cycles:
+ s = " -> ".join([ptype.name() for ptype in cycle])
+ r.append("`%s'" % s)
+ return ", ".join(r)
+
class CheckTypes(TcheckVisitor):
def __init__(self, errors):
# don't need the symbol table, we just want the error reporting
TcheckVisitor.__init__(self, None, errors)
self.visited = set()
def visitProtocolInclude(self, inc):
if inc.tu.filename in self.visited:
@@ -974,16 +994,23 @@ class CheckTypes(TcheckVisitor):
if not p.decl.type.isToplevel():
for md in p.messageDecls:
if _DELETE_MSG == md.name: break
else:
self.error(
p.decl.loc,
"managed protocol `%s' requires a `delete()' message to be declared",
p.name)
+ else:
+ cycles = checkcycles(p.decl.type)
+ if cycles:
+ self.error(
+ p.decl.loc,
+ "cycle(s) detected in manager/manages heirarchy: %s",
+ formatcycles(cycles))
return Visitor.visitProtocol(self, p)
def visitManagesStmt(self, mgs):
pdecl = mgs.manager.decl
ptype, pname = pdecl.type, pdecl.shortname
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/ipdl/error/cyclecheck_Child.ipdl
@@ -0,0 +1,12 @@
+include protocol "cyclecheck_Parent.ipdl";
+include protocol "cyclecheck_Grandchild.ipdl";
+
+protocol cyclecheck_Child {
+ manager cyclecheck_Parent;
+ manages cyclecheck_Grandchild;
+
+child:
+ cyclecheck_Grandchild();
+ __delete__();
+};
+
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/ipdl/error/cyclecheck_Grandchild.ipdl
@@ -0,0 +1,12 @@
+include protocol "cyclecheck_Child.ipdl";
+include protocol "cyclecheck_Parent.ipdl";
+
+protocol cyclecheck_Grandchild {
+ manager cyclecheck_Child;
+ manages cyclecheck_Parent;
+
+child:
+ cyclecheck_Parent();
+ __delete__();
+};
+
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/ipdl/error/cyclecheck_Parent.ipdl
@@ -0,0 +1,10 @@
+include protocol "cyclecheck_Child.ipdl";
+
+protocol cyclecheck_Parent {
+ manages cyclecheck_Child;
+
+child:
+ cyclecheck_Child();
+ __delete__();
+};
+