Bug 1475139 part 2 - Add 'moveonly' qualifier to IPDL using statements. r=jld
authorRyan Hunt <rhunt@eqrion.net>
Mon, 24 Sep 2018 21:24:24 -0500
changeset 488284 766131a8c0a9a8361c313b45f28ae8262af3dd8a
parent 488283 ab436fa8add92c153513aa8eedb8ccd5658976c7
child 488285 ba9a0af62c4b60260cb90b7cc4673dec0e25fd7d
push id246
push userfmarier@mozilla.com
push dateSat, 13 Oct 2018 00:15:40 +0000
reviewersjld
bugs1475139
milestone64.0a1
Bug 1475139 part 2 - Add 'moveonly' qualifier to IPDL using statements. r=jld I'd like to use a struct over IPDL which is move only. This patch adds a modifier to usings statements to indicate the C++ type should always be moved, similar to refcounted. Differential Revision: https://phabricator.services.mozilla.com/D6781
ipc/ipdl/ipdl/ast.py
ipc/ipdl/ipdl/lower.py
ipc/ipdl/ipdl/parser.py
ipc/ipdl/ipdl/type.py
--- a/ipc/ipdl/ipdl/ast.py
+++ b/ipc/ipdl/ipdl/ast.py
@@ -172,38 +172,43 @@ class Include(Node):
         Node.__init__(self, loc)
         suffix = 'ipdl'
         if type == 'header':
             suffix += 'h'
         self.file = "%s.%s" % (name, suffix)
 
 
 class UsingStmt(Node):
-    def __init__(self, loc, cxxTypeSpec, cxxHeader=None, kind=None, refcounted=False):
+    def __init__(self, loc, cxxTypeSpec, cxxHeader=None, kind=None,
+                 refcounted=False, moveonly=False):
         Node.__init__(self, loc)
         assert not isinstance(cxxTypeSpec, str)
         assert cxxHeader is None or isinstance(cxxHeader, str)
         assert kind is None or kind == 'class' or kind == 'struct'
         self.type = cxxTypeSpec
         self.header = cxxHeader
         self.kind = kind
         self.refcounted = refcounted
+        self.moveonly = moveonly
 
     def canBeForwardDeclared(self):
         return self.isClass() or self.isStruct()
 
     def isClass(self):
         return self.kind == 'class'
 
     def isStruct(self):
         return self.kind == 'struct'
 
     def isRefcounted(self):
         return self.refcounted
 
+    def isMoveonly(self):
+        return self.moveonly
+
 # "singletons"
 
 
 class PrettyPrinted:
     @classmethod
     def __hash__(cls): return hash(cls.pretty)
 
     @classmethod
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -593,31 +593,35 @@ def _cxxConstRefType(ipdltype, side):
         t.ref = 1
         return t
     if ipdltype.isIPDL() and ipdltype.isArray():
         # Keep same constness as inner type.
         inner = _cxxConstRefType(ipdltype.basetype, side)
         t.const = inner.const or not inner.ref
         t.ref = 1
         return t
+    if ipdltype.isCxx() and ipdltype.isMoveonly():
+        t.ref = 1
+        return t
     if ipdltype.isCxx() and ipdltype.isRefcounted():
         # Use T* instead of const RefPtr<T>&
         t = t.T
         t.ptr = 1
         return t
     t.const = 1
     t.ref = 1
     return t
 
 
 def _cxxTypeNeedsMove(ipdltype):
-    return ipdltype.isIPDL() and (ipdltype.isArray() or
-                                  ipdltype.isShmem() or
-                                  ipdltype.isByteBuf() or
-                                  ipdltype.isEndpoint())
+    return ((ipdltype.isIPDL() and (ipdltype.isArray() or
+                                    ipdltype.isShmem() or
+                                    ipdltype.isByteBuf() or
+                                    ipdltype.isEndpoint())) or
+            (ipdltype.isCxx() and ipdltype.isMoveonly()))
 
 
 def _cxxTypeCanMove(ipdltype):
     return not (ipdltype.isIPDL() and ipdltype.isActor())
 
 
 def _cxxMoveRefType(ipdltype, side):
     t = _cxxBareType(ipdltype, side)
