llvm-project icon indicating copy to clipboard operation
llvm-project copied to clipboard

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

Open alvinhochun opened this issue 3 years ago • 4 comments

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 avatar Oct 14 '22 16:10 alvinhochun

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

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

erichkeane avatar Oct 14 '22 17:10 erichkeane

@llvm/issue-subscribers-clang-frontend

llvmbot avatar Oct 14 '22 17:10 llvmbot

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 avatar Oct 14 '22 17:10 erichkeane

@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 :)

erichkeane avatar Oct 14 '22 17:10 erichkeane

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());

alvinhochun avatar Nov 19 '22 11:11 alvinhochun

Fixed in trunk (post 17)

cor3ntin avatar Jan 24 '24 22:01 cor3ntin