Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bundling base class and derived class in same dictionary can lead to failure in recursive parsing. #13034

Open
1 task
pcanal opened this issue Jun 15, 2023 · 0 comments

Comments

@pcanal
Copy link
Member

pcanal commented Jun 15, 2023

Check duplicate issues.

  • Checked for duplicates

Describe the bug

Using the example provide in the original report : linker_example.zip
Doing:

make
root.exe -b -l -q macro.cc

leads to:


Loading A.sl

Processing macro.cc...
In file included from ADictUX dictionary payload:6:
./B.h:5:18: error: base class has incomplete type
class B : public A {
          ~~~~~~~^
./A.h:5:7: note: definition of 'A' is not complete until the closing '}'
class A {
      ^
In file included from ADictUX dictionary payload:6:
./B.h:7:15: error: type 'A' is not a direct or virtual base of 'B'
        B(int arg) : A(arg) {}
                     ^
Error in <TInterpreter::AutoParse>: Error parsing payload code for class A with content:

#line 1 "ADictUX dictionary payload"


#define _BACKWARD_BACKWARD_WARNING_H
// Inline headers
#include "A.h"
#include "B.h"

#undef  _BACKWARD_BACKWARD_WARNING_H

Error in <TInterpreter::AutoParse>: Error parsing payload code for class B with content:

#line 1 "ADictUX dictionary payload"


#define _BACKWARD_BACKWARD_WARNING_H
// Inline headers
#include "A.h"
#include "B.h"

#undef  _BACKWARD_BACKWARD_WARNING_H

What is the expected behaviour?

The correct output is:


Loading A.sl

Processing macro.cc...
init A with arg=0
test A
init A with arg=0
test A

How to reproduce?

unzip linker_example.zip
make
root.exe -b -q -q macro.cc

ROOT version

Any v6 version

How did you install ROOT?

any

Which operating system are you using?

linux

Additional context

The problem might have been introduced by commit 3081bf5. In particular applying this diff 'fixes' the problem:

diff --git a/core/dictgen/src/rootcling_impl.cxx b/core/dictgen/src/rootcling_impl.cxx
index f56ce23b7a..7cd24d2c63 100644
--- a/core/dictgen/src/rootcling_impl.cxx
+++ b/core/dictgen/src/rootcling_impl.cxx
@@ -4971,7 +4971,7 @@ int RootClingMain(int argc,
       if (!gOptCxxModule) {
          headersClassesMapString = GenerateStringFromHeadersForClasses(headersDeclsMap,
                                                                        detectedUmbrella,
-                                                                       true);
+                                                                       false);
          if (!gDriverConfig->fBuildingROOTStage1) {
             if (!gOptWriteEmptyRootPCM)
                fwdDeclsString = GenerateFwdDeclString(scan, interp);

This introduces the following diff in the generated dictionary:

rootsrv1:2023-dict pcanal$ diff -C2 dict.cxx dict.good.2.cxx 
*** dict.cxx    2023-06-15 15:55:39.818476668 -0500
--- dict.good.2.cxx     2023-06-15 14:54:48.505264642 -0500
***************
*** 187,192 ****
  )DICTPAYLOAD";
      static const char* classesHeaders[] = {
! "A", payloadCode, "@",
! "B", payloadCode, "@",
  nullptr
  };
--- 187,192 ----
  )DICTPAYLOAD";
      static const char* classesHeaders[] = {
! "A", "A.h", "@",
! "B", "B.h", "@",
  nullptr
  };

and indeed in practice the order of operation are as follow: (macro.cc contains a #include "A.h"):

  • Process the A.h and then start declaring class A:
  • While declaring A, process the constructor (of anything involving A itself in A declaration and call TCling::AutoParse
  • TCling::AutoParse recognizes A for the dictionary's classesHeaders
  • TCling::AutoParse proceeed to ask for the payloadCode to be processed/included (with the 'patch / fix / reversal' this is replaced by A.h), this payloadCode consist of:
#include "A.h"
#include "B.h"
  • Thanks to the code guard A.h is skipped (well anyway it is actually being processed by the outer code !!)
  • B.h is being included is reached:
class B : public A

which correctly complains that A is not yet fully declared ....

The commit log corresponding to the change is explicitly referring to this change:

   Associate to autoParse entries only the payload ([ROOT-6321](https://sft.its.cern.ch/jira/browse/ROOT-6321))
    
    de facto implementing lazy payload parsing instead of header
    parsing on demand.

It is not clear why TCling::AutoParse is called with a symbol that is "being" declared.

A work around (why we don't usually see this issue) is to generate a rootmap file (generating the c++ module should also in principle):

diff Makefile.orig Makefile
25c25
<               rootcint -f ${DICT} -c ${DICTHDRS}
---
>               rootcint -rml=A -f ${DICT} -c ${DICTHDRS}

Full stack trace at the starting point of the failing recursive parsing:

#0  TCling::AutoParse (this=0x4c1820, cls=0x7fffffff5670 "A") at /local2/pcanal/cint_working/rootcling/root/core/metacling/src/TCling.cxx:6449
#1  0x00007fffea9724aa in TCling__AutoParseCallback (className=0x7fffffff5670 "A") at /local2/pcanal/cint_working/rootcling/root/core/metacling/src/TCling.cxx:628
#2  0x00007fffeab15723 in TClingCallbacks::tryAutoParseInternal (this=0x953710, Name=..., R=..., S=0x6a4ee0, FE=0x0) at /local2/pcanal/cint_working/rootcling/root/core/metacling/src/TClingCallbacks.cxx:661
#3  0x00007fffeab14661 in TClingCallbacks::LookupObject (this=0x953710, R=..., S=0x6a4ee0) at /local2/pcanal/cint_working/rootcling/root/core/metacling/src/TClingCallbacks.cxx:392

#4  0x00007fffeac100fc in cling::MultiplexInterpreterCallbacks::LookupObject (this=0x4d2120, LR=..., S=0x6a4ee0) at /local2/pcanal/cint_working/rootcling/root/interpreter/cling/lib/Interpreter/MultiplexInterpreterCallbacks.h:62
#5  0x00007fffeac2259e in cling::InterpreterExternalSemaSource::LookupUnqualified (this=0x72d080, R=..., S=0x6a4ee0) at /local2/pcanal/cint_working/rootcling/root/interpreter/cling/lib/Interpreter/InterpreterCallbacks.cpp:269
#6  0x00007fffebc660b9 in clang::MultiplexExternalSemaSource::LookupUnqualified (this=0x72d0b0, R=..., S=0x6a4ee0)
    at /local2/pcanal/cint_working/rootcling/root/interpreter/llvm/src/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp:241
#7  0x00007fffec47ee6c in clang::Sema::LookupName (this=0x5250d0, R=..., S=0x6a4ee0, AllowBuiltinCreation=false) at /local2/pcanal/cint_working/rootcling/root/interpreter/llvm/src/tools/clang/lib/Sema/SemaLookup.cpp:2026
#8  0x00007fffebe7a672 in clang::Sema::HandleDeclarator (this=0x5250d0, S=0x6a4ee0, D=..., TemplateParamLists=...) at /local2/pcanal/cint_working/rootcling/root/interpreter/llvm/src/tools/clang/lib/Sema/SemaDecl.cpp:5895
#9  0x00007fffebf8e2c8 in clang::Sema::ActOnCXXMemberDeclarator (this=0x5250d0, S=0x6a4ee0, AS=clang::AS_public, D=..., TemplateParameterLists=..., BW=0x0, VS=..., InitStyle=clang::ICIS_NoInit)
    at /local2/pcanal/cint_working/rootcling/root/interpreter/llvm/src/tools/clang/lib/Sema/SemaDeclCXX.cpp:3430
#10 0x00007fffeba4151e in clang::Parser::ParseCXXInlineMethodDef (this=0x6a8f70, AS=clang::AS_public, AccessAttrs=..., D=..., TemplateInfo=..., VS=..., PureSpecLoc=...)
    at /local2/pcanal/cint_working/rootcling/root/interpreter/llvm/src/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp:42
#11 0x00007fffeb986810 in clang::Parser::ParseCXXClassMemberDeclaration (this=0x6a8f70, AS=clang::AS_public, AccessAttrs=..., TemplateInfo=..., TemplateDiags=0x0)
    at /local2/pcanal/cint_working/rootcling/root/interpreter/llvm/src/tools/clang/lib/Parse/ParseDeclCXX.cpp:2858
#12 0x00007fffeb9885f5 in clang::Parser::ParseCXXClassMemberDeclarationWithPragmas (this=0x6a8f70, AS=@0x7fffffff7ac8: clang::AS_public, AccessAttrs=..., TagType=clang::TST_class, TagDecl=0x1407fc0)
    at /local2/pcanal/cint_working/rootcling/root/interpreter/llvm/src/tools/clang/lib/Parse/ParseDeclCXX.cpp:3284
#13 0x00007fffeb989306 in clang::Parser::ParseCXXMemberSpecification (this=0x6a8f70, RecordLoc=..., AttrFixitLoc=..., Attrs=..., TagType=25, TagDecl=0x1407fc0)
    at /local2/pcanal/cint_working/rootcling/root/interpreter/llvm/src/tools/clang/lib/Parse/ParseDeclCXX.cpp:3488
#14 0x00007fffeb983667 in clang::Parser::ParseClassSpecifier (this=0x6a8f70, TagTokKind=clang::tok::kw_class, StartLoc=..., DS=..., TemplateInfo=..., AS=clang::AS_none, EnteringContext=true,
    DSC=clang::Parser::DeclSpecContext::DSC_top_level, Attributes=...) at /local2/pcanal/cint_working/rootcling/root/interpreter/llvm/src/tools/clang/lib/Parse/ParseDeclCXX.cpp:2030
#15 0x00007fffeb95e5c7 in clang::Parser::ParseDeclarationSpecifiers (this=0x6a8f70, DS=..., TemplateInfo=..., AS=clang::AS_none, DSContext=clang::Parser::DeclSpecContext::DSC_top_level, LateAttrs=0x0)
    at /local2/pcanal/cint_working/rootcling/root/interpreter/llvm/src/tools/clang/lib/Parse/ParseDecl.cpp:3988
#16 0x00007fffeba39e8c in clang::Parser::ParseDeclOrFunctionDefInternal (this=0x6a8f70, attrs=..., DS=..., AS=clang::AS_none) at /local2/pcanal/cint_working/rootcling/root/interpreter/llvm/src/tools/clang/lib/Parse/Parser.cpp:1054
#17 0x00007fffeba3a512 in clang::Parser::ParseDeclarationOrFunctionDefinition (this=0x6a8f70, attrs=..., DS=0x0, AS=clang::AS_none) at /local2/pcanal/cint_working/rootcling/root/interpreter/llvm/src/tools/clang/lib/Parse/Parser.cpp:1162
#18 0x00007fffeba39a20 in clang::Parser::ParseExternalDeclaration (this=0x6a8f70, attrs=..., DS=0x0) at /local2/pcanal/cint_working/rootcling/root/interpreter/llvm/src/tools/clang/lib/Parse/Parser.cpp:984
#19 0x00007fffeba38af9 in clang::Parser::ParseTopLevelDecl (this=0x6a8f70, Result=..., IsFirstDecl=false) at /local2/pcanal/cint_working/rootcling/root/interpreter/llvm/src/tools/clang/lib/Parse/Parser.cpp:729
#20 0x00007fffead8c986 in cling::IncrementalParser::ParseInternal (this=0x4c5c20, input=...) at /local2/pcanal/cint_working/rootcling/root/interpreter/cling/lib/Interpreter/IncrementalParser.cpp:930
#21 0x00007fffead8c401 in cling::IncrementalParser::Compile (this=0x4c5c20, input=..., Opts=...) at /local2/pcanal/cint_working/rootcling/root/interpreter/cling/lib/Interpreter/IncrementalParser.cpp:840
#22 0x00007fffeac0cb09 in cling::Interpreter::DeclareInternal (this=0x4c22e0, input=..., CO=..., T=0x7fffffffa030) at /local2/pcanal/cint_working/rootcling/root/interpreter/cling/lib/Interpreter/Interpreter.cpp:1357
#23 0x00007fffeac0d647 in cling::Interpreter::loadHeader (this=0x4c22e0, filename=..., T=0x7fffffffa030) at /local2/pcanal/cint_working/rootcling/root/interpreter/cling/lib/Interpreter/Interpreter.cpp:1495
#24 0x00007fffeac0dc30 in cling::Interpreter::loadFile (this=0x4c22e0, filename=..., allowSharedLib=true, T=0x7fffffffa030) at /local2/pcanal/cint_working/rootcling/root/interpreter/cling/lib/Interpreter/Interpreter.cpp:1589
#25 0x00007fffeaea2dc4 in cling::MetaSema::actOnLCommand (this=0x532780, file=..., transaction=0x7fffffffa030) at /local2/pcanal/cint_working/rootcling/root/interpreter/cling/lib/MetaProcessor/MetaSema.cpp:79
#26 0x00007fffeaea3377 in cling::MetaSema::actOnxCommand (this=0x532780, file=..., args=..., result=0x7fffffffa810) at /local2/pcanal/cint_working/rootcling/root/interpreter/cling/lib/MetaProcessor/MetaSema.cpp:146
#27 0x00007fffeaeb4ac7 in cling::MetaParser::isXCommand (this=0x7fffffffa350, actionResult=@0x7fffffffa34c: cling::MetaSema::AR_Success, resultValue=0x7fffffffa810)
    at /local2/pcanal/cint_working/rootcling/root/interpreter/cling/lib/MetaProcessor/MetaParser.cpp:315
#28 0x00007fffeaeb3b27 in cling::MetaParser::isCommand (this=0x7fffffffa350, actionResult=@0x7fffffffa34c: cling::MetaSema::AR_Success, resultValue=0x7fffffffa810)
    at /local2/pcanal/cint_working/rootcling/root/interpreter/cling/lib/MetaProcessor/MetaParser.cpp:119
#29 0x00007fffeaeb39af in cling::MetaParser::isMetaCommand (this=0x7fffffffa350, actionResult=@0x7fffffffa34c: cling::MetaSema::AR_Success, resultValue=0x7fffffffa810)
    at /local2/pcanal/cint_working/rootcling/root/interpreter/cling/lib/MetaProcessor/MetaParser.cpp:96
#30 0x00007fffeae9d2dc in cling::MetaProcessor::process (this=0x95c1b0, input_line=..., compRes=@0x7fffffffa80c: cling::Interpreter::kSuccess, result=0x7fffffffa810, disableValuePrinting=false)
    at /local2/pcanal/cint_working/rootcling/root/interpreter/cling/lib/MetaProcessor/MetaProcessor.cpp:317
#31 0x00007fffea97c5cd in HandleInterpreterException (metaProcessor=0x95c1b0, input_line=0xccf520 ".X  /local2/pcanal/root_working/test/2023-dict/./macro.cc", compRes=@0x7fffffffa80c: cling::Interpreter::kSuccess, result=0x7fffffffa810)
    at /local2/pcanal/cint_working/rootcling/root/core/metacling/src/TCling.cxx:2434
#32 0x00007fffea97cff6 in TCling::ProcessLine (this=0x4c1820, line=0x141f860 ".X  /local2/pcanal/root_working/test/2023-dict/./macro.cc", error=0x7fffffffd888)
    at /local2/pcanal/cint_working/rootcling/root/core/metacling/src/TCling.cxx:2578
#33 0x00007fffea9808ab in TCling::ProcessLineSynch (this=0x4c1820, line=0x141f860 ".X  /local2/pcanal/root_working/test/2023-dict/./macro.cc", error=0x7fffffffd888)
    at /local2/pcanal/cint_working/rootcling/root/core/metacling/src/TCling.cxx:3524
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment