[clang] eb00182 - [Clang] prevent errors for deduction guides using deduced type aliases (#117450)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Nov 27 01:51:43 PST 2024
Author: Oleksandr T.
Date: 2024-11-27T11:51:34+02:00
New Revision: eb001820b47176fc3e7bc643525c6352b76dcd1d
URL: https://github.com/llvm/llvm-project/commit/eb001820b47176fc3e7bc643525c6352b76dcd1d
DIFF: https://github.com/llvm/llvm-project/commit/eb001820b47176fc3e7bc643525c6352b76dcd1d.diff
LOG: [Clang] prevent errors for deduction guides using deduced type aliases (#117450)
Fixes #54909
---
Clang incorrectly produces diagnostics for alias templates in deduction
guides, treating them as separate from their underlying types. This
issue arises because Clang doesn't properly handle
`TypeAliasTemplateDecl` when comparing template names for equality in
the context of deduction guides, resulting in diagnostics that don't
align with the C++ standard. As the C++ standard specifies - _an alias
template is considered a synonym for its underlying type_
With this change, Clang now correctly resolves alias templates to their
underlying types in deduction guides, ensuring compliance with the C++
standard.
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/Sema/SemaDeclCXX.cpp
clang/test/CXX/temp/temp.deduct.guide/p3.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 6c40e48e2f49b3..356b091c13af4f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -590,6 +590,9 @@ Improvements to Clang's diagnostics
- Fixed a false negative ``-Wunused-private-field`` diagnostic when a defaulted comparison operator is defined out of class (#GH116961).
+- Clang now supports using alias templates in deduction guides, aligning with the C++ standard,
+ which treats alias templates as synonyms for their underlying types (#GH54909).
+
Improvements to Clang's time-trace
----------------------------------
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 26041e53de5061..3ff365649c93d2 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -11451,23 +11451,29 @@ bool Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
bool MightInstantiateToSpecialization = false;
if (auto RetTST =
TSI->getTypeLoc().getAsAdjusted<TemplateSpecializationTypeLoc>()) {
- TemplateName SpecifiedName = RetTST.getTypePtr()->getTemplateName();
- bool TemplateMatches = Context.hasSameTemplateName(
- SpecifiedName, GuidedTemplate, /*IgnoreDeduced=*/true);
-
- const QualifiedTemplateName *Qualifiers =
- SpecifiedName.getAsQualifiedTemplateName();
- assert(Qualifiers && "expected QualifiedTemplate");
- bool SimplyWritten = !Qualifiers->hasTemplateKeyword() &&
- Qualifiers->getQualifier() == nullptr;
- if (SimplyWritten && TemplateMatches)
- AcceptableReturnType = true;
- else {
- // This could still instantiate to the right type, unless we know it
- // names the wrong class template.
- auto *TD = SpecifiedName.getAsTemplateDecl();
- MightInstantiateToSpecialization = !(TD && isa<ClassTemplateDecl>(TD) &&
- !TemplateMatches);
+ const TemplateSpecializationType *TST = RetTST.getTypePtr();
+ while (TST && TST->isTypeAlias())
+ TST = TST->getAliasedType()->getAs<TemplateSpecializationType>();
+
+ if (TST) {
+ TemplateName SpecifiedName = TST->getTemplateName();
+ bool TemplateMatches = Context.hasSameTemplateName(
+ SpecifiedName, GuidedTemplate, /*IgnoreDeduced=*/true);
+
+ const QualifiedTemplateName *Qualifiers =
+ SpecifiedName.getAsQualifiedTemplateName();
+ assert(Qualifiers && "expected QualifiedTemplate");
+ bool SimplyWritten = !Qualifiers->hasTemplateKeyword() &&
+ Qualifiers->getQualifier() == nullptr;
+ if (SimplyWritten && TemplateMatches)
+ AcceptableReturnType = true;
+ else {
+ // This could still instantiate to the right type, unless we know it
+ // names the wrong class template.
+ auto *TD = SpecifiedName.getAsTemplateDecl();
+ MightInstantiateToSpecialization =
+ !(TD && isa<ClassTemplateDecl>(TD) && !TemplateMatches);
+ }
}
} else if (!RetTy.hasQualifiers() && RetTy->isDependentType()) {
MightInstantiateToSpecialization = true;
diff --git a/clang/test/CXX/temp/temp.deduct.guide/p3.cpp b/clang/test/CXX/temp/temp.deduct.guide/p3.cpp
index c5404847beb066..195ba2831439d0 100644
--- a/clang/test/CXX/temp/temp.deduct.guide/p3.cpp
+++ b/clang/test/CXX/temp/temp.deduct.guide/p3.cpp
@@ -33,7 +33,7 @@ template<template<typename> typename TT> struct E { // expected-note 2{{template
};
A(int) -> int; // expected-error {{deduced type 'int' of deduction guide is not a specialization of template 'A'}}
-template <typename T> A(T)->B<T>; // expected-error {{deduced type 'B<T>' (aka 'A<T>') of deduction guide is not written as a specialization of template 'A'}}
+template <typename T> A(T)->B<T>;
template<typename T> A(T*) -> const A<T>; // expected-error {{deduced type 'const A<T>' of deduction guide is not a specialization of template 'A'}}
// A deduction-guide shall be declared in the same scope as the corresponding
@@ -71,3 +71,11 @@ namespace WrongScope {
Local(int) -> Local<int>; // expected-error {{expected}}
}
}
+
+namespace GH54909 {
+template <class T> struct A {};
+struct B {};
+
+template <typename T> using C = B;
+template <typename T> A() -> C<T>; // expected-error {{deduced type 'C<T>' (aka 'GH54909::B') of deduction guide is not a specialization of template 'A'}}
+}
More information about the cfe-commits
mailing list