[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
alexfh wrote: Thanks! The fix resolves the crash, but the original code still doesn't compile. See https://github.com/llvm/llvm-project/pull/108491#issuecomment-2350634130 https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
mizvekov wrote: @alexfh Thanks, fixed in https://github.com/llvm/llvm-project/pull/108491 https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
mizvekov wrote: Thanks for the repro! I am taking a look. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
alexfh wrote: Here's a reduced test case: https://gcc.godbolt.org/z/jxer3W39W As usual, it's hard to say if the code got invalid during automatic reduction, but it at least compiles well with clang before this commit. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
alexfh wrote: Hi @mizvekov, we started seeing crashes after this commit. I'm working on a shareable test case, but here's the assertion failure and the stack trace: ``` assert.h assertion failed at llvm-project/clang/lib/AST/TemplateName.cpp:184 in TemplateDecl *clang::TemplateName::getAsTemplateDecl(bool) const: Name.getAsDeducedTemplateName () == nullptr && "Unexpected canonical DeducedTemplateName; Did you mean to use " "getTemplateDeclAndDefaultArgs instead?" @ 0x559dafb2e734 __assert_fail @ 0x559dac2d2534 clang::TemplateName::getAsTemplateDecl() @ 0x559dab8f5744 (anonymous namespace)::TemplateInstantiator::TransformTemplateName() @ 0x559dab94e9a2 clang::TreeTransform<>::TransformTemplateSpecializationType() @ 0x559dab8e7f9f clang::TreeTransform<>::TransformType() @ 0x559dab94ad68 clang::TreeTransform<>::TransformElaboratedType() @ 0x559dab8e80a5 clang::TreeTransform<>::TransformType() @ 0x559dab8e7a0b clang::TreeTransform<>::TransformType() @ 0x559dab8e8790 clang::TreeTransform<>::TransformType() @ 0x559dab8e8690 clang::Sema::SubstType() @ 0x559dab6f4796 clang::Sema::CheckTemplateIdType() @ 0x559dab94a6d1 clang::TreeTransform<>::TransformDependentTemplateSpecializationType() @ 0x559dab8e815f clang::TreeTransform<>::TransformType() @ 0x559dab8e8ebe clang::Sema::SubstFunctionDeclType() @ 0x559dab985787 clang::TemplateDeclInstantiator::SubstFunctionType() @ 0x559dab98386d clang::TemplateDeclInstantiator::VisitFunctionDecl() @ 0x559dab9de2f3 llvm::function_ref<>::callback_fn<>() @ 0x559daace13df clang::Sema::runWithSufficientStackSpace() @ 0x559dab98e1c8 clang::Sema::SubstDecl() @ 0x559dab7d6bc1 clang::Sema::FinishTemplateArgumentDeduction() @ 0x559dab866702 llvm::function_ref<>::callback_fn<>() @ 0x559daace13df clang::Sema::runWithSufficientStackSpace() @ 0x559dab7da125 clang::Sema::DeduceTemplateArguments() @ 0x559dab64655f clang::Sema::AddTemplateOverloadCandidate() @ 0x559dab65b2e4 AddOverloadedCallCandidate() @ 0x559dab65b167 clang::Sema::AddOverloadedCallCandidates() @ 0x559dab65b735 clang::Sema::buildOverloadedCallSet() @ 0x559dab65bb92 clang::Sema::BuildOverloadedCallExpr() @ 0x559dab13092c clang::Sema::BuildCallExpr() @ 0x559dab14af37 clang::Sema::ActOnCallExpr() @ 0x559daa9f72b4 clang::Parser::ParsePostfixExpressionSuffix() @ 0x559daa9f9078 clang::Parser::ParseCastExpression() @ 0x559daa9f44b2 clang::Parser::ParseAssignmentExpression() @ 0x559daaa4f9a0 clang::Parser::ParseDeclarationAfterDeclaratorAndAttributes() @ 0x559daaa4cf26 clang::Parser::ParseDeclGroup() @ 0x559daaa4b310 clang::Parser::ParseSimpleDeclaration() @ 0x559daaa4aa30 clang::Parser::ParseDeclaration() @ 0x559daaa96433 clang::Parser::ParseStatementOrDeclarationAfterAttributes() @ 0x559daaa9428e clang::Parser::ParseStatementOrDeclaration() @ 0x559daaa9f8f3 clang::Parser::ParseCompoundStatementBody() @ 0x559daaa94f57 clang::Parser::ParseStatementOrDeclarationAfterAttributes() @ 0x559daaa9428e clang::Parser::ParseStatementOrDeclaration() @ 0x559daaa9b8c0 clang::Parser::ParseForStatement() @ 0x559daaa94e07 clang::Parser::ParseStatementOrDeclarationAfterAttributes() @ 0x559daaa9428e clang::Parser::ParseStatementOrDeclaration() @ 0x559daaa9f8f3 clang::Parser::ParseCompoundStatementBody() @ 0x559daaa94f57 clang::Parser::ParseStatementOrDeclarationAfterAttributes() @ 0x559daaa9428e clang::Parser::ParseStatementOrDeclaration() @ 0x559daaa9b8c0 clang::Parser::ParseForStatement() @ 0x559daaa94e07 clang::Parser::ParseStatementOrDeclarationAfterAttributes() @ 0x559daaa9428e clang::Parser::ParseStatementOrDeclaration() @ 0x559daaa9f8f3 clang::Parser::ParseCompoundStatementBody() @ 0x559daaa94f57 clang::Parser::ParseStatementOrDeclarationAfterAttributes() @ 0x559daaa9428e clang::Parser::ParseStatementOrDeclaration() @ 0x559daaa9b8c0 clang::Parser::ParseForStatement() @ 0x559daaa94e07 clang::Parser::ParseStatementOrDeclarationAfterAttributes() @ 0x559daaa9428e clang::Parser::ParseStatementOrDeclaration() @ 0x559daaa9f8f3 clang::Parser::ParseCompoundStatementBody() @ 0x559d0c70 clang::Parser::ParseFunctionStatementBody() @ 0x559daa9d361c clang::Parser::ParseFunctionDefinition() @ 0x559daaa4d89b clang::Parser::ParseDeclGroup() @ 0x559daa9d1ea8 clang::Parser::ParseDeclOrFunctionDefInternal() @ 0x559daa9d13d2 clang::Parser::ParseDeclarationOrFunctionDefinition() @ 0x559daa9d0106 clang::Parser::ParseExternalDeclaration() @ 0x559daaa1fba7 clang::Parser::Par
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
https://github.com/mizvekov closed https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -6753,16 +6758,41 @@ ASTContext::getNameForTemplate(TemplateName Name, case TemplateName::UsingTemplate: return DeclarationNameInfo(Name.getAsUsingShadowDecl()->getDeclName(), NameLoc); + case TemplateName::DeducedTemplate: { +DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName(); +return getNameForTemplate(DTS->getUnderlying(), NameLoc); + } } llvm_unreachable("bad template name kind!"); } -TemplateName -ASTContext::getCanonicalTemplateName(const TemplateName &Name) const { +static const TemplateArgument * +getDefaultTemplateArgumentOrNone(const NamedDecl *P) { + auto handleParam = [](auto *TP) -> const TemplateArgument * { +if (!TP->hasDefaultArgument()) + return nullptr; +return &TP->getDefaultArgument().getArgument(); + }; + switch (P->getKind()) { + case NamedDecl::TemplateTypeParm: +return handleParam(cast(P)); + case NamedDecl::NonTypeTemplateParm: +return handleParam(cast(P)); + case NamedDecl::TemplateTemplateParm: +return handleParam(cast(P)); + default: +llvm_unreachable("Unexpected template parameter kind"); + } +} mizvekov wrote: We'd have to break TypeDecl, DeclaratorDecl, TemplateDecl, etc into mixins. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -645,6 +645,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, // It is sufficient to check value of getAsTemplateDecl. break; + case TemplateName::DeducedTemplate: + // FIXME: We can't reach here. + llvm_unreachable("unimplemented"); cor3ntin wrote: Hum, fair enough. It's hard to me to understand how we could ever get there though https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -2304,6 +2306,15 @@ class ASTContext : public RefCountedBase { unsigned Index, bool Final) const; + /// Represents a TemplateName which had some of it's default arguments cor3ntin wrote: ```suggestion /// Represents a TemplateName which had some of its default arguments ``` https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
https://github.com/cor3ntin edited https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -6753,16 +6758,41 @@ ASTContext::getNameForTemplate(TemplateName Name, case TemplateName::UsingTemplate: return DeclarationNameInfo(Name.getAsUsingShadowDecl()->getDeclName(), NameLoc); + case TemplateName::DeducedTemplate: { +DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName(); +return getNameForTemplate(DTS->getUnderlying(), NameLoc); + } } llvm_unreachable("bad template name kind!"); } -TemplateName -ASTContext::getCanonicalTemplateName(const TemplateName &Name) const { +static const TemplateArgument * +getDefaultTemplateArgumentOrNone(const NamedDecl *P) { + auto handleParam = [](auto *TP) -> const TemplateArgument * { +if (!TP->hasDefaultArgument()) + return nullptr; +return &TP->getDefaultArgument().getArgument(); + }; + switch (P->getKind()) { + case NamedDecl::TemplateTypeParm: +return handleParam(cast(P)); + case NamedDecl::NonTypeTemplateParm: +return handleParam(cast(P)); + case NamedDecl::TemplateTemplateParm: +return handleParam(cast(P)); + default: +llvm_unreachable("Unexpected template parameter kind"); + } +} cor3ntin wrote: Not in this PR, but i wonder if we should have a base class for all these types https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
https://github.com/cor3ntin approved this pull request. Only nits at this point. Sorry the review took this long, it was a pretty large PR. Thanks for working on it! https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -1555,6 +1499,11 @@ DeduceTemplateBases(Sema &S, const CXXRecordDecl *RD, return TemplateDeductionResult::Success; } +static PartialOrderingKind +degradeCallPartialOrderingKind(PartialOrderingKind POK) { + return std::min(POK, PartialOrderingKind::NonCall); +} + cor3ntin wrote: Can we get a comment here? https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -6803,9 +6809,6 @@ bool CXXNameMangler::mangleSubstitution(QualType T) { } bool CXXNameMangler::mangleSubstitution(TemplateName Template) { - if (TemplateDecl *TD = Template.getAsTemplateDecl()) -return mangleSubstitution(TD); - mizvekov wrote: This one looks like it was a rebasing mistake. Restored. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -2143,15 +2107,17 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( unsigned SubTDF = TDF & TDF_IgnoreQualifiers; if (auto Result = DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, PPT, APT, Info, Deduced, SubTDF, - /*PartialOrdering=*/false, /*DeducedFromArrayBound=*/false, - HasDeducedAnyParam); + POK != PartialOrderingKind::None ? PartialOrderingKind::NonCall mizvekov wrote: Yes, this is slightly complicated because I tried to do an enum instead of adding another bool. Basically we want to add a new flag to the deduction functions saying that we are in a partial ordering context, which needs to be propagated deeply. We already had one such flag, but this one was for supporting deduction of function calls, and it had shallow propagation. So this is the transfer function for the shallow Call Partial ordering mode into the deep non-call mode. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -139,28 +165,63 @@ TemplateName::NameKind TemplateName::getKind() const { return AssumedTemplate; if (uncommon->getAsSubstTemplateTemplateParm()) return SubstTemplateTemplateParm; + if (uncommon->getAsDeducedTemplateName()) +return DeducedTemplate; + + assert(uncommon->getAsSubstTemplateTemplateParmPack() != nullptr); return SubstTemplateTemplateParmPack; } -TemplateDecl *TemplateName::getAsTemplateDecl() const { - if (Decl *TemplateOrUsing = Storage.dyn_cast()) { -if (UsingShadowDecl *USD = dyn_cast(TemplateOrUsing)) - return cast(USD->getTargetDecl()); - -assert(isa(TemplateOrUsing)); -return cast(TemplateOrUsing); - } +TemplateDecl *TemplateName::getAsTemplateDecl(bool IgnoreDeduced) const { mizvekov wrote: I am not sure which part you were talking about, but a DeducedTemplateName is sugar when it appears in the TemplateName of a TemplateSpecializationType, so we need this new logic here. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -5327,9 +5332,29 @@ bool Sema::CheckTemplateArgumentList( SmallVector CanonicalArgumentPack; unsigned ArgIdx = 0, NumArgs = NewArgs.size(); LocalInstantiationScope InstScope(*this, true); - for (TemplateParameterList::iterator Param = Params->begin(), - ParamEnd = Params->end(); - Param != ParamEnd; /* increment in loop */) { + for (TemplateParameterList::iterator ParamBegin = Params->begin(), + ParamEnd = Params->end(), + Param = ParamBegin; + Param != ParamEnd; + /* increment in loop */) { +if (size_t ParamIdx = Param - ParamBegin; +DefaultArgs && ParamIdx >= DefaultArgs.StartPos) { + // All written arguments should have been consumed by this point. + assert(ArgIdx == NumArgs && "bad default argument deduction"); + // FIXME: Don't ignore parameter packs. mizvekov wrote: This is already tested and tackled in the next patch in the series, the P0522 complete implementation one. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -1198,6 +1198,18 @@ void TextNodeDumper::dumpBareTemplateName(TemplateName TN) { dumpTemplateName(STS->getReplacement(), "replacement"); return; } + case TemplateName::DeducedTemplate: { +OS << " deduced"; +const DeducedTemplateStorage *DTS = TN.getAsDeducedTemplateName(); +dumpTemplateName(DTS->getUnderlying(), "underlying"); +AddChild("defaults", [=] { + auto [StartPos, Args] = DTS->getDefaultArguments(); + OS << " start " << StartPos; + for (const TemplateArgument &Arg : Args) +AddChild([=] { Visit(Arg, SourceRange()); }); +}); +return; + } mizvekov wrote: Yeah, this could be tested in ast-dump tests before we restricted this to partial ordering. Now it only helps in debugging there. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -139,28 +165,63 @@ TemplateName::NameKind TemplateName::getKind() const { return AssumedTemplate; if (uncommon->getAsSubstTemplateTemplateParm()) return SubstTemplateTemplateParm; + if (uncommon->getAsDeducedTemplateName()) +return DeducedTemplate; + + assert(uncommon->getAsSubstTemplateTemplateParmPack() != nullptr); return SubstTemplateTemplateParmPack; } -TemplateDecl *TemplateName::getAsTemplateDecl() const { - if (Decl *TemplateOrUsing = Storage.dyn_cast()) { -if (UsingShadowDecl *USD = dyn_cast(TemplateOrUsing)) - return cast(USD->getTargetDecl()); - -assert(isa(TemplateOrUsing)); -return cast(TemplateOrUsing); - } +TemplateDecl *TemplateName::getAsTemplateDecl(bool IgnoreDeduced) const { + TemplateName Name = *this; + while (std::optional UnderlyingOrNone = + Name.desugar(IgnoreDeduced)) +Name = *UnderlyingOrNone; - if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) -return QTN->getUnderlyingTemplate().getAsTemplateDecl(); + if (!IgnoreDeduced) +assert(Name.getAsDeducedTemplateName() == nullptr && + "Unexpected canonical DeducedTemplateName; Did you mean to use " + "getTemplateDeclAndDefaultArgs instead?"); - if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm()) -return sub->getReplacement().getAsTemplateDecl(); + return cast_if_present(Name.Storage.dyn_cast()); +} - if (UsingShadowDecl *USD = getAsUsingShadowDecl()) -return cast(USD->getTargetDecl()); +std::pair +TemplateName::getTemplateDeclAndDefaultArgs() const { + for (TemplateName Name = *this; /**/; /**/) { +if (Name.getKind() == TemplateName::DeducedTemplate) { + DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName(); + TemplateDecl *TD = + DTS->getUnderlying().getAsTemplateDecl(/*IgnoreDeduced=*/true); + DefaultArguments DefArgs = DTS->getDefaultArguments(); + if (TD && DefArgs) +assert(DefArgs.StartPos + DefArgs.Args.size() <= + TD->getTemplateParameters()->size()); + return {TD, DTS->getDefaultArguments()}; +} +if (std::optional UnderlyingOrNone = +Name.desugar(/*IgnoreDeduced=*/false)) { + Name = *UnderlyingOrNone; + continue; +} +return {cast_if_present(Name.Storage.dyn_cast()), {}}; + } +} - return nullptr; +std::optional TemplateName::desugar(bool IgnoreDeduced) const { mizvekov wrote: They were not fully fledged implemented like the other kinds of AST nodes. Their canonicalization plays by different rules, and this patch expands on that. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -326,6 +320,48 @@ namespace classes { // expected-error@-1 {{no matching function for call}} } } // namespace packs + namespace nested { mizvekov wrote: The test case from 100692 doesn't have anything interesting new on top of this one. There might be differences in the kinds of template arguments which have default deductions, but we already test all kinds when matching TTP to TTP, so I am not sure it would be worth doing a power set where we test every combination of matching with every kind. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -1371,11 +1371,17 @@ class TemplateDiff { /// argument info into a tree. void DiffTemplate(const TemplateSpecializationType *FromTST, const TemplateSpecializationType *ToTST) { +// FIXME: With P3310R0, A TST formed from a DeducedTemplateName might +// differ in template arguments which were not written. mizvekov wrote: It's still possible these types might appear in diagnostics, even if they don't make it to the final program. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -645,6 +645,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, // It is sufficient to check value of getAsTemplateDecl. break; + case TemplateName::DeducedTemplate: + // FIXME: We can't reach here. + llvm_unreachable("unimplemented"); mizvekov wrote: Well it's both, ideally we should implement this, but we don't implement other stuff that would even allow us to reach here. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -412,6 +445,30 @@ class SubstTemplateTemplateParmStorage std::optional PackIndex); }; +class DeducedTemplateStorage : public UncommonTemplateNameStorage, mizvekov wrote: This one is a too internal detail of how the different kinds of TemplateNames are implemented. Ie if we can't fit everything we need in one pointer, then we allocate separate storage for it. Might be more useful to document the DeducedTemplate itself. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -9219,7 +9222,8 @@ class Sema final : public SemaBase { /// \returns true if an error occurred, false otherwise. bool CheckTemplateArgumentList( TemplateDecl *Template, SourceLocation TemplateLoc, - TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, + TemplateArgumentListInfo &TemplateArgs, mizvekov wrote: The problem with the separate Sugared / Converted lists I already have an incomplete patch to address that, though I am currently working on something else. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -9219,7 +9222,8 @@ class Sema final : public SemaBase { /// \returns true if an error occurred, false otherwise. bool CheckTemplateArgumentList( TemplateDecl *Template, SourceLocation TemplateLoc, - TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, + TemplateArgumentListInfo &TemplateArgs, erichkeane wrote: There's enough repeated stuff though these interfaces here, I don't think I'd mind a followup that created an object to contain all the related stuff. For example, the Sugared/Canonical vectors shoudl probably be a vectro of TempalteArgument pairs (or more likely their own structure) or something? But I'm open to other ideas as well (agian in a followup). https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -139,28 +165,63 @@ TemplateName::NameKind TemplateName::getKind() const { return AssumedTemplate; if (uncommon->getAsSubstTemplateTemplateParm()) return SubstTemplateTemplateParm; + if (uncommon->getAsDeducedTemplateName()) +return DeducedTemplate; + + assert(uncommon->getAsSubstTemplateTemplateParmPack() != nullptr); return SubstTemplateTemplateParmPack; } -TemplateDecl *TemplateName::getAsTemplateDecl() const { - if (Decl *TemplateOrUsing = Storage.dyn_cast()) { -if (UsingShadowDecl *USD = dyn_cast(TemplateOrUsing)) - return cast(USD->getTargetDecl()); - -assert(isa(TemplateOrUsing)); -return cast(TemplateOrUsing); - } +TemplateDecl *TemplateName::getAsTemplateDecl(bool IgnoreDeduced) const { cor3ntin wrote: That change looks sort of unrelated? https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -139,28 +165,63 @@ TemplateName::NameKind TemplateName::getKind() const { return AssumedTemplate; if (uncommon->getAsSubstTemplateTemplateParm()) return SubstTemplateTemplateParm; + if (uncommon->getAsDeducedTemplateName()) +return DeducedTemplate; + + assert(uncommon->getAsSubstTemplateTemplateParmPack() != nullptr); return SubstTemplateTemplateParmPack; } -TemplateDecl *TemplateName::getAsTemplateDecl() const { - if (Decl *TemplateOrUsing = Storage.dyn_cast()) { -if (UsingShadowDecl *USD = dyn_cast(TemplateOrUsing)) - return cast(USD->getTargetDecl()); - -assert(isa(TemplateOrUsing)); -return cast(TemplateOrUsing); - } +TemplateDecl *TemplateName::getAsTemplateDecl(bool IgnoreDeduced) const { + TemplateName Name = *this; + while (std::optional UnderlyingOrNone = + Name.desugar(IgnoreDeduced)) +Name = *UnderlyingOrNone; - if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) -return QTN->getUnderlyingTemplate().getAsTemplateDecl(); + if (!IgnoreDeduced) +assert(Name.getAsDeducedTemplateName() == nullptr && + "Unexpected canonical DeducedTemplateName; Did you mean to use " + "getTemplateDeclAndDefaultArgs instead?"); - if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm()) -return sub->getReplacement().getAsTemplateDecl(); + return cast_if_present(Name.Storage.dyn_cast()); +} - if (UsingShadowDecl *USD = getAsUsingShadowDecl()) -return cast(USD->getTargetDecl()); +std::pair +TemplateName::getTemplateDeclAndDefaultArgs() const { + for (TemplateName Name = *this; /**/; /**/) { +if (Name.getKind() == TemplateName::DeducedTemplate) { + DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName(); + TemplateDecl *TD = + DTS->getUnderlying().getAsTemplateDecl(/*IgnoreDeduced=*/true); + DefaultArguments DefArgs = DTS->getDefaultArguments(); + if (TD && DefArgs) +assert(DefArgs.StartPos + DefArgs.Args.size() <= + TD->getTemplateParameters()->size()); + return {TD, DTS->getDefaultArguments()}; +} +if (std::optional UnderlyingOrNone = +Name.desugar(/*IgnoreDeduced=*/false)) { + Name = *UnderlyingOrNone; + continue; +} +return {cast_if_present(Name.Storage.dyn_cast()), {}}; + } +} - return nullptr; +std::optional TemplateName::desugar(bool IgnoreDeduced) const { cor3ntin wrote: I am surprise that we don't have something to desugar template names already? https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -645,6 +645,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, // It is sufficient to check value of getAsTemplateDecl. break; + case TemplateName::DeducedTemplate: + // FIXME: We can't reach here. + llvm_unreachable("unimplemented"); cor3ntin wrote: is it unreachable or just unimplemented? If deduced arguments are only used during partial ordering they should never need to be compared for structural equivalence... maybe. I am not actually sure, but the fix me and the strings should agree with each other! https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -134,11 +134,16 @@ static bool hasSameExtendedValue(llvm::APSInt X, llvm::APSInt Y) { return X == Y; } +/// What kind of PartialOrdering we're performing template argument deduction cor3ntin wrote: ```suggestion /// The kind of PartialOrdering we're performing template argument deduction ``` https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -1371,11 +1371,17 @@ class TemplateDiff { /// argument info into a tree. void DiffTemplate(const TemplateSpecializationType *FromTST, const TemplateSpecializationType *ToTST) { +// FIXME: With P3310R0, A TST formed from a DeducedTemplateName might +// differ in template arguments which were not written. cor3ntin wrote: I am not sure we need that fixme now https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -134,11 +134,16 @@ static bool hasSameExtendedValue(llvm::APSInt X, llvm::APSInt Y) { return X == Y; } +/// What kind of PartialOrdering we're performing template argument deduction +/// for (C++0x [temp.deduct.partial]). cor3ntin wrote: ```suggestion /// for (C++11 [temp.deduct.partial]). ``` https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -6803,9 +6809,6 @@ bool CXXNameMangler::mangleSubstitution(QualType T) { } bool CXXNameMangler::mangleSubstitution(TemplateName Template) { - if (TemplateDecl *TD = Template.getAsTemplateDecl()) -return mangleSubstitution(TD); - cor3ntin wrote: Can you explain that change? https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -9219,7 +9222,8 @@ class Sema final : public SemaBase { /// \returns true if an error occurred, false otherwise. bool CheckTemplateArgumentList( TemplateDecl *Template, SourceLocation TemplateLoc, - TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, + TemplateArgumentListInfo &TemplateArgs, cor3ntin wrote: Can we think about ways to simplify these interface in a subsequent patch? @AaronBallman @erichkeane for additional opinions https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -5327,9 +5332,29 @@ bool Sema::CheckTemplateArgumentList( SmallVector CanonicalArgumentPack; unsigned ArgIdx = 0, NumArgs = NewArgs.size(); LocalInstantiationScope InstScope(*this, true); - for (TemplateParameterList::iterator Param = Params->begin(), - ParamEnd = Params->end(); - Param != ParamEnd; /* increment in loop */) { + for (TemplateParameterList::iterator ParamBegin = Params->begin(), + ParamEnd = Params->end(), + Param = ParamBegin; + Param != ParamEnd; + /* increment in loop */) { +if (size_t ParamIdx = Param - ParamBegin; +DefaultArgs && ParamIdx >= DefaultArgs.StartPos) { + // All written arguments should have been consumed by this point. + assert(ArgIdx == NumArgs && "bad default argument deduction"); + // FIXME: Don't ignore parameter packs. cor3ntin wrote: Do we need a test/issue? https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -326,6 +320,48 @@ namespace classes { // expected-error@-1 {{no matching function for call}} } } // namespace packs + namespace nested { cor3ntin wrote: Do we need more tests? Maybe add the example from #100692 ? https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -6797,15 +6821,58 @@ ASTContext::getCanonicalTemplateName(const TemplateName &Name) const { canonArgPack, subst->getAssociatedDecl()->getCanonicalDecl(), subst->getFinal(), subst->getIndex()); } + case TemplateName::DeducedTemplate: { +assert(IgnoreDeduced == false); +DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName(); +DefaultArguments DefArgs = DTS->getDefaultArguments(); +TemplateName Underlying = DTS->getUnderlying(); + +TemplateName CanonUnderlying = +getCanonicalTemplateName(Underlying, /*IgnoreDeduced=*/true); +bool NonCanonical = CanonUnderlying != Underlying; +auto CanonArgs = +getCanonicalTemplateArguments(*this, DefArgs.Args, NonCanonical); + +ArrayRef Params = + CanonUnderlying.getAsTemplateDecl()->getTemplateParameters()->asArray(); +assert(CanonArgs.size() <= Params.size()); +// A deduced template name which deduces the same default arguments already +// declared in the underlying template, is the same template as the cor3ntin wrote: ```suggestion // declared in the underlying template is the same template as the ``` https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -6797,15 +6821,58 @@ ASTContext::getCanonicalTemplateName(const TemplateName &Name) const { canonArgPack, subst->getAssociatedDecl()->getCanonicalDecl(), subst->getFinal(), subst->getIndex()); } + case TemplateName::DeducedTemplate: { +assert(IgnoreDeduced == false); +DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName(); +DefaultArguments DefArgs = DTS->getDefaultArguments(); +TemplateName Underlying = DTS->getUnderlying(); + +TemplateName CanonUnderlying = +getCanonicalTemplateName(Underlying, /*IgnoreDeduced=*/true); +bool NonCanonical = CanonUnderlying != Underlying; +auto CanonArgs = +getCanonicalTemplateArguments(*this, DefArgs.Args, NonCanonical); + +ArrayRef Params = + CanonUnderlying.getAsTemplateDecl()->getTemplateParameters()->asArray(); +assert(CanonArgs.size() <= Params.size()); +// A deduced template name which deduces the same default arguments already +// declared in the underlying template, is the same template as the +// underlying template. We need need to note any arguments which differ from +// the corresponding declaration. If they are not the same, we must build a +// deduced template name. cor3ntin wrote: ```suggestion // underlying template. We need need to note any arguments which differ from // the corresponding declaration. If any argument differ, we build a // deduced template name. ``` https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -2143,15 +2107,17 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( unsigned SubTDF = TDF & TDF_IgnoreQualifiers; if (auto Result = DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, PPT, APT, Info, Deduced, SubTDF, - /*PartialOrdering=*/false, /*DeducedFromArrayBound=*/false, - HasDeducedAnyParam); + POK != PartialOrderingKind::None ? PartialOrderingKind::NonCall cor3ntin wrote: Can you explain that logic? And you do it in a whole bunch of places, how putting it a getPartialOrderingKindForTypeMatch() function, or modifying DeduceTemplateArgumentsByTypeMatch to do that transformation there? https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -1198,6 +1198,18 @@ void TextNodeDumper::dumpBareTemplateName(TemplateName TN) { dumpTemplateName(STS->getReplacement(), "replacement"); return; } + case TemplateName::DeducedTemplate: { +OS << " deduced"; +const DeducedTemplateStorage *DTS = TN.getAsDeducedTemplateName(); +dumpTemplateName(DTS->getUnderlying(), "underlying"); +AddChild("defaults", [=] { + auto [StartPos, Args] = DTS->getDefaultArguments(); + OS << " start " << StartPos; + for (const TemplateArgument &Arg : Args) +AddChild([=] { Visit(Arg, SourceRange()); }); +}); +return; + } cor3ntin wrote: When would these things be printed? I guess if you call dump() while debugging partial ordering? Do we need a test? https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -412,6 +445,30 @@ class SubstTemplateTemplateParmStorage std::optional PackIndex); }; +class DeducedTemplateStorage : public UncommonTemplateNameStorage, cor3ntin wrote: I think a comment describing when this is useful would be beneficial https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
https://github.com/erichkeane commented: I've not done as in depth of a review as Corentin, but I approve of the direction here, I think the approach is correct, and most of the changes are fairly mechanical. So once Corentin is happy with the changes, so am I. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
https://github.com/mizvekov edited https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
Endilll wrote: Sure. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
mizvekov wrote: After we fork for clang-20, we can entirely remove `frelaxed-template-template-args`, and so won't need to worry about testing that non-conforming mode. Would it be reasonable to postpone that until then? https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
Endilll wrote: Now that you published P3310R0, this test can be moved to DR tests with a status `// cwg2398: 19 drafting P3310R0`. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/94981 >From b238961ba3a174d7dc211caf36ff8fd6c8429a76 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Mon, 20 May 2024 01:15:03 -0300 Subject: [PATCH] [clang] Implement CWG2398 provisional TTP matching to class templates This extends default argument deduction to cover class templates as well, and also applies outside of partial ordering, adding to the provisional wording introduced in https://github.com/llvm/llvm-project/pull/89807. This solves some ambuguity introduced in P0522 regarding how template template parameters are partially ordered, and should reduce the negative impact of enabling `-frelaxed-template-template-args` by default. Given the following example: ```C++ template struct A; template struct B; template class TT1, class T5> struct B>; // #1 template struct B>; // #2 template struct B>; ``` Prior to P0522, `#2` was picked. Afterwards, this became ambiguous. This patch restores the pre-P0522 behavior, `#2` is picked again. As the consequences are not restricted to partial ordering, the following code becomes valid: ```C++ template struct A {}; A v; template class TT> void f(TT); // OK: TT picks 'float' as the default argument for the second parameter. void g() { f(v); } ``` Also, since 'f' deduced from `A` is different from 'f' deduced from `A`, this implements an additional mangling rule. --- Since this changes provisional implementation of CWG2398 which has not been released yet, and already contains a changelog entry, we don't provide a changelog entry here. --- clang-tools-extra/clangd/DumpAST.cpp | 1 + .../clangd/SemanticHighlighting.cpp | 1 + clang/include/clang/AST/ASTContext.h | 11 +- clang/include/clang/AST/ASTImporter.h | 5 + clang/include/clang/AST/DependenceFlags.h | 5 + clang/include/clang/AST/PropertiesBase.td | 17 ++ clang/include/clang/AST/TemplateName.h| 63 ++- clang/include/clang/Sema/Sema.h | 10 +- clang/lib/AST/ASTContext.cpp | 153 +--- clang/lib/AST/ASTDiagnostic.cpp | 45 +++-- clang/lib/AST/ASTImporter.cpp | 15 ++ clang/lib/AST/ASTStructuralEquivalence.cpp| 3 + clang/lib/AST/Decl.cpp| 3 +- clang/lib/AST/ItaniumMangle.cpp | 20 ++- clang/lib/AST/ODRHash.cpp | 1 + clang/lib/AST/TemplateName.cpp| 163 ++ clang/lib/AST/TextNodeDumper.cpp | 12 ++ clang/lib/AST/Type.cpp| 3 +- clang/lib/AST/TypePrinter.cpp | 3 +- clang/lib/Sema/SemaDeclCXX.cpp| 9 +- clang/lib/Sema/SemaTemplate.cpp | 63 +-- clang/lib/Sema/SemaTemplateDeduction.cpp | 158 + .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 24 +-- .../CXX/temp/temp.decls/temp.alias/p2.cpp | 5 +- clang/test/CodeGenCXX/mangle-cwg2398.cpp | 11 ++ clang/test/SemaTemplate/cwg2398.cpp | 62 +-- clang/tools/libclang/CIndex.cpp | 3 + clang/unittests/AST/ASTImporterTest.cpp | 17 ++ 28 files changed, 629 insertions(+), 257 deletions(-) create mode 100644 clang/test/CodeGenCXX/mangle-cwg2398.cpp diff --git a/clang-tools-extra/clangd/DumpAST.cpp b/clang-tools-extra/clangd/DumpAST.cpp index 9a525efb938e8..e605f82e91fe4 100644 --- a/clang-tools-extra/clangd/DumpAST.cpp +++ b/clang-tools-extra/clangd/DumpAST.cpp @@ -187,6 +187,7 @@ class DumpVisitor : public RecursiveASTVisitor { TEMPLATE_KIND(SubstTemplateTemplateParm); TEMPLATE_KIND(SubstTemplateTemplateParmPack); TEMPLATE_KIND(UsingTemplate); + TEMPLATE_KIND(DeducedTemplate); #undef TEMPLATE_KIND } llvm_unreachable("Unhandled NameKind enum"); diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index a366f1331c2d3..e6d16af2495fe 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -1120,6 +1120,7 @@ class CollectExtraHighlightings case TemplateName::SubstTemplateTemplateParm: case TemplateName::SubstTemplateTemplateParmPack: case TemplateName::UsingTemplate: +case TemplateName::DeducedTemplate: // Names that could be resolved to a TemplateDecl are handled elsewhere. break; } diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index de86cb5e9d7fc..837bcacbc0bfc 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -262,6 +262,8 @@ class ASTContext : public RefCountedBase { mutable llvm::ContextualFoldingSet SubstTemplateTemplateParmPacks; + mutable llvm::ContextualFoldingSet + DeducedTemplates; mutable llvm::ContextualFoldingSet Arr
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -9219,7 +9222,8 @@ class Sema final : public SemaBase { /// \returns true if an error occurred, false otherwise. bool CheckTemplateArgumentList( TemplateDecl *Template, SourceLocation TemplateLoc, - TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, + TemplateArgumentListInfo &TemplateArgs, mizvekov wrote: Yeah. One issue I have often had with these functions with large amount of both defaulted and non-defaulted parameters, is that you would want to extend it by changing the signature, then arguments would match parameters incorrectly, but this would not cause a hard error on all of the call sites. I could have easily added DefaultArgs as defaulted empty here, but chose not to due to this reason. Besides that, overloading functions with such huge numbers of parameters creates some confusion as well. I'd slightly prefer if we avoided that, but don't have strong enough feelings to go on a crusade against it. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
https://github.com/cor3ntin edited https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -9219,7 +9222,8 @@ class Sema final : public SemaBase { /// \returns true if an error occurred, false otherwise. bool CheckTemplateArgumentList( TemplateDecl *Template, SourceLocation TemplateLoc, - TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, + TemplateArgumentListInfo &TemplateArgs, cor3ntin wrote: ```cpp bool CheckTemplateArgumentList( TemplateDecl *Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, SmallVectorImpl &SugaredConverted, SmallVectorImpl &CanonicalConverted, bool UpdateArgsWithConversions = true, bool *ConstraintsNotSatisfied = nullptr, bool PartialOrderingTTP = false, const DefaultArguments * DefaultArgs = nullptr); bool CheckTemplateArgumentList( TemplateDecl *Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, const DefaultArguments & DefaultArgs, SmallVectorImpl &SugaredConverted, SmallVectorImpl &CanonicalConverted) { return CheckTemplateArgumentList(Template, TemplateLoc, /*PartialTemplateArgs=*/false, SugaredConverted, CanonicalConverted, /*UpdateArgsWithConversions=*/true, nullptr, false, &DefaultArgs); } ``` Maybe something like that? https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
https://github.com/Endilll commented: `Sema.h` changes look good. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
mizvekov wrote: FYI https://github.com/itanium-cxx-abi/cxx-abi/issues/184 is the tracking issue for the mangling rules we need here. We will probably end up with something quite different than what I coded here so far. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -9219,7 +9222,8 @@ class Sema final : public SemaBase { /// \returns true if an error occurred, false otherwise. bool CheckTemplateArgumentList( TemplateDecl *Template, SourceLocation TemplateLoc, - TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, + TemplateArgumentListInfo &TemplateArgs, mizvekov wrote: I am not seeing a worthwhile tradeoff. Just the function signature is hugely complicated, and would need to be duplicated. The implementation would be mostly the same, with a small block which would be omitted in one of the implementations. What did you have in mind? https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -9434,6 +9505,32 @@ ASTContext::getSubstTemplateTemplateParmPack(const TemplateArgument &ArgPack, return TemplateName(Subst); } +/// Retrieve the template name that represents a template name +/// deduced from a specialization. +TemplateName +ASTContext::getDeducedTemplateName(TemplateName Underlying, + DefaultArguments DefaultArgs) const { + if (!DefaultArgs) +return Underlying; + + auto &Self = const_cast(*this); mizvekov wrote: Actually in this case the relevant hash tables were already declared mutable, but there were a couple of profile functions not marked const. Fixed. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/94981 >From f05e8590c7fae599d0658829949fa907942e83f2 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Mon, 20 May 2024 01:15:03 -0300 Subject: [PATCH] [clang] Implement CWG2398 provisional TTP matching to class templates This extends default argument deduction to cover class templates as well, and also applies outside of partial ordering, adding to the provisional wording introduced in https://github.com/llvm/llvm-project/pull/89807. This solves some ambuguity introduced in P0522 regarding how template template parameters are partially ordered, and should reduce the negative impact of enabling `-frelaxed-template-template-args` by default. Given the following example: ```C++ template struct A; template struct B; template class TT1, class T5> struct B>; // #1 template struct B>; // #2 template struct B>; ``` Prior to P0522, `#2` was picked. Afterwards, this became ambiguous. This patch restores the pre-P0522 behavior, `#2` is picked again. As the consequences are not restricted to partial ordering, the following code becomes valid: ```C++ template struct A {}; A v; template class TT> void f(TT); // OK: TT picks 'float' as the default argument for the second parameter. void g() { f(v); } ``` Also, since 'f' deduced from `A` is different from 'f' deduced from `A`, this implements an additional mangling rule. --- Since this changes provisional implementation of CWG2398 which has not been released yet, and already contains a changelog entry, we don't provide a changelog entry here. --- clang-tools-extra/clangd/DumpAST.cpp | 1 + .../clangd/SemanticHighlighting.cpp | 1 + clang/include/clang/AST/ASTContext.h | 11 +- clang/include/clang/AST/ASTImporter.h | 5 + clang/include/clang/AST/DependenceFlags.h | 5 + clang/include/clang/AST/PropertiesBase.td | 17 ++ clang/include/clang/AST/TemplateName.h| 63 ++- clang/include/clang/Sema/Sema.h | 10 +- clang/lib/AST/ASTContext.cpp | 153 +--- clang/lib/AST/ASTDiagnostic.cpp | 45 +++-- clang/lib/AST/ASTImporter.cpp | 15 ++ clang/lib/AST/ASTStructuralEquivalence.cpp| 3 + clang/lib/AST/Decl.cpp| 3 +- clang/lib/AST/ItaniumMangle.cpp | 20 ++- clang/lib/AST/ODRHash.cpp | 1 + clang/lib/AST/TemplateName.cpp| 163 ++ clang/lib/AST/TextNodeDumper.cpp | 12 ++ clang/lib/AST/Type.cpp| 3 +- clang/lib/AST/TypePrinter.cpp | 3 +- clang/lib/Sema/SemaDeclCXX.cpp| 9 +- clang/lib/Sema/SemaTemplate.cpp | 63 +-- clang/lib/Sema/SemaTemplateDeduction.cpp | 158 + .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 24 +-- .../CXX/temp/temp.decls/temp.alias/p2.cpp | 5 +- clang/test/CodeGenCXX/mangle-cwg2398.cpp | 11 ++ clang/test/SemaTemplate/cwg2398.cpp | 62 +-- clang/tools/libclang/CIndex.cpp | 3 + clang/unittests/AST/ASTImporterTest.cpp | 17 ++ 28 files changed, 629 insertions(+), 257 deletions(-) create mode 100644 clang/test/CodeGenCXX/mangle-cwg2398.cpp diff --git a/clang-tools-extra/clangd/DumpAST.cpp b/clang-tools-extra/clangd/DumpAST.cpp index 9a525efb938e8..e605f82e91fe4 100644 --- a/clang-tools-extra/clangd/DumpAST.cpp +++ b/clang-tools-extra/clangd/DumpAST.cpp @@ -187,6 +187,7 @@ class DumpVisitor : public RecursiveASTVisitor { TEMPLATE_KIND(SubstTemplateTemplateParm); TEMPLATE_KIND(SubstTemplateTemplateParmPack); TEMPLATE_KIND(UsingTemplate); + TEMPLATE_KIND(DeducedTemplate); #undef TEMPLATE_KIND } llvm_unreachable("Unhandled NameKind enum"); diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index a366f1331c2d3..e6d16af2495fe 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -1120,6 +1120,7 @@ class CollectExtraHighlightings case TemplateName::SubstTemplateTemplateParm: case TemplateName::SubstTemplateTemplateParmPack: case TemplateName::UsingTemplate: +case TemplateName::DeducedTemplate: // Names that could be resolved to a TemplateDecl are handled elsewhere. break; } diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index f1f20fca477a4..c9376dc02fcfc 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -262,6 +262,8 @@ class ASTContext : public RefCountedBase { mutable llvm::ContextualFoldingSet SubstTemplateTemplateParmPacks; + mutable llvm::ContextualFoldingSet + DeducedTemplates; mutable llvm::ContextualFoldingSet Arr
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -9434,6 +9505,32 @@ ASTContext::getSubstTemplateTemplateParmPack(const TemplateArgument &ArgPack, return TemplateName(Subst); } +/// Retrieve the template name that represents a template name +/// deduced from a specialization. +TemplateName +ASTContext::getDeducedTemplateName(TemplateName Underlying, + DefaultArguments DefaultArgs) const { + if (!DefaultArgs) +return Underlying; + + auto &Self = const_cast(*this); mizvekov wrote: This is done throughout the ASTContext and is not novel here. We wish to be able to create a new node from a const ASTContext reference. These creation functions mostly behave const-ish, they just use hash tables in the ASTContext for caching / identity purposes. The other alternative is to declare these hash tables as mutable, though this would necessitate a large noisy change to update everything at once. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -6371,6 +6376,70 @@ ASTContext::getCanonicalTemplateName(const TemplateName &Name) const { canonArgPack, subst->getAssociatedDecl()->getCanonicalDecl(), subst->getFinal(), subst->getIndex()); } + case TemplateName::DeducedTemplate: { +assert(IgnoreDeduced == false); +DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName(); +DefaultArguments DefArgs = DTS->getDefaultArguments(); +TemplateName Underlying = DTS->getUnderlying(); + +bool NonCanonical = false; +TemplateName CanonUnderlying = +getCanonicalTemplateName(Underlying, /*IgnoreDeduced=*/true); +NonCanonical |= CanonUnderlying != Underlying; +auto CanonArgs = +getCanonicalTemplateArguments(*this, DefArgs.Args, NonCanonical); +{ + unsigned NumArgs = CanonArgs.size() - 1; + auto handleParamDefArg = [&](const TemplateArgument &ParamDefArg, + unsigned I) { +auto CanonParamDefArg = getCanonicalTemplateArgument(ParamDefArg); +TemplateArgument &CanonDefArg = CanonArgs[I]; +if (CanonDefArg.structurallyEquals(CanonParamDefArg)) + return; +if (I == NumArgs) + CanonArgs.pop_back(); +NonCanonical = true; + }; + auto handleParam = [&](auto *TP, int I) -> bool { +if (!TP->hasDefaultArgument()) + return true; +handleParamDefArg(TP->getDefaultArgument().getArgument(), I); +return false; + }; + + ArrayRef Params = CanonUnderlying.getAsTemplateDecl() + ->getTemplateParameters() + ->asArray(); + assert(CanonArgs.size() <= Params.size()); + for (int I = NumArgs; I >= 0; --I) { mizvekov wrote: The code is correct, but the variable name is not right. Should have been `LastArgIndex` or some such. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -6371,6 +6376,70 @@ ASTContext::getCanonicalTemplateName(const TemplateName &Name) const { canonArgPack, subst->getAssociatedDecl()->getCanonicalDecl(), subst->getFinal(), subst->getIndex()); } + case TemplateName::DeducedTemplate: { +assert(IgnoreDeduced == false); +DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName(); +DefaultArguments DefArgs = DTS->getDefaultArguments(); +TemplateName Underlying = DTS->getUnderlying(); mizvekov wrote: They are pointer sized, it's the same as a QualType, and we never take those by reference either. https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -6371,6 +6376,70 @@ ASTContext::getCanonicalTemplateName(const TemplateName &Name) const { canonArgPack, subst->getAssociatedDecl()->getCanonicalDecl(), subst->getFinal(), subst->getIndex()); } + case TemplateName::DeducedTemplate: { +assert(IgnoreDeduced == false); +DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName(); +DefaultArguments DefArgs = DTS->getDefaultArguments(); +TemplateName Underlying = DTS->getUnderlying(); + +bool NonCanonical = false; +TemplateName CanonUnderlying = +getCanonicalTemplateName(Underlying, /*IgnoreDeduced=*/true); +NonCanonical |= CanonUnderlying != Underlying; +auto CanonArgs = +getCanonicalTemplateArguments(*this, DefArgs.Args, NonCanonical); +{ + unsigned NumArgs = CanonArgs.size() - 1; + auto handleParamDefArg = [&](const TemplateArgument &ParamDefArg, + unsigned I) { +auto CanonParamDefArg = getCanonicalTemplateArgument(ParamDefArg); +TemplateArgument &CanonDefArg = CanonArgs[I]; +if (CanonDefArg.structurallyEquals(CanonParamDefArg)) + return; +if (I == NumArgs) + CanonArgs.pop_back(); +NonCanonical = true; cor3ntin wrote: I think this lambdas needs a comment, I'm not sure I understand what's happening here https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -9434,6 +9505,32 @@ ASTContext::getSubstTemplateTemplateParmPack(const TemplateArgument &ArgPack, return TemplateName(Subst); } +/// Retrieve the template name that represents a template name +/// deduced from a specialization. +TemplateName +ASTContext::getDeducedTemplateName(TemplateName Underlying, + DefaultArguments DefaultArgs) const { + if (!DefaultArgs) +return Underlying; + + auto &Self = const_cast(*this); cor3ntin wrote: Why do you need the const_cast? https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -172,6 +180,13 @@ class SubstTemplateTemplateParmPackStorage : public UncommonTemplateNameStorage, unsigned Index, bool Final); }; +struct DefaultArguments { + unsigned StartPos; cor3ntin wrote: Can we add a comment here? https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -139,28 +165,61 @@ TemplateName::NameKind TemplateName::getKind() const { return AssumedTemplate; if (uncommon->getAsSubstTemplateTemplateParm()) return SubstTemplateTemplateParm; + if (uncommon->getAsDeducedTemplateName()) +return DeducedTemplate; + + assert(uncommon->getAsSubstTemplateTemplateParmPack() != nullptr); return SubstTemplateTemplateParmPack; } TemplateDecl *TemplateName::getAsTemplateDecl() const { - if (Decl *TemplateOrUsing = Storage.dyn_cast()) { -if (UsingShadowDecl *USD = dyn_cast(TemplateOrUsing)) - return cast(USD->getTargetDecl()); + TemplateName Name = *this; + while (std::optional UnderlyingOrNone = + Name.desugar(/*IgnoreDeduced=*/false)) +Name = *UnderlyingOrNone; -assert(isa(TemplateOrUsing)); + if (Decl *TemplateOrUsing = Name.Storage.dyn_cast()) return cast(TemplateOrUsing); + return nullptr; +} + +std::pair +TemplateName::getTemplateDeclAndDefaultArgs() const { + DefaultArguments DefArgs; + for (TemplateName Name = *this; /**/; /**/) { +if (!DefArgs && Name.getKind() == TemplateName::DeducedTemplate) { + DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName(); + Name = DTS->getUnderlying(); + DefArgs = DTS->getDefaultArguments(); + continue; +} +if (std::optional UnderlyingOrNone = +Name.desugar(/*IgnoreDeduced=*/DefArgs)) { + Name = *UnderlyingOrNone; + continue; +} +TemplateDecl *TD = Name.getAsTemplateDecl(); +if (TD && DefArgs != 0) + assert(DefArgs.StartPos + DefArgs.Args.size() <= + TD->getTemplateParameters()->size()); +return {TD, DefArgs}; } +} cor3ntin wrote: This is too clever. I'd do ```cpp static std::pair getTemplateDeclAndDefaultArgs(const TemplateName N&, DefaultArguments Args) { if(...) { return getTemplateDeclAndDefaultArgs(DTS->getUnderlying(), DTS->getDefaultArguments()) ; } // ... } std::pair TemplateName::getTemplateDeclAndDefaultArgs() const { return getTemplateDeclAndDefaultArgs(*this, {}); } ``` https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -6371,6 +6376,70 @@ ASTContext::getCanonicalTemplateName(const TemplateName &Name) const { canonArgPack, subst->getAssociatedDecl()->getCanonicalDecl(), subst->getFinal(), subst->getIndex()); } + case TemplateName::DeducedTemplate: { +assert(IgnoreDeduced == false); +DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName(); +DefaultArguments DefArgs = DTS->getDefaultArguments(); +TemplateName Underlying = DTS->getUnderlying(); cor3ntin wrote: These could be reference. they are small-ish, but no need to copy https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -6371,6 +6376,70 @@ ASTContext::getCanonicalTemplateName(const TemplateName &Name) const { canonArgPack, subst->getAssociatedDecl()->getCanonicalDecl(), subst->getFinal(), subst->getIndex()); } + case TemplateName::DeducedTemplate: { +assert(IgnoreDeduced == false); +DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName(); +DefaultArguments DefArgs = DTS->getDefaultArguments(); +TemplateName Underlying = DTS->getUnderlying(); + +bool NonCanonical = false; +TemplateName CanonUnderlying = +getCanonicalTemplateName(Underlying, /*IgnoreDeduced=*/true); +NonCanonical |= CanonUnderlying != Underlying; cor3ntin wrote: ```suggestion bool NonCanonical = CanonUnderlying != Underlying; ``` https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -9219,7 +9222,8 @@ class Sema final : public SemaBase { /// \returns true if an error occurred, false otherwise. bool CheckTemplateArgumentList( TemplateDecl *Template, SourceLocation TemplateLoc, - TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, + TemplateArgumentListInfo &TemplateArgs, cor3ntin wrote: I wonder if instead we want to add an additional method. In a lot of places through the rest of the patch, `DefaultArgs` is defaulted https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -6371,6 +6376,70 @@ ASTContext::getCanonicalTemplateName(const TemplateName &Name) const { canonArgPack, subst->getAssociatedDecl()->getCanonicalDecl(), subst->getFinal(), subst->getIndex()); } + case TemplateName::DeducedTemplate: { +assert(IgnoreDeduced == false); +DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName(); +DefaultArguments DefArgs = DTS->getDefaultArguments(); +TemplateName Underlying = DTS->getUnderlying(); + +bool NonCanonical = false; cor3ntin wrote: ```suggestion ``` https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
https://github.com/cor3ntin commented: Thanks for this! I still need time to fully understand the work this but i left a few comment in the meantime. Overall it seems like a good approach https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -6371,6 +6376,70 @@ ASTContext::getCanonicalTemplateName(const TemplateName &Name) const { canonArgPack, subst->getAssociatedDecl()->getCanonicalDecl(), subst->getFinal(), subst->getIndex()); } + case TemplateName::DeducedTemplate: { +assert(IgnoreDeduced == false); +DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName(); +DefaultArguments DefArgs = DTS->getDefaultArguments(); +TemplateName Underlying = DTS->getUnderlying(); + +bool NonCanonical = false; +TemplateName CanonUnderlying = +getCanonicalTemplateName(Underlying, /*IgnoreDeduced=*/true); +NonCanonical |= CanonUnderlying != Underlying; +auto CanonArgs = +getCanonicalTemplateArguments(*this, DefArgs.Args, NonCanonical); +{ + unsigned NumArgs = CanonArgs.size() - 1; + auto handleParamDefArg = [&](const TemplateArgument &ParamDefArg, + unsigned I) { +auto CanonParamDefArg = getCanonicalTemplateArgument(ParamDefArg); +TemplateArgument &CanonDefArg = CanonArgs[I]; +if (CanonDefArg.structurallyEquals(CanonParamDefArg)) + return; +if (I == NumArgs) + CanonArgs.pop_back(); +NonCanonical = true; + }; + auto handleParam = [&](auto *TP, int I) -> bool { +if (!TP->hasDefaultArgument()) + return true; +handleParamDefArg(TP->getDefaultArgument().getArgument(), I); +return false; + }; + + ArrayRef Params = CanonUnderlying.getAsTemplateDecl() + ->getTemplateParameters() + ->asArray(); + assert(CanonArgs.size() <= Params.size()); + for (int I = NumArgs; I >= 0; --I) { cor3ntin wrote: Should that not be `NumArgs -1` ? https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
https://github.com/cor3ntin edited https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
@@ -6371,6 +6376,70 @@ ASTContext::getCanonicalTemplateName(const TemplateName &Name) const { canonArgPack, subst->getAssociatedDecl()->getCanonicalDecl(), subst->getFinal(), subst->getIndex()); } + case TemplateName::DeducedTemplate: { +assert(IgnoreDeduced == false); +DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName(); +DefaultArguments DefArgs = DTS->getDefaultArguments(); +TemplateName Underlying = DTS->getUnderlying(); + +bool NonCanonical = false; +TemplateName CanonUnderlying = +getCanonicalTemplateName(Underlying, /*IgnoreDeduced=*/true); +NonCanonical |= CanonUnderlying != Underlying; +auto CanonArgs = +getCanonicalTemplateArguments(*this, DefArgs.Args, NonCanonical); +{ cor3ntin wrote: I don't think this scope is useful (unless you would want to put the whole thing in a separate function which might be cleaner) https://github.com/llvm/llvm-project/pull/94981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/94981 >From d12c7d50b67cd669f09b3701ccf34154876786c9 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Mon, 20 May 2024 01:15:03 -0300 Subject: [PATCH] [clang] Implement CWG2398 provisional TTP matching to class templates This extends default argument deduction to cover class templates as well, and also applies outside of partial ordering, adding to the provisional wording introduced in https://github.com/llvm/llvm-project/pull/89807. This solves some ambuguity introduced in P0522 regarding how template template parameters are partially ordered, and should reduce the negative impact of enabling `-frelaxed-template-template-args` by default. Given the following example: ```C++ template struct A; template struct B; template class TT1, class T5> struct B>; // #1 template struct B>; // #2 template struct B>; ``` Prior to P0522, `#2` was picked. Afterwards, this became ambiguous. This patch restores the pre-P0522 behavior, `#2` is picked again. As the consequences are not restricted to partial ordering, the following code becomes valid: ```C++ template struct A {}; A v; template class TT> void f(TT); // OK: TT picks 'float' as the default argument for the second parameter. void g() { f(v); } ``` Also, since 'f' deduced from `A` is different from 'f' deduced from `A`, this implements an additional mangling rule. --- Since this changes provisional implementation of CWG2398 which has not been released yet, and already contains a changelog entry, we don't provide a changelog entry here. --- clang-tools-extra/clangd/DumpAST.cpp | 1 + .../clangd/SemanticHighlighting.cpp | 1 + clang/include/clang/AST/ASTContext.h | 8 +- clang/include/clang/AST/ASTImporter.h | 5 + clang/include/clang/AST/DependenceFlags.h | 5 + clang/include/clang/AST/PropertiesBase.td | 17 ++ clang/include/clang/AST/TemplateName.h| 59 ++- clang/include/clang/Sema/Sema.h | 10 +- clang/lib/AST/ASTContext.cpp | 129 -- clang/lib/AST/ASTDiagnostic.cpp | 24 +-- clang/lib/AST/ASTImporter.cpp | 15 ++ clang/lib/AST/ASTStructuralEquivalence.cpp| 3 + clang/lib/AST/ItaniumMangle.cpp | 11 ++ clang/lib/AST/ODRHash.cpp | 1 + clang/lib/AST/TemplateName.cpp| 157 ++ clang/lib/AST/TextNodeDumper.cpp | 12 ++ clang/lib/AST/Type.cpp| 3 +- clang/lib/Sema/SemaTemplate.cpp | 63 +-- clang/lib/Sema/SemaTemplateDeduction.cpp | 128 -- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 24 +-- .../CXX/temp/temp.decls/temp.alias/p2.cpp | 5 +- clang/test/CodeGenCXX/mangle-cwg2398.cpp | 11 ++ clang/test/SemaTemplate/cwg2398.cpp | 60 +-- clang/tools/libclang/CIndex.cpp | 3 + clang/unittests/AST/ASTImporterTest.cpp | 17 ++ 25 files changed, 564 insertions(+), 208 deletions(-) create mode 100644 clang/test/CodeGenCXX/mangle-cwg2398.cpp diff --git a/clang-tools-extra/clangd/DumpAST.cpp b/clang-tools-extra/clangd/DumpAST.cpp index 9a525efb938e8..e605f82e91fe4 100644 --- a/clang-tools-extra/clangd/DumpAST.cpp +++ b/clang-tools-extra/clangd/DumpAST.cpp @@ -187,6 +187,7 @@ class DumpVisitor : public RecursiveASTVisitor { TEMPLATE_KIND(SubstTemplateTemplateParm); TEMPLATE_KIND(SubstTemplateTemplateParmPack); TEMPLATE_KIND(UsingTemplate); + TEMPLATE_KIND(DeducedTemplate); #undef TEMPLATE_KIND } llvm_unreachable("Unhandled NameKind enum"); diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index a366f1331c2d3..e6d16af2495fe 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -1120,6 +1120,7 @@ class CollectExtraHighlightings case TemplateName::SubstTemplateTemplateParm: case TemplateName::SubstTemplateTemplateParmPack: case TemplateName::UsingTemplate: +case TemplateName::DeducedTemplate: // Names that could be resolved to a TemplateDecl are handled elsewhere. break; } diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 8bce4812f0d48..8818314de9364 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -262,6 +262,8 @@ class ASTContext : public RefCountedBase { mutable llvm::ContextualFoldingSet SubstTemplateTemplateParmPacks; + mutable llvm::ContextualFoldingSet + DeducedTemplates; mutable llvm::ContextualFoldingSet ArrayParameterTypes; @@ -2247,6 +2249,9 @@ class ASTContext : public RefCountedBase { unsigned Index,
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/94981 >From 68791782b7a1a0eafa98950f6e03aa1585be5223 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Mon, 20 May 2024 01:15:03 -0300 Subject: [PATCH] [clang] Implement CWG2398 provisional TTP matching to class templates This extends default argument deduction to cover class templates as well, and also applies outside of partial ordering, adding to the provisional wording introduced in https://github.com/llvm/llvm-project/pull/89807. This solves some ambuguity introduced in P0522 regarding how template template parameters are partially ordered, and should reduce the negative impact of enabling `-frelaxed-template-template-args` by default. Given the following example: ```C++ template struct A; template struct B; template class TT1, class T5> struct B>; // #1 template struct B>; // #2 template struct B>; ``` Prior to P0522, `#2` was picked. Afterwards, this became ambiguous. This patch restores the pre-P0522 behavior, `#2` is picked again. As the consequences are not restricted to partial ordering, the following code becomes valid: ```C++ template struct A {}; A v; template class TT> void f(TT); // OK: TT picks 'float' as the default argument for the second parameter. void g() { f(v); } ``` Also, since 'f' deduced from `A` is different from 'f' deduced from `A`, this implements an additional mangling rule. --- Since this changes provisional implementation of CWG2398 which has not been released yet, and already contains a changelog entry, we don't provide a changelog entry here. --- clang-tools-extra/clangd/DumpAST.cpp | 1 + .../clangd/SemanticHighlighting.cpp | 1 + clang/include/clang/AST/ASTContext.h | 8 +- clang/include/clang/AST/ASTImporter.h | 5 + clang/include/clang/AST/DependenceFlags.h | 5 + clang/include/clang/AST/PropertiesBase.td | 17 ++ clang/include/clang/AST/TemplateName.h| 59 ++- clang/include/clang/Sema/Sema.h | 10 +- clang/lib/AST/ASTContext.cpp | 129 -- clang/lib/AST/ASTDiagnostic.cpp | 24 +-- clang/lib/AST/ASTImporter.cpp | 92 +- clang/lib/AST/ASTStructuralEquivalence.cpp| 3 + clang/lib/AST/ItaniumMangle.cpp | 11 ++ clang/lib/AST/ODRHash.cpp | 1 + clang/lib/AST/TemplateName.cpp| 157 ++ clang/lib/AST/TextNodeDumper.cpp | 12 ++ clang/lib/AST/Type.cpp| 3 +- clang/lib/Sema/SemaTemplate.cpp | 63 +-- clang/lib/Sema/SemaTemplateDeduction.cpp | 128 -- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 24 +-- .../CXX/temp/temp.decls/temp.alias/p2.cpp | 5 +- clang/test/CodeGenCXX/mangle-cwg2398.cpp | 11 ++ clang/test/SemaTemplate/cwg2398.cpp | 60 +-- clang/tools/libclang/CIndex.cpp | 3 + clang/unittests/AST/ASTImporterTest.cpp | 17 ++ 25 files changed, 594 insertions(+), 255 deletions(-) create mode 100644 clang/test/CodeGenCXX/mangle-cwg2398.cpp diff --git a/clang-tools-extra/clangd/DumpAST.cpp b/clang-tools-extra/clangd/DumpAST.cpp index 9a525efb938e8..e605f82e91fe4 100644 --- a/clang-tools-extra/clangd/DumpAST.cpp +++ b/clang-tools-extra/clangd/DumpAST.cpp @@ -187,6 +187,7 @@ class DumpVisitor : public RecursiveASTVisitor { TEMPLATE_KIND(SubstTemplateTemplateParm); TEMPLATE_KIND(SubstTemplateTemplateParmPack); TEMPLATE_KIND(UsingTemplate); + TEMPLATE_KIND(DeducedTemplate); #undef TEMPLATE_KIND } llvm_unreachable("Unhandled NameKind enum"); diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index a366f1331c2d3..e6d16af2495fe 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -1120,6 +1120,7 @@ class CollectExtraHighlightings case TemplateName::SubstTemplateTemplateParm: case TemplateName::SubstTemplateTemplateParmPack: case TemplateName::UsingTemplate: +case TemplateName::DeducedTemplate: // Names that could be resolved to a TemplateDecl are handled elsewhere. break; } diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 8bce4812f0d48..8818314de9364 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -262,6 +262,8 @@ class ASTContext : public RefCountedBase { mutable llvm::ContextualFoldingSet SubstTemplateTemplateParmPacks; + mutable llvm::ContextualFoldingSet + DeducedTemplates; mutable llvm::ContextualFoldingSet ArrayParameterTypes; @@ -2247,6 +2249,9 @@ class ASTContext : public RefCountedBase { unsigned Index,
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/94981 >From ea98dec85a9817eb4e35ce97389433e4a5b9676d Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Mon, 20 May 2024 01:15:03 -0300 Subject: [PATCH] [clang] Implement CWG2398 provisional TTP matching to class templates This extends default argument deduction to cover class templates as well, and also applies outside of partial ordering, adding to the provisional wording introduced in https://github.com/llvm/llvm-project/pull/89807. This solves some ambuguity introduced in P0522 regarding how template template parameters are partially ordered, and should reduce the negative impact of enabling `-frelaxed-template-template-args` by default. Given the following example: ```C++ template struct A; template struct B; template class TT1, class T5> struct B>; // #1 template struct B>; // #2 template struct B>; ``` Prior to P0522, `#2` was picked. Afterwards, this became ambiguous. This patch restores the pre-P0522 behavior, `#2` is picked again. As the consequences are not restricted to partial ordering, the following code becomes valid: ```C++ template struct A {}; A v; template class TT> void f(TT); // OK: TT picks 'float' as the default argument for the second parameter. void g() { f(v); } ``` Also, since 'f' deduced from `A` is different from 'f' deduced from `A`, this implements an additional mangling rule. --- Since this changes provisional implementation of CWG2398 which has not been released yet, and already contains a changelog entry, we don't provide a changelog entry here. --- clang-tools-extra/clangd/DumpAST.cpp | 1 + .../clangd/SemanticHighlighting.cpp | 1 + clang/include/clang/AST/ASTContext.h | 8 +- clang/include/clang/AST/ASTImporter.h | 5 + clang/include/clang/AST/DependenceFlags.h | 5 + clang/include/clang/AST/PropertiesBase.td | 17 ++ clang/include/clang/AST/TemplateName.h| 59 ++- clang/include/clang/Sema/Sema.h | 10 +- clang/lib/AST/ASTContext.cpp | 129 -- clang/lib/AST/ASTDiagnostic.cpp | 24 +-- clang/lib/AST/ASTImporter.cpp | 92 +- clang/lib/AST/ASTStructuralEquivalence.cpp| 3 + clang/lib/AST/ItaniumMangle.cpp | 11 ++ clang/lib/AST/ODRHash.cpp | 1 + clang/lib/AST/TemplateName.cpp| 157 ++ clang/lib/AST/TextNodeDumper.cpp | 12 ++ clang/lib/AST/Type.cpp| 3 +- clang/lib/Sema/SemaTemplate.cpp | 63 +-- clang/lib/Sema/SemaTemplateDeduction.cpp | 134 --- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 24 +-- .../CXX/temp/temp.decls/temp.alias/p2.cpp | 5 +- clang/test/CodeGenCXX/mangle-cwg2398.cpp | 11 ++ clang/test/SemaTemplate/cwg2398.cpp | 60 +-- clang/tools/libclang/CIndex.cpp | 3 + clang/unittests/AST/ASTImporterTest.cpp | 17 ++ 25 files changed, 600 insertions(+), 255 deletions(-) create mode 100644 clang/test/CodeGenCXX/mangle-cwg2398.cpp diff --git a/clang-tools-extra/clangd/DumpAST.cpp b/clang-tools-extra/clangd/DumpAST.cpp index 9a525efb938e8..e605f82e91fe4 100644 --- a/clang-tools-extra/clangd/DumpAST.cpp +++ b/clang-tools-extra/clangd/DumpAST.cpp @@ -187,6 +187,7 @@ class DumpVisitor : public RecursiveASTVisitor { TEMPLATE_KIND(SubstTemplateTemplateParm); TEMPLATE_KIND(SubstTemplateTemplateParmPack); TEMPLATE_KIND(UsingTemplate); + TEMPLATE_KIND(DeducedTemplate); #undef TEMPLATE_KIND } llvm_unreachable("Unhandled NameKind enum"); diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index a366f1331c2d3..e6d16af2495fe 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -1120,6 +1120,7 @@ class CollectExtraHighlightings case TemplateName::SubstTemplateTemplateParm: case TemplateName::SubstTemplateTemplateParmPack: case TemplateName::UsingTemplate: +case TemplateName::DeducedTemplate: // Names that could be resolved to a TemplateDecl are handled elsewhere. break; } diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 8bce4812f0d48..8818314de9364 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -262,6 +262,8 @@ class ASTContext : public RefCountedBase { mutable llvm::ContextualFoldingSet SubstTemplateTemplateParmPacks; + mutable llvm::ContextualFoldingSet + DeducedTemplates; mutable llvm::ContextualFoldingSet ArrayParameterTypes; @@ -2247,6 +2249,9 @@ class ASTContext : public RefCountedBase { unsigned Index,
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/94981 >From 015a05707caad5d39909bc68a5371161de464d9d Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Mon, 20 May 2024 01:15:03 -0300 Subject: [PATCH] [clang] Implement CWG2398 provisional TTP matching to class templates This extends default argument deduction to cover class templates as well, and also applies outside of partial ordering, adding to the provisional wording introduced in https://github.com/llvm/llvm-project/pull/89807. This solves some ambuguity introduced in P0522 regarding how template template parameters are partially ordered, and should reduce the negative impact of enabling `-frelaxed-template-template-args` by default. Given the following example: ```C++ template struct A; template struct B; template class TT1, class T5> struct B>; // #1 template struct B>; // #2 template struct B>; ``` Prior to P0522, `#2` was picked. Afterwards, this became ambiguous. This patch restores the pre-P0522 behavior, `#2` is picked again. As the consequences are not restricted to partial ordering, the following code becomes valid: ```C++ template struct A {}; A v; template class TT> void f(TT); // OK: TT picks 'float' as the default argument for the second parameter. void g() { f(v); } ``` Also, since 'f' deduced from `A` is different from 'f' deduced from `A`, this implements an additional mangling rule. --- Since this changes provisional implementation of CWG2398 which has not been released yet, and already contains a changelog entry, we don't provide a changelog entry here. --- clang-tools-extra/clangd/DumpAST.cpp | 1 + .../clangd/SemanticHighlighting.cpp | 1 + clang/include/clang/AST/ASTContext.h | 8 +- clang/include/clang/AST/ASTImporter.h | 5 + clang/include/clang/AST/DependenceFlags.h | 5 + clang/include/clang/AST/PropertiesBase.td | 17 ++ clang/include/clang/AST/TemplateName.h| 59 ++- clang/include/clang/Sema/Sema.h | 10 +- clang/lib/AST/ASTContext.cpp | 129 -- clang/lib/AST/ASTDiagnostic.cpp | 24 +-- clang/lib/AST/ASTImporter.cpp | 92 +- clang/lib/AST/ASTStructuralEquivalence.cpp| 3 + clang/lib/AST/ItaniumMangle.cpp | 11 ++ clang/lib/AST/ODRHash.cpp | 1 + clang/lib/AST/TemplateName.cpp| 157 ++ clang/lib/AST/TextNodeDumper.cpp | 12 ++ clang/lib/AST/Type.cpp| 3 +- clang/lib/Sema/SemaTemplate.cpp | 63 +-- clang/lib/Sema/SemaTemplateDeduction.cpp | 134 --- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 24 +-- .../CXX/temp/temp.decls/temp.alias/p2.cpp | 5 +- clang/test/CodeGenCXX/mangle-cwg2398.cpp | 11 ++ clang/test/SemaTemplate/cwg2398.cpp | 44 +++-- clang/tools/libclang/CIndex.cpp | 3 + clang/unittests/AST/ASTImporterTest.cpp | 17 ++ 25 files changed, 584 insertions(+), 255 deletions(-) create mode 100644 clang/test/CodeGenCXX/mangle-cwg2398.cpp diff --git a/clang-tools-extra/clangd/DumpAST.cpp b/clang-tools-extra/clangd/DumpAST.cpp index 9a525efb938e8..e605f82e91fe4 100644 --- a/clang-tools-extra/clangd/DumpAST.cpp +++ b/clang-tools-extra/clangd/DumpAST.cpp @@ -187,6 +187,7 @@ class DumpVisitor : public RecursiveASTVisitor { TEMPLATE_KIND(SubstTemplateTemplateParm); TEMPLATE_KIND(SubstTemplateTemplateParmPack); TEMPLATE_KIND(UsingTemplate); + TEMPLATE_KIND(DeducedTemplate); #undef TEMPLATE_KIND } llvm_unreachable("Unhandled NameKind enum"); diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index a366f1331c2d3..e6d16af2495fe 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -1120,6 +1120,7 @@ class CollectExtraHighlightings case TemplateName::SubstTemplateTemplateParm: case TemplateName::SubstTemplateTemplateParmPack: case TemplateName::UsingTemplate: +case TemplateName::DeducedTemplate: // Names that could be resolved to a TemplateDecl are handled elsewhere. break; } diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 8bce4812f0d48..8818314de9364 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -262,6 +262,8 @@ class ASTContext : public RefCountedBase { mutable llvm::ContextualFoldingSet SubstTemplateTemplateParmPacks; + mutable llvm::ContextualFoldingSet + DeducedTemplates; mutable llvm::ContextualFoldingSet ArrayParameterTypes; @@ -2247,6 +2249,9 @@ class ASTContext : public RefCountedBase { unsigned Index,
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
llvmbot wrote: @llvm/pr-subscribers-clang-modules Author: Matheus Izvekov (mizvekov) Changes This extends default argument deduction to cover class templates as well, and also applies outside of partial ordering, adding to the provisional wording introduced in https://github.com/llvm/llvm-project/pull/89807. This solves some ambuguity introduced in P0522 regarding how template template parameters are partially ordered, and should reduce the negative impact of enabling `-frelaxed-template-template-args` by default. Given the following example: ```C++ templatestruct A; template struct B; template class TT1, class T5> struct B >; // #1 template struct B>; // #2 template struct B>; ``` Prior to P0522, `#2` was picked. Afterwards, this became ambiguous. This patch restores the pre-P0522 behavior, `#2` is picked again. As the consequences are not restricted to partial ordering, the following code becomes valid: ```C++ template struct A {}; A v; template class TT> void f(TT ); // OK: TT picks 'float' as the default argument for the second parameter. void g() { f(v); } ``` Also, since 'f' deduced from `A ` is different from 'f' deduced from `A `, this implements an additional mangling rule. --- Since this changes provisional implementation of CWG2398 which has not been released yet, and already contains a changelog entry, we don't provide a changelog entry here. --- Patch is 73.91 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/94981.diff 25 Files Affected: - (modified) clang-tools-extra/clangd/DumpAST.cpp (+1) - (modified) clang-tools-extra/clangd/SemanticHighlighting.cpp (+1) - (modified) clang/include/clang/AST/ASTContext.h (+7-1) - (modified) clang/include/clang/AST/ASTImporter.h (+5) - (modified) clang/include/clang/AST/DependenceFlags.h (+5) - (modified) clang/include/clang/AST/PropertiesBase.td (+17) - (modified) clang/include/clang/AST/TemplateName.h (+57-2) - (modified) clang/include/clang/Sema/Sema.h (+7-3) - (modified) clang/lib/AST/ASTContext.cpp (+113-16) - (modified) clang/lib/AST/ASTDiagnostic.cpp (+13-11) - (modified) clang/lib/AST/ASTImporter.cpp (+45-47) - (modified) clang/lib/AST/ASTStructuralEquivalence.cpp (+3) - (modified) clang/lib/AST/ItaniumMangle.cpp (+11) - (modified) clang/lib/AST/ODRHash.cpp (+1) - (modified) clang/lib/AST/TemplateName.cpp (+123-34) - (modified) clang/lib/AST/TextNodeDumper.cpp (+12) - (modified) clang/lib/AST/Type.cpp (+2-1) - (modified) clang/lib/Sema/SemaTemplate.cpp (+46-17) - (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+35-98) - (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+13-11) - (modified) clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp (+3-2) - (added) clang/test/CodeGenCXX/mangle-cwg2398.cpp (+11) - (modified) clang/test/SemaTemplate/cwg2398.cpp (+31-12) - (modified) clang/tools/libclang/CIndex.cpp (+3) - (modified) clang/unittests/AST/ASTImporterTest.cpp (+17) ``diff diff --git a/clang-tools-extra/clangd/DumpAST.cpp b/clang-tools-extra/clangd/DumpAST.cpp index 9a525efb938e8..e605f82e91fe4 100644 --- a/clang-tools-extra/clangd/DumpAST.cpp +++ b/clang-tools-extra/clangd/DumpAST.cpp @@ -187,6 +187,7 @@ class DumpVisitor : public RecursiveASTVisitor { TEMPLATE_KIND(SubstTemplateTemplateParm); TEMPLATE_KIND(SubstTemplateTemplateParmPack); TEMPLATE_KIND(UsingTemplate); + TEMPLATE_KIND(DeducedTemplate); #undef TEMPLATE_KIND } llvm_unreachable("Unhandled NameKind enum"); diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index a366f1331c2d3..e6d16af2495fe 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -1120,6 +1120,7 @@ class CollectExtraHighlightings case TemplateName::SubstTemplateTemplateParm: case TemplateName::SubstTemplateTemplateParmPack: case TemplateName::UsingTemplate: +case TemplateName::DeducedTemplate: // Names that could be resolved to a TemplateDecl are handled elsewhere. break; } diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 8bce4812f0d48..8818314de9364 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -262,6 +262,8 @@ class ASTContext : public RefCountedBase { mutable llvm::ContextualFoldingSet SubstTemplateTemplateParmPacks; + mutable llvm::ContextualFoldingSet + DeducedTemplates; mutable llvm::ContextualFoldingSet ArrayParameterTypes; @@ -2247,6 +2249,9 @@ class ASTContext : public RefCountedBase { unsigned Index,
[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
https://github.com/mizvekov created https://github.com/llvm/llvm-project/pull/94981 This extends default argument deduction to cover class templates as well, and also applies outside of partial ordering, adding to the provisional wording introduced in https://github.com/llvm/llvm-project/pull/89807. This solves some ambuguity introduced in P0522 regarding how template template parameters are partially ordered, and should reduce the negative impact of enabling `-frelaxed-template-template-args` by default. Given the following example: ```C++ template struct A; template struct B; template class TT1, class T5> struct B>; // #1 template struct B>; // #2 template struct B>; ``` Prior to P0522, `#2` was picked. Afterwards, this became ambiguous. This patch restores the pre-P0522 behavior, `#2` is picked again. As the consequences are not restricted to partial ordering, the following code becomes valid: ```C++ template struct A {}; A v; template class TT> void f(TT); // OK: TT picks 'float' as the default argument for the second parameter. void g() { f(v); } ``` Also, since 'f' deduced from `A` is different from 'f' deduced from `A`, this implements an additional mangling rule. --- Since this changes provisional implementation of CWG2398 which has not been released yet, and already contains a changelog entry, we don't provide a changelog entry here. >From 28bc152e72d458e91aee90d46763eea04091ebe2 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Mon, 20 May 2024 01:15:03 -0300 Subject: [PATCH] [clang] Implement CWG2398 provisional TTP matching to class templates This extends default argument deduction to cover class templates as well, and also applies outside of partial ordering, adding to the provisional wording introduced in https://github.com/llvm/llvm-project/pull/89807. This solves some ambuguity introduced in P0522 regarding how template template parameters are partially ordered, and should reduce the negative impact of enabling `-frelaxed-template-template-args` by default. Given the following example: ```C++ template struct A; template struct B; template class TT1, class T5> struct B>; // #1 template struct B>; // #2 template struct B>; ``` Prior to P0522, `#2` was picked. Afterwards, this became ambiguous. This patch restores the pre-P0522 behavior, `#2` is picked again. As the consequences are not restricted to partial ordering, the following code becomes valid: ```C++ template struct A {}; A v; template class TT> void f(TT); // OK: TT picks 'float' as the default argument for the second parameter. void g() { f(v); } ``` Also, since 'f' deduced from `A` is different from 'f' deduced from `A`, this implements an additional mangling rule. --- Since this changes provisional implementation of CWG2398 which has not been released yet, and already contains a changelog entry, we don't provide a changelog entry here. --- clang-tools-extra/clangd/DumpAST.cpp | 1 + .../clangd/SemanticHighlighting.cpp | 1 + clang/include/clang/AST/ASTContext.h | 8 +- clang/include/clang/AST/ASTImporter.h | 5 + clang/include/clang/AST/DependenceFlags.h | 5 + clang/include/clang/AST/PropertiesBase.td | 17 ++ clang/include/clang/AST/TemplateName.h| 59 ++- clang/include/clang/Sema/Sema.h | 10 +- clang/lib/AST/ASTContext.cpp | 129 -- clang/lib/AST/ASTDiagnostic.cpp | 24 +-- clang/lib/AST/ASTImporter.cpp | 92 +- clang/lib/AST/ASTStructuralEquivalence.cpp| 3 + clang/lib/AST/ItaniumMangle.cpp | 11 ++ clang/lib/AST/ODRHash.cpp | 1 + clang/lib/AST/TemplateName.cpp| 157 ++ clang/lib/AST/TextNodeDumper.cpp | 12 ++ clang/lib/AST/Type.cpp| 3 +- clang/lib/Sema/SemaTemplate.cpp | 63 +-- clang/lib/Sema/SemaTemplateDeduction.cpp | 133 --- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 24 +-- .../CXX/temp/temp.decls/temp.alias/p2.cpp | 5 +- clang/test/CodeGenCXX/mangle-cwg2398.cpp | 11 ++ clang/test/SemaTemplate/cwg2398.cpp | 43 +++-- clang/tools/libclang/CIndex.cpp | 3 + clang/unittests/AST/ASTImporterTest.cpp | 17 ++ 25 files changed, 582 insertions(+), 255 deletions(-) create mode 100644 clang/test/CodeGenCXX/mangle-cwg2398.cpp diff --git a/clang-tools-extra/clangd/DumpAST.cpp b/clang-tools-extra/clangd/DumpAST.cpp index 9a525efb938e8..e605f82e91fe4 100644 --- a/clang-tools-extra/clangd/DumpAST.cpp +++ b/clang-tools-extra/clangd/DumpAST.cpp @@ -187,6 +187,7 @@ class DumpVisitor : public RecursiveASTVisitor { TEMPLATE_KIND(SubstTemplateTemplateParm); TEMPLATE_KIND(SubstTemplateTemplateParmPack); TEMPLATE_KIND(UsingTemplate); + TEMPLATE_KIND(DeducedTemplate);