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

[cling] Crash unloading a templated function containing a lambda expression #9850

Closed
michael-mpik opened this issue Feb 9, 2022 · 11 comments · Fixed by #10037
Closed

[cling] Crash unloading a templated function containing a lambda expression #9850

michael-mpik opened this issue Feb 9, 2022 · 11 comments · Fixed by #10037

Comments

@michael-mpik
Copy link

// cling problem with lambda functions inside of template functions
//
// A code fragment illustrating the problem is given below.
// Starting ROOT and running the macro once works, running it
// a second time produces a crash. Commenting the (not-even used)
// lambda function avoid the crash. The macro can be run as often as
// one likes.
//
// ROOT 6.20/02 on MacOSX 10.15.06
// root [1] .x crash.cc -> works
// root [2] .x crash.cc -> crash

template T square(T x) {
auto crash = [](double x) {return x;}; // comment this line to avoid the crash
return x*x;
}

void crash()
{
printf("%d\n",square(2));
}

@vepadulano
Copy link
Member

Cannot reproduce with a recent master build on Fedora 35

(base) vpadulan@fedora [~]: cat crash.cc
#include <stdio.h>

template <typename T> auto square(T x) {
auto crash = [](double x) {return x;};
return x*x;
}

void crash()
{
printf("%d\n",square(2));
}
(base) vpadulan@fedora [~]: root
   ------------------------------------------------------------------
  | Welcome to ROOT 6.27/01                        https://root.cern |
  | (c) 1995-2021, The ROOT Team; conception: R. Brun, F. Rademakers |
  | Built for linuxx8664gcc on Feb 06 2022, 22:51:00                 |
  | From heads/master@v6-25-02-409-g61e89ed823                       |
  | With c++ (GCC) 11.2.1 20211203 (Red Hat 11.2.1-7)                |
  | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q'       |
   ------------------------------------------------------------------

root [0] .x crash.cc
4
root [1] .x crash.cc
4
root [2] .x crash.cc
4
root [3] .x crash.cc
4

@michael-mpik
Copy link
Author

michael-mpik commented Feb 10, 2022 via email

@vepadulano
Copy link
Member

Works on lxplus with latest ROOT release 6.24.06 (6.26 is due soon)

[vpadulan@lxplus772 ~]$source /cvmfs/sft.cern.ch/lcg/views/LCG_101/x86_64-centos7-gcc11-opt/setup.sh
[vpadulan@lxplus772 ~]$root --version
ROOT Version: 6.24/06
Built for linuxx8664gcc on Sep 02 2021, 14:20:23
From tags/v6-24-06@v6-24-06
[vpadulan@lxplus772 ~]$cat crash.cc
#include <stdio.h>

template <typename T> auto square(T x) {
auto crash = [](double x) {return x;};
return x*x;
}

void crash()
{
printf("%d\n",square(2));
}
[vpadulan@lxplus772 ~]$root
   ------------------------------------------------------------------
  | Welcome to ROOT 6.24/06                        https://root.cern |
  | (c) 1995-2021, The ROOT Team; conception: R. Brun, F. Rademakers |
  | Built for linuxx8664gcc on Sep 02 2021, 14:20:23                 |
  | From tags/v6-24-06@v6-24-06                                      |
  | With g++ (GCC) 11.1.0                                            |
  | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q'       |
   ------------------------------------------------------------------

root [0] .x crash.cc
4
root [1] .x crash.cc
4
root [2] .x crash.cc
4
root [3] .x crash.cc
4
root [4] .x crash.cc
4

@michael-mpik
Copy link
Author

michael-mpik commented Feb 10, 2022 via email

@vepadulano
Copy link
Member

Four our reference, found the issue in ROOT 6.22.06 on lxplus with a debug build

[vpadulan@lxplus772 ~]$source /cvmfs/sft.cern.ch/lcg/views/LCG_99/x86_64-centos7-gcc10-dbg/setup.sh
[vpadulan@lxplus772 ~]$root --version
ROOT Version: 6.22/06
Built for linuxx8664gcc on Nov 27 2020, 15:14:08
From tags/v6-22-06@v6-22-06
[vpadulan@lxplus772 ~]$cat crash.cc
#include <stdio.h>

template <typename T> auto square(T x) {
auto crash = [](double x) {return x;};
return x*x;
}

void crash()
{
printf("%d\n",square(2));
}
[vpadulan@lxplus772 ~]$root
   ------------------------------------------------------------------
  | Welcome to ROOT 6.22/06                        https://root.cern |
  | (c) 1995-2020, The ROOT Team; conception: R. Brun, F. Rademakers |
  | Built for linuxx8664gcc on Nov 27 2020, 15:14:08                 |
  | From tags/v6-22-06@v6-22-06                                      |
  | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q'       |
   ------------------------------------------------------------------

root [0] .x crash.cc
4
root [1] .x crash.cc
root.exe: /build/jenkins/workspace/lcg_release_pipeline/build/projects/ROOT-v6.22.06/src/ROOT/v6.22.06/interpreter/llvm/src/tools/clang/lib/AST/DeclCXX.cpp:1106: clang::CXXMethodDecl* clang::CXXRecordDecl::getLambdaCallOperator() const: Assertion `!Calls.empty() && "Missing lambda call operator!"' failed.

We are probably missing some backport, to be decided if it is needed.
@michael-mpik if possible please upgrade to the latest ROOT version and let us know if the problem persists. Thanks again for your report 😄

@michael-mpik
Copy link
Author

michael-mpik commented Feb 10, 2022 via email

@vepadulano
Copy link
Member

I tried on one of our CI nodes with MacOS 10.15 at the tip of the 6.24 branch and still the problem is not shown.

macitois19:6-24 sftnight$ root
   ------------------------------------------------------------------
  | Welcome to ROOT 6.24/07                        https://root.cern |
  | (c) 1995-2021, The ROOT Team; conception: R. Brun, F. Rademakers |
  | Built for macosx64 on Feb 09 2022, 23:19:43                      |
  | From remotes/origin/v6-24-00-patches@v6-24-06-41-gad88a28875     |
  | With Apple clang version 12.0.0 (clang-1200.0.32.28)             |
  | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q'       |
   ------------------------------------------------------------------

root [0] .x crash.cc
4
root [1] .x crash.cc
4
root [2] .x crash.cc
4
root [3] .x crash.cc
4

In your example above, From ***@***.*** looks quite weird to me. To better understand the differences, it would be helpful to know how you installed ROOT.

@michael-mpik
Copy link
Author

michael-mpik commented Feb 11, 2022 via email

@michael-mpik
Copy link
Author

michael-mpik commented Feb 11, 2022 via email

@jalopezg-git jalopezg-git changed the title cling problem with lambda functions inside of template functions [cling] Crash unloading a templated function containing a lambda expression Mar 2, 2022
@jalopezg-git
Copy link
Contributor

Thanks for reporting @michael-mpik. I have reproduced the problem and a PR is on its way.

@jalopezg-git
Copy link
Contributor

jalopezg-git commented Mar 2, 2022

TLDR; for reference, the issue is described below.

Implicit instantiation of a function template calls DeclCollector::HandleCXXImplicitFunctionInstantiation(), which appends the FunctionDecl to the transaction. According to the docs, the body of the function has not yet been instantiated. HandleTopLevelDecl() will be called again for this decl at the end of the TU, which will append it again to the transaction -same Decl *, different DCI.

This is by design. However, unloading of decls in the transaction should not process the same Decl * twice. In the reported case, traversing the AST for a second time triggers an assertion failure in clang::CXXRecordDecl::getLambdaCallOperator(), as part of the members of the underlying CXXRecordDecl (of a lambda) are not there anymore.

jalopezg-git added a commit to jalopezg-git/root that referenced this issue Mar 3, 2022
…ssed only once

Implicit instantiation of a function template calls
`DeclCollector::HandleCXXImplicitFunctionInstantiation()`, which appends the
FunctionDecl to the transaction.  According to clang documentation, the body of
the function has not yet been instantiated. `HandleTopLevelDecl()` will be
called again for this decl at the end of the TU, which will append it
again to the transaction - same `Decl *`, different ConsumerCallInfo.

This is by design. However, unloading of decls in the transaction should
not process the same `Decl *` twice. In particular, entries with ConsumerCallInfo
== `kCCIHandleCXXImplicitFunctionInstantiation` will omitted.

Fixes issue root-project#9850.
jalopezg-git added a commit to jalopezg-git/root that referenced this issue Mar 3, 2022
…ssed only once

Implicit instantiation of a function template calls
`DeclCollector::HandleCXXImplicitFunctionInstantiation()`, which appends the
FunctionDecl to the transaction.  According to clang documentation, the body of
the function has not yet been instantiated. `HandleTopLevelDecl()` will be
called again for this decl at the end of the TU, which will append it
again to the transaction - same `Decl *`, different ConsumerCallInfo.

This is by design. However, unloading of decls in the transaction should
not process the same `Decl *` twice. In particular, entries with ConsumerCallInfo
== `kCCIHandleCXXImplicitFunctionInstantiation` will omitted.

Fixes issue root-project#9850.
jalopezg-git added a commit to jalopezg-git/root that referenced this issue Mar 3, 2022
…ssed only once

Implicit instantiation of a function template calls
`DeclCollector::HandleCXXImplicitFunctionInstantiation()`, which appends the
FunctionDecl to the transaction.  According to clang documentation, the body of
the function has not yet been instantiated. `HandleTopLevelDecl()` will be
called again for this decl at the end of the TU, which will append it
again to the transaction - same `Decl *`, different ConsumerCallInfo.

This is by design. However, unloading of decls in the transaction should
not process the same `Decl *` twice. In particular, entries with ConsumerCallInfo
== `kCCIHandleCXXImplicitFunctionInstantiation` will omitted.

Fixes issue root-project#9850.
jalopezg-git added a commit that referenced this issue Mar 3, 2022
…ssed only once

Implicit instantiation of a function template calls
`DeclCollector::HandleCXXImplicitFunctionInstantiation()`, which appends the
FunctionDecl to the transaction.  According to clang documentation, the body of
the function has not yet been instantiated. `HandleTopLevelDecl()` will be
called again for this decl at the end of the TU, which will append it
again to the transaction - same `Decl *`, different ConsumerCallInfo.

This is by design. However, unloading of decls in the transaction should
not process the same `Decl *` twice. In particular, entries with ConsumerCallInfo
== `kCCIHandleCXXImplicitFunctionInstantiation` will omitted.

Fixes issue #9850.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants