d: add 'final' and 'override' to gcc/d/*.cc 'visit' impls
authorDavid Malcolm <dmalcolm@redhat.com>
Tue, 24 May 2022 13:07:22 +0000 (09:07 -0400)
committerDavid Malcolm <dmalcolm@redhat.com>
Tue, 24 May 2022 13:07:22 +0000 (09:07 -0400)
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
gcc/d/expr.cc
gcc/d/toir.cc
gcc/d/typeinfo.cc
gcc/d/types.cc

index f5c2107..5d85006 100644 (file)
@@ -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)
index 7f5e683..c259e7d 100644 (file)
@@ -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;
 
index d20c5c3..50d4415 100644 (file)
@@ -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;
index 668b7b3..a31762f 100644 (file)
@@ -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 ();
 
index c54049d..b17b153 100644 (file)
@@ -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));