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

[PATCH] [clang][frontend] Fix serialization for CXXConstructorDecl (refs llvm#132794) #133077

Merged
merged 2 commits into from
Mar 28, 2025

Conversation

koplas
Copy link
Contributor

@koplas koplas commented Mar 26, 2025

When retrieving the ExplicitSpecifier from a CXXConstructorDecl, one of its canonical declarations is returned. To correctly write the declaration record the ExplicitSpecifier of the current declaration must be used.

Failing to do so results in a crash during deserialization.

Copy link

github-actions bot commented Mar 26, 2025

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

@koplas koplas force-pushed the fix-explicit branch 3 times, most recently from 5139570 to 686a9a7 Compare March 26, 2025 14:22
@koplas koplas marked this pull request as ready for review March 26, 2025 14:23
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules labels Mar 26, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 26, 2025

@llvm/pr-subscribers-clang-modules

@llvm/pr-subscribers-clang

Author: Paul Schwabauer (koplas)

Changes

When getting the ExplicitSpecifier of the CXXConstructorDecl, one of the canonical declaration is returned. When writing the declaration record with ExplicitSpecifier, the AllocKind of the canonical declaration has to be used.
If this is not done, it will later crash when on deserialization.

TODO: Reduce test.


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

2 Files Affected:

  • (modified) clang/include/clang/AST/DeclCXX.h (+3-2)
  • (added) clang/test/Modules/ComplexExplicitSpecifier.cpp (+45)
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index dbd02ef7f8011..7728669b3bcec 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -2601,10 +2601,11 @@ class CXXConstructorDecl final
   void anchor() override;
 
   size_t numTrailingObjects(OverloadToken<InheritedConstructor>) const {
-    return CXXConstructorDeclBits.IsInheritingConstructor;
+    return getCanonicalDecl()->CXXConstructorDeclBits.IsInheritingConstructor;
   }
   size_t numTrailingObjects(OverloadToken<ExplicitSpecifier>) const {
-    return CXXConstructorDeclBits.HasTrailingExplicitSpecifier;
+    return getCanonicalDecl()
+        ->CXXConstructorDeclBits.HasTrailingExplicitSpecifier;
   }
 
   ExplicitSpecifier getExplicitSpecifierInternal() const {
diff --git a/clang/test/Modules/ComplexExplicitSpecifier.cpp b/clang/test/Modules/ComplexExplicitSpecifier.cpp
new file mode 100644
index 0000000000000..33501ba264cc6
--- /dev/null
+++ b/clang/test/Modules/ComplexExplicitSpecifier.cpp
@@ -0,0 +1,45 @@
+// Tests complex explicit constructor across modules.
+//
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/Foo.cppm \
+// RUN: -o %t/Foo.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface \
+// RUN: -fmodule-file=Foo=%t/Foo.pcm \
+// RUN: %t/Bar.cppm \
+// RUN: -o %t/Bar.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-obj \
+// RUN: -main-file-name Bar.cppm \
+// RUN: -fmodule-file=Foo=%t/Foo.pcm \
+// RUN: -x pcm %t/Bar.pcm \
+// RUN: -o %t/Bar.o
+
+//--- Foo.cppm
+export module Foo;
+
+export {
+template<class T>
+class Foo {
+  public:
+    template<class... Args>
+    explicit (sizeof...(Args) == 1) Foo(Args&&... args);
+};
+}
+
+template<class T>
+template<class... Args>
+inline Foo<T>::Foo(Args&&... args) {}
+
+//--- Bar.cppm
+export module Bar;
+import Foo;
+
+struct Bar {};
+
+void a() {
+  auto foo = Foo<Bar>{};
+}

@cor3ntin
Copy link
Contributor

Thanks for working on this

This change needs a release note.
Please add an entry to clang/docs/ReleaseNotes.rst in the section the most adapted to the change, and referencing any Github issue this change fixes. Thanks!

…efs llvm#132794)

When retrieving the ExplicitSpecifier from a CXXConstructorDecl, one
of its canonical declarations is returned. To correctly write the
declaration record the ExplicitSpecifier of the current declaration
must be used.

Failing to do so results in a crash during deserialization.
Copy link
Contributor

@cor3ntin cor3ntin left a comment

Choose a reason for hiding this comment

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

LGTM, Thanks!
Will you need me to merge that for you?

@koplas
Copy link
Contributor Author

koplas commented Mar 27, 2025

LGTM, Thanks! Will you need me to merge that for you?

Yes, I don't have any permissions to merge this.

Co-authored-by: cor3ntin <corentinjabot@gmail.com>
Copy link
Collaborator

@shafik shafik left a comment

Choose a reason for hiding this comment

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

I am probably missing something here but I see you switched to using getExplicitSpecifierInternal() but in your summary you talk about using the correct AllocKind but I just don't see how they related at all.

I see the line before does Record.push_back(D->getTrailingAllocKind());. I looked at ExplicitSpecifier and also don't see how it relates.

Could you please clarify?

@koplas koplas changed the title [PATCH] [clang][frontend] Fix AllocKind retrieving for CXXConstructorDecl refs #132794 [PATCH] [clang][frontend] Fix serialization for CXXConstructorDecl (refs llvm#132794) Mar 28, 2025
@koplas
Copy link
Contributor Author

koplas commented Mar 28, 2025

@shafik, I updated the commit message based on the feedback of @cor3ntin. I have now updated the title and description to reflect the new commit message, to avoid further confusion.

@cor3ntin cor3ntin merged commit 8a3fe30 into llvm:main Mar 28, 2025
12 checks passed
@koplas koplas deleted the fix-explicit branch March 28, 2025 10:44
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" clang:modules C++20 modules and Clang Header Modules clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants