https://github.com/zwuis created https://github.com/llvm/llvm-project/pull/208010
Split off from #190495. Co-authored-by: Matheus Izvekov <[email protected]> >From ca21bf15a609ac7d76c08ccdcf39e8b64ea04882 Mon Sep 17 00:00:00 2001 From: Yanzuo Liu <[email protected]> Date: Tue, 7 Jul 2026 13:02:26 +0800 Subject: [PATCH 1/3] Move `return nullptr;` for null NNS to `switch` body --- clang/lib/Sema/SemaCXXScopeSpec.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 255c22d9c2a31..9f8530a8a861f 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -48,9 +48,6 @@ DeclContext *Sema::computeDeclContext(QualType T) { DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, bool EnteringContext) { - if (!SS.isSet() || SS.isInvalid()) - return nullptr; - NestedNameSpecifier NNS = SS.getScopeRep(); if (NNS.isDependent()) { // If this nested-name-specifier refers to the current @@ -143,7 +140,7 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, return NNS.getAsMicrosoftSuper(); case NestedNameSpecifier::Kind::Null: - llvm_unreachable("unexpected null nested name specifier"); + return nullptr; } llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); >From 1997bc5ae73ac88b6e8fd1e10ded95379ce08e9b Mon Sep 17 00:00:00 2001 From: Yanzuo Liu <[email protected]> Date: Tue, 7 Jul 2026 13:14:22 +0800 Subject: [PATCH 2/3] Decrease indent by swapping the order of branches and merging conditions --- clang/lib/Sema/SemaCXXScopeSpec.cpp | 56 ++++++++++++++--------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 9f8530a8a861f..d83bd29bdd60f 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -49,14 +49,34 @@ DeclContext *Sema::computeDeclContext(QualType T) { DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, bool EnteringContext) { NestedNameSpecifier NNS = SS.getScopeRep(); - if (NNS.isDependent()) { + if (!NNS.isDependent()) { + switch (NNS.getKind()) { + case NestedNameSpecifier::Kind::Namespace: + return const_cast<NamespaceDecl *>( + NNS.getAsNamespaceAndPrefix().Namespace->getNamespace()); + + case NestedNameSpecifier::Kind::Type: + return NNS.getAsType()->castAsTagDecl(); + + case NestedNameSpecifier::Kind::Global: + return Context.getTranslationUnitDecl(); + + case NestedNameSpecifier::Kind::MicrosoftSuper: + return NNS.getAsMicrosoftSuper(); + + case NestedNameSpecifier::Kind::Null: + return nullptr; + } + + llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); + } + // If this nested-name-specifier refers to the current // instantiation, return its DeclContext. if (CXXRecordDecl *Record = getCurrentInstantiationOf(NNS)) return Record; - if (EnteringContext) { - if (NNS.getKind() != NestedNameSpecifier::Kind::Type) + if (!EnteringContext || NNS.getKind() != NestedNameSpecifier::Kind::Type) return nullptr; const Type *NNSType = NNS.getAsType(); @@ -67,14 +87,16 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, // We are entering the context of the nested name specifier, so try to // match the nested name specifier to either a primary class template // or a class template partial specialization. - if (ClassTemplateDecl *ClassTemplate = + ClassTemplateDecl *ClassTemplate = dyn_cast_or_null<ClassTemplateDecl>( - SpecType->getTemplateName().getAsTemplateDecl())) { + SpecType->getTemplateName().getAsTemplateDecl()) // FIXME: The fallback on the search of partial // specialization using ContextType should be eventually removed since // it doesn't handle the case of constrained template parameters // correctly. Currently removing this fallback would change the // diagnostic output for invalid code in a number of tests. + if (!ClassTemplate) + return nullptr; ClassTemplatePartialSpecializationDecl *PartialSpec = nullptr; ArrayRef<TemplateParameterList *> TemplateParamLists = SS.getTemplateParamLists(); @@ -115,35 +137,13 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, ClassTemplate->getCanonicalInjectedSpecializationType(Context); if (Context.hasSameType(Injected, QualType(SpecType, 0))) return ClassTemplate->getTemplatedDecl(); - } + return nullptr; } else if (const auto *RecordT = dyn_cast<RecordType>(NNSType)) { // The nested name specifier refers to a member of a class template. return RecordT->getDecl()->getDefinitionOrSelf(); } - } return nullptr; - } - - switch (NNS.getKind()) { - case NestedNameSpecifier::Kind::Namespace: - return const_cast<NamespaceDecl *>( - NNS.getAsNamespaceAndPrefix().Namespace->getNamespace()); - - case NestedNameSpecifier::Kind::Type: - return NNS.getAsType()->castAsTagDecl(); - - case NestedNameSpecifier::Kind::Global: - return Context.getTranslationUnitDecl(); - - case NestedNameSpecifier::Kind::MicrosoftSuper: - return NNS.getAsMicrosoftSuper(); - - case NestedNameSpecifier::Kind::Null: - return nullptr; - } - - llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); } bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) { >From 83a9b4d13f28ef3904126f091af4d86997521174 Mon Sep 17 00:00:00 2001 From: Yanzuo Liu <[email protected]> Date: Tue, 7 Jul 2026 14:51:12 +0800 Subject: [PATCH 3/3] Move comment and `git clang-format` --- clang/lib/Sema/SemaCXXScopeSpec.cpp | 159 ++++++++++++++-------------- 1 file changed, 78 insertions(+), 81 deletions(-) diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index d83bd29bdd60f..00a566cfab7b0 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -50,100 +50,97 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, bool EnteringContext) { NestedNameSpecifier NNS = SS.getScopeRep(); if (!NNS.isDependent()) { - switch (NNS.getKind()) { - case NestedNameSpecifier::Kind::Namespace: - return const_cast<NamespaceDecl *>( - NNS.getAsNamespaceAndPrefix().Namespace->getNamespace()); + switch (NNS.getKind()) { + case NestedNameSpecifier::Kind::Namespace: + return const_cast<NamespaceDecl *>( + NNS.getAsNamespaceAndPrefix().Namespace->getNamespace()); - case NestedNameSpecifier::Kind::Type: - return NNS.getAsType()->castAsTagDecl(); + case NestedNameSpecifier::Kind::Type: + return NNS.getAsType()->castAsTagDecl(); - case NestedNameSpecifier::Kind::Global: - return Context.getTranslationUnitDecl(); + case NestedNameSpecifier::Kind::Global: + return Context.getTranslationUnitDecl(); - case NestedNameSpecifier::Kind::MicrosoftSuper: - return NNS.getAsMicrosoftSuper(); + case NestedNameSpecifier::Kind::MicrosoftSuper: + return NNS.getAsMicrosoftSuper(); - case NestedNameSpecifier::Kind::Null: - return nullptr; - } + case NestedNameSpecifier::Kind::Null: + return nullptr; + } - llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); + llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); } - // If this nested-name-specifier refers to the current - // instantiation, return its DeclContext. - if (CXXRecordDecl *Record = getCurrentInstantiationOf(NNS)) - return Record; - - if (!EnteringContext || NNS.getKind() != NestedNameSpecifier::Kind::Type) - return nullptr; - const Type *NNSType = NNS.getAsType(); - - // Look through type alias templates, per C++0x [temp.dep.type]p1. - NNSType = Context.getCanonicalType(NNSType); - if (const auto *SpecType = - dyn_cast<TemplateSpecializationType>(NNSType)) { - // We are entering the context of the nested name specifier, so try to - // match the nested name specifier to either a primary class template - // or a class template partial specialization. - ClassTemplateDecl *ClassTemplate = - dyn_cast_or_null<ClassTemplateDecl>( - SpecType->getTemplateName().getAsTemplateDecl()) - // FIXME: The fallback on the search of partial - // specialization using ContextType should be eventually removed since - // it doesn't handle the case of constrained template parameters - // correctly. Currently removing this fallback would change the - // diagnostic output for invalid code in a number of tests. - if (!ClassTemplate) - return nullptr; - ClassTemplatePartialSpecializationDecl *PartialSpec = nullptr; - ArrayRef<TemplateParameterList *> TemplateParamLists = - SS.getTemplateParamLists(); - if (!TemplateParamLists.empty()) { - unsigned Depth = ClassTemplate->getTemplateParameters()->getDepth(); - auto L = find_if(TemplateParamLists, + // If this nested-name-specifier refers to the current + // instantiation, return its DeclContext. + if (CXXRecordDecl *Record = getCurrentInstantiationOf(NNS)) + return Record; + + if (!EnteringContext || NNS.getKind() != NestedNameSpecifier::Kind::Type) + return nullptr; + const Type *NNSType = NNS.getAsType(); + + // Look through type alias templates, per C++0x [temp.dep.type]p1. + NNSType = Context.getCanonicalType(NNSType); + if (const auto *SpecType = dyn_cast<TemplateSpecializationType>(NNSType)) { + // We are entering the context of the nested name specifier, so try to + // match the nested name specifier to either a primary class template + // or a class template partial specialization. + ClassTemplateDecl *ClassTemplate = dyn_cast_or_null<ClassTemplateDecl>( + SpecType->getTemplateName().getAsTemplateDecl()); + if (!ClassTemplate) + return nullptr; + ClassTemplatePartialSpecializationDecl *PartialSpec = nullptr; + ArrayRef<TemplateParameterList *> TemplateParamLists = + SS.getTemplateParamLists(); + if (!TemplateParamLists.empty()) { + unsigned Depth = ClassTemplate->getTemplateParameters()->getDepth(); + auto L = llvm::find_if(TemplateParamLists, [Depth](TemplateParameterList *TPL) { return TPL->getDepth() == Depth; }); - if (L != TemplateParamLists.end()) { - void *Pos = nullptr; - PartialSpec = ClassTemplate->findPartialSpecialization( - SpecType->template_arguments(), *L, Pos); - } - } else { - PartialSpec = - ClassTemplate->findPartialSpecialization(QualType(SpecType, 0)); - } - - if (PartialSpec) { - // A declaration of the partial specialization must be visible. - // We can always recover here, because this only happens when we're - // entering the context, and that can't happen in a SFINAE context. - assert(!isSFINAEContext() && "partial specialization scope " - "specifier in SFINAE context?"); - if (PartialSpec->hasDefinition() && - !hasReachableDefinition(PartialSpec)) - diagnoseMissingImport(SS.getLastQualifierNameLoc(), PartialSpec, - MissingImportKind::PartialSpecialization, - true); - return PartialSpec; - } - - // If the type of the nested name specifier is the same as the - // injected class name of the named class template, we're entering - // into that class template definition. - CanQualType Injected = - ClassTemplate->getCanonicalInjectedSpecializationType(Context); - if (Context.hasSameType(Injected, QualType(SpecType, 0))) - return ClassTemplate->getTemplatedDecl(); - return nullptr; - } else if (const auto *RecordT = dyn_cast<RecordType>(NNSType)) { - // The nested name specifier refers to a member of a class template. - return RecordT->getDecl()->getDefinitionOrSelf(); + if (L != TemplateParamLists.end()) { + void *Pos = nullptr; + PartialSpec = ClassTemplate->findPartialSpecialization( + SpecType->template_arguments(), *L, Pos); } + } else { + // FIXME: The fallback on the search of partial + // specialization using ContextType should be eventually removed since + // it doesn't handle the case of constrained template parameters + // correctly. Currently removing this fallback would change the + // diagnostic output for invalid code in a number of tests. + PartialSpec = + ClassTemplate->findPartialSpecialization(QualType(SpecType, 0)); + } + + if (PartialSpec) { + // A declaration of the partial specialization must be visible. + // We can always recover here, because this only happens when we're + // entering the context, and that can't happen in a SFINAE context. + assert(!isSFINAEContext() && "partial specialization scope " + "specifier in SFINAE context?"); + if (PartialSpec->hasDefinition() && !hasReachableDefinition(PartialSpec)) + diagnoseMissingImport(SS.getLastQualifierNameLoc(), PartialSpec, + MissingImportKind::PartialSpecialization, true); + return PartialSpec; + } + // If the type of the nested name specifier is the same as the + // injected class name of the named class template, we're entering + // into that class template definition. + CanQualType Injected = + ClassTemplate->getCanonicalInjectedSpecializationType(Context); + if (Context.hasSameType(Injected, QualType(SpecType, 0))) + return ClassTemplate->getTemplatedDecl(); return nullptr; + } + if (const auto *RecordT = dyn_cast<RecordType>(NNSType)) { + // The nested name specifier refers to a member of a class template. + return RecordT->getDecl()->getDefinitionOrSelf(); + } + + return nullptr; } bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
