Skip to content

[modules] Handle friend function that was a definition but became only a declaration during AST deserialization #132214

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

Merged
merged 11 commits into from
Apr 3, 2025

Conversation

dmpolukhin
Copy link
Contributor

@dmpolukhin dmpolukhin commented Mar 20, 2025

Fix for regression #130917, changes in #111992 were too broad. This change reduces scope of previous fix. Unfortunately in clang there is no way to know when redeclaration was craeted artificially due to AST mergse and when it was the case in the original code.

I'm not sure that this fix covers all cases but at least it should fix regression in clang-20. The ideas how to fix it better are very wellcome.

Changes in llvm#111992 was too broad. This change reduces scope of previous
fix. Unfortunately in clang there is no way to know when redeclaration
was craeted artificially due to AST mergse and when it was the case in
the original code.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Mar 20, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 20, 2025

@llvm/pr-subscribers-clang-modules

@llvm/pr-subscribers-clang

Author: Dmitry Polukhin (dmpolukhin)

Changes

Changes in #111992 was too broad. This change reduces scope of previous fix. Unfortunately in clang there is no way to know when redeclaration was craeted artificially due to AST mergse and when it was the case in the original code.

I'm not sure that this fix covers all cases but at least it should fix regression in clang-20. The ideas how to fix it better are very wellcome.


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

2 Files Affected:

  • (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+1-1)
  • (added) clang/test/SemaCXX/friend-default-parameters.cpp (+21)
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 539c2fdb83797..eda5d1151ab19 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2572,7 +2572,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
   // Friend function defined withing class template may stop being function
   // definition during AST merges from different modules, in this case decl
   // with function body should be used for instantiation.
-  if (isFriend) {
+  if (isFriend && D->hasOwningModule()) {
     const FunctionDecl *Defn = nullptr;
     if (D->hasBody(Defn)) {
       D = const_cast<FunctionDecl *>(Defn);
diff --git a/clang/test/SemaCXX/friend-default-parameters.cpp b/clang/test/SemaCXX/friend-default-parameters.cpp
new file mode 100644
index 0000000000000..7190477ac496a
--- /dev/null
+++ b/clang/test/SemaCXX/friend-default-parameters.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=c++20 -verify -emit-llvm-only %s
+
+template <int>
+void Create(const void* = nullptr);
+
+template <int>
+struct ObjImpl {
+  template <int>
+  friend void ::Create(const void*);
+};
+
+template <int I>
+void Create(const void*) {
+  (void) ObjImpl<I>{};
+}
+
+int main() {
+  Create<42>();
+}
+
+// expected-no-diagnostics

@@ -2572,7 +2572,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
// Friend function defined withing class template may stop being function
// definition during AST merges from different modules, in this case decl
// with function body should be used for instantiation.
if (isFriend) {
if (isFriend && D->hasOwningModule()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Clang AST is open to modifications.

Can't you add a new bit to Redeclarable to keep track of this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There is a problem with adding more flags to FunctionDecl, FunctionDeclBitfields is full and I cannot add there anything. Redeclarable doesn't have any flags as the moment and we need this extra flag only for FunctionDecls at the moment. So new version of the code works but most probably it cannot be committed as is. I also added another test case for the same example but inside module. My previous version was not able to compile it correctly.

Copy link
Member

Choose a reason for hiding this comment

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

We can do this in ASTReader (ExternalASTSource). We can add a new interface to ExternalASTSource and calling it. It will be helpful since the call to wasThisDeclarationADefinition() should be cold.

Copy link
Contributor Author

@dmpolukhin dmpolukhin Mar 26, 2025

Choose a reason for hiding this comment

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

@ChuanqiXu9 sorry I'm not sure I fully understand your idea about ExternalASTSource. Are you suggesting to extend ASTReader::DefinitionSource to also keep this information there? Now ASTReader::DefinitionSource maps to bool but I can change value to a struct with two flags (previous DefinitionSource and ThisDeclarationWasADefinition), I think we don't need to store it in PCM file. Does it sound like the right approach?

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh yes, I took the last free bit in FunctionDeclBits a couple of months ago :)

This is a tall order, but it may be possible to make room in there. For example:

    LLVM_PREFERRED_TYPE(bool)
    uint64_t IsDefaulted : 1;
    LLVM_PREFERRED_TYPE(bool)
    uint64_t IsExplicitlyDefaulted : 1;

It looks like IsExplicitlyDefaulted only makes sense if IsDefaulted is true, and maybe your new stuff only makes sense if IsDefaulted is false, so you can
probably share the IsExplicitlyDefaulted bit.

if that doesn't work, there are some other potential candidates.

For example, some bit fields only make sense if the function has a body, like UsesSEHTry, and these bits would probably be free for you as well.

Copy link
Contributor

Choose a reason for hiding this comment

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

we can add bits by shrinking

NumCtorInitializers.

however, in the present case it doesn't seem justified. these bits are precious.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I would prefer ExternalASTSource approach because it won't add any additional memory overhead and we already have hashtable ASTReader::DefinitionSource. Access to the filed should be super cold so it won't slowdown things. I will update this PR soon.

@llvmbot llvmbot added the clang:modules C++20 modules and Clang Header Modules label Mar 25, 2025
Copy link

github-actions bot commented Mar 25, 2025

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

@ChuanqiXu9
Copy link
Member

It may be better to update the title to make it more descriptive. e.g., what it does.

@dmpolukhin dmpolukhin changed the title [RFC][clang] Fix for regression #130917 [RFC][clang] Handle friend function that was a definition but became only a declaration during AST deserialization Mar 26, 2025
@cor3ntin cor3ntin requested a review from AaronBallman March 26, 2025 13:00
@@ -1390,7 +1390,19 @@ class ASTReader
/// predefines buffer may contain additional definitions.
std::string SuggestedPredefines;

llvm::DenseMap<const Decl *, bool> DefinitionSource;
struct DefinitionSourceFlags {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
struct DefinitionSourceFlags {
struct DefinitionSourceBits {

nit: Personal taste

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

ThisDeclarationWasADefinition(false) {}
};

llvm::DenseMap<const Decl *, DefinitionSourceFlags> DefinitionSource;
Copy link
Member

Choose a reason for hiding this comment

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

It might be better to add another new map for it. e.g., Decl is not a function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think memory overhead for another map will be higher. The value_type was bool but in reality at least 4-8 bytes were allocated for it so converting it to struct with 3 bits only shouldn't take extra space.

Copy link
Member

Choose a reason for hiding this comment

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

But it may introduce unnecessary insertions. I still feel it is better to add another map. And this practice seems to be more scalarble to me, e.g, if we want to add other similar information, it may not be good to add all the information to the struct.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IMHO it will only increase memory consumption but I don't have strong opinion here so moved to a new map. PTAL

@ChuanqiXu9
Copy link
Member

LGTM generally.

Some other personal suggestion to the title, it might be better to add [modules] to the title. Since my mail filter will highlight these mails with the tag : ) This might be why I missed you last ping.

@dmpolukhin dmpolukhin changed the title [RFC][clang] Handle friend function that was a definition but became only a declaration during AST deserialization [modules] Handle friend function that was a definition but became only a declaration during AST deserialization Mar 28, 2025
@dmpolukhin dmpolukhin requested a review from ChuanqiXu9 March 31, 2025 13:21
};

/// A mapping from declarations to extra bits of information about this decl.
llvm::DenseMap<const Decl *, ExternalDeclarationBits>
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
llvm::DenseMap<const Decl *, ExternalDeclarationBits>
llvm::DenseMap<const Decl *, bool>

nit: I think we can avoid the abstraction here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In this case we don't even need map, I replaced with with a set.

Copy link
Contributor Author

@dmpolukhin dmpolukhin left a comment

Choose a reason for hiding this comment

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

PTAL

};

/// A mapping from declarations to extra bits of information about this decl.
llvm::DenseMap<const Decl *, ExternalDeclarationBits>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

In this case we don't even need map, I replaced with with a set.

Copy link
Member

@ChuanqiXu9 ChuanqiXu9 left a comment

Choose a reason for hiding this comment

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

LGTM.

But I didn't recognize you didn't update MultiplexExternalSemaSource. Every time we add new interface to ExternalASTSource, we need to update MultiplexExternalSemaSource too.

@dmpolukhin
Copy link
Contributor Author

LGTM.

But I didn't recognize you didn't update MultiplexExternalSemaSource. Every time we add new interface to ExternalASTSource, we need to update MultiplexExternalSemaSource too.

Oh, thanks for the good catch! Fixed now.

Copy link
Member

@ChuanqiXu9 ChuanqiXu9 left a comment

Choose a reason for hiding this comment

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

Let it go.

@dmpolukhin dmpolukhin merged commit e1aaee7 into llvm:main Apr 3, 2025
11 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Apr 3, 2025

LLVM Buildbot has detected a new failure on builder sanitizer-x86_64-linux running on sanitizer-buildbot2 while building clang at step 2 "annotate".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/66/builds/12077

Here is the relevant piece of the build log for the reference
Step 2 (annotate) failure: 'python ../sanitizer_buildbot/sanitizers/zorg/buildbot/builders/sanitizers/buildbot_selector.py' (failure)
...
llvm-lit: /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:248: warning: COMPILER_RT_TEST_STANDALONE_BUILD_LIBS=ON, but this test suite does not support testing the just-built runtime libraries when the test compiler is configured to use different runtime libraries. Either modify this test suite to support this test configuration, or set COMPILER_RT_TEST_STANDALONE_BUILD_LIBS=OFF to test the runtime libraries included in the compiler instead.
llvm-lit: /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:259: note: Testing using libraries in "/home/b/sanitizer-x86_64-linux/build/build_default/./lib/../lib/clang/21/lib/i386-unknown-linux-gnu"
llvm-lit: /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:237: warning: Compiler lib dir != compiler-rt lib dir
Compiler libdir:     "/home/b/sanitizer-x86_64-linux/build/build_default/lib/clang/21/lib/i386-unknown-linux-gnu"
compiler-rt libdir:  "/home/b/sanitizer-x86_64-linux/build/build_default/lib/clang/21/lib/x86_64-unknown-linux-gnu"
llvm-lit: /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:248: warning: COMPILER_RT_TEST_STANDALONE_BUILD_LIBS=ON, but this test suite does not support testing the just-built runtime libraries when the test compiler is configured to use different runtime libraries. Either modify this test suite to support this test configuration, or set COMPILER_RT_TEST_STANDALONE_BUILD_LIBS=OFF to test the runtime libraries included in the compiler instead.
llvm-lit: /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:259: note: Testing using libraries in "/home/b/sanitizer-x86_64-linux/build/build_default/./lib/../lib/clang/21/lib/x86_64-unknown-linux-gnu"
llvm-lit: /home/b/sanitizer-x86_64-linux/build/llvm-project/llvm/utils/lit/lit/main.py:72: note: The test suite configuration requested an individual test timeout of 0 seconds but a timeout of 900 seconds was requested on the command line. Forcing timeout to be 900 seconds.
-- Testing: 4894 of 10694 tests, 88 workers --
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 60..
FAIL: ThreadSanitizer-x86_64 :: cxa_guard_acquire.cpp (3357 of 4894)
******************** TEST 'ThreadSanitizer-x86_64 :: cxa_guard_acquire.cpp' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
/home/b/sanitizer-x86_64-linux/build/build_default/./bin/clang  --driver-mode=g++ -fsanitize=thread -Wall  -m64  -msse4.2   -gline-tables-only -I/home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/../ -std=c++11 -I/home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/../ -nostdinc++ -I/home/b/sanitizer-x86_64-linux/build/build_default/runtimes/runtimes-bins/compiler-rt/lib/tsan/libcxx_tsan_x86_64/include/c++/v1 -O1 /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/cxa_guard_acquire.cpp -o /home/b/sanitizer-x86_64-linux/build/build_default/runtimes/runtimes-bins/compiler-rt/test/tsan/X86_64Config/Output/cxa_guard_acquire.cpp.tmp &&  /home/b/sanitizer-x86_64-linux/build/build_default/runtimes/runtimes-bins/compiler-rt/test/tsan/X86_64Config/Output/cxa_guard_acquire.cpp.tmp 2>&1 | FileCheck /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/cxa_guard_acquire.cpp # RUN: at line 1
+ /home/b/sanitizer-x86_64-linux/build/build_default/./bin/clang --driver-mode=g++ -fsanitize=thread -Wall -m64 -msse4.2 -gline-tables-only -I/home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/../ -std=c++11 -I/home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/../ -nostdinc++ -I/home/b/sanitizer-x86_64-linux/build/build_default/runtimes/runtimes-bins/compiler-rt/lib/tsan/libcxx_tsan_x86_64/include/c++/v1 -O1 /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/cxa_guard_acquire.cpp -o /home/b/sanitizer-x86_64-linux/build/build_default/runtimes/runtimes-bins/compiler-rt/test/tsan/X86_64Config/Output/cxa_guard_acquire.cpp.tmp
+ FileCheck /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/cxa_guard_acquire.cpp
+ /home/b/sanitizer-x86_64-linux/build/build_default/runtimes/runtimes-bins/compiler-rt/test/tsan/X86_64Config/Output/cxa_guard_acquire.cpp.tmp
/home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/cxa_guard_acquire.cpp:71:17: error: CHECK-NEXT: is not on the line after the previous match
 // CHECK-NEXT: Enter constructor
                ^
<stdin>:3:1: note: 'next' match was here
Enter constructor
^
<stdin>:1:11: note: previous match ended here
Enter main
          ^
<stdin>:2:1: note: non-matching line after previous match is here
Enter potentially blocking region
^

Input file: <stdin>
Check file: /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/cxa_guard_acquire.cpp

-dump-input=help explains the following input dump.

Input was:
<<<<<<
         1: Enter main 
         2: Enter potentially blocking region 
         3: Enter constructor 
next:71     !~~~~~~~~~~~~~~~~  error: match on wrong line
         4: Exit constructor 
         5: Exit potentially blocking region 
         6: Enter constructor 2 
         7: Exit main 
>>>>>>
Step 11 (test compiler-rt debug) failure: test compiler-rt debug (failure)
...
llvm-lit: /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:248: warning: COMPILER_RT_TEST_STANDALONE_BUILD_LIBS=ON, but this test suite does not support testing the just-built runtime libraries when the test compiler is configured to use different runtime libraries. Either modify this test suite to support this test configuration, or set COMPILER_RT_TEST_STANDALONE_BUILD_LIBS=OFF to test the runtime libraries included in the compiler instead.
llvm-lit: /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:259: note: Testing using libraries in "/home/b/sanitizer-x86_64-linux/build/build_default/./lib/../lib/clang/21/lib/i386-unknown-linux-gnu"
llvm-lit: /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:237: warning: Compiler lib dir != compiler-rt lib dir
Compiler libdir:     "/home/b/sanitizer-x86_64-linux/build/build_default/lib/clang/21/lib/i386-unknown-linux-gnu"
compiler-rt libdir:  "/home/b/sanitizer-x86_64-linux/build/build_default/lib/clang/21/lib/x86_64-unknown-linux-gnu"
llvm-lit: /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:248: warning: COMPILER_RT_TEST_STANDALONE_BUILD_LIBS=ON, but this test suite does not support testing the just-built runtime libraries when the test compiler is configured to use different runtime libraries. Either modify this test suite to support this test configuration, or set COMPILER_RT_TEST_STANDALONE_BUILD_LIBS=OFF to test the runtime libraries included in the compiler instead.
llvm-lit: /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:259: note: Testing using libraries in "/home/b/sanitizer-x86_64-linux/build/build_default/./lib/../lib/clang/21/lib/x86_64-unknown-linux-gnu"
llvm-lit: /home/b/sanitizer-x86_64-linux/build/llvm-project/llvm/utils/lit/lit/main.py:72: note: The test suite configuration requested an individual test timeout of 0 seconds but a timeout of 900 seconds was requested on the command line. Forcing timeout to be 900 seconds.
-- Testing: 4894 of 10694 tests, 88 workers --
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 60..
FAIL: ThreadSanitizer-x86_64 :: cxa_guard_acquire.cpp (3357 of 4894)
******************** TEST 'ThreadSanitizer-x86_64 :: cxa_guard_acquire.cpp' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
/home/b/sanitizer-x86_64-linux/build/build_default/./bin/clang  --driver-mode=g++ -fsanitize=thread -Wall  -m64  -msse4.2   -gline-tables-only -I/home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/../ -std=c++11 -I/home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/../ -nostdinc++ -I/home/b/sanitizer-x86_64-linux/build/build_default/runtimes/runtimes-bins/compiler-rt/lib/tsan/libcxx_tsan_x86_64/include/c++/v1 -O1 /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/cxa_guard_acquire.cpp -o /home/b/sanitizer-x86_64-linux/build/build_default/runtimes/runtimes-bins/compiler-rt/test/tsan/X86_64Config/Output/cxa_guard_acquire.cpp.tmp &&  /home/b/sanitizer-x86_64-linux/build/build_default/runtimes/runtimes-bins/compiler-rt/test/tsan/X86_64Config/Output/cxa_guard_acquire.cpp.tmp 2>&1 | FileCheck /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/cxa_guard_acquire.cpp # RUN: at line 1
+ /home/b/sanitizer-x86_64-linux/build/build_default/./bin/clang --driver-mode=g++ -fsanitize=thread -Wall -m64 -msse4.2 -gline-tables-only -I/home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/../ -std=c++11 -I/home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/../ -nostdinc++ -I/home/b/sanitizer-x86_64-linux/build/build_default/runtimes/runtimes-bins/compiler-rt/lib/tsan/libcxx_tsan_x86_64/include/c++/v1 -O1 /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/cxa_guard_acquire.cpp -o /home/b/sanitizer-x86_64-linux/build/build_default/runtimes/runtimes-bins/compiler-rt/test/tsan/X86_64Config/Output/cxa_guard_acquire.cpp.tmp
+ FileCheck /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/cxa_guard_acquire.cpp
+ /home/b/sanitizer-x86_64-linux/build/build_default/runtimes/runtimes-bins/compiler-rt/test/tsan/X86_64Config/Output/cxa_guard_acquire.cpp.tmp
/home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/cxa_guard_acquire.cpp:71:17: error: CHECK-NEXT: is not on the line after the previous match
 // CHECK-NEXT: Enter constructor
                ^
<stdin>:3:1: note: 'next' match was here
Enter constructor
^
<stdin>:1:11: note: previous match ended here
Enter main
          ^
<stdin>:2:1: note: non-matching line after previous match is here
Enter potentially blocking region
^

Input file: <stdin>
Check file: /home/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/tsan/cxa_guard_acquire.cpp

-dump-input=help explains the following input dump.

Input was:
<<<<<<
         1: Enter main 
         2: Enter potentially blocking region 
         3: Enter constructor 
next:71     !~~~~~~~~~~~~~~~~  error: match on wrong line
         4: Exit constructor 
         5: Exit potentially blocking region 
         6: Enter constructor 2 
         7: Exit main 
>>>>>>

dmpolukhin added a commit to dmpolukhin/llvm-project that referenced this pull request Apr 3, 2025
…y a declaration during AST deserialization (llvm#132214)

Fix for regression llvm#130917, changes in llvm#111992 were too broad. This change reduces scope of previous fix. Added `ExternalASTSource::wasThisDeclarationADefinition` to detect cases when FunctionDecl lost body due to declaration merges.
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.

6 participants