Bug 95155 - d: wrong vtable offset in virtual function call
Summary: d: wrong vtable offset in virtual function call
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: d (show other bugs)
Version: 9.3.1
: P3 normal
Target Milestone: ---
Assignee: Iain Buclaw
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-05-15 21:08 UTC by Iain Buclaw
Modified: 2020-05-16 22:28 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work: 10.1.0
Known to fail: 9.3.1
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Iain Buclaw 2020-05-15 21:08:01 UTC
Seen when compiling self-hosted D compiler.

release/gcc-9 compiles:

isBaseOf (struct TypeClass * const this, struct Type * t, int * poffset)
{
  if (t != 0B && t->ty == 7)
    {
      {
        struct ClassDeclaration * cd;

        cd = ((struct TypeClass *) t)->sym;
        if (MEM[(bool (*<T1704>) (struct ClassDeclaration *, struct ClassDeclaration *, int *))this->sym->__vptr + 704B] (this->sym, cd, poffset))
          {
            return <retval> = 1;
          }
      }
    }
  return <retval> = 0;
}


release/gcc-10 compiles:

isBaseOf (struct TypeClass * const this, struct Type * t, int * poffset)
{
  if (t != 0B && t->ty == 7)
    {
      {
        struct ClassDeclaration * cd;

        cd = ((struct TypeClass *) t)->sym;
        if (MEM[(bool (*<T171b>) (struct ClassDeclaration *, struct ClassDeclaration *, int *))this->sym->__vptr + 736B] (this->sym, cd, poffset))
          {
            return <retval> = 1;
          }
      }
    }
  return <retval> = 0;
}


Applied all changes to gcc/d to the gcc-9 branch, and the problem gets resolved, so will have to comb through the diff to find out what missing change is causing gdc-9 to miscompile.
Comment 1 Iain Buclaw 2020-05-15 23:19:13 UTC
Looks like fix was in r10-7280, taken from the upstream backport in https://github.com/dlang/dmd/pull/10913
Comment 2 GCC Commits 2020-05-16 22:21:32 UTC
The releases/gcc-9 branch has been updated by Iain Buclaw <ibuclaw@gcc.gnu.org>:

https://gcc.gnu.org/g:7d505b0ed8565b8c120ddd2b0b4630c93eecdec5

commit r9-8599-g7d505b0ed8565b8c120ddd2b0b4630c93eecdec5
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sat May 16 23:33:15 2020 +0200

    d: Fix wrong vtable offset in virtual function call
    
    The Semantic (pass 1) analysis for classes is handled by
    ClassDeclaration::semantic.  For a given class, this method may be ran
    multiple times in order to resolve forward references.  The method
    incrementally tries to resolve the types referred to by the members of
    the class.
    
    The subsequent calls to this method are short-circuited if the class
    members have been fully analyzed.  For this the code tests that it is
    not the first/main call to the method (semanticRun == PASS.init else
    branch), scx is not set, and that the this->symtab is already set.  If
    all these conditions are met, the method returns.  But before returning,
    the method was setting this->semanticRun to PASSsemanticdone.  It should
    not set semanticRun since the class has not been fully analyzed yet.
    The base class analysis for this class could be pending and as a result
    vtable may not have been fully created.
    
    This fake setting of semanticRun results in the semantic analyzer to
    believe that the class has been fully analyzed.  As exposed by the
    issues in upstream, it may result in compile time errors when a derived
    type class is getting analyzed and because of this fake semanticdone on
    the base class, the semantic analysis construes that an overriden method
    is not defined in the base class.  PR95155 exposes anoter scenario where
    a buggy vtable may be created and a call to a class method may result in
    execution of some adhoc code.
    
    gcc/d/ChangeLog:
    
            PR d/95155
            * dmd/dclass.c (ClassDeclaration::semantic): Don't prematurely
            set done on semantic analysis.
    
    gcc/testsuite/ChangeLog:
    
            PR d/95155
            * gdc.test/compilable/imports/pr9471a.d: New test.
            * gdc.test/compilable/imports/pr9471b.d: New test.
            * gdc.test/compilable/imports/pr9471c.d: New test.
            * gdc.test/compilable/imports/pr9471d.d: New test.
            * gdc.test/compilable/pr9471.d: New test.
Comment 3 Iain Buclaw 2020-05-16 22:28:52 UTC
Fixed.