root icon indicating copy to clipboard operation
root copied to clipboard

[cling] ROOT crash with unnamed macro

Open ferdymercury opened this issue 1 year ago • 1 comments

Check duplicate issues.

  • [ ] Checked for duplicates

Description

A (cumbersome) macro file shown below gives an error in ROOT 6.30.06, but crashes with 6.33.01

6.30.06

Processing merged.C...
In file included from input_line_8:1:
/.../merged.C:4:1: error: expected unqualified-id
{

6.33.01

#9 0x00007eea14d80b1e in clang::Sema::PushCompoundScope(bool) [clone .cold] () from /home/user/build/build-root-Desktop-Debug/lib/libCling.so

Reproducer

root -l merged.C

#if defined(FUNCTION_INTERFACE)
void merged()
#endif
{
    int a=0;
}

ROOT version

6.30 vs 6.33.01

Installation method

Binary

Operating system

Ubuntu 22

Additional context

https://root-forum.cern.ch/t/how-to-unify-named-and-anonymous-scripts/59694/3

ferdymercury avatar Jun 20 '24 07:06 ferdymercury

Another example:

int a = 0;
a = a+5;
//for (int i=0; i<10; i++) { a = a+10;}

void merged()
{
    cout << a << endl;
}

If I uncomment the for loop, cling crashes.

ferdymercury avatar Jun 21 '24 07:06 ferdymercury

I can see that also with LLVM18

Assertion failed: (VD.isLocalVarDecl() && "Should not see file-scope variables inside a function!"), function EmitDecl, file CGDecl.cpp, line 161.

@devajithvs ?

dpiparo avatar Oct 28 '24 12:10 dpiparo

It doesn't crash anymore with ROOT master for me. And what Danilo is citing is a failed assertion, not a crash.

@ferdymercury, can you still reproduce the issue?

guitargeek avatar Nov 14 '24 16:11 guitargeek

Yep, I can still reproduce the issue, in the sense that:

  • Before (6.30), it gave a useful error message: /.../merged.C:4:1: error: expected unqualified-id
  • Now, it leads to an assertion that 'crashes' your running ROOT session and gives no warning on what line the error is coming from.
   ------------------------------------------------------------------
  | Welcome to ROOT 6.35.001                       https://root.cern |
  | (c) 1995-2024, The ROOT Team; conception: R. Brun, F. Rademakers |
  | Built for linuxx8664gcc on Nov 14 2024, 16:23:56                 |
  | From heads/master@v6-31-01-3947-g990c31e1b3                      |
  | With g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0                   |
  | Try '.help'/'.?', '.demo', '.license', '.credits', '.quit'/'.q'  |
   ------------------------------------------------------------------

root [0] 
Processing /tmp/merged.C...
root.exe: /opt/root_src/interpreter/llvm-project/clang/lib/CodeGen/CGDecl.cpp:160: void clang::CodeGen::CodeGenFunction::EmitDecl(const clang::Decl&): Assertion `VD.isLocalVarDecl() && "Should not see file-scope variables inside a function!"' failed.

                                                                                                                                                                      
                                                                                                                                                                      
1  __pthread_kill_implementation                                                                                                 pthread_kill.c   44   0x7b163cc969fc 
2  __pthread_kill_internal                                                                                                       pthread_kill.c   78   0x7b163cc969fc 
3  __GI___pthread_kill                                                                                                           pthread_kill.c   89   0x7b163cc969fc 
4  __GI_raise                                                                                                                    raise.c          26   0x7b163cc42476 
5  __GI_abort                                                                                                                    abort.c          79   0x7b163cc287f3 
6  __assert_fail_base                                                                                                            assert.c         92   0x7b163cc2871b 
7  __GI___assert_fail                                                                                                            assert.c         101  0x7b163cc39e96 
8  clang::CodeGen::CodeGenFunction::EmitDecl(clang::Decl const&)                                                                                       0x7b16355e8595 
9  clang::CodeGen::CodeGenFunction::EmitDeclStmt(clang::DeclStmt const&)                                                                               0x7b16352009b7 
10 clang::CodeGen::CodeGenFunction::EmitSimpleStmt(clang::Stmt const *, llvm::ArrayRef<clang::Attr const *>)                                           0x7b1635215d35 
11 clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const *, llvm::ArrayRef<clang::Attr const *>)                                                 0x7b163520e3c5 
12 clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot)                       0x7b163520f8b4 
13 clang::CodeGen::CodeGenFunction::EmitCompoundStmt(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot)                                   0x7b163520fcdc 
14 clang::CodeGen::CodeGenFunction::EmitSimpleStmt(clang::Stmt const *, llvm::ArrayRef<clang::Attr const *>)                                           0x7b1635215d8a 
15 clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const *, llvm::ArrayRef<clang::Attr const *>)                                                 0x7b163520e3c5 
16 clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl *) [clone .part.0]                                                                      0x7b16352ee03d 
17 clang::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef)                                                                                   0x7b163517bc09 
18 clang::MultiplexConsumer::HandleTopLevelDecl(clang::DeclGroupRef)                                                                                   0x7b1635898fe8 
19 cling::DeclCollector::HandleTopLevelDecl(clang::DeclGroupRef)                                                                                       0x7b1635019212 
20 cling::IncrementalParser::ParseOrWrapTopLevelDecl()                                                                                                 0x7b1634fd5333 
21 cling::IncrementalParser::ParseInternal(llvm::StringRef)                                                                                            0x7b1634fd5c60 
22 cling::IncrementalParser::Compile(llvm::StringRef, cling::CompilationOptions const&)                                                                0x7b1634fd6861 
23 cling::Interpreter::loadHeader(std::string const&, cling::Transaction * *)                                                                          0x7b1634f47fe0 
24 cling::MetaSema::actOnLCommand(llvm::StringRef, cling::Transaction * *)                                                                             0x7b1635034e0a 
25 cling::MetaSema::actOnxCommand(llvm::StringRef, llvm::StringRef, cling::Value *)                                                                    0x7b1635034f71 
26 cling::MetaParser::isXCommand(cling::MetaSema::ActionResult&, cling::Value *)                                                                       0x7b1635044f8d 
27 cling::MetaParser::isCommand(cling::MetaSema::ActionResult&, cling::Value *)                                                                        0x7b1635046c19 
28 cling::MetaProcessor::process(llvm::StringRef, cling::Interpreter::CompilationResult&, cling::Value *, bool)                                        0x7b163502d990 
29 HandleInterpreterException                                                                                                    TCling.cxx       2429 0x7b1634ce641e 
30 TCling::ProcessLine                                                                                                           TCling.cxx       2602 0x7b1634ce71e0 
31 TCling::ProcessLineSynch                                                                                                      TCling.cxx       3574 0x7b1634ceae6a 
32 TApplication::ExecuteFile                                                                                                     TApplication.cxx 1879 0x7b163d79e19b 
33 TApplication::ProcessFile                                                                                                     TApplication.cxx 1751 0x7b163d79d8b6 
34 TApplication::ProcessLine                                                                                                     TApplication.cxx 1718 0x7b163d79d646 
35 TRint::ProcessLineNr                                                                                                          TRint.cxx        820  0x7b163dd87f01 
36 TRint::Run                                                                                                                    TRint.cxx        461  0x7b163dd865b3 
37 main                                                                                                                          rmain.cxx        84   0x62090546c5e4 

ferdymercury avatar Nov 14 '24 16:11 ferdymercury

This seems a duplicate of https://its.cern.ch/jira/browse/ROOT-8025 so I'd suggesting closing one or the other.

#ifdef TEST_TEST_TEST
void myfunc()
#endif
{
cout << "Foo!" << endl;
}

or

#ifdef ClingWorkAroundUnnamedDetection
void runretobjTest()
#endif
{

ferdymercury avatar Nov 19 '24 08:11 ferdymercury

Another occurrence https://its.cern.ch/jira/browse/ROOT-5487:

We determine whether a .x'ed file is an unnamed macro. If it is, the following procedure is executed. Also, input from the prompt will go through this procedure.

we split input into statements using a custom lexer, and expose
(preprocess, parse, execute) cling to each of them one by one.

we find the next PP directive ('#...') in the input OR the end of
the script/input, preprocess the input in front of it, use a custom
lexer to split that input in front of the PP directive into statements,
and expose (parse, execute) cling to each of them one by one.

when we hit a preprocessor directive "as a statement" (i.e. right
after the end of a previous statement, but not inside a block):

#include, #define is passed to cling
#ifdef is evaluated (only top-level); we recurse on the expanded
block (likely a separate memory buffer) again splitting and evaluating
statements, continuing with the original buffer at the #endif

Cling might need (maybe functionally needed to not re-preprocess, maybe just a performance improvement) an interface that does not preprocess the input string.

The question is how it interacts with the usage of the CPP. For example

#ifdef UNAMED_MACRO
{
#else 
void myfunction()
{
#endif

or simpler

{
#ifdef SOMETHING
int var;
#else
float var;
#endif
}

or

{
#ifdef CODE_BROKEN_ON_THIS_PLATFORM
some thing that does not work on this platform
}
#else
alternativecode();
}
#endif

ferdymercury avatar Apr 15 '25 16:04 ferdymercury