Skip to content

Commit 2d4b74f

Browse files
committed
Reland: [clang] Improved canonicalization for template specialization types
This changes the TemplateArgument representation to hold a flag indicating whether a tempalte argument of expression type is supposed to be canonical or not. This gets one step closer to solving #92292 This still doesn't try to unique as-written TSTs. While this would increase the amount of memory savings and make code dealing with the AST more well-behaved, profiling template argument lists is still too expensive for this to be worthwhile, at least for now. This also fixes the context creation of TSTs, so that they don't in some cases get incorrectly flagged as sugar over their own canonical form. This is captured in the test expectation change of some AST dumps. This fixes some places which were unnecessarily canonicalizing these TSTs.
1 parent ffac140 commit 2d4b74f

30 files changed

+457
-423
lines changed

.ci/compute_projects.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
},
5050
"lld": {"bolt", "cross-project-tests"},
5151
# TODO(issues/132795): LLDB should be enabled on clang changes.
52-
"clang": {"clang-tools-extra", "compiler-rt", "cross-project-tests"},
52+
"clang": {"clang-tools-extra", "compiler-rt", "cross-project-tests", "lldb"},
5353
"clang-tools-extra": {"libc"},
5454
"mlir": {"flang"},
5555
}

.ci/monolithic-linux.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,18 @@ lit_args="-v --xunit-xml-output ${BUILD_DIR}/test-results.xml --use-unique-outpu
5454

5555
echo "--- cmake"
5656
export PIP_BREAK_SYSTEM_PACKAGES=1
57+
5758
pip install -q -r "${MONOREPO_ROOT}"/mlir/python/requirements.txt
5859
pip install -q -r "${MONOREPO_ROOT}"/lldb/test/requirements.txt
5960
pip install -q -r "${MONOREPO_ROOT}"/.ci/requirements.txt
61+
62+
# This is an lldb requirement which is not listed above.
63+
pip install -q swig
64+
6065
cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \
6166
-D LLVM_ENABLE_PROJECTS="${projects}" \
6267
-G Ninja \
68+
-D CMAKE_PREFIX_PATH="${HOME}/.local" \
6369
-D CMAKE_BUILD_TYPE=Release \
6470
-D LLVM_ENABLE_ASSERTIONS=ON \
6571
-D LLVM_BUILD_EXAMPLES=ON \
@@ -69,6 +75,8 @@ cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \
6975
-D CMAKE_CXX_FLAGS=-gmlt \
7076
-D LLVM_CCACHE_BUILD=ON \
7177
-D MLIR_ENABLE_BINDINGS_PYTHON=ON \
78+
-D LLDB_ENABLE_PYTHON=ON \
79+
-D LLDB_ENFORCE_STRICT_TEST_REQUIREMENTS=ON \
7280
-D CMAKE_INSTALL_PREFIX="${INSTALL_DIR}"
7381

7482
echo "--- ninja"

clang-tools-extra/clangd/AST.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,8 @@ QualType declaredType(const TypeDecl *D) {
439439
if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D))
440440
if (const auto *Args = CTSD->getTemplateArgsAsWritten())
441441
return Context.getTemplateSpecializationType(
442-
TemplateName(CTSD->getSpecializedTemplate()), Args->arguments());
442+
TemplateName(CTSD->getSpecializedTemplate()), Args->arguments(),
443+
/*CanonicalArgs=*/std::nullopt);
443444
return Context.getTypeDeclType(D);
444445
}
445446

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,8 @@ Improvements to Clang's diagnostics
303303
- Clang now better preserves the sugared types of pointers to member.
304304
- Clang now better preserves the presence of the template keyword with dependent
305305
prefixes.
306+
- Clang now in more cases avoids printing 'type-parameter-X-X' instead of the name of
307+
the template parameter.
306308
- Clang now respects the current language mode when printing expressions in
307309
diagnostics. This fixes a bunch of `bool` being printed as `_Bool`, and also
308310
a bunch of HLSL types being printed as their C++ equivalents.

clang/include/clang/AST/ASTContext.h

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -367,9 +367,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
367367
const ASTContext&>
368368
CanonTemplateTemplateParms;
369369

370-
TemplateTemplateParmDecl *
371-
getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const;
372-
373370
/// The typedef for the __int128_t type.
374371
mutable TypedefDecl *Int128Decl = nullptr;
375372

@@ -1811,22 +1808,26 @@ class ASTContext : public RefCountedBase<ASTContext> {
18111808
bool ParameterPack,
18121809
TemplateTypeParmDecl *ParmDecl = nullptr) const;
18131810

1814-
QualType getTemplateSpecializationType(TemplateName T,
1815-
ArrayRef<TemplateArgument> Args,
1816-
QualType Canon = QualType()) const;
1811+
QualType getCanonicalTemplateSpecializationType(
1812+
TemplateName T, ArrayRef<TemplateArgument> CanonicalArgs) const;
18171813

18181814
QualType
1819-
getCanonicalTemplateSpecializationType(TemplateName T,
1820-
ArrayRef<TemplateArgument> Args) const;
1815+
getTemplateSpecializationType(TemplateName T,
1816+
ArrayRef<TemplateArgument> SpecifiedArgs,
1817+
ArrayRef<TemplateArgument> CanonicalArgs,
1818+
QualType Underlying = QualType()) const;
18211819

1822-
QualType getTemplateSpecializationType(TemplateName T,
1823-
ArrayRef<TemplateArgumentLoc> Args,
1824-
QualType Canon = QualType()) const;
1820+
QualType
1821+
getTemplateSpecializationType(TemplateName T,
1822+
ArrayRef<TemplateArgumentLoc> SpecifiedArgs,
1823+
ArrayRef<TemplateArgument> CanonicalArgs,
1824+
QualType Canon = QualType()) const;
18251825

1826-
TypeSourceInfo *
1827-
getTemplateSpecializationTypeInfo(TemplateName T, SourceLocation TLoc,
1828-
const TemplateArgumentListInfo &Args,
1829-
QualType Canon = QualType()) const;
1826+
TypeSourceInfo *getTemplateSpecializationTypeInfo(
1827+
TemplateName T, SourceLocation TLoc,
1828+
const TemplateArgumentListInfo &SpecifiedArgs,
1829+
ArrayRef<TemplateArgument> CanonicalArgs,
1830+
QualType Canon = QualType()) const;
18301831

18311832
QualType getParenType(QualType NamedType) const;
18321833

@@ -2942,6 +2943,21 @@ class ASTContext : public RefCountedBase<ASTContext> {
29422943
TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg)
29432944
const;
29442945

2946+
/// Canonicalize the given template argument list.
2947+
///
2948+
/// Returns true if any arguments were non-canonical, false otherwise.
2949+
bool
2950+
canonicalizeTemplateArguments(MutableArrayRef<TemplateArgument> Args) const;
2951+
2952+
/// Canonicalize the given TemplateTemplateParmDecl.
2953+
TemplateTemplateParmDecl *
2954+
getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const;
2955+
2956+
TemplateTemplateParmDecl *findCanonicalTemplateTemplateParmDeclInternal(
2957+
TemplateTemplateParmDecl *TTP) const;
2958+
TemplateTemplateParmDecl *insertCanonicalTemplateTemplateParmDeclInternal(
2959+
TemplateTemplateParmDecl *CanonTTP) const;
2960+
29452961
/// Type Query functions. If the type is an instance of the specified class,
29462962
/// return the Type pointer for the underlying maximally pretty type. This
29472963
/// is a member of ASTContext because this may need to do some amount of

