Skip to content

[PATCH 6/6] [clang] improve NestedNameSpecifier #149748

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: users/mizvekov/name-qualification-refactor-5
Choose a base branch
from

Conversation

mizvekov
Copy link
Contributor

This contains the NestedNameSpecifier representation changes originally from: #147835

@mizvekov mizvekov self-assigned this Jul 20, 2025
@llvmbot llvmbot added clang Clang issues not falling into any other category clang-tools-extra clangd clang-tidy clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules clang:codegen IR generation bugs: mangling, exceptions, etc. clang:as-a-library libclang and C++ API clang:openmp OpenMP related changes to Clang labels Jul 20, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 20, 2025

@llvm/pr-subscribers-clang
@llvm/pr-subscribers-clang-modules
@llvm/pr-subscribers-clangd

@llvm/pr-subscribers-clang-tidy

Author: Matheus Izvekov (mizvekov)

Changes

This contains the NestedNameSpecifier representation changes originally from: #147835


Patch is 465.84 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/149748.diff

124 Files Affected:

  • (modified) clang-tools-extra/clang-change-namespace/ChangeNamespace.cpp (+17-36)
  • (modified) clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp (+2-1)
  • (modified) clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp (+7-11)
  • (modified) clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp (+12-5)
  • (modified) clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp (-8)
  • (modified) clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp (+5-5)
  • (modified) clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp (+12-17)
  • (modified) clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp (+46-47)
  • (modified) clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp (+16-10)
  • (modified) clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp (+3-2)
  • (modified) clang-tools-extra/clangd/AST.cpp (+51-32)
  • (modified) clang-tools-extra/clangd/CodeComplete.cpp (+6-10)
  • (modified) clang-tools-extra/clangd/DumpAST.cpp (+14-19)
  • (modified) clang-tools-extra/clangd/FindTarget.cpp (+42-43)
  • (modified) clang-tools-extra/clangd/IncludeFixer.cpp (+25-25)
  • (modified) clang-tools-extra/clangd/Selection.cpp (+1-1)
  • (modified) clang-tools-extra/clangd/SemanticHighlighting.cpp (-15)
  • (modified) clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp (+77-44)
  • (modified) clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp (+1-1)
  • (modified) clang-tools-extra/clangd/unittests/FindTargetTests.cpp (+2-2)
  • (modified) clang-tools-extra/clangd/unittests/SelectionTests.cpp (+2-2)
  • (modified) clang-tools-extra/include-cleaner/lib/WalkAST.cpp (+7-9)
  • (modified) clang/include/clang/AST/ASTConcept.h (+2-7)
  • (modified) clang/include/clang/AST/ASTContext.h (+6-32)
  • (modified) clang/include/clang/AST/ASTImporter.h (+1-1)
  • (modified) clang/include/clang/AST/ASTNodeTraverser.h (+7-5)
  • (modified) clang/include/clang/AST/ASTTypeTraits.h (+7-6)
  • (modified) clang/include/clang/AST/AbstractBasicReader.h (+16-21)
  • (modified) clang/include/clang/AST/AbstractBasicWriter.h (+17-16)
  • (modified) clang/include/clang/AST/CanonicalType.h (+1-1)
  • (modified) clang/include/clang/AST/Decl.h (+5-5)
  • (modified) clang/include/clang/AST/DeclCXX.h (+7-9)
  • (modified) clang/include/clang/AST/DependenceFlags.h (+1-1)
  • (modified) clang/include/clang/AST/DynamicRecursiveASTVisitor.h (+1-2)
  • (modified) clang/include/clang/AST/Expr.h (+2-2)
  • (modified) clang/include/clang/AST/ExprCXX.h (+4-4)
  • (modified) clang/include/clang/AST/NestedNameSpecifier.h (+212-453)
  • (added) clang/include/clang/AST/NestedNameSpecifierBase.h (+586)
  • (modified) clang/include/clang/AST/ODRHash.h (+1-1)
  • (modified) clang/include/clang/AST/PropertiesBase.td (+2-3)
  • (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+37-37)
  • (modified) clang/include/clang/AST/TemplateBase.h (+13-23)
  • (modified) clang/include/clang/AST/TemplateName.h (+19-11)
  • (modified) clang/include/clang/AST/TextNodeDumper.h (+1-1)
  • (modified) clang/include/clang/AST/Type.h (+18-13)
  • (modified) clang/include/clang/AST/TypeLoc.h (+17-2)
  • (modified) clang/include/clang/ASTMatchers/ASTMatchers.h (+33-9)
  • (modified) clang/include/clang/ASTMatchers/ASTMatchersInternal.h (+1-1)
  • (modified) clang/include/clang/ExtractAPI/DeclarationFragments.h (+2-3)
  • (modified) clang/include/clang/Sema/CodeCompleteConsumer.h (+4-3)
  • (modified) clang/include/clang/Sema/DeclSpec.h (+6-6)
  • (modified) clang/include/clang/Sema/HeuristicResolver.h (+1-2)
  • (modified) clang/include/clang/Sema/Sema.h (+7-6)
  • (modified) clang/include/clang/Sema/SemaInternal.h (+4-4)
  • (modified) clang/include/clang/Sema/TypoCorrection.h (+15-14)
  • (modified) clang/include/clang/Serialization/ASTRecordReader.h (+1-1)
  • (modified) clang/include/clang/Serialization/ASTRecordWriter.h (+1-1)
  • (modified) clang/include/clang/Tooling/Refactoring/Lookup.h (+1-2)
  • (modified) clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h (+9-7)
  • (modified) clang/lib/AST/ASTConcept.cpp (+9-2)
  • (modified) clang/lib/AST/ASTContext.cpp (+94-214)
  • (modified) clang/lib/AST/ASTDiagnostic.cpp (+3-4)
  • (modified) clang/lib/AST/ASTImporter.cpp (+42-56)
  • (modified) clang/lib/AST/ASTStructuralEquivalence.cpp (+26-33)
  • (modified) clang/lib/AST/ASTTypeTraits.cpp (+31-5)
  • (modified) clang/lib/AST/ComputeDependence.cpp (+8-12)
  • (modified) clang/lib/AST/Decl.cpp (+7-12)
  • (modified) clang/lib/AST/DeclPrinter.cpp (+2-5)
  • (modified) clang/lib/AST/DynamicRecursiveASTVisitor.cpp (+17-4)
  • (modified) clang/lib/AST/ExprCXX.cpp (+3-4)
  • (modified) clang/lib/AST/ExprConcepts.cpp (+2-2)
  • (modified) clang/lib/AST/ItaniumMangle.cpp (+41-100)
  • (modified) clang/lib/AST/JSONNodeDumper.cpp (+2-2)
  • (modified) clang/lib/AST/NestedNameSpecifier.cpp (+89-382)
  • (modified) clang/lib/AST/ODRHash.cpp (+17-27)
  • (modified) clang/lib/AST/OpenMPClause.cpp (+11-15)
  • (modified) clang/lib/AST/ParentMapContext.cpp (+4-2)
  • (modified) clang/lib/AST/QualTypeNames.cpp (+163-161)
  • (modified) clang/lib/AST/StmtPrinter.cpp (+8-19)
  • (modified) clang/lib/AST/StmtProfile.cpp (+7-8)
  • (modified) clang/lib/AST/TemplateBase.cpp (+27-3)
  • (modified) clang/lib/AST/TemplateName.cpp (+36-20)
  • (modified) clang/lib/AST/TextNodeDumper.cpp (+14-16)
  • (modified) clang/lib/AST/Type.cpp (+32-3)
  • (modified) clang/lib/AST/TypeLoc.cpp (+131-3)
  • (modified) clang/lib/ASTMatchers/ASTMatchFinder.cpp (+21-21)
  • (modified) clang/lib/CodeGen/CGCXX.cpp (+5-6)
  • (modified) clang/lib/CodeGen/CGExprCXX.cpp (+2-2)
  • (modified) clang/lib/CodeGen/CodeGenFunction.h (+2-2)
  • (modified) clang/lib/ExtractAPI/DeclarationFragments.cpp (+18-24)
  • (modified) clang/lib/Index/IndexTypeSourceInfo.cpp (+16-20)
  • (modified) clang/lib/Index/USRGeneration.cpp (+2-2)
  • (modified) clang/lib/Parse/ParseDeclCXX.cpp (+1-1)
  • (modified) clang/lib/Parse/ParseTentative.cpp (+1-1)
  • (modified) clang/lib/Sema/AnalysisBasedWarnings.cpp (+4-7)
  • (modified) clang/lib/Sema/DeclSpec.cpp (+5-18)
  • (modified) clang/lib/Sema/HeuristicResolver.cpp (+20-17)
  • (modified) clang/lib/Sema/SemaCXXScopeSpec.cpp (+60-50)
  • (modified) clang/lib/Sema/SemaCodeComplete.cpp (+48-34)
  • (modified) clang/lib/Sema/SemaDecl.cpp (+40-38)
  • (modified) clang/lib/Sema/SemaDeclCXX.cpp (+20-23)
  • (modified) clang/lib/Sema/SemaExpr.cpp (+8-10)
  • (modified) clang/lib/Sema/SemaExprCXX.cpp (+21-16)
  • (modified) clang/lib/Sema/SemaLookup.cpp (+114-55)
  • (modified) clang/lib/Sema/SemaOverload.cpp (+9-9)
  • (modified) clang/lib/Sema/SemaTemplate.cpp (+87-108)
  • (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+16-29)
  • (modified) clang/lib/Sema/SemaTemplateDeductionGuide.cpp (+10-3)
  • (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+60-55)
  • (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+7-8)
  • (modified) clang/lib/Sema/SemaType.cpp (+15-4)
  • (modified) clang/lib/Sema/SemaTypeTraits.cpp (+3-4)
  • (modified) clang/lib/Sema/TreeTransform.h (+234-162)
  • (modified) clang/lib/Serialization/ASTReader.cpp (+15-22)
  • (modified) clang/lib/Serialization/ASTWriter.cpp (+25-24)
  • (modified) clang/lib/Tooling/Refactoring/Lookup.cpp (+1-11)
  • (modified) clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp (+74-36)
  • (modified) clang/lib/Tooling/Syntax/BuildTree.cpp (+82-84)
  • (modified) clang/tools/libclang/CIndex.cpp (+43-89)
  • (modified) clang/tools/libclang/CursorVisitor.h (+2-2)
  • (modified) clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp (+33-41)
  • (modified) clang/unittests/Sema/HeuristicResolverTest.cpp (+8-7)
  • (modified) clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp (+10-7)
  • (modified) clang/unittests/Tooling/RefactoringTest.cpp (+6-3)
diff --git a/clang-tools-extra/clang-change-namespace/ChangeNamespace.cpp b/clang-tools-extra/clang-change-namespace/ChangeNamespace.cpp
index 3e367ab1a5558..471ca45fb5a53 100644
--- a/clang-tools-extra/clang-change-namespace/ChangeNamespace.cpp
+++ b/clang-tools-extra/clang-change-namespace/ChangeNamespace.cpp
@@ -31,24 +31,9 @@ llvm::SmallVector<llvm::StringRef, 4> splitSymbolName(llvm::StringRef Name) {
   return Splitted;
 }
 
-SourceLocation startLocationForType(TypeLoc TLoc) {
-  // For elaborated types (e.g. `struct a::A`) we want the portion after the
-  // `struct` but including the namespace qualifier, `a::`.
-  if (TLoc.getTypeLocClass() == TypeLoc::Elaborated) {
-    NestedNameSpecifierLoc NestedNameSpecifier =
-        TLoc.castAs<ElaboratedTypeLoc>().getQualifierLoc();
-    if (NestedNameSpecifier.getNestedNameSpecifier())
-      return NestedNameSpecifier.getBeginLoc();
-    TLoc = TLoc.getNextTypeLoc();
-  }
-  return TLoc.getBeginLoc();
-}
-
 SourceLocation endLocationForType(TypeLoc TLoc) {
-  // Dig past any namespace or keyword qualifications.
-  while (TLoc.getTypeLocClass() == TypeLoc::Elaborated ||
-         TLoc.getTypeLocClass() == TypeLoc::Qualified)
-    TLoc = TLoc.getNextTypeLoc();
+  if (auto QTL = TLoc.getAs<QualifiedTypeLoc>())
+    TLoc = QTL.getUnqualifiedLoc();
 
   // The location for template specializations (e.g. Foo<int>) includes the
   // templated types in its location range.  We want to restrict this to just
@@ -550,8 +535,8 @@ void ChangeNamespaceTool::run(
                  Result.Nodes.getNodeAs<NestedNameSpecifierLoc>(
                      "nested_specifier_loc")) {
     SourceLocation Start = Specifier->getBeginLoc();
-    SourceLocation End = endLocationForType(Specifier->getTypeLoc());
-    fixTypeLoc(Result, Start, End, Specifier->getTypeLoc());
+    SourceLocation End = endLocationForType(Specifier->castAsTypeLoc());
+    fixTypeLoc(Result, Start, End, Specifier->castAsTypeLoc());
   } else if (const auto *BaseInitializer =
                  Result.Nodes.getNodeAs<CXXCtorInitializer>(
                      "base_initializer")) {
@@ -562,19 +547,16 @@ void ChangeNamespaceTool::run(
     // filtered by matchers in some cases, e.g. the type is templated. We should
     // handle the record type qualifier instead.
     TypeLoc Loc = *TLoc;
-    while (Loc.getTypeLocClass() == TypeLoc::Qualified)
-      Loc = Loc.getNextTypeLoc();
-    if (Loc.getTypeLocClass() == TypeLoc::Elaborated) {
-      NestedNameSpecifierLoc NestedNameSpecifier =
-          Loc.castAs<ElaboratedTypeLoc>().getQualifierLoc();
-      // FIXME: avoid changing injected class names.
-      if (auto *NNS = NestedNameSpecifier.getNestedNameSpecifier()) {
-        const Type *SpecifierType = NNS->getAsType();
-        if (SpecifierType && SpecifierType->isRecordType())
-          return;
-      }
-    }
-    fixTypeLoc(Result, startLocationForType(Loc), endLocationForType(Loc), Loc);
+    if (auto QTL = Loc.getAs<QualifiedTypeLoc>())
+      Loc = QTL.getUnqualifiedLoc();
+    // FIXME: avoid changing injected class names.
+    if (NestedNameSpecifier NestedNameSpecifier =
+            Loc.getPrefix().getNestedNameSpecifier();
+        NestedNameSpecifier.getKind() == NestedNameSpecifier::Kind::Type &&
+        NestedNameSpecifier.getAsType()->isRecordType())
+      return;
+    fixTypeLoc(Result, Loc.getNonElaboratedBeginLoc(), endLocationForType(Loc),
+               Loc);
   } else if (const auto *VarRef =
                  Result.Nodes.getNodeAs<DeclRefExpr>("var_ref")) {
     const auto *Var = Result.Nodes.getNodeAs<VarDecl>("var_decl");
@@ -588,10 +570,9 @@ void ChangeNamespaceTool::run(
   } else if (const auto *EnumConstRef =
                  Result.Nodes.getNodeAs<DeclRefExpr>("enum_const_ref")) {
     // Do not rename the reference if it is already scoped by the EnumDecl name.
-    if (EnumConstRef->hasQualifier() &&
-        EnumConstRef->getQualifier()->getKind() ==
-            NestedNameSpecifier::SpecifierKind::TypeSpec &&
-        EnumConstRef->getQualifier()->getAsType()->isEnumeralType())
+    if (NestedNameSpecifier Qualifier = EnumConstRef->getQualifier();
+        Qualifier.getKind() == NestedNameSpecifier::Kind::Type &&
+        Qualifier.getAsType()->isEnumeralType())
       return;
     const auto *EnumConstDecl =
         Result.Nodes.getNodeAs<EnumConstantDecl>("enum_const_decl");
diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index f9d75978d0ea8..fac6e0418d163 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -533,7 +533,8 @@ void ClangTidyDiagnosticConsumer::forwardDiagnostic(const Diagnostic &Info) {
       Builder << reinterpret_cast<const NamedDecl *>(Info.getRawArg(Index));
       break;
     case clang::DiagnosticsEngine::ak_nestednamespec:
-      Builder << reinterpret_cast<NestedNameSpecifier *>(Info.getRawArg(Index));
+      Builder << NestedNameSpecifier::getFromVoidPointer(
+          reinterpret_cast<void *>(Info.getRawArg(Index)));
       break;
     case clang::DiagnosticsEngine::ak_declcontext:
       Builder << reinterpret_cast<DeclContext *>(Info.getRawArg(Index));
diff --git a/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
index 00e8f7e514368..10b747e17e2ad 100644
--- a/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
@@ -33,21 +33,17 @@ AST_MATCHER(QualType, isEnableIf) {
     BaseType = BaseType->getPointeeType().getTypePtr();
   }
   // Case: type parameter dependent (enable_if<is_integral<T>>).
-  if (const auto *Dependent = BaseType->getAs<DependentNameType>()) {
-    BaseType = Dependent->getQualifier()->getAsType();
-  }
+  if (const auto *Dependent = BaseType->getAs<DependentNameType>())
+    BaseType = Dependent->getQualifier().getAsType();
   if (!BaseType)
     return false;
   if (CheckTemplate(BaseType->getAs<TemplateSpecializationType>()))
     return true; // Case: enable_if_t< >.
-  if (const auto *Elaborated = BaseType->getAs<ElaboratedType>()) {
-    if (const auto *Q = Elaborated->getQualifier())
-      if (const auto *Qualifier = Q->getAsType()) {
-        if (CheckTemplate(Qualifier->getAs<TemplateSpecializationType>())) {
-          return true; // Case: enable_if< >::type.
-        }
-      }
-  }
+  if (const auto *TT = BaseType->getAs<TypedefType>())
+    if (NestedNameSpecifier Q = TT->getQualifier();
+        Q.getKind() == NestedNameSpecifier::Kind::Type)
+      if (CheckTemplate(Q.getAsType()->getAs<TemplateSpecializationType>()))
+        return true; // Case: enable_if< >::type.
   return false;
 }
 AST_MATCHER_P(TemplateTypeParmDecl, hasDefaultArgument,
diff --git a/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp
index bfa2ab51a6d03..5dc988d6662df 100644
--- a/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp
@@ -39,24 +39,31 @@ static void replaceMoveWithForward(const UnresolvedLookupExpr *Callee,
     // std::move(). This will hopefully prevent erroneous replacements if the
     // code does unusual things (e.g. create an alias for std::move() in
     // another namespace).
-    NestedNameSpecifier *NNS = Callee->getQualifier();
-    if (!NNS) {
+    NestedNameSpecifier NNS = Callee->getQualifier();
+    switch (NNS.getKind()) {
+    case NestedNameSpecifier::Kind::Null:
       // Called as "move" (i.e. presumably the code had a "using std::move;").
       // We still conservatively put a "std::" in front of the forward because
       // we don't know whether the code also had a "using std::forward;".
       Diag << FixItHint::CreateReplacement(CallRange, "std::" + ForwardName);
-    } else if (const NamespaceBaseDecl *Namespace = NNS->getAsNamespace()) {
+      break;
+    case NestedNameSpecifier::Kind::Namespace: {
+      auto [Namespace, Prefix] = NNS.getAsNamespaceAndPrefix();
       if (Namespace->getName() == "std") {
-        if (!NNS->getPrefix()) {
+        if (!Prefix) {
           // Called as "std::move".
           Diag << FixItHint::CreateReplacement(CallRange,
                                                "std::" + ForwardName);
-        } else if (NNS->getPrefix()->getKind() == NestedNameSpecifier::Global) {
+        } else if (Prefix.getKind() == NestedNameSpecifier::Kind::Global) {
           // Called as "::std::move".
           Diag << FixItHint::CreateReplacement(CallRange,
                                                "::std::" + ForwardName);
         }
       }
+      break;
+    }
+    default:
+      return;
     }
   }
 }
diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
index 99763bd430f00..107eda2e98f27 100644
--- a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
@@ -45,14 +45,6 @@ static bool incrementWithoutOverflow(const APSInt &Value, APSInt &Result) {
   return Value < Result;
 }
 
-static bool areEquivalentNameSpecifier(const NestedNameSpecifier *Left,
-                                       const NestedNameSpecifier *Right) {
-  llvm::FoldingSetNodeID LeftID, RightID;
-  Left->Profile(LeftID);
-  Right->Profile(RightID);
-  return LeftID == RightID;
-}
-
 static bool areEquivalentExpr(const Expr *Left, const Expr *Right) {
   if (!Left || !Right)
     return !Left && !Right;
diff --git a/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp b/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp
index 86992cd8a141b..4fa679aa8dd88 100644
--- a/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp
@@ -35,12 +35,12 @@ void UnusedAliasDeclsCheck::check(const MatchFinder::MatchResult &Result) {
   }
 
   if (const auto *NestedName =
-          Result.Nodes.getNodeAs<NestedNameSpecifier>("nns")) {
-    if (const auto *AliasDecl = dyn_cast_if_present<NamespaceAliasDecl>(
-            NestedName->getAsNamespace())) {
+          Result.Nodes.getNodeAs<NestedNameSpecifier>("nns");
+      NestedName &&
+      NestedName->getKind() == NestedNameSpecifier::Kind::Namespace)
+    if (const auto *AliasDecl = dyn_cast<NamespaceAliasDecl>(
+            NestedName->getAsNamespaceAndPrefix().Namespace))
       FoundDecls[AliasDecl] = CharSourceRange();
-    }
-  }
 }
 
 void UnusedAliasDeclsCheck::onEndOfTranslationUnit() {
diff --git a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp
index 76ea3e799aa6d..de2d42d760550 100644
--- a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp
@@ -214,14 +214,11 @@ static bool isNamedDeclInStdTraitsSet(const NamedDecl *ND,
          Set.contains(ND->getName());
 }
 
-static bool checkTemplatedDecl(const NestedNameSpecifier *NNS,
+static bool checkTemplatedDecl(NestedNameSpecifier NNS,
                                const llvm::StringSet<> &Set) {
-  if (!NNS)
+  if (NNS.getKind() != NestedNameSpecifier::Kind::Type)
     return false;
-  const Type *NNST = NNS->getAsType();
-  if (!NNST)
-    return false;
-  const auto *TST = NNST->getAs<TemplateSpecializationType>();
+  const auto *TST = NNS.getAsType()->getAs<TemplateSpecializationType>();
   if (!TST)
     return false;
   if (const TemplateDecl *TD = TST->getTemplateName().getAsTemplateDecl()) {
@@ -238,8 +235,8 @@ void TypeTraitsCheck::check(const MatchFinder::MatchResult &Result) {
   auto EmitValueWarning = [this, &Result](const NestedNameSpecifierLoc &QualLoc,
                                           SourceLocation EndLoc) {
     SourceLocation TemplateNameEndLoc;
-    if (auto TSTL = QualLoc.getTypeLoc().getAs<TemplateSpecializationTypeLoc>();
-        !TSTL.isNull())
+    if (auto TSTL =
+            QualLoc.getAsTypeLoc().getAs<TemplateSpecializationTypeLoc>())
       TemplateNameEndLoc = Lexer::getLocForEndOfToken(
           TSTL.getTemplateNameLoc(), 0, *Result.SourceManager,
           Result.Context->getLangOpts());
@@ -289,23 +286,21 @@ void TypeTraitsCheck::check(const MatchFinder::MatchResult &Result) {
     if (!DRE->hasQualifier())
       return;
     if (const auto *CTSD = dyn_cast_if_present<ClassTemplateSpecializationDecl>(
-            DRE->getQualifier()->getAsRecordDecl())) {
+            DRE->getQualifier().getAsRecordDecl())) {
       if (isNamedDeclInStdTraitsSet(CTSD, ValueTraits))
         EmitValueWarning(DRE->getQualifierLoc(), DRE->getEndLoc());
     }
     return;
   }
 
-  if (const auto *ETL = Result.Nodes.getNodeAs<ElaboratedTypeLoc>(Bind)) {
-    const NestedNameSpecifierLoc QualLoc = ETL->getQualifierLoc();
-    const auto *NNS = QualLoc.getNestedNameSpecifier();
-    if (!NNS)
-      return;
+  if (const auto *TL = Result.Nodes.getNodeAs<TypedefTypeLoc>(Bind)) {
+    const NestedNameSpecifierLoc QualLoc = TL->getQualifierLoc();
+    NestedNameSpecifier NNS = QualLoc.getNestedNameSpecifier();
     if (const auto *CTSD = dyn_cast_if_present<ClassTemplateSpecializationDecl>(
-            NNS->getAsRecordDecl())) {
+            NNS.getAsRecordDecl())) {
       if (isNamedDeclInStdTraitsSet(CTSD, TypeTraits))
-        EmitTypeWarning(ETL->getQualifierLoc(), ETL->getEndLoc(),
-                        ETL->getElaboratedKeywordLoc());
+        EmitTypeWarning(TL->getQualifierLoc(), TL->getEndLoc(),
+                        TL->getElaboratedKeywordLoc());
     }
     return;
   }
diff --git a/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
index ced4825f79a99..82f64096cbec1 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
@@ -64,66 +64,65 @@ struct UnqualNameVisitor : public RecursiveASTVisitor<UnqualNameVisitor> {
     return false;
   }
 
-  bool TraverseTypeLoc(TypeLoc TL, bool Elaborated = false) {
+  bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) {
     if (TL.isNull())
       return true;
 
-    if (!Elaborated) {
-      switch (TL.getTypeLocClass()) {
-      case TypeLoc::Record:
-        if (visitUnqualName(
-                TL.getAs<RecordTypeLoc>().getTypePtr()->getDecl()->getName()))
-          return false;
+    switch (TL.getTypeLocClass()) {
+    case TypeLoc::InjectedClassName:
+    case TypeLoc::Record:
+    case TypeLoc::Enum: {
+      auto TTL = TL.getAs<TagTypeLoc>();
+      const auto *T = TTL.getTypePtr();
+      if (T->getKeyword() != ElaboratedTypeKeyword::None ||
+          TTL.getQualifierLoc())
         break;
-      case TypeLoc::Enum:
-        if (visitUnqualName(
-                TL.getAs<EnumTypeLoc>().getTypePtr()->getDecl()->getName()))
-          return false;
-        break;
-      case TypeLoc::TemplateSpecialization:
-        if (visitUnqualName(TL.getAs<TemplateSpecializationTypeLoc>()
-                                .getTypePtr()
-                                ->getTemplateName()
-                                .getAsTemplateDecl()
-                                ->getName()))
-          return false;
-        break;
-      case TypeLoc::Typedef:
-        if (visitUnqualName(
-                TL.getAs<TypedefTypeLoc>().getTypePtr()->getDecl()->getName()))
-          return false;
+      if (visitUnqualName(T->getOriginalDecl()->getName()))
+        return false;
+      break;
+    }
+    case TypeLoc::TemplateSpecialization: {
+      auto TTL = TL.getAs<TemplateSpecializationTypeLoc>();
+      const auto *T = TTL.getTypePtr();
+      if (T->getKeyword() != ElaboratedTypeKeyword::None ||
+          TTL.getQualifierLoc())
         break;
-      case TypeLoc::Using:
-        if (visitUnqualName(TL.getAs<UsingTypeLoc>()
-                                .getTypePtr()
-                                ->getFoundDecl()
-                                ->getName()))
-          return false;
+      if (visitUnqualName(T->getTemplateName().getAsTemplateDecl()->getName()))
+        return false;
+      break;
+    }
+    case TypeLoc::Typedef: {
+      auto TTL = TL.getAs<TypedefTypeLoc>();
+      const auto *T = TTL.getTypePtr();
+      if (T->getKeyword() != ElaboratedTypeKeyword::None ||
+          TTL.getQualifierLoc())
         break;
-      default:
+      if (visitUnqualName(T->getDecl()->getName()))
+        return false;
+      break;
+    }
+    case TypeLoc::Using: {
+      auto TTL = TL.getAs<UsingTypeLoc>();
+      const auto *T = TTL.getTypePtr();
+      if (T->getKeyword() != ElaboratedTypeKeyword::None ||
+          TTL.getQualifierLoc())
         break;
-      }
+      if (visitUnqualName(T->getDecl()->getName()))
+        return false;
+      break;
+    }
+    default:
+      break;
     }
 
-    return RecursiveASTVisitor<UnqualNameVisitor>::TraverseTypeLoc(TL);
+    return RecursiveASTVisitor<UnqualNameVisitor>::TraverseTypeLoc(
+        TL, TraverseQualifier);
   }
 
   // Replace the base method in order to call our own
   // TraverseTypeLoc().
-  bool TraverseQualifiedTypeLoc(QualifiedTypeLoc TL) {
-    return TraverseTypeLoc(TL.getUnqualifiedLoc());
-  }
-
-  // Replace the base version to inform TraverseTypeLoc that the type is
-  // elaborated.
-  bool TraverseElaboratedTypeLoc(ElaboratedTypeLoc TL) {
-    if (TL.getQualifierLoc() &&
-        !TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()))
-      return false;
-    const auto *T = TL.getTypePtr();
-    return TraverseTypeLoc(TL.getNamedTypeLoc(),
-                           T->getKeyword() != ElaboratedTypeKeyword::None ||
-                               T->getQualifier());
+  bool TraverseQualifiedTypeLoc(QualifiedTypeLoc TL, bool TraverseQualifier) {
+    return TraverseTypeLoc(TL.getUnqualifiedLoc(), TraverseQualifier);
   }
 
   bool VisitDeclRefExpr(DeclRefExpr *S) {
diff --git a/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp b/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
index fffb136e5a332..a7b3c4a1f7cf9 100644
--- a/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
@@ -19,19 +19,25 @@ namespace {
 AST_MATCHER(CXXMethodDecl, isStatic) { return Node.isStatic(); }
 } // namespace
 
-static unsigned getNameSpecifierNestingLevel(const QualType &QType) {
-  if (const auto *ElType = QType->getAs<ElaboratedType>()) {
-    if (const NestedNameSpecifier *NestedSpecifiers = ElType->getQualifier()) {
-      unsigned NameSpecifierNestingLevel = 1;
-      do {
-        NameSpecifierNestingLevel++;
-        NestedSpecifiers = NestedSpecifiers->getPrefix();
-      } while (NestedSpecifiers);
-
+static unsigned getNameSpecifierNestingLevel(QualType QType) {
+  unsigned NameSpecifierNestingLevel = 1;
+  for (NestedNameSpecifier Qualifier = QType->getPrefix(); /**/;
+       ++NameSpecifierNestingLevel) {
+    switch (Qualifier.getKind()) {
+    case NestedNameSpecifier::Kind::Null:
       return NameSpecifierNestingLevel;
+    case NestedNameSpecifier::Kind::Global:
+    case NestedNameSpecifier::Kind::MicrosoftSuper:
+      return NameSpecifierNestingLevel + 1;
+    case NestedNameSpecifier::Kind::Namespace:
+      Qualifier = Qualifier.getAsNamespaceAndPrefix().Prefix;
+      continue;
+    case NestedNameSpecifier::Kind::Type:
+      Qualifier = Qualifier.getAsType()->getPrefix();
+      continue;
     }
+    llvm_unreachable("unhandled nested name specifier kind");
   }
-  return 0;
 }
 
 void StaticAccessedThroughInstanceCheck::storeOptions(
diff --git a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp
index 1ef1da71cbce1..3cf6e57ca4df5 100644
--- a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp
+++ b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp
@@ -281,9 +281,10 @@ ...
[truncated]

@mizvekov mizvekov force-pushed the users/mizvekov/name-qualification-refactor-5 branch from 3c4412b to 021d58c Compare July 21, 2025 00:07
@mizvekov mizvekov force-pushed the users/mizvekov/name-qualification-refactor-6 branch from a94165a to 1937c00 Compare July 21, 2025 00:07
@mizvekov mizvekov force-pushed the users/mizvekov/name-qualification-refactor-5 branch from 021d58c to ee9bcb9 Compare July 21, 2025 03:27
@mizvekov mizvekov force-pushed the users/mizvekov/name-qualification-refactor-6 branch 2 times, most recently from 45732be to df4ca6a Compare July 21, 2025 23:55
@mizvekov mizvekov force-pushed the users/mizvekov/name-qualification-refactor-5 branch from ee9bcb9 to f695908 Compare July 21, 2025 23:55
@mizvekov
Copy link
Contributor Author

@erichkeane this was the only patch in the series you didn't review. FYI in case this was an oversight.

@mizvekov mizvekov force-pushed the users/mizvekov/name-qualification-refactor-5 branch from f695908 to ce5f365 Compare July 22, 2025 00:01
@mizvekov mizvekov force-pushed the users/mizvekov/name-qualification-refactor-6 branch from df4ca6a to 998f226 Compare July 22, 2025 00:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:as-a-library libclang and C++ API clang:codegen IR generation bugs: mangling, exceptions, etc. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules clang:openmp OpenMP related changes to Clang clang Clang issues not falling into any other category clang-tidy clang-tools-extra clangd
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants