Bug 1428535 - Part 3: Emit override specifiers in generated ipc/ipdl code. r?froydnj
TBD: I made visitMethodDecl requiresvirtual=1 if override=1 (for consistency with its virtual and pure parameters), even though the method only emits `virtual` xor `override`. However, this makes the caller code more verbose. Should we consolidate the virtual, override, pure, and static parameters into one method type enum? Something like separate values like VIRTUAL, PURE_VIRTUAL, VIRTUAL_OVERRIDE, and STATIC.
MozReview-Commit-ID: 2mpQcRKzfCo
--- a/ipc/ipdl/ipdl/cxx/ast.py
+++ b/ipc/ipdl/ipdl/cxx/ast.py
@@ -466,20 +466,22 @@ class FriendClassDecl(Node):
def __init__(self, friend):
Node.__init__(self)
self.friend = friend
class MethodDecl(Node):
def __init__(self, name, params=[ ], ret=Type('void'),
virtual=0, const=0, pure=0, static=0, warn_unused=0,
inline=0, force_inline=0, never_inline=0,
- typeop=None,
+ typeop=None, override=0,
T=None):
assert not (virtual and static)
assert not pure or virtual # pure => virtual
+ assert not override or virtual # override => virtual
+ assert not (override and pure)
assert not (static and typeop)
assert not (name and typeop)
assert name is None or isinstance(name, str)
assert not isinstance(ret, list)
for decl in params: assert not isinstance(decl, str)
assert not isinstance(T, int)
assert not (inline and never_inline)
assert not (force_inline and never_inline)
@@ -489,16 +491,17 @@ class MethodDecl(Node):
Node.__init__(self)
self.name = name
self.params = params # [ Param ]
self.ret = ret # Type or None
self.virtual = virtual # bool
self.const = const # bool
self.pure = pure # bool
+ self.override = override # bool
self.static = static # bool
self.warn_unused = warn_unused # bool
self.force_inline = (force_inline or T) # bool
self.inline = inline # bool
self.never_inline = never_inline # bool
self.typeop = typeop # Type or None
self.T = T # Type or None
self.only_for_definition = False
@@ -506,16 +509,17 @@ class MethodDecl(Node):
def __deepcopy__(self, memo):
return MethodDecl(
self.name,
params=copy.deepcopy(self.params, memo),
ret=copy.deepcopy(self.ret, memo),
virtual=self.virtual,
const=self.const,
pure=self.pure,
+ override=self.override,
static=self.static,
warn_unused=self.warn_unused,
inline=self.inline,
force_inline=self.force_inline,
never_inline=self.never_inline,
typeop=copy.deepcopy(self.typeop, memo),
T=copy.deepcopy(self.T, memo))
@@ -550,17 +554,17 @@ class ConstructorDecl(MethodDecl):
self.explicit)
class ConstructorDefn(MethodDefn):
def __init__(self, decl, memberinits=[ ]):
MethodDefn.__init__(self, decl)
self.memberinits = memberinits
class DestructorDecl(MethodDecl):
- def __init__(self, name, virtual=0, force_inline=0, inline=0):
+ def __init__(self, name, virtual=0, override=0, force_inline=0, inline=0):
MethodDecl.__init__(self, name, params=[ ], ret=None,
virtual=virtual,
force_inline=force_inline, inline=inline)
def __deepcopy__(self, memo):
return DestructorDecl(self.name,
virtual=self.virtual,
force_inline=self.force_inline,
--- a/ipc/ipdl/ipdl/cxx/cgen.py
+++ b/ipc/ipdl/ipdl/cxx/cgen.py
@@ -187,33 +187,36 @@ class CxxCodeGen(CodePrinter, Visitor):
inh.type.accept(self)
def visitFriendClassDecl(self, fcd):
self.printdentln('friend class '+ fcd.friend +';')
def visitMethodDecl(self, md):
assert not (md.static and md.virtual)
+ assert not (md.override and md.pure)
+ assert not md.pure or md.virtual # pure => virtual
+ assert not md.override or md.virtual # override => virtual
if md.T:
self.write('template<')
self.write('typename ')
md.T.accept(self)
self.println('>')
self.printdent()
if md.warn_unused:
self.write('MOZ_MUST_USE ')
if md.inline:
self.write('inline ')
if md.never_inline:
self.write('MOZ_NEVER_INLINE ')
if md.static:
self.write('static ')
- if md.virtual:
+ if md.virtual and not md.override:
self.write('virtual ')
if md.ret:
if md.only_for_definition:
self.write('auto ')
else:
md.ret.accept(self)
self.println()
self.printdent()
@@ -227,16 +230,19 @@ class CxxCodeGen(CodePrinter, Visitor):
self.writeDeclList(md.params)
self.write(')')
if md.const:
self.write(' const')
if md.ret and md.only_for_definition:
self.write(' -> ')
md.ret.accept(self)
+
+ if md.override:
+ self.write(' override')
if md.pure:
self.write(' = 0')
def visitMethodDefn(self, md):
if md.decl.pure:
return
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -2782,33 +2782,33 @@ class _GenerateProtocolActorCode(ipdl.as
])
if ptype.isToplevel():
# void ProcessingError(code); default to no-op
processingerror = MethodDefn(
MethodDecl(p.processingErrorVar().name,
params=[ Param(_Result.Type(), 'aCode'),
Param(Type('char', const=1, ptr=1), 'aReason') ],
- virtual=1))
+ virtual=1, override=1))
# bool ShouldContinueFromReplyTimeout(); default to |true|
shouldcontinue = MethodDefn(
MethodDecl(p.shouldContinueFromTimeoutVar().name,
- ret=Type.BOOL, virtual=1))
+ ret=Type.BOOL, virtual=1, override=1))
shouldcontinue.addstmt(StmtReturn.TRUE)
# void Entered*()/Exited*(); default to no-op
entered = MethodDefn(
- MethodDecl(p.enteredCxxStackVar().name, virtual=1))
+ MethodDecl(p.enteredCxxStackVar().name, virtual=1, override=1))
exited = MethodDefn(
- MethodDecl(p.exitedCxxStackVar().name, virtual=1))
+ MethodDecl(p.exitedCxxStackVar().name, virtual=1, override=1))
enteredcall = MethodDefn(
- MethodDecl(p.enteredCallVar().name, virtual=1))
+ MethodDecl(p.enteredCallVar().name, virtual=1, override=1))
exitedcall = MethodDefn(
- MethodDecl(p.exitedCallVar().name, virtual=1))
+ MethodDecl(p.exitedCallVar().name, virtual=1, override=1))
self.cls.addstmts([ processingerror,
shouldcontinue,
entered, exited,
enteredcall, exitedcall,
Whitespace.NL ])
self.cls.addstmts((
@@ -2943,17 +2943,17 @@ class _GenerateProtocolActorCode(ipdl.as
self.cls.addstmts(self.implementManagerIface())
def makeHandlerMethod(name, switch, hasReply, dispatches=0):
params = [ Decl(Type('Message', const=1, ref=1), msgvar.name) ]
if hasReply:
params.append(Decl(Type('Message', ref=1, ptr=1),
replyvar.name))
- method = MethodDefn(MethodDecl(name, virtual=True,
+ method = MethodDefn(MethodDecl(name, virtual=1, override=1,
params=params, ret=_Result.Type()))
if not switch:
crash = StmtExpr(ExprCall(ExprVar('MOZ_ASSERT_UNREACHABLE'),
args=[ExprLiteral.String('message protocol not supported')]))
method.addstmts([crash, StmtReturn(_Result.NotKnown)])
return method
@@ -3023,34 +3023,34 @@ class _GenerateProtocolActorCode(ipdl.as
destroysubtreevar = ExprVar('DestroySubtree')
deallocsubtreevar = ExprVar('DeallocSubtree')
deallocshmemvar = ExprVar('DeallocShmems')
deallocselfvar = ExprVar('Dealloc' + _actorName(ptype.name(), self.side))
# int32_t GetProtocolTypeId() { return PFoo; }
gettypetag = MethodDefn(
- MethodDecl('GetProtocolTypeId', ret=_actorTypeTagType()))
+ MethodDecl('GetProtocolTypeId', ret=_actorTypeTagType(), virtual=1, override=1))
gettypetag.addstmt(StmtReturn(_protocolId(ptype)))
self.cls.addstmts([ gettypetag, Whitespace.NL ])
if ptype.isToplevel():
# OnChannelClose()
- onclose = MethodDefn(MethodDecl('OnChannelClose'))
+ onclose = MethodDefn(MethodDecl('OnChannelClose', virtual=1, override=1))
onclose.addstmts([
StmtExpr(ExprCall(destroysubtreevar,
args=[ _DestroyReason.NormalShutdown ])),
StmtExpr(ExprCall(deallocsubtreevar)),
StmtExpr(ExprCall(deallocshmemvar)),
StmtExpr(ExprCall(deallocselfvar))
])
self.cls.addstmts([ onclose, Whitespace.NL ])
# OnChannelError()
- onerror = MethodDefn(MethodDecl('OnChannelError'))
+ onerror = MethodDefn(MethodDecl('OnChannelError', virtual=1, override=1))
onerror.addstmts([
StmtExpr(ExprCall(destroysubtreevar,
args=[ _DestroyReason.AbnormalShutdown ])),
StmtExpr(ExprCall(deallocsubtreevar)),
StmtExpr(ExprCall(deallocshmemvar)),
StmtExpr(ExprCall(deallocselfvar))
])
self.cls.addstmts([ onerror, Whitespace.NL ])
@@ -3074,17 +3074,17 @@ class _GenerateProtocolActorCode(ipdl.as
## private methods
self.cls.addstmt(Label.PRIVATE)
## ProtocolName()
actorname = _actorName(p.name, self.side)
protocolname = MethodDefn(MethodDecl(
'ProtocolName', params=[],
- const=1, virtual=1, ret=Type('char', const=1, ptr=1)))
+ const=1, virtual=1, override=1, ret=Type('char', const=1, ptr=1)))
protocolname.addstmts([
StmtReturn(ExprLiteral.String(actorname))
])
self.cls.addstmts([ protocolname, Whitespace.NL ])
## DestroySubtree(bool normal)
whyvar = ExprVar('why')
subtreewhyvar = ExprVar('subtreewhy')
@@ -3237,23 +3237,23 @@ class _GenerateProtocolActorCode(ipdl.as
ithkid = ExprIndex(kidsvar, ivar)
methods = []
if p.decl.type.isToplevel():
getchannel = MethodDefn(MethodDecl(
p.getChannelMethod().name,
ret=Type('MessageChannel', ptr=1),
- virtual=1))
+ virtual=1, override=1))
getchannel.addstmt(StmtReturn(ExprAddrOf(p.channelVar())))
getchannelconst = MethodDefn(MethodDecl(
p.getChannelMethod().name,
ret=Type('MessageChannel', ptr=1, const=1),
- virtual=1, const=1))
+ virtual=1, override=1, const=1))
getchannelconst.addstmt(StmtReturn(ExprAddrOf(p.channelVar())))
methods += [ getchannel,
getchannelconst ]
if p.decl.type.isToplevel():
tmpvar = ExprVar('tmp')
@@ -3291,17 +3291,17 @@ class _GenerateProtocolActorCode(ipdl.as
# all protocols share the "same" RemoveManagee() implementation
pvar = ExprVar('aProtocolId')
listenervar = ExprVar('aListener')
removemanagee = MethodDefn(MethodDecl(
p.removeManageeMethod().name,
params=[ Decl(_protocolIdType(), pvar.name),
Decl(protocolbase, listenervar.name) ],
- virtual=1))
+ virtual=1, override=1))
if not len(p.managesStmts):
removemanagee.addstmts([ _fatalError('unreached'), StmtReturn() ])
else:
switchontype = StmtSwitch(pvar)
for managee in p.managesStmts:
case = StmtBlock()
actorvar = ExprVar('actor')
@@ -4888,16 +4888,17 @@ methodDefns."""
defns.addstmts([ defn, Whitespace.NL ])
return cls, defns
def _splitMethodDefn(md, clsname):
saveddecl = deepcopy(md.decl)
md.decl.name = (clsname +'::'+ md.decl.name)
md.decl.virtual = 0
+ md.decl.override = 0
md.decl.static = 0
md.decl.warn_unused = 0
md.decl.never_inline = 0
md.decl.only_for_definition = True
for param in md.decl.params:
if isinstance(param, Param):
param.default = None
return saveddecl, md