clang/include/clang/AST/PropertiesBase.td

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -877,11 +877,14 @@ let Class = PropertyTypeCase<TemplateArgument, "Expression"> in {
877877
def : Property<"expression", ExprRef> {
878878
let Read = [{ node.getAsExpr() }];
879879
}
880+
def : Property<"IsCanonical", Bool> {
881+
let Read = [{ node.isCanonicalExpr() }];
882+
}
880883
def : Property<"isDefaulted", Bool> {
881884
let Read = [{ node.getIsDefaulted() }];
882885
}
883886
def : Creator<[{
884-
return TemplateArgument(expression, isDefaulted);
887+
return TemplateArgument(expression, IsCanonical, isDefaulted);
885888
}]>;
886889
}
887890
let Class = PropertyTypeCase<TemplateArgument, "Pack"> in {

clang/include/clang/AST/TemplateBase.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ class TemplateArgument {
167167
unsigned Kind : 31;
168168
LLVM_PREFERRED_TYPE(bool)
169169
unsigned IsDefaulted : 1;
170+
LLVM_PREFERRED_TYPE(bool)
171+
unsigned IsCanonicalExpr : 1;
170172
uintptr_t V;
171173
};
172174
union {
@@ -187,7 +189,8 @@ class TemplateArgument {
187189

188190
public:
189191
/// Construct an empty, invalid template argument.
190-
constexpr TemplateArgument() : TypeOrValue({Null, 0, /* IsDefaulted */ 0}) {}
192+
constexpr TemplateArgument()
193+
: TypeOrValue{Null, /*IsDefaulted=*/0, /*IsCanonicalExpr=*/0, /*V=*/0} {}
191194

192195
/// Construct a template type argument.
193196
TemplateArgument(QualType T, bool isNullPtr = false,
@@ -262,9 +265,10 @@ class TemplateArgument {
262265
/// This form of template argument only occurs in template argument
263266
/// lists used for dependent types and for expression; it will not
264267
/// occur in a non-dependent, canonical template argument list.
265-
explicit TemplateArgument(Expr *E, bool IsDefaulted = false) {
268+
TemplateArgument(Expr *E, bool IsCanonical, bool IsDefaulted = false) {
266269
TypeOrValue.Kind = Expression;
267270
TypeOrValue.IsDefaulted = IsDefaulted;
271+
TypeOrValue.IsCanonicalExpr = IsCanonical;
268272
TypeOrValue.V = reinterpret_cast<uintptr_t>(E);
269273
}
270274

@@ -407,6 +411,11 @@ class TemplateArgument {
407411
return reinterpret_cast<Expr *>(TypeOrValue.V);
408412
}
409413

414+
bool isCanonicalExpr() const {
415+
assert(getKind() == Expression && "Unexpected kind");
416+
return TypeOrValue.IsCanonicalExpr;
417+
}
418+
410419
/// Iterator that traverses the elements of a template argument pack.
411420
using pack_iterator = const TemplateArgument *;
412421

clang/include/clang/AST/Type.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6676,10 +6676,9 @@ class TemplateSpecializationType : public Type, public llvm::FoldingSetNode {
66766676
/// replacement must, recursively, be one of these).
66776677
TemplateName Template;
66786678

6679-
TemplateSpecializationType(TemplateName T,
6679+
TemplateSpecializationType(TemplateName T, bool IsAlias,
66806680
ArrayRef<TemplateArgument> Args,
6681-
QualType Canon,
6682-
QualType Aliased);
6681+
QualType Underlying);
66836682

66846683
public:
66856684
/// Determine whether any of the given template arguments are dependent.
@@ -6747,7 +6746,7 @@ class TemplateSpecializationType : public Type, public llvm::FoldingSetNode {
67476746

67486747
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx);
67496748
static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T,
6750-
ArrayRef<TemplateArgument> Args,
6749+
ArrayRef<TemplateArgument> Args, QualType Underlying,
67516750
const ASTContext &Context);
67526751

67536752
static bool classof(const Type *T) {

clang/include/clang/AST/TypeProperties.td

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -737,39 +737,19 @@ let Class = DependentAddressSpaceType in {
737737
}
738738

739739
let Class = TemplateSpecializationType in {
740-
def : Property<"dependent", Bool> {
741-
let Read = [{ node->isDependentType() }];
742-
}
743740
def : Property<"templateName", TemplateName> {
744741
let Read = [{ node->getTemplateName() }];
745742
}
746-
def : Property<"templateArguments", Array<TemplateArgument>> {
743+
def : Property<"args", Array<TemplateArgument>> {
747744
let Read = [{ node->template_arguments() }];
748745
}
749-
def : Property<"underlyingType", Optional<QualType>> {
750-
let Read = [{
751-
node->isTypeAlias()
752-
? std::optional<QualType>(node->getAliasedType())
753-
: node->isCanonicalUnqualified()
754-
? std::nullopt
755-
: std::optional<QualType>(node->getCanonicalTypeInternal())
756-
}];
746+
def : Property<"UnderlyingType", QualType> {
747+
let Read = [{ node->isCanonicalUnqualified() ? QualType() :
748+
node->desugar() }];
757749
}
758750

759751
def : Creator<[{
760-
QualType result;
761-
if (!underlyingType) {
762-
result = ctx.getCanonicalTemplateSpecializationType(templateName,
763-
templateArguments);
764-
} else {
765-
result = ctx.getTemplateSpecializationType(templateName,
766-
templateArguments,
767-
*underlyingType);
768-
}
769-
if (dependent)
770-
const_cast<Type *>(result.getTypePtr())
771-
->addDependence(TypeDependence::DependentInstantiation);
772-
return result;
752+
return ctx.getTemplateSpecializationType(templateName, args, std::nullopt, UnderlyingType);
773753
}]>;
774754
}
775755

0 commit comments

Comments
 (0)