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

Cloning call to method via clad::utils::StmtClone::VisitCXXMemberCallExpr causes segmentation fault #49

Closed
efremale opened this issue Jul 6, 2018 · 9 comments · Fixed by #719
Assignees
Milestone

Comments

@efremale
Copy link
Contributor

efremale commented Jul 6, 2018

Can be reproduced by

struct S{
  int f0() { return 0; }
  int f1(int x) { return f0() + x; }
};
...
clad::differentiate(&S::f1, 0);
@AdityaSanthosh
Copy link

AdityaSanthosh commented Feb 9, 2020

I successfully reproduced the issue. It caused me segmentation fault(core dumped). Any idea how to approach solving this problem. Also i am new to this Repository.(And a gsoc guide recommended to fix this as a good first issue)
Also The definition of the function differentiate mentions not to pass any zero argument.
segfault

@blide
Copy link
Contributor

blide commented Mar 23, 2020

It no longer causes segfault on master, now just a warning
issue49.cpp:5:26: warning: function 'f0' was not differentiated because clad failed to differentiate it and no overload was found in namespace 'custom_derivatives' because f0 has no arguments. Clad replaces it with zero, so everything's ok for a constant

But segfault is reproducible with such revisions

clang: ae610a215a867aadf97fc8cf9a61f9ffe4901476
llvm: release_50
clad: 11777b8
output
➜  demos git:(2b6298e) ✗ /home/blide/gsoc/inst/bin/clang-5.0 -Xclang -add-plugin -Xclang clad -Xclang -load -Xclang /home/blide/gsoc/inst/lib/clad.so -I../include/ -x c++ -std=c++11 issue49.cpp
#0 0x000055d55b884ad7 llvm::sys::PrintStackTrace(llvm::raw_ostream&) /home/blide/gsoc/src/lib/Support/Unix/Signals.inc:398:22
#1 0x000055d55b884b6a PrintStackTraceSignalHandler(void*) /home/blide/gsoc/src/lib/Support/Unix/Signals.inc:462:1
#2 0x000055d55b882d97 llvm::sys::RunSignalHandlers() /home/blide/gsoc/src/lib/Support/Signals.cpp:49:19
#3 0x000055d55b884345 SignalHandler(int) /home/blide/gsoc/src/lib/Support/Unix/Signals.inc:252:1
#4 0x00007f5411643f40 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x13f40)
#5 0x000055d55bb94286 clang::Expr::isTypeDependent() const /home/blide/gsoc/src/tools/clang/include/clang/AST/Expr.h:166:50
#6 0x000055d55ea42ac2 clang::CallExpr::updateDependenciesFromArg(clang::Expr*) /home/blide/gsoc/src/tools/clang/lib/AST/Expr.cpp:1206:3
#7 0x000055d55ea427e2 clang::CallExpr::CallExpr(clang::ASTContext const&, clang::Stmt::StmtClass, clang::Expr*, llvm::ArrayRef<clang::Expr*>, llvm::ArrayRef<clang::Expr*>, clang::QualType, clang::ExprValueKind, clang::SourceLocation) /home/blide/gsoc/src/tools/clang/lib/AST/Expr.cpp:1177:50
#8 0x000055d55ea428d9 clang::CallExpr::CallExpr(clang::ASTContext const&, clang::Stmt::StmtClass, clang::Expr*, llvm::ArrayRef<clang::Expr*>, clang::QualType, clang::ExprValueKind, clang::SourceLocation) /home/blide/gsoc/src/tools/clang/lib/AST/Expr.cpp:1187:69
#9 0x00007f5410fc8aa8 clang::CXXMemberCallExpr::CXXMemberCallExpr(clang::ASTContext&, clang::Expr*, llvm::ArrayRef<clang::Expr*>, clang::QualType, clang::ExprValueKind, clang::SourceLocation) /home/blide/gsoc/src/tools/clad/../clang/include/clang/AST/ExprCXX.h:140:62
#10 0x00007f5410fc4634 clad::utils::StmtClone::VisitCXXMemberCallExpr(clang::CXXMemberCallExpr*) /home/blide/gsoc/src/tools/clad/lib/Differentiator/StmtClone.cpp:205:77
#11 0x00007f5410ef16a0 clang::StmtVisitorBase<clang::make_ptr, clad::utils::StmtClone, clang::Stmt*>::Visit(clang::Stmt*) /home/blide/gsoc/obj/tools/clad/../clang/include/clang/AST/StmtNodes.inc:339:1
#12 0x00007f5410fc9922 clang::Expr* clad::utils::StmtClone::Clone<clang::Expr>(clang::Expr const*) /home/blide/gsoc/src/tools/clad/include/clad/Differentiator/StmtClone.h:130:18
#13 0x00007f5410fc0fd0 clad::utils::StmtClone::VisitBinaryOperator(clang::BinaryOperator*) /home/blide/gsoc/src/tools/clad/lib/Differentiator/StmtClone.cpp:44:1
#14 0x00007f5410efcebd clang::StmtVisitorBase<clang::make_ptr, clad::utils::StmtClone, clang::Stmt*>::VisitBinAdd(clang::BinaryOperator*) /home/blide/gsoc/src/tools/clad/../clang/include/clang/AST/StmtVisitor.h:125:3
#15 0x00007f5410ef0d7f clang::StmtVisitorBase<clang::make_ptr, clad::utils::StmtClone, clang::Stmt*>::Visit(clang::Stmt*) /home/blide/gsoc/src/tools/clad/../clang/include/clang/AST/StmtVisitor.h:52:26
#16 0x00007f5410ee38d3 clang::Stmt* clad::utils::StmtClone::Clone<clang::Stmt>(clang::Stmt const*) /home/blide/gsoc/src/tools/clad/include/clad/Differentiator/StmtClone.h:130:18
#17 0x00007f5410ec4210 clad::DerivativeBuilder::Clone(clang::Stmt const*) /home/blide/gsoc/src/tools/clad/lib/Differentiator/DerivativeBuilder.cpp:220:43
#18 0x00007f5410ec4374 clad::ForwardModeVisitor::Clone(clang::Stmt const*) /home/blide/gsoc/src/tools/clad/lib/Differentiator/DerivativeBuilder.cpp:238:42
#19 0x00007f5410ec4980 clad::ForwardModeVisitor::VisitReturnStmt(clang::ReturnStmt const*) /home/blide/gsoc/src/tools/clad/lib/Differentiator/DerivativeBuilder.cpp:288:58
#20 0x00007f5410ee379b clang::StmtVisitorBase<clang::make_const_ptr, clad::ForwardModeVisitor, clad::NodeContext>::Visit(clang::Stmt const*) /home/blide/gsoc/obj/tools/clad/../clang/include/clang/AST/StmtNodes.inc:1219:1
#21 0x00007f5410ec447e clad::ForwardModeVisitor::VisitCompoundStmt(clang::CompoundStmt const*) /home/blide/gsoc/src/tools/clad/lib/Differentiator/DerivativeBuilder.cpp:249:40
#22 0x00007f5410ee242d clang::StmtVisitorBase<clang::make_const_ptr, clad::ForwardModeVisitor, clad::NodeContext>::Visit(clang::Stmt const*) /home/blide/gsoc/obj/tools/clad/../clang/include/clang/AST/StmtNodes.inc:79:1
#23 0x00007f5410ec40a2 clad::ForwardModeVisitor::Derive(clad::FunctionDeclInfo&, clad::DiffPlan const&) /home/blide/gsoc/src/tools/clad/lib/Differentiator/DerivativeBuilder.cpp:203:77
#24 0x00007f5410ec351f clad::DerivativeBuilder::Derive(clad::FunctionDeclInfo&, clad::DiffPlan const&) /home/blide/gsoc/src/tools/clad/lib/Differentiator/DerivativeBuilder.cpp:73:24
#25 0x00007f5410ebe7d8 clad::plugin::CladPlugin::HandleTopLevelDecl(clang::DeclGroupRef) /home/blide/gsoc/src/tools/clad/tools/ClangPlugin.cpp:133:51
#26 0x000055d55c1b1466 clang::MultiplexConsumer::HandleTopLevelDecl(clang::DeclGroupRef) /home/blide/gsoc/src/tools/clang/lib/Frontend/MultiplexConsumer.cpp:284:25
#27 0x000055d55d432a4b clang::ParseAST(clang::Sema&, bool, bool) /home/blide/gsoc/src/tools/clang/lib/Parse/ParseAST.cpp:151:18
#28 0x000055d55c17e6ff clang::ASTFrontendAction::ExecuteAction() /home/blide/gsoc/src/tools/clang/lib/Frontend/FrontendAction.cpp:1003:11
#29 0x000055d55c67730e clang::CodeGenAction::ExecuteAction() /home/blide/gsoc/src/tools/clang/lib/CodeGen/CodeGenAction.cpp:993:1
#30 0x000055d55c17e142 clang::FrontendAction::Execute() /home/blide/gsoc/src/tools/clang/lib/Frontend/FrontendAction.cpp:906:38
#31 0x000055d55c11d898 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) /home/blide/gsoc/src/tools/clang/lib/Frontend/CompilerInstance.cpp:981:24
#32 0x000055d55c2c472c clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /home/blide/gsoc/src/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:251:38
#33 0x000055d55a63b9a9 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) /home/blide/gsoc/src/tools/clang/tools/driver/cc1_main.cpp:221:38
#34 0x000055d55a630ee2 ExecuteCC1Tool(llvm::ArrayRef<char const*>, llvm::StringRef) /home/blide/gsoc/src/tools/clang/tools/driver/driver.cpp:306:64
#35 0x000055d55a631a78 main /home/blide/gsoc/src/tools/clang/tools/driver/driver.cpp:387:26
#36 0x00007f54110cfb6b __libc_start_main /build/glibc-KRRWSm/glibc-2.29/csu/../csu/libc-start.c:308:16
#37 0x000055d55a62e61a _start (/home/blide/gsoc/inst/bin/clang-5.0+0x163e61a)
Stack dump:
0.	Program arguments: /home/blide/gsoc/inst/bin/clang-5.0 -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all -disable-free -main-file-name issue49.cpp -mrelocation-model static -mthread-model posix -mdisable-fp-elim -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -resource-dir /home/blide/gsoc/inst/lib/clang/5.0.2 -I ../include/ -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/x86_64-linux-gnu/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/x86_64-linux-gnu/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/backward -internal-isystem /usr/local/include -internal-isystem /home/blide/gsoc/inst/lib/clang/5.0.2/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /home/blide/gsoc/src/tools/clad/demos -ferror-limit 19 -fmessage-length 118 -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -add-plugin clad -load /home/blide/gsoc/inst/lib/clad.so -o /tmp/issue49-e7aad9.o -x c++ issue49.cpp 
1.	<eof> parser at end of file
clang-5.0: error: unable to execute command: Segmentation fault (core dumped)
clang-5.0: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 5.0.2 (https://github.com/llvm-mirror/clang.git ae610a215a867aadf97fc8cf9a61f9ffe4901476) (https://github.com/llvm-mirror/llvm.git da4a2839d80ac52958be0129b871beedfe90136e)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/blide/gsoc/inst/bin
clang-5.0: note: diagnostic msg: PLEASE submit a bug report to http://llvm.org/bugs/ and include the crash backtrace, preprocessed source, and associated run script.
clang-5.0: note: diagnostic msg: 
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang-5.0: note: diagnostic msg: /tmp/issue49-f9238a.cpp
clang-5.0: note: diagnostic msg: /tmp/issue49-f9238a.sh
clang-5.0: note: diagnostic msg: 

********************

@vgvassilev
Copy link
Owner

@Nirhar, can you look into this issue, too?

@Nirhar
Copy link
Contributor

Nirhar commented May 25, 2022

@vgvassilev Can you give me some resources to understand the usecase of this class utils::StmtClone. I understand that it is used to make a copy of a certain portion of ths AST, but under what scenarios is this class used? I see that an object of the StmtClone class, m_NodeCloner, is used in the following code snippet:

void VisitorBase::updateReferencesOf(Stmt* InSubtree) {
utils::ReferencesUpdater up(m_Sema, m_Builder.m_NodeCloner.get(),
getCurrentScope(), m_Function);
up.TraverseStmt(InSubtree);
}

and then in

Stmt* VisitorBase::Clone(const Stmt* S) {
Stmt* clonedStmt = m_Builder.m_NodeCloner->Clone(S);
updateReferencesOf(clonedStmt);
return clonedStmt;
}

but I didnt quite understand the concept of ReferenceUpdater and why we are cloning portions of the code. Can you help me with this?

@parth-07
Copy link
Collaborator

@Nirhar

Can you give me some resources to understand the usecase of this class utils::StmtClone. I understand that it is used to make a copy of a certain portion of ths AST, but under what scenarios is this class used?

It will be difficult to find resources for this. A good place to start would be understanding how the Reverse Mode AD mechanism works and trying to produce hand-written derivatives of simple functions by using the Reverse Mode AD. StmtClone class, as you mentioned, clones a certain part of AST. VisitorBase::updateReferencesOf is more interesting. updateReferencesOf is required because cloned AST cannot be used as it is in the derived functions. Certain nodes refers other nodes. Clones of nodes of the original function will refer nodes of the original function as well, they need to updated to refer the corresponding nodes of the derived function. (clang doxygen docs)[https://clang.llvm.org/doxygen/index.html] will come handly while trying to understand the codebase.

@Nirhar
Copy link
Contributor

Nirhar commented Jun 7, 2022

running this code below:

//Code snippet 1
class S{
public:
  int f1(int x) { return x; }
};
...
clad::differentiate(&S::f1, 0);

throws Assertion `m_Functor && "No default object set, explicitly pass an object to " error. The same is thrown when the code mentioned in the first comment in this issue is executed.

But however, if the function is made static, then this error is not thrown:

//Code snippet 2
class S{
public:
  static int f1(int x) { return x; }
};
...
clad::differentiate(S::f1, 0);

Code snippet 2 runs smoothly

The derivative generated by code snippet 1 is

int f1_darg0(int x) {
    int _d_x = 1;
    S _d_this_obj;
    S *_d_this = &_d_this_obj;
    return _d_x;
}

and the derivative generated by code snippet 2 is:

static int f1_darg0(int x) {
    int _d_x = 1;
    return _d_x;
}

I think both the generated derivatives are correct

I think the issue lies in how the CladFunction execute function handles the code and how these derivatives are supposed to be linked to the cladfunction object. Especially the m_Functor object is null, which is the reason why the assertion fails. As far as I understand the m_Functor object will not be null only if I use a class overloads its "()" operator. Therefore logically m_functor should be null. So i guess the wrong template is being instantiated for the execute statement. @vgvassilev @parth-07 can you correct me if I am wrong?

@parth-07
Copy link
Collaborator

parth-07 commented Jun 7, 2022

I am not getting any error on running the code snippet 1, can you please paste the complete code that is giving you the error?

@Nirhar
Copy link
Contributor

Nirhar commented Jun 7, 2022

The code:

//Complete version of code snippet 2 from the previous comment
#include "clad/Differentiator/Differentiator.h"
#include <iostream>

class S{
public:
  static int f1(int x) { return x; }
};

int main() {
  auto f_dx = clad::differentiate(S::f1, 0);
  double x=3;
  std::cout << f_dx.execute(x) << std::endl;
  f_dx.dump();
}

works properly with the output:

1
The code is: 
static int f1_darg0(int x) {
    int _d_x = 1;
    return _d_x;
}

While the below code:

//Complete version of code snippet 1 from the previous comment
#include "clad/Differentiator/Differentiator.h"
#include <iostream>

class S{
public:
  int f1(int x) { return x; }
};

int main() {
  auto f_dx = clad::differentiate(&S::f1, 0);
  double x=3;
  std::cout << f_dx.execute(x) << std::endl;
  f_dx.dump();
}

compiles successfully but during runtime throws the below error:

 ./inst/include/clad/Differentiator/Differentiator.h:277: return_type_t<clad::CladFunction::CladFunctionType> clad::CladFunction<int (S::*)(int), S, false>::execute_helper(ReturnType C::*, Args &&...) [F = int (S::*)(int), FunctorT = S, EnablePadding = false, ReturnType = int (int), C = S, Args = <double &>]: Assertion `m_Functor && "No default object set, explicitly pass an object to " "CladFunction::execute"' failed.

If I dump the derivative generated during compilation of code snippet 1 to a file, the following derivative is generated:

int f1_darg0(int x) {
    int _d_x = 1;
    S _d_this_obj;
    S *_d_this = &_d_this_obj;
    return _d_x;
}

@parth-07
Copy link
Collaborator

In the code snippet shown below, f1 is a member function, the derivative function of a member function is a member function as well. To call a member function, we need an object of the class, through which we can call the member function. This object should be passed as first argument to CladFunction::execute call.

//Complete version of code snippet 1 from the previous comment
#include "clad/Differentiator/Differentiator.h"
#include <iostream>

class S{
public:
  int f1(int x) { return x; }
};

int main() {
  auto f_dx = clad::differentiate(&S::f1, 0);
  double x=3;
  std::cout << f_dx.execute(x) << std::endl;
  f_dx.dump();
}

Therefore, f_dx.execute should be called as follows:

S s;
std::cout << f_dx.execute(s, x) << std::endl;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants