[clang] [clang][Sema][NFC] Improve readability in `computeDeclContext` (PR #208010)
Yanzuo Liu via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 7 07:35:44 PDT 2026
https://github.com/zwuis created https://github.com/llvm/llvm-project/pull/208010
Split off from #190495.
Co-authored-by: Matheus Izvekov <mizvekov at gmail.com>
>From ca21bf15a609ac7d76c08ccdcf39e8b64ea04882 Mon Sep 17 00:00:00 2001
From: Yanzuo Liu <zwuis at outlook.com>
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 <zwuis at outlook.com>
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 <zwuis at outlook.com>
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) {
More information about the cfe-commits
mailing list