This is an archive of the discontinued LLVM Phabricator instance.

[clang] Enforce instantiation of constexpr template functions during non-constexpr evaluation
ClosedPublic

Authored by serge-sans-paille on Jun 18 2022, 4:51 AM.

Details

Summary

Otherwise these functions are not instantiated and we end up with an undefined
symbol.

Fix #55560

Diff Detail

Event Timeline

Herald added a project: Restricted Project. · View Herald TranscriptJun 18 2022, 4:51 AM
serge-sans-paille requested review of this revision.Jun 18 2022, 4:51 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 18 2022, 4:51 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript

I"m not 100% sure of the fix but it fixes bug #55560 and does not introduce regression :-/

(rebased on main branch)

aaron.ballman added reviewers: rsmith, Restricted Project.Jul 1 2022, 7:36 AM

It's a bummer that patch application failed on precommit CI for reasons unrelated to your patch (as best I can tell, anyway)... Also, please update the patch summary to have some more details about what your changing and why.

clang/test/SemaCXX/constexpr-late-instantiation.cpp
2
3

This test should be in CodeGenCXX, not SemaCXX. But there is a SemaCXX test I'd appreciate:

template <typename T>
constexpr T foo(T a);

int main() {
  int k = foo<int>(5); // Ok
  constexpr int j = foo<int>(5); // Not okay, a definition is needed for this
}

template <typename T>
constexpr T foo(T a) {
  return a;
}
erichkeane added inline comments.
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
4859

This condition seems a little aggressive, and will end up instantiating way more than just constexprs here, right? I guess my real question is what it is about the constexpr that makes us decide to skip the instantiation earlier.

shafik added a subscriber: shafik.Jul 2 2022, 1:59 PM

During the parsing of the assignment in main for the constexpr case we end up in Sema::MarkFunctionReferenced in particular this code:

else if (Func->isConstexpr())
    // Do not defer instantiations of constexpr functions, to avoid the
    // expression evaluator needing to call back into Sema if it sees a
    // call to such a function.
    InstantiateFunctionDefinition(PointOfInstantiation, Func);

And so I experimented with modifying Sema::InstantiateFunctionDefinition in particular:

else if (TSK == TSK_ExplicitInstantiationDefinition) {

And modified in this way:

else if (TSK == TSK_ExplicitInstantiationDefinition || (Function->isConstexpr() && !Recursive)) {

This seems more targeted, reflects what I think is the intent and passes check-clang as well.

I also looked at the non-constexpr case:

template <typename T>
T foo(T a);

int main() {
  int k = foo<int>(5);
}

template <typename T>
T foo(T a) {
  return a;
}

And in this case we hit Sema::InstantiateFunctionDefinition from Sema::PerformPendingInstantiations which is called by Sema::ActOnEndOfTranslationUnitFragment and so by this time we have seen the definition already.

Pinging about updates to this, because if this really does fix https://github.com/llvm/llvm-project/issues/55560, I think we want to get that fix into Clang 15. The release branch point is coming up pretty soon (https://discourse.llvm.org/t/llvm-15-0-0-release-schedule/63495/10).

serge-sans-paille retitled this revision from [clang] enforce instantiation of constexpr template functions to [clang] Enforce instantiation of constexpr template functions during non-constexpr evaluation.
serge-sans-paille edited the summary of this revision. (Show Details)

@shafik: I've implemented your patch which indeed looks closer to the original intent
@aaron.ballman : test case and code updated.

Can you also add a release note for the fix?

clang/test/SemaCXX/constexpr-late-instantiation.cpp
2
9

+ release note
+ take review into account

aaron.ballman accepted this revision.Jul 8 2022, 10:29 AM

LGTM aside from some test changes, assuming that precommit CI comes back green.

clang/docs/ReleaseNotes.rst
184 ↗(On Diff #443276)
clang/test/SemaCXX/constexpr-late-instantiation.cpp
2

You can remove this comment since this is no longer testing the IR.

3

Oops, I missed that in my earlier suggestion!

This revision is now accepted and ready to land.Jul 8 2022, 10:29 AM

++review

clang/docs/ReleaseNotes.rst
184 ↗(On Diff #443276)

Thanks you for removing this french touch ;-)

shafik accepted this revision.Jul 8 2022, 1:58 PM

LGTM, thank you!