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

Clang crash instantiating lambda with a calling convention specified on it. #58366

Closed
alvinhochun opened this issue Oct 14, 2022 · 6 comments
Closed
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" crash Prefer [crash-on-valid] or [crash-on-invalid]

Comments

@alvinhochun
Copy link
Contributor

alvinhochun commented Oct 14, 2022

Stack dump:
0.      Program arguments: D:\\dev\\toolchain\\llvm-mingw\\llvm-mingw-20220906-ucrt-x86_64\\bin\\clang-15 --start-no-unused-arguments --driver-mode=g++ -target x86_64-w64-mingw32 -rtlib=compiler-rt -unwindlib=libunwind -stdlib=libc++ -fuse-ld=lld --end-no-unused-arguments -DCPPWINRT_VERSION_STRING=\"2.3.4.5\" -DNEEDS_UUIDOF_ICONTEXTCALLBACK_HACK -D_WIN32_WINNT=0x0602 -ID:/dev/mingw-winrt/cppwinrt/test -ID:/dev/mingw-winrt/cppwinrt/mingw-support -ID:/dev/mingw-winrt/cppwinrt/cppwinrt -ID:/dev/mingw-winrt/cppwinrt/build/x64/test/cppwinrt -g -std=gnu++20 -Winvalid-pch -Xclang -include-pch -Xclang D:/dev/mingw-winrt/cppwinrt/build/x64/test/CMakeFiles/cppwinrt-test.dir/cmake_pch.hxx.pch -Xclang -include -Xclang D:/dev/mingw-winrt/cppwinrt/build/x64/test/CMakeFiles/cppwinrt-test.dir/cmake_pch.hxx -MD -MT test/CMakeFiles/cppwinrt-test.dir/test/disconnected.cpp.obj -MF test\\CMakeFiles\\cppwinrt-test.dir\\test\\disconnected.cpp.obj.d -o test/CMakeFiles/cppwinrt-test.dir/test/disconnected.cpp.obj -c D:/dev/mingw-winrt/cppwinrt/test/test/disconnected.cpp
1.      <eof> parser at end of file
2.      D:/dev/mingw-winrt/cppwinrt/test/test/disconnected.cpp:192:10: instantiating function definition '(anonymous namespace)::InvokeInContext<(lambda at D:/dev/mingw-winrt/cppwinrt/test/test/disconnected.cpp:207:40)>'
Exception Code: 0xC0000005
 #0 0x00007ffa996e80ee llvm::DenseMap<std::__1::pair<clang::Decl*, unsigned int>, llvm::detail::DenseSetEmpty, llvm::DenseMapInfo<std::__1::pair<clang::Decl*, unsigned int>, void>, llvm::detail::DenseSetPair<std::__1::pair<clang::Decl*, unsigned int>>>::grow(unsigned int) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0xfc80ee)
 #1 0x00007ffa996de815 llvm::DenseMap<std::__1::pair<clang::Decl*, unsigned int>, llvm::detail::DenseSetEmpty, llvm::DenseMapInfo<std::__1::pair<clang::Decl*, unsigned int>, void>, llvm::detail::DenseSetPair<std::__1::pair<clang::Decl*, unsigned int>>>::grow(unsigned int) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0xfbe815)
 #2 0x00007ffa996d64a3 clang::Sema::SubstExprs(llvm::ArrayRef<clang::Expr*>, bool, clang::MultiLevelTemplateArgumentList const&, llvm::SmallVectorImpl<clang::Expr*>&) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0xfb64a3)
 #3 0x00007ffa996dc504 llvm::DenseMap<std::__1::pair<clang::Decl*, unsigned int>, llvm::detail::DenseSetEmpty, llvm::DenseMapInfo<std::__1::pair<clang::Decl*, unsigned int>, void>, llvm::detail::DenseSetPair<std::__1::pair<clang::Decl*, unsigned int>>>::grow(unsigned int) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0xfbc504)
 #4 0x00007ffa996d64a3 clang::Sema::SubstExprs(llvm::ArrayRef<clang::Expr*>, bool, clang::MultiLevelTemplateArgumentList const&, llvm::SmallVectorImpl<clang::Expr*>&) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0xfb64a3)
 #5 0x00007ffa996dc504 llvm::DenseMap<std::__1::pair<clang::Decl*, unsigned int>, llvm::detail::DenseSetEmpty, llvm::DenseMapInfo<std::__1::pair<clang::Decl*, unsigned int>, void>, llvm::detail::DenseSetPair<std::__1::pair<clang::Decl*, unsigned int>>>::grow(unsigned int) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0xfbc504)
 #6 0x00007ffa996d47c5 clang::Sema::SubstStmt(clang::Stmt*, clang::MultiLevelTemplateArgumentList const&) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0xfb47c5)
 #7 0x00007ffa996ed12d clang::PackExpansionExpr::PackExpansionExpr(clang::QualType, clang::Expr*, clang::SourceLocation, llvm::Optional<unsigned int>) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0xfcd12d)
 #8 0x00007ffa996d4762 clang::Sema::SubstStmt(clang::Stmt*, clang::MultiLevelTemplateArgumentList const&) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0xfb4762)
 #9 0x00007ffa99716e62 clang::Sema::InstantiateFunctionDefinition(clang::SourceLocation, clang::FunctionDecl*, bool, bool, bool) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0xff6e62)
