Skip to content

[clang] Fix loss of dllexport for exported template specialization #93302

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

Closed

Conversation

nga888
Copy link
Collaborator

@nga888 nga888 commented May 24, 2024

In commit 0a20f54, "Better codegen support for DLL attributes being dropped after the first declaration (PR20792)", code was added to enable "dropping" of DLL attributes. The specific issue and example given was related to dllimport and this was the test case that was added in that commit.

However, the code also included the "dropping" of dllexport but no test case for this was added. This "dropping" of dllexport can cause a dllexport template specialization to incorrectly lose its dllexport attribute as shown by the test case in this patch.

As there appears to be no need for the "dropping" of dllexport, remove this code to fix this issue.

In commit 0a20f54, "Better codegen support for DLL attributes being
dropped after the first declaration (PR20792)", code was added to enable
"dropping" of DLL attributes. The specific issue and example given was
related to `dllimport` and this was the test case that was added in that
commit.

However, the code also included the "dropping" of `dllexport` but no
test case for this was added. This "dropping" of `dllexport` can cause a
`dllexport` template specialization to incorrectly lose its `dllexport`
attribute as shown by the test case in this patch.

As there appears to be no need for the "dropping" of `dllexport`, remove
this code to fix this issue.
@nga888 nga888 requested review from wjristow and pogo59 May 24, 2024 13:55
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:codegen IR generation bugs: mangling, exceptions, etc. labels May 24, 2024
@llvmbot
Copy link
Member

llvmbot commented May 24, 2024

@llvm/pr-subscribers-clang-codegen

Author: Andrew Ng (nga888)

Changes

In commit 0a20f54, "Better codegen support for DLL attributes being dropped after the first declaration (PR20792)", code was added to enable "dropping" of DLL attributes. The specific issue and example given was related to dllimport and this was the test case that was added in that commit.

However, the code also included the "dropping" of dllexport but no test case for this was added. This "dropping" of dllexport can cause a dllexport template specialization to incorrectly lose its dllexport attribute as shown by the test case in this patch.

As there appears to be no need for the "dropping" of dllexport, remove this code to fix this issue.


Full diff: https://github.com/llvm/llvm-project/pull/93302.diff

2 Files Affected:

  • (modified) clang/lib/CodeGen/CodeGenModule.cpp (+11-5)
  • (added) clang/test/CodeGenCXX/windows-instantiate-dllexport-template-specialization.cpp (+18)
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index e4774a587707a..ae8104fe1c4cb 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4554,8 +4554,11 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
         Entry->setLinkage(llvm::Function::ExternalLinkage);
     }
 
-    // Handle dropped DLL attributes.
-    if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>() &&
+    // Handle dropped dllimport.
+    if (D &&
+        (Entry->getDLLStorageClass() ==
+         llvm::GlobalVariable::DLLImportStorageClass) &&
+        !D->hasAttr<DLLImportAttr>() &&
         !shouldMapVisibilityToDLLExport(cast_or_null<NamedDecl>(D))) {
       Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
       setDSOLocal(Entry);
@@ -4849,9 +4852,12 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty,
         Entry->setLinkage(llvm::Function::ExternalLinkage);
     }
 
-    // Handle dropped DLL attributes.
-    if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>() &&
-        !shouldMapVisibilityToDLLExport(D))
+    // Handle dropped dllimport.
+    if (D &&
+        (Entry->getDLLStorageClass() ==
+         llvm::GlobalVariable::DLLImportStorageClass) &&
+        !D->hasAttr<DLLImportAttr>() &&
+        !shouldMapVisibilityToDLLExport(cast_or_null<NamedDecl>(D)))
       Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
 
     if (LangOpts.OpenMP && !LangOpts.OpenMPSimd && D)
