Skip to content

[Clang] Bypass TAD during overload resolution if a perfect match exists #136203

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 32 commits into from
Apr 18, 2025

Conversation

cor3ntin
Copy link
Contributor

This implements the same overload resolution behavior as GCC,
as described in https://wg21.link/p3606 (section 1-2, not 3)

If during overload resolution, there is a non-template candidate
that would be always be picked - because each of the argument
is a perfect match (ie the source and target types are the same),
we do not perform deduction for any template candidate
that might exists.

The goal is to be able to merge #122423 without being too disruptive.

This change means that the selection of the best viable candidate and
template argument deduction become interleaved.

To avoid rewriting half of Clang we store in OverloadCandidateSet
enough information to be able to deduce template candidates from
OverloadCandidateSet::BestViableFunction. Which means
the lifetime of any object used by template argument must outlive
a call to AddTemplateCandidate.

This two phase resolution is not performed for some initialization
as there are cases where template candidate are better match
in these cases per the standard. It's also bypassed for code completion.

The change has a nice impact on compile times
https://llvm-compile-time-tracker.com/compare.php?from=719b029c16eeb1035da522fd641dfcc4cee6be74&to=bf7041045c9408490c395230047c5461de72fc39&stat=instructions%3Au

Fixes #62096
Fixes #74581

Reapplies #133426

Copy link

github-actions bot commented Apr 17, 2025

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

cor3ntin added 29 commits April 17, 2025 23:52
…match exists

This implements the same overload resolution behavior as GCC,
as described in https://wg21.link/p3606 (section 1-2, not 3)

If during overload resolution, there is a non-template candidate
that would be always be picked - because each of the argument
is a perfect match (ie the source and target types are the same),
we do not perform deduction for any template candidate
that might exists.

The goal is to be able to merge llvm#122423 without being too disruptive.

This change means that the selection of the best viable candidate and
template argument deduction become interleaved.

To avoid rewriting half of Clang we store in `OverloadCandidateSet`
enough information to be able to deduce template candidates from
`OverloadCandidateSet::BestViableFunction`. Which means
the lifetime of any object used by template argument must outlive
a call to `Add*Template*Candidate`.

This two phase resolution is not performed for some initialization
as there are cases where template candidate are better match
in these cases per the standard. It's also bypassed for code completion.

The change has a nice impact on compile times
https://llvm-compile-time-tracker.com/compare.php?from=719b029c16eeb1035da522fd641dfcc4cee6be74&to=bf7041045c9408490c395230047c5461de72fc39&stat=instructions%3Au

Fixes llvm#62096
Fixes llvm#74581
* Prefer a constructor template over a non-template conversion function
 - We find a template conversion candidate
 - A constructor with a dependent explicit specifier
@alexfh
Copy link
Contributor

alexfh commented Apr 30, 2025

This change breaks a bunch of other cases, for example, calls to NodeDefBuilder::Attr("...", {some_value}) https://android.googlesource.com/platform/external/tensorflow/+/main/tensorflow/core/framework/node_def_builder.h#130

@alexfh
Copy link
Contributor

alexfh commented May 2, 2025

Please take a look, so far it seems like it should be reverted.

@zyn0217
Copy link
Contributor

zyn0217 commented May 2, 2025

This change breaks a bunch of other cases, for example, calls to NodeDefBuilder::Attr("...", {some_value}) https://android.googlesource.com/platform/external/tensorflow/+/main/tensorflow/core/framework/node_def_builder.h#130

Can you provide us with a reduced example?

@cor3ntin
Copy link
Contributor Author

cor3ntin commented May 2, 2025

@alexfh I just noticed, I'll look into it (please mention people explicitly, otherwise it's unlikely people notice)

cor3ntin added a commit to cor3ntin/llvm-project that referenced this pull request May 2, 2025
…t perfect

We might prefer a template std::initializer list constructor.

Fix a regression introduced by llvm#136203
llvm#136203 (comment)