#10 0x00007ffa9971910b clang::Sema::PerformPendingInstantiations(bool) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0xff910b)
#11 0x00007ffa98ff660b clang::Sema::ActOnEndOfTranslationUnitFragment(clang::Sema::TUFragmentKind) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0x8d660b) 
#12 0x00007ffa98ff74a3 clang::Sema::ActOnEndOfTranslationUnit() (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0x8d74a3)
#13 0x00007ffa9895fcb6 clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&, clang::Sema::ModuleImportState&) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0x23fcb6)
#14 0x00007ffa9887f08e clang::ParseAST(clang::Sema&, bool, bool) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0x15f08e)
#15 0x00007ffa9a4a3794 clang::FrontendAction::Execute() (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0x1d83794)
#16 0x00007ffa9a42e014 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0x1d0e014)
#17 0x00007ffa9a51de80 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0x1dfde80)
#18 0x00007ff6f4d36a71 (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\clang-15.exe+0x6a71)
#19 0x00007ff6f4d34b25 (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\clang-15.exe+0x4b25)
#20 0x00007ffa9a0c5ac6 llvm::SmallVectorTemplateBase<llvm::SmallString<128u>, false>::grow(unsigned long long) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0x19a5ac6)
#21 0x00007ffaaaa97be3 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libLLVM-15.dll+0x97be3)
#22 0x00007ffa9a0c56a9 clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>*, bool*) const (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0x19a56a9)
#23 0x00007ffa9a08f646 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0x196f646)
#24 0x00007ffa9a08f8ad clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::__1::pair<int, clang::driver::Command const*>>&, bool) const (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0x196f8ad)
#25 0x00007ffa9a0a8bcb clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::__1::pair<int, clang::driver::Command const*>>&) (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\libclang-cpp.dll+0x1988bcb)
#26 0x00007ff6f4d3441e (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\clang-15.exe+0x441e)
#27 0x00007ff6f4d313d6 (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\clang-15.exe+0x13d6)
#28 0x00007ff6f4d31426 (D:\dev\toolchain\llvm-mingw\llvm-mingw-20220906-ucrt-x86_64\bin\clang-15.exe+0x1426)
#29 0x00007ffb2eb47034 (C:\WINDOWS\System32\KERNEL32.DLL+0x17034)
#30 0x00007ffb2f602651 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x52651)
clang-15: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 15.0.0 (https://github.com/llvm/llvm-project.git 4ba6a9c9f65bbc8bd06e3652cb20fd4dfc846137)
Target: x86_64-w64-windows-gnu
Thread model: posix
InstalledDir: D:/dev/toolchain/llvm-mingw/llvm-mingw-20220906-ucrt-x86_64/bin
clang-15: note: diagnostic msg:
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang-15: note: diagnostic msg: C:/Users/Alvin/AppData/Local/Temp/disconnected-40302b.cpp
clang-15: note: diagnostic msg: C:/Users/Alvin/AppData/Local/Temp/disconnected-40302b.sh
clang-15: note: diagnostic msg:

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

Original code: disconnected-40302b.zip
Toolchain: https://github.com/mstorsjo/llvm-mingw/releases/tag/20220906

Reduced reproducer: https://godbolt.org/z/hM47hEbq8

using func_t = int (__attribute__((stdcall)) *)(void *);

void call(void *, func_t);

template<typename T>
void a(T &&lambda) {
    void *d = &lambda;
    call(d, [](void *x) __attribute__((stdcall)) -> int {
        auto &lambda = *reinterpret_cast<T*>(x);
        lambda();
        return 0;
    });
}

extern "C" int puts(const char *);

void b() {
    a([]() {
        puts("xxx");
    });
}
alvinhochun added a commit to alvinhochun/cppwinrt that referenced this issue Oct 14, 2022
The lambda in InvokeInContext needs to be annotated with
__attribute__((stdcall)) for it to work on Clang, but this is blocked on
a Clang crash bug: llvm/llvm-project#58366

This reverts commit cc561ec.
@erichkeane
Copy link
Collaborator

erichkeane commented Oct 14, 2022

Simplified: https://godbolt.org/z/8v16T7PMT

template<typename T>
void foo(void *x) {
    [](void*x) __attribute__((stdcall)) { return 0;};
}
void bar() {
    foo<int>(0);
}

@EugeneZelenko EugeneZelenko added clang:frontend Language frontend issues, e.g. anything involving "Sema" crash Prefer [crash-on-valid] or [crash-on-invalid] and removed new issue labels Oct 14, 2022
@llvmbot
Copy link
Collaborator

llvmbot commented Oct 14, 2022

@llvm/issue-subscribers-clang-frontend

@erichkeane erichkeane changed the title Clang crash instantiating lambda with __attribute__((stdcall)) Clang crash instantiating lambda with a calling convention specified on it. Oct 14, 2022
@erichkeane
Copy link
Collaborator

This is happening during the call to TransformFunctionProtoType in TreeTransform.h's TransformLambdaExpr because the OldCallOpFPTL is actually an AttributedTypeTypeLoc, not a FunctionProtoTypeLoc. I find myself wondering whether the lambda should be calling TransformFunctionProtoType and not just TransformType.

@erichkeane
Copy link
Collaborator

@MaskRay ended up doing this implementation it looks like, and I'm not completely sure what the exception-specifier stuff is doing, AND TransformFunctionProtoType seems to need quite a bit more work to get exceptions and the context to work correctly. I might look at this again, but hopefully @MaskRay can bring his knowledge of that code and just figure it out :)

alvinhochun added a commit to alvinhochun/cppwinrt that referenced this issue Oct 15, 2022
The lambda in InvokeInContext needs to be annotated with
__attribute__((stdcall)) for it to work on Clang, but this is blocked on
a Clang crash bug: llvm/llvm-project#58366

This reverts commit cc561ec.
@alvinhochun
Copy link
Contributor Author

Hi, thanks for looking into this initially. Any chance you can revisit this?

I did try to hack this and got something that can compile without crashing, but to be honest I have no idea what is going on here. I am attaching my hack in case it helps... (No lit tests added btw.)

Hack patch
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index f0d3a5ca089a..1dfb6178e8c9 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -13128,10 +13128,21 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
   // it introduces a mapping of the original to the newly created
   // transformed parameters.
   TypeSourceInfo *NewCallOpTSI = nullptr;
+  FunctionProtoTypeLoc NewCallOpFPTL;
   {
     TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo();
     FunctionProtoTypeLoc OldCallOpFPTL =
         OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
+    AttributedTypeLoc OldCallOpATTL;
+    bool IsAttributed = false;
+    if (!OldCallOpFPTL) {
+      OldCallOpATTL = OldCallOpTSI->getTypeLoc().getAs<AttributedTypeLoc>();
+      assert(OldCallOpATTL);
+      OldCallOpFPTL =
+          OldCallOpATTL.getModifiedLoc().getAs<FunctionProtoTypeLoc>();
+      assert(OldCallOpFPTL);
+      IsAttributed = true;
+    }
 
     TypeLocBuilder NewCallOpTLBuilder;
     SmallVector<QualType, 4> ExceptionStorage;
@@ -13144,8 +13155,36 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
         });
     if (NewCallOpType.isNull())
       return ExprError();
-    NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context,
-                                                        NewCallOpType);
+
+    if (IsAttributed) {
+      const AttributedType *oldType = OldCallOpATTL.getTypePtr();
+
+      const Attr *newAttr = getDerived().TransformAttr(OldCallOpATTL.getAttr());
+      if (!newAttr)
+        return ExprError();
+
+      QualType equivalentType =
+          getDerived().TransformType(oldType->getEquivalentType());
+      if (equivalentType.isNull())
+        return ExprError();
+      QualType result = SemaRef.Context.getAttributedType(
+          OldCallOpATTL.getAttrKind(), NewCallOpType, equivalentType);
+
+      AttributedTypeLoc newTL =
+          NewCallOpTLBuilder.push<AttributedTypeLoc>(result);
+      newTL.setAttr(newAttr);
+
+      NewCallOpTSI =
+          NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, result);
+      NewCallOpFPTL = NewCallOpTSI->getTypeLoc()
+                          .castAs<AttributedTypeLoc>()
+                          .getModifiedLoc()
+                          .castAs<FunctionProtoTypeLoc>();
+    } else {
+      NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context,
+                                                          NewCallOpType);
+      NewCallOpFPTL = NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>();
+    }
   }
 
   // Create the local class that will describe the lambda.
@@ -13179,8 +13218,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
   // Build the call operator.
   CXXMethodDecl *NewCallOperator = getSema().startLambdaDefinition(
       Class, E->getIntroducerRange(), NewCallOpTSI,
-      E->getCallOperator()->getEndLoc(),
-      NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(),
+      E->getCallOperator()->getEndLoc(), NewCallOpFPTL.getParams(),
       E->getCallOperator()->getConstexprKind(),
       E->getCallOperator()->getStorageClass(),
       E->getCallOperator()->getTrailingRequiresClause());

@cor3ntin
Copy link
Contributor

Fixed in trunk (post 17)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" crash Prefer [crash-on-valid] or [crash-on-invalid]
Projects
None yet
Development

No branches or pull requests

5 participants