@@ -5747,6 +5747,30 @@ ASTContext::getMacroQualifiedType(QualType UnderlyingTy,
57475747 return QualType(newType, 0);
57485748}
57495749
5750+ static ElaboratedTypeKeyword
5751+ getCanonicalElaboratedTypeKeyword(ElaboratedTypeKeyword Keyword) {
5752+ switch (Keyword) {
5753+ // These are just themselves.
5754+ case ElaboratedTypeKeyword::None:
5755+ case ElaboratedTypeKeyword::Struct:
5756+ case ElaboratedTypeKeyword::Union:
5757+ case ElaboratedTypeKeyword::Enum:
5758+ case ElaboratedTypeKeyword::Interface:
5759+ return Keyword;
5760+
5761+ // These are equivalent.
5762+ case ElaboratedTypeKeyword::Typename:
5763+ return ElaboratedTypeKeyword::None;
5764+
5765+ // These are functionally equivalent, so relying on their equivalence is
5766+ // IFNDR. By making them equivalent, we disallow overloading, which at least
5767+ // can produce a diagnostic.
5768+ case ElaboratedTypeKeyword::Class:
5769+ return ElaboratedTypeKeyword::Struct;
5770+ }
5771+ llvm_unreachable("unexpected keyword kind");
5772+ }
5773+
57505774QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
57515775 NestedNameSpecifier *NNS,
57525776 const IdentifierInfo *Name) const {
@@ -5758,10 +5782,13 @@ QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
57585782 DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos))
57595783 return QualType(T, 0);
57605784
5785+ ElaboratedTypeKeyword CanonKeyword =
5786+ getCanonicalElaboratedTypeKeyword(Keyword);
5787+ NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
5788+
57615789 QualType Canon;
5762- if (NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
5763- CanonNNS != NNS) {
5764- Canon = getDependentNameType(Keyword, CanonNNS, Name);
5790+ if (CanonKeyword != Keyword || CanonNNS != NNS) {
5791+ Canon = getDependentNameType(CanonKeyword, CanonNNS, Name);
57655792 [[maybe_unused]] DependentNameType *T =
57665793 DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos);
57675794 assert(!T && "broken canonicalization");
@@ -5800,27 +5827,27 @@ QualType ASTContext::getDependentTemplateSpecializationType(
58005827
58015828 QualType Canon;
58025829 if (!IsCanonical) {
5803- ElaboratedTypeKeyword CanonKeyword = Keyword != ElaboratedTypeKeyword::None
5804- ? Keyword
5805- : ElaboratedTypeKeyword::Typename;
5830+ ElaboratedTypeKeyword CanonKeyword =
5831+ getCanonicalElaboratedTypeKeyword(Keyword);
58065832 NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
58075833 bool AnyNonCanonArgs = false;
58085834 auto CanonArgs =
58095835 ::getCanonicalTemplateArguments(*this, Args, AnyNonCanonArgs);
58105836
5811- if (AnyNonCanonArgs || CanonNNS != NNS || !Name.hasTemplateKeyword() ||
5812- CanonKeyword != Keyword ) {
5837+ if (CanonKeyword != Keyword || AnyNonCanonArgs || CanonNNS != NNS ||
5838+ !Name.hasTemplateKeyword() ) {
58135839 Canon = getDependentTemplateSpecializationType(
58145840 CanonKeyword, {CanonNNS, Name.getName(), /*HasTemplateKeyword=*/true},
5815- CanonArgs, /*IsCanonical=*/true);
5841+ CanonArgs,
5842+ /*IsCanonical=*/true);
58165843 // Find the insert position again.
58175844 [[maybe_unused]] auto *Nothing =
58185845 DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID,
58195846 InsertPos);
58205847 assert(!Nothing && "canonical type broken");
58215848 }
58225849 } else {
5823- assert(Keyword != ElaboratedTypeKeyword::None );
5850+ assert(Keyword == getCanonicalElaboratedTypeKeyword(Keyword) );
58245851 assert(Name.hasTemplateKeyword());
58255852 assert(NNS == getCanonicalNestedNameSpecifier(NNS));
58265853#ifndef NDEBUG
@@ -7657,7 +7684,7 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
76577684 if (const auto *DTST = T->getAs<DependentTemplateSpecializationType>()) {
76587685 const DependentTemplateStorage &DTN = DTST->getDependentTemplateName();
76597686 QualType NewT = getDependentTemplateSpecializationType(
7660- ElaboratedTypeKeyword::Typename ,
7687+ ElaboratedTypeKeyword::None ,
76617688 {/*NNS=*/nullptr, DTN.getName(), /*HasTemplateKeyword=*/true},
76627689 DTST->template_arguments(), /*IsCanonical=*/true);
76637690 assert(NewT.isCanonical());
0 commit comments