[05/10] d: add 'final' and 'override' to gcc/d/*.cc 'visit' impls

Message ID 20220523192834.3785673-6-dmalcolm@redhat.com
State Committed
Commit 442cf0977a2993940a81aac08134fcdde4fb3035
Headers
Series Add 'final' and 'override' where missing |

Commit Message

David Malcolm May 23, 2022, 7:28 p.m. UTC
  gcc/d/ChangeLog:
	* decl.cc: Add "final" and "override" to all "visit" vfunc decls
	as appropriate.
	* expr.cc: Likewise.
	* toir.cc: Likewise.
	* typeinfo.cc: Likewise.
	* types.cc: Likewise.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/d/decl.cc     | 36 +++++++++++++-------------
 gcc/d/expr.cc     |  2 +-
 gcc/d/toir.cc     | 64 +++++++++++++++++++++++------------------------
 gcc/d/typeinfo.cc | 34 ++++++++++++-------------
 gcc/d/types.cc    | 30 +++++++++++-----------
 5 files changed, 83 insertions(+), 83 deletions(-)
  

Comments

Iain Buclaw May 24, 2022, 12:56 p.m. UTC | #1
Excerpts from David Malcolm via Gcc-patches's message of Mai 23, 2022 9:28 pm:
> gcc/d/ChangeLog:
> 	* decl.cc: Add "final" and "override" to all "visit" vfunc decls
> 	as appropriate.
> 	* expr.cc: Likewise.
> 	* toir.cc: Likewise.
> 	* typeinfo.cc: Likewise.
> 	* types.cc: Likewise.
> 
> Signed-off-by: David Malcolm <dmalcolm@redhat.com>


Thanks David!

Looks OK to me.

Iain.


> ---
>  gcc/d/decl.cc     | 36 +++++++++++++-------------
>  gcc/d/expr.cc     |  2 +-
>  gcc/d/toir.cc     | 64 +++++++++++++++++++++++------------------------
>  gcc/d/typeinfo.cc | 34 ++++++++++++-------------
>  gcc/d/types.cc    | 30 +++++++++++-----------
>  5 files changed, 83 insertions(+), 83 deletions(-)
> 
> diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
> index f5c21078aad..5d850065bf0 100644
> --- a/gcc/d/decl.cc
> +++ b/gcc/d/decl.cc
> @@ -149,13 +149,13 @@ public:
>  
>    /* This should be overridden by each declaration class.  */
>  
> -  void visit (Dsymbol *)
> +  void visit (Dsymbol *) final override
>    {
>    }
>  
>    /* Compile a D module, and all members of it.  */
>  
> -  void visit (Module *d)
> +  void visit (Module *d) final override
>    {
>      if (d->semanticRun >= PASS::obj)
>        return;
> @@ -166,7 +166,7 @@ public:
>  
>    /* Write the imported symbol to debug.  */
>  
> -  void visit (Import *d)
> +  void visit (Import *d) final override
>    {
>      if (d->semanticRun >= PASS::obj)
>        return;
> @@ -218,7 +218,7 @@ public:
>  
>    /* Expand any local variables found in tuples.  */
>  
> -  void visit (TupleDeclaration *d)
> +  void visit (TupleDeclaration *d) final override
>    {
>      for (size_t i = 0; i < d->objects->length; i++)
>        {
> @@ -234,7 +234,7 @@ public:
>  
>    /* Walk over all declarations in the attribute scope.  */
>  
> -  void visit (AttribDeclaration *d)
> +  void visit (AttribDeclaration *d) final override
>    {
>      Dsymbols *ds = d->include (NULL);
>  
> @@ -248,7 +248,7 @@ public:
>    /* Pragmas are a way to pass special information to the compiler and to add
>       vendor specific extensions to D.  */
>  
> -  void visit (PragmaDeclaration *d)
> +  void visit (PragmaDeclaration *d) final override
>    {
>      if (d->ident == Identifier::idPool ("lib")
>  	|| d->ident == Identifier::idPool ("startaddress"))
> @@ -266,7 +266,7 @@ public:
>    /* Conditional compilation is the process of selecting which code to compile
>       and which code to not compile.  Look for version conditions that may  */
>  
> -  void visit (ConditionalDeclaration *d)
> +  void visit (ConditionalDeclaration *d) final override
>    {
>      bool old_condition = this->in_version_unittest_;
>  
> @@ -284,7 +284,7 @@ public:
>  
>    /* Walk over all members in the namespace scope.  */
>  
> -  void visit (Nspace *d)
> +  void visit (Nspace *d) final override
>    {
>      if (isError (d) || !d->members)
>        return;
> @@ -298,7 +298,7 @@ public:
>       voldemort type, then it's members must be compiled before the parent
>       function finishes.  */
>  
> -  void visit (TemplateDeclaration *d)
> +  void visit (TemplateDeclaration *d) final override
>    {
>      /* Type cannot be directly named outside of the scope it's declared in, so
>         the only way it can be escaped is if the function has auto return.  */
> @@ -329,7 +329,7 @@ public:
>  
>    /* Walk over all members in the instantiated template.  */
>  
> -  void visit (TemplateInstance *d)
> +  void visit (TemplateInstance *d) final override
>    {
>      if (isError (d)|| !d->members)
>        return;
> @@ -343,7 +343,7 @@ public:
>  
>    /* Walk over all members in the mixin template scope.  */
>  
> -  void visit (TemplateMixin *d)
> +  void visit (TemplateMixin *d) final override
>    {
>      if (isError (d)|| !d->members)
>        return;
> @@ -355,7 +355,7 @@ public:
>    /* Write out compiler generated TypeInfo, initializer and functions for the
>       given struct declaration, walking over all static members.  */
>  
> -  void visit (StructDeclaration *d)
> +  void visit (StructDeclaration *d) final override
>    {
>      if (d->semanticRun >= PASS::obj)
>        return;
> @@ -470,7 +470,7 @@ public:
>    /* Write out compiler generated TypeInfo, initializer and vtables for the
>       given class declaration, walking over all static members.  */
>  
> -  void visit (ClassDeclaration *d)
> +  void visit (ClassDeclaration *d) final override
>    {
>      if (d->semanticRun >= PASS::obj)
>        return;
> @@ -544,7 +544,7 @@ public:
>    /* Write out compiler generated TypeInfo and vtables for the given interface
>       declaration, walking over all static members.  */
>  
> -  void visit (InterfaceDeclaration *d)
> +  void visit (InterfaceDeclaration *d) final override
>    {
>      if (d->semanticRun >= PASS::obj)
>        return;
> @@ -587,7 +587,7 @@ public:
>    /* Write out compiler generated TypeInfo and initializer for the given
>       enum declaration.  */
>  
> -  void visit (EnumDeclaration *d)
> +  void visit (EnumDeclaration *d) final override
>    {
>      if (d->semanticRun >= PASS::obj)
>        return;
> @@ -626,7 +626,7 @@ public:
>    /* Finish up a variable declaration and push it into the current scope.
>       This can either be a static, local or manifest constant.  */
>  
> -  void visit (VarDeclaration *d)
> +  void visit (VarDeclaration *d) final override
>    {
>      if (d->semanticRun >= PASS::obj)
>        return;
> @@ -753,7 +753,7 @@ public:
>    /* Generate and compile a static TypeInfo declaration, but only if it is
>       needed in the current compilation.  */
>  
> -  void visit (TypeInfoDeclaration *d)
> +  void visit (TypeInfoDeclaration *d) final override
>    {
>      if (d->semanticRun >= PASS::obj)
>        return;
> @@ -770,7 +770,7 @@ public:
>    /* Finish up a function declaration and compile it all the way
>       down to assembler language output.  */
>  
> -  void visit (FuncDeclaration *d)
> +  void visit (FuncDeclaration *d) final override
>    {
>      /* Already generated the function.  */
>      if (d->semanticRun >= PASS::obj)
> diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
> index 7f5e683a676..c259e7df6d5 100644
> --- a/gcc/d/expr.cc
> +++ b/gcc/d/expr.cc
> @@ -2556,7 +2556,7 @@ public:
>    /* Build a tuple literal.  Just an argument list that may have
>       side effects that need evaluation.  */
>  
> -  void visit (TupleExp *e)
> +  void visit (TupleExp *e) final override
>    {
>      tree result = NULL_TREE;
>  
> diff --git a/gcc/d/toir.cc b/gcc/d/toir.cc
> index d20c5c3b927..50d44156cca 100644
> --- a/gcc/d/toir.cc
> +++ b/gcc/d/toir.cc
> @@ -534,7 +534,7 @@ public:
>  
>    /* This should be overridden by each statement class.  */
>  
> -  void visit (Statement *)
> +  void visit (Statement *) final override
>    {
>      gcc_unreachable ();
>    }
> @@ -543,13 +543,13 @@ public:
>       try/catch/finally.  At this point, this statement is just an empty
>       placeholder.  Maybe the frontend shouldn't leak these.  */
>  
> -  void visit (ScopeGuardStatement *)
> +  void visit (ScopeGuardStatement *) final override
>    {
>    }
>  
>    /* If statements provide simple conditional execution of statements.  */
>  
> -  void visit (IfStatement *s)
> +  void visit (IfStatement *s) final override
>    {
>      this->start_scope (level_cond);
>  
> @@ -588,7 +588,7 @@ public:
>       here would be the place to do it.  For now, all pragmas are handled
>       by the frontend.  */
>  
> -  void visit (PragmaStatement *)
> +  void visit (PragmaStatement *) final override
>    {
>    }
>  
> @@ -596,7 +596,7 @@ public:
>       This visitor is not strictly required other than to enforce that
>       these kinds of statements never reach here.  */
>  
> -  void visit (WhileStatement *)
> +  void visit (WhileStatement *) final override
>    {
>      gcc_unreachable ();
>    }
> @@ -604,7 +604,7 @@ public:
>    /* Do while statments implement simple loops.  The body is executed, then
>       the condition is evaluated.  */
>  
> -  void visit (DoStatement *s)
> +  void visit (DoStatement *s) final override
>    {
>      tree lbreak = this->push_break_label (s);
>  
> @@ -633,7 +633,7 @@ public:
>    /* For statements implement loops with initialization, test, and
>       increment clauses.  */
>  
> -  void visit (ForStatement *s)
> +  void visit (ForStatement *s) final override
>    {
>      tree lbreak = this->push_break_label (s);
>      this->start_scope (level_loop);
> @@ -674,7 +674,7 @@ public:
>       This visitor is not strictly required other than to enforce that
>       these kinds of statements never reach here.  */
>  
> -  void visit (ForeachStatement *)
> +  void visit (ForeachStatement *) final override
>    {
>      gcc_unreachable ();
>    }
> @@ -683,7 +683,7 @@ public:
>       loops.  This visitor is not strictly required other than to enforce that
>       these kinds of statements never reach here.  */
>  
> -  void visit (ForeachRangeStatement *)
> +  void visit (ForeachRangeStatement *) final override
>    {
>      gcc_unreachable ();
>    }
> @@ -691,7 +691,7 @@ public:
>    /* Jump to the associated exit label for the current loop.  If IDENT
>       for the Statement is not null, then the label is user defined.  */
>  
> -  void visit (BreakStatement *s)
> +  void visit (BreakStatement *s) final override
>    {
>      if (s->ident)
>        {
> @@ -710,7 +710,7 @@ public:
>    /* Jump to the associated continue label for the current loop.  If IDENT
>       for the Statement is not null, then the label is user defined.  */
>  
> -  void visit (ContinueStatement *s)
> +  void visit (ContinueStatement *s) final override
>    {
>      if (s->ident)
>        {
> @@ -726,7 +726,7 @@ public:
>  
>    /* A goto statement jumps to the statement identified by the given label.  */
>  
> -  void visit (GotoStatement *s)
> +  void visit (GotoStatement *s) final override
>    {
>      gcc_assert (s->label->statement != NULL);
>      gcc_assert (s->tf == s->label->statement->tf);
> @@ -742,7 +742,7 @@ public:
>    /* Statements can be labeled.  A label is an identifier that precedes
>       a statement.  */
>  
> -  void visit (LabelStatement *s)
> +  void visit (LabelStatement *s) final override
>    {
>      LabelDsymbol *sym;
>  
> @@ -766,7 +766,7 @@ public:
>    /* A switch statement goes to one of a collection of case statements
>       depending on the value of the switch expression.  */
>  
> -  void visit (SwitchStatement *s)
> +  void visit (SwitchStatement *s) final override
>    {
>      this->start_scope (level_switch);
>      tree lbreak = this->push_break_label (s);
> @@ -855,7 +855,7 @@ public:
>  
>    /* Declare the case label associated with the current SwitchStatement.  */
>  
> -  void visit (CaseStatement *s)
> +  void visit (CaseStatement *s) final override
>    {
>      /* Emit the case label.  */
>      tree label = this->define_label (s);
> @@ -881,7 +881,7 @@ public:
>  
>    /* Declare the default label associated with the current SwitchStatement.  */
>  
> -  void visit (DefaultStatement *s)
> +  void visit (DefaultStatement *s) final override
>    {
>      /* Emit the default case label.  */
>      tree label = this->define_label (s);
> @@ -902,7 +902,7 @@ public:
>    /* Implements `goto default' by jumping to the label associated with
>       the DefaultStatement in a switch block.  */
>  
> -  void visit (GotoDefaultStatement *s)
> +  void visit (GotoDefaultStatement *s) final override
>    {
>      tree label = this->lookup_label (s->sw->sdefault);
>      this->do_jump (label);
> @@ -911,7 +911,7 @@ public:
>    /* Implements `goto case' by jumping to the label associated with the
>       CaseStatement in a switch block.  */
>  
> -  void visit (GotoCaseStatement *s)
> +  void visit (GotoCaseStatement *s) final override
>    {
>      tree label = this->lookup_label (s->cs);
>      this->do_jump (label);
> @@ -920,7 +920,7 @@ public:
>    /* Throw a SwitchError exception, called when a switch statement has
>       no DefaultStatement, yet none of the cases match.  */
>  
> -  void visit (SwitchErrorStatement *s)
> +  void visit (SwitchErrorStatement *s) final override
>    {
>      /* A throw SwitchError statement gets turned into a library call.
>         The call is wrapped in the enclosed expression.  */
> @@ -931,7 +931,7 @@ public:
>    /* A return statement exits the current function and supplies its return
>       value, if the return type is not void.  */
>  
> -  void visit (ReturnStatement *s)
> +  void visit (ReturnStatement *s) final override
>    {
>      if (s->exp == NULL || s->exp->type->toBasetype ()->ty == TY::Tvoid)
>        {
> @@ -1044,7 +1044,7 @@ public:
>  
>    /* Evaluate the enclosed expression, and add it to the statement list.  */
>  
> -  void visit (ExpStatement *s)
> +  void visit (ExpStatement *s) final override
>    {
>      if (s->exp)
>        {
> @@ -1056,7 +1056,7 @@ public:
>  
>    /* Evaluate all enclosed statements.  */
>  
> -  void visit (CompoundStatement *s)
> +  void visit (CompoundStatement *s) final override
>    {
>      if (s->statements == NULL)
>        return;
> @@ -1074,7 +1074,7 @@ public:
>       These are compiled down as a `do ... while (0)', where each unrolled loop
>       is nested inside and given their own continue label to jump to.  */
>  
> -  void visit (UnrolledLoopStatement *s)
> +  void visit (UnrolledLoopStatement *s) final override
>    {
>      if (s->statements == NULL)
>        return;
> @@ -1105,7 +1105,7 @@ public:
>    /* Start a new scope and visit all nested statements, wrapping
>       them up into a BIND_EXPR at the end of the scope.  */
>  
> -  void visit (ScopeStatement *s)
> +  void visit (ScopeStatement *s) final override
>    {
>      if (s->statement == NULL)
>        return;
> @@ -1118,7 +1118,7 @@ public:
>    /* A with statement is a way to simplify repeated references to the same
>       object, where the handle is either a class or struct instance.  */
>  
> -  void visit (WithStatement *s)
> +  void visit (WithStatement *s) final override
>    {
>      this->start_scope (level_with);
>  
> @@ -1143,7 +1143,7 @@ public:
>       thrown is a class type, but does not check if it is derived from
>       Object.  Foreign objects are not currently supported at run-time.  */
>  
> -  void visit (ThrowStatement *s)
> +  void visit (ThrowStatement *s) final override
>    {
>      ClassDeclaration *cd = s->exp->type->toBasetype ()->isClassHandle ();
>      InterfaceDeclaration *id = cd->isInterfaceDeclaration ();
> @@ -1174,7 +1174,7 @@ public:
>       handling generated by the frontend.  This is also used to implement
>       `scope (failure)' statements.  */
>  
> -  void visit (TryCatchStatement *s)
> +  void visit (TryCatchStatement *s) final override
>    {
>      this->start_scope (level_try);
>      if (s->_body)
> @@ -1263,7 +1263,7 @@ public:
>       handling generated by the frontend.  This is also used to implement
>       `scope (exit)' statements.  */
>  
> -  void visit (TryFinallyStatement *s)
> +  void visit (TryFinallyStatement *s) final override
>    {
>      this->start_scope (level_try);
>      if (s->_body)
> @@ -1285,7 +1285,7 @@ public:
>       This visitor is not strictly required other than to enforce that
>       these kinds of statements never reach here.  */
>  
> -  void visit (SynchronizedStatement *)
> +  void visit (SynchronizedStatement *) final override
>    {
>      gcc_unreachable ();
>    }
> @@ -1294,7 +1294,7 @@ public:
>       an assembly parser for each supported target.  Instead we leverage
>       GCC extended assembler using the GccAsmStatement class.  */
>  
> -  void visit (AsmStatement *)
> +  void visit (AsmStatement *) final override
>    {
>      sorry ("D inline assembler statements are not supported in GDC.");
>    }
> @@ -1302,7 +1302,7 @@ public:
>    /* Build a GCC extended assembler expression, whose components are
>       an INSN string, some OUTPUTS, some INPUTS, and some CLOBBERS.  */
>  
> -  void visit (GccAsmStatement *s)
> +  void visit (GccAsmStatement *s) final override
>    {
>      StringExp *insn = s->insn->toStringExp ();
>      tree outputs = NULL_TREE;
> @@ -1454,7 +1454,7 @@ public:
>  
>    /* Import symbols from another module.  */
>  
> -  void visit (ImportStatement *s)
> +  void visit (ImportStatement *s) final override
>    {
>      if (s->imports == NULL)
>        return;
> diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc
> index 668b7b3c8e1..a31762fe270 100644
> --- a/gcc/d/typeinfo.cc
> +++ b/gcc/d/typeinfo.cc
> @@ -556,7 +556,7 @@ public:
>  	void **__vptr;
>  	void *__monitor;  */
>  
> -  void visit (TypeInfoDeclaration *)
> +  void visit (TypeInfoDeclaration *) final override
>    {
>      /* The vtable for TypeInfo.  */
>      this->layout_base (Type::dtypeinfo);
> @@ -567,7 +567,7 @@ public:
>  	void *__monitor;
>  	TypeInfo base;  */
>  
> -  void visit (TypeInfoConstDeclaration *d)
> +  void visit (TypeInfoConstDeclaration *d) final override
>    {
>      Type *tm = d->tinfo->mutableOf ();
>      tm = tm->merge2 ();
> @@ -584,7 +584,7 @@ public:
>  	void *__monitor;
>  	TypeInfo base;  */
>  
> -  void visit (TypeInfoInvariantDeclaration *d)
> +  void visit (TypeInfoInvariantDeclaration *d) final override
>    {
>      Type *tm = d->tinfo->mutableOf ();
>      tm = tm->merge2 ();
> @@ -601,7 +601,7 @@ public:
>  	void *__monitor;
>  	TypeInfo base;  */
>  
> -  void visit (TypeInfoSharedDeclaration *d)
> +  void visit (TypeInfoSharedDeclaration *d) final override
>    {
>      Type *tm = d->tinfo->unSharedOf ();
>      tm = tm->merge2 ();
> @@ -618,7 +618,7 @@ public:
>  	void *__monitor;
>  	TypeInfo base;  */
>  
> -  void visit (TypeInfoWildDeclaration *d)
> +  void visit (TypeInfoWildDeclaration *d) final override
>    {
>      Type *tm = d->tinfo->mutableOf ();
>      tm = tm->merge2 ();
> @@ -637,7 +637,7 @@ public:
>  	string name;
>  	void[] m_init;  */
>  
> -  void visit (TypeInfoEnumDeclaration *d)
> +  void visit (TypeInfoEnumDeclaration *d) final override
>    {
>      TypeEnum *ti = d->tinfo->isTypeEnum ();
>      EnumDeclaration *ed = ti->sym;
> @@ -669,7 +669,7 @@ public:
>  	void *__monitor;
>  	TypeInfo m_next;  */
>  
> -  void visit (TypeInfoPointerDeclaration *d)
> +  void visit (TypeInfoPointerDeclaration *d) final override
>    {
>      TypePointer *ti = d->tinfo->isTypePointer ();
>  
> @@ -685,7 +685,7 @@ public:
>  	void *__monitor;
>  	TypeInfo value;  */
>  
> -  void visit (TypeInfoArrayDeclaration *d)
> +  void visit (TypeInfoArrayDeclaration *d) final override
>    {
>      TypeDArray *ti = d->tinfo->isTypeDArray ();
>  
> @@ -702,7 +702,7 @@ public:
>  	TypeInfo value;
>  	size_t len;  */
>  
> -  void visit (TypeInfoStaticArrayDeclaration *d)
> +  void visit (TypeInfoStaticArrayDeclaration *d) final override
>    {
>      TypeSArray *ti = d->tinfo->isTypeSArray ();
>  
> @@ -722,7 +722,7 @@ public:
>  	TypeInfo value;
>  	TypeInfo key;  */
>  
> -  void visit (TypeInfoAssociativeArrayDeclaration *d)
> +  void visit (TypeInfoAssociativeArrayDeclaration *d) final override
>    {
>      TypeAArray *ti = d->tinfo->isTypeAArray ();
>  
> @@ -741,7 +741,7 @@ public:
>  	void *__monitor;
>  	TypeInfo base;  */
>  
> -  void visit (TypeInfoVectorDeclaration *d)
> +  void visit (TypeInfoVectorDeclaration *d) final override
>    {
>      TypeVector *ti = d->tinfo->isTypeVector ();
>  
> @@ -758,7 +758,7 @@ public:
>  	TypeInfo next;
>  	string deco;  */
>  
> -  void visit (TypeInfoFunctionDeclaration *d)
> +  void visit (TypeInfoFunctionDeclaration *d) final override
>    {
>      TypeFunction *ti = d->tinfo->isTypeFunction ();
>      gcc_assert (ti->deco != NULL);
> @@ -779,7 +779,7 @@ public:
>  	TypeInfo next;
>  	string deco;  */
>  
> -  void visit (TypeInfoDelegateDeclaration *d)
> +  void visit (TypeInfoDelegateDeclaration *d) final override
>    {
>      TypeDelegate *ti = d->tinfo->isTypeDelegate ();
>      gcc_assert (ti->deco != NULL);
> @@ -813,7 +813,7 @@ public:
>       Information relating to interfaces, and their vtables are laid out
>       immediately after the named fields, if there is anything to write.  */
>  
> -  void visit (TypeInfoClassDeclaration *d)
> +  void visit (TypeInfoClassDeclaration *d) final override
>    {
>      TypeClass *ti = d->tinfo->isTypeClass ();
>      ClassDeclaration *cd = ti->sym;
> @@ -1004,7 +1004,7 @@ public:
>  	void *__monitor;
>  	TypeInfo_Class info;  */
>  
> -  void visit (TypeInfoInterfaceDeclaration *d)
> +  void visit (TypeInfoInterfaceDeclaration *d) final override
>    {
>      TypeClass *ti = d->tinfo->isTypeClass ();
>  
> @@ -1034,7 +1034,7 @@ public:
>  	uint m_align;
>  	immutable(void)* xgetRTInfo;  */
>  
> -  void visit (TypeInfoStructDeclaration *d)
> +  void visit (TypeInfoStructDeclaration *d) final override
>    {
>      TypeStruct *ti = d->tinfo->isTypeStruct ();
>      StructDeclaration *sd = ti->sym;
> @@ -1119,7 +1119,7 @@ public:
>  	void *__monitor;
>  	TypeInfo[] elements;  */
>  
> -  void visit (TypeInfoTupleDeclaration *d)
> +  void visit (TypeInfoTupleDeclaration *d) final override
>    {
>      TypeTuple *ti = d->tinfo->isTypeTuple ();
>  
> diff --git a/gcc/d/types.cc b/gcc/d/types.cc
> index c54049dfb98..b17b15359c8 100644
> --- a/gcc/d/types.cc
> +++ b/gcc/d/types.cc
> @@ -665,7 +665,7 @@ public:
>  
>    /* This should be overridden by each type class.  */
>  
> -  void visit (Type *)
> +  void visit (Type *) final override
>    {
>      gcc_unreachable ();
>    }
> @@ -673,21 +673,21 @@ public:
>    /* Type assigned to erroneous expressions or constructs that
>       failed during the semantic stage.  */
>  
> -  void visit (TypeError *t)
> +  void visit (TypeError *t) final override
>    {
>      t->ctype = error_mark_node;
>    }
>  
>    /* Type assigned to generic nullable types.  */
>  
> -  void visit (TypeNull *t)
> +  void visit (TypeNull *t) final override
>    {
>      t->ctype = ptr_type_node;
>    }
>  
>    /* Bottom type used for functions that never return.  */
>  
> -  void visit (TypeNoreturn *t)
> +  void visit (TypeNoreturn *t) final override
>    {
>      t->ctype = noreturn_type_node;
>      TYPE_NAME (t->ctype) = get_identifier (t->toChars ());
> @@ -695,7 +695,7 @@ public:
>  
>    /* Basic Data Types.  */
>  
> -  void visit (TypeBasic *t)
> +  void visit (TypeBasic *t) final override
>    {
>      /* [type/basic-data-types]
>  
> @@ -761,7 +761,7 @@ public:
>  
>    /* Build a simple pointer to data type, analogous to C pointers.  */
>  
> -  void visit (TypePointer *t)
> +  void visit (TypePointer *t) final override
>    {
>      t->ctype = build_pointer_type (build_ctype (t->next));
>    }
> @@ -769,7 +769,7 @@ public:
>    /* Build a dynamic array type, consisting of a length and a pointer
>       to the array data.  */
>  
> -  void visit (TypeDArray *t)
> +  void visit (TypeDArray *t) final override
>    {
>      /* In [abi/arrays], dynamic array layout is:
>  	.length	array dimension.
> @@ -787,7 +787,7 @@ public:
>    /* Build a static array type, distinguished from dynamic arrays by
>       having a length fixed at compile-time, analogous to C arrays.  */
>  
> -  void visit (TypeSArray *t)
> +  void visit (TypeSArray *t) final override
>    {
>      if (t->dim->isConst () && t->dim->type->isintegral ())
>        {
> @@ -804,7 +804,7 @@ public:
>  
>    /* Build a vector type, a fixed array of floating or integer types.  */
>  
> -  void visit (TypeVector *t)
> +  void visit (TypeVector *t) final override
>    {
>      int nunits = t->basetype->isTypeSArray ()->dim->toUInteger ();
>      tree inner = build_ctype (t->elementType ());
> @@ -821,7 +821,7 @@ public:
>    /* Build an associative array type, distinguished from arrays by having an
>       index that's not necessarily an integer, and can be sparsely populated.  */
>  
> -  void visit (TypeAArray *t)
> +  void visit (TypeAArray *t) final override
>    {
>      /* In [abi/associative-arrays], associative arrays are a struct that only
>         consist of a pointer to an opaque, implementation defined type.  */
> @@ -835,7 +835,7 @@ public:
>    /* Build type for a function declaration, which consists of a return type,
>       and a list of parameter types, and a linkage attribute.  */
>  
> -  void visit (TypeFunction *t)
> +  void visit (TypeFunction *t) final override
>    {
>      tree fnparams = NULL_TREE;
>      tree fntype;
> @@ -925,7 +925,7 @@ public:
>       reference and a pointer to a non-static member function, or a pointer
>       to a closure and a pointer to a nested function.  */
>  
> -  void visit (TypeDelegate *t)
> +  void visit (TypeDelegate *t) final override
>    {
>      /* In [abi/delegates], delegate layout is:
>  	.ptr	    context pointer.
> @@ -952,7 +952,7 @@ public:
>    /* Build a named enum type, a distinct value whose values are restrict to
>       a group of constants of the same underlying base type.  */
>  
> -  void visit (TypeEnum *t)
> +  void visit (TypeEnum *t) final override
>    {
>      tree basetype = (t->sym->memtype)
>        ? build_ctype (t->sym->memtype) : void_type_node;
> @@ -1067,7 +1067,7 @@ public:
>    /* Build a struct or union type.  Layout should be exactly represented
>       as an equivalent C struct, except for non-POD or nested structs.  */
>  
> -  void visit (TypeStruct *t)
> +  void visit (TypeStruct *t) final override
>    {
>      /* Merge types in the back-end if the front-end did not itself do so.  */
>      tree deco = get_identifier (d_mangle_decl (t->sym));
> @@ -1123,7 +1123,7 @@ public:
>    /* Build a class type.  Whereas structs are value types, classes are
>       reference types, with all the object-orientated features.  */
>  
> -  void visit (TypeClass *t)
> +  void visit (TypeClass *t) final override
>    {
>      /* Merge types in the back-end if the front-end did not itself do so.  */
>      tree deco = get_identifier (d_mangle_decl (t->sym));
> -- 
> 2.26.3
> 
>
  
David Malcolm May 24, 2022, 1:15 p.m. UTC | #2
On Tue, 2022-05-24 at 14:56 +0200, Iain Buclaw wrote:
> Excerpts from David Malcolm via Gcc-patches's message of Mai 23, 2022
> 9:28 pm:
> > gcc/d/ChangeLog:
> >         * decl.cc: Add "final" and "override" to all "visit" vfunc
> > decls
> >         as appropriate.
> >         * expr.cc: Likewise.
> >         * toir.cc: Likewise.
> >         * typeinfo.cc: Likewise.
> >         * types.cc: Likewise.
> > 
> > Signed-off-by: David Malcolm <dmalcolm@redhat.com>
> 
> 
> Thanks David!
> 
> Looks OK to me.
> 
> Iain.

Thanks; I've pushed it to trunk as r13-736-g442cf0977a2993.

FWIW, to repeat something I said in the cover letter, I tried hacking -
Werror=suggest-override into the Makefile whilst I was creating the
patches, and IIRC there were a bunch of them in the gcc/d/dmd
subdirectory - but that code is copied from the D community upstream,
right?
So maybe if that D parser C++ code requires a C++11 compiler, perhaps
they might want to add "final" and "override" specifiers to it as
appropriate, to better document the intent of the decls?

Hope this is constructive
Dave
  
Iain Buclaw May 24, 2022, 3:11 p.m. UTC | #3
Excerpts from David Malcolm's message of Mai 24, 2022 3:15 pm:
> On Tue, 2022-05-24 at 14:56 +0200, Iain Buclaw wrote:
>> Excerpts from David Malcolm via Gcc-patches's message of Mai 23, 2022
>> 9:28 pm:
>> > gcc/d/ChangeLog:
>> >         * decl.cc: Add "final" and "override" to all "visit" vfunc
>> > decls
>> >         as appropriate.
>> >         * expr.cc: Likewise.
>> >         * toir.cc: Likewise.
>> >         * typeinfo.cc: Likewise.
>> >         * types.cc: Likewise.
>> > 
>> > Signed-off-by: David Malcolm <dmalcolm@redhat.com>
>> 
>> 
>> Thanks David!
>> 
>> Looks OK to me.
>> 
>> Iain.
> 
> Thanks; I've pushed it to trunk as r13-736-g442cf0977a2993.
> 
> FWIW, to repeat something I said in the cover letter, I tried hacking -
> Werror=suggest-override into the Makefile whilst I was creating the
> patches, and IIRC there were a bunch of them in the gcc/d/dmd
> subdirectory - but that code is copied from the D community upstream,
> right?
> So maybe if that D parser C++ code requires a C++11 compiler, perhaps
> they might want to add "final" and "override" specifiers to it as
> appropriate, to better document the intent of the decls?
> 

The D parser code is written in D, but most of it is marked
"extern(C++)" so that the code generator can interface with it.  It is
already a hard requirement in D that all overriden method have the
"override" keyword, and "final" is already tacked on most places, so for
the most part it is already there, just hasn't been mirrored to the C++
interfaces in the headers.

I'll have a look into it.

Iain.
  

Patch

diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index f5c21078aad..5d850065bf0 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -149,13 +149,13 @@  public:
 
   /* This should be overridden by each declaration class.  */
 
-  void visit (Dsymbol *)
+  void visit (Dsymbol *) final override
   {
   }
 
   /* Compile a D module, and all members of it.  */
 
-  void visit (Module *d)
+  void visit (Module *d) final override
   {
     if (d->semanticRun >= PASS::obj)
       return;
@@ -166,7 +166,7 @@  public:
 
   /* Write the imported symbol to debug.  */
 
-  void visit (Import *d)
+  void visit (Import *d) final override
   {
     if (d->semanticRun >= PASS::obj)
       return;
@@ -218,7 +218,7 @@  public:
 
   /* Expand any local variables found in tuples.  */
 
-  void visit (TupleDeclaration *d)
+  void visit (TupleDeclaration *d) final override
   {
     for (size_t i = 0; i < d->objects->length; i++)
       {
@@ -234,7 +234,7 @@  public:
 
   /* Walk over all declarations in the attribute scope.  */
 
-  void visit (AttribDeclaration *d)
+  void visit (AttribDeclaration *d) final override
   {
     Dsymbols *ds = d->include (NULL);
 
@@ -248,7 +248,7 @@  public:
   /* Pragmas are a way to pass special information to the compiler and to add
      vendor specific extensions to D.  */
 
-  void visit (PragmaDeclaration *d)
+  void visit (PragmaDeclaration *d) final override
   {
     if (d->ident == Identifier::idPool ("lib")
 	|| d->ident == Identifier::idPool ("startaddress"))
@@ -266,7 +266,7 @@  public:
   /* Conditional compilation is the process of selecting which code to compile
      and which code to not compile.  Look for version conditions that may  */
 
-  void visit (ConditionalDeclaration *d)
+  void visit (ConditionalDeclaration *d) final override
   {
     bool old_condition = this->in_version_unittest_;
 
@@ -284,7 +284,7 @@  public:
 
   /* Walk over all members in the namespace scope.  */
 
-  void visit (Nspace *d)
+  void visit (Nspace *d) final override
   {
     if (isError (d) || !d->members)
       return;
@@ -298,7 +298,7 @@  public:
      voldemort type, then it's members must be compiled before the parent
      function finishes.  */
 
-  void visit (TemplateDeclaration *d)
+  void visit (TemplateDeclaration *d) final override
   {
     /* Type cannot be directly named outside of the scope it's declared in, so
        the only way it can be escaped is if the function has auto return.  */
@@ -329,7 +329,7 @@  public:
 
   /* Walk over all members in the instantiated template.  */
 
-  void visit (TemplateInstance *d)
+  void visit (TemplateInstance *d) final override
   {
     if (isError (d)|| !d->members)
       return;
@@ -343,7 +343,7 @@  public:
 
   /* Walk over all members in the mixin template scope.  */
 
-  void visit (TemplateMixin *d)
+  void visit (TemplateMixin *d) final override
   {
     if (isError (d)|| !d->members)
       return;
@@ -355,7 +355,7 @@  public:
   /* Write out compiler generated TypeInfo, initializer and functions for the
      given struct declaration, walking over all static members.  */
 
-  void visit (StructDeclaration *d)
+  void visit (StructDeclaration *d) final override
   {
     if (d->semanticRun >= PASS::obj)
       return;
@@ -470,7 +470,7 @@  public:
   /* Write out compiler generated TypeInfo, initializer and vtables for the
      given class declaration, walking over all static members.  */
 
-  void visit (ClassDeclaration *d)
+  void visit (ClassDeclaration *d) final override
   {
     if (d->semanticRun >= PASS::obj)
       return;
@@ -544,7 +544,7 @@  public:
   /* Write out compiler generated TypeInfo and vtables for the given interface
      declaration, walking over all static members.  */
 
-  void visit (InterfaceDeclaration *d)
+  void visit (InterfaceDeclaration *d) final override
   {
     if (d->semanticRun >= PASS::obj)
       return;
@@ -587,7 +587,7 @@  public:
   /* Write out compiler generated TypeInfo and initializer for the given
      enum declaration.  */
 
-  void visit (EnumDeclaration *d)
+  void visit (EnumDeclaration *d) final override
   {
     if (d->semanticRun >= PASS::obj)
       return;
@@ -626,7 +626,7 @@  public:
   /* Finish up a variable declaration and push it into the current scope.
      This can either be a static, local or manifest constant.  */
 
-  void visit (VarDeclaration *d)
+  void visit (VarDeclaration *d) final override
   {
     if (d->semanticRun >= PASS::obj)
       return;
@@ -753,7 +753,7 @@  public:
   /* Generate and compile a static TypeInfo declaration, but only if it is
      needed in the current compilation.  */
 
-  void visit (TypeInfoDeclaration *d)
+  void visit (TypeInfoDeclaration *d) final override
   {
     if (d->semanticRun >= PASS::obj)
       return;
@@ -770,7 +770,7 @@  public:
   /* Finish up a function declaration and compile it all the way
      down to assembler language output.  */
 
-  void visit (FuncDeclaration *d)
+  void visit (FuncDeclaration *d) final override
   {
     /* Already generated the function.  */
     if (d->semanticRun >= PASS::obj)
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 7f5e683a676..c259e7df6d5 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -2556,7 +2556,7 @@  public:
   /* Build a tuple literal.  Just an argument list that may have
      side effects that need evaluation.  */
 
-  void visit (TupleExp *e)
+  void visit (TupleExp *e) final override
   {
     tree result = NULL_TREE;
 
diff --git a/gcc/d/toir.cc b/gcc/d/toir.cc
index d20c5c3b927..50d44156cca 100644
--- a/gcc/d/toir.cc
+++ b/gcc/d/toir.cc
@@ -534,7 +534,7 @@  public:
 
   /* This should be overridden by each statement class.  */
 
-  void visit (Statement *)
+  void visit (Statement *) final override
   {
     gcc_unreachable ();
   }
@@ -543,13 +543,13 @@  public:
      try/catch/finally.  At this point, this statement is just an empty
      placeholder.  Maybe the frontend shouldn't leak these.  */
 
-  void visit (ScopeGuardStatement *)
+  void visit (ScopeGuardStatement *) final override
   {
   }
 
   /* If statements provide simple conditional execution of statements.  */
 
-  void visit (IfStatement *s)
+  void visit (IfStatement *s) final override
   {
     this->start_scope (level_cond);
 
@@ -588,7 +588,7 @@  public:
      here would be the place to do it.  For now, all pragmas are handled
      by the frontend.  */
 
-  void visit (PragmaStatement *)
+  void visit (PragmaStatement *) final override
   {
   }
 
@@ -596,7 +596,7 @@  public:
      This visitor is not strictly required other than to enforce that
      these kinds of statements never reach here.  */
 
-  void visit (WhileStatement *)
+  void visit (WhileStatement *) final override
   {
     gcc_unreachable ();
   }
@@ -604,7 +604,7 @@  public:
   /* Do while statments implement simple loops.  The body is executed, then
      the condition is evaluated.  */
 
-  void visit (DoStatement *s)
+  void visit (DoStatement *s) final override
   {
     tree lbreak = this->push_break_label (s);
 
@@ -633,7 +633,7 @@  public:
   /* For statements implement loops with initialization, test, and
      increment clauses.  */
 
-  void visit (ForStatement *s)
+  void visit (ForStatement *s) final override
   {
     tree lbreak = this->push_break_label (s);
     this->start_scope (level_loop);
@@ -674,7 +674,7 @@  public:
      This visitor is not strictly required other than to enforce that
      these kinds of statements never reach here.  */
 
-  void visit (ForeachStatement *)
+  void visit (ForeachStatement *) final override
   {
     gcc_unreachable ();
   }
@@ -683,7 +683,7 @@  public:
      loops.  This visitor is not strictly required other than to enforce that
      these kinds of statements never reach here.  */
 
-  void visit (ForeachRangeStatement *)
+  void visit (ForeachRangeStatement *) final override
   {
     gcc_unreachable ();
   }
@@ -691,7 +691,7 @@  public:
   /* Jump to the associated exit label for the current loop.  If IDENT
      for the Statement is not null, then the label is user defined.  */
 
-  void visit (BreakStatement *s)
+  void visit (BreakStatement *s) final override
   {
     if (s->ident)
       {
@@ -710,7 +710,7 @@  public:
   /* Jump to the associated continue label for the current loop.  If IDENT
      for the Statement is not null, then the label is user defined.  */
 
-  void visit (ContinueStatement *s)
+  void visit (ContinueStatement *s) final override
   {
     if (s->ident)
       {
@@ -726,7 +726,7 @@  public:
 
   /* A goto statement jumps to the statement identified by the given label.  */
 
-  void visit (GotoStatement *s)
+  void visit (GotoStatement *s) final override
   {
     gcc_assert (s->label->statement != NULL);
     gcc_assert (s->tf == s->label->statement->tf);
@@ -742,7 +742,7 @@  public:
   /* Statements can be labeled.  A label is an identifier that precedes
      a statement.  */
 
-  void visit (LabelStatement *s)
+  void visit (LabelStatement *s) final override
   {
     LabelDsymbol *sym;
 
@@ -766,7 +766,7 @@  public:
   /* A switch statement goes to one of a collection of case statements
      depending on the value of the switch expression.  */
 
-  void visit (SwitchStatement *s)
+  void visit (SwitchStatement *s) final override
   {
     this->start_scope (level_switch);
     tree lbreak = this->push_break_label (s);
@@ -855,7 +855,7 @@  public:
 
   /* Declare the case label associated with the current SwitchStatement.  */
 
-  void visit (CaseStatement *s)
+  void visit (CaseStatement *s) final override
   {
     /* Emit the case label.  */
     tree label = this->define_label (s);
@@ -881,7 +881,7 @@  public:
 
   /* Declare the default label associated with the current SwitchStatement.  */
 
-  void visit (DefaultStatement *s)
+  void visit (DefaultStatement *s) final override
   {
     /* Emit the default case label.  */
     tree label = this->define_label (s);
@@ -902,7 +902,7 @@  public:
   /* Implements `goto default' by jumping to the label associated with
      the DefaultStatement in a switch block.  */
 
-  void visit (GotoDefaultStatement *s)
+  void visit (GotoDefaultStatement *s) final override
   {
     tree label = this->lookup_label (s->sw->sdefault);
     this->do_jump (label);
@@ -911,7 +911,7 @@  public:
   /* Implements `goto case' by jumping to the label associated with the
      CaseStatement in a switch block.  */
 
-  void visit (GotoCaseStatement *s)
+  void visit (GotoCaseStatement *s) final override
   {
     tree label = this->lookup_label (s->cs);
     this->do_jump (label);
@@ -920,7 +920,7 @@  public:
   /* Throw a SwitchError exception, called when a switch statement has
      no DefaultStatement, yet none of the cases match.  */
 
-  void visit (SwitchErrorStatement *s)
+  void visit (SwitchErrorStatement *s) final override
   {
     /* A throw SwitchError statement gets turned into a library call.
        The call is wrapped in the enclosed expression.  */
@@ -931,7 +931,7 @@  public:
   /* A return statement exits the current function and supplies its return
      value, if the return type is not void.  */
 
-  void visit (ReturnStatement *s)
+  void visit (ReturnStatement *s) final override
   {
     if (s->exp == NULL || s->exp->type->toBasetype ()->ty == TY::Tvoid)
       {
@@ -1044,7 +1044,7 @@  public:
 
   /* Evaluate the enclosed expression, and add it to the statement list.  */
 
-  void visit (ExpStatement *s)
+  void visit (ExpStatement *s) final override
   {
     if (s->exp)
       {
@@ -1056,7 +1056,7 @@  public:
 
   /* Evaluate all enclosed statements.  */
 
-  void visit (CompoundStatement *s)
+  void visit (CompoundStatement *s) final override
   {
     if (s->statements == NULL)
       return;
@@ -1074,7 +1074,7 @@  public:
      These are compiled down as a `do ... while (0)', where each unrolled loop
      is nested inside and given their own continue label to jump to.  */
 
-  void visit (UnrolledLoopStatement *s)
+  void visit (UnrolledLoopStatement *s) final override
   {
     if (s->statements == NULL)
       return;
@@ -1105,7 +1105,7 @@  public:
   /* Start a new scope and visit all nested statements, wrapping
      them up into a BIND_EXPR at the end of the scope.  */
 
-  void visit (ScopeStatement *s)
+  void visit (ScopeStatement *s) final override
   {
     if (s->statement == NULL)
       return;
@@ -1118,7 +1118,7 @@  public:
   /* A with statement is a way to simplify repeated references to the same
      object, where the handle is either a class or struct instance.  */
 
-  void visit (WithStatement *s)
+  void visit (WithStatement *s) final override
   {
     this->start_scope (level_with);
 
@@ -1143,7 +1143,7 @@  public:
      thrown is a class type, but does not check if it is derived from
      Object.  Foreign objects are not currently supported at run-time.  */
 
-  void visit (ThrowStatement *s)
+  void visit (ThrowStatement *s) final override
   {
     ClassDeclaration *cd = s->exp->type->toBasetype ()->isClassHandle ();
     InterfaceDeclaration *id = cd->isInterfaceDeclaration ();
@@ -1174,7 +1174,7 @@  public:
      handling generated by the frontend.  This is also used to implement
      `scope (failure)' statements.  */
 
-  void visit (TryCatchStatement *s)
+  void visit (TryCatchStatement *s) final override
   {
     this->start_scope (level_try);
     if (s->_body)
@@ -1263,7 +1263,7 @@  public:
      handling generated by the frontend.  This is also used to implement
      `scope (exit)' statements.  */
 
-  void visit (TryFinallyStatement *s)
+  void visit (TryFinallyStatement *s) final override
   {
     this->start_scope (level_try);
     if (s->_body)
@@ -1285,7 +1285,7 @@  public:
      This visitor is not strictly required other than to enforce that
      these kinds of statements never reach here.  */
 
-  void visit (SynchronizedStatement *)
+  void visit (SynchronizedStatement *) final override
   {
     gcc_unreachable ();
   }
@@ -1294,7 +1294,7 @@  public:
      an assembly parser for each supported target.  Instead we leverage
      GCC extended assembler using the GccAsmStatement class.  */
 
-  void visit (AsmStatement *)
+  void visit (AsmStatement *) final override
   {
     sorry ("D inline assembler statements are not supported in GDC.");
   }
@@ -1302,7 +1302,7 @@  public:
   /* Build a GCC extended assembler expression, whose components are
      an INSN string, some OUTPUTS, some INPUTS, and some CLOBBERS.  */
 
-  void visit (GccAsmStatement *s)
+  void visit (GccAsmStatement *s) final override
   {
     StringExp *insn = s->insn->toStringExp ();
     tree outputs = NULL_TREE;
@@ -1454,7 +1454,7 @@  public:
 
   /* Import symbols from another module.  */
 
-  void visit (ImportStatement *s)
+  void visit (ImportStatement *s) final override
   {
     if (s->imports == NULL)
       return;
diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc
index 668b7b3c8e1..a31762fe270 100644
--- a/gcc/d/typeinfo.cc
+++ b/gcc/d/typeinfo.cc
@@ -556,7 +556,7 @@  public:
 	void **__vptr;
 	void *__monitor;  */
 
-  void visit (TypeInfoDeclaration *)
+  void visit (TypeInfoDeclaration *) final override
   {
     /* The vtable for TypeInfo.  */
     this->layout_base (Type::dtypeinfo);
@@ -567,7 +567,7 @@  public:
 	void *__monitor;
 	TypeInfo base;  */
 
-  void visit (TypeInfoConstDeclaration *d)
+  void visit (TypeInfoConstDeclaration *d) final override
   {
     Type *tm = d->tinfo->mutableOf ();
     tm = tm->merge2 ();
@@ -584,7 +584,7 @@  public:
 	void *__monitor;
 	TypeInfo base;  */
 
-  void visit (TypeInfoInvariantDeclaration *d)
+  void visit (TypeInfoInvariantDeclaration *d) final override
   {
     Type *tm = d->tinfo->mutableOf ();
     tm = tm->merge2 ();
@@ -601,7 +601,7 @@  public:
 	void *__monitor;
 	TypeInfo base;  */
 
-  void visit (TypeInfoSharedDeclaration *d)
+  void visit (TypeInfoSharedDeclaration *d) final override
   {
     Type *tm = d->tinfo->unSharedOf ();
     tm = tm->merge2 ();
@@ -618,7 +618,7 @@  public:
 	void *__monitor;
 	TypeInfo base;  */
 
-  void visit (TypeInfoWildDeclaration *d)
+  void visit (TypeInfoWildDeclaration *d) final override
   {
     Type *tm = d->tinfo->mutableOf ();
     tm = tm->merge2 ();
@@ -637,7 +637,7 @@  public:
 	string name;
 	void[] m_init;  */
 
-  void visit (TypeInfoEnumDeclaration *d)
+  void visit (TypeInfoEnumDeclaration *d) final override
   {
     TypeEnum *ti = d->tinfo->isTypeEnum ();
     EnumDeclaration *ed = ti->sym;
@@ -669,7 +669,7 @@  public:
 	void *__monitor;
 	TypeInfo m_next;  */
 
-  void visit (TypeInfoPointerDeclaration *d)
+  void visit (TypeInfoPointerDeclaration *d) final override
   {
     TypePointer *ti = d->tinfo->isTypePointer ();
 
@@ -685,7 +685,7 @@  public:
 	void *__monitor;
 	TypeInfo value;  */
 
-  void visit (TypeInfoArrayDeclaration *d)
+  void visit (TypeInfoArrayDeclaration *d) final override
   {
     TypeDArray *ti = d->tinfo->isTypeDArray ();
 
@@ -702,7 +702,7 @@  public:
 	TypeInfo value;
 	size_t len;  */
 
-  void visit (TypeInfoStaticArrayDeclaration *d)
+  void visit (TypeInfoStaticArrayDeclaration *d) final override
   {
     TypeSArray *ti = d->tinfo->isTypeSArray ();
 
@@ -722,7 +722,7 @@  public:
 	TypeInfo value;
 	TypeInfo key;  */
 
-  void visit (TypeInfoAssociativeArrayDeclaration *d)
+  void visit (TypeInfoAssociativeArrayDeclaration *d) final override
   {
     TypeAArray *ti = d->tinfo->isTypeAArray ();
 
@@ -741,7 +741,7 @@  public:
 	void *__monitor;
 	TypeInfo base;  */
 
-  void visit (TypeInfoVectorDeclaration *d)
+  void visit (TypeInfoVectorDeclaration *d) final override
   {
     TypeVector *ti = d->tinfo->isTypeVector ();
 
@@ -758,7 +758,7 @@  public:
 	TypeInfo next;
 	string deco;  */
 
-  void visit (TypeInfoFunctionDeclaration *d)
+  void visit (TypeInfoFunctionDeclaration *d) final override
   {
     TypeFunction *ti = d->tinfo->isTypeFunction ();
     gcc_assert (ti->deco != NULL);
@@ -779,7 +779,7 @@  public:
 	TypeInfo next;
 	string deco;  */
 
-  void visit (TypeInfoDelegateDeclaration *d)
+  void visit (TypeInfoDelegateDeclaration *d) final override
   {
     TypeDelegate *ti = d->tinfo->isTypeDelegate ();
     gcc_assert (ti->deco != NULL);
@@ -813,7 +813,7 @@  public:
      Information relating to interfaces, and their vtables are laid out
      immediately after the named fields, if there is anything to write.  */
 
-  void visit (TypeInfoClassDeclaration *d)
+  void visit (TypeInfoClassDeclaration *d) final override
   {
     TypeClass *ti = d->tinfo->isTypeClass ();
     ClassDeclaration *cd = ti->sym;
@@ -1004,7 +1004,7 @@  public:
 	void *__monitor;
 	TypeInfo_Class info;  */
 
-  void visit (TypeInfoInterfaceDeclaration *d)
+  void visit (TypeInfoInterfaceDeclaration *d) final override
   {
     TypeClass *ti = d->tinfo->isTypeClass ();
 
@@ -1034,7 +1034,7 @@  public:
 	uint m_align;
 	immutable(void)* xgetRTInfo;  */
 
-  void visit (TypeInfoStructDeclaration *d)
+  void visit (TypeInfoStructDeclaration *d) final override
   {
     TypeStruct *ti = d->tinfo->isTypeStruct ();
     StructDeclaration *sd = ti->sym;
@@ -1119,7 +1119,7 @@  public:
 	void *__monitor;
 	TypeInfo[] elements;  */
 
-  void visit (TypeInfoTupleDeclaration *d)
+  void visit (TypeInfoTupleDeclaration *d) final override
   {
     TypeTuple *ti = d->tinfo->isTypeTuple ();
 
diff --git a/gcc/d/types.cc b/gcc/d/types.cc
index c54049dfb98..b17b15359c8 100644
--- a/gcc/d/types.cc
+++ b/gcc/d/types.cc
@@ -665,7 +665,7 @@  public:
 
   /* This should be overridden by each type class.  */
 
-  void visit (Type *)
+  void visit (Type *) final override
   {
     gcc_unreachable ();
   }
@@ -673,21 +673,21 @@  public:
   /* Type assigned to erroneous expressions or constructs that
      failed during the semantic stage.  */
 
-  void visit (TypeError *t)
+  void visit (TypeError *t) final override
   {
     t->ctype = error_mark_node;
   }
 
   /* Type assigned to generic nullable types.  */
 
-  void visit (TypeNull *t)
+  void visit (TypeNull *t) final override
   {
     t->ctype = ptr_type_node;
   }
 
   /* Bottom type used for functions that never return.  */
 
-  void visit (TypeNoreturn *t)
+  void visit (TypeNoreturn *t) final override
   {
     t->ctype = noreturn_type_node;
     TYPE_NAME (t->ctype) = get_identifier (t->toChars ());
@@ -695,7 +695,7 @@  public:
 
   /* Basic Data Types.  */
 
-  void visit (TypeBasic *t)
+  void visit (TypeBasic *t) final override
   {
     /* [type/basic-data-types]
 
@@ -761,7 +761,7 @@  public:
 
   /* Build a simple pointer to data type, analogous to C pointers.  */
 
-  void visit (TypePointer *t)
+  void visit (TypePointer *t) final override
   {
     t->ctype = build_pointer_type (build_ctype (t->next));
   }
@@ -769,7 +769,7 @@  public:
   /* Build a dynamic array type, consisting of a length and a pointer
      to the array data.  */
 
-  void visit (TypeDArray *t)
+  void visit (TypeDArray *t) final override
   {
     /* In [abi/arrays], dynamic array layout is:
 	.length	array dimension.
@@ -787,7 +787,7 @@  public:
   /* Build a static array type, distinguished from dynamic arrays by
      having a length fixed at compile-time, analogous to C arrays.  */
 
-  void visit (TypeSArray *t)
+  void visit (TypeSArray *t) final override
   {
     if (t->dim->isConst () && t->dim->type->isintegral ())
       {
@@ -804,7 +804,7 @@  public:
 
   /* Build a vector type, a fixed array of floating or integer types.  */
 
-  void visit (TypeVector *t)
+  void visit (TypeVector *t) final override
   {
     int nunits = t->basetype->isTypeSArray ()->dim->toUInteger ();
     tree inner = build_ctype (t->elementType ());
@@ -821,7 +821,7 @@  public:
   /* Build an associative array type, distinguished from arrays by having an
      index that's not necessarily an integer, and can be sparsely populated.  */
 
-  void visit (TypeAArray *t)
+  void visit (TypeAArray *t) final override
   {
     /* In [abi/associative-arrays], associative arrays are a struct that only
        consist of a pointer to an opaque, implementation defined type.  */
@@ -835,7 +835,7 @@  public:
   /* Build type for a function declaration, which consists of a return type,
      and a list of parameter types, and a linkage attribute.  */
 
-  void visit (TypeFunction *t)
+  void visit (TypeFunction *t) final override
   {
     tree fnparams = NULL_TREE;
     tree fntype;
@@ -925,7 +925,7 @@  public:
      reference and a pointer to a non-static member function, or a pointer
      to a closure and a pointer to a nested function.  */
 
-  void visit (TypeDelegate *t)
+  void visit (TypeDelegate *t) final override
   {
     /* In [abi/delegates], delegate layout is:
 	.ptr	    context pointer.
@@ -952,7 +952,7 @@  public:
   /* Build a named enum type, a distinct value whose values are restrict to
      a group of constants of the same underlying base type.  */
 
-  void visit (TypeEnum *t)
+  void visit (TypeEnum *t) final override
   {
     tree basetype = (t->sym->memtype)
       ? build_ctype (t->sym->memtype) : void_type_node;
@@ -1067,7 +1067,7 @@  public:
   /* Build a struct or union type.  Layout should be exactly represented
      as an equivalent C struct, except for non-POD or nested structs.  */
 
-  void visit (TypeStruct *t)
+  void visit (TypeStruct *t) final override
   {
     /* Merge types in the back-end if the front-end did not itself do so.  */
     tree deco = get_identifier (d_mangle_decl (t->sym));
@@ -1123,7 +1123,7 @@  public:
   /* Build a class type.  Whereas structs are value types, classes are
      reference types, with all the object-orientated features.  */
 
-  void visit (TypeClass *t)
+  void visit (TypeClass *t) final override
   {
     /* Merge types in the back-end if the front-end did not itself do so.  */
     tree deco = get_identifier (d_mangle_decl (t->sym));