I have forgot to include the matcher I used for the test:
```
AST_MATCHER_P(CXXRecordDecl, hasMethodOrder, std::vector<StringRef>, Order) {
  size_t Index = 0;
  for (CXXMethodDecl *Method : Node.methods()) {
    if (!Method->isImplicit()) {
      if (Method->getName() != Order[Index])
        return false;
      ++Index;
    }
  }
  return Index == Order.size();
}
```

Gabor
On Fri, Aug 10, 2018 at 6:42 PM Gábor Márton <martongab...@gmail.com> wrote:
>
> Hi Lang, Alexey,
>
> I dug deeper into this and it seems like the issue happens only when a
> **minimal** import is used. LLDB uses the minimal import. CrossTU
> static analyzer uses the normal mode.
> In normal import mode, in `ImportDeclContext` we do import all the
> methods in the correct order. However, in minimal mode we early return
> before importing the methods.
> So by merging D44100 this particular problem will not be solved.
> Still, that patch sounds very reasonable and I support that we should
> reorder all imported Decls, not just fields.
>
> One trivial solution would be to change `ImporDeclContext` to behave
> the same way in both modes. This is somewhat similar to the "brute
> force" method you mentioned.
> I am not an LLDB expert, so I am not sure if this is acceptable, and
> really don't know how many LLDB tests would it break, but this seems
> the simplest solution (and preferred) to me.
>
> The other solution if you'd like to keep the minimal behavior is the
> index based solution (as you mentioned).
> You should compare the order of all the imported methods (and fields)
> to the order in the original class in the "From" context. And I
> believe you have to do that at the end of VisitFunctionDecl. It would
> not work if you did that check when the type become complete, since in
> minimal mode we never set the class to be incomplete.
>
> I have created a unit test case, which fails in minimal mode and
> succeeds in normal mode. You can change the mode in
> `ASTImporterTestBase::TU::lazyInitImporter`.
> If you provide a patch then could you please also add this test (or
> similar) for both normal and minimal mode?
> ```
> TEST_P(ASTImporterTestBase, OrderOfVirtualMethods) {
>   auto Code =
>       R"(
>       class Base {
>       public:
>         virtual void bar() {}
>         virtual void foo() {}
>       };
>
>       class Derived : public Base {
>       public:
>         void foo() override {}
>       };
>       )";
>   Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input0.cc");
>   auto *DerivedFoo = FirstDeclMatcher<FunctionDecl>().match(
>       FromTU, functionDecl(hasName("foo"),
>                            hasParent(cxxRecordDecl(hasName("Derived")))));
>   auto *BaseBar = FirstDeclMatcher<FunctionDecl>().match(
>       FromTU, functionDecl(hasName("bar"),
>                            hasParent(cxxRecordDecl(hasName("Base")))));
>
>   Import(DerivedFoo, Lang_CXX);
>   // Importing Base::bar explicitly is needed only in minimal mode,
>   // in normal mode we already imported all methods of Base.
>   Import(BaseBar, Lang_CXX);
>
>   Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
>   auto *ImportedBase = FirstDeclMatcher<CXXRecordDecl>().match(
>       ToTU, cxxRecordDecl(hasName("Base")));
>   MatchVerifier<Decl> Verifier;
>   EXPECT_TRUE(Verifier.match(ImportedBase,
>                              cxxRecordDecl(hasMethodOrder({"bar", "foo"}))));
> }
> ```
>
> Thanks,
> Gabor
> On Fri, Aug 10, 2018 at 3:47 PM Alexey Sidorin <alexey.v.sido...@ya.ru> wrote:
> >
> > (+ Gabor and Gabor)
> >
> > Hi Lang,
> >
> > We faced a very similar issue with record fields where import order can 
> > change the order of imported FieldDecls resulting in broken 
> > ASTRecordLayout. The patch for this issue is on review: 
> > https://reviews.llvm.org/D44100. It just reorders the fields after 
> > structure import is finished. CSA guys also reported the same problem with 
> > FriendDecls in the same review.The order of methods was not a problem for 
> > us but your report adds a new item to support. It looks like _all_ decls 
> > inside RecordDecl have to be reordered. I'll try to resurrect the patch 
> > this weekend (it is a bit outdated due to my workload, sorry) and add you 
> > as a reviewer so you can check if it solves the problem or not.
> >
> > 09.08.2018 20:46, Lang Hames via lldb-dev пишет:
> >
> > Hi clang-dev, lldb-dev,
> >
> > It looks like my clang commit r305850, which modified ASTImporter to import 
> > method override tables from an external context, introduced a new bug which 
> > manifests as incorrect vtable layouts for LLDB expression code.
> >
> > The bug itself is fairly straightforward. In r305850 I introduced the 
> > following method, which is called from ASTNodeImporter::VisitFunctionDecl:
> >
> > void ASTNodeImporter::ImportOverrides(CXXMethodDecl *ToMethod,
> >                                       CXXMethodDecl *FromMethod) {
> >   for (auto *FromOverriddenMethod : FromMethod->overridden_methods())
> >     ToMethod->addOverriddenMethod(
> >       cast<CXXMethodDecl>(Importer.Import(const_cast<CXXMethodDecl*>(
> >                                             FromOverriddenMethod))));
> > }
> >
> > This will produce the correct override table, but can also cause methods in 
> > the Base class to be visited in the wrong order. Consider:
> >
> > class Base {
> > public:
> >   virtual void bar() {}
> >   virtual void foo() {}
> > };
> >
> > class Derived : public Base {
> > public:
> >   void foo() override {}
> > };
> >
> > If Derived is imported into a new context before Base, then the importer 
> > will visit Derived::foo, and (via ImportOverrides) immediately import 
> > Base::foo, but this happens before Base::bar is imported. As a consequence, 
> > the decl order on the imported Base class will end up being [ foo, bar ], 
> > instead of [ bar, foo ]. In LLDB expression evaluation this manifests as an 
> > incorrect vtable layout for Base, with foo occupying the first slot.
> >
> > I am looking for suggestions on the right way to fix this. A brute force 
> > solution might be to always have ASTNodeImporter::VisitRecordDecl visit all 
> > base classes, then all virtual methods, which would ensure they are visited 
> > in the original decl order. However I do not know whether this covers all 
> > paths by which a CXXRecordDecl might be imported, nor whether the 
> > performance of this solution would be acceptable (it seems like it would 
> > preclude a lot of laziness).
> >
> > Alternatively we might be able to associate an index with each imported 
> > decl and sort on that when we complete the type, but that would leave 
> > imported decls in the wrong order until the type was complete, and since I 
> > do not know all the use cases for the importer I'm concerned people may 
> > rely on the decl order before type is complete.
> >
> > Any insight from ASTImporter experts would be greatly appreciated. :)
> >
> > Cheers,
> > Lang.
> >
> >
> > _______________________________________________
> > lldb-dev mailing list
> > lldb-dev@lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
> >
> >
_______________________________________________
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev

Reply via email to