diff --git a/clang/test/CodeGenCXX/windows-instantiate-dllexport-template-specialization.cpp b/clang/test/CodeGenCXX/windows-instantiate-dllexport-template-specialization.cpp
new file mode 100644
index 0000000000000..97f341ba1f909
--- /dev/null
+++ b/clang/test/CodeGenCXX/windows-instantiate-dllexport-template-specialization.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple i686-windows         -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MS
+// RUN: %clang_cc1 -triple i686-windows-itanium -fdeclspec -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-scei-ps4      -fdeclspec -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-sie-ps5       -fdeclspec -emit-llvm %s -o - | FileCheck %s
+
+struct s {
+  template <bool b = true> static bool f();
+};
+
+template <typename T> bool template_using_f(T) { return s::f(); }
+
+bool use_template_using_f() { return template_using_f(0); }
+
+template<>
+bool __declspec(dllexport) s::f<true>() { return true; }
+
+// CHECK-MS: dllexport {{.*}} @"??$f@$00@s@@SA_NXZ"
+// CHECK: dllexport {{.*}} @_ZN1s1fILb1EEEbv

@llvmbot
Copy link
Member

llvmbot commented May 24, 2024

@llvm/pr-subscribers-clang

Author: Andrew Ng (nga888)

Changes

In commit 0a20f54, "Better codegen support for DLL attributes being dropped after the first declaration (PR20792)", code was added to enable "dropping" of DLL attributes. The specific issue and example given was related to dllimport and this was the test case that was added in that commit.

However, the code also included the "dropping" of dllexport but no test case for this was added. This "dropping" of dllexport can cause a dllexport template specialization to incorrectly lose its dllexport attribute as shown by the test case in this patch.

As there appears to be no need for the "dropping" of dllexport, remove this code to fix this issue.


Full diff: https://github.com/llvm/llvm-project/pull/93302.diff

2 Files Affected:

  • (modified) clang/lib/CodeGen/CodeGenModule.cpp (+11-5)
  • (added) clang/test/CodeGenCXX/windows-instantiate-dllexport-template-specialization.cpp (+18)
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index e4774a587707a..ae8104fe1c4cb 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4554,8 +4554,11 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
         Entry->setLinkage(llvm::Function::ExternalLinkage);
     }
 
-    // Handle dropped DLL attributes.
-    if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>() &&
+    // Handle dropped dllimport.
+    if (D &&
+        (Entry->getDLLStorageClass() ==
+         llvm::GlobalVariable::DLLImportStorageClass) &&
+        !D->hasAttr<DLLImportAttr>() &&
         !shouldMapVisibilityToDLLExport(cast_or_null<NamedDecl>(D))) {
       Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
       setDSOLocal(Entry);
@@ -4849,9 +4852,12 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty,
         Entry->setLinkage(llvm::Function::ExternalLinkage);
     }
 
-    // Handle dropped DLL attributes.
-    if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>() &&
-        !shouldMapVisibilityToDLLExport(D))
+    // Handle dropped dllimport.
+    if (D &&
+        (Entry->getDLLStorageClass() ==
+         llvm::GlobalVariable::DLLImportStorageClass) &&
+        !D->hasAttr<DLLImportAttr>() &&
+        !shouldMapVisibilityToDLLExport(cast_or_null<NamedDecl>(D)))
       Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
 
     if (LangOpts.OpenMP && !LangOpts.OpenMPSimd && D)
diff --git a/clang/test/CodeGenCXX/windows-instantiate-dllexport-template-specialization.cpp b/clang/test/CodeGenCXX/windows-instantiate-dllexport-template-specialization.cpp
new file mode 100644
index 0000000000000..97f341ba1f909
--- /dev/null
+++ b/clang/test/CodeGenCXX/windows-instantiate-dllexport-template-specialization.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple i686-windows         -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MS
+// RUN: %clang_cc1 -triple i686-windows-itanium -fdeclspec -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-scei-ps4      -fdeclspec -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-sie-ps5       -fdeclspec -emit-llvm %s -o - | FileCheck %s
+
+struct s {
+  template <bool b = true> static bool f();
+};
+
+template <typename T> bool template_using_f(T) { return s::f(); }
+
+bool use_template_using_f() { return template_using_f(0); }
+
+template<>
+bool __declspec(dllexport) s::f<true>() { return true; }
+
+// CHECK-MS: dllexport {{.*}} @"??$f@$00@s@@SA_NXZ"
+// CHECK: dllexport {{.*}} @_ZN1s1fILb1EEEbv

@nga888 nga888 requested a review from zmodem May 24, 2024 14:13
Copy link
Collaborator

@pogo59 pogo59 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the test exercise both modified paths? I'm guessing it only exercises GetOrCreateLLVMFunction, but I'm not a codegen expert.

(Entry->getDLLStorageClass() ==
llvm::GlobalVariable::DLLImportStorageClass) &&
!D->hasAttr<DLLImportAttr>() &&
!shouldMapVisibilityToDLLExport(cast_or_null<NamedDecl>(D)))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
!shouldMapVisibilityToDLLExport(cast_or_null<NamedDecl>(D)))
!shouldMapVisibilityToDLLExport(cast<NamedDecl>(D)))

D is non-null here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part of the code isn't directly related to the change but I assume I can go ahead and change it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, the above comment should have been in reply to the instance above. This cast shouldn't be needed at all. I suspect a copy & paste error on my behalf!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've fixed up both instances of the call to shouldMapVisibilityToDLLExport().

if (D &&
(Entry->getDLLStorageClass() ==
llvm::GlobalVariable::DLLImportStorageClass) &&
!D->hasAttr<DLLImportAttr>() &&
!shouldMapVisibilityToDLLExport(cast_or_null<NamedDecl>(D))) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
!shouldMapVisibilityToDLLExport(cast_or_null<NamedDecl>(D))) {
!shouldMapVisibilityToDLLExport(cast<NamedDecl>(D))) {

D is non-null here.

@nga888
Copy link
Collaborator Author

nga888 commented May 24, 2024

Does the test exercise both modified paths? I'm guessing it only exercises GetOrCreateLLVMFunction, but I'm not a codegen expert.

Only 1 path is "exercised" but I believe neither path of the removed code was exercised previously and no other tests are affected by the code removal.

Copy link

github-actions bot commented May 24, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Collaborator

@zmodem zmodem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit 0a20f54, "Better codegen support for DLL attributes being dropped after the first declaration (PR20792)", code was added to enable "dropping" of DLL attributes.

Wow, how is that 10 years ago already?

I'm not sure this is the right place for the fix though. Note that even though my patch added handling for dropping dllexport, we still do export f in this case:

__declspec(dllexport) int f(int x);
int user(int x) {
  return f(x);
}
int f(int x) { return 1; }

Because f is still dllexport at the AST level, as it should. That's handled by the code which deals with redeclarations.

I suspect that's where we should fix your case also: we should figure out why s::f<true>() isn't(?) marked dllexport in the AST.

@nga888
Copy link
Collaborator Author

nga888 commented May 28, 2024

I'm not sure this is the right place for the fix though. Note that even though my patch added handling for dropping dllexport, we still do export f in this case:

__declspec(dllexport) int f(int x);
int user(int x) {
  return f(x);
}
int f(int x) { return 1; }

In your example, the "early" declaration of f already has dllexport. For the test case in this patch:

struct s {
  template <bool b = true> static bool f();
};
template <typename T> bool template_using_f(T) { return s::f(); }
bool use_template_using_f() { return template_using_f(0); }
template<>
bool __declspec(dllexport) s::f<true>() { return true; }

It is the "late" specialization of the template that has dllexport and I think this is the main reason why s::f<true>() isn't consistently marked as dllexport in the AST. This in turn, then triggers the dllexport to be dropped by the code in your patch.

I understand that removing the code that drops dllexport may not be the "best" place to fix this issue but if this code is not actually required, which appears to be the case (please let me know if this is not), then removing the code to achieve "better" behaviour feels like a "win". The alternative would be to add more code/complexity to the AST handling. It already seems that there is some level of "entanglement" between the AST and codegen given the need for the code to remove dllimport.

One existing scenario where this patch's test case does result in the expected export is with the option -fdelayed-template-parsing which appears to still be the default for clang-cl. However, this is non-standard MSVC behaviour which I believe even MSVC is moving away from. Compiling with clang-cl using the -permissive- option, which disables delayed template parsing amongst other things, results in the same issue, i.e. the missing export. This patch also fixes this use case.

@zmodem
Copy link
Collaborator

zmodem commented May 29, 2024

I understand that removing the code that drops dllexport may not be the "best" place to fix this issue but if this code is not actually required, which appears to be the case (please let me know if this is not), then removing the code to achieve "better" behaviour feels like a "win". The alternative would be to add more code/complexity to the AST handling.

I still think fixing the AST would be better. That would also fix the "dllimport version" of your test case:

struct s {
  template <bool b = true> static bool f();
};
template <typename T> bool template_using_f(T) { return s::f(); }
bool use_template_using_f() { return template_using_f(0); }

template<> inline
bool __declspec(dllimport) s::f<true>() { return true; }

Here, dllimport gets dropped from s::f<true>() for the same reason as in your test: the AST node which the call in template_using_f() refers to is missing the attribute. (Godbolt: https://godbolt.org/z/nnfET4r13)

@nga888
Copy link
Collaborator Author

nga888 commented May 29, 2024

Here, dllimport gets dropped from s::f<true>() for the same reason as in your test: the AST node which the call in template_using_f() refers to is missing the attribute. (Godbolt: https://godbolt.org/z/nnfET4r13)

I think the difference in this case, is that this behaviour is unlikely to cause a "real" issue. The import of a definition/specialization is already a bit of an anomaly, so dropping dllimport is probably reasonable.

Copy link
Collaborator

@zmodem zmodem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import of a definition/specialization is already a bit of an anomaly, so dropping dllimport is probably reasonable.

Well, you're exporting a specialization. How is it going to get imported?

Perhaps me leaving the definition in there was unnecessary. How about just:

template<>
bool __declspec(dllimport) s::f<true>();

(https://godbolt.org/z/nqE7zPWYP)

Anyway, my point is that your patch is only working around half the bug. It seems to me that the proper fix has to be to get the attributes right in the AST.

@nga888
Copy link
Collaborator Author

nga888 commented May 29, 2024

Well, you're exporting a specialization. How is it going to get imported?

The "importing" side is just:

struct s {
  template <bool b = true> static bool f();
};
bool use_f() { return s::f(); }

This test case was derived from code that is part of UnrealEngine 5.4 which builds fine with MSVC, i.e. no undefined symbol for s::f<true>().

Anyway, my point is that your patch is only working around half the bug. It seems to me that the proper fix has to be to get the attributes right in the AST.

So in this test case for exported template specializations, there isn't really another "half" to the issue.

@zmodem
Copy link
Collaborator

zmodem commented May 31, 2024

I looked at this some more. Here's a slightly reduced version of your test case:

template <typename> void foo();
template <typename> void f() {
    foo<void>();
}
void g() { f<void>(); }
template <> void __declspec(dllexport) foo<void>() {}

What happens (when building with -fno-delayed-template-parsing) is something like:

  1. The f() template gets parsed. Because the call to foo is not type-dependent, the call gets resolved to a FunctionDecl for foo<void>, which isn't dllexport because that happens later.
  2. g() calls f<void>(), so the latter gets queued up for codegen at the end of the TU.
  3. Codegen for foo<void> happens, with dllexport.
  4. (End of the TU) Codegen for f<void> happens. When generating the call to foo<void>, it uses the FunctionDecl from step 1). We enter CodeGenModule::GetOrCreateLLVMFunction, see that the old Entry is dllexport but the new FunctionDecl isn't, and so the attribute gets dropped.

I think the "surprise" is that the latter call to GetOrCreateLLVMFunction is using an earlier FunctionDecl. Because of that, I'm thinking maybe the fix is to call getMostRecentDecl on it, something like:

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 489c08a4d481..8fe36305e104 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4554,10 +4554,13 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
     }
 
     // Handle dropped DLL attributes.
-    if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>() &&
-        !shouldMapVisibilityToDLLExport(cast_or_null<NamedDecl>(D))) {
-      Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
-      setDSOLocal(Entry);
+    if (D) {
+      const Decl *MRD = D->getMostRecentDecl();
+      if (!MRD->hasAttr<DLLImportAttr>() && !MRD->hasAttr<DLLExportAttr>() &&
+          !shouldMapVisibilityToDLLExport(cast<NamedDecl>(MRD))) {
+        Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
+        setDSOLocal(Entry);
+      }
     }
 
     // If there are two attempts to define the same mangled name, issue an

If we're concerned about the extra function call in a common codepath, we could only do this if there is a dll attribute on the Entry.

@nga888
Copy link
Collaborator Author

nga888 commented May 31, 2024

I think the "surprise" is that the latter call to GetOrCreateLLVMFunction is using an earlier FunctionDecl. Because of that, I'm thinking maybe the fix is to call getMostRecentDecl on it, something like:

Thanks for your time and the update. Yes, this is what I also discovered whilst debugging this issue. I also came to the same conclusion as you but when I tried using getMostRecentDecl() it didn't appear to work for me. Have you confirmed that this does fix this issue? I will look again, perhaps I made a mistake when trying this fix.

It was after this failure that I then started to question the whole removing of dllexport. I still think that this doesn't serve any useful purpose (and it isn't tested) which is why I would still favour the removal of the code.

@nga888
Copy link
Collaborator Author

nga888 commented May 31, 2024

Ok, I have confirmed that the getMostRecentDecl() fix does indeed work on the main branch. When I started debugging this issue sometime ago, I was working with a downstream branch based off 17.x using the source file from UE 5.4. I remember trying the use of getMostRecentDecl() but it did not work. I thought that it had failed to fix this specific issue but on retrying the fix, it does fix the test case from this patch (haven't retested with UE 5.4 itself). However, this fix also causes a dllimport test to fail too, so perhaps that was the "failure" that I encountered, I just don't remember. The same also applies to 18.x. However, interestingly, this dllimport test does not fail on the main branch, I think because of other changes since 18.x, but this does make me feel a little uneasy.

The code changes in this patch have been tested across 17.x, 18.x and main with no "extra" issues.

@zmodem, how would you like to proceed? If the removal of the dropping of dllexport is not acceptable, then I guess a new PR based on a fix using getMostRecentDecl()?

@zmodem
Copy link
Collaborator

zmodem commented Jun 3, 2024

Ok, I have confirmed that the getMostRecentDecl() fix does indeed work on the main branch.

Great!

However, this fix also causes a dllimport test to fail too, so perhaps that was the "failure" that I encountered, I just don't remember.

Was this about @_ZdlPv in clang/test/CodeGenCXX/dllimport.cpp? Using getMostRecentDecl() makes that dllimport, and I think that's correct and matching MinGW's behavior: https://godbolt.org/z/Mzo1zGsrj

I think we should proceed with switching to getMostRecentDecl(). Either a new PR or continuing in this one works for me.

@nga888
Copy link
Collaborator Author

nga888 commented Jun 3, 2024

However, this fix also causes a dllimport test to fail too, so perhaps that was the "failure" that I encountered, I just don't remember.

Was this about @_ZdlPv in clang/test/CodeGenCXX/dllimport.cpp? Using getMostRecentDecl() makes that dllimport, and I think that's correct and matching MinGW's behavior: https://godbolt.org/z/Mzo1zGsrj

OK, so this change in behaviour is desirable and matches MinGW? The odd thing is that this behaviour doesn't change on the main branch or at least not with the version of it that I tried on Friday.

I think we should proceed with switching to getMostRecentDecl(). Either a new PR or continuing in this one works for me.

I think it might be easier and simpler to go with a new PR.

@nga888
Copy link
Collaborator Author

nga888 commented Jun 3, 2024

@zmodem, forgot to ask, and not directly linked to this patch as such, but shouldn't there be a test case added for the dropping of dllexport?

@zmodem
Copy link
Collaborator

zmodem commented Jun 3, 2024

The odd thing is that this behaviour doesn't change on the main branch or at least not with the version of it that I tried on Friday.

I could have sworn it failed... but I was also using main from a few weeks ago. I think the test doesn't fail anymore because sized delete was enabled in 130e93c. Maybe we should specify -fno-sized-deallocation or update the test somehow.

shouldn't there be a test case added for the dropping of dllexport?

I can't think of a test case that would hit it.

@nga888
Copy link
Collaborator Author

nga888 commented Jun 4, 2024

shouldn't there be a test case added for the dropping of dllexport?

I can't think of a test case that would hit it.

Just for clarification, you want to pursue the getMostRecentDecl() approach but keep the code for the dropping of dllexport even though there appears to be no test case that would/can exercise this code?

@zmodem
Copy link
Collaborator

zmodem commented Jun 4, 2024

Yes.

@nga888
Copy link
Collaborator Author

nga888 commented Jun 6, 2024

Closing this PR in favour of PR #94664.

@nga888 nga888 closed this Jun 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen IR generation bugs: mangling, exceptions, etc. clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants