This is an archive of the discontinued LLVM Phabricator instance.

[clang] Do not crash on undefined template partial specialization
ClosedPublic

Authored by Fznamznon on Apr 14 2023, 5:19 AM.

Details

Summary

Before checking that template partial specialization is "reachable",
ensure it exists.

Fixes https://github.com/llvm/llvm-project/issues/61356

Diff Detail

Event Timeline

Fznamznon created this revision.Apr 14 2023, 5:19 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 14 2023, 5:19 AM
Fznamznon requested review of this revision.Apr 14 2023, 5:19 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 14 2023, 5:19 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
erichkeane added inline comments.Apr 14 2023, 6:07 AM
clang/lib/Sema/SemaCXXScopeSpec.cpp
134–135

I would expect 'hasReachableDefinition' to check boht reachable AND definition :)

That said, I doubt the 'missing import' error is an appropriate one here.

clang/test/SemaCXX/undefined-partial-specialization.cpp
13

I don't think this is correct. The diagnostic is inaccurate, it DOES refer to a class template partial specialization (I can see it on line 9!), but the problem is that it is incomplete.

Fznamznon added inline comments.Apr 14 2023, 6:21 AM
clang/lib/Sema/SemaCXXScopeSpec.cpp
134–135

I would expect 'hasReachableDefinition' to check boht reachable AND definition :)

Well, it is implemented in a way that it actually expects definition to be present. In some other places where 'hasReachableDefinition' is called there is also a check that definition exists prior the call.

Fznamznon marked an inline comment as not done.Apr 14 2023, 6:51 AM
Fznamznon added inline comments.
clang/test/SemaCXX/undefined-partial-specialization.cpp
13

Huh, it seems it was my change that made this diagnostic inaccurate. I was under impression that it shouldn't have done this.
For c++17 it used to say "error: out-of-line definition of 'foo' from class 'boo<type-parameter-0-0, true>' without definition" without crash. Now it is inaccurate for both c++17 and c++20. I'll look into this more.

erichkeane added inline comments.Apr 14 2023, 7:02 AM
clang/lib/Sema/SemaCXXScopeSpec.cpp
134–135

Hrmph, ok then. Perhaps it is not the right place to change things anyway.

clang/test/SemaCXX/undefined-partial-specialization.cpp
13

Yes, I would definitely expect the 'out-of-line-definition' diagnostic, like we do for non-partial specs, and the C++17 behavior. Interesting that we've messed this up for C++20, should be fun to track down/figure out!

Fznamznon updated this revision to Diff 513575.Apr 14 2023, 7:08 AM

Rebase, fix error message

Fznamznon added inline comments.Apr 14 2023, 7:11 AM
clang/test/SemaCXX/undefined-partial-specialization.cpp
13

Interesting that we've messed this up for C++20, should be fun to track down/figure out!

hasReachableDefinition calls hasAcceptableDefinition that early-exits if support for modules is not required.

erichkeane accepted this revision.Apr 14 2023, 7:11 AM
erichkeane added inline comments.
clang/test/SemaCXX/undefined-partial-specialization.cpp
2

nit: can you add a c++17 run line here too? Only 20 crashed, but I want to make sure these have hte same behavior.

This revision is now accepted and ready to land.Apr 14 2023, 7:11 AM
Fznamznon updated this revision to Diff 513581.Apr 14 2023, 7:16 AM

Test c++17 too

clang/test/SemaCXX/undefined-partial-specialization.cpp
2

Sure.

erichkeane accepted this revision.Apr 14 2023, 7:17 AM

Thanks! still LGTM.

shafik added inline comments.Apr 14 2023, 3:46 PM
clang/lib/Sema/SemaCXXScopeSpec.cpp
134–135

So I see in another location we are basically checking !isBeginDefined() and in another place hasCompleteDefinition(). It is not clear to me if these are all basically checking the same thing or if we should figure out what is the right thing to check and do that everywhere.

Fznamznon added inline comments.Apr 17 2023, 4:20 AM
clang/lib/Sema/SemaCXXScopeSpec.cpp
134–135

I suppose you meant isBeingDefined(). So, IMO isBeingDefined() is not exactly the same as having a definition, this is set to true when TagDecl::startDefinition I suppose this should be done when parser meets a definition so at this point it can't be or have a complete definition. But at the places where !isBeingDefined() is checked prior hasReachableDefinition I saw a pointer representing a definition checked for not being null. Interestingly, hasReachableDefinition() early exits if isBeingDefined() returns true, so probably this check additional doesn't make sense at all.
Maybe we should just move both checks on having a definition and not being in the process of definition under hasReachableDefinition after all. That will require changing unrelated places, so I would prefer doing this separately in any case.

I can't grep hasCompleteDefinition() either, so I suppose you meant isCompleteDefinition(), I think this is basically the same thing as having definition and additionally the declaration through which the method called is checked that IT IS the definition. I'm not sure we have to require it here.

Fznamznon added inline comments.Apr 19 2023, 11:38 AM
clang/lib/Sema/SemaCXXScopeSpec.cpp
134–135

@shafik , are you satisfied with the explanation?

shafik accepted this revision.Apr 26 2023, 9:22 AM

LGTM

clang/lib/Sema/SemaCXXScopeSpec.cpp
134–135

I think we are good.