GCC had a similar issue and a similar fix
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100963
cor3ntin added a commit that referenced this pull request May 2, 2025
…t perfect (#138307)

We might prefer a template std::initializer list constructor.

Fix a regression introduced by #136203
#136203 (comment)

GCC had a similar issue and a similar fix
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100963
@alexfh
Copy link
Contributor

alexfh commented May 3, 2025

Thank you for the prompt fix! It addresses the problems we've found so far.

@alexfh
Copy link
Contributor

alexfh commented May 3, 2025

This change breaks a bunch of other cases, for example, calls to NodeDefBuilder::Attr("...", {some_value}) https://android.googlesource.com/platform/external/tensorflow/+/main/tensorflow/core/framework/node_def_builder.h#130

Can you provide us with a reduced example?

This is fixed now. I think, the test case in #138307 already covers this.

IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
…ts (llvm#136203)

This implements the same overload resolution behavior as GCC,
as described in https://wg21.link/p3606 (section 1-2, not 3)

If during overload resolution, there is a non-template candidate
that would be always be picked - because each of the argument
is a perfect match (ie the source and target types are the same),
we do not perform deduction for any template candidate
that might exists.

The goal is to be able to merge
llvm#122423 without being too
disruptive.

This change means that the selection of the best viable candidate and
template argument deduction become interleaved.

To avoid rewriting half of Clang we store in OverloadCandidateSet
enough information to be able to deduce template candidates from
OverloadCandidateSet::BestViableFunction. Which means
the lifetime of any object used by template argument must outlive
a call to Add*Template*Candidate.

This two phase resolution is not performed for some initialization
as there are cases where template candidate are better match
in these cases per the standard. It's also bypassed for code completion.

The change has a nice impact on compile times

https://llvm-compile-time-tracker.com/compare.php?from=719b029c16eeb1035da522fd641dfcc4cee6be74&to=bf7041045c9408490c395230047c5461de72fc39&stat=instructions%3Au

Fixes llvm#62096
Fixes llvm#74581

Reapplies llvm#133426
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
…t perfect (llvm#138307)

We might prefer a template std::initializer list constructor.

Fix a regression introduced by llvm#136203
llvm#136203 (comment)

GCC had a similar issue and a similar fix
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100963
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
…t perfect (llvm#138307)

We might prefer a template std::initializer list constructor.

Fix a regression introduced by llvm#136203
llvm#136203 (comment)

GCC had a similar issue and a similar fix
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100963
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
…ts (llvm#136203)

This implements the same overload resolution behavior as GCC,
as described in https://wg21.link/p3606 (section 1-2, not 3)

If during overload resolution, there is a non-template candidate
that would be always be picked - because each of the argument
is a perfect match (ie the source and target types are the same),
we do not perform deduction for any template candidate
that might exists.

The goal is to be able to merge
llvm#122423 without being too
disruptive.

This change means that the selection of the best viable candidate and
template argument deduction become interleaved.

To avoid rewriting half of Clang we store in OverloadCandidateSet
enough information to be able to deduce template candidates from
OverloadCandidateSet::BestViableFunction. Which means
the lifetime of any object used by template argument must outlive
a call to Add*Template*Candidate.

This two phase resolution is not performed for some initialization
as there are cases where template candidate are better match
in these cases per the standard. It's also bypassed for code completion.

The change has a nice impact on compile times

https://llvm-compile-time-tracker.com/compare.php?from=719b029c16eeb1035da522fd641dfcc4cee6be74&to=bf7041045c9408490c395230047c5461de72fc39&stat=instructions%3Au

Fixes llvm#62096
Fixes llvm#74581

Reapplies llvm#133426
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
…t perfect (llvm#138307)

We might prefer a template std::initializer list constructor.

Fix a regression introduced by llvm#136203
llvm#136203 (comment)

GCC had a similar issue and a similar fix
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100963
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request May 6, 2025
…ed-init-list perfect (#138307)

We might prefer a template std::initializer list constructor.

Fix a regression introduced by #136203
llvm/llvm-project#136203 (comment)

GCC had a similar issue and a similar fix
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100963
GeorgeARM pushed a commit to GeorgeARM/llvm-project that referenced this pull request May 7, 2025
…t perfect (llvm#138307)

We might prefer a template std::initializer list constructor.

Fix a regression introduced by llvm#136203
llvm#136203 (comment)

GCC had a similar issue and a similar fix
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100963
@yuxuanchen1997
Copy link
Member

I was confused a little here. It sounded like this patch will make strictly more programs accepted. However, this seems not true: https://godbolt.org/z/erhjKhKP5

This program might be problematic to accept in the first place, which means that this patch has some side effect to indirectly fixing other bugs. (e.g. 1. why removing unused field in base class made clang 20 reject the program. and 2. why remove the subclass made clang 20 reject the program)

@cor3ntin cor3ntin added the clang:frontend Language frontend issues, e.g. anything involving "Sema" label May 12, 2025
facebook-github-bot pushed a commit to facebook/folly that referenced this pull request May 14, 2025
…nique_ptr<T>>

Summary:
Adding this as a test for the new compiler. With this upstream PR: llvm/llvm-project#136203

This test starts to fail with the following error:
```
fbcode/folly/memory/test/not_null_test.cpp:465:24: error: call to constructor of 'std::unique_ptr<int>' is ambiguous
  465 |   std::unique_ptr<int> i{std::move(nnu)};
      |                        ^~~~~~~~~~~~~~~~~
fbcode/third-party-buck/platform010/build/libgcc/include/c++/trunk/bits/unique_ptr.h:327:7: note: candidate constructor
  327 |       unique_ptr(unique_ptr&&) = default;
      |       ^
fbcode/third-party-buck/platform010/build/libgcc/include/c++/trunk/bits/unique_ptr.h:468:7: note: candidate constructor has been explicitly deleted
  468 |       unique_ptr(const unique_ptr&) = delete;
      |       ^
fbcode/folly/memory/test/not_null_test.cpp:467:7: error: static assertion failed due to requirement 'std::is_constructible_v<std::unique_ptr<int, std::default_delete<int>>, folly::not_null<std::unique_ptr<int, std::default_delete<int>>>>'
  467 |       std::is_constructible_v<
      |       ^~~~~~~~~~~~~~~~~~~~~~~~
  468 |           std::unique_ptr<int>,
      |           ~~~~~~~~~~~~~~~~~~~~~
  469 |           not_null<std::unique_ptr<int>>>);
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 errors generated.
```
Note that when you construct a unique_ptr, its deleted copy constructor still participates in overload resolution. So it's possible for a operator const PtrT&() const& noexcept to be selected. Meanwhile, its operator PtrT&&() && noexcept; is selected to convert not_null to the unique_ptr&& for the move constructor. Hence the ambiguity.

Why is this only a problem now? See D74599633. The existence of the conversion operator template was a better match to create a unique_ptr from a not_null previously. However, the SFINAE conditions are circular and caused weird compiler behaviours. This upstream PR now stops looking at templates when there's a "perfect match", which are the nontemplated `operator PtrT&&` and `operator const PtrT&` for not_null. It's possible that the PR has hidden some bugs, but the behaviour is unspecified by the standard anyway. The PR implements the change to make it align with GCC behaviour.

Reviewed By: snarkmaster, Gownta

Differential Revision: D74602687

fbshipit-source-id: ad6c49e6fa57c6340d6646734e9b6120e309353c
facebook-github-bot pushed a commit to facebook/hhvm that referenced this pull request May 14, 2025
…nique_ptr<T>>

Summary:
Adding this as a test for the new compiler. With this upstream PR: llvm/llvm-project#136203

This test starts to fail with the following error:
```
fbcode/folly/memory/test/not_null_test.cpp:465:24: error: call to constructor of 'std::unique_ptr<int>' is ambiguous
  465 |   std::unique_ptr<int> i{std::move(nnu)};
      |                        ^~~~~~~~~~~~~~~~~
fbcode/third-party-buck/platform010/build/libgcc/include/c++/trunk/bits/unique_ptr.h:327:7: note: candidate constructor
  327 |       unique_ptr(unique_ptr&&) = default;
      |       ^
fbcode/third-party-buck/platform010/build/libgcc/include/c++/trunk/bits/unique_ptr.h:468:7: note: candidate constructor has been explicitly deleted
  468 |       unique_ptr(const unique_ptr&) = delete;
      |       ^
fbcode/folly/memory/test/not_null_test.cpp:467:7: error: static assertion failed due to requirement 'std::is_constructible_v<std::unique_ptr<int, std::default_delete<int>>, folly::not_null<std::unique_ptr<int, std::default_delete<int>>>>'
  467 |       std::is_constructible_v<
      |       ^~~~~~~~~~~~~~~~~~~~~~~~
  468 |           std::unique_ptr<int>,
      |           ~~~~~~~~~~~~~~~~~~~~~
  469 |           not_null<std::unique_ptr<int>>>);
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 errors generated.
```
Note that when you construct a unique_ptr, its deleted copy constructor still participates in overload resolution. So it's possible for a operator const PtrT&() const& noexcept to be selected. Meanwhile, its operator PtrT&&() && noexcept; is selected to convert not_null to the unique_ptr&& for the move constructor. Hence the ambiguity.

Why is this only a problem now? See D74599633. The existence of the conversion operator template was a better match to create a unique_ptr from a not_null previously. However, the SFINAE conditions are circular and caused weird compiler behaviours. This upstream PR now stops looking at templates when there's a "perfect match", which are the nontemplated `operator PtrT&&` and `operator const PtrT&` for not_null. It's possible that the PR has hidden some bugs, but the behaviour is unspecified by the standard anyway. The PR implements the change to make it align with GCC behaviour.

Reviewed By: snarkmaster, Gownta

Differential Revision: D74602687

fbshipit-source-id: ad6c49e6fa57c6340d6646734e9b6120e309353c
@alexfh
Copy link
Contributor

alexfh commented May 15, 2025

@cor3ntin we've root-caused an assertion failure in Clang to this commit. It reproduces at least up to 1778d3b.

The test case is being reduced, but maybe you can spot something obviously wrong from the assertion failure and the stack trace:

assert.h assertion failed at clang/include/clang/Sema/Overload.h:440 in bool clang::StandardConversionSequence::isPerfect(const ASTContext &) const: C.hasSameUnqualifiedType(Decay(getFromType()), Decay(getToType(2)))
    @     0x55c6ab026ba4  __assert_fail
    @     0x55c6a677b4f4  clang::StandardConversionSequence::isPerfect()
    @     0x55c6a67593a2  clang::OverloadCandidateSet::PerfectViableFunction()
    @     0x55c6a67460cf  clang::OverloadCandidateSet::BestViableFunction()
    @     0x55c6a676b222  clang::Sema::BuildCallToMemberFunction()
    @     0x55c6a6306c71  clang::Sema::BuildCallExpr()
    @     0x55c6a63217c7  clang::Sema::ActOnCallExpr()
    @     0x55c6a5d1609d  clang::Parser::ParsePostfixExpressionSuffix()
    @     0x55c6a5d18328  clang::Parser::ParseCastExpression()
    @     0x55c6a5d1351d  clang::Parser::ParseAssignmentExpression()
    @     0x55c6a5d133fe  clang::Parser::ParseExpression()
    @     0x55c6a5db2d9e  clang::Parser::ParseExprStatement()
    @     0x55c6a5db2178  clang::Parser::ParseStatementOrDeclarationAfterAttributes()
    @     0x55c6a5db0111  clang::Parser::ParseStatementOrDeclaration()
    @     0x55c6a5dbbf55  clang::Parser::ParseCompoundStatementBody()
    @     0x55c6a5dbcd63  clang::Parser::ParseFunctionStatementBody()
    @     0x55c6a5cf33f3  clang::Parser::ParseFunctionDefinition()
    @     0x55c6a5d6a88e  clang::Parser::ParseDeclGroup()
    @     0x55c6a5cf1dc3  clang::Parser::ParseDeclOrFunctionDefInternal()
    @     0x55c6a5cf131b  clang::Parser::ParseDeclarationOrFunctionDefinition()
    @     0x55c6a5cf00a6  clang::Parser::ParseExternalDeclaration()
    @     0x55c6a5d3d2a7  clang::Parser::ParseInnerNamespace()
    @     0x55c6a5d3d3ea  clang::Parser::ParseInnerNamespace()
    @     0x55c6a5d3c242  clang::Parser::ParseNamespace()
    @     0x55c6a5d67d7b  clang::Parser::ParseDeclaration()
    @     0x55c6a5cefbae  clang::Parser::ParseExternalDeclaration()
    @     0x55c6a5cee1c8  clang::Parser::ParseTopLevelDecl()
    @     0x55c6a5ce93ce  clang::ParseAST()

And the stack trace dump from lldb (llvm revision 1778d3b):

    frame #8: 0x000055555ab81674 clang`clang::StandardConversionSequence::isPerfect(this=0x00007ffffffef450, C=0x00005092ffc1e000) const at Overload.h:439:9
    frame #9: 0x000055555ab5f522 clang`clang::ImplicitConversionSequence::isPerfect(this=<unavailable>, C=<unavailable>) const at Overload.h:790:39
    frame #10: 0x000055555ab5f513 clang`clang::OverloadCandidate::isPerfectMatch(this=0x00007ffffffee370, Ctx=0x00005092ffc1e000) const at Overload.h:1039:38
    frame #11: 0x000055555ab5f4db clang`clang::OverloadCandidateSet::PerfectViableFunction(this=0x00007ffffffee168, S=0x00005092ffd24000, Loc=<unavailable>, Best=0x00007fffffff02b0) at SemaOverload.cpp:11258:14
    frame #12: 0x000055555ab4c24f clang`clang::OverloadCandidateSet::BestViableFunction(this=0x00007ffffffee168, S=0x00005092ffd24000, Loc=(ID = 322271), Best=0x00007fffffff02b0) at SemaOverload.cpp:11243:5
    frame #13: 0x000055555ab713a2 clang`clang::Sema::BuildCallToMemberFunction(this=0x00005092ffd24000, S=<unavailable>, MemExprE=0x00005092ff728228, LParenLoc=(ID = 322301), Args=clang::MultiExprArg @ 0x00007fffffff02d0, RParenLoc=(ID = 322436), ExecConfig=0x0000000000000000, IsExecConfig=<unavailable>, AllowRecovery=true) at SemaOverload.cpp:16073:26
    frame #14: 0x000055555a70cdf1 clang`clang::Sema::BuildCallExpr(this=0x00005092ffd24000, Scope=0x00005092ffce9440, Fn=<unavailable>, LParenLoc=(ID = 322301), ArgExprs=clang::MultiExprArg @ 0x000070b4f5b1b060, RParenLoc=(ID = 322436), ExecConfig=0x0000000000000000, IsExecConfig=<unavailable>, AllowRecovery=<unavailable>) at SemaExpr.cpp:0
    frame #15: 0x000055555a727947 clang`clang::Sema::ActOnCallExpr(this=0x00005092ffd24000, Scope=<unavailable>, Fn=<unavailable>, LParenLoc=<unavailable>, ArgExprs=<unavailable>, RParenLoc=(ID = 322436), ExecConfig=0x0000000000000000) at SemaExpr.cpp:6521:7
    frame #16: 0x000055555a11c21d clang`clang::Parser::ParsePostfixExpressionSuffix(this=0x00005092ffc08880, LHS=<unavailable>) at ParseExpr.cpp:1931:23
    frame #17: 0x000055555a11e4a8 clang`clang::Parser::ParseCastExpression(this=0x00005092ffc08880, ParseKind=AnyCastExpr, isAddressOfOperand=<unavailable>, NotCastExpr=0x00007fffffff1e97, isTypeCast=<unavailable>, isVectorLiteral=<unavailable>, NotPrimaryExpression=0x0000000000000000) at ParseExpr.cpp:1648:9
    frame #18: 0x000055555a11969d clang`clang::Parser::ParseCastExpression(this=<unavailable>, ParseKind=AnyCastExpr, isAddressOfOperand=false, isTypeCast=<unavailable>, isVectorLiteral=false, NotPrimaryExpression=0x0000000000000000) at ParseExpr.cpp:593:20
    frame #19: 0x000055555a11967e clang`clang::Parser::ParseAssignmentExpression(this=<unavailable>, isTypeCast=<unavailable>) at ParseExpr.cpp:88:7
    frame #20: 0x000055555a11957e clang`clang::Parser::ParseExpression(this=<unavailable>, isTypeCast=<unavailable>) at ParseExpr.cpp:47:18
    frame #21: 0x000055555a1b8f1e clang`clang::Parser::ParseExprStatement(this=<unavailable>, StmtCtx=Compound) at ParseStmt.cpp:513:19
    frame #22: 0x000055555a1b82f8 clang`clang::Parser::ParseStatementOrDeclarationAfterAttributes(this=0x00005092ffc08880, Stmts=0x00007fffffff2420, StmtCtx=Compound, TrailingElseLoc=0x0000000000000000, CXX11Attrs=0x00007fffffff2160, GNUAttrs=0x00007fffffff20d0) at ParseStmt.cpp:241:14
    frame #23: 0x000055555a1b6291 clang`clang::Parser::ParseStatementOrDeclaration(this=0x00005092ffc08880, Stmts=0x00007fffffff2420, StmtCtx=Compound, TrailingElseLoc=0x0000000000000000) at ParseStmt.cpp:74:20
    frame #24: 0x000055555a1c20d5 clang`clang::Parser::ParseCompoundStatementBody(this=0x00005092ffc08880, isStmtExpr=false) at ParseStmt.cpp:1151:11
    frame #25: 0x000055555a1c2ee3 clang`clang::Parser::ParseFunctionStatementBody(this=0x00005092ffc08880, Decl=0x00005092ff70c388, BodyScope=0x00007fffffff2890) at ParseStmt.cpp:2389:21
    frame #26: 0x000055555a0f9573 clang`clang::Parser::ParseFunctionDefinition(this=0x00005092ffc08880, D=0x00007fffffff2978, TemplateInfo=0x00007fffffff4090, LateParsedAttrs=0x00007fffffff3f30) at Parser.cpp:1450:10
    frame #27: 0x000055555a170a0e clang`clang::Parser::ParseDeclGroup(this=0x00005092ffc08880, DS=0x00007fffffff4158, Context=File, Attrs=<unavailable>, TemplateInfo=0x00007fffffff4090, DeclEnd=0x0000000000000000, FRI=0x0000000000000000) at ParseDecl.cpp:0
    frame #28: 0x000055555a0f7f43 clang`clang::Parser::ParseDeclOrFunctionDefInternal(this=0x00005092ffc08880, Attrs=0x00007fffffff4700, DeclSpecAttrs=0x00007fffffff4670, DS=0x00007fffffff4158, AS=AS_none) at Parser.cpp:1188:10
    frame #29: 0x000055555a0f749b clang`clang::Parser::ParseDeclarationOrFunctionDefinition(this=0x00005092ffc08880, Attrs=0x00007fffffff4700, DeclSpecAttrs=0x00007fffffff4670, DS=0x0000000000000000, AS=AS_none) at Parser.cpp:1210:12
    frame #30: 0x000055555a0f6226 clang`clang::Parser::ParseExternalDeclaration(this=0x00005092ffc08880, Attrs=<unavailable>, DeclSpecAttrs=<unavailable>, DS=<unavailable>) at Parser.cpp:1033:14
    frame #31: 0x000055555a143427 clang`clang::Parser::ParseInnerNamespace(this=0x00005092ffc08880, InnerNSs=0x00007fffffff4de0, index=1, InlineLoc=0x00007fffffff4e9c, attrs=0x00007fffffff4ca0, Tracker=0x00007fffffff4d90) at ParseDeclCXX.cpp:242:7
    frame #32: 0x000055555a14356a clang`clang::Parser::ParseInnerNamespace(this=0x00005092ffc08880, InnerNSs=0x00007fffffff4de0, index=1, InlineLoc=0x00007fffffff4e9c, attrs=0x00007fffffff4ca0, Tracker=0x00007fffffff4d90) at ParseDeclCXX.cpp:264:3
    frame #33: 0x000055555a1423c2 clang`clang::Parser::ParseNamespace(this=0x00005092ffc08880, Context=<unavailable>, DeclEnd=0x00007fffffff5150, InlineLoc=(ID = 0)) at ParseDeclCXX.cpp:220:3
    frame #34: 0x000055555a16defb clang`clang::Parser::ParseDeclaration(this=0x00005092ffc08880, Context=File, DeclEnd=0x00007fffffff5150, DeclAttrs=0x00007fffffff52d0, DeclSpecAttrs=0x00007fffffff5230, DeclSpecStart=0x0000000000000000) at ParseDecl.cpp:0
    frame #35: 0x000055555a0f5d2e clang`clang::Parser::ParseExternalDeclaration(this=0x00005092ffc08880, Attrs=0x00007fffffff52d0, DeclSpecAttrs=0x00007fffffff5230, DS=0x0000000000000000) at SourceLocation.h:0:10
    frame #36: 0x000055555a0f4348 clang`clang::Parser::ParseTopLevelDecl(this=0x00005092ffc08880, Result=0x00007fffffff53e8, ImportState=0x00007fffffff53e4) at Parser.cpp:746:12
    frame #37: 0x000055555a0ef54e clang`clang::ParseAST(S=0x00005092ffd24000, PrintStats=false, SkipFunctionBodies=<unavailable>) at ParseAST.cpp:171:20

@cor3ntin
Copy link
Contributor Author

@alexfh Unfortunately, I will need a repro. I'm very curious to see what case we forgot to account for. Thanks in advance!

@alexfh
Copy link
Contributor

alexfh commented May 15, 2025

Reduced test case: https://gcc.godbolt.org/z/qG1Yv35rb

@alexfh
Copy link
Contributor

alexfh commented May 15, 2025

Reduced test case: https://gcc.godbolt.org/z/qG1Yv35rb

@cor3ntin ^^

@cor3ntin
Copy link
Contributor Author

Thanks, I will look into it today

cor3ntin added a commit to cor3ntin/llvm-project that referenced this pull request May 15, 2025
Function pointers can have an identity conversion to
a pointer to member function if they are resolved to
a member function.

Fix a regression introduced by llvm#136203
cor3ntin added a commit to cor3ntin/llvm-project that referenced this pull request May 15, 2025
Function pointers can have an identity conversion to
a pointer to member function if they are resolved to
a member function.

Fix a regression introduced by llvm#136203
cor3ntin added a commit that referenced this pull request May 15, 2025
Function pointers can have an identity conversion to a pointer to member
function if they are resolved to a member function.

Fix a regression introduced by #136203
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"
Projects
None yet
4 participants