2017-11-21 23:26:08 +00:00
|
|
|
//===- TemplateName.cpp - C++ Template Name Representation ----------------===//
|
2009-03-30 22:58:21 +00:00
|
|
|
//
|
2019-01-19 08:50:56 +00:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2009-03-30 22:58:21 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file defines the TemplateName interface and subclasses.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2009-04-02 06:07:12 +00:00
|
|
|
|
2009-03-30 22:58:21 +00:00
|
|
|
#include "clang/AST/TemplateName.h"
|
[AST] Refactor propagation of dependency bits. NFC
Summary:
This changes introduces an enum to represent dependencies as a bitmask
and extract common patterns from code that computes dependency bits into
helper functions.
Reviewers: rsmith, martong, shafik, ilya-biryukov, hokein
Subscribers: hokein, sammccall, Mordante, riccibruno, merge_guards_bot, rnkovacs, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71920
2020-03-02 16:07:09 +01:00
|
|
|
#include "clang/AST/Decl.h"
|
2017-11-21 23:26:08 +00:00
|
|
|
#include "clang/AST/DeclBase.h"
|
2022-04-12 15:51:16 +02:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
2009-03-30 22:58:21 +00:00
|
|
|
#include "clang/AST/DeclTemplate.h"
|
2020-03-16 13:43:40 +01:00
|
|
|
#include "clang/AST/DependenceFlags.h"
|
2009-03-30 22:58:21 +00:00
|
|
|
#include "clang/AST/NestedNameSpecifier.h"
|
2009-05-29 20:38:28 +00:00
|
|
|
#include "clang/AST/PrettyPrinter.h"
|
2012-12-04 09:13:33 +00:00
|
|
|
#include "clang/AST/TemplateBase.h"
|
2010-04-08 00:03:06 +00:00
|
|
|
#include "clang/Basic/Diagnostic.h"
|
2017-11-21 23:26:08 +00:00
|
|
|
#include "clang/Basic/LLVM.h"
|
2009-06-30 01:26:17 +00:00
|
|
|
#include "clang/Basic/LangOptions.h"
|
2017-11-21 23:26:08 +00:00
|
|
|
#include "clang/Basic/OperatorKinds.h"
|
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
|
|
#include "llvm/ADT/FoldingSet.h"
|
|
|
|
#include "llvm/Support/Compiler.h"
|
2009-03-30 22:58:21 +00:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2017-11-21 23:26:08 +00:00
|
|
|
#include <cassert>
|
2023-01-14 11:07:21 -08:00
|
|
|
#include <optional>
|
2017-11-21 23:26:08 +00:00
|
|
|
#include <string>
|
|
|
|
|
2009-03-30 22:58:21 +00:00
|
|
|
using namespace clang;
|
|
|
|
|
[clang] Implement CWG2398 provisional TTP matching to class templates (#94981)
This extends default argument deduction to cover class templates as
well, applying only to 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.
2024-09-07 15:49:07 -03:00
|
|
|
DeducedTemplateStorage::DeducedTemplateStorage(TemplateName Underlying,
|
|
|
|
const DefaultArguments &DefArgs)
|
|
|
|
: UncommonTemplateNameStorage(Deduced, /*Index=*/DefArgs.StartPos,
|
|
|
|
DefArgs.Args.size()),
|
|
|
|
Underlying(Underlying) {
|
|
|
|
llvm::copy(DefArgs.Args, reinterpret_cast<TemplateArgument *>(this + 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeducedTemplateStorage::Profile(llvm::FoldingSetNodeID &ID,
|
|
|
|
const ASTContext &Context) const {
|
|
|
|
Profile(ID, Context, Underlying, getDefaultArguments());
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeducedTemplateStorage::Profile(llvm::FoldingSetNodeID &ID,
|
|
|
|
const ASTContext &Context,
|
|
|
|
TemplateName Underlying,
|
|
|
|
const DefaultArguments &DefArgs) {
|
|
|
|
Underlying.Profile(ID);
|
|
|
|
ID.AddInteger(DefArgs.StartPos);
|
|
|
|
ID.AddInteger(DefArgs.Args.size());
|
|
|
|
for (const TemplateArgument &Arg : DefArgs.Args)
|
|
|
|
Arg.Profile(ID, Context);
|
|
|
|
}
|
|
|
|
|
2018-07-30 19:24:48 +00:00
|
|
|
TemplateArgument
|
2011-01-15 06:45:20 +00:00
|
|
|
SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
|
2023-01-06 16:56:23 +01:00
|
|
|
return TemplateArgument(llvm::ArrayRef(Arguments, Bits.Data));
|
2022-08-14 13:48:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTemplateParmDecl *
|
|
|
|
SubstTemplateTemplateParmPackStorage::getParameterPack() const {
|
|
|
|
return cast<TemplateTemplateParmDecl>(
|
|
|
|
getReplacedTemplateParameterList(getAssociatedDecl())
|
|
|
|
->asArray()[Bits.Index]);
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTemplateParmDecl *
|
|
|
|
SubstTemplateTemplateParmStorage::getParameter() const {
|
|
|
|
return cast<TemplateTemplateParmDecl>(
|
|
|
|
getReplacedTemplateParameterList(getAssociatedDecl())
|
|
|
|
->asArray()[Bits.Index]);
|
2011-01-15 06:45:20 +00:00
|
|
|
}
|
|
|
|
|
2011-06-30 08:33:18 +00:00
|
|
|
void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
|
2025-04-02 19:27:29 -03:00
|
|
|
Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex(),
|
|
|
|
getFinal());
|
2011-06-30 08:33:18 +00:00
|
|
|
}
|
|
|
|
|
2023-01-14 12:31:01 -08:00
|
|
|
void SubstTemplateTemplateParmStorage::Profile(
|
|
|
|
llvm::FoldingSetNodeID &ID, TemplateName Replacement, Decl *AssociatedDecl,
|
2025-04-03 14:27:18 -03:00
|
|
|
unsigned Index, UnsignedOrNone PackIndex, bool Final) {
|
2022-08-14 13:48:18 +02:00
|
|
|
Replacement.Profile(ID);
|
|
|
|
ID.AddPointer(AssociatedDecl);
|
|
|
|
ID.AddInteger(Index);
|
2025-04-03 14:27:18 -03:00
|
|
|
ID.AddInteger(PackIndex.toInternalRepresentation());
|
2025-04-02 19:27:29 -03:00
|
|
|
ID.AddBoolean(Final);
|
2011-06-30 08:33:18 +00:00
|
|
|
}
|
|
|
|
|
2022-09-25 17:18:39 +02:00
|
|
|
SubstTemplateTemplateParmPackStorage::SubstTemplateTemplateParmPackStorage(
|
|
|
|
ArrayRef<TemplateArgument> ArgPack, Decl *AssociatedDecl, unsigned Index,
|
|
|
|
bool Final)
|
|
|
|
: UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Index,
|
|
|
|
ArgPack.size()),
|
|
|
|
Arguments(ArgPack.data()), AssociatedDeclAndFinal(AssociatedDecl, Final) {
|
|
|
|
assert(AssociatedDecl != nullptr);
|
|
|
|
}
|
|
|
|
|
2011-06-30 08:33:18 +00:00
|
|
|
void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
|
|
|
|
ASTContext &Context) {
|
2022-09-25 17:18:39 +02:00
|
|
|
Profile(ID, Context, getArgumentPack(), getAssociatedDecl(), getIndex(),
|
|
|
|
getFinal());
|
|
|
|
}
|
|
|
|
|
|
|
|
Decl *SubstTemplateTemplateParmPackStorage::getAssociatedDecl() const {
|
|
|
|
return AssociatedDeclAndFinal.getPointer();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SubstTemplateTemplateParmPackStorage::getFinal() const {
|
|
|
|
return AssociatedDeclAndFinal.getInt();
|
2011-01-15 06:45:20 +00:00
|
|
|
}
|
|
|
|
|
2022-08-14 13:48:18 +02:00
|
|
|
void SubstTemplateTemplateParmPackStorage::Profile(
|
|
|
|
llvm::FoldingSetNodeID &ID, ASTContext &Context,
|
2022-09-25 17:18:39 +02:00
|
|
|
const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index,
|
|
|
|
bool Final) {
|
2011-01-15 06:45:20 +00:00
|
|
|
ArgPack.Profile(ID, Context);
|
2022-08-14 13:48:18 +02:00
|
|
|
ID.AddPointer(AssociatedDecl);
|
|
|
|
ID.AddInteger(Index);
|
2022-09-25 17:18:39 +02:00
|
|
|
ID.AddBoolean(Final);
|
2011-01-15 06:45:20 +00:00
|
|
|
}
|
|
|
|
|
2025-04-01 17:15:18 -03:00
|
|
|
IdentifierOrOverloadedOperator::IdentifierOrOverloadedOperator(
|
|
|
|
const IdentifierInfo *II)
|
|
|
|
: PtrOrOp(reinterpret_cast<uintptr_t>(II)) {
|
|
|
|
static_assert(NUM_OVERLOADED_OPERATORS <= 4096,
|
|
|
|
"NUM_OVERLOADED_OPERATORS is too large");
|
|
|
|
assert(II);
|
|
|
|
assert(getIdentifier() == II);
|
|
|
|
}
|
|
|
|
IdentifierOrOverloadedOperator::IdentifierOrOverloadedOperator(
|
|
|
|
OverloadedOperatorKind OOK)
|
|
|
|
: PtrOrOp(-uintptr_t(OOK)) {
|
|
|
|
assert(OOK != OO_None);
|
|
|
|
assert(getOperator() == OOK);
|
|
|
|
}
|
|
|
|
|
|
|
|
void IdentifierOrOverloadedOperator::Profile(llvm::FoldingSetNodeID &ID) const {
|
|
|
|
if (auto *Identifier = getIdentifier()) {
|
|
|
|
ID.AddBoolean(false);
|
|
|
|
ID.AddPointer(Identifier);
|
|
|
|
} else {
|
|
|
|
ID.AddBoolean(true);
|
|
|
|
ID.AddInteger(getOperator());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-30 06:21:02 +00:00
|
|
|
TemplateName::TemplateName(void *Ptr) {
|
|
|
|
Storage = StorageType::getFromOpaqueValue(Ptr);
|
|
|
|
}
|
|
|
|
|
2015-12-30 03:24:14 +00:00
|
|
|
TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
|
|
|
|
TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
|
|
|
|
: Storage(Storage) {}
|
2019-05-09 03:31:27 +00:00
|
|
|
TemplateName::TemplateName(AssumedTemplateStorage *Storage)
|
|
|
|
: Storage(Storage) {}
|
2015-12-30 03:24:14 +00:00
|
|
|
TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
|
|
|
|
: Storage(Storage) {}
|
|
|
|
TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
|
|
|
|
: Storage(Storage) {}
|
|
|
|
TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
|
|
|
|
TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
|
2022-04-12 15:51:16 +02:00
|
|
|
TemplateName::TemplateName(UsingShadowDecl *Using) : Storage(Using) {}
|
[clang] Implement CWG2398 provisional TTP matching to class templates (#94981)
This extends default argument deduction to cover class templates as
well, applying only to 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.
2024-09-07 15:49:07 -03:00
|
|
|
TemplateName::TemplateName(DeducedTemplateStorage *Deduced)
|
|
|
|
: Storage(Deduced) {}
|
2015-12-30 03:24:14 +00:00
|
|
|
|
|
|
|
bool TemplateName::isNull() const { return Storage.isNull(); }
|
|
|
|
|
2010-06-19 19:28:53 +00:00
|
|
|
TemplateName::NameKind TemplateName::getKind() const {
|
2025-02-01 08:13:20 -08:00
|
|
|
if (auto *ND = dyn_cast<Decl *>(Storage)) {
|
2022-04-12 15:51:16 +02:00
|
|
|
if (isa<UsingShadowDecl>(ND))
|
|
|
|
return UsingTemplate;
|
|
|
|
assert(isa<TemplateDecl>(ND));
|
2010-06-19 19:28:53 +00:00
|
|
|
return Template;
|
2022-04-12 15:51:16 +02:00
|
|
|
}
|
|
|
|
|
2024-11-24 07:28:20 -08:00
|
|
|
if (isa<DependentTemplateName *>(Storage))
|
2011-01-15 06:45:20 +00:00
|
|
|
return DependentTemplate;
|
2024-11-24 07:28:20 -08:00
|
|
|
if (isa<QualifiedTemplateName *>(Storage))
|
2010-06-19 19:28:53 +00:00
|
|
|
return QualifiedTemplate;
|
2011-06-30 08:33:18 +00:00
|
|
|
|
2024-11-24 07:28:20 -08:00
|
|
|
UncommonTemplateNameStorage *uncommon =
|
|
|
|
cast<UncommonTemplateNameStorage *>(Storage);
|
2011-06-30 08:33:18 +00:00
|
|
|
if (uncommon->getAsOverloadedStorage())
|
|
|
|
return OverloadedTemplate;
|
2019-05-09 03:31:27 +00:00
|
|
|
if (uncommon->getAsAssumedTemplateName())
|
|
|
|
return AssumedTemplate;
|
2011-06-30 08:33:18 +00:00
|
|
|
if (uncommon->getAsSubstTemplateTemplateParm())
|
|
|
|
return SubstTemplateTemplateParm;
|
[clang] Implement CWG2398 provisional TTP matching to class templates (#94981)
This extends default argument deduction to cover class templates as
well, applying only to 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.
2024-09-07 15:49:07 -03:00
|
|
|
if (uncommon->getAsDeducedTemplateName())
|
|
|
|
return DeducedTemplate;
|
|
|
|
|
|
|
|
assert(uncommon->getAsSubstTemplateTemplateParmPack() != nullptr);
|
2011-06-30 08:33:18 +00:00
|
|
|
return SubstTemplateTemplateParmPack;
|
2010-06-19 19:28:53 +00:00
|
|
|
}
|
|
|
|
|
[clang] Implement CWG2398 provisional TTP matching to class templates (#94981)
This extends default argument deduction to cover class templates as
well, applying only to 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.
2024-09-07 15:49:07 -03:00
|
|
|
TemplateDecl *TemplateName::getAsTemplateDecl(bool IgnoreDeduced) const {
|
|
|
|
TemplateName Name = *this;
|
|
|
|
while (std::optional<TemplateName> UnderlyingOrNone =
|
|
|
|
Name.desugar(IgnoreDeduced))
|
|
|
|
Name = *UnderlyingOrNone;
|
2009-09-09 15:08:12 +00:00
|
|
|
|
[clang] Implement CWG2398 provisional TTP matching to class templates (#94981)
This extends default argument deduction to cover class templates as
well, applying only to 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.
2024-09-07 15:49:07 -03:00
|
|
|
if (!IgnoreDeduced)
|
|
|
|
assert(Name.getAsDeducedTemplateName() == nullptr &&
|
|
|
|
"Unexpected canonical DeducedTemplateName; Did you mean to use "
|
|
|
|
"getTemplateDeclAndDefaultArgs instead?");
|
2009-03-30 22:58:21 +00:00
|
|
|
|
2025-01-25 14:05:01 -08:00
|
|
|
return cast_if_present<TemplateDecl>(
|
|
|
|
dyn_cast_if_present<Decl *>(Name.Storage));
|
[clang] Implement CWG2398 provisional TTP matching to class templates (#94981)
This extends default argument deduction to cover class templates as
well, applying only to 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.
2024-09-07 15:49:07 -03:00
|
|
|
}
|
2011-06-30 08:33:18 +00:00
|
|
|
|
[clang] Implement CWG2398 provisional TTP matching to class templates (#94981)
This extends default argument deduction to cover class templates as
well, applying only to 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.
2024-09-07 15:49:07 -03:00
|
|
|
std::pair<TemplateDecl *, DefaultArguments>
|
|
|
|
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<TemplateName> UnderlyingOrNone =
|
|
|
|
Name.desugar(/*IgnoreDeduced=*/false)) {
|
|
|
|
Name = *UnderlyingOrNone;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
return {cast_if_present<TemplateDecl>(Name.Storage.dyn_cast<Decl *>()), {}};
|
|
|
|
}
|
|
|
|
}
|
2022-04-12 15:51:16 +02:00
|
|
|
|
[clang] Implement CWG2398 provisional TTP matching to class templates (#94981)
This extends default argument deduction to cover class templates as
well, applying only to 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.
2024-09-07 15:49:07 -03:00
|
|
|
std::optional<TemplateName> TemplateName::desugar(bool IgnoreDeduced) const {
|
2025-01-25 14:05:01 -08:00
|
|
|
if (Decl *D = dyn_cast_if_present<Decl *>(Storage)) {
|
[clang] Implement CWG2398 provisional TTP matching to class templates (#94981)
This extends default argument deduction to cover class templates as
well, applying only to 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.
2024-09-07 15:49:07 -03:00
|
|
|
if (auto *USD = dyn_cast<UsingShadowDecl>(D))
|
|
|
|
return TemplateName(USD->getTargetDecl());
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
|
|
|
|
return QTN->getUnderlyingTemplate();
|
|
|
|
if (SubstTemplateTemplateParmStorage *S = getAsSubstTemplateTemplateParm())
|
|
|
|
return S->getReplacement();
|
|
|
|
if (IgnoreDeduced)
|
|
|
|
if (DeducedTemplateStorage *S = getAsDeducedTemplateName())
|
|
|
|
return S->getUnderlying();
|
|
|
|
return std::nullopt;
|
2009-03-30 22:58:21 +00:00
|
|
|
}
|
|
|
|
|
2015-12-30 03:24:14 +00:00
|
|
|
OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
|
|
|
|
if (UncommonTemplateNameStorage *Uncommon =
|
|
|
|
Storage.dyn_cast<UncommonTemplateNameStorage *>())
|
|
|
|
return Uncommon->getAsOverloadedStorage();
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-05-09 03:31:27 +00:00
|
|
|
AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const {
|
|
|
|
if (UncommonTemplateNameStorage *Uncommon =
|
|
|
|
Storage.dyn_cast<UncommonTemplateNameStorage *>())
|
|
|
|
return Uncommon->getAsAssumedTemplateName();
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-12-30 03:24:14 +00:00
|
|
|
SubstTemplateTemplateParmStorage *
|
|
|
|
TemplateName::getAsSubstTemplateTemplateParm() const {
|
|
|
|
if (UncommonTemplateNameStorage *uncommon =
|
2025-01-25 14:05:01 -08:00
|
|
|
dyn_cast_if_present<UncommonTemplateNameStorage *>(Storage))
|
2015-12-30 03:24:14 +00:00
|
|
|
return uncommon->getAsSubstTemplateTemplateParm();
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
SubstTemplateTemplateParmPackStorage *
|
|
|
|
TemplateName::getAsSubstTemplateTemplateParmPack() const {
|
|
|
|
if (UncommonTemplateNameStorage *Uncommon =
|
|
|
|
Storage.dyn_cast<UncommonTemplateNameStorage *>())
|
|
|
|
return Uncommon->getAsSubstTemplateTemplateParmPack();
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
|
2025-01-25 14:05:01 -08:00
|
|
|
return dyn_cast_if_present<QualifiedTemplateName *>(Storage);
|
2015-12-30 03:24:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
|
|
|
|
return Storage.dyn_cast<DependentTemplateName *>();
|
|
|
|
}
|
|
|
|
|
2022-04-12 15:51:16 +02:00
|
|
|
UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {
|
|
|
|
if (Decl *D = Storage.dyn_cast<Decl *>())
|
|
|
|
if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
|
|
|
|
return USD;
|
2022-04-26 09:34:46 +02:00
|
|
|
if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
|
|
|
|
return QTN->getUnderlyingTemplate().getAsUsingShadowDecl();
|
2022-04-12 15:51:16 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2025-04-01 17:15:18 -03:00
|
|
|
DependentTemplateStorage::DependentTemplateStorage(
|
|
|
|
NestedNameSpecifier *Qualifier, IdentifierOrOverloadedOperator Name,
|
|
|
|
bool HasTemplateKeyword)
|
|
|
|
: Qualifier(Qualifier, HasTemplateKeyword), Name(Name) {
|
|
|
|
assert((!Qualifier || Qualifier->isDependent()) &&
|
|
|
|
"Qualifier must be dependent");
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateNameDependence DependentTemplateStorage::getDependence() const {
|
|
|
|
auto D = TemplateNameDependence::DependentInstantiation;
|
|
|
|
if (NestedNameSpecifier *Qualifier = getQualifier())
|
|
|
|
D |= toTemplateNameDependence(Qualifier->getDependence());
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DependentTemplateStorage::print(raw_ostream &OS,
|
|
|
|
const PrintingPolicy &Policy) const {
|
|
|
|
if (NestedNameSpecifier *NNS = getQualifier())
|
|
|
|
NNS->print(OS, Policy);
|
|
|
|
|
|
|
|
if (hasTemplateKeyword())
|
|
|
|
OS << "template ";
|
|
|
|
|
|
|
|
IdentifierOrOverloadedOperator Name = getName();
|
|
|
|
if (const IdentifierInfo *II = Name.getIdentifier())
|
|
|
|
OS << II->getName();
|
|
|
|
else
|
|
|
|
OS << "operator " << getOperatorSpelling(Name.getOperator());
|
|
|
|
}
|
|
|
|
|
[clang] Implement CWG2398 provisional TTP matching to class templates (#94981)
This extends default argument deduction to cover class templates as
well, applying only to 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.
2024-09-07 15:49:07 -03:00
|
|
|
DeducedTemplateStorage *TemplateName::getAsDeducedTemplateName() const {
|
|
|
|
if (UncommonTemplateNameStorage *Uncommon =
|
2025-01-25 14:05:01 -08:00
|
|
|
dyn_cast_if_present<UncommonTemplateNameStorage *>(Storage))
|
[clang] Implement CWG2398 provisional TTP matching to class templates (#94981)
This extends default argument deduction to cover class templates as
well, applying only to 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.
2024-09-07 15:49:07 -03:00
|
|
|
return Uncommon->getAsDeducedTemplateName();
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
[AST] Refactor propagation of dependency bits. NFC
Summary:
This changes introduces an enum to represent dependencies as a bitmask
and extract common patterns from code that computes dependency bits into
helper functions.
Reviewers: rsmith, martong, shafik, ilya-biryukov, hokein
Subscribers: hokein, sammccall, Mordante, riccibruno, merge_guards_bot, rnkovacs, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71920
2020-03-02 16:07:09 +01:00
|
|
|
TemplateNameDependence TemplateName::getDependence() const {
|
|
|
|
switch (getKind()) {
|
[clang] Implement CWG2398 provisional TTP matching to class templates (#94981)
This extends default argument deduction to cover class templates as
well, applying only to 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.
2024-09-07 15:49:07 -03:00
|
|
|
case NameKind::Template:
|
|
|
|
case NameKind::UsingTemplate: {
|
|
|
|
TemplateDecl *Template = getAsTemplateDecl();
|
|
|
|
auto D = TemplateNameDependence::None;
|
[AST] Refactor propagation of dependency bits. NFC
Summary:
This changes introduces an enum to represent dependencies as a bitmask
and extract common patterns from code that computes dependency bits into
helper functions.
Reviewers: rsmith, martong, shafik, ilya-biryukov, hokein
Subscribers: hokein, sammccall, Mordante, riccibruno, merge_guards_bot, rnkovacs, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71920
2020-03-02 16:07:09 +01:00
|
|
|
if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
|
|
|
|
D |= TemplateNameDependence::DependentInstantiation;
|
|
|
|
if (TTP->isParameterPack())
|
|
|
|
D |= TemplateNameDependence::UnexpandedPack;
|
|
|
|
}
|
2010-09-08 19:31:22 +00:00
|
|
|
// FIXME: Hack, getDeclContext() can be null if Template is still
|
|
|
|
// initializing due to PCH reading, so we check it before using it.
|
|
|
|
// Should probably modify TemplateSpecializationType to allow constructing
|
|
|
|
// it without the isDependent() checking.
|
[AST] Refactor propagation of dependency bits. NFC
Summary:
This changes introduces an enum to represent dependencies as a bitmask
and extract common patterns from code that computes dependency bits into
helper functions.
Reviewers: rsmith, martong, shafik, ilya-biryukov, hokein
Subscribers: hokein, sammccall, Mordante, riccibruno, merge_guards_bot, rnkovacs, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71920
2020-03-02 16:07:09 +01:00
|
|
|
if (Template->getDeclContext() &&
|
|
|
|
Template->getDeclContext()->isDependentContext())
|
|
|
|
D |= TemplateNameDependence::DependentInstantiation;
|
[clang] Implement CWG2398 provisional TTP matching to class templates (#94981)
This extends default argument deduction to cover class templates as
well, applying only to 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.
2024-09-07 15:49:07 -03:00
|
|
|
return D;
|
|
|
|
}
|
|
|
|
case NameKind::QualifiedTemplate: {
|
|
|
|
QualifiedTemplateName *S = getAsQualifiedTemplateName();
|
|
|
|
TemplateNameDependence D = S->getUnderlyingTemplate().getDependence();
|
|
|
|
if (NestedNameSpecifier *NNS = S->getQualifier())
|
|
|
|
D |= toTemplateNameDependence(NNS->getDependence());
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
case NameKind::DependentTemplate: {
|
|
|
|
DependentTemplateName *S = getAsDependentTemplateName();
|
|
|
|
auto D = TemplateNameDependence::DependentInstantiation;
|
2025-04-01 17:15:18 -03:00
|
|
|
if (NestedNameSpecifier *Qualifier = S->getQualifier())
|
|
|
|
D |= toTemplateNameDependence(Qualifier->getDependence());
|
[clang] Implement CWG2398 provisional TTP matching to class templates (#94981)
This extends default argument deduction to cover class templates as
well, applying only to 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.
2024-09-07 15:49:07 -03:00
|
|
|
return D;
|
|
|
|
}
|
|
|
|
case NameKind::SubstTemplateTemplateParm: {
|
|
|
|
auto *S = getAsSubstTemplateTemplateParm();
|
|
|
|
return S->getReplacement().getDependence();
|
|
|
|
}
|
|
|
|
case NameKind::SubstTemplateTemplateParmPack:
|
|
|
|
return TemplateNameDependence::UnexpandedPack |
|
|
|
|
TemplateNameDependence::DependentInstantiation;
|
|
|
|
case NameKind::DeducedTemplate: {
|
|
|
|
DeducedTemplateStorage *DTS = getAsDeducedTemplateName();
|
|
|
|
TemplateNameDependence D = DTS->getUnderlying().getDependence();
|
|
|
|
for (const TemplateArgument &Arg : DTS->getDefaultArguments().Args)
|
|
|
|
D |= toTemplateNameDependence(Arg.getDependence());
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
case NameKind::AssumedTemplate:
|
|
|
|
return TemplateNameDependence::DependentInstantiation;
|
|
|
|
case NameKind::OverloadedTemplate:
|
|
|
|
llvm_unreachable("overloaded templates shouldn't survive to here.");
|
2009-03-30 22:58:21 +00:00
|
|
|
}
|
[clang] Implement CWG2398 provisional TTP matching to class templates (#94981)
This extends default argument deduction to cover class templates as
well, applying only to 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.
2024-09-07 15:49:07 -03:00
|
|
|
llvm_unreachable("Unknown TemplateName kind");
|
[AST] Refactor propagation of dependency bits. NFC
Summary:
This changes introduces an enum to represent dependencies as a bitmask
and extract common patterns from code that computes dependency bits into
helper functions.
Reviewers: rsmith, martong, shafik, ilya-biryukov, hokein
Subscribers: hokein, sammccall, Mordante, riccibruno, merge_guards_bot, rnkovacs, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71920
2020-03-02 16:07:09 +01:00
|
|
|
}
|
2009-03-30 22:58:21 +00:00
|
|
|
|
[AST] Refactor propagation of dependency bits. NFC
Summary:
This changes introduces an enum to represent dependencies as a bitmask
and extract common patterns from code that computes dependency bits into
helper functions.
Reviewers: rsmith, martong, shafik, ilya-biryukov, hokein
Subscribers: hokein, sammccall, Mordante, riccibruno, merge_guards_bot, rnkovacs, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71920
2020-03-02 16:07:09 +01:00
|
|
|
bool TemplateName::isDependent() const {
|
|
|
|
return getDependence() & TemplateNameDependence::Dependent;
|
2009-03-30 22:58:21 +00:00
|
|
|
}
|
|
|
|
|
2011-07-01 01:22:09 +00:00
|
|
|
bool TemplateName::isInstantiationDependent() const {
|
[AST] Refactor propagation of dependency bits. NFC
Summary:
This changes introduces an enum to represent dependencies as a bitmask
and extract common patterns from code that computes dependency bits into
helper functions.
Reviewers: rsmith, martong, shafik, ilya-biryukov, hokein
Subscribers: hokein, sammccall, Mordante, riccibruno, merge_guards_bot, rnkovacs, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71920
2020-03-02 16:07:09 +01:00
|
|
|
return getDependence() & TemplateNameDependence::Instantiation;
|
2011-07-01 01:22:09 +00:00
|
|
|
}
|
|
|
|
|
Variadic templates: extend Type, NestedNameSpecifier, TemplateName,
and TemplateArgument with an operation that determines whether there
are any unexpanded parameter packs within that construct. Use this
information to diagnose the appearance of the names of parameter packs
that have not been expanded (C++ [temp.variadic]p5). Since this
property is checked often (every declaration, ever expression
statement, etc.), we extend Type and Expr with a bit storing the
result of this computation, rather than walking the AST each time to
determine whether any unexpanded parameter packs occur.
This commit is deficient in several ways, which will be remedied with
future commits:
- Expr has a bit to store the presence of an unexpanded parameter
pack, but it is never set.
- The error messages don't point out where the unexpanded parameter
packs were named in the type/expression, but they should.
- We don't check for unexpanded parameter packs in all of the places
where we should.
- Testing is sparse, pending the resolution of the above three
issues.
llvm-svn: 121724
2010-12-13 22:49:22 +00:00
|
|
|
bool TemplateName::containsUnexpandedParameterPack() const {
|
[AST] Refactor propagation of dependency bits. NFC
Summary:
This changes introduces an enum to represent dependencies as a bitmask
and extract common patterns from code that computes dependency bits into
helper functions.
Reviewers: rsmith, martong, shafik, ilya-biryukov, hokein
Subscribers: hokein, sammccall, Mordante, riccibruno, merge_guards_bot, rnkovacs, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71920
2020-03-02 16:07:09 +01:00
|
|
|
return getDependence() & TemplateNameDependence::UnexpandedPack;
|
Variadic templates: extend Type, NestedNameSpecifier, TemplateName,
and TemplateArgument with an operation that determines whether there
are any unexpanded parameter packs within that construct. Use this
information to diagnose the appearance of the names of parameter packs
that have not been expanded (C++ [temp.variadic]p5). Since this
property is checked often (every declaration, ever expression
statement, etc.), we extend Type and Expr with a bit storing the
result of this computation, rather than walking the AST each time to
determine whether any unexpanded parameter packs occur.
This commit is deficient in several ways, which will be remedied with
future commits:
- Expr has a bit to store the presence of an unexpanded parameter
pack, but it is never set.
- The error messages don't point out where the unexpanded parameter
packs were named in the type/expression, but they should.
- We don't check for unexpanded parameter packs in all of the places
where we should.
- Testing is sparse, pending the resolution of the above three
issues.
llvm-svn: 121724
2010-12-13 22:49:22 +00:00
|
|
|
}
|
|
|
|
|
2021-08-26 16:54:47 -07:00
|
|
|
void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
|
|
|
|
Qualified Qual) const {
|
2025-04-14 12:59:36 -03:00
|
|
|
auto handleAnonymousTTP = [&](TemplateDecl *TD, raw_ostream &OS) {
|
2024-05-29 21:45:01 -03:00
|
|
|
if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(TD);
|
2025-04-14 12:59:36 -03:00
|
|
|
TTP && (Policy.PrintAsCanonical || TTP->getIdentifier() == nullptr)) {
|
2024-05-29 21:45:01 -03:00
|
|
|
OS << "template-parameter-" << TTP->getDepth() << "-" << TTP->getIndex();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
2024-05-29 17:02:15 -03:00
|
|
|
if (NameKind Kind = getKind();
|
|
|
|
Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) {
|
2022-04-12 15:51:16 +02:00
|
|
|
// After `namespace ns { using std::vector }`, what is the fully-qualified
|
|
|
|
// name of the UsingTemplateName `vector` within ns?
|
|
|
|
//
|
|
|
|
// - ns::vector (the qualified name of the using-shadow decl)
|
|
|
|
// - std::vector (the qualified name of the underlying template decl)
|
|
|
|
//
|
|
|
|
// Similar to the UsingType behavior, using declarations are used to import
|
|
|
|
// names more often than to export them, thus using the original name is
|
|
|
|
// most useful in this case.
|
2024-05-29 17:02:15 -03:00
|
|
|
TemplateDecl *Template = getAsTemplateDecl();
|
2025-04-14 12:59:36 -03:00
|
|
|
if (Policy.PrintAsCanonical)
|
|
|
|
Template = cast<TemplateDecl>(Template->getCanonicalDecl());
|
2024-05-29 21:45:01 -03:00
|
|
|
if (handleAnonymousTTP(Template, OS))
|
|
|
|
return;
|
2024-05-29 17:02:15 -03:00
|
|
|
if (Qual == Qualified::None)
|
2021-08-26 16:54:47 -07:00
|
|
|
OS << *Template;
|
2024-05-29 17:02:15 -03:00
|
|
|
else
|
|
|
|
Template->printQualifiedName(OS, Policy);
|
|
|
|
} else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
|
2025-04-14 12:59:36 -03:00
|
|
|
if (Policy.PrintAsCanonical) {
|
|
|
|
QTN->getUnderlyingTemplate().print(OS, Policy, Qual);
|
|
|
|
return;
|
|
|
|
}
|
2024-05-29 17:02:15 -03:00
|
|
|
if (NestedNameSpecifier *NNS = QTN->getQualifier();
|
|
|
|
Qual != Qualified::None && NNS)
|
|
|
|
NNS->print(OS, Policy);
|
2009-03-30 22:58:21 +00:00
|
|
|
if (QTN->hasTemplateKeyword())
|
|
|
|
OS << "template ";
|
2024-05-29 17:02:15 -03:00
|
|
|
|
|
|
|
TemplateName Underlying = QTN->getUnderlyingTemplate();
|
|
|
|
assert(Underlying.getKind() == TemplateName::Template ||
|
|
|
|
Underlying.getKind() == TemplateName::UsingTemplate);
|
|
|
|
|
|
|
|
TemplateDecl *UTD = Underlying.getAsTemplateDecl();
|
2024-05-29 21:45:01 -03:00
|
|
|
|
|
|
|
if (handleAnonymousTTP(UTD, OS))
|
|
|
|
return;
|
|
|
|
|
2024-05-29 17:02:15 -03:00
|
|
|
if (IdentifierInfo *II = UTD->getIdentifier();
|
|
|
|
Policy.CleanUglifiedParameters && II &&
|
|
|
|
isa<TemplateTemplateParmDecl>(UTD))
|
|
|
|
OS << II->deuglifiedName();
|
|
|
|
else
|
|
|
|
OS << *UTD;
|
2009-03-30 22:58:21 +00:00
|
|
|
} else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
|
2025-04-01 17:15:18 -03:00
|
|
|
DTN->print(OS, Policy);
|
2024-05-29 17:02:15 -03:00
|
|
|
} else if (SubstTemplateTemplateParmStorage *subst =
|
|
|
|
getAsSubstTemplateTemplateParm()) {
|
2021-08-26 16:54:47 -07:00
|
|
|
subst->getReplacement().print(OS, Policy, Qual);
|
2024-05-29 17:02:15 -03:00
|
|
|
} else if (SubstTemplateTemplateParmPackStorage *SubstPack =
|
|
|
|
getAsSubstTemplateTemplateParmPack())
|
2012-02-07 11:57:57 +00:00
|
|
|
OS << *SubstPack->getParameterPack();
|
2019-05-09 03:31:27 +00:00
|
|
|
else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
|
|
|
|
Assumed->getDeclName().print(OS, Policy);
|
[clang] Implement CWG2398 provisional TTP matching to class templates (#94981)
This extends default argument deduction to cover class templates as
well, applying only to 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.
2024-09-07 15:49:07 -03:00
|
|
|
} else if (DeducedTemplateStorage *Deduced = getAsDeducedTemplateName()) {
|
|
|
|
Deduced->getUnderlying().print(OS, Policy);
|
|
|
|
DefaultArguments DefArgs = Deduced->getDefaultArguments();
|
|
|
|
OS << ":" << DefArgs.StartPos;
|
|
|
|
printTemplateArgumentList(OS, DefArgs.Args, Policy);
|
2019-05-09 03:31:27 +00:00
|
|
|
} else {
|
2022-04-12 15:51:16 +02:00
|
|
|
assert(getKind() == TemplateName::OverloadedTemplate);
|
2011-03-04 21:37:14 +00:00
|
|
|
OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
|
2022-10-14 08:17:16 -04:00
|
|
|
(*OTS->begin())->printName(OS, Policy);
|
2011-03-04 21:37:14 +00:00
|
|
|
}
|
2009-03-30 22:58:21 +00:00
|
|
|
}
|
2009-03-31 18:38:02 +00:00
|
|
|
|
2020-09-23 16:16:00 -04:00
|
|
|
const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
|
|
|
|
TemplateName N) {
|
2010-04-08 00:03:06 +00:00
|
|
|
std::string NameStr;
|
2017-11-21 23:26:08 +00:00
|
|
|
llvm::raw_string_ostream OS(NameStr);
|
2010-04-08 00:03:06 +00:00
|
|
|
LangOptions LO;
|
|
|
|
LO.CPlusPlus = true;
|
|
|
|
LO.Bool = true;
|
2013-03-05 06:21:38 +00:00
|
|
|
OS << '\'';
|
2010-04-08 00:03:06 +00:00
|
|
|
N.print(OS, PrintingPolicy(LO));
|
2013-03-05 06:21:38 +00:00
|
|
|
OS << '\'';
|
2010-04-08 00:03:06 +00:00
|
|
|
return DB << NameStr;
|
|
|
|
}
|