--- a/ipc/ipdl/ipdl/parser.py
+++ b/ipc/ipdl/ipdl/parser.py
@@ -127,16 +127,17 @@ reserved = set((
     'namespace',
     'nested',
     'nullable',
     'or',
     'parent',
     'prio',
     'protocol',
     'refcounted',
+    'moveonly',
     'returns',
     'struct',
     'sync',
     'union',
     'upto',
     'using',
     'verify'))
 tokens = [
@@ -283,23 +284,30 @@ def p_UsingKind(p):
 
 
 def p_MaybeRefcounted(p):
     """MaybeRefcounted : REFCOUNTED
                        |"""
     p[0] = 2 == len(p)
 
 
+def p_MaybeMoveOnly(p):
+    """MaybeMoveOnly : MOVEONLY
+                       |"""
+    p[0] = 2 == len(p)
+
+
 def p_UsingStmt(p):
-    """UsingStmt : USING MaybeRefcounted UsingKind CxxType FROM STRING"""
+    """UsingStmt : USING MaybeRefcounted MaybeMoveOnly UsingKind CxxType FROM STRING"""
     p[0] = UsingStmt(locFromTok(p, 1),
                      refcounted=p[2],
-                     kind=p[3],
-                     cxxTypeSpec=p[4],
-                     cxxHeader=p[6])
+                     moveonly=p[3],
+                     kind=p[4],
+                     cxxTypeSpec=p[5],
+                     cxxHeader=p[7])
 
 # --------------------
 # Namespaced stuff
 
 
 def p_NamespacedStuff(p):
     """NamespacedStuff : NamespacedStuff NamespaceThing
                        | NamespaceThing"""
--- a/ipc/ipdl/ipdl/type.py
+++ b/ipc/ipdl/ipdl/type.py
@@ -137,31 +137,35 @@ class VoidType(Type):
 
 
 VOID = VoidType()
 
 # --------------------
 
 
 class ImportedCxxType(Type):
-    def __init__(self, qname, refcounted):
+    def __init__(self, qname, refcounted, moveonly):
         assert isinstance(qname, QualifiedId)
         self.loc = qname.loc
         self.qname = qname
         self.refcounted = refcounted
+        self.moveonly = moveonly
 
     def isCxx(self):
         return True
 
     def isAtom(self):
         return True
 
     def isRefcounted(self):
         return self.refcounted
 
+    def isMoveonly(self):
+        return self.moveonly
+
     def name(self):
         return self.qname.baseid
 
     def fullname(self):
         return str(self.qname)
 
 # --------------------
 
@@ -843,22 +847,25 @@ class GatherDecls(TcheckVisitor):
             fullname = None
         if fullname == 'mozilla::ipc::Shmem':
             ipdltype = ShmemType(using.type.spec)
         elif fullname == 'mozilla::ipc::ByteBuf':
             ipdltype = ByteBufType(using.type.spec)
         elif fullname == 'mozilla::ipc::FileDescriptor':
             ipdltype = FDType(using.type.spec)
         else:
-            ipdltype = ImportedCxxType(using.type.spec, using.isRefcounted())
+            ipdltype = ImportedCxxType(using.type.spec, using.isRefcounted(), using.isMoveonly())
             existingType = self.symtab.lookup(ipdltype.fullname())
             if existingType and existingType.fullname == ipdltype.fullname():
                 if ipdltype.isRefcounted() != existingType.type.isRefcounted():
                     self.error(using.loc, "inconsistent refcounted status of type `%s`",
                                str(using.type))
+                if ipdltype.isMoveonly() != existingType.type.isMoveonly():
+                    self.error(using.loc, "inconsistent moveonly status of type `%s`",
+                               str(using.type))
                 using.decl = existingType
                 return
         using.decl = self.declare(
             loc=using.loc,
             type=ipdltype,
             shortname=using.type.basename(),
             fullname=fullname)