Skip to content

Commit 0bdab9c

Browse files
committed
[clang] preserve sugar on initializer_list deduction
1 parent 3de88fe commit 0bdab9c

File tree

4 files changed

+61
-26
lines changed

4 files changed

+61
-26
lines changed

clang/include/clang/AST/Type.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2838,6 +2838,18 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
28382838
/// immediately following this class.
28392839
template <typename T> const T *getAs() const;
28402840

2841+
/// Look through sugar for an instance of TemplateSpecializationType which
2842+
/// is not a type alias.
2843+
const TemplateSpecializationType *
2844+
getAsNonAliasTemplateSpecializationType() const;
2845+
2846+
const TemplateSpecializationType *
2847+
castAsNonAliasTemplateSpecializationType() const {
2848+
auto TST = getAsNonAliasTemplateSpecializationType();
2849+
assert(TST && "not a TemplateSpecializationType");
2850+
return TST;
2851+
}
2852+
28412853
/// Member-template getAsAdjusted<specific type>. Look through specific kinds
28422854
/// of sugar (parens, attributes, etc) for an instance of \<specific type>.
28432855
/// This is used when you need to walk over sugar nodes that represent some

clang/lib/AST/Type.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1938,6 +1938,17 @@ TagDecl *Type::getAsTagDecl() const {
19381938
return nullptr;
19391939
}
19401940

1941+
const TemplateSpecializationType *
1942+
Type::getAsNonAliasTemplateSpecializationType() const {
1943+
for (const auto *T = this; /**/; /**/) {
1944+
const TemplateSpecializationType *TST =
1945+
T->getAs<TemplateSpecializationType>();
1946+
if (!TST || !TST->isTypeAlias())
1947+
return TST;
1948+
T = TST->desugar().getTypePtr();
1949+
}
1950+
}
1951+
19411952
bool Type::hasAttr(attr::Kind AK) const {
19421953
const Type *Cur = this;
19431954
while (const auto *AT = Cur->getAs<AttributedType>()) {

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12154,33 +12154,31 @@ static bool isStdClassTemplate(Sema &S, QualType SugaredType, QualType *TypeArg,
1215412154
};
1215512155

1215612156
ClassTemplateDecl *Template = nullptr;
12157-
const TemplateArgument *Arguments = nullptr;
12158-
12159-
QualType Ty = S.Context.getCanonicalType(SugaredType);
12160-
if (const RecordType *RT = Ty->getAs<RecordType>()) {
12161-
ClassTemplateSpecializationDecl *Specialization =
12162-
dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
12163-
if (!Specialization) {
12164-
ReportMatchingNameAsMalformed(RT->getDecl());
12165-
return false;
12166-
}
12167-
12168-
Template = Specialization->getSpecializedTemplate();
12169-
Arguments = Specialization->getTemplateArgs().data();
12170-
} else {
12171-
const TemplateSpecializationType *TST = nullptr;
12172-
if (auto *ICN = Ty->getAs<InjectedClassNameType>())
12173-
TST = ICN->getInjectedTST();
12174-
else
12175-
TST = Ty->getAs<TemplateSpecializationType>();
12157+
ArrayRef<TemplateArgument> Arguments;
12158+
{
12159+
const TemplateSpecializationType *TST =
12160+
SugaredType->getAsNonAliasTemplateSpecializationType();
12161+
if (!TST)
12162+
if (const auto *ICN = SugaredType->getAs<InjectedClassNameType>())
12163+
TST = ICN->getInjectedTST();
1217612164
if (TST) {
1217712165
Template = dyn_cast_or_null<ClassTemplateDecl>(
1217812166
TST->getTemplateName().getAsTemplateDecl());
12179-
Arguments = TST->template_arguments().begin();
12167+
Arguments = TST->template_arguments();
12168+
} else if (const RecordType *RT = SugaredType->getAs<RecordType>()) {
12169+
ClassTemplateSpecializationDecl *Specialization =
12170+
dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
12171+
if (!Specialization) {
12172+
ReportMatchingNameAsMalformed(RT->getDecl());
12173+
return false;
12174+
}
12175+
Template = Specialization->getSpecializedTemplate();
12176+
Arguments = Specialization->getTemplateArgs().asArray();
1218012177
}
1218112178
}
12179+
1218212180
if (!Template) {
12183-
ReportMatchingNameAsMalformed(Ty->getAsTagDecl());
12181+
ReportMatchingNameAsMalformed(SugaredType->getAsTagDecl());
1218412182
return false;
1218512183
}
1218612184

@@ -12200,7 +12198,8 @@ static bool isStdClassTemplate(Sema &S, QualType SugaredType, QualType *TypeArg,
1220012198
// template?
1220112199
TemplateParameterList *Params = Template->getTemplateParameters();
1220212200
if (Params->getMinRequiredArguments() != 1 ||
12203-
!isa<TemplateTypeParmDecl>(Params->getParam(0))) {
12201+
!isa<TemplateTypeParmDecl>(Params->getParam(0)) ||
12202+
Params->getParam(0)->isTemplateParameterPack()) {
1220412203
if (MalformedDecl)
1220512204
*MalformedDecl = TemplateClass;
1220612205
return false;
@@ -12214,8 +12213,21 @@ static bool isStdClassTemplate(Sema &S, QualType SugaredType, QualType *TypeArg,
1221412213
return false;
1221512214

1221612215
// This is an instance of std::{ClassName}. Find the argument type.
12217-
if (TypeArg)
12218-
*TypeArg = Arguments[0].getAsType();
12216+
if (TypeArg) {
12217+
QualType ArgType = Arguments[0].getAsType();
12218+
// FIXME: Since TST only has as-written arguments, we have to perform the
12219+
// only kind of conversion applicable to type arguments; in Objective-C ARC:
12220+
// - If an explicitly-specified template argument type is a lifetime type
12221+
// with no lifetime qualifier, the __strong lifetime qualifier is
12222+
// inferred.
12223+
if (S.getLangOpts().ObjCAutoRefCount && ArgType->isObjCLifetimeType() &&
12224+
!ArgType.getObjCLifetime()) {
12225+
Qualifiers Qs;
12226+
Qs.setObjCLifetime(Qualifiers::OCL_Strong);
12227+
ArgType = S.Context.getQualifiedType(ArgType, Qs);
12228+
}
12229+
*TypeArg = ArgType;
12230+
}
1221912231

1222012232
return true;
1222112233
}

clang/test/CXX/drs/cwg23xx.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ struct Y {};
9191
struct Z : W,
9292
X, check_derived_from<Z, X>, // #cwg2310-X
9393
check_derived_from<Z, Y>, Y // #cwg2310-Y
94-
{
94+
{
9595
// FIXME: It was properly rejected before, but we're crashing since Clang 11 in C++11 and C++14 modes.
9696
// See https://github.com/llvm/llvm-project/issues/59920
9797
#if __cplusplus >= 201703L
@@ -188,7 +188,7 @@ struct InitListCtor {
188188

189189
std::initializer_list<InitListCtor> i;
190190
auto j = std::initializer_list<InitListCtor>{ i };
191-
// since-cxx17-error@-1 {{conversion function from 'std::initializer_list<InitListCtor>' to 'const cwg2311::InitListCtor' invokes a deleted function}}
191+
// since-cxx17-error@-1 {{conversion function from 'std::initializer_list<InitListCtor>' to 'const InitListCtor' invokes a deleted function}}
192192
// since-cxx17-note@#cwg2311-InitListCtor {{'InitListCtor' has been explicitly marked deleted here}}
193193
#endif
194194
} // namespace cwg2311

0 commit comments

Comments
 (0)