[cling] ROOT crash with unnamed macro
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
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.
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 ?
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?
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
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
{
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