[clang] [clang-tools-extra] [clang] Implement CWG2398 provisional TTP matching to class templates (PR #94981)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 10 07:08:09 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-modules
Author: Matheus Izvekov (mizvekov)
<details>
<summary>Changes</summary>
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 <class T1, class T2 = float> struct A;
template <class T3> struct B;
template <template <class T4> class TT1, class T5> struct B<TT1<T5>>; // #<!-- -->1
template <class T6, class T7> struct B<A<T6, T7>>; // #<!-- -->2
template struct B<A<int>>;
```
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<class T, class U> struct A {};
A<int, float> v;
template<template<class> class TT> void f(TT<int>);
// OK: TT picks 'float' as the default argument for the second parameter.
void g() { f(v); }
```
Also, since 'f' deduced from `A<int, float>` is different from 'f' deduced from `A<int, double>`, 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<DumpVisitor> {
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<ASTContext> {
mutable llvm::ContextualFoldingSet<SubstTemplateTemplateParmPackStorage,
ASTContext&>
SubstTemplateTemplateParmPacks;
+ mutable llvm::ContextualFoldingSet<DeducedTemplateStorage, ASTContext &>
+ DeducedTemplates;
mutable llvm::ContextualFoldingSet<ArrayParameterType, ASTContext &>
ArrayParameterTypes;
@@ -2247,6 +2249,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
unsigned Index,
bool Final) const;
+ TemplateName getDeducedTemplateName(TemplateName Underlying,
+ DefaultArguments DefaultArgs) const;
+
enum GetBuiltinTypeError {
/// No error
GE_None,
@@ -2726,7 +2731,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// template name uses the shortest form of the dependent
/// nested-name-specifier, which itself contains all canonical
/// types, values, and templates.
- TemplateName getCanonicalTemplateName(const TemplateName &Name) const;
+ TemplateName getCanonicalTemplateName(TemplateName Name,
+ bool IgnoreDeduced = false) const;
/// Determine whether the given template names refer to the same
/// template.
diff --git a/clang/include/clang/AST/ASTImporter.h b/clang/include/clang/AST/ASTImporter.h
index 4ffd913846575..7b890bdf492fa 100644
--- a/clang/include/clang/AST/ASTImporter.h
+++ b/clang/include/clang/AST/ASTImporter.h
@@ -485,6 +485,11 @@ class TypeSourceInfo;
/// the declarations it contains.
[[nodiscard]] llvm::Error ImportDefinition(Decl *From);
+ llvm::Error
+ ImportTemplateArguments(ArrayRef<TemplateArgument> FromArgs,
+ SmallVectorImpl<TemplateArgument> &ToArgs);
+ Expected<TemplateArgument> Import(const TemplateArgument &From);
+
/// Cope with a name conflict when importing a declaration into the
/// given context.
///
diff --git a/clang/include/clang/AST/DependenceFlags.h b/clang/include/clang/AST/DependenceFlags.h
index 3b3c1afb096ad..bdcaabc143cc4 100644
--- a/clang/include/clang/AST/DependenceFlags.h
+++ b/clang/include/clang/AST/DependenceFlags.h
@@ -315,6 +315,11 @@ toTemplateNameDependence(NestedNameSpecifierDependence D) {
return Dependence(D).templateName();
}
+inline TemplateNameDependence
+toTemplateNameDependence(TemplateArgumentDependence D) {
+ return Dependence(D).templateName();
+}
+
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
} // namespace clang
diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td
index 6df1d93a7ba2e..bd0b316a4958a 100644
--- a/clang/include/clang/AST/PropertiesBase.td
+++ b/clang/include/clang/AST/PropertiesBase.td
@@ -750,6 +750,23 @@ let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParmPack"> in {
return ctx.getSubstTemplateTemplateParmPack(argumentPack, associatedDecl, index, final);
}]>;
}
+let Class = PropertyTypeCase<TemplateName, "DeducedTemplate"> in {
+ def : ReadHelper<[{
+ auto DTS = node.getAsDeducedTemplateName();
+ }]>;
+ def : Property<"underlying", TemplateName> {
+ let Read = [{ DTS->getUnderlying() }];
+ }
+ def : Property<"startPos", UInt32> {
+ let Read = [{ DTS->getDefaultArguments().StartPos }];
+ }
+ def : Property<"defaultArgs", Array<TemplateArgument>> {
+ let Read = [{ DTS->getDefaultArguments().Args }];
+ }
+ def : Creator<[{
+ return ctx.getDeducedTemplateName(underlying, {startPos, defaultArgs});
+ }]>;
+}
// Type cases for TemplateArgument.
def : PropertyTypeKind<TemplateArgument, TemplateArgumentKind,
diff --git a/clang/include/clang/AST/TemplateName.h b/clang/include/clang/AST/TemplateName.h
index 988a55acd2252..bd70954a42e0d 100644
--- a/clang/include/clang/AST/TemplateName.h
+++ b/clang/include/clang/AST/TemplateName.h
@@ -34,6 +34,7 @@ class NestedNameSpecifier;
enum OverloadedOperatorKind : int;
class OverloadedTemplateStorage;
class AssumedTemplateStorage;
+class DeducedTemplateStorage;
struct PrintingPolicy;
class QualifiedTemplateName;
class SubstTemplateTemplateParmPackStorage;
@@ -50,16 +51,17 @@ class UncommonTemplateNameStorage {
enum Kind {
Overloaded,
Assumed, // defined in DeclarationName.h
+ Deduced,
SubstTemplateTemplateParm,
SubstTemplateTemplateParmPack
};
struct BitsTag {
LLVM_PREFERRED_TYPE(Kind)
- unsigned Kind : 2;
+ unsigned Kind : 3;
// The template parameter index.
- unsigned Index : 15;
+ unsigned Index : 14;
/// The pack index, or the number of stored templates
/// or template arguments, depending on which subclass we have.
@@ -90,6 +92,12 @@ class UncommonTemplateNameStorage {
: nullptr;
}
+ DeducedTemplateStorage *getAsDeducedTemplateName() {
+ return Bits.Kind == Deduced
+ ? reinterpret_cast<DeducedTemplateStorage *>(this)
+ : nullptr;
+ }
+
SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() {
return Bits.Kind == SubstTemplateTemplateParm
? reinterpret_cast<SubstTemplateTemplateParmStorage *>(this)
@@ -172,6 +180,13 @@ class SubstTemplateTemplateParmPackStorage : public UncommonTemplateNameStorage,
unsigned Index, bool Final);
};
+struct DefaultArguments {
+ unsigned StartPos;
+ ArrayRef<TemplateArgument> Args;
+
+ operator bool() const { return !Args.empty(); }
+};
+
/// Represents a C++ template name within the type system.
///
/// A C++ template name refers to a template within the C++ type
@@ -245,6 +260,10 @@ class TemplateName {
/// A template name that refers to a template declaration found through a
/// specific using shadow declaration.
UsingTemplate,
+
+ /// A template name that refers to another TemplateName with deduced default
+ /// arguments.
+ DeducedTemplate,
};
TemplateName() = default;
@@ -256,6 +275,7 @@ class TemplateName {
explicit TemplateName(QualifiedTemplateName *Qual);
explicit TemplateName(DependentTemplateName *Dep);
explicit TemplateName(UsingShadowDecl *Using);
+ explicit TemplateName(DeducedTemplateStorage *Deduced);
/// Determine whether this template name is NULL.
bool isNull() const;
@@ -272,6 +292,12 @@ class TemplateName {
/// set of function templates, returns NULL.
TemplateDecl *getAsTemplateDecl() const;
+ /// Retrieves the underlying template declaration that
+ /// this template name refers to, along with the
+ /// deduced default arguments, if any.
+ std::pair<TemplateDecl *, DefaultArguments>
+ getTemplateDeclAndDefaultArgs() const;
+
/// Retrieve the underlying, overloaded function template
/// declarations that this template name refers to, if known.
///
@@ -312,6 +338,11 @@ class TemplateName {
/// template declaration is introduced, if any.
UsingShadowDecl *getAsUsingShadowDecl() const;
+ /// Retrieve the deduced template info, if any.
+ DeducedTemplateStorage *getAsDeducedTemplateName() const;
+
+ std::optional<TemplateName> desugar(bool IgnoreDeduced) const;
+
TemplateName getUnderlying() const;
TemplateNameDependence getDependence() const;
@@ -409,6 +440,30 @@ class SubstTemplateTemplateParmStorage
std::optional<unsigned> PackIndex);
};
+class DeducedTemplateStorage : public UncommonTemplateNameStorage,
+ public llvm::FoldingSetNode {
+ friend class ASTContext;
+
+ TemplateName Underlying;
+
+ DeducedTemplateStorage(TemplateName Underlying,
+ const DefaultArguments &DefArgs);
+
+public:
+ TemplateName getUnderlying() const { return Underlying; }
+
+ DefaultArguments getDefaultArguments() const {
+ return {/*StartPos=*/Bits.Index,
+ /*Args=*/{reinterpret_cast<const TemplateArgument *>(this + 1),
+ Bits.Data}};
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context);
+
+ static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
+ TemplateName Underlying, const DefaultArguments &DefArgs);
+};
+
inline TemplateName TemplateName::getUnderlying() const {
if (SubstTemplateTemplateParmStorage *subst
= getAsSubstTemplateTemplateParm())
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 4d4579fcfd456..ce7066a76eaec 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9210,6 +9210,9 @@ class Sema final : public SemaBase {
/// receive true if the cause for the error is the associated constraints of
/// the template not being satisfied by the template arguments.
///
+ /// \param DefaultArgs any default arguments from template specialization
+ /// deduction.
+ ///
/// \param PartialOrderingTTP If true, assume these template arguments are
/// the injected template arguments for a template template parameter.
/// This will relax the requirement that all its possible uses are valid:
@@ -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,
+ const DefaultArguments &DefaultArgs, bool PartialTemplateArgs,
SmallVectorImpl<TemplateArgument> &SugaredConverted,
SmallVectorImpl<TemplateArgument> &CanonicalConverted,
bool UpdateArgsWithConversions = true,
@@ -9718,8 +9722,8 @@ class Sema final : public SemaBase {
sema::TemplateDeductionInfo &Info);
bool isTemplateTemplateParameterAtLeastAsSpecializedAs(
- TemplateParameterList *PParam, TemplateDecl *AArg, SourceLocation Loc,
- bool IsDeduced);
+ TemplateParameterList *PParam, TemplateDecl *AArg,
+ const DefaultArguments &DefaultArgs, SourceLocation Loc, bool IsDeduced);
void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced,
unsigned Depth, llvm::SmallBitVector &Used);
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index cd76b8aa271da..9c8f92cd60b7b 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -880,8 +880,8 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
TemplateSpecializationTypes(this_()),
DependentTemplateSpecializationTypes(this_()), AutoTypes(this_()),
DependentBitIntTypes(this_()), SubstTemplateTemplateParmPacks(this_()),
- ArrayParameterTypes(this_()), CanonTemplateTemplateParms(this_()),
- SourceMgr(SM), LangOpts(LOpts),
+ DeducedTemplates(this_()), ArrayParameterTypes(this_()),
+ CanonTemplateTemplateParms(this_()), SourceMgr(SM), LangOpts(LOpts),
NoSanitizeL(new NoSanitizeList(LangOpts.NoSanitizeFiles, SM)),
XRayFilter(new XRayFunctionFilter(LangOpts.XRayAlwaysInstrumentFiles,
LangOpts.XRayNeverInstrumentFiles,
@@ -5043,7 +5043,12 @@ QualType ASTContext::getCanonicalTemplateSpecializationType(
"No dependent template names here!");
// Build the canonical template specialization type.
- TemplateName CanonTemplate = getCanonicalTemplateName(Template);
+ // Any DeducedTemplateNames are ignored, because the effective name of a TST
+ // accounts for the TST arguments laid over any default arguments contained in
+ // its name.
+ TemplateName CanonTemplate =
+ getCanonicalTemplateName(Template, /*IgnoreDeduced=*/true);
+
bool AnyNonCanonArgs = false;
auto CanonArgs =
::getCanonicalTemplateArguments(*this, Args, AnyNonCanonArgs);
@@ -6327,16 +6332,22 @@ 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 {
+TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name,
+ bool IgnoreDeduced) const {
+ while (std::optional<TemplateName> UnderlyingOrNone =
+ Name.desugar(IgnoreDeduced))
+ Name = *UnderlyingOrNone;
+
switch (Name.getKind()) {
- case TemplateName::UsingTemplate:
- case TemplateName::QualifiedTemplate:
case TemplateName::Template: {
TemplateDecl *Template = Name.getAsTemplateDecl();
if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template))
@@ -6356,12 +6367,6 @@ ASTContext::getCanonicalTemplateName(const TemplateName &Name) const {
return DTN->CanonicalTemplateName;
}
- case TemplateName::SubstTemplateTemplateParm: {
- SubstTemplateTemplateParmStorage *subst
- = Name.getAsSubstTemplateTemplateParm();
- return getCanonicalTemplateName(subst->getReplacement());
- }
-
case TemplateName::SubstTemplateTemplateParmPack: {
SubstTemplateTemplateParmPackStorage *subst =
Name.getAsSubstTemplateTemplateParmPack();
@@ -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<NamedDecl *> Params = CanonUnderlying.getAsTemplateDecl()
+ ->getTemplateParameters()
+ ->asArray();
+ assert(CanonArgs.size() <= Params.size());
+ for (int I = NumArgs; I >= 0; --I) {
+ switch (auto *Param = Params[I]; Param->getKind()) {
+ case NamedDecl::TemplateTypeParm:
+ if (handleParam(cast<TemplateTypeParmDecl>(Param), I))
+ break;
+ continue;
+ case NamedDecl::NonTypeTemplateParm:
+ if (handleParam(cast<NonTypeTemplateParmDecl>(Param), I))
+ break;
+ continue;
+ case NamedDecl::TemplateTemplateParm:
+ if (handleParam(cast<TemplateTemplateParmDecl>(Param), I))
+ break;
+ continue;
+ default:
+ llvm_unreachable("Unexpected template parameter kind");
+ }
+ break;
+ }
+ }
+ return NonCanonical ? getDeducedTemplateName(
+ CanonUnderlying,
+ /*DefaultArgs=*/{DefArgs.StartPos, CanonArgs})
+ : Name;
+ }
+ case TemplateName::UsingTemplate:
+ case TemplateName::QualifiedTemplate:
+ case TemplateName::SubstTemplateTemplateParm:
+ llvm_unreachable("always sugar node");
}
llvm_unreachable("bad template name!");
@@ -6868,7 +6937,7 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
case TemplateArgument::StructuralValue:
return TemplateArgument(*this,
getCanonicalType(Arg.getStructuralValueType()),
- Arg.getAsStructuralValue());
+ Arg.getAsStructuralValue(), Arg.getIsDefaulted());
case TemplateArgument::Type:
return TemplateArgument(getCanonicalType(Arg.getAsType()),
@@ -6880,8 +6949,10 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
*this, Arg.pack_elements(), AnyNonCanonArgs);
if (!AnyNonCanonArgs)
return Arg;
- return TemplateArgument::CreatePackCopy(const_cast<ASTContext &>(*this),
- CanonArgs);
+ auto NewArg = TemplateArgument::CreatePackCopy(
+ const_cast<ASTContext &>(*this), CanonArgs);
+ NewArg.setIsDefaulted(Arg.getIsDefaulted());
+ return NewArg;
}
}
@@ -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<ASTContext &>(*this);
+ llvm::FoldingSetNodeID ID;
+ DeducedTemplateStorage::Profile(ID, Self, Underlying, DefaultArgs);
+
+ void *InsertPos = nullptr;
+ DeducedTemplateStorage *DTS =
+ DeducedTemplates.FindNodeOrInsertPos(ID, InsertPos);
+ if (!DTS) {
+ void *Mem = Allocate(sizeof(DeducedTemplateStorage) +
+ sizeof(TemplateArgument) * DefaultArgs.Args.size(),
+ alignof(DeducedTemplateStorage));
+ DTS = new (Mem) DeducedTemplateStorage(Underlying, DefaultArgs);
+ DeducedTemplates.InsertNode(DTS, InsertPos);
+ }
+
+ return TemplateName(DTS);
+}
+
/// getFromTargetType - Given one of the integer types provided by
/// TargetInfo, produce the corresponding type. The unsigned @p Type
/// is actually a value of type @c TargetInfo::IntType.
diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp
index 0680ff5e3a385..18463d72514b1 100644
--- a/clang/lib/AST/ASTDiagnostic.cpp
+++ b/clang/lib/AST/ASTDiagnostic.cpp
@@ -1114,8 +1114,8 @@ class TemplateDiff {
// These functions build up the template diff tree, including functions to
// retrieve and compare temp...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/94981
More information about the cfe-commits
mailing list