[llvm-branch-commits] [clang] [clang-tools-extra] [PATCH 6/6] [clang] improve NestedNameSpecifier (PR #149748)
Matheus Izvekov via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sun Jul 20 16:47:00 PDT 2025
https://github.com/mizvekov created https://github.com/llvm/llvm-project/pull/149748
This contains the NestedNameSpecifier representation changes originally from: https://github.com/llvm/llvm-project/pull/147835
>From a94165a38354076b700b7581d183496267f1a186 Mon Sep 17 00:00:00 2001
From: Matheus Izvekov <mizvekov at gmail.com>
Date: Sun, 20 Jul 2025 14:53:30 -0300
Subject: [PATCH] [PATCH 6/6] [clang] improve NestedNameSpecifier
---
.../ChangeNamespace.cpp | 53 +-
.../ClangTidyDiagnosticConsumer.cpp | 3 +-
.../ForwardingReferenceOverloadCheck.cpp | 18 +-
.../bugprone/MoveForwardingReferenceCheck.cpp | 17 +-
.../misc/RedundantExpressionCheck.cpp | 8 -
.../clang-tidy/misc/UnusedAliasDeclsCheck.cpp | 10 +-
.../clang-tidy/modernize/TypeTraitsCheck.cpp | 29 +-
.../modernize/UseTrailingReturnTypeCheck.cpp | 93 ++-
.../StaticAccessedThroughInstanceCheck.cpp | 26 +-
.../utils/RenamerClangTidyCheck.cpp | 5 +-
clang-tools-extra/clangd/AST.cpp | 83 ++-
clang-tools-extra/clangd/CodeComplete.cpp | 16 +-
clang-tools-extra/clangd/DumpAST.cpp | 33 +-
clang-tools-extra/clangd/FindTarget.cpp | 85 ++-
clang-tools-extra/clangd/IncludeFixer.cpp | 50 +-
clang-tools-extra/clangd/Selection.cpp | 2 +-
.../clangd/SemanticHighlighting.cpp | 15 -
.../clangd/refactor/tweaks/AddUsing.cpp | 121 ++--
.../refactor/tweaks/ExtractFunction.cpp | 2 +-
.../clangd/unittests/FindTargetTests.cpp | 4 +-
.../clangd/unittests/SelectionTests.cpp | 4 +-
.../include-cleaner/lib/WalkAST.cpp | 16 +-
clang/include/clang/AST/ASTConcept.h | 9 +-
clang/include/clang/AST/ASTContext.h | 38 +-
clang/include/clang/AST/ASTImporter.h | 2 +-
clang/include/clang/AST/ASTNodeTraverser.h | 12 +-
clang/include/clang/AST/ASTTypeTraits.h | 13 +-
clang/include/clang/AST/AbstractBasicReader.h | 37 +-
clang/include/clang/AST/AbstractBasicWriter.h | 33 +-
clang/include/clang/AST/CanonicalType.h | 2 +-
clang/include/clang/AST/Decl.h | 10 +-
clang/include/clang/AST/DeclCXX.h | 16 +-
clang/include/clang/AST/DependenceFlags.h | 2 +-
.../clang/AST/DynamicRecursiveASTVisitor.h | 3 +-
clang/include/clang/AST/Expr.h | 4 +-
clang/include/clang/AST/ExprCXX.h | 8 +-
clang/include/clang/AST/NestedNameSpecifier.h | 665 ++++++------------
.../clang/AST/NestedNameSpecifierBase.h | 586 +++++++++++++++
clang/include/clang/AST/ODRHash.h | 2 +-
clang/include/clang/AST/PropertiesBase.td | 5 +-
clang/include/clang/AST/RecursiveASTVisitor.h | 74 +-
clang/include/clang/AST/TemplateBase.h | 36 +-
clang/include/clang/AST/TemplateName.h | 30 +-
clang/include/clang/AST/TextNodeDumper.h | 2 +-
clang/include/clang/AST/Type.h | 31 +-
clang/include/clang/AST/TypeLoc.h | 19 +-
clang/include/clang/ASTMatchers/ASTMatchers.h | 42 +-
.../clang/ASTMatchers/ASTMatchersInternal.h | 2 +-
.../clang/ExtractAPI/DeclarationFragments.h | 5 +-
.../include/clang/Sema/CodeCompleteConsumer.h | 7 +-
clang/include/clang/Sema/DeclSpec.h | 12 +-
clang/include/clang/Sema/HeuristicResolver.h | 3 +-
clang/include/clang/Sema/Sema.h | 13 +-
clang/include/clang/Sema/SemaInternal.h | 8 +-
clang/include/clang/Sema/TypoCorrection.h | 29 +-
.../clang/Serialization/ASTRecordReader.h | 2 +-
.../clang/Serialization/ASTRecordWriter.h | 2 +-
.../clang/Tooling/Refactoring/Lookup.h | 3 +-
.../Refactoring/RecursiveSymbolVisitor.h | 16 +-
clang/lib/AST/ASTConcept.cpp | 11 +-
clang/lib/AST/ASTContext.cpp | 308 +++-----
clang/lib/AST/ASTDiagnostic.cpp | 7 +-
clang/lib/AST/ASTImporter.cpp | 98 ++-
clang/lib/AST/ASTStructuralEquivalence.cpp | 59 +-
clang/lib/AST/ASTTypeTraits.cpp | 36 +-
clang/lib/AST/ComputeDependence.cpp | 20 +-
clang/lib/AST/Decl.cpp | 19 +-
clang/lib/AST/DeclPrinter.cpp | 7 +-
clang/lib/AST/DynamicRecursiveASTVisitor.cpp | 21 +-
clang/lib/AST/ExprCXX.cpp | 7 +-
clang/lib/AST/ExprConcepts.cpp | 4 +-
clang/lib/AST/ItaniumMangle.cpp | 141 ++--
clang/lib/AST/JSONNodeDumper.cpp | 4 +-
clang/lib/AST/NestedNameSpecifier.cpp | 471 +++----------
clang/lib/AST/ODRHash.cpp | 44 +-
clang/lib/AST/OpenMPClause.cpp | 26 +-
clang/lib/AST/ParentMapContext.cpp | 6 +-
clang/lib/AST/QualTypeNames.cpp | 324 ++++-----
clang/lib/AST/StmtPrinter.cpp | 27 +-
clang/lib/AST/StmtProfile.cpp | 15 +-
clang/lib/AST/TemplateBase.cpp | 30 +-
clang/lib/AST/TemplateName.cpp | 56 +-
clang/lib/AST/TextNodeDumper.cpp | 30 +-
clang/lib/AST/Type.cpp | 35 +-
clang/lib/AST/TypeLoc.cpp | 134 +++-
clang/lib/ASTMatchers/ASTMatchFinder.cpp | 42 +-
clang/lib/CodeGen/CGCXX.cpp | 11 +-
clang/lib/CodeGen/CGExprCXX.cpp | 4 +-
clang/lib/CodeGen/CodeGenFunction.h | 4 +-
clang/lib/ExtractAPI/DeclarationFragments.cpp | 42 +-
clang/lib/Index/IndexTypeSourceInfo.cpp | 36 +-
clang/lib/Index/USRGeneration.cpp | 4 +-
clang/lib/Parse/ParseDeclCXX.cpp | 2 +-
clang/lib/Parse/ParseTentative.cpp | 2 +-
clang/lib/Sema/AnalysisBasedWarnings.cpp | 11 +-
clang/lib/Sema/DeclSpec.cpp | 23 +-
clang/lib/Sema/HeuristicResolver.cpp | 37 +-
clang/lib/Sema/SemaCXXScopeSpec.cpp | 110 +--
clang/lib/Sema/SemaCodeComplete.cpp | 82 ++-
clang/lib/Sema/SemaDecl.cpp | 78 +-
clang/lib/Sema/SemaDeclCXX.cpp | 43 +-
clang/lib/Sema/SemaExpr.cpp | 18 +-
clang/lib/Sema/SemaExprCXX.cpp | 37 +-
clang/lib/Sema/SemaLookup.cpp | 169 +++--
clang/lib/Sema/SemaOverload.cpp | 18 +-
clang/lib/Sema/SemaTemplate.cpp | 195 +++--
clang/lib/Sema/SemaTemplateDeduction.cpp | 45 +-
clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 13 +-
clang/lib/Sema/SemaTemplateInstantiate.cpp | 115 +--
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 15 +-
clang/lib/Sema/SemaType.cpp | 19 +-
clang/lib/Sema/SemaTypeTraits.cpp | 7 +-
clang/lib/Sema/TreeTransform.h | 396 ++++++-----
clang/lib/Serialization/ASTReader.cpp | 37 +-
clang/lib/Serialization/ASTWriter.cpp | 49 +-
clang/lib/Tooling/Refactoring/Lookup.cpp | 12 +-
.../Refactoring/Rename/USRLocFinder.cpp | 110 ++-
clang/lib/Tooling/Syntax/BuildTree.cpp | 166 +++--
clang/tools/libclang/CIndex.cpp | 132 ++--
clang/tools/libclang/CursorVisitor.h | 4 +-
.../ASTMatchers/ASTMatchersTraversalTest.cpp | 74 +-
.../unittests/Sema/HeuristicResolverTest.cpp | 15 +-
.../NestedNameSpecifiers.cpp | 17 +-
clang/unittests/Tooling/RefactoringTest.cpp | 9 +-
124 files changed, 3390 insertions(+), 3229 deletions(-)
create mode 100644 clang/include/clang/AST/NestedNameSpecifierBase.h
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 @@ class RenamerClangTidyVisitor
}
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc Loc) {
- if (const NestedNameSpecifier *Spec = Loc.getNestedNameSpecifier()) {
+ if (NestedNameSpecifier Spec = Loc.getNestedNameSpecifier();
+ Spec.getKind() == NestedNameSpecifier::Kind::Namespace) {
if (const auto *Decl =
- dyn_cast_if_present<NamespaceDecl>(Spec->getAsNamespace()))
+ dyn_cast<NamespaceDecl>(Spec.getAsNamespaceAndPrefix().Namespace))
Check->addUsage(Decl, Loc.getLocalSourceRange(), SM);
}
diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp
index 218d3f7359afb..82aee4c84d074 100644
--- a/clang-tools-extra/clangd/AST.cpp
+++ b/clang-tools-extra/clangd/AST.cpp
@@ -102,54 +102,78 @@ getUsingNamespaceDirectives(const DeclContext *DestContext,
// ancestor is redundant, therefore we stop at lowest common ancestor.
// In addition to that stops early whenever IsVisible returns true. This can be
// used to implement support for "using namespace" decls.
-std::string
-getQualification(ASTContext &Context, const DeclContext *DestContext,
- const DeclContext *SourceContext,
- llvm::function_ref<bool(NestedNameSpecifier *)> IsVisible) {
- std::vector<const NestedNameSpecifier *> Parents;
- bool ReachedNS = false;
+std::string getQualification(ASTContext &Context,
+ const DeclContext *DestContext,
+ const DeclContext *SourceContext,
+ llvm::function_ref<bool(const Decl *)> IsVisible) {
+ std::vector<const Decl *> Parents;
+ [[maybe_unused]] bool ReachedNS = false;
for (const DeclContext *CurContext = SourceContext; CurContext;
CurContext = CurContext->getLookupParent()) {
// Stop once we reach a common ancestor.
if (CurContext->Encloses(DestContext))
break;
- NestedNameSpecifier *NNS = nullptr;
+ const Decl *CurD;
if (auto *TD = llvm::dyn_cast<TagDecl>(CurContext)) {
// There can't be any more tag parents after hitting a namespace.
assert(!ReachedNS);
- (void)ReachedNS;
- NNS = NestedNameSpecifier::Create(Context, nullptr, TD->getTypeForDecl());
+ CurD = TD;
} else if (auto *NSD = llvm::dyn_cast<NamespaceDecl>(CurContext)) {
ReachedNS = true;
- NNS = NestedNameSpecifier::Create(Context, nullptr, NSD);
// Anonymous and inline namespace names are not spelled while qualifying
// a name, so skip those.
if (NSD->isAnonymousNamespace() || NSD->isInlineNamespace())
continue;
+ CurD = NSD;
} else {
// Other types of contexts cannot be spelled in code, just skip over
// them.
continue;
}
// Stop if this namespace is already visible at DestContext.
- if (IsVisible(NNS))
+ if (IsVisible(CurD))
break;
- Parents.push_back(NNS);
+ Parents.push_back(CurD);
+ }
+
+ // Go over the declarations in reverse order, since we stored inner-most
+ // parent first.
+ NestedNameSpecifier Qualifier = std::nullopt;
+ bool IsFirst = true;
+ for (const auto *CurD : llvm::reverse(Parents)) {
+ if (auto *TD = llvm::dyn_cast<TagDecl>(CurD)) {
+ QualType T;
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(TD);
+ ClassTemplateDecl *CTD = RD->getDescribedClassTemplate()) {
+ ArrayRef<TemplateArgument> Args;
+ if (const auto *SD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
+ Args = SD->getTemplateArgs().asArray();
+ else
+ Args = CTD->getTemplateParameters()->getInjectedTemplateArgs(Context);
+ T = Context.getTemplateSpecializationType(
+ ElaboratedTypeKeyword::None,
+ Context.getQualifiedTemplateName(
+ Qualifier, /*TemplateKeyword=*/!IsFirst, TemplateName(CTD)),
+ Args, /*CanonicalArgs=*/{}, Context.getCanonicalTagType(RD));
+ } else {
+ T = Context.getTagType(ElaboratedTypeKeyword::None, Qualifier, TD,
+ /*OwnsTag=*/false);
+ }
+ Qualifier = NestedNameSpecifier(T.getTypePtr());
+ } else {
+ Qualifier =
+ NestedNameSpecifier(Context, cast<NamespaceDecl>(CurD), Qualifier);
+ }
+ IsFirst = false;
}
+ if (!Qualifier)
+ return "";
- // Go over name-specifiers in reverse order to create necessary qualification,
- // since we stored inner-most parent first.
std::string Result;
llvm::raw_string_ostream OS(Result);
- for (const auto *Parent : llvm::reverse(Parents)) {
- if (Parent != *Parents.rbegin() && Parent->isDependent() &&
- Parent->getAsRecordDecl() &&
- Parent->getAsRecordDecl()->getDescribedClassTemplate())
- OS << "template ";
- Parent->print(OS, Context.getPrintingPolicy());
- }
+ Qualifier.print(OS, Context.getPrintingPolicy());
return OS.str();
}
@@ -249,8 +273,7 @@ std::string printName(const ASTContext &Ctx, const NamedDecl &ND) {
}
// Print nested name qualifier if it was written in the source code.
- if (auto *Qualifier = getQualifierLoc(ND).getNestedNameSpecifier())
- Qualifier->print(Out, PP);
+ getQualifierLoc(ND).getNestedNameSpecifier().print(Out, PP);
// Print the name itself.
ND.getDeclName().print(Out, PP);
// Print template arguments.
@@ -665,13 +688,10 @@ std::string getQualification(ASTContext &Context,
auto VisibleNamespaceDecls =
getUsingNamespaceDirectives(DestContext, InsertionPoint);
return getQualification(
- Context, DestContext, ND->getDeclContext(),
- [&](NestedNameSpecifier *NNS) {
- const NamespaceDecl *NS =
- dyn_cast_if_present<NamespaceDecl>(NNS->getAsNamespace());
- if (!NS)
+ Context, DestContext, ND->getDeclContext(), [&](const Decl *D) {
+ if (D->getKind() != Decl::Namespace)
return false;
- NS = NS->getCanonicalDecl();
+ const auto *NS = cast<NamespaceDecl>(D)->getCanonicalDecl();
return llvm::any_of(VisibleNamespaceDecls,
[NS](const NamespaceDecl *NSD) {
return NSD->getCanonicalDecl() == NS;
@@ -688,12 +708,11 @@ std::string getQualification(ASTContext &Context,
(void)NS;
}
return getQualification(
- Context, DestContext, ND->getDeclContext(),
- [&](NestedNameSpecifier *NNS) {
+ Context, DestContext, ND->getDeclContext(), [&](const Decl *D) {
return llvm::any_of(VisibleNamespaces, [&](llvm::StringRef Namespace) {
std::string NS;
llvm::raw_string_ostream OS(NS);
- NNS->print(OS, Context.getPrintingPolicy());
+ D->print(OS, Context.getPrintingPolicy());
return OS.str() == Namespace;
});
});
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index 184c3c962f063..69fca8de6b402 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -1462,19 +1462,15 @@ bool allowIndex(CodeCompletionContext &CC) {
auto Scope = CC.getCXXScopeSpecifier();
if (!Scope)
return true;
- NestedNameSpecifier *NameSpec = (*Scope)->getScopeRep();
- if (!NameSpec)
- return true;
// We only query the index when qualifier is a namespace.
// If it's a class, we rely solely on sema completions.
- switch (NameSpec->getKind()) {
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Namespace:
+ switch ((*Scope)->getScopeRep().getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::Namespace:
return true;
- case NestedNameSpecifier::Super:
- case NestedNameSpecifier::TypeSpec:
- // Unresolved inside a template.
- case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ case NestedNameSpecifier::Kind::Type:
return false;
}
llvm_unreachable("invalid NestedNameSpecifier kind");
diff --git a/clang-tools-extra/clangd/DumpAST.cpp b/clang-tools-extra/clangd/DumpAST.cpp
index 14e14a5e9f544..9a8d41d870929 100644
--- a/clang-tools-extra/clangd/DumpAST.cpp
+++ b/clang-tools-extra/clangd/DumpAST.cpp
@@ -147,17 +147,17 @@ class DumpVisitor : public RecursiveASTVisitor<DumpVisitor> {
}
llvm_unreachable("Unhandled ArgKind enum");
}
- std::string getKind(const NestedNameSpecifierLoc &NNSL) {
- assert(NNSL.getNestedNameSpecifier());
- switch (NNSL.getNestedNameSpecifier()->getKind()) {
+ std::string getKind(NestedNameSpecifierLoc NNSL) {
+ switch (NNSL.getNestedNameSpecifier().getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
#define NNS_KIND(X) \
- case NestedNameSpecifier::X: \
+ case NestedNameSpecifier::Kind::X: \
return #X
- NNS_KIND(Identifier);
NNS_KIND(Namespace);
- NNS_KIND(TypeSpec);
+ NNS_KIND(Type);
NNS_KIND(Global);
- NNS_KIND(Super);
+ NNS_KIND(MicrosoftSuper);
#undef NNS_KIND
}
llvm_unreachable("Unhandled SpecifierKind enum");
@@ -273,16 +273,11 @@ class DumpVisitor : public RecursiveASTVisitor<DumpVisitor> {
return getDetail(TT->getDecl());
return "";
}
- std::string getDetail(const NestedNameSpecifierLoc &NNSL) {
- const auto &NNS = *NNSL.getNestedNameSpecifier();
- switch (NNS.getKind()) {
- case NestedNameSpecifier::Identifier:
- return NNS.getAsIdentifier()->getName().str() + "::";
- case NestedNameSpecifier::Namespace:
- return NNS.getAsNamespace()->getNameAsString() + "::";
- default:
+ std::string getDetail(NestedNameSpecifierLoc NNSL) {
+ NestedNameSpecifier NNS = NNSL.getNestedNameSpecifier();
+ if (NNS.getKind() != NestedNameSpecifier::Kind::Namespace)
return "";
- }
+ return NNS.getAsNamespaceAndPrefix().Namespace->getNameAsString() + "::";
}
std::string getDetail(const CXXCtorInitializer *CCI) {
if (FieldDecl *FD = CCI->getAnyMember())
@@ -391,11 +386,11 @@ class DumpVisitor : public RecursiveASTVisitor<DumpVisitor> {
// This means we'd never see 'int' in 'const int'! Work around that here.
// (The reason for the behavior is to avoid traversing the nested Type twice,
// but we ignore TraverseType anyway).
- bool TraverseQualifiedTypeLoc(QualifiedTypeLoc QTL) {
+ bool TraverseQualifiedTypeLoc(QualifiedTypeLoc QTL, bool TraverseQualifier) {
return TraverseTypeLoc(QTL.getUnqualifiedLoc());
}
// Uninteresting parts of the AST that don't have locations within them.
- bool TraverseNestedNameSpecifier(NestedNameSpecifier *) { return true; }
+ bool TraverseNestedNameSpecifier(NestedNameSpecifier) { return true; }
bool TraverseType(QualType) { return true; }
// OpaqueValueExpr blocks traversal, we must explicitly traverse it.
@@ -422,7 +417,7 @@ ASTNode dumpAST(const DynTypedNode &N, const syntax::TokenBuffer &Tokens,
V.TraverseNestedNameSpecifierLoc(
*const_cast<NestedNameSpecifierLoc *>(NNSL));
else if (const auto *NNS = N.get<NestedNameSpecifier>())
- V.TraverseNestedNameSpecifier(const_cast<NestedNameSpecifier *>(NNS));
+ V.TraverseNestedNameSpecifier(*NNS);
else if (const auto *TL = N.get<TypeLoc>())
V.TraverseTypeLoc(*const_cast<TypeLoc *>(TL));
else if (const auto *QT = N.get<QualType>())
diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp
index a5ab40e4221f1..32018d1bf3a84 100644
--- a/clang-tools-extra/clangd/FindTarget.cpp
+++ b/clang-tools-extra/clangd/FindTarget.cpp
@@ -475,30 +475,27 @@ struct TargetFinder {
Visitor(*this, Flags).Visit(T.getTypePtr());
}
- void add(const NestedNameSpecifier *NNS, RelSet Flags) {
+ void add(NestedNameSpecifier NNS, RelSet Flags) {
if (!NNS)
return;
- debug(*NNS, Flags);
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Namespace:
- add(NNS->getAsNamespace(), Flags);
+ debug(NNS, Flags);
+ switch (NNS.getKind()) {
+ case NestedNameSpecifier::Kind::Namespace:
+ add(NNS.getAsNamespaceAndPrefix().Namespace, Flags);
return;
- case NestedNameSpecifier::Identifier:
- if (Resolver) {
- add(Resolver->resolveNestedNameSpecifierToType(NNS), Flags);
- }
+ case NestedNameSpecifier::Kind::Type:
+ add(QualType(NNS.getAsType(), 0), Flags);
return;
- case NestedNameSpecifier::TypeSpec:
- add(QualType(NNS->getAsType(), 0), Flags);
- return;
- case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Kind::Global:
// This should be TUDecl, but we can't get a pointer to it!
return;
- case NestedNameSpecifier::Super:
- add(NNS->getAsRecordDecl(), Flags);
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ add(NNS.getAsMicrosoftSuper(), Flags);
return;
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
}
- llvm_unreachable("unhandled NestedNameSpecifier::SpecifierKind");
+ llvm_unreachable("unhandled NestedNameSpecifier::Kind");
}
void add(const CXXCtorInitializer *CCI, RelSet Flags) {
@@ -547,7 +544,7 @@ allTargetDecls(const DynTypedNode &N, const HeuristicResolver *Resolver) {
else if (const NestedNameSpecifierLoc *NNSL = N.get<NestedNameSpecifierLoc>())
Finder.add(NNSL->getNestedNameSpecifier(), Flags);
else if (const NestedNameSpecifier *NNS = N.get<NestedNameSpecifier>())
- Finder.add(NNS, Flags);
+ Finder.add(*NNS, Flags);
else if (const TypeLoc *TL = N.get<TypeLoc>())
Finder.add(TL->getType(), Flags);
else if (const QualType *QT = N.get<QualType>())
@@ -853,29 +850,22 @@ refInTypeLoc(TypeLoc L, const HeuristicResolver *Resolver) {
const HeuristicResolver *Resolver;
llvm::SmallVector<ReferenceLoc> Refs;
- void VisitElaboratedTypeLoc(ElaboratedTypeLoc L) {
- // We only know about qualifier, rest if filled by inner locations.
- size_t InitialSize = Refs.size();
- Visit(L.getNamedTypeLoc().getUnqualifiedLoc());
- size_t NewSize = Refs.size();
- // Add qualifier for the newly-added refs.
- for (unsigned I = InitialSize; I < NewSize; ++I) {
- ReferenceLoc *Ref = &Refs[I];
- // Fill in the qualifier.
- assert(!Ref->Qualifier.hasQualifier() && "qualifier already set");
- Ref->Qualifier = L.getQualifierLoc();
- }
+ void VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc L) {
+ Refs.push_back(ReferenceLoc{L.getQualifierLoc(),
+ L.getLocalSourceRange().getBegin(),
+ /*IsDecl=*/false,
+ {L.getDecl()}});
}
void VisitUsingTypeLoc(UsingTypeLoc L) {
- Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+ Refs.push_back(ReferenceLoc{L.getQualifierLoc(),
L.getLocalSourceRange().getBegin(),
/*IsDecl=*/false,
- {L.getFoundDecl()}});
+ {L.getDecl()}});
}
void VisitTagTypeLoc(TagTypeLoc L) {
- Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+ Refs.push_back(ReferenceLoc{L.getQualifierLoc(),
L.getNameLoc(),
/*IsDecl=*/false,
{L.getOriginalDecl()}});
@@ -898,14 +888,14 @@ refInTypeLoc(TypeLoc L, const HeuristicResolver *Resolver) {
// 2. 'vector<int>' with mask 'Underlying'.
// we want to return only #1 in this case.
Refs.push_back(ReferenceLoc{
- NestedNameSpecifierLoc(), L.getTemplateNameLoc(), /*IsDecl=*/false,
+ L.getQualifierLoc(), L.getTemplateNameLoc(), /*IsDecl=*/false,
explicitReferenceTargets(DynTypedNode::create(L.getType()),
DeclRelation::Alias, Resolver)});
}
void VisitDeducedTemplateSpecializationTypeLoc(
DeducedTemplateSpecializationTypeLoc L) {
Refs.push_back(ReferenceLoc{
- NestedNameSpecifierLoc(), L.getNameLoc(), /*IsDecl=*/false,
+ L.getQualifierLoc(), L.getNameLoc(), /*IsDecl=*/false,
explicitReferenceTargets(DynTypedNode::create(L.getType()),
DeclRelation::Alias, Resolver)});
}
@@ -1025,7 +1015,7 @@ class ExplicitReferenceCollector
return true;
visitNode(DynTypedNode::create(L));
// Inner type is missing information about its qualifier, skip it.
- if (auto TL = L.getTypeLoc())
+ if (auto TL = L.getAsTypeLoc())
TypeLocsToSkip.insert(TL.getBeginLoc());
return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(L);
}
@@ -1066,12 +1056,21 @@ class ExplicitReferenceCollector
if (auto *S = N.get<Stmt>())
return refInStmt(S, Resolver);
if (auto *NNSL = N.get<NestedNameSpecifierLoc>()) {
- // (!) 'DeclRelation::Alias' ensures we do not loose namespace aliases.
- return {ReferenceLoc{
- NNSL->getPrefix(), NNSL->getLocalBeginLoc(), false,
- explicitReferenceTargets(
- DynTypedNode::create(*NNSL->getNestedNameSpecifier()),
- DeclRelation::Alias, Resolver)}};
+ // (!) 'DeclRelation::Alias' ensures we do not lose namespace aliases.
+ NestedNameSpecifierLoc Qualifier;
+ SourceLocation NameLoc;
+ if (auto TL = NNSL->getAsTypeLoc()) {
+ Qualifier = TL.getPrefix();
+ NameLoc = TL.getNonPrefixBeginLoc();
+ } else {
+ Qualifier = NNSL->getAsNamespaceAndPrefix().Prefix;
+ NameLoc = NNSL->getLocalBeginLoc();
+ }
+ return {
+ ReferenceLoc{Qualifier, NameLoc, false,
+ explicitReferenceTargets(
+ DynTypedNode::create(NNSL->getNestedNameSpecifier()),
+ DeclRelation::Alias, Resolver)}};
}
if (const TypeLoc *TL = N.get<TypeLoc>())
return refInTypeLoc(*TL, Resolver);
@@ -1184,8 +1183,8 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ReferenceLoc R) {
OS << "}";
if (R.Qualifier) {
OS << ", qualifier = '";
- R.Qualifier.getNestedNameSpecifier()->print(OS,
- PrintingPolicy(LangOptions()));
+ R.Qualifier.getNestedNameSpecifier().print(OS,
+ PrintingPolicy(LangOptions()));
OS << "'";
}
if (R.IsDecl)
diff --git a/clang-tools-extra/clangd/IncludeFixer.cpp b/clang-tools-extra/clangd/IncludeFixer.cpp
index cc1125e705674..c27d960cd963b 100644
--- a/clang-tools-extra/clangd/IncludeFixer.cpp
+++ b/clang-tools-extra/clangd/IncludeFixer.cpp
@@ -400,35 +400,35 @@ std::optional<CheapUnresolvedName> extractUnresolvedNameCheaply(
CheapUnresolvedName Result;
Result.Name = Unresolved.getAsString();
if (SS && SS->isNotEmpty()) { // "::" or "ns::"
- if (auto *Nested = SS->getScopeRep()) {
- if (Nested->getKind() == NestedNameSpecifier::Global) {
- Result.ResolvedScope = "";
- } else if (const NamespaceBaseDecl *NSB = Nested->getAsNamespace()) {
- if (const auto *NS = dyn_cast<NamespaceDecl>(NSB)) {
- std::string SpecifiedNS = printNamespaceScope(*NS);
- std::optional<std::string> Spelling = getSpelledSpecifier(*SS, SM);
-
- // Check the specifier spelled in the source.
- // If the resolved scope doesn't end with the spelled scope, the
- // resolved scope may come from a sema typo correction. For example,
- // sema assumes that "clangd::" is a typo of "clang::" and uses
- // "clang::" as the specified scope in:
- // namespace clang { clangd::X; }
- // In this case, we use the "typo" specifier as extra scope instead
- // of using the scope assumed by sema.
- if (!Spelling || llvm::StringRef(SpecifiedNS).ends_with(*Spelling)) {
- Result.ResolvedScope = std::move(SpecifiedNS);
- } else {
- Result.UnresolvedScope = std::move(*Spelling);
- }
+ NestedNameSpecifier Nested = SS->getScopeRep();
+ if (Nested.getKind() == NestedNameSpecifier::Kind::Global) {
+ Result.ResolvedScope = "";
+ } else if (Nested.getKind() == NestedNameSpecifier::Kind::Namespace) {
+ const NamespaceBaseDecl *NSB = Nested.getAsNamespaceAndPrefix().Namespace;
+ if (const auto *NS = dyn_cast<NamespaceDecl>(NSB)) {
+ std::string SpecifiedNS = printNamespaceScope(*NS);
+ std::optional<std::string> Spelling = getSpelledSpecifier(*SS, SM);
+
+ // Check the specifier spelled in the source.
+ // If the resolved scope doesn't end with the spelled scope, the
+ // resolved scope may come from a sema typo correction. For example,
+ // sema assumes that "clangd::" is a typo of "clang::" and uses
+ // "clang::" as the specified scope in:
+ // namespace clang { clangd::X; }
+ // In this case, we use the "typo" specifier as extra scope instead
+ // of using the scope assumed by sema.
+ if (!Spelling || llvm::StringRef(SpecifiedNS).ends_with(*Spelling)) {
+ Result.ResolvedScope = std::move(SpecifiedNS);
} else {
- Result.ResolvedScope = printNamespaceScope(*cast<NamespaceAliasDecl>(NSB)->getNamespace());
+ Result.UnresolvedScope = std::move(*Spelling);
}
} else {
- // We don't fix symbols in scopes that are not top-level e.g. class
- // members, as we don't collect includes for them.
- return std::nullopt;
+ Result.ResolvedScope = printNamespaceScope(*cast<NamespaceAliasDecl>(NSB)->getNamespace());
}
+ } else {
+ // We don't fix symbols in scopes that are not top-level e.g. class
+ // members, as we don't collect includes for them.
+ return std::nullopt;
}
}
diff --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp
index a6e15fcee6bd2..06165dfbbcdd2 100644
--- a/clang-tools-extra/clangd/Selection.cpp
+++ b/clang-tools-extra/clangd/Selection.cpp
@@ -701,7 +701,7 @@ class SelectionVisitor : public RecursiveASTVisitor<SelectionVisitor> {
return traverseNode(&PL, [&] { return Base::TraverseObjCProtocolLoc(PL); });
}
// Uninteresting parts of the AST that don't have locations within them.
- bool TraverseNestedNameSpecifier(NestedNameSpecifier *) { return true; }
+ bool TraverseNestedNameSpecifier(NestedNameSpecifier) { return true; }
bool TraverseType(QualType) { return true; }
// The DeclStmt for the loop variable claims to cover the whole range
diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp
index e6d5cf7053694..2b151b1274428 100644
--- a/clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -1127,21 +1127,6 @@ class CollectExtraHighlightings
return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
}
- // findExplicitReferences will walk nested-name-specifiers and
- // find anything that can be resolved to a Decl. However, non-leaf
- // components of nested-name-specifiers which are dependent names
- // (kind "Identifier") cannot be resolved to a decl, so we visit
- // them here.
- bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc Q) {
- if (NestedNameSpecifier *NNS = Q.getNestedNameSpecifier()) {
- if (NNS->getKind() == NestedNameSpecifier::Identifier)
- H.addToken(Q.getLocalBeginLoc(), HighlightingKind::Type)
- .addModifier(HighlightingModifier::DependentName)
- .addModifier(HighlightingModifier::ClassScope);
- }
- return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(Q);
- }
-
private:
HighlightingsBuilder &H;
};
diff --git a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
index 67fc451a6a1a1..f65c74fdbc9ee 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
@@ -115,13 +115,6 @@ class UsingFinder : public RecursiveASTVisitor<UsingFinder> {
const SourceManager &SM;
};
-bool isFullyQualified(const NestedNameSpecifier *NNS) {
- if (!NNS)
- return false;
- return NNS->getKind() == NestedNameSpecifier::Global ||
- isFullyQualified(NNS->getPrefix());
-}
-
struct InsertionPointData {
// Location to insert the "using" statement. If invalid then the statement
// should not be inserted at all (it already exists).
@@ -167,18 +160,20 @@ findInsertionPoint(const Tweak::Selection &Inputs,
for (auto &U : Usings) {
// Only "upgrade" to fully qualified is all relevant using decls are fully
// qualified. Otherwise trust what the user typed.
- if (!isFullyQualified(U->getQualifier()))
+ if (!U->getQualifier().isFullyQualified())
AlwaysFullyQualify = false;
if (SM.isBeforeInTranslationUnit(Inputs.Cursor, U->getUsingLoc()))
// "Usings" is sorted, so we're done.
break;
- if (const auto *Namespace = dyn_cast_if_present<NamespaceDecl>(
- U->getQualifier()->getAsNamespace())) {
+ if (NestedNameSpecifier Qualifier = U->getQualifier();
+ Qualifier.getKind() == NestedNameSpecifier::Kind::Namespace) {
+ const auto *Namespace =
+ U->getQualifier().getAsNamespaceAndPrefix().Namespace;
if (Namespace->getCanonicalDecl() ==
QualifierToRemove.getNestedNameSpecifier()
- ->getAsNamespace()
- ->getCanonicalDecl() &&
+ .getAsNamespaceAndPrefix()
+ .Namespace->getCanonicalDecl() &&
U->getName() == Name) {
return InsertionPointData();
}
@@ -232,8 +227,9 @@ findInsertionPoint(const Tweak::Selection &Inputs,
}
bool isNamespaceForbidden(const Tweak::Selection &Inputs,
- const NestedNameSpecifier &Namespace) {
- const auto *NS = dyn_cast<NamespaceDecl>(Namespace.getAsNamespace());
+ NestedNameSpecifier Namespace) {
+ const auto *NS =
+ dyn_cast<NamespaceDecl>(Namespace.getAsNamespaceAndPrefix().Namespace);
if (!NS)
return true;
std::string NamespaceStr = printNamespaceScope(*NS);
@@ -247,11 +243,11 @@ bool isNamespaceForbidden(const Tweak::Selection &Inputs,
return false;
}
-std::string getNNSLAsString(NestedNameSpecifierLoc &NNSL,
+std::string getNNSLAsString(NestedNameSpecifierLoc NNSL,
const PrintingPolicy &Policy) {
std::string Out;
llvm::raw_string_ostream OutStream(Out);
- NNSL.getNestedNameSpecifier()->print(OutStream, Policy);
+ NNSL.getNestedNameSpecifier().print(OutStream, Policy);
return OutStream.str();
}
@@ -276,16 +272,15 @@ bool AddUsing::prepare(const Selection &Inputs) {
continue;
}
if (auto *T = Node->ASTNode.get<TypeLoc>()) {
- if (T->getAs<ElaboratedTypeLoc>()) {
+ // Find the outermost TypeLoc.
+ if (Node->Parent->ASTNode.get<NestedNameSpecifierLoc>())
+ continue;
+ if (isa<TagType, TemplateSpecializationType, TypedefType, UsingType,
+ UnresolvedUsingType>(T->getTypePtr()))
break;
- }
- if (Node->Parent->ASTNode.get<TypeLoc>() ||
- Node->Parent->ASTNode.get<NestedNameSpecifierLoc>()) {
- // Node is TypeLoc, but it's parent is either TypeLoc or
- // NestedNameSpecifier. In both cases, we want to go up, to find
- // the outermost TypeLoc.
+ // Find the outermost TypeLoc.
+ if (Node->Parent->ASTNode.get<TypeLoc>())
continue;
- }
}
break;
}
@@ -307,32 +302,70 @@ bool AddUsing::prepare(const Selection &Inputs) {
MustInsertAfterLoc = D->getDecl()->getBeginLoc();
}
} else if (auto *T = Node->ASTNode.get<TypeLoc>()) {
- if (auto E = T->getAs<ElaboratedTypeLoc>()) {
- QualifierToRemove = E.getQualifierLoc();
-
- SpelledNameRange = E.getSourceRange();
- if (auto T = E.getNamedTypeLoc().getAs<TemplateSpecializationTypeLoc>()) {
- // Remove the template arguments from the name.
- SpelledNameRange.setEnd(T.getLAngleLoc().getLocWithOffset(-1));
- }
-
- if (const auto *ET = E.getTypePtr()) {
- if (const auto *TDT =
- dyn_cast<TypedefType>(ET->getNamedType().getTypePtr())) {
- MustInsertAfterLoc = TDT->getDecl()->getBeginLoc();
- } else if (auto *TD = ET->getAsTagDecl()) {
- MustInsertAfterLoc = TD->getBeginLoc();
- }
- }
+ switch (T->getTypeLocClass()) {
+ case TypeLoc::TemplateSpecialization: {
+ auto TL = T->castAs<TemplateSpecializationTypeLoc>();
+ QualifierToRemove = TL.getQualifierLoc();
+ if (!QualifierToRemove)
+ break;
+ SpelledNameRange = TL.getTemplateNameLoc();
+ if (auto *TD = TL.getTypePtr()->getTemplateName().getAsTemplateDecl(
+ /*IgnoreDeduced=*/true))
+ MustInsertAfterLoc = TD->getBeginLoc();
+ break;
+ }
+ case TypeLoc::Enum:
+ case TypeLoc::Record:
+ case TypeLoc::InjectedClassName: {
+ auto TL = T->castAs<TagTypeLoc>();
+ QualifierToRemove = TL.getQualifierLoc();
+ if (!QualifierToRemove)
+ break;
+ SpelledNameRange = TL.getNameLoc();
+ MustInsertAfterLoc = TL.getOriginalDecl()->getBeginLoc();
+ break;
+ }
+ case TypeLoc::Typedef: {
+ auto TL = T->castAs<TypedefTypeLoc>();
+ QualifierToRemove = TL.getQualifierLoc();
+ if (!QualifierToRemove)
+ break;
+ SpelledNameRange = TL.getNameLoc();
+ MustInsertAfterLoc = TL.getDecl()->getBeginLoc();
+ break;
+ }
+ case TypeLoc::UnresolvedUsing: {
+ auto TL = T->castAs<UnresolvedUsingTypeLoc>();
+ QualifierToRemove = TL.getQualifierLoc();
+ if (!QualifierToRemove)
+ break;
+ SpelledNameRange = TL.getNameLoc();
+ MustInsertAfterLoc = TL.getDecl()->getBeginLoc();
+ break;
+ }
+ case TypeLoc::Using: {
+ auto TL = T->castAs<UsingTypeLoc>();
+ QualifierToRemove = TL.getQualifierLoc();
+ if (!QualifierToRemove)
+ break;
+ SpelledNameRange = TL.getNameLoc();
+ MustInsertAfterLoc = TL.getDecl()->getBeginLoc();
+ break;
+ }
+ default:
+ break;
}
+ if (QualifierToRemove)
+ SpelledNameRange.setBegin(QualifierToRemove.getBeginLoc());
}
if (!QualifierToRemove ||
// FIXME: This only supports removing qualifiers that are made up of just
// namespace names. If qualifier contains a type, we could take the
// longest namespace prefix and remove that.
- !QualifierToRemove.getNestedNameSpecifier()->getAsNamespace() ||
+ QualifierToRemove.getNestedNameSpecifier().getKind() !=
+ NestedNameSpecifier::Kind::Namespace ||
// Respect user config.
- isNamespaceForbidden(Inputs, *QualifierToRemove.getNestedNameSpecifier()))
+ isNamespaceForbidden(Inputs, QualifierToRemove.getNestedNameSpecifier()))
return false;
// Macros are difficult. We only want to offer code action when what's spelled
// under the cursor is a namespace qualifier. If it's a macro that expands to
@@ -384,7 +417,7 @@ Expected<Tweak::Effect> AddUsing::apply(const Selection &Inputs) {
llvm::raw_string_ostream UsingTextStream(UsingText);
UsingTextStream << "using ";
if (InsertionPoint->AlwaysFullyQualify &&
- !isFullyQualified(QualifierToRemove.getNestedNameSpecifier()))
+ !QualifierToRemove.getNestedNameSpecifier().isFullyQualified())
UsingTextStream << "::";
UsingTextStream << QualifierToSpell << SpelledName << ";"
<< InsertionPoint->Suffix;
diff --git a/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp b/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
index 3f900ab2aae86..134ae89288300 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
@@ -362,7 +362,7 @@ struct NewFunction {
SourceLocation DefinitionPoint;
std::optional<SourceLocation> ForwardDeclarationPoint;
const CXXRecordDecl *EnclosingClass = nullptr;
- const NestedNameSpecifier *DefinitionQualifier = nullptr;
+ NestedNameSpecifier DefinitionQualifier = std::nullopt;
const DeclContext *SemanticDC = nullptr;
const DeclContext *SyntacticDC = nullptr;
const DeclContext *ForwardDeclarationSyntacticDC = nullptr;
diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index 4d77f9d690ca0..20fd23ed4fcdc 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -992,7 +992,7 @@ TEST_F(TargetDeclTest, DependentTypes) {
)cpp";
EXPECT_DECLS("DependentNameTypeLoc", "struct B");
- // Heuristic resolution of dependent type name which doesn't get a TypeLoc
+ // Heuristic resolution of dependent type name within a NestedNameSpecifierLoc
Code = R"cpp(
template <typename>
struct A { struct B { struct C {}; }; };
@@ -1000,7 +1000,7 @@ TEST_F(TargetDeclTest, DependentTypes) {
template <typename T>
void foo(typename A<T>::[[B]]::C);
)cpp";
- EXPECT_DECLS("NestedNameSpecifierLoc", "struct B");
+ EXPECT_DECLS("DependentNameTypeLoc", "struct B");
// Heuristic resolution of dependent type name whose qualifier is also
// dependent
diff --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp
index aaaf758e72236..3df19d8fc174d 100644
--- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp
@@ -104,9 +104,9 @@ TEST(SelectionTest, CommonAncestor) {
{
R"cpp(
template <typename T>
- int x = [[T::^U::]]ccc();
+ int x = T::[[^U]]::ccc();
)cpp",
- "NestedNameSpecifierLoc",
+ "DependentNameTypeLoc",
},
{
R"cpp(
diff --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
index ff64b0b257572..0cbf9a080a3ce 100644
--- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
+++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
@@ -131,16 +131,14 @@ class ASTWalker : public RecursiveASTVisitor<ASTWalker> {
}
bool qualifierIsNamespaceOrNone(DeclRefExpr *DRE) {
- const auto *Qual = DRE->getQualifier();
- if (!Qual)
+ NestedNameSpecifier Qual = DRE->getQualifier();
+ switch (Qual.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Namespace:
+ case NestedNameSpecifier::Kind::Global:
return true;
- switch (Qual->getKind()) {
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::Global:
- return true;
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::Super:
- case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Kind::Type:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
return false;
}
llvm_unreachable("Unknown value for NestedNameSpecifierKind");
diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h
index c8f6330a73bb1..6ab82824458ab 100644
--- a/clang/include/clang/AST/ASTConcept.h
+++ b/clang/include/clang/AST/ASTConcept.h
@@ -15,7 +15,7 @@
#define LLVM_CLANG_AST_ASTCONCEPT_H
#include "clang/AST/DeclarationName.h"
-#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/NestedNameSpecifierBase.h"
#include "clang/AST/TemplateBase.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/UnsignedOrNone.h"
@@ -175,12 +175,7 @@ class ConceptReference {
SourceLocation getLocation() const { return getConceptNameLoc(); }
- SourceLocation getBeginLoc() const LLVM_READONLY {
- // Note that if the qualifier is null the template KW must also be null.
- if (auto QualifierLoc = getNestedNameSpecifierLoc())
- return QualifierLoc.getBeginLoc();
- return getConceptNameInfo().getBeginLoc();
- }
+ SourceLocation getBeginLoc() const LLVM_READONLY;
SourceLocation getEndLoc() const LLVM_READONLY {
return getTemplateArgsAsWritten() &&
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index e200cd17007bf..38d934e14da2b 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -283,11 +283,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
llvm::to_underlying(PredefinedSugarType::Kind::Last) + 1>
PredefinedSugarTypes{};
- /// The set of nested name specifiers.
+ /// Internal storage for NestedNameSpecifiers.
///
/// This set is managed by the NestedNameSpecifier class.
- mutable llvm::FoldingSet<NestedNameSpecifier> NestedNameSpecifiers;
- mutable NestedNameSpecifier *GlobalNestedNameSpecifier = nullptr;
+ mutable llvm::FoldingSet<NamespaceAndPrefixStorage>
+ NamespaceAndPrefixStorages;
/// A cache mapping from RecordDecls to ASTRecordLayouts.
///
@@ -1620,7 +1620,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// Return the uniqued reference to the type for a member pointer to
/// the specified type in the specified nested name.
- QualType getMemberPointerType(QualType T, NestedNameSpecifier *Qualifier,
+ QualType getMemberPointerType(QualType T, NestedNameSpecifier Qualifier,
const CXXRecordDecl *Cls) const;
/// Return a non-unique reference to the type for a variable array of
@@ -1919,7 +1919,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
const IdentifierInfo *MacroII) const;
QualType getDependentNameType(ElaboratedTypeKeyword Keyword,
- NestedNameSpecifier *NNS,
+ NestedNameSpecifier NNS,
const IdentifierInfo *Name) const;
QualType getDependentTemplateSpecializationType(
@@ -2484,7 +2484,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
UnresolvedSetIterator End) const;
TemplateName getAssumedTemplateName(DeclarationName Name) const;
- TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
+ TemplateName getQualifiedTemplateName(NestedNameSpecifier Qualifier,
bool TemplateKeyword,
TemplateName Template) const;
TemplateName
@@ -2926,32 +2926,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// Determine if two types are similar, ignoring only CVR qualifiers.
bool hasCvrSimilarType(QualType T1, QualType T2);
- /// Retrieves the "canonical" nested name specifier for a
- /// given nested name specifier.
- ///
- /// The canonical nested name specifier is a nested name specifier
- /// that uniquely identifies a type or namespace within the type
- /// system. For example, given:
- ///
- /// \code
- /// namespace N {
- /// struct S {
- /// template<typename T> struct X { typename T* type; };
- /// };
- /// }
- ///
- /// template<typename T> struct Y {
- /// typename N::S::X<T>::type member;
- /// };
- /// \endcode
- ///
- /// Here, the nested-name-specifier for N::S::X<T>:: will be
- /// S::X<template-param-0-0>, since 'S' and 'X' are uniquely defined
- /// by declarations in the type system and the canonical type for
- /// the template type parameter 'T' is template-param-0-0.
- NestedNameSpecifier *
- getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const;
-
/// Retrieves the default calling convention for the current context.
///
/// The context's default calling convention may differ from the current
diff --git a/clang/include/clang/AST/ASTImporter.h b/clang/include/clang/AST/ASTImporter.h
index c40b92666a2ff..4a0ca45b785a9 100644
--- a/clang/include/clang/AST/ASTImporter.h
+++ b/clang/include/clang/AST/ASTImporter.h
@@ -404,7 +404,7 @@ class TypeSourceInfo;
///
/// \returns The equivalent nested-name-specifier in the "to"
/// context, or the import error.
- llvm::Expected<NestedNameSpecifier *> Import(NestedNameSpecifier *FromNNS);
+ llvm::Expected<NestedNameSpecifier> Import(NestedNameSpecifier FromNNS);
/// Import the given nested-name-specifier-loc from the "from"
/// context into the "to" context.
diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h
index 1d846a1f9df35..d9dc8290b0e49 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -394,12 +394,14 @@ class ASTNodeTraverser
}
void VisitMemberPointerType(const MemberPointerType *T) {
// FIXME: Provide a NestedNameSpecifier visitor.
- NestedNameSpecifier *Qualifier = T->getQualifier();
- if (NestedNameSpecifier::SpecifierKind K = Qualifier->getKind();
- K == NestedNameSpecifier::TypeSpec)
- Visit(Qualifier->getAsType());
+ NestedNameSpecifier Qualifier = T->getQualifier();
+ if (NestedNameSpecifier::Kind K = Qualifier.getKind();
+ K == NestedNameSpecifier::Kind::Type)
+ Visit(Qualifier.getAsType());
if (T->isSugared())
- Visit(T->getMostRecentCXXRecordDecl()->getTypeForDecl());
+ Visit(cast<MemberPointerType>(T->getCanonicalTypeUnqualified())
+ ->getQualifier()
+ .getAsType());
Visit(T->getPointeeType());
}
void VisitArrayType(const ArrayType *T) { Visit(T->getElementType()); }
diff --git a/clang/include/clang/AST/ASTTypeTraits.h b/clang/include/clang/AST/ASTTypeTraits.h
index d63cbf405fba1..6f40705fb7436 100644
--- a/clang/include/clang/AST/ASTTypeTraits.h
+++ b/clang/include/clang/AST/ASTTypeTraits.h
@@ -336,9 +336,9 @@ class DynTypedNode {
NodeKind)) {
auto NNSLA = getUnchecked<NestedNameSpecifierLoc>();
auto NNSLB = Other.getUnchecked<NestedNameSpecifierLoc>();
- return std::make_pair(NNSLA.getNestedNameSpecifier(),
+ return std::make_pair(NNSLA.getNestedNameSpecifier().getAsVoidPointer(),
NNSLA.getOpaqueData()) <
- std::make_pair(NNSLB.getNestedNameSpecifier(),
+ std::make_pair(NNSLB.getNestedNameSpecifier().getAsVoidPointer(),
NNSLB.getOpaqueData());
}
@@ -393,8 +393,9 @@ class DynTypedNode {
if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(
Val.NodeKind)) {
auto NNSL = Val.getUnchecked<NestedNameSpecifierLoc>();
- return llvm::hash_combine(NNSL.getNestedNameSpecifier(),
- NNSL.getOpaqueData());
+ return llvm::hash_combine(
+ NNSL.getNestedNameSpecifier().getAsVoidPointer(),
+ NNSL.getOpaqueData());
}
assert(Val.getMemoizationData());
@@ -539,8 +540,8 @@ struct DynTypedNode::BaseConverter<
: public DynCastPtrConverter<T, Attr> {};
template <>
-struct DynTypedNode::BaseConverter<
- NestedNameSpecifier, void> : public PtrConverter<NestedNameSpecifier> {};
+struct DynTypedNode::BaseConverter<NestedNameSpecifier, void>
+ : public ValueConverter<NestedNameSpecifier> {};
template <>
struct DynTypedNode::BaseConverter<
diff --git a/clang/include/clang/AST/AbstractBasicReader.h b/clang/include/clang/AST/AbstractBasicReader.h
index 8f5fdc9d93c78..26052b8086cf7 100644
--- a/clang/include/clang/AST/AbstractBasicReader.h
+++ b/clang/include/clang/AST/AbstractBasicReader.h
@@ -252,39 +252,34 @@ class DataStreamBasicReader : public BasicReaderBase<Impl> {
return EffectConditionExpr{asImpl().readExprRef()};
}
- NestedNameSpecifier *readNestedNameSpecifier() {
+ NestedNameSpecifier readNestedNameSpecifier() {
auto &ctx = getASTContext();
// We build this up iteratively.
- NestedNameSpecifier *cur = nullptr;
+ NestedNameSpecifier cur = std::nullopt;
uint32_t depth = asImpl().readUInt32();
for (uint32_t i = 0; i != depth; ++i) {
auto kind = asImpl().readNestedNameSpecifierKind();
switch (kind) {
- case NestedNameSpecifier::Identifier:
- cur = NestedNameSpecifier::Create(ctx, cur,
- asImpl().readIdentifier());
+ case NestedNameSpecifier::Kind::Namespace:
+ cur =
+ NestedNameSpecifier(ctx, asImpl().readNamespaceBaseDeclRef(), cur);
continue;
-
- case NestedNameSpecifier::Namespace:
- cur = NestedNameSpecifier::Create(ctx, cur,
- asImpl().readNamespaceBaseDeclRef());
+ case NestedNameSpecifier::Kind::Type:
+ assert(!cur);
+ cur = NestedNameSpecifier(asImpl().readQualType().getTypePtr());
continue;
-
- case NestedNameSpecifier::TypeSpec:
- cur = NestedNameSpecifier::Create(ctx, cur,
- asImpl().readQualType().getTypePtr());
+ case NestedNameSpecifier::Kind::Global:
+ assert(!cur);
+ cur = NestedNameSpecifier::getGlobal();
continue;
-
- case NestedNameSpecifier::Global:
- cur = NestedNameSpecifier::GlobalSpecifier(ctx);
- continue;
-
- case NestedNameSpecifier::Super:
- cur = NestedNameSpecifier::SuperSpecifier(ctx,
- asImpl().readCXXRecordDeclRef());
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ assert(!cur);
+ cur = NestedNameSpecifier(asImpl().readCXXRecordDeclRef());
continue;
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
}
llvm_unreachable("bad nested name specifier kind");
}
diff --git a/clang/include/clang/AST/AbstractBasicWriter.h b/clang/include/clang/AST/AbstractBasicWriter.h
index fbbaba5f7327b..d41e655986ef9 100644
--- a/clang/include/clang/AST/AbstractBasicWriter.h
+++ b/clang/include/clang/AST/AbstractBasicWriter.h
@@ -229,42 +229,43 @@ class DataStreamBasicWriter : public BasicWriterBase<Impl> {
asImpl().writeExprRef(CE.getCondition());
}
- void writeNestedNameSpecifier(NestedNameSpecifier *NNS) {
+ void writeNestedNameSpecifier(NestedNameSpecifier NNS) {
// Nested name specifiers usually aren't too long. I think that 8 would
// typically accommodate the vast majority.
- SmallVector<NestedNameSpecifier *, 8> nestedNames;
+ SmallVector<NestedNameSpecifier, 8> nestedNames;
// Push each of the NNS's onto a stack for serialization in reverse order.
while (NNS) {
nestedNames.push_back(NNS);
- NNS = NNS->getPrefix();
+ NNS = NNS.getKind() == NestedNameSpecifier::Kind::Namespace
+ ? NNS.getAsNamespaceAndPrefix().Prefix
+ : std::nullopt;
}
asImpl().writeUInt32(nestedNames.size());
while (!nestedNames.empty()) {
NNS = nestedNames.pop_back_val();
- NestedNameSpecifier::SpecifierKind kind = NNS->getKind();
+ NestedNameSpecifier::Kind kind = NNS.getKind();
asImpl().writeNestedNameSpecifierKind(kind);
switch (kind) {
- case NestedNameSpecifier::Identifier:
- asImpl().writeIdentifier(NNS->getAsIdentifier());
+ case NestedNameSpecifier::Kind::Namespace:
+ asImpl().writeNamespaceBaseDeclRef(
+ NNS.getAsNamespaceAndPrefix().Namespace);
continue;
-
- case NestedNameSpecifier::Namespace:
- asImpl().writeNamespaceBaseDeclRef(NNS->getAsNamespace());
- continue;
-
- case NestedNameSpecifier::TypeSpec:
- asImpl().writeQualType(QualType(NNS->getAsType(), 0));
+ case NestedNameSpecifier::Kind::Type:
+ asImpl().writeQualType(QualType(NNS.getAsType(), 0));
continue;
- case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Kind::Global:
// Don't need to write an associated value.
continue;
- case NestedNameSpecifier::Super:
- asImpl().writeDeclRef(NNS->getAsRecordDecl());
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ asImpl().writeDeclRef(NNS.getAsMicrosoftSuper());
continue;
+
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
}
llvm_unreachable("bad nested name specifier kind");
}
diff --git a/clang/include/clang/AST/CanonicalType.h b/clang/include/clang/AST/CanonicalType.h
index 10dab7fbdfa77..b5a4e94e1330a 100644
--- a/clang/include/clang/AST/CanonicalType.h
+++ b/clang/include/clang/AST/CanonicalType.h
@@ -453,7 +453,7 @@ template<>
struct CanProxyAdaptor<MemberPointerType>
: public CanProxyBase<MemberPointerType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
- LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(NestedNameSpecifier *, getQualifier)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(NestedNameSpecifier, getQualifier)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const CXXRecordDecl *,
getMostRecentCXXRecordDecl)
};
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index bdff7030fc8c1..9b72b448431ee 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -20,7 +20,7 @@
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExternalASTSource.h"
-#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/NestedNameSpecifierBase.h"
#include "clang/AST/Redeclarable.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AddressSpaces.h"
@@ -833,9 +833,9 @@ class DeclaratorDecl : public ValueDecl {
/// Retrieve the nested-name-specifier that qualifies the name of this
/// declaration, if it was present in the source.
- NestedNameSpecifier *getQualifier() const {
+ NestedNameSpecifier getQualifier() const {
return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier()
- : nullptr;
+ : std::nullopt;
}
/// Retrieve the nested-name-specifier (with source-location
@@ -3942,9 +3942,9 @@ class TagDecl : public TypeDecl,
/// Retrieve the nested-name-specifier that qualifies the name of this
/// declaration, if it was present in the source.
- NestedNameSpecifier *getQualifier() const {
+ NestedNameSpecifier getQualifier() const {
return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier()
- : nullptr;
+ : std::nullopt;
}
/// Retrieve the nested-name-specifier (with source-location
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index d9b222067c41b..1d2ef0f4f2319 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -3136,7 +3136,7 @@ class UsingDirectiveDecl : public NamedDecl {
/// Retrieve the nested-name-specifier that qualifies the
/// name of the namespace.
- NestedNameSpecifier *getQualifier() const {
+ NestedNameSpecifier getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
@@ -3257,7 +3257,7 @@ class NamespaceAliasDecl : public NamespaceBaseDecl,
/// Retrieve the nested-name-specifier that qualifies the
/// name of the namespace.
- NestedNameSpecifier *getQualifier() const {
+ NestedNameSpecifier getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
@@ -3619,7 +3619,7 @@ class UsingDecl : public BaseUsingDecl, public Mergeable<UsingDecl> {
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
/// Retrieve the nested-name-specifier that qualifies the name.
- NestedNameSpecifier *getQualifier() const {
+ NestedNameSpecifier getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
@@ -3809,13 +3809,11 @@ class UsingEnumDecl : public BaseUsingDecl, public Mergeable<UsingEnumDecl> {
/// The source location of the 'enum' keyword.
SourceLocation getEnumLoc() const { return EnumLocation; }
void setEnumLoc(SourceLocation L) { EnumLocation = L; }
- NestedNameSpecifier *getQualifier() const {
+ NestedNameSpecifier getQualifier() const {
return getQualifierLoc().getNestedNameSpecifier();
}
NestedNameSpecifierLoc getQualifierLoc() const {
- if (auto ETL = EnumType->getTypeLoc().getAs<ElaboratedTypeLoc>())
- return ETL.getQualifierLoc();
- return NestedNameSpecifierLoc();
+ return getEnumTypeLoc().getPrefix();
}
// Returns the "qualifier::Name" part as a TypeLoc.
TypeLoc getEnumTypeLoc() const {
@@ -3975,7 +3973,7 @@ class UnresolvedUsingValueDecl : public ValueDecl,
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
/// Retrieve the nested-name-specifier that qualifies the name.
- NestedNameSpecifier *getQualifier() const {
+ NestedNameSpecifier getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
@@ -4065,7 +4063,7 @@ class UnresolvedUsingTypenameDecl
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
/// Retrieve the nested-name-specifier that qualifies the name.
- NestedNameSpecifier *getQualifier() const {
+ NestedNameSpecifier getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
diff --git a/clang/include/clang/AST/DependenceFlags.h b/clang/include/clang/AST/DependenceFlags.h
index bdcaabc143cc4..c4395259f0758 100644
--- a/clang/include/clang/AST/DependenceFlags.h
+++ b/clang/include/clang/AST/DependenceFlags.h
@@ -293,7 +293,7 @@ inline TypeDependence toSemanticDependence(TypeDependence D) {
}
inline NestedNameSpecifierDependence
-toNestedNameSpecifierDependendence(TypeDependence D) {
+toNestedNameSpecifierDependence(TypeDependence D) {
return Dependence(D).nestedNameSpecifier();
}
diff --git a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
index 0bcd67322c7f6..7b5bdca318348 100644
--- a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
+++ b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
@@ -134,8 +134,7 @@ template <bool IsConst> class DynamicRecursiveASTVisitorBase {
/// Recursively visit a C++ nested-name-specifier.
///
/// \returns false if the visitation was terminated early, true otherwise.
- virtual bool
- TraverseNestedNameSpecifier(MaybeConst<NestedNameSpecifier> *NNS);
+ virtual bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS);
/// Recursively visit a C++ nested-name-specifier with location
/// information.
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 523c0326d47ef..d973e2cb822bd 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -1366,7 +1366,7 @@ class DeclRefExpr final
/// If the name was qualified, retrieves the nested-name-specifier
/// that precedes the name. Otherwise, returns NULL.
- NestedNameSpecifier *getQualifier() const {
+ NestedNameSpecifier getQualifier() const {
return getQualifierLoc().getNestedNameSpecifier();
}
@@ -3393,7 +3393,7 @@ class MemberExpr final
/// If the member name was qualified, retrieves the
/// nested-name-specifier that precedes the member name. Otherwise, returns
/// NULL.
- NestedNameSpecifier *getQualifier() const {
+ NestedNameSpecifier getQualifier() const {
return getQualifierLoc().getNestedNameSpecifier();
}
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index a22c32241ac61..f8fa782f3fb68 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -2780,7 +2780,7 @@ class CXXPseudoDestructorExpr : public Expr {
/// If the member name was qualified, retrieves the
/// nested-name-specifier that precedes the member name. Otherwise, returns
/// null.
- NestedNameSpecifier *getQualifier() const {
+ NestedNameSpecifier getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
@@ -3221,7 +3221,7 @@ class OverloadExpr : public Expr {
SourceLocation getNameLoc() const { return NameInfo.getLoc(); }
/// Fetches the nested-name qualifier, if one was given.
- NestedNameSpecifier *getQualifier() const {
+ NestedNameSpecifier getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
@@ -3497,7 +3497,7 @@ class DependentScopeDeclRefExpr final
/// Retrieve the nested-name-specifier that qualifies this
/// declaration.
- NestedNameSpecifier *getQualifier() const {
+ NestedNameSpecifier getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
@@ -3912,7 +3912,7 @@ class CXXDependentScopeMemberExpr final
}
/// Retrieve the nested-name-specifier that qualifies the member name.
- NestedNameSpecifier *getQualifier() const {
+ NestedNameSpecifier getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
diff --git a/clang/include/clang/AST/NestedNameSpecifier.h b/clang/include/clang/AST/NestedNameSpecifier.h
index 3edf3955d0f8e..df20ebd91edf1 100644
--- a/clang/include/clang/AST/NestedNameSpecifier.h
+++ b/clang/include/clang/AST/NestedNameSpecifier.h
@@ -6,507 +6,266 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the NestedNameSpecifier class, which represents
-// a C++ nested-name-specifier.
+// This file completes the definition of the NestedNameSpecifier class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
#define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
-#include "clang/AST/DependenceFlags.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/SourceLocation.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/NestedNameSpecifierBase.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
#include "llvm/ADT/DenseMapInfo.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/PointerIntPair.h"
-#include "llvm/Support/Compiler.h"
-#include <cstdint>
-#include <cstdlib>
-#include <utility>
namespace clang {
-class ASTContext;
-class CXXRecordDecl;
-class IdentifierInfo;
-class LangOptions;
-class NamespaceBaseDecl;
-struct PrintingPolicy;
-class Type;
-class TypeLoc;
-
-/// Represents a C++ nested name specifier, such as
-/// "\::std::vector<int>::".
-///
-/// C++ nested name specifiers are the prefixes to qualified
-/// names. For example, "foo::" in "foo::x" is a nested name
-/// specifier. Nested name specifiers are made up of a sequence of
-/// specifiers, each of which can be a namespace, type, identifier
-/// (for dependent names), decltype specifier, or the global specifier ('::').
-/// The last two specifiers can only appear at the start of a
-/// nested-namespace-specifier.
-class NestedNameSpecifier : public llvm::FoldingSetNode {
- /// Enumeration describing
- enum StoredSpecifierKind {
- StoredIdentifier = 0,
- StoredDecl = 1,
- StoredTypeSpec = 2
- };
-
- /// The nested name specifier that precedes this nested name
- /// specifier.
- ///
- /// The pointer is the nested-name-specifier that precedes this
- /// one. The integer stores one of the first four values of type
- /// SpecifierKind.
- llvm::PointerIntPair<NestedNameSpecifier *, 2, StoredSpecifierKind> Prefix;
-
- /// The last component in the nested name specifier, which
- /// can be an identifier, a declaration, or a type.
- ///
- /// When the pointer is NULL, this specifier represents the global
- /// specifier '::'. Otherwise, the pointer is one of
- /// IdentifierInfo*, Namespace*, or Type*, depending on the kind of
- /// specifier as encoded within the prefix.
- void* Specifier = nullptr;
-
-public:
- /// The kind of specifier that completes this nested name
- /// specifier.
- enum SpecifierKind {
- /// An identifier, stored as an IdentifierInfo*.
- Identifier,
-
- /// A namespace-like entity, stored as a NamespaceBaseDecl*.
- Namespace,
-
- /// A type, stored as a Type*.
- TypeSpec,
-
- /// The global specifier '::'. There is no stored value.
- Global,
-
- /// Microsoft's '__super' specifier, stored as a CXXRecordDecl* of
- /// the class it appeared in.
- Super
- };
-
-private:
- /// Builds the global specifier.
- NestedNameSpecifier() : Prefix(nullptr, StoredIdentifier) {}
-
- /// Copy constructor used internally to clone nested name
- /// specifiers.
- NestedNameSpecifier(const NestedNameSpecifier &Other) = default;
-
- /// Either find or insert the given nested name specifier
- /// mockup in the given context.
- static NestedNameSpecifier *FindOrInsert(const ASTContext &Context,
- const NestedNameSpecifier &Mockup);
-
-public:
- NestedNameSpecifier &operator=(const NestedNameSpecifier &) = delete;
-
- /// Builds a specifier combining a prefix and an identifier.
- ///
- /// The prefix must be dependent, since nested name specifiers
- /// referencing an identifier are only permitted when the identifier
- /// cannot be resolved.
- static NestedNameSpecifier *Create(const ASTContext &Context,
- NestedNameSpecifier *Prefix,
- const IdentifierInfo *II);
-
- /// Builds a nested name specifier that names a namespace or namespace alias.
- static NestedNameSpecifier *Create(const ASTContext &Context,
- NestedNameSpecifier *Prefix,
- const NamespaceBaseDecl *NS);
-
- /// Builds a nested name specifier that names a type.
- static NestedNameSpecifier *
- Create(const ASTContext &Context, NestedNameSpecifier *Prefix, const Type *T);
-
- /// Builds a specifier that consists of just an identifier.
- ///
- /// The nested-name-specifier is assumed to be dependent, but has no
- /// prefix because the prefix is implied by something outside of the
- /// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent
- /// type.
- static NestedNameSpecifier *Create(const ASTContext &Context,
- const IdentifierInfo *II);
-
- /// Returns the nested name specifier representing the global
- /// scope.
- static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context);
-
- /// Returns the nested name specifier representing the __super scope
- /// for the given CXXRecordDecl.
- static NestedNameSpecifier *SuperSpecifier(const ASTContext &Context,
- CXXRecordDecl *RD);
-
- /// Return the prefix of this nested name specifier.
- ///
- /// The prefix contains all of the parts of the nested name
- /// specifier that precede this current specifier. For example, for a
- /// nested name specifier that represents "foo::bar::", the current
- /// specifier will contain "bar::" and the prefix will contain
- /// "foo::".
- NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); }
-
- /// Determine what kind of nested name specifier is stored.
- SpecifierKind getKind() const;
-
- /// Retrieve the identifier stored in this nested name
- /// specifier.
- IdentifierInfo *getAsIdentifier() const {
- if (Prefix.getInt() == StoredIdentifier)
- return (IdentifierInfo *)Specifier;
-
- return nullptr;
+auto NestedNameSpecifier::getKind() const -> Kind {
+ if (!isStoredKind()) {
+ switch (getFlagKind()) {
+ case FlagKind::Null:
+ return Kind::Null;
+ case FlagKind::Global:
+ return Kind::Global;
+ case FlagKind::Invalid:
+ llvm_unreachable("use of invalid NestedNameSpecifier");
+ }
+ llvm_unreachable("unhandled FlagKind");
}
+ switch (auto [K, Ptr] = getStored(); K) {
+ case StoredKind::Type:
+ return Kind::Type;
+ case StoredKind::NamespaceWithGlobal:
+ case StoredKind::NamespaceWithNamespace:
+ return Kind::Namespace;
+ case StoredKind::NamespaceOrSuper:
+ switch (static_cast<const Decl *>(Ptr)->getKind()) {
+ case Decl::Namespace:
+ case Decl::NamespaceAlias:
+ return Kind::Namespace;
+ case Decl::CXXRecord:
+ case Decl::ClassTemplateSpecialization:
+ case Decl::ClassTemplatePartialSpecialization:
+ return Kind::MicrosoftSuper;
+ default:
+ llvm_unreachable("unexpected decl kind");
+ }
+ }
+ llvm_unreachable("unknown StoredKind");
+}
- /// Retrieve the namespace or namespace alias stored in this nested name
- /// specifier.
- NamespaceBaseDecl *getAsNamespace() const;
-
- /// Retrieve the record declaration stored in this nested name
- /// specifier.
- CXXRecordDecl *getAsRecordDecl() const;
-
- /// Retrieve the type stored in this nested name specifier.
- const Type *getAsType() const {
- if (Prefix.getInt() == StoredTypeSpec)
- return (const Type *)Specifier;
+NestedNameSpecifier::NestedNameSpecifier(const Type *T)
+ : NestedNameSpecifier({StoredKind::Type, T}) {
+ assert(getKind() == Kind::Type);
+}
- return nullptr;
+auto NestedNameSpecifier::MakeNamespacePtrKind(
+ const ASTContext &Ctx, const NamespaceBaseDecl *Namespace,
+ NestedNameSpecifier Prefix) -> PtrKind {
+ switch (Prefix.getKind()) {
+ case Kind::Null:
+ return {StoredKind::NamespaceOrSuper, Namespace};
+ case Kind::Global:
+ return {StoredKind::NamespaceWithGlobal, Namespace};
+ case Kind::Namespace:
+ return {StoredKind::NamespaceWithNamespace,
+ MakeNamespaceAndPrefixStorage(Ctx, Namespace, Prefix)};
+ case Kind::MicrosoftSuper:
+ case Kind::Type:
+ llvm_unreachable("invalid prefix for namespace");
}
+ llvm_unreachable("unhandled kind");
+}
- /// Fully translate this nested name specifier to a type.
- /// Unlike getAsType, this will convert this entire nested
- /// name specifier chain into its equivalent type.
- const Type *translateToType(const ASTContext &Context) const;
+/// Builds a nested name specifier that names a namespace.
+NestedNameSpecifier::NestedNameSpecifier(const ASTContext &Ctx,
+ const NamespaceBaseDecl *Namespace,
+ NestedNameSpecifier Prefix)
+ : NestedNameSpecifier(MakeNamespacePtrKind(Ctx, Namespace, Prefix)) {
+ assert(getKind() == Kind::Namespace);
+}
- NestedNameSpecifierDependence getDependence() const;
+/// Builds a nested name specifier that names a class through microsoft's
+/// __super specifier.
+NestedNameSpecifier::NestedNameSpecifier(CXXRecordDecl *RD)
+ : NestedNameSpecifier({StoredKind::NamespaceOrSuper, RD}) {
+ assert(getKind() == Kind::MicrosoftSuper);
+}
- /// Whether this nested name specifier refers to a dependent
- /// type or not.
- bool isDependent() const;
+CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
+ switch (getKind()) {
+ case Kind::MicrosoftSuper:
+ return getAsMicrosoftSuper();
+ case Kind::Type:
+ return getAsType()->getAsCXXRecordDecl();
+ case Kind::Global:
+ case Kind::Namespace:
+ case Kind::Null:
+ return nullptr;
+ }
+ llvm_unreachable("Invalid NNS Kind!");
+}
- /// Whether this nested name specifier involves a template
- /// parameter.
- bool isInstantiationDependent() const;
+NestedNameSpecifier NestedNameSpecifier::getCanonical() const {
+ switch (getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ // These are canonical and unique.
+ return *this;
+ case NestedNameSpecifier::Kind::Namespace: {
+ // A namespace is canonical; build a nested-name-specifier with
+ // this namespace and no prefix.
+ const NamespaceBaseDecl *ND = getAsNamespaceAndPrefix().Namespace;
+ return NestedNameSpecifier(
+ {StoredKind::NamespaceOrSuper, ND->getNamespace()->getCanonicalDecl()});
+ }
+ case NestedNameSpecifier::Kind::Type:
+ return NestedNameSpecifier(
+ getAsType()->getCanonicalTypeInternal().getTypePtr());
+ }
+ llvm_unreachable("unhandled kind");
+}
- /// Whether this nested-name-specifier contains an unexpanded
- /// parameter pack (for C++11 variadic templates).
- bool containsUnexpandedParameterPack() const;
+bool NestedNameSpecifier::isCanonical() const {
+ return *this == getCanonical();
+}
- /// Whether this nested name specifier contains an error.
- bool containsErrors() const;
+TypeLoc NestedNameSpecifierLoc::castAsTypeLoc() const {
+ return TypeLoc(Qualifier.getAsType(), LoadPointer(/*Offset=*/0));
+}
- /// Print this nested name specifier to the given output stream. If
- /// `ResolveTemplateArguments` is true, we'll print actual types, e.g.
- /// `ns::SomeTemplate<int, MyClass>` instead of
- /// `ns::SomeTemplate<Container::value_type, T>`.
- void print(raw_ostream &OS, const PrintingPolicy &Policy,
- bool ResolveTemplateArguments = false,
- bool PrintFinalScopeResOp = true) const;
+TypeLoc NestedNameSpecifierLoc::getAsTypeLoc() const {
+ if (Qualifier.getKind() != NestedNameSpecifier::Kind::Type)
+ return TypeLoc();
+ return castAsTypeLoc();
+}
- void Profile(llvm::FoldingSetNodeID &ID) const {
- ID.AddPointer(Prefix.getOpaqueValue());
- ID.AddPointer(Specifier);
+unsigned
+NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier Qualifier) {
+ // Location of the trailing '::'.
+ unsigned Length = sizeof(SourceLocation::UIntTy);
+
+ switch (Qualifier.getKind()) {
+ case NestedNameSpecifier::Kind::Global:
+ // Nothing more to add.
+ break;
+
+ case NestedNameSpecifier::Kind::Namespace:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ // The location of the identifier or namespace name.
+ Length += sizeof(SourceLocation::UIntTy);
+ break;
+
+ case NestedNameSpecifier::Kind::Type:
+ // The "void*" that points at the TypeLoc data.
+ // Note: the 'template' keyword is part of the TypeLoc.
+ Length += sizeof(void *);
+ break;
+
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("Expected a non-NULL qualifier");
}
- /// Dump the nested name specifier to standard output to aid
- /// in debugging.
- void dump(const LangOptions &LO) const;
- void dump() const;
- void dump(llvm::raw_ostream &OS) const;
- void dump(llvm::raw_ostream &OS, const LangOptions &LO) const;
-};
+ return Length;
+}
-/// A C++ nested-name-specifier augmented with source location
-/// information.
-class NestedNameSpecifierLoc {
- NestedNameSpecifier *Qualifier = nullptr;
- void *Data = nullptr;
-
- /// Determines the data length for the last component in the
- /// given nested-name-specifier.
- static unsigned getLocalDataLength(NestedNameSpecifier *Qualifier);
-
- /// Determines the data length for the entire
- /// nested-name-specifier.
- static unsigned getDataLength(NestedNameSpecifier *Qualifier);
-
-public:
- /// Construct an empty nested-name-specifier.
- NestedNameSpecifierLoc() = default;
-
- /// Construct a nested-name-specifier with source location information
- /// from
- NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data)
- : Qualifier(Qualifier), Data(Data) {}
-
- /// Evaluates true when this nested-name-specifier location is
- /// non-empty.
- explicit operator bool() const { return Qualifier; }
-
- /// Evaluates true when this nested-name-specifier location is
- /// non-empty.
- bool hasQualifier() const { return Qualifier; }
-
- /// Retrieve the nested-name-specifier to which this instance
- /// refers.
- NestedNameSpecifier *getNestedNameSpecifier() const {
- return Qualifier;
- }
+NamespaceAndPrefixLoc NestedNameSpecifierLoc::castAsNamespaceAndPrefix() const {
+ auto [Namespace, Prefix] = Qualifier.getAsNamespaceAndPrefix();
+ return {Namespace, NestedNameSpecifierLoc(Prefix, Data)};
+}
- /// Retrieve the opaque pointer that refers to source-location data.
- void *getOpaqueData() const { return Data; }
-
- /// Retrieve the source range covering the entirety of this
- /// nested-name-specifier.
- ///
- /// For example, if this instance refers to a nested-name-specifier
- /// \c \::std::vector<int>::, the returned source range would cover
- /// from the initial '::' to the last '::'.
- SourceRange getSourceRange() const LLVM_READONLY {
- return SourceRange(getBeginLoc(), getEndLoc());
- }
+NamespaceAndPrefixLoc NestedNameSpecifierLoc::getAsNamespaceAndPrefix() const {
+ if (Qualifier.getKind() != NestedNameSpecifier::Kind::Namespace)
+ return {};
+ return castAsNamespaceAndPrefix();
+}
- /// Retrieve the source range covering just the last part of
- /// this nested-name-specifier, not including the prefix.
- ///
- /// For example, if this instance refers to a nested-name-specifier
- /// \c \::std::vector<int>::, the returned source range would cover
- /// from "vector" to the last '::'.
- SourceRange getLocalSourceRange() const;
-
- /// Retrieve the location of the beginning of this
- /// nested-name-specifier.
- SourceLocation getBeginLoc() const {
- if (!Qualifier)
- return SourceLocation();
-
- NestedNameSpecifierLoc First = *this;
- while (NestedNameSpecifierLoc Prefix = First.getPrefix())
- First = Prefix;
- return First.getLocalSourceRange().getBegin();
+unsigned NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier Qualifier) {
+ unsigned Length = 0;
+ for (; Qualifier; Qualifier = Qualifier.getAsNamespaceAndPrefix().Prefix) {
+ Length += getLocalDataLength(Qualifier);
+ if (Qualifier.getKind() != NestedNameSpecifier::Kind::Namespace)
+ break;
}
+ return Length;
+}
- /// Retrieve the location of the end of this
- /// nested-name-specifier.
- SourceLocation getEndLoc() const { return getLocalSourceRange().getEnd(); }
+unsigned NestedNameSpecifierLoc::getDataLength() const {
+ return getDataLength(Qualifier);
+}
- /// Retrieve the location of the beginning of this
- /// component of the nested-name-specifier.
- SourceLocation getLocalBeginLoc() const {
- return getLocalSourceRange().getBegin();
+SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
+ switch (auto Kind = Qualifier.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ return SourceRange();
+ case NestedNameSpecifier::Kind::Global:
+ return LoadSourceLocation(/*Offset=*/0);
+ case NestedNameSpecifier::Kind::Namespace:
+ case NestedNameSpecifier::Kind::MicrosoftSuper: {
+ unsigned Offset =
+ Kind == NestedNameSpecifier::Kind::Namespace
+ ? getDataLength(Qualifier.getAsNamespaceAndPrefix().Prefix)
+ : 0;
+ return SourceRange(
+ LoadSourceLocation(Offset),
+ LoadSourceLocation(Offset + sizeof(SourceLocation::UIntTy)));
}
-
- /// Retrieve the location of the end of this component of the
- /// nested-name-specifier.
- SourceLocation getLocalEndLoc() const {
- return getLocalSourceRange().getEnd();
+ case NestedNameSpecifier::Kind::Type: {
+ // The "void*" that points at the TypeLoc data.
+ // Note: the 'template' keyword is part of the TypeLoc.
+ void *TypeData = LoadPointer(/*Offset=*/0);
+ TypeLoc TL(Qualifier.getAsType(), TypeData);
+ return SourceRange(TL.getBeginLoc(), LoadSourceLocation(sizeof(void *)));
}
-
- /// Return the prefix of this nested-name-specifier.
- ///
- /// For example, if this instance refers to a nested-name-specifier
- /// \c \::std::vector<int>::, the prefix is \c \::std::. Note that the
- /// returned prefix may be empty, if this is the first component of
- /// the nested-name-specifier.
- NestedNameSpecifierLoc getPrefix() const {
- if (!Qualifier)
- return *this;
-
- return NestedNameSpecifierLoc(Qualifier->getPrefix(), Data);
}
- /// For a nested-name-specifier that refers to a type,
- /// retrieve the type with source-location information.
- TypeLoc getTypeLoc() const;
+ llvm_unreachable("Invalid NNS Kind!");
+}
- /// Determines the data length for the entire
- /// nested-name-specifier.
- unsigned getDataLength() const { return getDataLength(Qualifier); }
+SourceRange NestedNameSpecifierLoc::getSourceRange() const {
+ return SourceRange(getBeginLoc(), getEndLoc());
+}
- friend bool operator==(NestedNameSpecifierLoc X,
- NestedNameSpecifierLoc Y) {
- return X.Qualifier == Y.Qualifier && X.Data == Y.Data;
- }
+SourceLocation NestedNameSpecifierLoc::getEndLoc() const {
+ return getLocalSourceRange().getEnd();
+}
- friend bool operator!=(NestedNameSpecifierLoc X,
- NestedNameSpecifierLoc Y) {
- return !(X == Y);
- }
-};
+/// Retrieve the location of the beginning of this
+/// component of the nested-name-specifier.
+SourceLocation NestedNameSpecifierLoc::getLocalBeginLoc() const {
+ return getLocalSourceRange().getBegin();
+}
-/// Class that aids in the construction of nested-name-specifiers along
-/// with source-location information for all of the components of the
+/// Retrieve the location of the end of this component of the
/// nested-name-specifier.
-class NestedNameSpecifierLocBuilder {
- /// The current representation of the nested-name-specifier we're
- /// building.
- NestedNameSpecifier *Representation = nullptr;
-
- /// Buffer used to store source-location information for the
- /// nested-name-specifier.
- ///
- /// Note that we explicitly manage the buffer (rather than using a
- /// SmallVector) because \c Declarator expects it to be possible to memcpy()
- /// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder.
- char *Buffer = nullptr;
-
- /// The size of the buffer used to store source-location information
- /// for the nested-name-specifier.
- unsigned BufferSize = 0;
-
- /// The capacity of the buffer used to store source-location
- /// information for the nested-name-specifier.
- unsigned BufferCapacity = 0;
-
-public:
- NestedNameSpecifierLocBuilder() = default;
- NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other);
-
- NestedNameSpecifierLocBuilder &
- operator=(const NestedNameSpecifierLocBuilder &Other);
-
- ~NestedNameSpecifierLocBuilder() {
- if (BufferCapacity)
- free(Buffer);
- }
+SourceLocation NestedNameSpecifierLoc::getLocalEndLoc() const {
+ return getLocalSourceRange().getEnd();
+}
- /// Retrieve the representation of the nested-name-specifier.
- NestedNameSpecifier *getRepresentation() const { return Representation; }
-
- /// Extend the current nested-name-specifier by another
- /// nested-name-specifier component of the form 'type::'.
- ///
- /// \param Context The AST context in which this nested-name-specifier
- /// resides.
- ///
- /// \param TL The TypeLoc that describes the type preceding the '::'.
- ///
- /// \param ColonColonLoc The location of the trailing '::'.
- void Extend(ASTContext &Context, TypeLoc TL, SourceLocation ColonColonLoc);
-
- /// Extend the current nested-name-specifier by another
- /// nested-name-specifier component of the form 'identifier::'.
- ///
- /// \param Context The AST context in which this nested-name-specifier
- /// resides.
- ///
- /// \param Identifier The identifier.
- ///
- /// \param IdentifierLoc The location of the identifier.
- ///
- /// \param ColonColonLoc The location of the trailing '::'.
- void Extend(ASTContext &Context, IdentifierInfo *Identifier,
- SourceLocation IdentifierLoc, SourceLocation ColonColonLoc);
-
- /// Extend the current nested-name-specifier by another
- /// nested-name-specifier component of the form 'namespace::'.
- ///
- /// \param Context The AST context in which this nested-name-specifier
- /// resides.
- ///
- /// \param Namespace The namespace or namespace alias.
- ///
- /// \param NamespaceLoc The location of the namespace name or the namespace
- // alias.
- ///
- /// \param ColonColonLoc The location of the trailing '::'.
- void Extend(ASTContext &Context, NamespaceBaseDecl *Namespace,
- SourceLocation NamespaceLoc, SourceLocation ColonColonLoc);
-
- /// Turn this (empty) nested-name-specifier into the global
- /// nested-name-specifier '::'.
- void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
-
- /// Turns this (empty) nested-name-specifier into '__super'
- /// nested-name-specifier.
- ///
- /// \param Context The AST context in which this nested-name-specifier
- /// resides.
- ///
- /// \param RD The declaration of the class in which nested-name-specifier
- /// appeared.
- ///
- /// \param SuperLoc The location of the '__super' keyword.
- /// name.
- ///
- /// \param ColonColonLoc The location of the trailing '::'.
- void MakeSuper(ASTContext &Context, CXXRecordDecl *RD,
- SourceLocation SuperLoc, SourceLocation ColonColonLoc);
-
- /// Make a new nested-name-specifier from incomplete source-location
- /// information.
- ///
- /// This routine should be used very, very rarely, in cases where we
- /// need to synthesize a nested-name-specifier. Most code should instead use
- /// \c Adopt() with a proper \c NestedNameSpecifierLoc.
- void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier,
- SourceRange R);
-
- /// Adopt an existing nested-name-specifier (with source-range
- /// information).
- void Adopt(NestedNameSpecifierLoc Other);
-
- /// Retrieve the source range covered by this nested-name-specifier.
- SourceRange getSourceRange() const LLVM_READONLY {
- return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange();
- }
+SourceRange NestedNameSpecifierLocBuilder::getSourceRange() const {
+ return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange();
+}
- /// Retrieve a nested-name-specifier with location information,
- /// copied into the given AST context.
- ///
- /// \param Context The context into which this nested-name-specifier will be
- /// copied.
- NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const;
-
- /// Retrieve a nested-name-specifier with location
- /// information based on the information in this builder.
- ///
- /// This loc will contain references to the builder's internal data and may
- /// be invalidated by any change to the builder.
- NestedNameSpecifierLoc getTemporary() const {
- return NestedNameSpecifierLoc(Representation, Buffer);
- }
+} // namespace clang
+
+namespace llvm {
+
+template <> struct DenseMapInfo<clang::NestedNameSpecifier> {
+ static clang::NestedNameSpecifier getEmptyKey() { return std::nullopt; }
- /// Clear out this builder, and prepare it to build another
- /// nested-name-specifier with source-location information.
- void Clear() {
- Representation = nullptr;
- BufferSize = 0;
+ static clang::NestedNameSpecifier getTombstoneKey() {
+ return clang::NestedNameSpecifier::getInvalid();
}
- /// Retrieve the underlying buffer.
- ///
- /// \returns A pair containing a pointer to the buffer of source-location
- /// data and the size of the source-location data that resides in that
- /// buffer.
- std::pair<char *, unsigned> getBuffer() const {
- return std::make_pair(Buffer, BufferSize);
+ static unsigned getHashValue(const clang::NestedNameSpecifier &V) {
+ return hash_combine(V.getAsVoidPointer());
}
};
-/// Insertion operator for diagnostics. This allows sending
-/// NestedNameSpecifiers into a diagnostic with <<.
-inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
- NestedNameSpecifier *NNS) {
- DB.AddTaggedVal(reinterpret_cast<uint64_t>(NNS),
- DiagnosticsEngine::ak_nestednamespec);
- return DB;
-}
-
-} // namespace clang
-
-namespace llvm {
-
template <> struct DenseMapInfo<clang::NestedNameSpecifierLoc> {
- using FirstInfo = DenseMapInfo<clang::NestedNameSpecifier *>;
+ using FirstInfo = DenseMapInfo<clang::NestedNameSpecifier>;
using SecondInfo = DenseMapInfo<void *>;
static clang::NestedNameSpecifierLoc getEmptyKey() {
diff --git a/clang/include/clang/AST/NestedNameSpecifierBase.h b/clang/include/clang/AST/NestedNameSpecifierBase.h
new file mode 100644
index 0000000000000..73c60ba695419
--- /dev/null
+++ b/clang/include/clang/AST/NestedNameSpecifierBase.h
@@ -0,0 +1,586 @@
+//===- NestedNameSpecifier.h - C++ nested name specifiers -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the NestedNameSpecifier class, which represents
+// a C++ nested-name-specifier.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIERBASE_H
+#define LLVM_CLANG_AST_NESTEDNAMESPECIFIERBASE_H
+
+#include "clang/AST/DependenceFlags.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include <cstdint>
+#include <cstdlib>
+#include <utility>
+
+namespace clang {
+
+class ASTContext;
+class CXXRecordDecl;
+class NamedDecl;
+class IdentifierInfo;
+class LangOptions;
+class NamespaceBaseDecl;
+struct PrintingPolicy;
+class Type;
+class TypeLoc;
+
+struct NamespaceAndPrefix;
+struct alignas(8) NamespaceAndPrefixStorage;
+
+/// Represents a C++ nested name specifier, such as
+/// "\::std::vector<int>::".
+///
+/// C++ nested name specifiers are the prefixes to qualified
+/// names. For example, "foo::" in "foo::x" is a nested name
+/// specifier. Nested name specifiers are made up of a sequence of
+/// specifiers, each of which can be a namespace, type, decltype specifier, or
+/// the global specifier ('::'). The last two specifiers can only appear at the
+/// start of a nested-namespace-specifier.
+class NestedNameSpecifier {
+ enum class FlagKind { Null, Global, Invalid };
+ enum class StoredKind {
+ Type,
+ NamespaceOrSuper,
+ NamespaceWithGlobal,
+ NamespaceWithNamespace
+ };
+ static constexpr uintptr_t FlagBits = 2, FlagMask = (1u << FlagBits) - 1u,
+ FlagOffset = 1, PtrOffset = FlagBits + FlagOffset,
+ PtrMask = (1u << PtrOffset) - 1u;
+
+ uintptr_t StoredOrFlag;
+
+ explicit NestedNameSpecifier(uintptr_t StoredOrFlag)
+ : StoredOrFlag(StoredOrFlag) {}
+ struct PtrKind {
+ StoredKind SK;
+ const void *Ptr;
+ };
+ explicit NestedNameSpecifier(PtrKind PK)
+ : StoredOrFlag(uintptr_t(PK.Ptr) | (uintptr_t(PK.SK) << FlagOffset)) {
+ assert(PK.Ptr != nullptr);
+ assert((uintptr_t(PK.Ptr) & ((1u << PtrOffset) - 1u)) == 0);
+ assert((uintptr_t(PK.Ptr) >> PtrOffset) != 0);
+ }
+
+ explicit constexpr NestedNameSpecifier(FlagKind K)
+ : StoredOrFlag(uintptr_t(K) << FlagOffset) {}
+
+ bool isStoredKind() const { return (StoredOrFlag >> PtrOffset) != 0; }
+
+ std::pair<StoredKind, const void *> getStored() const {
+ assert(isStoredKind());
+ return {StoredKind(StoredOrFlag >> FlagOffset & FlagMask),
+ reinterpret_cast<const void *>(StoredOrFlag & ~PtrMask)};
+ }
+
+ FlagKind getFlagKind() const {
+ assert(!isStoredKind());
+ return FlagKind(StoredOrFlag >> FlagOffset);
+ }
+
+ static const NamespaceAndPrefixStorage *
+ MakeNamespaceAndPrefixStorage(const ASTContext &Ctx,
+ const NamespaceBaseDecl *Namespace,
+ NestedNameSpecifier Prefix);
+ static inline PtrKind MakeNamespacePtrKind(const ASTContext &Ctx,
+ const NamespaceBaseDecl *Namespace,
+ NestedNameSpecifier Prefix);
+
+public:
+ static constexpr NestedNameSpecifier getInvalid() {
+ return NestedNameSpecifier(FlagKind::Invalid);
+ }
+
+ static constexpr NestedNameSpecifier getGlobal() {
+ return NestedNameSpecifier(FlagKind::Global);
+ }
+
+ NestedNameSpecifier() : NestedNameSpecifier(FlagKind::Invalid) {}
+
+ /// The kind of specifier that completes this nested name
+ /// specifier.
+ enum class Kind {
+ /// Empty.
+ Null,
+
+ /// The global specifier '::'. There is no stored value.
+ Global,
+
+ /// A type, stored as a Type*.
+ Type,
+
+ /// A namespace-like entity, stored as a NamespaceBaseDecl*.
+ Namespace,
+
+ /// Microsoft's '__super' specifier, stored as a CXXRecordDecl* of
+ /// the class it appeared in.
+ MicrosoftSuper,
+ };
+
+ inline Kind getKind() const;
+
+ NestedNameSpecifier(std::nullopt_t) : StoredOrFlag(0) {}
+
+ explicit inline NestedNameSpecifier(const Type *T);
+
+ /// Builds a nested name specifier that names a namespace.
+ inline NestedNameSpecifier(const ASTContext &Ctx,
+ const NamespaceBaseDecl *Namespace,
+ NestedNameSpecifier Prefix);
+
+ /// Builds a nested name specifier that names a class through microsoft's
+ /// __super specifier.
+ explicit inline NestedNameSpecifier(CXXRecordDecl *RD);
+
+ explicit operator bool() const { return StoredOrFlag != 0; }
+
+ void *getAsVoidPointer() const {
+ return reinterpret_cast<void *>(StoredOrFlag);
+ }
+ static NestedNameSpecifier getFromVoidPointer(const void *Ptr) {
+ return NestedNameSpecifier(reinterpret_cast<uintptr_t>(Ptr));
+ }
+
+ const Type *getAsType() const {
+ auto [Kind, Ptr] = getStored();
+ assert(Kind == StoredKind::Type);
+ assert(Ptr != nullptr);
+ return static_cast<const Type *>(Ptr);
+ }
+
+ inline NamespaceAndPrefix getAsNamespaceAndPrefix() const;
+
+ CXXRecordDecl *getAsMicrosoftSuper() const {
+ auto [Kind, Ptr] = getStored();
+ assert(Kind == StoredKind::NamespaceOrSuper);
+ assert(Ptr != nullptr);
+ return static_cast<CXXRecordDecl *>(const_cast<void *>(Ptr));
+ }
+
+ /// Retrieve the record declaration stored in this nested name
+ /// specifier, or null.
+ inline CXXRecordDecl *getAsRecordDecl() const;
+
+ friend bool operator==(NestedNameSpecifier LHS, NestedNameSpecifier RHS) {
+ return LHS.StoredOrFlag == RHS.StoredOrFlag;
+ }
+ friend bool operator!=(NestedNameSpecifier LHS, NestedNameSpecifier RHS) {
+ return LHS.StoredOrFlag != RHS.StoredOrFlag;
+ }
+
+ /// Retrieves the "canonical" nested name specifier for a
+ /// given nested name specifier.
+ ///
+ /// The canonical nested name specifier is a nested name specifier
+ /// that uniquely identifies a type or namespace within the type
+ /// system. For example, given:
+ ///
+ /// \code
+ /// namespace N {
+ /// struct S {
+ /// template<typename T> struct X { typename T* type; };
+ /// };
+ /// }
+ ///
+ /// template<typename T> struct Y {
+ /// typename N::S::X<T>::type member;
+ /// };
+ /// \endcode
+ ///
+ /// Here, the nested-name-specifier for N::S::X<T>:: will be
+ /// S::X<template-param-0-0>, since 'S' and 'X' are uniquely defined
+ /// by declarations in the type system and the canonical type for
+ /// the template type parameter 'T' is template-param-0-0.
+ inline NestedNameSpecifier getCanonical() const;
+
+ /// Whether this nested name specifier is canonical.
+ inline bool isCanonical() const;
+
+ /// Whether this nested name specifier starts with a '::'.
+ bool isFullyQualified() const;
+
+ NestedNameSpecifierDependence getDependence() const;
+
+ /// Whether this nested name specifier refers to a dependent
+ /// type or not.
+ bool isDependent() const {
+ return getDependence() & NestedNameSpecifierDependence::Dependent;
+ }
+
+ /// Whether this nested name specifier involves a template
+ /// parameter.
+ bool isInstantiationDependent() const {
+ return getDependence() & NestedNameSpecifierDependence::Instantiation;
+ }
+
+ /// Whether this nested-name-specifier contains an unexpanded
+ /// parameter pack (for C++11 variadic templates).
+ bool containsUnexpandedParameterPack() const {
+ return getDependence() & NestedNameSpecifierDependence::UnexpandedPack;
+ }
+
+ /// Whether this nested name specifier contains an error.
+ bool containsErrors() const {
+ return getDependence() & NestedNameSpecifierDependence::Error;
+ }
+
+ /// Print this nested name specifier to the given output stream. If
+ /// `ResolveTemplateArguments` is true, we'll print actual types, e.g.
+ /// `ns::SomeTemplate<int, MyClass>` instead of
+ /// `ns::SomeTemplate<Container::value_type, T>`.
+ void print(raw_ostream &OS, const PrintingPolicy &Policy,
+ bool ResolveTemplateArguments = false,
+ bool PrintFinalScopeResOp = true) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(StoredOrFlag);
+ }
+
+ /// Dump the nested name specifier to aid in debugging.
+ void dump(llvm::raw_ostream *OS = nullptr,
+ const LangOptions *LO = nullptr) const;
+ void dump(const LangOptions &LO) const;
+ void dump(llvm::raw_ostream &OS) const;
+ void dump(llvm::raw_ostream &OS, const LangOptions &LO) const;
+
+ static constexpr auto NumLowBitsAvailable = FlagOffset;
+};
+
+struct NamespaceAndPrefix {
+ const NamespaceBaseDecl *Namespace;
+ NestedNameSpecifier Prefix;
+};
+
+struct alignas(8) NamespaceAndPrefixStorage : NamespaceAndPrefix,
+ llvm::FoldingSetNode {
+ NamespaceAndPrefixStorage(const NamespaceBaseDecl *Namespace,
+ NestedNameSpecifier Prefix)
+ : NamespaceAndPrefix{Namespace, Prefix} {}
+ void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Namespace, Prefix); }
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const NamespaceBaseDecl *Namespace,
+ NestedNameSpecifier Prefix) {
+ ID.AddPointer(Namespace);
+ Prefix.Profile(ID);
+ }
+};
+
+NamespaceAndPrefix NestedNameSpecifier::getAsNamespaceAndPrefix() const {
+ auto [Kind, Ptr] = getStored();
+ switch (Kind) {
+ case StoredKind::NamespaceOrSuper:
+ case StoredKind::NamespaceWithGlobal:
+ return {static_cast<const NamespaceBaseDecl *>(Ptr),
+ Kind == StoredKind::NamespaceWithGlobal
+ ? NestedNameSpecifier::getGlobal()
+ : std::nullopt};
+ case StoredKind::NamespaceWithNamespace:
+ return *static_cast<const NamespaceAndPrefixStorage *>(Ptr);
+ case StoredKind::Type:;
+ }
+ llvm_unreachable("unexpected stored kind");
+}
+
+struct NamespaceAndPrefixLoc;
+
+/// A C++ nested-name-specifier augmented with source location
+/// information.
+class NestedNameSpecifierLoc {
+ NestedNameSpecifier Qualifier = std::nullopt;
+ void *Data = nullptr;
+
+ /// Load a (possibly unaligned) source location from a given address
+ /// and offset.
+ SourceLocation LoadSourceLocation(unsigned Offset) const {
+ SourceLocation::UIntTy Raw;
+ memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(Raw));
+ return SourceLocation::getFromRawEncoding(Raw);
+ }
+
+ /// Load a (possibly unaligned) pointer from a given address and
+ /// offset.
+ void *LoadPointer(unsigned Offset) const {
+ void *Result;
+ memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void *));
+ return Result;
+ }
+
+ /// Determines the data length for the last component in the
+ /// given nested-name-specifier.
+ static inline unsigned getLocalDataLength(NestedNameSpecifier Qualifier);
+
+ /// Determines the data length for the entire
+ /// nested-name-specifier.
+ static inline unsigned getDataLength(NestedNameSpecifier Qualifier);
+
+public:
+ /// Construct an empty nested-name-specifier.
+ NestedNameSpecifierLoc() = default;
+
+ /// Construct a nested-name-specifier with source location information
+ /// from
+ NestedNameSpecifierLoc(NestedNameSpecifier Qualifier, void *Data)
+ : Qualifier(Qualifier), Data(Data) {}
+
+ /// Evaluates true when this nested-name-specifier location is
+ /// non-empty.
+ explicit operator bool() const { return bool(Qualifier); }
+
+ /// Evaluates true when this nested-name-specifier location is
+ /// non-empty.
+ bool hasQualifier() const { return bool(Qualifier); }
+
+ /// Retrieve the nested-name-specifier to which this instance
+ /// refers.
+ NestedNameSpecifier getNestedNameSpecifier() const { return Qualifier; }
+
+ /// Retrieve the opaque pointer that refers to source-location data.
+ void *getOpaqueData() const { return Data; }
+
+ /// Retrieve the source range covering the entirety of this
+ /// nested-name-specifier.
+ ///
+ /// For example, if this instance refers to a nested-name-specifier
+ /// \c \::std::vector<int>::, the returned source range would cover
+ /// from the initial '::' to the last '::'.
+ inline SourceRange getSourceRange() const LLVM_READONLY;
+
+ /// Retrieve the source range covering just the last part of
+ /// this nested-name-specifier, not including the prefix.
+ ///
+ /// For example, if this instance refers to a nested-name-specifier
+ /// \c \::std::vector<int>::, the returned source range would cover
+ /// from "vector" to the last '::'.
+ inline SourceRange getLocalSourceRange() const;
+
+ /// Retrieve the location of the beginning of this
+ /// nested-name-specifier.
+ SourceLocation getBeginLoc() const;
+
+ /// Retrieve the location of the end of this
+ /// nested-name-specifier.
+ inline SourceLocation getEndLoc() const;
+
+ /// Retrieve the location of the beginning of this
+ /// component of the nested-name-specifier.
+ inline SourceLocation getLocalBeginLoc() const;
+
+ /// Retrieve the location of the end of this component of the
+ /// nested-name-specifier.
+ inline SourceLocation getLocalEndLoc() const;
+
+ /// For a nested-name-specifier that refers to a namespace,
+ /// retrieve the namespace and its prefix.
+ ///
+ /// For example, if this instance refers to a nested-name-specifier
+ /// \c \::std::chrono::, the prefix is \c \::std::. Note that the
+ /// returned prefix may be empty, if this is the first component of
+ /// the nested-name-specifier.
+ inline NamespaceAndPrefixLoc castAsNamespaceAndPrefix() const;
+ inline NamespaceAndPrefixLoc getAsNamespaceAndPrefix() const;
+
+ /// For a nested-name-specifier that refers to a type,
+ /// retrieve the type with source-location information.
+ inline TypeLoc castAsTypeLoc() const;
+ inline TypeLoc getAsTypeLoc() const;
+
+ /// Determines the data length for the entire
+ /// nested-name-specifier.
+ inline unsigned getDataLength() const;
+
+ friend bool operator==(NestedNameSpecifierLoc X, NestedNameSpecifierLoc Y) {
+ return X.Qualifier == Y.Qualifier && X.Data == Y.Data;
+ }
+
+ friend bool operator!=(NestedNameSpecifierLoc X, NestedNameSpecifierLoc Y) {
+ return !(X == Y);
+ }
+};
+
+struct NamespaceAndPrefixLoc {
+ const NamespaceBaseDecl *Namespace = nullptr;
+ NestedNameSpecifierLoc Prefix;
+
+ explicit operator bool() const { return Namespace != nullptr; }
+};
+
+/// Class that aids in the construction of nested-name-specifiers along
+/// with source-location information for all of the components of the
+/// nested-name-specifier.
+class NestedNameSpecifierLocBuilder {
+ /// The current representation of the nested-name-specifier we're
+ /// building.
+ NestedNameSpecifier Representation = std::nullopt;
+
+ /// Buffer used to store source-location information for the
+ /// nested-name-specifier.
+ ///
+ /// Note that we explicitly manage the buffer (rather than using a
+ /// SmallVector) because \c Declarator expects it to be possible to memcpy()
+ /// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder.
+ char *Buffer = nullptr;
+
+ /// The size of the buffer used to store source-location information
+ /// for the nested-name-specifier.
+ unsigned BufferSize = 0;
+
+ /// The capacity of the buffer used to store source-location
+ /// information for the nested-name-specifier.
+ unsigned BufferCapacity = 0;
+
+ void PushTrivial(ASTContext &Context, NestedNameSpecifier Qualifier,
+ SourceRange R);
+
+public:
+ NestedNameSpecifierLocBuilder() = default;
+ NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other);
+
+ NestedNameSpecifierLocBuilder &
+ operator=(const NestedNameSpecifierLocBuilder &Other);
+
+ ~NestedNameSpecifierLocBuilder() {
+ if (BufferCapacity)
+ free(Buffer);
+ }
+
+ /// Retrieve the representation of the nested-name-specifier.
+ NestedNameSpecifier getRepresentation() const { return Representation; }
+
+ /// Make a nested-name-specifier of the form 'type::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param TL The TypeLoc that describes the type preceding the '::'.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Make(ASTContext &Context, TypeLoc TL, SourceLocation ColonColonLoc);
+
+ /// Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'namespace::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param Namespace The namespace.
+ ///
+ /// \param NamespaceLoc The location of the namespace name.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, const NamespaceBaseDecl *Namespace,
+ SourceLocation NamespaceLoc, SourceLocation ColonColonLoc);
+
+ /// Turn this (empty) nested-name-specifier into the global
+ /// nested-name-specifier '::'.
+ void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
+
+ /// Turns this (empty) nested-name-specifier into '__super'
+ /// nested-name-specifier.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param RD The declaration of the class in which nested-name-specifier
+ /// appeared.
+ ///
+ /// \param SuperLoc The location of the '__super' keyword.
+ /// name.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void MakeMicrosoftSuper(ASTContext &Context, CXXRecordDecl *RD,
+ SourceLocation SuperLoc,
+ SourceLocation ColonColonLoc);
+
+ /// Make a new nested-name-specifier from incomplete source-location
+ /// information.
+ ///
+ /// This routine should be used very, very rarely, in cases where we
+ /// need to synthesize a nested-name-specifier. Most code should instead use
+ /// \c Adopt() with a proper \c NestedNameSpecifierLoc.
+ void MakeTrivial(ASTContext &Context, NestedNameSpecifier Qualifier,
+ SourceRange R) {
+ Representation = Qualifier;
+ BufferSize = 0;
+ PushTrivial(Context, Qualifier, R);
+ }
+
+ /// Adopt an existing nested-name-specifier (with source-range
+ /// information).
+ void Adopt(NestedNameSpecifierLoc Other);
+
+ /// Retrieve the source range covered by this nested-name-specifier.
+ inline SourceRange getSourceRange() const LLVM_READONLY;
+
+ /// Retrieve a nested-name-specifier with location information,
+ /// copied into the given AST context.
+ ///
+ /// \param Context The context into which this nested-name-specifier will be
+ /// copied.
+ NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const;
+
+ /// Retrieve a nested-name-specifier with location
+ /// information based on the information in this builder.
+ ///
+ /// This loc will contain references to the builder's internal data and may
+ /// be invalidated by any change to the builder.
+ NestedNameSpecifierLoc getTemporary() const {
+ return NestedNameSpecifierLoc(Representation, Buffer);
+ }
+
+ /// Clear out this builder, and prepare it to build another
+ /// nested-name-specifier with source-location information.
+ void Clear() {
+ Representation = std::nullopt;
+ BufferSize = 0;
+ }
+
+ /// Retrieve the underlying buffer.
+ ///
+ /// \returns A pair containing a pointer to the buffer of source-location
+ /// data and the size of the source-location data that resides in that
+ /// buffer.
+ std::pair<char *, unsigned> getBuffer() const {
+ return std::make_pair(Buffer, BufferSize);
+ }
+};
+
+/// Insertion operator for diagnostics. This allows sending
+/// NestedNameSpecifiers into a diagnostic with <<.
+inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
+ NestedNameSpecifier NNS) {
+ DB.AddTaggedVal(reinterpret_cast<uintptr_t>(NNS.getAsVoidPointer()),
+ DiagnosticsEngine::ak_nestednamespec);
+ return DB;
+}
+
+} // namespace clang
+
+namespace llvm {
+
+template <> struct PointerLikeTypeTraits<clang::NestedNameSpecifier> {
+ static void *getAsVoidPointer(clang::NestedNameSpecifier P) {
+ return P.getAsVoidPointer();
+ }
+ static clang::NestedNameSpecifier getFromVoidPointer(const void *P) {
+ return clang::NestedNameSpecifier::getFromVoidPointer(P);
+ }
+ static constexpr int NumLowBitsAvailable =
+ clang::NestedNameSpecifier::NumLowBitsAvailable;
+};
+
+} // namespace llvm
+
+#endif // LLVM_CLANG_AST_NESTEDNAMESPECIFIERBASE_H
diff --git a/clang/include/clang/AST/ODRHash.h b/clang/include/clang/AST/ODRHash.h
index 11f917a1a4634..ae3fab697786a 100644
--- a/clang/include/clang/AST/ODRHash.h
+++ b/clang/include/clang/AST/ODRHash.h
@@ -93,7 +93,7 @@ class ODRHash {
void AddQualType(QualType T);
void AddStmt(const Stmt *S);
void AddIdentifierInfo(const IdentifierInfo *II);
- void AddNestedNameSpecifier(const NestedNameSpecifier *NNS);
+ void AddNestedNameSpecifier(NestedNameSpecifier NNS);
void AddDependentTemplateName(const DependentTemplateStorage &Name);
void AddTemplateName(TemplateName Name);
void AddDeclarationNameInfo(DeclarationNameInfo NameInfo,
diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td
index 0438e4dfbafac..5b10127526e4e 100644
--- a/clang/include/clang/AST/PropertiesBase.td
+++ b/clang/include/clang/AST/PropertiesBase.td
@@ -127,9 +127,8 @@ def LValuePathSerializationHelper :
PropertyType<"APValue::LValuePathSerializationHelper"> {
let BufferElementTypes = [ LValuePathEntry ];
}
-def NestedNameSpecifier : PropertyType<"NestedNameSpecifier *">;
-def NestedNameSpecifierKind :
- EnumPropertyType<"NestedNameSpecifier::SpecifierKind">;
+def NestedNameSpecifier : PropertyType<"NestedNameSpecifier">;
+def NestedNameSpecifierKind : EnumPropertyType<"NestedNameSpecifier::Kind">;
def OverloadedOperatorKind : EnumPropertyType;
def Qualifiers : PropertyType;
def QualType : DefaultValuePropertyType;
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 05134422797b3..248b89200eace 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -242,7 +242,7 @@ template <typename Derived> class RecursiveASTVisitor {
/// Recursively visit a C++ nested-name-specifier.
///
/// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
+ bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS);
/// Recursively visit a C++ nested-name-specifier with location
/// information.
@@ -787,46 +787,43 @@ bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier(
- NestedNameSpecifier *NNS) {
- if (!NNS)
+ NestedNameSpecifier NNS) {
+ switch (NNS.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
return true;
-
- if (NNS->getPrefix())
- TRY_TO(TraverseNestedNameSpecifier(NNS->getPrefix()));
-
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
+ case NestedNameSpecifier::Kind::Namespace:
+ TRY_TO(TraverseNestedNameSpecifier(NNS.getAsNamespaceAndPrefix().Prefix));
+ return true;
+ case NestedNameSpecifier::Kind::Type: {
+ auto *T = const_cast<Type *>(NNS.getAsType());
+ TRY_TO(TraverseNestedNameSpecifier(T->getPrefix()));
+ TRY_TO(TraverseType(QualType(T, 0), /*TraverseQualifier=*/false));
return true;
-
- case NestedNameSpecifier::TypeSpec:
- TRY_TO(TraverseType(QualType(NNS->getAsType(), 0)));
}
-
- return true;
+ }
+ llvm_unreachable("unhandled kind");
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc(
NestedNameSpecifierLoc NNS) {
- if (!NNS)
+ switch (NNS.getNestedNameSpecifier().getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
return true;
-
- if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
- TRY_TO(TraverseNestedNameSpecifierLoc(Prefix));
-
- switch (NNS.getNestedNameSpecifier()->getKind()) {
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
+ case NestedNameSpecifier::Kind::Namespace:
+ TRY_TO(
+ TraverseNestedNameSpecifierLoc(NNS.castAsNamespaceAndPrefix().Prefix));
return true;
-
- case NestedNameSpecifier::TypeSpec:
- TRY_TO(TraverseTypeLoc(NNS.getTypeLoc()));
- break;
+ case NestedNameSpecifier::Kind::Type: {
+ TypeLoc TL = NNS.castAsTypeLoc();
+ TRY_TO(TraverseNestedNameSpecifierLoc(TL.getPrefix()));
+ TRY_TO(TraverseTypeLoc(TL, /*TraverseQualifier=*/false));
+ return true;
+ }
}
return true;
@@ -1011,10 +1008,11 @@ DEF_TRAVERSE_TYPE(RValueReferenceType,
{ TRY_TO(TraverseType(T->getPointeeType())); })
DEF_TRAVERSE_TYPE(MemberPointerType, {
- TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
- if (T->isSugared())
- TRY_TO(TraverseType(
- QualType(T->getMostRecentCXXRecordDecl()->getTypeForDecl(), 0)));
+ NestedNameSpecifier Qualifier =
+ T->isSugared() ? cast<MemberPointerType>(T->getCanonicalTypeUnqualified())
+ ->getQualifier()
+ : T->getQualifier();
+ TRY_TO(TraverseNestedNameSpecifier(Qualifier));
TRY_TO(TraverseType(T->getPointeeType()));
})
@@ -1279,8 +1277,10 @@ DEF_TRAVERSE_TYPE(PredefinedSugarType, {})
}
template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::TraverseQualifiedTypeLoc(QualifiedTypeLoc TL) {
+bool RecursiveASTVisitor<Derived>::TraverseQualifiedTypeLoc(
+ QualifiedTypeLoc TL, bool TraverseQualifier) {
+ assert(TraverseQualifier &&
+ "Qualifiers should never occur within NestedNameSpecifiers");
// Move this over to the 'main' typeloc tree. Note that this is a
// move -- we pretend that we were really looking at the unqualified
// typeloc all along -- rather than a recursion, so we don't follow
diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h
index 86c155dc17c51..ac0c0cc7e0286 100644
--- a/clang/include/clang/AST/TemplateBase.h
+++ b/clang/include/clang/AST/TemplateBase.h
@@ -15,7 +15,7 @@
#define LLVM_CLANG_AST_TEMPLATEBASE_H
#include "clang/AST/DependenceFlags.h"
-#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/NestedNameSpecifierBase.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/Basic/LLVM.h"
@@ -476,31 +476,25 @@ class TemplateArgument {
/// Location information for a TemplateArgument.
struct TemplateArgumentLocInfo {
-private:
struct TemplateTemplateArgLocInfo {
- // FIXME: We'd like to just use the qualifier in the TemplateName,
- // but template arguments get canonicalized too quickly.
- NestedNameSpecifier *Qualifier;
void *QualifierLocData;
+ SourceLocation TemplateKwLoc;
SourceLocation TemplateNameLoc;
SourceLocation EllipsisLoc;
};
- llvm::PointerUnion<TemplateTemplateArgLocInfo *, Expr *, TypeSourceInfo *>
- Pointer;
-
TemplateTemplateArgLocInfo *getTemplate() const {
return cast<TemplateTemplateArgLocInfo *>(Pointer);
}
-public:
TemplateArgumentLocInfo() {}
TemplateArgumentLocInfo(TypeSourceInfo *Declarator) { Pointer = Declarator; }
TemplateArgumentLocInfo(Expr *E) { Pointer = E; }
// Ctx is used for allocation -- this case is unusually large and also rare,
// so we store the payload out-of-line.
- TemplateArgumentLocInfo(ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc,
+ TemplateArgumentLocInfo(ASTContext &Ctx, SourceLocation TemplateKwLoc,
+ NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateNameLoc,
SourceLocation EllipsisLoc);
@@ -510,10 +504,8 @@ struct TemplateArgumentLocInfo {
Expr *getAsExpr() const { return cast<Expr *>(Pointer); }
- NestedNameSpecifierLoc getTemplateQualifierLoc() const {
- const auto *Template = getTemplate();
- return NestedNameSpecifierLoc(Template->Qualifier,
- Template->QualifierLocData);
+ SourceLocation getTemplateKwLoc() const {
+ return getTemplate()->TemplateKwLoc;
}
SourceLocation getTemplateNameLoc() const {
@@ -560,14 +552,10 @@ class TemplateArgumentLoc {
}
TemplateArgumentLoc(ASTContext &Ctx, const TemplateArgument &Argument,
+ SourceLocation TemplateKWLoc,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateNameLoc,
- SourceLocation EllipsisLoc = SourceLocation())
- : Argument(Argument),
- LocInfo(Ctx, QualifierLoc, TemplateNameLoc, EllipsisLoc) {
- assert(Argument.getKind() == TemplateArgument::Template ||
- Argument.getKind() == TemplateArgument::TemplateExpansion);
- }
+ SourceLocation EllipsisLoc = SourceLocation());
/// - Fetches the primary location of the argument.
SourceLocation getLocation() const {
@@ -616,13 +604,15 @@ class TemplateArgumentLoc {
return LocInfo.getAsExpr();
}
- NestedNameSpecifierLoc getTemplateQualifierLoc() const {
+ SourceLocation getTemplateKWLoc() const {
if (Argument.getKind() != TemplateArgument::Template &&
Argument.getKind() != TemplateArgument::TemplateExpansion)
- return NestedNameSpecifierLoc();
- return LocInfo.getTemplateQualifierLoc();
+ return SourceLocation();
+ return LocInfo.getTemplateKwLoc();
}
+ NestedNameSpecifierLoc getTemplateQualifierLoc() const;
+
SourceLocation getTemplateNameLoc() const {
if (Argument.getKind() != TemplateArgument::Template &&
Argument.getKind() != TemplateArgument::TemplateExpansion)
diff --git a/clang/include/clang/AST/TemplateName.h b/clang/include/clang/AST/TemplateName.h
index 63949f898f6a2..37ea401a0045a 100644
--- a/clang/include/clang/AST/TemplateName.h
+++ b/clang/include/clang/AST/TemplateName.h
@@ -14,7 +14,7 @@
#define LLVM_CLANG_AST_TEMPLATENAME_H
#include "clang/AST/DependenceFlags.h"
-#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/NestedNameSpecifierBase.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/UnsignedOrNone.h"
@@ -335,10 +335,18 @@ class TemplateName {
/// structure, if any.
QualifiedTemplateName *getAsQualifiedTemplateName() const;
+ /// Retrieve the underlying qualified template name,
+ /// looking through underlying nodes.
+ QualifiedTemplateName *getAsAdjustedQualifiedTemplateName() const;
+
/// Retrieve the underlying dependent template name
/// structure, if any.
DependentTemplateName *getAsDependentTemplateName() const;
+ // Retrieve the qualifier stored in either a underlying DependentTemplateName
+ // or QualifiedTemplateName.
+ NestedNameSpecifier getQualifier() const;
+
/// Retrieve the using shadow declaration through which the underlying
/// template declaration is introduced, if any.
UsingShadowDecl *getAsUsingShadowDecl() const;
@@ -503,7 +511,7 @@ class QualifiedTemplateName : public llvm::FoldingSetNode {
/// "template" keyword is always redundant in this case (otherwise,
/// the template name would be a dependent name and we would express
/// this name with DependentTemplateName).
- llvm::PointerIntPair<NestedNameSpecifier *, 1> Qualifier;
+ llvm::PointerIntPair<NestedNameSpecifier, 1, bool> Qualifier;
/// The underlying template name, it is either
/// 1) a Template -- a template declaration that this qualified name refers
@@ -512,7 +520,7 @@ class QualifiedTemplateName : public llvm::FoldingSetNode {
/// using-shadow declaration.
TemplateName UnderlyingTemplate;
- QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword,
+ QualifiedTemplateName(NestedNameSpecifier NNS, bool TemplateKeyword,
TemplateName Template)
: Qualifier(NNS, TemplateKeyword ? 1 : 0), UnderlyingTemplate(Template) {
assert(UnderlyingTemplate.getKind() == TemplateName::Template ||
@@ -521,7 +529,7 @@ class QualifiedTemplateName : public llvm::FoldingSetNode {
public:
/// Return the nested name specifier that qualifies this name.
- NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }
+ NestedNameSpecifier getQualifier() const { return Qualifier.getPointer(); }
/// Whether the template name was prefixed by the "template"
/// keyword.
@@ -534,9 +542,9 @@ class QualifiedTemplateName : public llvm::FoldingSetNode {
Profile(ID, getQualifier(), hasTemplateKeyword(), UnderlyingTemplate);
}
- static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
+ static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier NNS,
bool TemplateKeyword, TemplateName TN) {
- ID.AddPointer(NNS);
+ NNS.Profile(ID);
ID.AddBoolean(TemplateKeyword);
ID.AddPointer(TN.getAsVoidPointer());
}
@@ -585,18 +593,18 @@ class DependentTemplateStorage {
///
/// The bit stored in this qualifier describes whether the \c Name field
/// was preceeded by a template keyword.
- llvm::PointerIntPair<NestedNameSpecifier *, 1, bool> Qualifier;
+ llvm::PointerIntPair<NestedNameSpecifier, 1, bool> Qualifier;
/// The dependent template name.
IdentifierOrOverloadedOperator Name;
public:
- DependentTemplateStorage(NestedNameSpecifier *Qualifier,
+ DependentTemplateStorage(NestedNameSpecifier Qualifier,
IdentifierOrOverloadedOperator Name,
bool HasTemplateKeyword);
/// Return the nested name specifier that qualifies this name.
- NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }
+ NestedNameSpecifier getQualifier() const { return Qualifier.getPointer(); }
IdentifierOrOverloadedOperator getName() const { return Name; }
@@ -609,10 +617,10 @@ class DependentTemplateStorage {
Profile(ID, getQualifier(), getName(), hasTemplateKeyword());
}
- static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
+ static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier NNS,
IdentifierOrOverloadedOperator Name,
bool HasTemplateKeyword) {
- ID.AddPointer(NNS);
+ NNS.Profile(ID);
ID.AddBoolean(HasTemplateKeyword);
Name.Profile(ID);
}
diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h
index 1917a8ac29f05..6d2795111685a 100644
--- a/clang/include/clang/AST/TextNodeDumper.h
+++ b/clang/include/clang/AST/TextNodeDumper.h
@@ -211,7 +211,7 @@ class TextNodeDumper
void dumpAccessSpecifier(AccessSpecifier AS);
void dumpCleanupObject(const ExprWithCleanups::CleanupObject &C);
void dumpTemplateSpecializationKind(TemplateSpecializationKind TSK);
- void dumpNestedNameSpecifier(const NestedNameSpecifier *NNS);
+ void dumpNestedNameSpecifier(NestedNameSpecifier NNS);
void dumpConceptReference(const ConceptReference *R);
void dumpTemplateArgument(const TemplateArgument &TA);
void dumpBareTemplateName(TemplateName TN);
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 23a683ededa87..c0874ef01697f 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -18,7 +18,7 @@
#define LLVM_CLANG_AST_TYPE_H
#include "clang/AST/DependenceFlags.h"
-#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/NestedNameSpecifierBase.h"
#include "clang/AST/TemplateName.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/AttrKinds.h"
@@ -2956,6 +2956,11 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
/// qualifiers from the outermost type.
const ArrayType *castAsArrayTypeUnsafe() const;
+ /// If this type represents a qualified-id, this returns its nested name
+ /// specifier. For example, for the qualified-id "foo::bar::baz", this returns
+ /// "foo::bar". Returns null if this type represents an unqualified-id.
+ NestedNameSpecifier getPrefix() const;
+
/// Determine whether this type had the specified attribute applied to it
/// (looking through top-level type sugar).
bool hasAttr(attr::Kind AK) const;
@@ -3633,12 +3638,12 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
/// The class of which the pointee is a member. Must ultimately be a
/// CXXRecordType, but could be a typedef or a template parameter too.
- NestedNameSpecifier *Qualifier;
+ NestedNameSpecifier Qualifier;
- MemberPointerType(QualType Pointee, NestedNameSpecifier *Qualifier,
+ MemberPointerType(QualType Pointee, NestedNameSpecifier Qualifier,
QualType CanonicalPtr)
: Type(MemberPointer, CanonicalPtr,
- (toTypeDependence(Qualifier->getDependence()) &
+ (toTypeDependence(Qualifier.getDependence()) &
~TypeDependence::VariablyModified) |
Pointee->getDependence()),
PointeeType(Pointee), Qualifier(Qualifier) {}
@@ -3658,7 +3663,7 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
return !PointeeType->isFunctionProtoType();
}
- NestedNameSpecifier *getQualifier() const { return Qualifier; }
+ NestedNameSpecifier getQualifier() const { return Qualifier; }
/// Note: this can trigger extra deserialization when external AST sources are
/// used. Prefer `getCXXRecordDecl()` unless you really need the most recent
/// decl.
@@ -3677,7 +3682,7 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
- const NestedNameSpecifier *Qualifier,
+ const NestedNameSpecifier Qualifier,
const CXXRecordDecl *Cls);
static bool classof(const Type *T) {
@@ -7280,24 +7285,24 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these
/// The nested name specifier containing the qualifier.
- NestedNameSpecifier *NNS;
+ NestedNameSpecifier NNS;
/// The type that this typename specifier refers to.
const IdentifierInfo *Name;
- DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
+ DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier NNS,
const IdentifierInfo *Name, QualType CanonType)
: TypeWithKeyword(Keyword, DependentName, CanonType,
TypeDependence::DependentInstantiation |
- toTypeDependence(NNS->getDependence())),
+ (NNS ? toTypeDependence(NNS.getDependence())
+ : TypeDependence::Dependent)),
NNS(NNS), Name(Name) {
- assert(NNS);
assert(Name);
}
public:
/// Retrieve the qualification on this type.
- NestedNameSpecifier *getQualifier() const { return NNS; }
+ NestedNameSpecifier getQualifier() const { return NNS; }
/// Retrieve the identifier that terminates this type name.
/// For example, "type" in "typename T::type".
@@ -7313,9 +7318,9 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode {
}
static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword,
- NestedNameSpecifier *NNS, const IdentifierInfo *Name) {
+ NestedNameSpecifier NNS, const IdentifierInfo *Name) {
ID.AddInteger(llvm::to_underlying(Keyword));
- ID.AddPointer(NNS);
+ NNS.Profile(ID);
ID.AddPointer(Name);
}
diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index 8b57951121323..18fac458601c0 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -16,7 +16,7 @@
#include "clang/AST/ASTConcept.h"
#include "clang/AST/DeclarationName.h"
-#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/NestedNameSpecifierBase.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
#include "clang/Basic/LLVM.h"
@@ -193,6 +193,21 @@ class TypeLoc {
/// Get the SourceLocation of the template keyword (if any).
SourceLocation getTemplateKeywordLoc() const;
+ /// If this type represents a qualified-id, this returns it's nested name
+ /// specifier. For example, for the qualified-id "foo::bar::baz", this returns
+ /// "foo::bar". Returns null if this type represents an unqualified-id.
+ NestedNameSpecifierLoc getPrefix() const;
+
+ /// This returns the position of the type after any elaboration, such as the
+ /// 'struct' keyword, and name qualifiers. This will the 'template' keyword if
+ /// present, or the name location otherwise.
+ SourceLocation getNonPrefixBeginLoc() const;
+
+ /// This returns the position of the type after any elaboration, such as the
+ /// 'struct' keyword. This may be the position of the name qualifiers,
+ /// 'template' keyword, or the name location otherwise.
+ SourceLocation getNonElaboratedBeginLoc() const;
+
/// Initializes this to state that every location in this
/// type is the given location.
///
@@ -1520,7 +1535,7 @@ class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc,
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setSigilLoc(Loc);
- if (auto *Qualifier = getTypePtr()->getQualifier()) {
+ if (NestedNameSpecifier Qualifier = getTypePtr()->getQualifier()) {
NestedNameSpecifierLocBuilder Builder;
Builder.MakeTrivial(Context, Qualifier, Loc);
setQualifierLoc(Builder.getWithLocInContext(Context));
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 02d79b7488f82..cbd931cabd806 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -7775,7 +7775,7 @@ AST_MATCHER_FUNCTION_P_OVERLOAD(
/// matches "A::"
AST_MATCHER_P(NestedNameSpecifier, specifiesType,
internal::Matcher<QualType>, InnerMatcher) {
- if (!Node.getAsType())
+ if (Node.getKind() != NestedNameSpecifier::Kind::Type)
return false;
return InnerMatcher.matches(QualType(Node.getAsType(), 0), Finder, Builder);
}
@@ -7793,8 +7793,12 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesType,
/// matches "A::"
AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc,
internal::Matcher<TypeLoc>, InnerMatcher) {
- return Node && Node.getNestedNameSpecifier()->getAsType() &&
- InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder);
+ if (!Node)
+ return false;
+ TypeLoc TL = Node.getAsTypeLoc();
+ if (!TL)
+ return false;
+ return InnerMatcher.matches(TL, Finder, Builder);
}
/// Matches on the prefix of a \c NestedNameSpecifier.
@@ -7809,10 +7813,21 @@ AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc,
AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix,
internal::Matcher<NestedNameSpecifier>, InnerMatcher,
0) {
- const NestedNameSpecifier *NextNode = Node.getPrefix();
+ NestedNameSpecifier NextNode = std::nullopt;
+ switch (Node.getKind()) {
+ case NestedNameSpecifier::Kind::Namespace:
+ NextNode = Node.getAsNamespaceAndPrefix().Prefix;
+ break;
+ case NestedNameSpecifier::Kind::Type:
+ NextNode = Node.getAsType()->getPrefix();
+ break;
+ default:
+ break;
+ }
+
if (!NextNode)
return false;
- return InnerMatcher.matches(*NextNode, Finder, Builder);
+ return InnerMatcher.matches(NextNode, Finder, Builder);
}
/// Matches on the prefix of a \c NestedNameSpecifierLoc.
@@ -7827,7 +7842,12 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix,
AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix,
internal::Matcher<NestedNameSpecifierLoc>, InnerMatcher,
1) {
- NestedNameSpecifierLoc NextNode = Node.getPrefix();
+ NestedNameSpecifierLoc NextNode;
+ if (TypeLoc TL = Node.getAsTypeLoc())
+ NextNode = TL.getPrefix();
+ else
+ NextNode = Node.getAsNamespaceAndPrefix().Prefix;
+
if (!NextNode)
return false;
return InnerMatcher.matches(NextNode, Finder, Builder);
@@ -7845,9 +7865,13 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix,
/// matches "ns::"
AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace,
internal::Matcher<NamespaceDecl>, InnerMatcher) {
- if (auto *NS = dyn_cast_if_present<NamespaceDecl>(Node.getAsNamespace()))
- return InnerMatcher.matches(*NS, Finder, Builder);
- return false;
+ if (Node.getKind() != NestedNameSpecifier::Kind::Namespace)
+ return false;
+ const auto *Namespace =
+ dyn_cast<NamespaceDecl>(Node.getAsNamespaceAndPrefix().Namespace);
+ if (!Namespace)
+ return false;
+ return InnerMatcher.matches(*Namespace, Finder, Builder);
}
/// Matches attributes.
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index f074bc5fed2cc..1ab6f11a23e12 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -1783,7 +1783,7 @@ class LocMatcher : public MatcherInterface<TLoc> {
private:
static DynTypedNode extract(const NestedNameSpecifierLoc &Loc) {
- return DynTypedNode::create(*Loc.getNestedNameSpecifier());
+ return DynTypedNode::create(Loc.getNestedNameSpecifier());
}
};
diff --git a/clang/include/clang/ExtractAPI/DeclarationFragments.h b/clang/include/clang/ExtractAPI/DeclarationFragments.h
index 4ac744459031e..4859225ef4ced 100644
--- a/clang/include/clang/ExtractAPI/DeclarationFragments.h
+++ b/clang/include/clang/ExtractAPI/DeclarationFragments.h
@@ -440,9 +440,8 @@ class DeclarationFragmentsBuilder {
DeclarationFragments &);
/// Build DeclarationFragments for a NestedNameSpecifier.
- static DeclarationFragments getFragmentsForNNS(const NestedNameSpecifier *,
- ASTContext &,
- DeclarationFragments &);
+ static DeclarationFragments
+ getFragmentsForNNS(NestedNameSpecifier, ASTContext &, DeclarationFragments &);
/// Build DeclarationFragments for Qualifiers.
static DeclarationFragments getFragmentsForQualifiers(const Qualifiers quals);
diff --git a/clang/include/clang/Sema/CodeCompleteConsumer.h b/clang/include/clang/Sema/CodeCompleteConsumer.h
index 2dd27593778c7..c26f4e33d289c 100644
--- a/clang/include/clang/Sema/CodeCompleteConsumer.h
+++ b/clang/include/clang/Sema/CodeCompleteConsumer.h
@@ -162,7 +162,8 @@ SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T);
/// Determine the type that this declaration will have if it is used
/// as a type or in an expression.
-QualType getDeclUsageType(ASTContext &C, const NamedDecl *ND);
+QualType getDeclUsageType(ASTContext &C, NestedNameSpecifier Qualifier,
+ const NamedDecl *ND);
/// Determine the priority to be given to a macro code completion result
/// with the given name.
@@ -867,7 +868,7 @@ class CodeCompletionResult {
/// If the result should have a nested-name-specifier, this is it.
/// When \c QualifierIsInformative, the nested-name-specifier is
/// informative rather than required.
- NestedNameSpecifier *Qualifier = nullptr;
+ NestedNameSpecifier Qualifier = std::nullopt;
/// If this Decl was unshadowed by using declaration, this can store a
/// pointer to the UsingShadowDecl which was used in the unshadowing process.
@@ -882,7 +883,7 @@ class CodeCompletionResult {
/// Build a result that refers to a declaration.
CodeCompletionResult(const NamedDecl *Declaration, unsigned Priority,
- NestedNameSpecifier *Qualifier = nullptr,
+ NestedNameSpecifier Qualifier = std::nullopt,
bool QualifierIsInformative = false,
bool Accessible = true,
std::vector<FixItHint> FixIts = std::vector<FixItHint>())
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 797ef9b601ebc..c1a99a1fddc80 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -91,12 +91,11 @@ class CXXScopeSpec {
}
/// Retrieve the representation of the nested-name-specifier.
- NestedNameSpecifier *getScopeRep() const {
+ NestedNameSpecifier getScopeRep() const {
return Builder.getRepresentation();
}
- /// Extend the current nested-name-specifier by another
- /// nested-name-specifier component of the form 'type::'.
+ /// Make a nested-name-specifier of the form 'type::'.
///
/// \param Context The AST context in which this nested-name-specifier
/// resides.
@@ -140,8 +139,9 @@ class CXXScopeSpec {
/// name.
///
/// \param ColonColonLoc The location of the trailing '::'.
- void MakeSuper(ASTContext &Context, CXXRecordDecl *RD,
- SourceLocation SuperLoc, SourceLocation ColonColonLoc);
+ void MakeMicrosoftSuper(ASTContext &Context, CXXRecordDecl *RD,
+ SourceLocation SuperLoc,
+ SourceLocation ColonColonLoc);
/// Make a new nested-name-specifier from incomplete source-location
/// information.
@@ -149,7 +149,7 @@ class CXXScopeSpec {
/// FIXME: This routine should be used very, very rarely, in cases where we
/// need to synthesize a nested-name-specifier. Most code should instead use
/// \c Adopt() with a proper \c NestedNameSpecifierLoc.
- void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier,
+ void MakeTrivial(ASTContext &Context, NestedNameSpecifier Qualifier,
SourceRange R);
/// Adopt an existing nested-name-specifier (with source-range
diff --git a/clang/include/clang/Sema/HeuristicResolver.h b/clang/include/clang/Sema/HeuristicResolver.h
index e193c0bc14cd9..71588bee92d16 100644
--- a/clang/include/clang/Sema/HeuristicResolver.h
+++ b/clang/include/clang/Sema/HeuristicResolver.h
@@ -67,8 +67,7 @@ class HeuristicResolver {
// Try to heuristically resolve a dependent nested name specifier
// to the type it likely denotes. Note that *dependent* name specifiers always
// denote types, not namespaces.
- QualType
- resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS) const;
+ QualType resolveNestedNameSpecifierToType(NestedNameSpecifier NNS) const;
// Perform an imprecise lookup of a dependent name in `RD`.
// This function does not follow strict semantic rules and should be used
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 24dccffcd5675..1655c855d119e 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3218,7 +3218,7 @@ class Sema final : public SemaBase {
/// current instantiation (C++0x [temp.dep.type]p1).
///
/// \param NNS a dependent nested name specifier.
- CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
+ CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier NNS);
/// The parser has parsed a global nested-name-specifier '::'.
///
@@ -3255,7 +3255,7 @@ class Sema final : public SemaBase {
/// (e.g., Base::), perform name lookup for that identifier as a
/// nested-name-specifier within the given scope, and return the result of
/// that name lookup.
- NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
+ NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier NNS);
/// Keeps information about an identifier in a nested-name-spec.
///
@@ -7618,7 +7618,7 @@ class Sema final : public SemaBase {
/// "real" base class is checked as appropriate when checking the access of
/// the member name.
ExprResult PerformObjectMemberConversion(Expr *From,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifier Qualifier,
NamedDecl *FoundDecl,
NamedDecl *Member);
@@ -10196,7 +10196,7 @@ class Sema final : public SemaBase {
ExprResult InitializeExplicitObjectArgument(Sema &S, Expr *Obj,
FunctionDecl *Fun);
ExprResult PerformImplicitObjectArgumentInitialization(
- Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl,
+ Expr *From, NestedNameSpecifier Qualifier, NamedDecl *FoundDecl,
CXXMethodDecl *Method);
/// PerformContextuallyConvertToBool - Perform a contextual conversion
@@ -13741,8 +13741,9 @@ class Sema final : public SemaBase {
SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
const MultiLevelTemplateArgumentList &TemplateArgs);
TemplateName
- SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, TemplateName Name,
- SourceLocation Loc,
+ SubstTemplateName(SourceLocation TemplateKWLoc,
+ NestedNameSpecifierLoc &QualifierLoc, TemplateName Name,
+ SourceLocation NameLoc,
const MultiLevelTemplateArgumentList &TemplateArgs);
bool SubstTypeConstraint(TemplateTypeParmDecl *Inst, const TypeConstraint *TC,
diff --git a/clang/include/clang/Sema/SemaInternal.h b/clang/include/clang/Sema/SemaInternal.h
index 4d0da1102bb59..c6287f4c76a11 100644
--- a/clang/include/clang/Sema/SemaInternal.h
+++ b/clang/include/clang/Sema/SemaInternal.h
@@ -208,7 +208,7 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer {
class NamespaceSpecifierSet {
struct SpecifierInfo {
DeclContext* DeclCtx;
- NestedNameSpecifier* NameSpecifier;
+ NestedNameSpecifier NameSpecifier;
unsigned EditDistance;
};
@@ -228,9 +228,9 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer {
static DeclContextList buildContextChain(DeclContext *Start);
unsigned buildNestedNameSpecifier(DeclContextList &DeclChain,
- NestedNameSpecifier *&NNS);
+ NestedNameSpecifier &NNS);
- public:
+ public:
NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext,
CXXScopeSpec *CurScopeSpec);
@@ -275,7 +275,7 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer {
};
void addName(StringRef Name, NamedDecl *ND,
- NestedNameSpecifier *NNS = nullptr, bool isKeyword = false);
+ NestedNameSpecifier NNS = std::nullopt, bool isKeyword = false);
/// Find any visible decls for the given typo correction candidate.
/// If none are found, it to the set of candidates for which qualified lookups
diff --git a/clang/include/clang/Sema/TypoCorrection.h b/clang/include/clang/Sema/TypoCorrection.h
index 09de164297e7b..1d780c45efd55 100644
--- a/clang/include/clang/Sema/TypoCorrection.h
+++ b/clang/include/clang/Sema/TypoCorrection.h
@@ -57,15 +57,15 @@ class TypoCorrection {
static const unsigned CallbackDistanceWeight = 150U;
TypoCorrection(const DeclarationName &Name, NamedDecl *NameDecl,
- NestedNameSpecifier *NNS = nullptr, unsigned CharDistance = 0,
- unsigned QualifierDistance = 0)
+ NestedNameSpecifier NNS = std::nullopt,
+ unsigned CharDistance = 0, unsigned QualifierDistance = 0)
: CorrectionName(Name), CorrectionNameSpec(NNS),
CharDistance(CharDistance), QualifierDistance(QualifierDistance) {
if (NameDecl)
CorrectionDecls.push_back(NameDecl);
}
- TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS = nullptr,
+ TypoCorrection(NamedDecl *Name, NestedNameSpecifier NNS = std::nullopt,
unsigned CharDistance = 0)
: CorrectionName(Name->getDeclName()), CorrectionNameSpec(NNS),
CharDistance(CharDistance) {
@@ -73,7 +73,7 @@ class TypoCorrection {
CorrectionDecls.push_back(Name);
}
- TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS = nullptr,
+ TypoCorrection(DeclarationName Name, NestedNameSpecifier NNS = std::nullopt,
unsigned CharDistance = 0)
: CorrectionName(Name), CorrectionNameSpec(NNS),
CharDistance(CharDistance) {}
@@ -88,13 +88,13 @@ class TypoCorrection {
}
/// Gets the NestedNameSpecifier needed to use the typo correction
- NestedNameSpecifier *getCorrectionSpecifier() const {
+ NestedNameSpecifier getCorrectionSpecifier() const {
return CorrectionNameSpec;
}
- void setCorrectionSpecifier(NestedNameSpecifier *NNS) {
+ void setCorrectionSpecifier(NestedNameSpecifier NNS) {
CorrectionNameSpec = NNS;
- ForceSpecifierReplacement = (NNS != nullptr);
+ ForceSpecifierReplacement = !!NNS;
}
void WillReplaceSpecifier(bool ForceReplacement) {
@@ -264,7 +264,7 @@ class TypoCorrection {
// Results.
DeclarationName CorrectionName;
- NestedNameSpecifier *CorrectionNameSpec = nullptr;
+ NestedNameSpecifier CorrectionNameSpec = std::nullopt;
SmallVector<NamedDecl *, 1> CorrectionDecls;
unsigned CharDistance = 0;
unsigned QualifierDistance = 0;
@@ -282,8 +282,9 @@ class CorrectionCandidateCallback {
public:
static const unsigned InvalidDistance = TypoCorrection::InvalidDistance;
- explicit CorrectionCandidateCallback(const IdentifierInfo *Typo = nullptr,
- NestedNameSpecifier *TypoNNS = nullptr)
+ explicit CorrectionCandidateCallback(
+ const IdentifierInfo *Typo = nullptr,
+ NestedNameSpecifier TypoNNS = std::nullopt)
: Typo(Typo), TypoNNS(TypoNNS) {}
virtual ~CorrectionCandidateCallback() = default;
@@ -320,7 +321,7 @@ class CorrectionCandidateCallback {
virtual std::unique_ptr<CorrectionCandidateCallback> clone() = 0;
void setTypoName(const IdentifierInfo *II) { Typo = II; }
- void setTypoNNS(NestedNameSpecifier *NNS) { TypoNNS = NNS; }
+ void setTypoNNS(NestedNameSpecifier NNS) { TypoNNS = NNS; }
// Flags for context-dependent keywords. WantFunctionLikeCasts is only
// used/meaningful when WantCXXNamedCasts is false.
@@ -346,13 +347,13 @@ class CorrectionCandidateCallback {
}
const IdentifierInfo *Typo;
- NestedNameSpecifier *TypoNNS;
+ NestedNameSpecifier TypoNNS;
};
class DefaultFilterCCC final : public CorrectionCandidateCallback {
public:
explicit DefaultFilterCCC(const IdentifierInfo *Typo = nullptr,
- NestedNameSpecifier *TypoNNS = nullptr)
+ NestedNameSpecifier TypoNNS = std::nullopt)
: CorrectionCandidateCallback(Typo, TypoNNS) {}
std::unique_ptr<CorrectionCandidateCallback> clone() override {
@@ -366,7 +367,7 @@ template <class C>
class DeclFilterCCC final : public CorrectionCandidateCallback {
public:
explicit DeclFilterCCC(const IdentifierInfo *Typo = nullptr,
- NestedNameSpecifier *TypoNNS = nullptr)
+ NestedNameSpecifier TypoNNS = std::nullopt)
: CorrectionCandidateCallback(Typo, TypoNNS) {}
bool ValidateCandidate(const TypoCorrection &candidate) override {
diff --git a/clang/include/clang/Serialization/ASTRecordReader.h b/clang/include/clang/Serialization/ASTRecordReader.h
index 1472497ff5e7e..aed1b7d309001 100644
--- a/clang/include/clang/Serialization/ASTRecordReader.h
+++ b/clang/include/clang/Serialization/ASTRecordReader.h
@@ -223,7 +223,7 @@ class ASTRecordReader
void readQualifierInfo(QualifierInfo &Info);
/// Return a nested name specifier, advancing Idx.
- // NestedNameSpecifier *readNestedNameSpecifier(); (inherited)
+ // NestedNameSpecifier readNestedNameSpecifier(); (inherited)
NestedNameSpecifierLoc readNestedNameSpecifierLoc();
diff --git a/clang/include/clang/Serialization/ASTRecordWriter.h b/clang/include/clang/Serialization/ASTRecordWriter.h
index 97178a4aa980c..9849ea6b395ab 100644
--- a/clang/include/clang/Serialization/ASTRecordWriter.h
+++ b/clang/include/clang/Serialization/ASTRecordWriter.h
@@ -279,7 +279,7 @@ class ASTRecordWriter
void AddQualifierInfo(const QualifierInfo &Info);
/// Emit a nested name specifier.
- void AddNestedNameSpecifier(NestedNameSpecifier *NNS) {
+ void AddNestedNameSpecifier(NestedNameSpecifier NNS) {
writeNestedNameSpecifier(NNS);
}
diff --git a/clang/include/clang/Tooling/Refactoring/Lookup.h b/clang/include/clang/Tooling/Refactoring/Lookup.h
index dcb40b7eee66c..fe0df8656bce1 100644
--- a/clang/include/clang/Tooling/Refactoring/Lookup.h
+++ b/clang/include/clang/Tooling/Refactoring/Lookup.h
@@ -38,8 +38,7 @@ namespace tooling {
/// \param ReplacementString The replacement nested name. Must be fully
/// qualified including a leading "::".
/// \returns The new name to be inserted in place of the current nested name.
-std::string replaceNestedName(const NestedNameSpecifier *Use,
- SourceLocation UseLoc,
+std::string replaceNestedName(NestedNameSpecifier Use, SourceLocation UseLoc,
const DeclContext *UseContext,
const NamedDecl *FromDecl,
StringRef ReplacementString);
diff --git a/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h b/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
index 271232e66626e..319569fd5ab33 100644
--- a/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
+++ b/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
@@ -108,19 +108,21 @@ class RecursiveSymbolVisitor
bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
const SourceLocation TypeEndLoc =
Lexer::getLocForEndOfToken(TL.getBeginLoc(), 0, SM, LangOpts);
- return visit(TL.getTypedefNameDecl(), TL.getBeginLoc(), TypeEndLoc);
+ return visit(TL.getDecl(), TL.getBeginLoc(), TypeEndLoc);
}
- bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+ bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc QualifierLoc) {
// The base visitor will visit NNSL prefixes, so we should only look at
// the current NNS.
- if (NNS) {
- const auto *ND = dyn_cast_if_present<NamespaceDecl>(
- NNS.getNestedNameSpecifier()->getAsNamespace());
- if (!visit(ND, NNS.getLocalBeginLoc(), NNS.getLocalEndLoc()))
+ if (NestedNameSpecifier Qualifier = QualifierLoc.getNestedNameSpecifier();
+ Qualifier.getKind() == NestedNameSpecifier::Kind::Namespace) {
+ const auto *ND = dyn_cast<NamespaceDecl>(
+ Qualifier.getAsNamespaceAndPrefix().Namespace);
+ if (!visit(ND, QualifierLoc.getLocalBeginLoc(),
+ QualifierLoc.getLocalEndLoc()))
return false;
}
- return BaseType::TraverseNestedNameSpecifierLoc(NNS);
+ return BaseType::TraverseNestedNameSpecifierLoc(QualifierLoc);
}
bool VisitDesignatedInitExpr(const DesignatedInitExpr *E) {
diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp
index 91ab66f4639fc..b25757ba43455 100644
--- a/clang/lib/AST/ASTConcept.cpp
+++ b/clang/lib/AST/ASTConcept.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/ASTConcept.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ExprConcepts.h"
+#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h"
#include "llvm/ADT/StringExtras.h"
@@ -92,10 +93,16 @@ ConceptReference::Create(const ASTContext &C, NestedNameSpecifierLoc NNS,
FoundDecl, NamedConcept, ArgsAsWritten);
}
+SourceLocation ConceptReference::getBeginLoc() const {
+ // Note that if the qualifier is null the template KW must also be null.
+ if (auto QualifierLoc = getNestedNameSpecifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return getConceptNameInfo().getBeginLoc();
+}
+
void ConceptReference::print(llvm::raw_ostream &OS,
const PrintingPolicy &Policy) const {
- if (NestedNameSpec)
- NestedNameSpec.getNestedNameSpecifier()->print(OS, Policy);
+ NestedNameSpec.getNestedNameSpecifier().print(OS, Policy);
ConceptName.printName(OS, Policy);
if (hasExplicitTemplateArgs()) {
OS << "<";
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 2c98bccef5dbb..6f95b10cd9656 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -4163,14 +4163,13 @@ QualType ASTContext::getRValueReferenceType(QualType T) const {
}
QualType ASTContext::getMemberPointerType(QualType T,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifier Qualifier,
const CXXRecordDecl *Cls) const {
if (!Qualifier) {
assert(Cls && "At least one of Qualifier or Cls must be provided");
- Qualifier = NestedNameSpecifier::Create(*this, /*Prefix=*/nullptr,
- getTypeDeclType(Cls).getTypePtr());
+ Qualifier = NestedNameSpecifier(getCanonicalTagType(Cls).getTypePtr());
} else if (!Cls) {
- Cls = Qualifier->getAsRecordDecl();
+ Cls = Qualifier.getAsRecordDecl();
}
// Unique pointers, to guarantee there is only one pointer of a particular
// structure.
@@ -4182,12 +4181,11 @@ QualType ASTContext::getMemberPointerType(QualType T,
MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(PT, 0);
- NestedNameSpecifier *CanonicalQualifier = [&] {
+ NestedNameSpecifier CanonicalQualifier = [&] {
if (!Cls)
- return getCanonicalNestedNameSpecifier(Qualifier);
- NestedNameSpecifier *R = NestedNameSpecifier::Create(
- *this, /*Prefix=*/nullptr, Cls->getCanonicalDecl()->getTypeForDecl());
- assert(R == getCanonicalNestedNameSpecifier(R));
+ return Qualifier.getCanonical();
+ NestedNameSpecifier R(getCanonicalTagType(Cls).getTypePtr());
+ assert(R.isCanonical());
return R;
}();
// If the pointee or class type isn't canonical, this won't be a canonical
@@ -6101,7 +6099,7 @@ getCanonicalElaboratedTypeKeyword(ElaboratedTypeKeyword Keyword) {
}
QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
- NestedNameSpecifier *NNS,
+ NestedNameSpecifier NNS,
const IdentifierInfo *Name) const {
llvm::FoldingSetNodeID ID;
DependentNameType::Profile(ID, Keyword, NNS, Name);
@@ -6113,7 +6111,7 @@ QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
ElaboratedTypeKeyword CanonKeyword =
getCanonicalElaboratedTypeKeyword(Keyword);
- NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
+ NestedNameSpecifier CanonNNS = NNS.getCanonical();
QualType Canon;
if (CanonKeyword != Keyword || CanonNNS != NNS) {
@@ -6152,13 +6150,13 @@ QualType ASTContext::getDependentTemplateSpecializationType(
ID, InsertPos))
return QualType(T, 0);
- NestedNameSpecifier *NNS = Name.getQualifier();
+ NestedNameSpecifier NNS = Name.getQualifier();
QualType Canon;
if (!IsCanonical) {
ElaboratedTypeKeyword CanonKeyword =
getCanonicalElaboratedTypeKeyword(Keyword);
- NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
+ NestedNameSpecifier CanonNNS = NNS.getCanonical();
bool AnyNonCanonArgs = false;
auto CanonArgs =
::getCanonicalTemplateArguments(*this, Args, AnyNonCanonArgs);
@@ -6178,7 +6176,7 @@ QualType ASTContext::getDependentTemplateSpecializationType(
} else {
assert(Keyword == getCanonicalElaboratedTypeKeyword(Keyword));
assert(Name.hasTemplateKeyword());
- assert(NNS == getCanonicalNestedNameSpecifier(NNS));
+ assert(NNS.isCanonical());
#ifndef NDEBUG
for (const auto &Arg : Args)
assert(Arg.structurallyEquals(getCanonicalTemplateArgument(Arg)));
@@ -7216,8 +7214,8 @@ bool ASTContext::UnwrapSimilarTypes(QualType &T1, QualType &T2,
*RD2 = T2MPType->getMostRecentCXXRecordDecl();
RD1 != RD2 && RD1->getCanonicalDecl() != RD2->getCanonicalDecl())
return false;
- if (getCanonicalNestedNameSpecifier(T1MPType->getQualifier()) !=
- getCanonicalNestedNameSpecifier(T2MPType->getQualifier()))
+ if (T1MPType->getQualifier().getCanonical() !=
+ T2MPType->getQualifier().getCanonical())
return false;
T1 = T1MPType->getPointeeType();
T2 = T2MPType->getPointeeType();
@@ -7374,9 +7372,8 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name,
case TemplateName::DependentTemplate: {
DependentTemplateName *DTN = Name.getAsDependentTemplateName();
assert(DTN && "Non-dependent template names must refer to template decls.");
- NestedNameSpecifier *Qualifier = DTN->getQualifier();
- NestedNameSpecifier *CanonQualifier =
- getCanonicalNestedNameSpecifier(Qualifier);
+ NestedNameSpecifier Qualifier = DTN->getQualifier();
+ NestedNameSpecifier CanonQualifier = Qualifier.getCanonical();
if (Qualifier != CanonQualifier || !DTN->hasTemplateKeyword())
return getDependentTemplateName({CanonQualifier, DTN->getName(),
/*HasTemplateKeyword=*/true});
@@ -7593,38 +7590,40 @@ bool ASTContext::isSameDefaultTemplateArgument(const NamedDecl *X,
return hasSameTemplateName(TAX.getAsTemplate(), TAY.getAsTemplate());
}
-static bool isSameQualifier(const NestedNameSpecifier *X,
- const NestedNameSpecifier *Y) {
- if (X->getKind() != Y->getKind())
+static bool isSameQualifier(const NestedNameSpecifier X,
+ const NestedNameSpecifier Y) {
+ if (X == Y)
+ return true;
+ if (!X || !Y)
+ return false;
+
+ auto Kind = X.getKind();
+ if (Kind != Y.getKind())
return false;
// FIXME: For namespaces and types, we're permitted to check that the entity
// is named via the same tokens. We should probably do so.
- switch (X->getKind()) {
- case NestedNameSpecifier::Identifier:
- if (X->getAsIdentifier() != Y->getAsIdentifier())
- return false;
- break;
- case NestedNameSpecifier::Namespace:
- if (!declaresSameEntity(X->getAsNamespace(), Y->getAsNamespace()))
+ switch (Kind) {
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [NamespaceX, PrefixX] = X.getAsNamespaceAndPrefix();
+ auto [NamespaceY, PrefixY] = Y.getAsNamespaceAndPrefix();
+ if (!declaresSameEntity(NamespaceX->getNamespace(),
+ NamespaceY->getNamespace()))
return false;
- break;
- case NestedNameSpecifier::TypeSpec:
- if (X->getAsType()->getCanonicalTypeInternal() !=
- Y->getAsType()->getCanonicalTypeInternal())
+ return isSameQualifier(PrefixX, PrefixY);
+ }
+ case NestedNameSpecifier::Kind::Type: {
+ const auto *TX = X.getAsType(), *TY = Y.getAsType();
+ if (TX->getCanonicalTypeInternal() != TY->getCanonicalTypeInternal())
return false;
- break;
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
+ return isSameQualifier(TX->getPrefix(), TY->getPrefix());
+ }
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
return true;
}
-
- // Recurse into earlier portion of NNS, if any.
- auto *PX = X->getPrefix();
- auto *PY = Y->getPrefix();
- if (PX && PY)
- return isSameQualifier(PX, PY);
- return !PX && !PY;
+ llvm_unreachable("unhandled qualifier kind");
}
static bool hasSameCudaAttrs(const FunctionDecl *A, const FunctionDecl *B) {
@@ -8017,63 +8016,6 @@ bool ASTContext::isSameTemplateArgument(const TemplateArgument &Arg1,
llvm_unreachable("Unhandled template argument kind");
}
-NestedNameSpecifier *
-ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
- if (!NNS)
- return nullptr;
-
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- // Canonicalize the prefix but keep the identifier the same.
- return NestedNameSpecifier::Create(*this,
- getCanonicalNestedNameSpecifier(NNS->getPrefix()),
- NNS->getAsIdentifier());
-
- case NestedNameSpecifier::Namespace:
- // A namespace is canonical; build a nested-name-specifier with
- // this namespace and no prefix.
- return NestedNameSpecifier::Create(
- *this, nullptr, NNS->getAsNamespace()->getNamespace()->getFirstDecl());
-
- // The difference between TypeSpec and TypeSpecWithTemplate is that the
- // latter will have the 'template' keyword when printed.
- case NestedNameSpecifier::TypeSpec: {
- const Type *T = getCanonicalType(NNS->getAsType());
-
- // If we have some kind of dependent-named type (e.g., "typename T::type"),
- // break it apart into its prefix and identifier, then reconsititute those
- // as the canonical nested-name-specifier. This is required to canonicalize
- // a dependent nested-name-specifier involving typedefs of dependent-name
- // types, e.g.,
- // typedef typename T::type T1;
- // typedef typename T1::type T2;
- if (const auto *DNT = T->getAs<DependentNameType>())
- return NestedNameSpecifier::Create(*this, DNT->getQualifier(),
- DNT->getIdentifier());
- if (const auto *DTST = T->getAs<DependentTemplateSpecializationType>()) {
- const DependentTemplateStorage &DTN = DTST->getDependentTemplateName();
- QualType NewT = getDependentTemplateSpecializationType(
- ElaboratedTypeKeyword::None,
- {/*NNS=*/nullptr, DTN.getName(), /*HasTemplateKeyword=*/true},
- DTST->template_arguments(), /*IsCanonical=*/true);
- assert(NewT.isCanonical());
- NestedNameSpecifier *Prefix = DTN.getQualifier();
- if (!Prefix)
- Prefix = getCanonicalNestedNameSpecifier(NNS->getPrefix());
- return NestedNameSpecifier::Create(*this, Prefix, NewT.getTypePtr());
- }
- return NestedNameSpecifier::Create(*this, nullptr, T);
- }
-
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
- // The global specifier and __super specifer are canonical and unique.
- return NNS;
- }
-
- llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
-}
-
const ArrayType *ASTContext::getAsArrayType(QualType T) const {
// Handle the non-qualified case efficiently.
if (!T.hasLocalQualifiers()) {
@@ -10480,7 +10422,7 @@ TemplateName ASTContext::getAssumedTemplateName(DeclarationName Name) const {
/// Retrieve the template name that represents a qualified
/// template name such as \c std::vector.
-TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS,
+TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier Qualifier,
bool TemplateKeyword,
TemplateName Template) const {
assert(Template.getKind() == TemplateName::Template ||
@@ -13854,163 +13796,101 @@ static auto getCommonTemplateArguments(const ASTContext &Ctx,
}
template <class T>
-static ElaboratedTypeKeyword getCommonTypeKeyword(const T *X, const T *Y) {
- return X->getKeyword() == Y->getKeyword() ? X->getKeyword()
- : ElaboratedTypeKeyword::None;
+static ElaboratedTypeKeyword getCommonTypeKeyword(const T *X, const T *Y,
+ bool IsSame) {
+ ElaboratedTypeKeyword KX = X->getKeyword(), KY = Y->getKeyword();
+ if (KX == KY)
+ return KX;
+ KX = getCanonicalElaboratedTypeKeyword(KX);
+ assert(!IsSame || KX == getCanonicalElaboratedTypeKeyword(KY));
+ return KX;
}
/// Returns a NestedNameSpecifier which has only the common sugar
/// present in both NNS1 and NNS2.
-static NestedNameSpecifier *getCommonNNS(ASTContext &Ctx,
- NestedNameSpecifier *NNS1,
- NestedNameSpecifier *NNS2,
- bool IsSame) {
+static NestedNameSpecifier getCommonNNS(const ASTContext &Ctx,
+ NestedNameSpecifier NNS1,
+ NestedNameSpecifier NNS2, bool IsSame) {
// If they are identical, all sugar is common.
if (NNS1 == NNS2)
return NNS1;
- // IsSame implies both NNSes are equivalent.
- NestedNameSpecifier *Canon = Ctx.getCanonicalNestedNameSpecifier(NNS1);
- if (Canon != Ctx.getCanonicalNestedNameSpecifier(NNS2)) {
+ // IsSame implies both Qualifiers are equivalent.
+ NestedNameSpecifier Canon = NNS1.getCanonical();
+ if (Canon != NNS2.getCanonical()) {
assert(!IsSame && "Should be the same NestedNameSpecifier");
// If they are not the same, there is nothing to unify.
- // FIXME: It would be useful here if we could represent a canonically
- // empty NNS, which is not identical to an empty-as-written NNS.
- return nullptr;
+ return std::nullopt;
}
- NestedNameSpecifier *R = nullptr;
- NestedNameSpecifier::SpecifierKind K1 = NNS1->getKind(), K2 = NNS2->getKind();
- switch (K1) {
- case NestedNameSpecifier::SpecifierKind::Identifier: {
- assert(K2 == NestedNameSpecifier::SpecifierKind::Identifier);
- IdentifierInfo *II = NNS1->getAsIdentifier();
- assert(II == NNS2->getAsIdentifier());
- // For an identifier, the prefixes are significant, so they must be the
- // same.
- NestedNameSpecifier *P = ::getCommonNNS(Ctx, NNS1->getPrefix(),
- NNS2->getPrefix(), /*IsSame=*/true);
- R = NestedNameSpecifier::Create(Ctx, P, II);
- break;
- }
- case NestedNameSpecifier::SpecifierKind::Namespace: {
- assert(K2 == NestedNameSpecifier::SpecifierKind::Namespace);
- // The prefixes for namespaces are not significant, its declaration
- // identifies it uniquely.
- NestedNameSpecifier *P =
- ::getCommonNNS(Ctx, NNS1->getPrefix(), NNS2->getPrefix(),
- /*IsSame=*/false);
- NamespaceBaseDecl *Namespace1 = NNS1->getAsNamespace(),
- *Namespace2 = NNS2->getAsNamespace();
+ NestedNameSpecifier R = std::nullopt;
+ NestedNameSpecifier::Kind Kind = NNS1.getKind();
+ assert(Kind == NNS2.getKind());
+ switch (Kind) {
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace1, Prefix1] = NNS1.getAsNamespaceAndPrefix();
+ auto [Namespace2, Prefix2] = NNS2.getAsNamespaceAndPrefix();
auto Kind = Namespace1->getKind();
if (Kind != Namespace2->getKind() ||
(Kind == Decl::NamespaceAlias &&
!declaresSameEntity(Namespace1, Namespace2))) {
- R = NestedNameSpecifier::Create(
- Ctx, P,
+ R = NestedNameSpecifier(
+ Ctx,
::getCommonDeclChecked(Namespace1->getNamespace(),
- Namespace2->getNamespace()));
+ Namespace2->getNamespace()),
+ /*Prefix=*/std::nullopt);
break;
}
- R = NestedNameSpecifier::Create(
- Ctx, P, ::getCommonDeclChecked(Namespace1, Namespace2));
+ // The prefixes for namespaces are not significant, its declaration
+ // identifies it uniquely.
+ NestedNameSpecifier Prefix = ::getCommonNNS(Ctx, Prefix1, Prefix2,
+ /*IsSame=*/false);
+ R = NestedNameSpecifier(Ctx, ::getCommonDeclChecked(Namespace1, Namespace2),
+ Prefix);
break;
}
- case NestedNameSpecifier::SpecifierKind::TypeSpec: {
- // FIXME: See comment below, on Super case.
- if (K2 == NestedNameSpecifier::SpecifierKind::Super)
- return Ctx.getCanonicalNestedNameSpecifier(NNS1);
-
- assert(K2 == NestedNameSpecifier::SpecifierKind::TypeSpec);
-
- const Type *T1 = NNS1->getAsType(), *T2 = NNS2->getAsType();
- if (T1 == T2) {
- // If the types are indentical, then only the prefixes differ.
- // A well-formed NNS never has these types, as they have
- // special normalized forms.
- assert((!isa<DependentNameType, ElaboratedType>(T1)));
- // Only for a DependentTemplateSpecializationType the prefix
- // is actually significant. A DependentName, which would be another
- // plausible case, cannot occur here, as explained above.
- bool IsSame = isa<DependentTemplateSpecializationType>(T1);
- NestedNameSpecifier *P =
- ::getCommonNNS(Ctx, NNS1->getPrefix(), NNS2->getPrefix(), IsSame);
- R = NestedNameSpecifier::Create(Ctx, P, T1);
- break;
- }
- // TODO: Try to salvage the original prefix.
- // If getCommonSugaredType removed any top level sugar, the original prefix
- // is not applicable anymore.
+ case NestedNameSpecifier::Kind::Type: {
+ const Type *T1 = NNS1.getAsType(), *T2 = NNS2.getAsType();
const Type *T = Ctx.getCommonSugaredType(QualType(T1, 0), QualType(T2, 0),
/*Unqualified=*/true)
.getTypePtr();
-
- // A NestedNameSpecifier has special normalization rules for certain types.
- switch (T->getTypeClass()) {
- case Type::Elaborated: {
- // An ElaboratedType is stripped off, it's Qualifier becomes the prefix.
- auto *ET = cast<ElaboratedType>(T);
- R = NestedNameSpecifier::Create(Ctx, ET->getQualifier(),
- ET->getNamedType().getTypePtr());
- break;
- }
- case Type::DependentName: {
- // A DependentName is turned into an Identifier NNS.
- auto *DN = cast<DependentNameType>(T);
- R = NestedNameSpecifier::Create(Ctx, DN->getQualifier(),
- DN->getIdentifier());
- break;
- }
- case Type::DependentTemplateSpecialization: {
- // A DependentTemplateSpecializationType loses it's Qualifier, which
- // is turned into the prefix.
- auto *DTST = cast<DependentTemplateSpecializationType>(T);
- const DependentTemplateStorage &DTN = DTST->getDependentTemplateName();
- DependentTemplateStorage NewDTN(/*Qualifier=*/nullptr, DTN.getName(),
- DTN.hasTemplateKeyword());
- T = Ctx.getDependentTemplateSpecializationType(DTST->getKeyword(), NewDTN,
- DTST->template_arguments())
- .getTypePtr();
- R = NestedNameSpecifier::Create(Ctx, DTN.getQualifier(), T);
- break;
- }
- default:
- R = NestedNameSpecifier::Create(Ctx, /*Prefix=*/nullptr, T);
- break;
- }
+ R = NestedNameSpecifier(T);
break;
}
- case NestedNameSpecifier::SpecifierKind::Super:
+ case NestedNameSpecifier::Kind::MicrosoftSuper: {
// FIXME: Can __super even be used with data members?
// If it's only usable in functions, we will never see it here,
// unless we save the qualifiers used in function types.
// In that case, it might be possible NNS2 is a type,
// in which case we should degrade the result to
// a CXXRecordType.
- return Ctx.getCanonicalNestedNameSpecifier(NNS1);
- case NestedNameSpecifier::SpecifierKind::Global:
- // The global NNS is a singleton.
- assert(K2 == NestedNameSpecifier::SpecifierKind::Global &&
- "Global NNS cannot be equivalent to any other kind");
- llvm_unreachable("Global NestedNameSpecifiers did not compare equal");
- }
- assert(Ctx.getCanonicalNestedNameSpecifier(R) == Canon);
+ R = NestedNameSpecifier(getCommonDeclChecked(NNS1.getAsMicrosoftSuper(),
+ NNS2.getAsMicrosoftSuper()));
+ break;
+ }
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
+ // These are singletons.
+ llvm_unreachable("singletons did not compare equal");
+ }
+ assert(R.getCanonical() == Canon);
return R;
}
template <class T>
-static NestedNameSpecifier *getCommonQualifier(ASTContext &Ctx, const T *X,
- const T *Y, bool IsSame) {
+static NestedNameSpecifier getCommonQualifier(const ASTContext &Ctx, const T *X,
+ const T *Y, bool IsSame) {
return ::getCommonNNS(Ctx, X->getQualifier(), Y->getQualifier(), IsSame);
}
template <class T>
-static QualType getCommonElementType(ASTContext &Ctx, const T *X, const T *Y) {
+static QualType getCommonElementType(const ASTContext &Ctx, const T *X,
+ const T *Y) {
return Ctx.getCommonSugaredType(X->getElementType(), Y->getElementType());
}
template <class T>
-static QualType getCommonArrayElementType(ASTContext &Ctx, const T *X,
+static QualType getCommonArrayElementType(const ASTContext &Ctx, const T *X,
Qualifiers &QX, const T *Y,
Qualifiers &QY) {
QualType EX = X->getElementType(), EY = Y->getElementType();
diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp
index ee09b92715b93..d7fd411ab464c 100644
--- a/clang/lib/AST/ASTDiagnostic.cpp
+++ b/clang/lib/AST/ASTDiagnostic.cpp
@@ -458,13 +458,12 @@ void clang::FormatASTNodeDiagnosticArgument(
ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), Qualified);
break;
}
- case DiagnosticsEngine::ak_nestednamespec: {
- NestedNameSpecifier *NNS = reinterpret_cast<NestedNameSpecifier*>(Val);
- NNS->print(OS, Context.getPrintingPolicy(),
+ case DiagnosticsEngine::ak_nestednamespec:
+ NestedNameSpecifier::getFromVoidPointer(reinterpret_cast<void *>(Val))
+ .print(OS, Context.getPrintingPolicy(),
/*ResolveTemplateArguments=*/false,
/*PrintFinalScopeResOp=*/false);
break;
- }
case DiagnosticsEngine::ak_declcontext: {
DeclContext *DC = reinterpret_cast<DeclContext *> (Val);
assert(DC && "Should never have a null declaration context");
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 46d64b16a7624..ced24c4522db3 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -9972,46 +9972,34 @@ Expected<Stmt *> ASTImporter::Import(Stmt *FromS) {
return ToSOrErr;
}
-Expected<NestedNameSpecifier *>
-ASTImporter::Import(NestedNameSpecifier *FromNNS) {
- if (!FromNNS)
- return nullptr;
-
- NestedNameSpecifier *Prefix = nullptr;
- if (Error Err = importInto(Prefix, FromNNS->getPrefix()))
- return std::move(Err);
-
- switch (FromNNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- assert(FromNNS->getAsIdentifier() && "NNS should contain identifier.");
- return NestedNameSpecifier::Create(ToContext, Prefix,
- Import(FromNNS->getAsIdentifier()));
-
- case NestedNameSpecifier::Namespace:
- if (ExpectedDecl NSOrErr = Import(FromNNS->getAsNamespace())) {
- return NestedNameSpecifier::Create(ToContext, Prefix,
- cast<NamespaceBaseDecl>(*NSOrErr));
- } else
+Expected<NestedNameSpecifier> ASTImporter::Import(NestedNameSpecifier FromNNS) {
+ switch (FromNNS.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
+ return FromNNS;
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace, Prefix] = FromNNS.getAsNamespaceAndPrefix();
+ auto NSOrErr = Import(Namespace);
+ if (!NSOrErr)
return NSOrErr.takeError();
-
- case NestedNameSpecifier::Global:
- return NestedNameSpecifier::GlobalSpecifier(ToContext);
-
- case NestedNameSpecifier::Super:
- if (ExpectedDecl RDOrErr = Import(FromNNS->getAsRecordDecl()))
- return NestedNameSpecifier::SuperSpecifier(ToContext,
- cast<CXXRecordDecl>(*RDOrErr));
+ auto PrefixOrErr = Import(Prefix);
+ if (!PrefixOrErr)
+ return PrefixOrErr.takeError();
+ return NestedNameSpecifier(ToContext, cast<NamespaceBaseDecl>(*NSOrErr),
+ Prefix);
+ }
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ if (ExpectedDecl RDOrErr = Import(FromNNS.getAsMicrosoftSuper()))
+ return NestedNameSpecifier(cast<CXXRecordDecl>(*RDOrErr));
else
return RDOrErr.takeError();
-
- case NestedNameSpecifier::TypeSpec:
- if (ExpectedTypePtr TyOrErr = Import(FromNNS->getAsType())) {
- return NestedNameSpecifier::Create(ToContext, Prefix, *TyOrErr);
+ case NestedNameSpecifier::Kind::Type:
+ if (ExpectedTypePtr TyOrErr = Import(FromNNS.getAsType())) {
+ return NestedNameSpecifier(*TyOrErr);
} else {
return TyOrErr.takeError();
}
}
-
llvm_unreachable("Invalid nested name specifier kind");
}
@@ -10025,64 +10013,62 @@ ASTImporter::Import(NestedNameSpecifierLoc FromNNS) {
// serialization in reverse order.
while (NNS) {
NestedNames.push_back(NNS);
- NNS = NNS.getPrefix();
+ NNS = NNS.getAsNamespaceAndPrefix().Prefix;
}
NestedNameSpecifierLocBuilder Builder;
while (!NestedNames.empty()) {
NNS = NestedNames.pop_back_val();
- NestedNameSpecifier *Spec = nullptr;
+ NestedNameSpecifier Spec = std::nullopt;
if (Error Err = importInto(Spec, NNS.getNestedNameSpecifier()))
return std::move(Err);
- NestedNameSpecifier::SpecifierKind Kind = Spec->getKind();
+ NestedNameSpecifier::Kind Kind = Spec.getKind();
SourceLocation ToLocalBeginLoc, ToLocalEndLoc;
- if (Kind != NestedNameSpecifier::Super) {
+ if (Kind != NestedNameSpecifier::Kind::MicrosoftSuper) {
if (Error Err = importInto(ToLocalBeginLoc, NNS.getLocalBeginLoc()))
return std::move(Err);
- if (Kind != NestedNameSpecifier::Global)
+ if (Kind != NestedNameSpecifier::Kind::Global)
if (Error Err = importInto(ToLocalEndLoc, NNS.getLocalEndLoc()))
return std::move(Err);
}
switch (Kind) {
- case NestedNameSpecifier::Identifier:
- Builder.Extend(getToContext(), Spec->getAsIdentifier(), ToLocalBeginLoc,
- ToLocalEndLoc);
- break;
-
- case NestedNameSpecifier::Namespace:
- Builder.Extend(getToContext(), Spec->getAsNamespace(), ToLocalBeginLoc,
- ToLocalEndLoc);
+ case NestedNameSpecifier::Kind::Namespace:
+ Builder.Extend(getToContext(), Spec.getAsNamespaceAndPrefix().Namespace,
+ ToLocalBeginLoc, ToLocalEndLoc);
break;
- case NestedNameSpecifier::TypeSpec: {
+ case NestedNameSpecifier::Kind::Type: {
SourceLocation ToTLoc;
- if (Error Err = importInto(ToTLoc, NNS.getTypeLoc().getBeginLoc()))
+ if (Error Err = importInto(ToTLoc, NNS.castAsTypeLoc().getBeginLoc()))
return std::move(Err);
TypeSourceInfo *TSI = getToContext().getTrivialTypeSourceInfo(
- QualType(Spec->getAsType(), 0), ToTLoc);
- Builder.Extend(getToContext(), TSI->getTypeLoc(), ToLocalEndLoc);
+ QualType(Spec.getAsType(), 0), ToTLoc);
+ Builder.Make(getToContext(), TSI->getTypeLoc(), ToLocalEndLoc);
break;
}
- case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Kind::Global:
Builder.MakeGlobal(getToContext(), ToLocalBeginLoc);
break;
- case NestedNameSpecifier::Super: {
+ case NestedNameSpecifier::Kind::MicrosoftSuper: {
auto ToSourceRangeOrErr = Import(NNS.getSourceRange());
if (!ToSourceRangeOrErr)
return ToSourceRangeOrErr.takeError();
- Builder.MakeSuper(getToContext(), Spec->getAsRecordDecl(),
- ToSourceRangeOrErr->getBegin(),
- ToSourceRangeOrErr->getEnd());
+ Builder.MakeMicrosoftSuper(getToContext(), Spec.getAsMicrosoftSuper(),
+ ToSourceRangeOrErr->getBegin(),
+ ToSourceRangeOrErr->getEnd());
+ break;
+ }
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
}
- }
}
return Builder.getWithLocInContext(getToContext());
diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp
index f7c8c14d071e4..dd42a99ccd19c 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -110,8 +110,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
const TemplateArgumentLoc &Arg1,
const TemplateArgumentLoc &Arg2);
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- NestedNameSpecifier *NNS1,
- NestedNameSpecifier *NNS2);
+ NestedNameSpecifier NNS1,
+ NestedNameSpecifier NNS2);
static bool IsStructurallyEquivalent(const IdentifierInfo *Name1,
const IdentifierInfo *Name2);
@@ -577,35 +577,30 @@ static bool IsStructurallyEquivalent(const IdentifierInfo *Name1,
/// Determine whether two nested-name-specifiers are equivalent.
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- NestedNameSpecifier *NNS1,
- NestedNameSpecifier *NNS2) {
- if (NNS1->getKind() != NNS2->getKind())
- return false;
-
- NestedNameSpecifier *Prefix1 = NNS1->getPrefix(),
- *Prefix2 = NNS2->getPrefix();
- if ((bool)Prefix1 != (bool)Prefix2)
- return false;
-
- if (Prefix1)
- if (!IsStructurallyEquivalent(Context, Prefix1, Prefix2))
- return false;
-
- switch (NNS1->getKind()) {
- case NestedNameSpecifier::Identifier:
- return IsStructurallyEquivalent(NNS1->getAsIdentifier(),
- NNS2->getAsIdentifier());
- case NestedNameSpecifier::Namespace:
- return IsStructurallyEquivalent(Context, NNS1->getAsNamespace(),
- NNS2->getAsNamespace());
- case NestedNameSpecifier::TypeSpec:
- return IsStructurallyEquivalent(Context, QualType(NNS1->getAsType(), 0),
- QualType(NNS2->getAsType(), 0));
- case NestedNameSpecifier::Global:
+ NestedNameSpecifier NNS1,
+ NestedNameSpecifier NNS2) {
+ auto Kind = NNS1.getKind();
+ if (Kind != NNS2.getKind())
+ return false;
+ switch (Kind) {
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
return true;
- case NestedNameSpecifier::Super:
- return IsStructurallyEquivalent(Context, NNS1->getAsRecordDecl(),
- NNS2->getAsRecordDecl());
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace1, Prefix1] = NNS1.getAsNamespaceAndPrefix();
+ auto [Namespace2, Prefix2] = NNS2.getAsNamespaceAndPrefix();
+ if (!IsStructurallyEquivalent(Context,
+ const_cast<NamespaceBaseDecl *>(Namespace1),
+ const_cast<NamespaceBaseDecl *>(Namespace2)))
+ return false;
+ return IsStructurallyEquivalent(Context, Prefix1, Prefix2);
+ }
+ case NestedNameSpecifier::Kind::Type:
+ return IsStructurallyEquivalent(Context, QualType(NNS1.getAsType(), 0),
+ QualType(NNS2.getAsType(), 0));
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ return IsStructurallyEquivalent(Context, NNS1.getAsMicrosoftSuper(),
+ NNS2.getAsMicrosoftSuper());
}
return false;
}
@@ -613,9 +608,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
const DependentTemplateStorage &S1,
const DependentTemplateStorage &S2) {
- if (NestedNameSpecifier *NNS1 = S1.getQualifier(), *NNS2 = S2.getQualifier();
- !NNS1 != !NNS2 ||
- (NNS1 && !IsStructurallyEquivalent(Context, NNS1, NNS2)))
+ if (!IsStructurallyEquivalent(Context, S1.getQualifier(), S2.getQualifier()))
return false;
IdentifierOrOverloadedOperator IO1 = S1.getName(), IO2 = S2.getName();
diff --git a/clang/lib/AST/ASTTypeTraits.cpp b/clang/lib/AST/ASTTypeTraits.cpp
index 99916f523aa95..d2f7fdbbad04d 100644
--- a/clang/lib/AST/ASTTypeTraits.cpp
+++ b/clang/lib/AST/ASTTypeTraits.cpp
@@ -194,8 +194,8 @@ void DynTypedNode::print(llvm::raw_ostream &OS,
else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>())
NNS->print(OS, PP);
else if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>()) {
- if (const NestedNameSpecifier *NNS = NNSL->getNestedNameSpecifier())
- NNS->print(OS, PP);
+ if (NestedNameSpecifier NNS = NNSL->getNestedNameSpecifier())
+ NNS.print(OS, PP);
else
OS << "(empty NestedNameSpecifierLoc)";
} else if (const QualType *QT = get<QualType>())
@@ -234,13 +234,39 @@ void DynTypedNode::dump(llvm::raw_ostream &OS,
OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n";
}
-SourceRange DynTypedNode::getSourceRange() const {
+SourceRange DynTypedNode::getSourceRange(bool IncludeQualifier) const {
if (const CXXCtorInitializer *CCI = get<CXXCtorInitializer>())
return CCI->getSourceRange();
if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>())
return NNSL->getSourceRange();
- if (const TypeLoc *TL = get<TypeLoc>())
- return TL->getSourceRange();
+ if (const TypeLoc *TL = get<TypeLoc>()) {
+ if (IncludeQualifier)
+ return TL->getSourceRange();
+ switch (TL->getTypeLocClass()) {
+ case TypeLoc::DependentName:
+ return TL->castAs<DependentNameTypeLoc>().getNameLoc();
+ case TypeLoc::TemplateSpecialization: {
+ auto T = TL->castAs<TemplateSpecializationTypeLoc>();
+ return SourceRange(T.getTemplateNameLoc(), T.getEndLoc());
+ }
+ case TypeLoc::DependentTemplateSpecialization: {
+ auto T = TL->castAs<DependentTemplateSpecializationTypeLoc>();
+ return SourceRange(T.getTemplateNameLoc(), T.getEndLoc());
+ }
+ case TypeLoc::Enum:
+ case TypeLoc::Record:
+ case TypeLoc::InjectedClassName:
+ return TL->castAs<TagTypeLoc>().getNameLoc();
+ case TypeLoc::Typedef:
+ return TL->castAs<TypedefTypeLoc>().getNameLoc();
+ case TypeLoc::UnresolvedUsing:
+ return TL->castAs<UnresolvedUsingTypeLoc>().getNameLoc();
+ case TypeLoc::Using:
+ return TL->castAs<UsingTypeLoc>().getNameLoc();
+ default:
+ return TL->getSourceRange();
+ }
+ }
if (const Decl *D = get<Decl>())
return D->getSourceRange();
if (const Stmt *S = get<Stmt>())
diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp
index 698b956214309..e95bcd75634fa 100644
--- a/clang/lib/AST/ComputeDependence.cpp
+++ b/clang/lib/AST/ComputeDependence.cpp
@@ -500,9 +500,8 @@ ExprDependence clang::computeDependence(OMPIteratorExpr *E) {
ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) {
auto Deps = ExprDependence::None;
- if (auto *NNS = E->getQualifier())
- Deps |= toExprDependence(NNS->getDependence() &
- ~NestedNameSpecifierDependence::Dependent);
+ Deps |= toExprDependence(E->getQualifier().getDependence() &
+ ~NestedNameSpecifierDependence::Dependent);
if (auto *FirstArg = E->getTemplateArgs()) {
unsigned NumArgs = E->getNumTemplateArgs();
@@ -673,9 +672,8 @@ ExprDependence clang::computeDependence(MemberExpr *E) {
auto D = E->getBase()->getDependence();
D |= getDependenceInExpr(E->getMemberNameInfo());
- if (auto *NNS = E->getQualifier())
- D |= toExprDependence(NNS->getDependence() &
- ~NestedNameSpecifierDependence::Dependent);
+ D |= toExprDependence(E->getQualifier().getDependence() &
+ ~NestedNameSpecifierDependence::Dependent);
for (const auto &A : E->template_arguments())
D |= toExprDependence(A.getArgument().getDependence());
@@ -783,9 +781,8 @@ ExprDependence clang::computeDependence(CXXPseudoDestructorExpr *E) {
if (auto *ST = E->getScopeTypeInfo())
D |= turnTypeToValueDependence(
toExprDependenceAsWritten(ST->getType()->getDependence()));
- if (auto *Q = E->getQualifier())
- D |= toExprDependence(Q->getDependence() &
- ~NestedNameSpecifierDependence::Dependent);
+ D |= toExprDependence(E->getQualifier().getDependence() &
+ ~NestedNameSpecifierDependence::Dependent);
return D;
}
@@ -801,9 +798,8 @@ clang::computeDependence(OverloadExpr *E, bool KnownDependent,
if (KnownContainsUnexpandedParameterPack)
Deps |= ExprDependence::UnexpandedPack;
Deps |= getDependenceInExpr(E->getNameInfo());
- if (auto *Q = E->getQualifier())
- Deps |= toExprDependence(Q->getDependence() &
- ~NestedNameSpecifierDependence::Dependent);
+ Deps |= toExprDependence(E->getQualifier().getDependence() &
+ ~NestedNameSpecifierDependence::Dependent);
for (auto *D : E->decls()) {
if (D->getDeclContext()->isDependentContext() ||
isa<UnresolvedUsingValueDecl>(D))
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 891f0f3a0b45b..69ee5cc20710c 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1880,18 +1880,13 @@ bool NamedDecl::declarationReplaces(const NamedDecl *OldD,
// Using declarations can be replaced if they import the same name from the
// same context.
- if (const auto *UD = dyn_cast<UsingDecl>(this)) {
- ASTContext &Context = getASTContext();
- return Context.getCanonicalNestedNameSpecifier(UD->getQualifier()) ==
- Context.getCanonicalNestedNameSpecifier(
- cast<UsingDecl>(OldD)->getQualifier());
- }
- if (const auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(this)) {
- ASTContext &Context = getASTContext();
- return Context.getCanonicalNestedNameSpecifier(UUVD->getQualifier()) ==
- Context.getCanonicalNestedNameSpecifier(
- cast<UnresolvedUsingValueDecl>(OldD)->getQualifier());
- }
+ if (const auto *UD = dyn_cast<UsingDecl>(this))
+ return UD->getQualifier().getCanonical() ==
+
+ cast<UsingDecl>(OldD)->getQualifier().getCanonical();
+ if (const auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(this))
+ return UUVD->getQualifier().getCanonical() ==
+ cast<UnresolvedUsingValueDecl>(OldD)->getQualifier().getCanonical();
if (isRedeclarable(getKind())) {
if (getCanonicalDecl() != OldD->getCanonicalDecl())
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 7393233a64080..ca1d601370f23 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -708,11 +708,8 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
Proto += D->getQualifiedNameAsString();
} else {
llvm::raw_string_ostream OS(Proto);
- if (!Policy.SuppressScope) {
- if (const NestedNameSpecifier *NS = D->getQualifier()) {
- NS->print(OS, Policy);
- }
- }
+ if (!Policy.SuppressScope)
+ D->getQualifier().print(OS, Policy);
D->getNameInfo().printName(OS, Policy);
}
diff --git a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
index f5c42b8fec1bc..8821cd332e918 100644
--- a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
+++ b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
@@ -176,7 +176,7 @@ template <bool Const> struct Impl : RecursiveASTVisitor<Impl<Const>> {
return Visitor.TraverseLambdaCapture(LE, C, Init);
}
- bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
+ bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS) {
return Visitor.TraverseNestedNameSpecifier(NNS);
}
@@ -301,7 +301,6 @@ FORWARD_TO_BASE(TraverseAttr, Attr, *)
FORWARD_TO_BASE(TraverseConstructorInitializer, CXXCtorInitializer, *)
FORWARD_TO_BASE(TraverseDecl, Decl, *)
FORWARD_TO_BASE(TraverseStmt, Stmt, *)
-FORWARD_TO_BASE(TraverseNestedNameSpecifier, NestedNameSpecifier, *)
FORWARD_TO_BASE(TraverseTemplateInstantiations, ClassTemplateDecl, *)
FORWARD_TO_BASE(TraverseTemplateInstantiations, VarTemplateDecl, *)
FORWARD_TO_BASE(TraverseTemplateInstantiations, FunctionTemplateDecl, *)
@@ -318,8 +317,22 @@ FORWARD_TO_BASE_EXACT(TraverseTemplateArgument, const TemplateArgument &)
FORWARD_TO_BASE_EXACT(TraverseTemplateArguments, ArrayRef<TemplateArgument>)
FORWARD_TO_BASE_EXACT(TraverseTemplateArgumentLoc, const TemplateArgumentLoc &)
FORWARD_TO_BASE_EXACT(TraverseTemplateName, TemplateName)
-FORWARD_TO_BASE_EXACT(TraverseType, QualType)
-FORWARD_TO_BASE_EXACT(TraverseTypeLoc, TypeLoc)
+FORWARD_TO_BASE_EXACT(TraverseNestedNameSpecifier, NestedNameSpecifier)
+
+template <bool Const>
+bool DynamicRecursiveASTVisitorBase<Const>::TraverseType(
+ QualType T, bool TraverseQualifier) {
+ return Impl<Const>(*this).RecursiveASTVisitor<Impl<Const>>::TraverseType(
+ T, TraverseQualifier);
+}
+
+template <bool Const>
+bool DynamicRecursiveASTVisitorBase<Const>::TraverseTypeLoc(
+ TypeLoc TL, bool TraverseQualifier) {
+ return Impl<Const>(*this).RecursiveASTVisitor<Impl<Const>>::TraverseTypeLoc(
+ TL, TraverseQualifier);
+}
+
FORWARD_TO_BASE_EXACT(TraverseTypeConstraint, const TypeConstraint *)
FORWARD_TO_BASE_EXACT(TraverseObjCProtocolLoc, ObjCProtocolLoc)
FORWARD_TO_BASE_EXACT(TraverseNestedNameSpecifierLoc, NestedNameSpecifierLoc)
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 0d17fff38152a..21640c87ab424 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -1675,10 +1675,9 @@ CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() {
// It can't be dependent: after all, we were actually able to do the
// lookup.
CXXRecordDecl *Record = nullptr;
- auto *NNS = getQualifier();
- if (NNS && NNS->getKind() != NestedNameSpecifier::Super) {
- const Type *T = getQualifier()->getAsType();
- assert(T && "qualifier in member expression does not name type");
+ if (NestedNameSpecifier Qualifier = getQualifier();
+ Qualifier.getKind() == NestedNameSpecifier::Kind::Type) {
+ const Type *T = getQualifier().getAsType();
Record = T->getAsCXXRecordDecl();
assert(Record && "qualifier in member expression does not name record");
}
diff --git a/clang/lib/AST/ExprConcepts.cpp b/clang/lib/AST/ExprConcepts.cpp
index ac0e566fe6e72..36f910da49bfb 100644
--- a/clang/lib/AST/ExprConcepts.cpp
+++ b/clang/lib/AST/ExprConcepts.cpp
@@ -41,10 +41,10 @@ ConceptSpecializationExpr::ConceptSpecializationExpr(
assert(!Loc->getNestedNameSpecifierLoc() ||
(!Loc->getNestedNameSpecifierLoc()
.getNestedNameSpecifier()
- ->isInstantiationDependent() &&
+ .isInstantiationDependent() &&
!Loc->getNestedNameSpecifierLoc()
.getNestedNameSpecifier()
- ->containsUnexpandedParameterPack()));
+ .containsUnexpandedParameterPack()));
assert((!isValueDependent() || isInstantiationDependent()) &&
"should not be value-dependent");
}
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 0e5a0d5db8e8c..a3f8000e8c5f9 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -463,9 +463,7 @@ class CXXNameMangler {
void mangleVendorType(StringRef Name);
private:
-
bool mangleSubstitution(const NamedDecl *ND);
- bool mangleSubstitution(NestedNameSpecifier *NNS);
bool mangleSubstitution(QualType T);
bool mangleSubstitution(TemplateName Template);
bool mangleSubstitution(uintptr_t Ptr);
@@ -479,21 +477,15 @@ class CXXNameMangler {
addSubstitution(reinterpret_cast<uintptr_t>(ND));
}
- void addSubstitution(NestedNameSpecifier *NNS) {
- NNS = Context.getASTContext().getCanonicalNestedNameSpecifier(NNS);
-
- addSubstitution(reinterpret_cast<uintptr_t>(NNS));
- }
void addSubstitution(QualType T);
void addSubstitution(TemplateName Template);
void addSubstitution(uintptr_t Ptr);
// Destructive copy substitutions from other mangler.
void extendSubstitutions(CXXNameMangler* Other);
- void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
+ void mangleUnresolvedPrefix(NestedNameSpecifier Qualifier,
bool recursive = false);
- void mangleUnresolvedName(NestedNameSpecifier *qualifier,
- DeclarationName name,
+ void mangleUnresolvedName(NestedNameSpecifier Qualifier, DeclarationName name,
const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
unsigned KnownArity = UnknownArity);
@@ -542,7 +534,7 @@ class CXXNameMangler {
void mangleNestedNameWithClosurePrefix(GlobalDecl GD,
const NamedDecl *PrefixND,
const AbiTagList *AdditionalAbiTags);
- void manglePrefix(NestedNameSpecifier *qualifier);
+ void manglePrefix(NestedNameSpecifier Qualifier);
void manglePrefix(const DeclContext *DC, bool NoFunction=false);
void manglePrefix(QualType type);
void mangleTemplatePrefix(GlobalDecl GD, bool NoFunction=false);
@@ -588,12 +580,10 @@ class CXXNameMangler {
void mangleMemberExprBase(const Expr *base, bool isArrow);
void mangleMemberExpr(const Expr *base, bool isArrow,
- NestedNameSpecifier *qualifier,
- NamedDecl *firstQualifierLookup,
- DeclarationName name,
+ NestedNameSpecifier Qualifier,
+ NamedDecl *firstQualifierLookup, DeclarationName name,
const TemplateArgumentLoc *TemplateArgs,
- unsigned NumTemplateArgs,
- unsigned knownArity);
+ unsigned NumTemplateArgs, unsigned knownArity);
void mangleCastExpression(const Expr *E, StringRef CastEncoding);
void mangleInitListElements(const InitListExpr *InitList);
void mangleRequirement(SourceLocation RequiresExprLoc,
@@ -1360,7 +1350,7 @@ void CXXNameMangler::manglePrefix(QualType type) {
///
/// \param recursive - true if this is being called recursively,
/// i.e. if there is more prefix "to the right".
-void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
+void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier Qualifier,
bool recursive) {
// x, ::x
@@ -1377,8 +1367,11 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
// <unresolved-name> ::= [gs] sr <unresolved-qualifier-level>+ E
// <base-unresolved-name>
- switch (qualifier->getKind()) {
- case NestedNameSpecifier::Global:
+ switch (Qualifier.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
+
+ case NestedNameSpecifier::Kind::Global:
Out << "gs";
// We want an 'sr' unless this is the entire NNS.
@@ -1388,27 +1381,29 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
// We never want an 'E' here.
return;
- case NestedNameSpecifier::Super:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
llvm_unreachable("Can't mangle __super specifier");
- case NestedNameSpecifier::Namespace:
- if (qualifier->getPrefix())
- mangleUnresolvedPrefix(qualifier->getPrefix(),
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace, Prefix] = Qualifier.getAsNamespaceAndPrefix();
+ if (Prefix)
+ mangleUnresolvedPrefix(Prefix,
/*recursive*/ true);
else
Out << "sr";
- mangleSourceNameWithAbiTags(qualifier->getAsNamespace());
+ mangleSourceNameWithAbiTags(Namespace);
break;
+ }
- case NestedNameSpecifier::TypeSpec: {
- const Type *type = qualifier->getAsType();
+ case NestedNameSpecifier::Kind::Type: {
+ const Type *type = Qualifier.getAsType();
// We only want to use an unresolved-type encoding if this is one of:
// - a decltype
// - a template type parameter
// - a template template parameter with arguments
// In all of these cases, we should have no prefix.
- if (NestedNameSpecifier *Prefix = qualifier->getPrefix()) {
+ if (NestedNameSpecifier Prefix = type->getPrefix()) {
mangleUnresolvedPrefix(Prefix,
/*recursive=*/true);
} else {
@@ -1421,18 +1416,6 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
break;
}
-
- case NestedNameSpecifier::Identifier:
- // Member expressions can have these without prefixes.
- if (qualifier->getPrefix())
- mangleUnresolvedPrefix(qualifier->getPrefix(),
- /*recursive*/ true);
- else
- Out << "sr";
-
- mangleSourceName(qualifier->getAsIdentifier());
- // An Identifier has no type information, so we can't emit abi tags for it.
- break;
}
// If this was the innermost part of the NNS, and we fell out to
@@ -1444,10 +1427,11 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
/// Mangle an unresolved-name, which is generally used for names which
/// weren't resolved to specific entities.
void CXXNameMangler::mangleUnresolvedName(
- NestedNameSpecifier *qualifier, DeclarationName name,
+ NestedNameSpecifier Qualifier, DeclarationName name,
const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs,
unsigned knownArity) {
- if (qualifier) mangleUnresolvedPrefix(qualifier);
+ if (Qualifier)
+ mangleUnresolvedPrefix(Qualifier);
switch (name.getNameKind()) {
// <base-unresolved-name> ::= <simple-id>
case DeclarationName::Identifier:
@@ -2185,49 +2169,22 @@ void CXXNameMangler::mangleLambdaSig(const CXXRecordDecl *Lambda) {
Lambda->getLambdaStaticInvoker());
}
-void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) {
- switch (qualifier->getKind()) {
- case NestedNameSpecifier::Global:
+void CXXNameMangler::manglePrefix(NestedNameSpecifier Qualifier) {
+ switch (Qualifier.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
// nothing
return;
- case NestedNameSpecifier::Super:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
llvm_unreachable("Can't mangle __super specifier");
- case NestedNameSpecifier::Namespace:
- mangleName(qualifier->getAsNamespace()->getNamespace());
+ case NestedNameSpecifier::Kind::Namespace:
+ mangleName(Qualifier.getAsNamespaceAndPrefix().Namespace->getNamespace());
return;
- case NestedNameSpecifier::TypeSpec:
- if (NestedNameSpecifier *Prefix = qualifier->getPrefix()) {
- const auto *DTST =
- cast<DependentTemplateSpecializationType>(qualifier->getAsType());
- QualType NewT = getASTContext().getDependentTemplateSpecializationType(
- DTST->getKeyword(),
- {Prefix, DTST->getDependentTemplateName().getName(),
- /*HasTemplateKeyword=*/true},
- DTST->template_arguments(), /*IsCanonical=*/true);
- manglePrefix(NewT);
- return;
- }
- manglePrefix(QualType(qualifier->getAsType(), 0));
- return;
-
- case NestedNameSpecifier::Identifier:
- // Clang 14 and before did not consider this substitutable.
- bool Clang14Compat = isCompatibleWith(LangOptions::ClangABI::Ver14);
- if (!Clang14Compat && mangleSubstitution(qualifier))
- return;
-
- // Member expressions can have these without prefixes, but that
- // should end up in mangleUnresolvedPrefix instead.
- assert(qualifier->getPrefix());
- manglePrefix(qualifier->getPrefix());
-
- mangleSourceName(qualifier->getAsIdentifier());
-
- if (!Clang14Compat)
- addSubstitution(qualifier);
+ case NestedNameSpecifier::Kind::Type:
+ manglePrefix(QualType(Qualifier.getAsType(), 0));
return;
}
@@ -2287,8 +2244,7 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) {
if (!Clang11Compat && mangleSubstitution(Template))
return;
- if (NestedNameSpecifier *Qualifier = Dependent->getQualifier())
- manglePrefix(Qualifier);
+ manglePrefix(Dependent->getQualifier());
if (Clang11Compat && mangleSubstitution(Template))
return;
@@ -3892,16 +3848,10 @@ void CXXNameMangler::mangleType(const IncompleteArrayType *T) {
// <pointer-to-member-type> ::= M <class type> <member type>
void CXXNameMangler::mangleType(const MemberPointerType *T) {
Out << 'M';
- if (auto *RD = T->getMostRecentCXXRecordDecl()) {
+ if (auto *RD = T->getMostRecentCXXRecordDecl())
mangleCXXRecordDecl(RD);
- } else {
- NestedNameSpecifier *NNS = T->getQualifier();
- if (auto *II = NNS->getAsIdentifier())
- mangleType(getASTContext().getDependentNameType(
- ElaboratedTypeKeyword::None, NNS->getPrefix(), II));
- else
- manglePrefix(NNS);
- }
+ else
+ mangleType(QualType(T->getQualifier().getAsType(), 0));
QualType PointeeType = T->getPointeeType();
if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(PointeeType)) {
mangleType(FPT);
@@ -4785,9 +4735,8 @@ void CXXNameMangler::mangleMemberExprBase(const Expr *Base, bool IsArrow) {
}
/// Mangles a member expression.
-void CXXNameMangler::mangleMemberExpr(const Expr *base,
- bool isArrow,
- NestedNameSpecifier *qualifier,
+void CXXNameMangler::mangleMemberExpr(const Expr *base, bool isArrow,
+ NestedNameSpecifier Qualifier,
NamedDecl *firstQualifierLookup,
DeclarationName member,
const TemplateArgumentLoc *TemplateArgs,
@@ -5247,7 +5196,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
const auto *PDE = cast<CXXPseudoDestructorExpr>(E);
if (const Expr *Base = PDE->getBase())
mangleMemberExprBase(Base, PDE->isArrow());
- NestedNameSpecifier *Qualifier = PDE->getQualifier();
+ NestedNameSpecifier Qualifier = PDE->getQualifier();
if (TypeSourceInfo *ScopeInfo = PDE->getScopeTypeInfo()) {
if (Qualifier) {
mangleUnresolvedPrefix(Qualifier,
@@ -7023,14 +6972,6 @@ bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) {
return mangleSubstitution(reinterpret_cast<uintptr_t>(ND));
}
-bool CXXNameMangler::mangleSubstitution(NestedNameSpecifier *NNS) {
- assert(NNS->getKind() == NestedNameSpecifier::Identifier &&
- "mangleSubstitution(NestedNameSpecifier *) is only used for "
- "identifier nested name specifiers.");
- NNS = Context.getASTContext().getCanonicalNestedNameSpecifier(NNS);
- return mangleSubstitution(reinterpret_cast<uintptr_t>(NNS));
-}
-
/// Determine whether the given type has any qualifiers that are relevant for
/// substitutions.
static bool hasMangledSubstitutionQualifiers(QualType T) {
diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp
index 246e5322acb3d..b3f12a1cce2ec 100644
--- a/clang/lib/AST/JSONNodeDumper.cpp
+++ b/clang/lib/AST/JSONNodeDumper.cpp
@@ -898,9 +898,9 @@ void JSONNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD) {
void JSONNodeDumper::VisitUsingDecl(const UsingDecl *UD) {
std::string Name;
- if (const NestedNameSpecifier *NNS = UD->getQualifier()) {
+ if (NestedNameSpecifier Qualifier = UD->getQualifier()) {
llvm::raw_string_ostream SOS(Name);
- NNS->print(SOS, UD->getASTContext().getPrintingPolicy());
+ Qualifier.print(SOS, UD->getASTContext().getPrintingPolicy());
}
Name += UD->getNameAsString();
JOS.attribute("name", Name);
diff --git a/clang/lib/AST/NestedNameSpecifier.cpp b/clang/lib/AST/NestedNameSpecifier.cpp
index 872983f553e19..c6af91f5c0083 100644
--- a/clang/lib/AST/NestedNameSpecifier.cpp
+++ b/clang/lib/AST/NestedNameSpecifier.cpp
@@ -34,250 +34,67 @@
using namespace clang;
-NestedNameSpecifier *
-NestedNameSpecifier::FindOrInsert(const ASTContext &Context,
- const NestedNameSpecifier &Mockup) {
+const NamespaceAndPrefixStorage *
+NestedNameSpecifier::MakeNamespaceAndPrefixStorage(
+ const ASTContext &Ctx, const NamespaceBaseDecl *Namespace,
+ NestedNameSpecifier Prefix) {
llvm::FoldingSetNodeID ID;
- Mockup.Profile(ID);
+ NamespaceAndPrefixStorage::Profile(ID, Namespace, Prefix);
void *InsertPos = nullptr;
- NestedNameSpecifier *NNS
- = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
- if (!NNS) {
- NNS =
- new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(Mockup);
- Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
+ NamespaceAndPrefixStorage *S =
+ Ctx.NamespaceAndPrefixStorages.FindNodeOrInsertPos(ID, InsertPos);
+ if (!S) {
+ S = new (Ctx, alignof(NamespaceAndPrefixStorage))
+ NamespaceAndPrefixStorage(Namespace, Prefix);
+ Ctx.NamespaceAndPrefixStorages.InsertNode(S, InsertPos);
}
-
- return NNS;
-}
-
-NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context,
- NestedNameSpecifier *Prefix,
- const IdentifierInfo *II) {
- assert(II && "Identifier cannot be NULL");
- assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent");
-
- NestedNameSpecifier Mockup;
- Mockup.Prefix.setPointer(Prefix);
- Mockup.Prefix.setInt(StoredIdentifier);
- Mockup.Specifier = const_cast<IdentifierInfo *>(II);
- return FindOrInsert(Context, Mockup);
-}
-
-NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context,
- NestedNameSpecifier *Prefix,
- const NamespaceBaseDecl *NS) {
- assert(NS && "Namespace cannot be NULL");
- assert((!Prefix ||
- (Prefix->getAsType() == nullptr &&
- Prefix->getAsIdentifier() == nullptr)) &&
- "Broken nested name specifier");
- NestedNameSpecifier Mockup;
- Mockup.Prefix.setPointer(Prefix);
- Mockup.Prefix.setInt(StoredDecl);
- Mockup.Specifier = const_cast<NamespaceBaseDecl *>(NS);
- return FindOrInsert(Context, Mockup);
-}
-
-NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context,
- NestedNameSpecifier *Prefix,
- const Type *T) {
- assert(T && "Type cannot be NULL");
- NestedNameSpecifier Mockup;
- Mockup.Prefix.setPointer(Prefix);
- Mockup.Prefix.setInt(StoredTypeSpec);
- Mockup.Specifier = const_cast<Type*>(T);
- return FindOrInsert(Context, Mockup);
-}
-
-NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context,
- const IdentifierInfo *II) {
- assert(II && "Identifier cannot be NULL");
- NestedNameSpecifier Mockup;
- Mockup.Prefix.setPointer(nullptr);
- Mockup.Prefix.setInt(StoredIdentifier);
- Mockup.Specifier = const_cast<IdentifierInfo *>(II);
- return FindOrInsert(Context, Mockup);
-}
-
-NestedNameSpecifier *
-NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
- if (!Context.GlobalNestedNameSpecifier)
- Context.GlobalNestedNameSpecifier =
- new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier();
- return Context.GlobalNestedNameSpecifier;
-}
-
-NestedNameSpecifier *
-NestedNameSpecifier::SuperSpecifier(const ASTContext &Context,
- CXXRecordDecl *RD) {
- NestedNameSpecifier Mockup;
- Mockup.Prefix.setPointer(nullptr);
- Mockup.Prefix.setInt(StoredDecl);
- Mockup.Specifier = RD;
- return FindOrInsert(Context, Mockup);
+ return S;
}
-NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
- if (!Specifier)
- return Global;
-
- switch (Prefix.getInt()) {
- case StoredIdentifier:
- return Identifier;
-
- case StoredDecl: {
- NamedDecl *ND = static_cast<NamedDecl *>(Specifier);
- return isa<CXXRecordDecl>(ND) ? Super : Namespace;
- }
-
- case StoredTypeSpec:
- return TypeSpec;
- }
-
- llvm_unreachable("Invalid NNS Kind!");
-}
-
-/// Retrieve the namespace or namespace alias stored in this nested name
-/// specifier.
-NamespaceBaseDecl *NestedNameSpecifier::getAsNamespace() const {
- if (Prefix.getInt() == StoredDecl)
- return dyn_cast<NamespaceBaseDecl>(static_cast<NamedDecl *>(Specifier));
-
- return nullptr;
-}
-
-/// Retrieve the record declaration stored in this nested name specifier.
-CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
- switch (Prefix.getInt()) {
- case StoredIdentifier:
- return nullptr;
-
- case StoredDecl:
- return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier));
-
- case StoredTypeSpec:
- return getAsType()->getAsCXXRecordDecl();
+bool NestedNameSpecifier::isFullyQualified() const {
+ switch (getKind()) {
+ case NestedNameSpecifier::Kind::Global:
+ return true;
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ return false;
+ case NestedNameSpecifier::Kind::Namespace:
+ return getAsNamespaceAndPrefix().Prefix.isFullyQualified();
+ case NestedNameSpecifier::Kind::Type:
+ return getAsType()->getPrefix().isFullyQualified();
}
-
llvm_unreachable("Invalid NNS Kind!");
}
NestedNameSpecifierDependence NestedNameSpecifier::getDependence() const {
switch (getKind()) {
- case Identifier: {
- // Identifier specifiers always represent dependent types
- auto F = NestedNameSpecifierDependence::Dependent |
- NestedNameSpecifierDependence::Instantiation;
- // Prefix can contain unexpanded template parameters.
- if (getPrefix())
- return F | getPrefix()->getDependence();
- return F;
- }
-
- case Namespace:
- case Global:
- return NestedNameSpecifierDependence::None;
-
- case Super: {
- CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier);
- for (const auto &Base : RD->bases())
- if (Base.getType()->isDependentType())
- // FIXME: must also be instantiation-dependent.
- return NestedNameSpecifierDependence::Dependent;
+ case Kind::Null:
+ case Kind::Global:
+ case Kind::Namespace:
return NestedNameSpecifierDependence::None;
+ case Kind::MicrosoftSuper: {
+ CXXRecordDecl *RD = getAsMicrosoftSuper();
+ return RD->isDependentContext()
+ ? NestedNameSpecifierDependence::DependentInstantiation |
+ NestedNameSpecifierDependence::Dependent
+ : NestedNameSpecifierDependence::None;
}
-
- case TypeSpec: {
- NestedNameSpecifierDependence Dep =
- toNestedNameSpecifierDependendence(getAsType()->getDependence());
- if (NestedNameSpecifier *Prefix = getPrefix())
- Dep |=
- Prefix->getDependence() & ~NestedNameSpecifierDependence::Dependent;
- return Dep;
- }
+ case Kind::Type:
+ return toNestedNameSpecifierDependence(getAsType()->getDependence());
}
llvm_unreachable("Invalid NNS Kind!");
}
-bool NestedNameSpecifier::isDependent() const {
- return getDependence() & NestedNameSpecifierDependence::Dependent;
-}
-
-bool NestedNameSpecifier::isInstantiationDependent() const {
- return getDependence() & NestedNameSpecifierDependence::Instantiation;
-}
-
-bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
- return getDependence() & NestedNameSpecifierDependence::UnexpandedPack;
-}
-
-bool NestedNameSpecifier::containsErrors() const {
- return getDependence() & NestedNameSpecifierDependence::Error;
-}
-
-const Type *
-NestedNameSpecifier::translateToType(const ASTContext &Context) const {
- NestedNameSpecifier *Prefix = getPrefix();
- switch (getKind()) {
- case SpecifierKind::Identifier:
- return Context
- .getDependentNameType(ElaboratedTypeKeyword::None, Prefix,
- getAsIdentifier())
- .getTypePtr();
- case SpecifierKind::TypeSpec: {
- const Type *T = getAsType();
- switch (T->getTypeClass()) {
- case Type::DependentTemplateSpecialization: {
- const auto *DT = cast<DependentTemplateSpecializationType>(T);
- const DependentTemplateStorage &DTN = DT->getDependentTemplateName();
- return Context
- .getDependentTemplateSpecializationType(
- ElaboratedTypeKeyword::None,
- {Prefix, DTN.getName(), DTN.hasTemplateKeyword()},
- DT->template_arguments())
- .getTypePtr();
- }
- case Type::Record:
- case Type::TemplateSpecialization:
- case Type::Using:
- case Type::Enum:
- case Type::Typedef:
- case Type::UnresolvedUsing:
- return Context
- .getElaboratedType(ElaboratedTypeKeyword::None, Prefix,
- QualType(T, 0))
- .getTypePtr();
- default:
- assert(Prefix == nullptr && "unexpected type with elaboration");
- return T;
- }
- }
- case SpecifierKind::Global:
- case SpecifierKind::Namespace:
- case SpecifierKind::Super:
- // These are not representable as types.
- return nullptr;
- }
- llvm_unreachable("Unhandled SpecifierKind enum");
-}
-
/// Print this nested name specifier to the given output
/// stream.
void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
bool ResolveTemplateArguments,
bool PrintFinalScopeResOp) const {
- if (getPrefix())
- getPrefix()->print(OS, Policy);
-
switch (getKind()) {
- case Identifier:
- OS << getAsIdentifier()->getName();
- break;
-
- case Namespace: {
- NamespaceBaseDecl *Namespace = getAsNamespace();
+ case Kind::Namespace: {
+ auto [Namespace, Prefix] = getAsNamespaceAndPrefix();
+ Prefix.print(OS, Policy);
if (const auto *NS = dyn_cast<NamespaceDecl>(Namespace)) {
assert(!NS->isAnonymousNamespace());
OS << NS->getName();
@@ -286,134 +103,49 @@ void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
}
break;
}
-
- case Global:
+ case Kind::Global:
OS << "::";
return;
-
- case Super:
+ case Kind::MicrosoftSuper:
OS << "__super";
break;
-
- case TypeSpec: {
+ case Kind::Type: {
PrintingPolicy InnerPolicy(Policy);
- InnerPolicy.SuppressScope = true;
InnerPolicy.SuppressTagKeyword = true;
QualType(getAsType(), 0).print(OS, InnerPolicy);
break;
}
+ case Kind::Null:
+ return;
}
-
if (PrintFinalScopeResOp)
OS << "::";
}
-LLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const {
- dump(llvm::errs(), LO);
+LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream *OS,
+ const LangOptions *LO) const {
+ print(OS ? *OS : llvm::errs(), LO ? *LO : LangOptions());
}
-LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { dump(llvm::errs()); }
-
+LLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const {
+ dump(/*OS=*/nullptr, &LO);
+}
LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS) const {
- LangOptions LO;
- dump(OS, LO);
+ dump(&OS);
}
-
LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS,
const LangOptions &LO) const {
- print(OS, PrintingPolicy(LO));
-}
-
-unsigned
-NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
- assert(Qualifier && "Expected a non-NULL qualifier");
-
- // Location of the trailing '::'.
- unsigned Length = sizeof(SourceLocation::UIntTy);
-
- switch (Qualifier->getKind()) {
- case NestedNameSpecifier::Global:
- // Nothing more to add.
- break;
-
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::Super:
- // The location of the identifier or namespace name.
- Length += sizeof(SourceLocation::UIntTy);
- break;
-
- case NestedNameSpecifier::TypeSpec:
- // The "void*" that points at the TypeLoc data.
- // Note: the 'template' keyword is part of the TypeLoc.
- Length += sizeof(void *);
- break;
- }
-
- return Length;
-}
-
-unsigned
-NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
- unsigned Length = 0;
- for (; Qualifier; Qualifier = Qualifier->getPrefix())
- Length += getLocalDataLength(Qualifier);
- return Length;
-}
-
-/// Load a (possibly unaligned) source location from a given address
-/// and offset.
-static SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
- SourceLocation::UIntTy Raw;
- memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(Raw));
- return SourceLocation::getFromRawEncoding(Raw);
+ dump(&OS, &LO);
}
-/// Load a (possibly unaligned) pointer from a given address and
-/// offset.
-static void *LoadPointer(void *Data, unsigned Offset) {
- void *Result;
- memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
- return Result;
-}
-
-SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
+SourceLocation NestedNameSpecifierLoc::getBeginLoc() const {
if (!Qualifier)
- return SourceRange();
-
- unsigned Offset = getDataLength(Qualifier->getPrefix());
- switch (Qualifier->getKind()) {
- case NestedNameSpecifier::Global:
- return LoadSourceLocation(Data, Offset);
-
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::Super:
- return SourceRange(
- LoadSourceLocation(Data, Offset),
- LoadSourceLocation(Data, Offset + sizeof(SourceLocation::UIntTy)));
-
- case NestedNameSpecifier::TypeSpec: {
- // The "void*" that points at the TypeLoc data.
- // Note: the 'template' keyword is part of the TypeLoc.
- void *TypeData = LoadPointer(Data, Offset);
- TypeLoc TL(Qualifier->getAsType(), TypeData);
- return SourceRange(TL.getBeginLoc(),
- LoadSourceLocation(Data, Offset + sizeof(void*)));
- }
- }
+ return SourceLocation();
- llvm_unreachable("Invalid NNS Kind!");
-}
-
-TypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
- if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec)
- return TypeLoc();
-
- // The "void*" that points at the TypeLoc data.
- unsigned Offset = getDataLength(Qualifier->getPrefix());
- void *TypeData = LoadPointer(Data, Offset);
- return TypeLoc(Qualifier->getAsType(), TypeData);
+ NestedNameSpecifierLoc First = *this;
+ while (NestedNameSpecifierLoc Prefix = First.getAsNamespaceAndPrefix().Prefix)
+ First = Prefix;
+ return First.getLocalSourceRange().getBegin();
}
static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
@@ -515,10 +247,10 @@ operator=(const NestedNameSpecifierLocBuilder &Other) {
return *this;
}
-void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, TypeLoc TL,
- SourceLocation ColonColonLoc) {
- Representation =
- NestedNameSpecifier::Create(Context, Representation, TL.getTypePtr());
+void NestedNameSpecifierLocBuilder::Make(ASTContext &Context, TypeLoc TL,
+ SourceLocation ColonColonLoc) {
+ assert(!Representation);
+ Representation = NestedNameSpecifier(TL.getTypePtr());
// Push source-location info into the buffer.
SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
@@ -526,23 +258,10 @@ void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, TypeLoc TL,
}
void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
- IdentifierInfo *Identifier,
- SourceLocation IdentifierLoc,
- SourceLocation ColonColonLoc) {
- Representation = NestedNameSpecifier::Create(Context, Representation,
- Identifier);
-
- // Push source-location info into the buffer.
- SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
- SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
-}
-
-void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
- NamespaceBaseDecl *Namespace,
+ const NamespaceBaseDecl *Namespace,
SourceLocation NamespaceLoc,
SourceLocation ColonColonLoc) {
- Representation = NestedNameSpecifier::Create(Context, Representation,
- Namespace);
+ Representation = NestedNameSpecifier(Context, Namespace, Representation);
// Push source-location info into the buffer.
SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
@@ -552,60 +271,48 @@ void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,
SourceLocation ColonColonLoc) {
assert(!Representation && "Already have a nested-name-specifier!?");
- Representation = NestedNameSpecifier::GlobalSpecifier(Context);
+ Representation = NestedNameSpecifier::getGlobal();
// Push source-location info into the buffer.
SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
}
-void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context,
- CXXRecordDecl *RD,
- SourceLocation SuperLoc,
- SourceLocation ColonColonLoc) {
- Representation = NestedNameSpecifier::SuperSpecifier(Context, RD);
+void NestedNameSpecifierLocBuilder::MakeMicrosoftSuper(
+ ASTContext &Context, CXXRecordDecl *RD, SourceLocation SuperLoc,
+ SourceLocation ColonColonLoc) {
+ Representation = NestedNameSpecifier(RD);
// Push source-location info into the buffer.
SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity);
SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
}
-void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
- NestedNameSpecifier *Qualifier,
+void NestedNameSpecifierLocBuilder::PushTrivial(ASTContext &Context,
+ NestedNameSpecifier Qualifier,
SourceRange R) {
- Representation = Qualifier;
-
// Construct bogus (but well-formed) source information for the
// nested-name-specifier.
- BufferSize = 0;
- SmallVector<NestedNameSpecifier *, 4> Stack;
- for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
- Stack.push_back(NNS);
- while (!Stack.empty()) {
- NestedNameSpecifier *NNS = Stack.pop_back_val();
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Namespace:
- SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
- break;
-
- case NestedNameSpecifier::TypeSpec: {
- TypeSourceInfo *TSInfo
- = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
- R.getBegin());
- SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
- BufferCapacity);
- break;
- }
-
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
- break;
- }
-
- // Save the location of the '::'.
- SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),
- Buffer, BufferSize, BufferCapacity);
+ switch (Qualifier.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ return;
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [_1, Prefix] = Qualifier.getAsNamespaceAndPrefix();
+ PushTrivial(Context, Prefix, R.getBegin());
+ SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
+ break;
+ }
+ case NestedNameSpecifier::Kind::Type: {
+ TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(
+ QualType(Qualifier.getAsType(), 0), R.getBegin());
+ SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
+ BufferCapacity);
+ break;
+ }
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ break;
}
+ SaveSourceLocation(R.getEnd(), Buffer, BufferSize, BufferCapacity);
}
void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp
index c7a69d7c5ba42..fb95f58092c49 100644
--- a/clang/lib/AST/ODRHash.cpp
+++ b/clang/lib/AST/ODRHash.cpp
@@ -111,34 +111,28 @@ void ODRHash::AddDeclarationNameInfoImpl(DeclarationNameInfo NameInfo) {
}
}
-void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
- assert(NNS && "Expecting non-null pointer.");
- const auto *Prefix = NNS->getPrefix();
- AddBoolean(Prefix);
- if (Prefix) {
- AddNestedNameSpecifier(Prefix);
- }
- auto Kind = NNS->getKind();
- ID.AddInteger(Kind);
+void ODRHash::AddNestedNameSpecifier(NestedNameSpecifier NNS) {
+ auto Kind = NNS.getKind();
+ ID.AddInteger(llvm::to_underlying(Kind));
switch (Kind) {
- case NestedNameSpecifier::Identifier:
- AddIdentifierInfo(NNS->getAsIdentifier());
- break;
- case NestedNameSpecifier::Namespace:
- AddDecl(NNS->getAsNamespace());
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace, Prefix] = NNS.getAsNamespaceAndPrefix();
+ AddDecl(Namespace);
+ AddNestedNameSpecifier(Prefix);
break;
- case NestedNameSpecifier::TypeSpec:
- AddType(NNS->getAsType());
+ }
+ case NestedNameSpecifier::Kind::Type:
+ AddType(NNS.getAsType());
break;
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
break;
}
}
void ODRHash::AddDependentTemplateName(const DependentTemplateStorage &Name) {
- if (NestedNameSpecifier *NNS = Name.getQualifier())
- AddNestedNameSpecifier(NNS);
+ AddNestedNameSpecifier(Name.getQualifier());
if (IdentifierOrOverloadedOperator IO = Name.getName();
const IdentifierInfo *II = IO.getIdentifier())
AddIdentifierInfo(II);
@@ -156,8 +150,7 @@ void ODRHash::AddTemplateName(TemplateName Name) {
break;
case TemplateName::QualifiedTemplate: {
QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName();
- if (NestedNameSpecifier *NNS = QTN->getQualifier())
- AddNestedNameSpecifier(NNS);
+ AddNestedNameSpecifier(QTN->getQualifier());
AddBoolean(QTN->hasTemplateKeyword());
AddTemplateName(QTN->getUnderlyingTemplate());
break;
@@ -889,11 +882,8 @@ class ODRTypeVisitor : public TypeVisitor<ODRTypeVisitor> {
}
}
- void AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
- Hash.AddBoolean(NNS);
- if (NNS) {
- Hash.AddNestedNameSpecifier(NNS);
- }
+ void AddNestedNameSpecifier(NestedNameSpecifier NNS) {
+ Hash.AddNestedNameSpecifier(NNS);
}
void AddIdentifierInfo(const IdentifierInfo *II) {
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index de8b5996818de..588b0dcc6d7b8 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -2350,17 +2350,16 @@ void OMPClausePrinter::VisitOMPReductionClause(OMPReductionClause *Node) {
if (Node->getModifierLoc().isValid())
OS << getOpenMPSimpleClauseTypeName(OMPC_reduction, Node->getModifier())
<< ", ";
- NestedNameSpecifier *QualifierLoc =
+ NestedNameSpecifier Qualifier =
Node->getQualifierLoc().getNestedNameSpecifier();
OverloadedOperatorKind OOK =
Node->getNameInfo().getName().getCXXOverloadedOperator();
- if (QualifierLoc == nullptr && OOK != OO_None) {
+ if (!Qualifier && OOK != OO_None) {
// Print reduction identifier in C format
OS << getOperatorSpelling(OOK);
} else {
// Use C++ format
- if (QualifierLoc != nullptr)
- QualifierLoc->print(OS, Policy);
+ Qualifier.print(OS, Policy);
OS << Node->getNameInfo();
}
OS << ":";
@@ -2373,17 +2372,16 @@ void OMPClausePrinter::VisitOMPTaskReductionClause(
OMPTaskReductionClause *Node) {
if (!Node->varlist_empty()) {
OS << "task_reduction(";
- NestedNameSpecifier *QualifierLoc =
+ NestedNameSpecifier Qualifier =
Node->getQualifierLoc().getNestedNameSpecifier();
OverloadedOperatorKind OOK =
Node->getNameInfo().getName().getCXXOverloadedOperator();
- if (QualifierLoc == nullptr && OOK != OO_None) {
+ if (!Qualifier && OOK != OO_None) {
// Print reduction identifier in C format
OS << getOperatorSpelling(OOK);
} else {
// Use C++ format
- if (QualifierLoc != nullptr)
- QualifierLoc->print(OS, Policy);
+ Qualifier.print(OS, Policy);
OS << Node->getNameInfo();
}
OS << ":";
@@ -2395,17 +2393,16 @@ void OMPClausePrinter::VisitOMPTaskReductionClause(
void OMPClausePrinter::VisitOMPInReductionClause(OMPInReductionClause *Node) {
if (!Node->varlist_empty()) {
OS << "in_reduction(";
- NestedNameSpecifier *QualifierLoc =
+ NestedNameSpecifier Qualifier =
Node->getQualifierLoc().getNestedNameSpecifier();
OverloadedOperatorKind OOK =
Node->getNameInfo().getName().getCXXOverloadedOperator();
- if (QualifierLoc == nullptr && OOK != OO_None) {
+ if (!Qualifier && OOK != OO_None) {
// Print reduction identifier in C format
OS << getOperatorSpelling(OOK);
} else {
// Use C++ format
- if (QualifierLoc != nullptr)
- QualifierLoc->print(OS, Policy);
+ Qualifier.print(OS, Policy);
OS << Node->getNameInfo();
}
OS << ":";
@@ -2508,10 +2505,9 @@ template <typename T>
static void PrintMapper(raw_ostream &OS, T *Node,
const PrintingPolicy &Policy) {
OS << '(';
- NestedNameSpecifier *MapperNNS =
+ NestedNameSpecifier MapperNNS =
Node->getMapperQualifierLoc().getNestedNameSpecifier();
- if (MapperNNS)
- MapperNNS->print(OS, Policy);
+ MapperNNS.print(OS, Policy);
OS << Node->getMapperIdInfo() << ')';
}
diff --git a/clang/lib/AST/ParentMapContext.cpp b/clang/lib/AST/ParentMapContext.cpp
index 68dfe4d5d22cb..acc011cb2faa4 100644
--- a/clang/lib/AST/ParentMapContext.cpp
+++ b/clang/lib/AST/ParentMapContext.cpp
@@ -438,10 +438,12 @@ class ParentMapContext::ParentMap::ASTVisitor
DeclNode, DeclNode, [&] { return VisitorBase::TraverseDecl(DeclNode); },
&Map.PointerParents);
}
- bool TraverseTypeLoc(TypeLoc TypeLocNode) {
+ bool TraverseTypeLoc(TypeLoc TypeLocNode, bool TraverseQualifier = true) {
return TraverseNode(
TypeLocNode, DynTypedNode::create(TypeLocNode),
- [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); },
+ [&] {
+ return VisitorBase::TraverseTypeLoc(TypeLocNode, TraverseQualifier);
+ },
&Map.OtherParents);
}
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) {
diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp
index f5ae7686241e0..319becd8a5a98 100644
--- a/clang/lib/AST/QualTypeNames.cpp
+++ b/clang/lib/AST/QualTypeNames.cpp
@@ -24,10 +24,9 @@ namespace TypeName {
/// is requested.
/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
/// specifier "::" should be prepended or not.
-static NestedNameSpecifier *createNestedNameSpecifier(
- const ASTContext &Ctx,
- const NamespaceDecl *Namesp,
- bool WithGlobalNsPrefix);
+static NestedNameSpecifier
+createNestedNameSpecifier(const ASTContext &Ctx, const NamespaceDecl *Namesp,
+ bool WithGlobalNsPrefix);
/// Create a NestedNameSpecifier for TagDecl and its enclosing
/// scopes.
@@ -39,22 +38,24 @@ static NestedNameSpecifier *createNestedNameSpecifier(
/// qualified names.
/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
/// specifier "::" should be prepended or not.
-static NestedNameSpecifier *createNestedNameSpecifier(
- const ASTContext &Ctx, const TypeDecl *TD,
- bool FullyQualify, bool WithGlobalNsPrefix);
+static NestedNameSpecifier createNestedNameSpecifier(const ASTContext &Ctx,
+ const TypeDecl *TD,
+ bool FullyQualify,
+ bool WithGlobalNsPrefix);
-static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
- const ASTContext &Ctx, const Decl *decl,
- bool FullyQualified, bool WithGlobalNsPrefix);
+static NestedNameSpecifier
+createNestedNameSpecifierForScopeOf(const ASTContext &Ctx, const Decl *decl,
+ bool FullyQualified,
+ bool WithGlobalNsPrefix);
-static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier(
- const ASTContext &Ctx, NestedNameSpecifier *scope, bool WithGlobalNsPrefix);
+static NestedNameSpecifier getFullyQualifiedNestedNameSpecifier(
+ const ASTContext &Ctx, NestedNameSpecifier NNS, bool WithGlobalNsPrefix);
static bool getFullyQualifiedTemplateName(const ASTContext &Ctx,
TemplateName &TName,
bool WithGlobalNsPrefix) {
bool Changed = false;
- NestedNameSpecifier *NNS = nullptr;
+ NestedNameSpecifier NNS = std::nullopt;
TemplateDecl *ArgTDecl = TName.getAsTemplateDecl();
// ArgTDecl won't be NULL because we asserted that this isn't a
@@ -65,13 +66,13 @@ static bool getFullyQualifiedTemplateName(const ASTContext &Ctx,
if (QTName &&
!QTName->hasTemplateKeyword() &&
(NNS = QTName->getQualifier())) {
- NestedNameSpecifier *QNNS = getFullyQualifiedNestedNameSpecifier(
- Ctx, NNS, WithGlobalNsPrefix);
+ NestedNameSpecifier QNNS =
+ getFullyQualifiedNestedNameSpecifier(Ctx, NNS, WithGlobalNsPrefix);
if (QNNS != NNS) {
Changed = true;
NNS = QNNS;
} else {
- NNS = nullptr;
+ NNS = std::nullopt;
}
} else {
NNS = createNestedNameSpecifierForScopeOf(
@@ -116,76 +117,81 @@ static bool getFullyQualifiedTemplateArgument(const ASTContext &Ctx,
}
static const Type *getFullyQualifiedTemplateType(const ASTContext &Ctx,
- const Type *TypePtr,
+ const TagType *TSTRecord,
+ ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier Qualifier,
bool WithGlobalNsPrefix) {
- // DependentTemplateTypes exist within template declarations and
- // definitions. Therefore we shouldn't encounter them at the end of
- // a translation unit. If we do, the caller has made an error.
- assert(!isa<DependentTemplateSpecializationType>(TypePtr));
- // In case of template specializations, iterate over the arguments
- // and fully qualify them as well.
- if (const auto *TST = dyn_cast<const TemplateSpecializationType>(TypePtr)) {
- bool MightHaveChanged = false;
- SmallVector<TemplateArgument, 4> FQArgs;
- // Cheap to copy and potentially modified by
- // getFullyQualifedTemplateArgument.
- for (TemplateArgument Arg : TST->template_arguments()) {
- MightHaveChanged |= getFullyQualifiedTemplateArgument(
- Ctx, Arg, WithGlobalNsPrefix);
- FQArgs.push_back(Arg);
- }
+ // We are asked to fully qualify and we have a Record Type,
+ // which can point to a template instantiation with no sugar in any of
+ // its template argument, however we still need to fully qualify them.
+
+ const auto *TD = TSTRecord->getOriginalDecl();
+ const auto *TSTDecl = dyn_cast<ClassTemplateSpecializationDecl>(TD);
+ if (!TSTDecl)
+ return Ctx.getTagType(Keyword, Qualifier, TD, /*OwnsTag=*/false)
+ .getTypePtr();
+
+ const TemplateArgumentList &TemplateArgs = TSTDecl->getTemplateArgs();
+
+ bool MightHaveChanged = false;
+ SmallVector<TemplateArgument, 4> FQArgs;
+ for (unsigned int I = 0, E = TemplateArgs.size(); I != E; ++I) {
+ // cheap to copy and potentially modified by
+ // getFullyQualifedTemplateArgument
+ TemplateArgument Arg(TemplateArgs[I]);
+ MightHaveChanged |=
+ getFullyQualifiedTemplateArgument(Ctx, Arg, WithGlobalNsPrefix);
+ FQArgs.push_back(Arg);
+ }
- // If a fully qualified arg is different from the unqualified arg,
- // allocate new type in the AST.
- if (MightHaveChanged) {
- QualType QT = Ctx.getTemplateSpecializationType(
- TST->getTemplateName(), FQArgs,
- /*CanonicalArgs=*/{}, TST->desugar());
- // getTemplateSpecializationType returns a fully qualified
- // version of the specialization itself, so no need to qualify
- // it.
- return QT.getTypePtr();
- }
- } else if (const auto *TSTRecord = dyn_cast<const RecordType>(TypePtr)) {
- // We are asked to fully qualify and we have a Record Type,
- // which can point to a template instantiation with no sugar in any of
- // its template argument, however we still need to fully qualify them.
-
- if (const auto *TSTDecl =
- dyn_cast<ClassTemplateSpecializationDecl>(TSTRecord->getDecl())) {
- const TemplateArgumentList &TemplateArgs = TSTDecl->getTemplateArgs();
-
- bool MightHaveChanged = false;
- SmallVector<TemplateArgument, 4> FQArgs;
- for (unsigned int I = 0, E = TemplateArgs.size(); I != E; ++I) {
- // cheap to copy and potentially modified by
- // getFullyQualifedTemplateArgument
- TemplateArgument Arg(TemplateArgs[I]);
- MightHaveChanged |= getFullyQualifiedTemplateArgument(
- Ctx, Arg, WithGlobalNsPrefix);
- FQArgs.push_back(Arg);
- }
+ if (!MightHaveChanged)
+ return Ctx.getTagType(Keyword, Qualifier, TD, /*OwnsTag=*/false)
+ .getTypePtr();
+ // If a fully qualified arg is different from the unqualified arg,
+ // allocate new type in the AST.
+ TemplateName TN = Ctx.getQualifiedTemplateName(
+ Qualifier, /*TemplateKeyword=*/false,
+ TemplateName(TSTDecl->getSpecializedTemplate()));
+ QualType QT = Ctx.getTemplateSpecializationType(
+ Keyword, TN, FQArgs,
+ /*CanonicalArgs=*/{}, TSTRecord->getCanonicalTypeInternal());
+ // getTemplateSpecializationType returns a fully qualified
+ // version of the specialization itself, so no need to qualify
+ // it.
+ return QT.getTypePtr();
+}
- // If a fully qualified arg is different from the unqualified arg,
- // allocate new type in the AST.
- if (MightHaveChanged) {
- TemplateName TN(TSTDecl->getSpecializedTemplate());
- QualType QT = Ctx.getTemplateSpecializationType(
- TN, FQArgs,
- /*CanonicalArgs=*/{}, TSTRecord->getCanonicalTypeInternal());
- // getTemplateSpecializationType returns a fully qualified
- // version of the specialization itself, so no need to qualify
- // it.
- return QT.getTypePtr();
- }
- }
+static const Type *
+getFullyQualifiedTemplateType(const ASTContext &Ctx,
+ const TemplateSpecializationType *TST,
+ bool WithGlobalNsPrefix) {
+ TemplateName TName = TST->getTemplateName();
+ bool MightHaveChanged =
+ getFullyQualifiedTemplateName(Ctx, TName, WithGlobalNsPrefix);
+ SmallVector<TemplateArgument, 4> FQArgs;
+ // Cheap to copy and potentially modified by
+ // getFullyQualifedTemplateArgument.
+ for (TemplateArgument Arg : TST->template_arguments()) {
+ MightHaveChanged |=
+ getFullyQualifiedTemplateArgument(Ctx, Arg, WithGlobalNsPrefix);
+ FQArgs.push_back(Arg);
}
- return TypePtr;
+
+ if (!MightHaveChanged)
+ return TST;
+
+ QualType NewQT =
+ Ctx.getTemplateSpecializationType(TST->getKeyword(), TName, FQArgs,
+ /*CanonicalArgs=*/{}, TST->desugar());
+ // getTemplateSpecializationType returns a fully qualified
+ // version of the specialization itself, so no need to qualify
+ // it.
+ return NewQT.getTypePtr();
}
-static NestedNameSpecifier *createOuterNNS(const ASTContext &Ctx, const Decl *D,
- bool FullyQualify,
- bool WithGlobalNsPrefix) {
+static NestedNameSpecifier createOuterNNS(const ASTContext &Ctx, const Decl *D,
+ bool FullyQualify,
+ bool WithGlobalNsPrefix) {
const DeclContext *DC = D->getDeclContext();
if (const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
while (NS && NS->isInline()) {
@@ -195,71 +201,63 @@ static NestedNameSpecifier *createOuterNNS(const ASTContext &Ctx, const Decl *D,
if (NS && NS->getDeclName()) {
return createNestedNameSpecifier(Ctx, NS, WithGlobalNsPrefix);
}
- return nullptr; // no starting '::', no anonymous
- } else if (const auto *TD = dyn_cast<TagDecl>(DC)) {
- return createNestedNameSpecifier(Ctx, TD, FullyQualify, WithGlobalNsPrefix);
- } else if (const auto *TDD = dyn_cast<TypedefNameDecl>(DC)) {
- return createNestedNameSpecifier(
- Ctx, TDD, FullyQualify, WithGlobalNsPrefix);
- } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
- return NestedNameSpecifier::GlobalSpecifier(Ctx);
+ return std::nullopt; // no starting '::', no anonymous
}
- return nullptr; // no starting '::' if |WithGlobalNsPrefix| is false
+ if (const auto *TD = dyn_cast<TagDecl>(DC))
+ return createNestedNameSpecifier(Ctx, TD, FullyQualify, WithGlobalNsPrefix);
+ if (const auto *TDD = dyn_cast<TypedefNameDecl>(DC))
+ return createNestedNameSpecifier(Ctx, TDD, FullyQualify,
+ WithGlobalNsPrefix);
+ if (WithGlobalNsPrefix && DC->isTranslationUnit())
+ return NestedNameSpecifier::getGlobal();
+ return std::nullopt; // no starting '::' if |WithGlobalNsPrefix| is false
}
/// Return a fully qualified version of this name specifier.
-static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier(
- const ASTContext &Ctx, NestedNameSpecifier *Scope,
- bool WithGlobalNsPrefix) {
- switch (Scope->getKind()) {
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
- // Already fully qualified
- return Scope;
- case NestedNameSpecifier::Namespace:
- return TypeName::createNestedNameSpecifier(
- Ctx, Scope->getAsNamespace()->getNamespace(), WithGlobalNsPrefix);
- case NestedNameSpecifier::Identifier:
- // A function or some other construct that makes it un-namable
- // at the end of the TU. Skip the current component of the name,
- // but use the name of it's prefix.
- return getFullyQualifiedNestedNameSpecifier(
- Ctx, Scope->getPrefix(), WithGlobalNsPrefix);
- case NestedNameSpecifier::TypeSpec: {
- const Type *Type = Scope->getAsType();
- // Find decl context.
- const TagDecl *TD = nullptr;
- if (const TagType *TagDeclType = Type->getAs<TagType>()) {
- TD = TagDeclType->getDecl();
- } else {
- TD = Type->getAsCXXRecordDecl();
- }
- if (TD) {
- return TypeName::createNestedNameSpecifier(Ctx, TD,
- true /*FullyQualified*/,
- WithGlobalNsPrefix);
- } else if (const auto *TDD = dyn_cast<TypedefType>(Type)) {
- return TypeName::createNestedNameSpecifier(Ctx, TDD->getDecl(),
- true /*FullyQualified*/,
- WithGlobalNsPrefix);
- }
+static NestedNameSpecifier getFullyQualifiedNestedNameSpecifier(
+ const ASTContext &Ctx, NestedNameSpecifier Scope, bool WithGlobalNsPrefix) {
+ switch (Scope.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("can't fully qualify the empty nested name specifier");
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ // Already fully qualified
+ return Scope;
+ case NestedNameSpecifier::Kind::Namespace:
+ return TypeName::createNestedNameSpecifier(
+ Ctx, Scope.getAsNamespaceAndPrefix().Namespace->getNamespace(),
+ WithGlobalNsPrefix);
+ case NestedNameSpecifier::Kind::Type: {
+ const Type *Type = Scope.getAsType();
+ // Find decl context.
+ const TypeDecl *TD;
+ if (const TagType *TagDeclType = Type->getAs<TagType>())
+ TD = TagDeclType->getOriginalDecl();
+ else if (const auto *D = dyn_cast<TypedefType>(Type))
+ TD = D->getDecl();
+ else
return Scope;
- }
+ return TypeName::createNestedNameSpecifier(Ctx, TD, /*FullyQualify=*/true,
+ WithGlobalNsPrefix);
+ }
}
llvm_unreachable("bad NNS kind");
}
/// Create a nested name specifier for the declaring context of
/// the type.
-static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
- const ASTContext &Ctx, const Decl *Decl,
- bool FullyQualified, bool WithGlobalNsPrefix) {
+static NestedNameSpecifier
+createNestedNameSpecifierForScopeOf(const ASTContext &Ctx, const Decl *Decl,
+ bool FullyQualified,
+ bool WithGlobalNsPrefix) {
assert(Decl);
const DeclContext *DC = Decl->getDeclContext()->getRedeclContext();
const auto *Outer = dyn_cast<NamedDecl>(DC);
const auto *OuterNS = dyn_cast<NamespaceDecl>(DC);
- if (Outer && !(OuterNS && OuterNS->isAnonymousNamespace())) {
+ if (OuterNS && OuterNS->isAnonymousNamespace())
+ OuterNS = dyn_cast<NamespaceDecl>(OuterNS->getParent());
+ if (Outer) {
if (const auto *CxxDecl = dyn_cast<CXXRecordDecl>(DC)) {
if (ClassTemplateDecl *ClassTempl =
CxxDecl->getDescribedClassTemplate()) {
@@ -288,76 +286,80 @@ static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
Ctx, TD, FullyQualified, WithGlobalNsPrefix);
} else if (isa<TranslationUnitDecl>(Outer)) {
// Context is the TU. Nothing needs to be done.
- return nullptr;
+ return std::nullopt;
} else {
// Decl's context was neither the TU, a namespace, nor a
// TagDecl, which means it is a type local to a scope, and not
// accessible at the end of the TU.
- return nullptr;
+ return std::nullopt;
}
} else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
- return NestedNameSpecifier::GlobalSpecifier(Ctx);
+ return NestedNameSpecifier::getGlobal();
}
- return nullptr;
+ return std::nullopt;
}
/// Create a nested name specifier for the declaring context of
/// the type.
-static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
- const ASTContext &Ctx, const Type *TypePtr,
- bool FullyQualified, bool WithGlobalNsPrefix) {
- if (!TypePtr) return nullptr;
+static NestedNameSpecifier
+createNestedNameSpecifierForScopeOf(const ASTContext &Ctx, const Type *TypePtr,
+ bool FullyQualified,
+ bool WithGlobalNsPrefix) {
+ if (!TypePtr)
+ return std::nullopt;
Decl *Decl = nullptr;
// There are probably other cases ...
if (const auto *TDT = dyn_cast<TypedefType>(TypePtr)) {
Decl = TDT->getDecl();
} else if (const auto *TagDeclType = dyn_cast<TagType>(TypePtr)) {
- Decl = TagDeclType->getDecl();
+ Decl = TagDeclType->getOriginalDecl();
} else if (const auto *TST = dyn_cast<TemplateSpecializationType>(TypePtr)) {
Decl = TST->getTemplateName().getAsTemplateDecl();
} else {
Decl = TypePtr->getAsCXXRecordDecl();
}
- if (!Decl) return nullptr;
+ if (!Decl)
+ return std::nullopt;
return createNestedNameSpecifierForScopeOf(
Ctx, Decl, FullyQualified, WithGlobalNsPrefix);
}
-NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx,
- const NamespaceDecl *Namespace,
- bool WithGlobalNsPrefix) {
+static NestedNameSpecifier
+createNestedNameSpecifier(const ASTContext &Ctx, const NamespaceDecl *Namespace,
+ bool WithGlobalNsPrefix) {
while (Namespace && Namespace->isInline()) {
// Ignore inline namespace;
Namespace = dyn_cast<NamespaceDecl>(Namespace->getDeclContext());
}
- if (!Namespace) return nullptr;
+ if (!Namespace)
+ return std::nullopt;
- bool FullyQualified = true; // doesn't matter, DeclContexts are namespaces
- return NestedNameSpecifier::Create(
- Ctx,
- createOuterNNS(Ctx, Namespace, FullyQualified, WithGlobalNsPrefix),
- Namespace);
+ bool FullyQualify = true; // doesn't matter, DeclContexts are namespaces
+ return NestedNameSpecifier(
+ Ctx, Namespace,
+ createOuterNNS(Ctx, Namespace, FullyQualify, WithGlobalNsPrefix));
}
-NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx,
- const TypeDecl *TD,
- bool FullyQualify,
- bool WithGlobalNsPrefix) {
- const Type *TypePtr = TD->getTypeForDecl();
- if (isa<const TemplateSpecializationType>(TypePtr) ||
- isa<const RecordType>(TypePtr)) {
+NestedNameSpecifier createNestedNameSpecifier(const ASTContext &Ctx,
+ const TypeDecl *TD,
+ bool FullyQualify,
+ bool WithGlobalNsPrefix) {
+ const Type *TypePtr = Ctx.getTypeDeclType(TD).getTypePtr();
+ if (auto *RD = dyn_cast<TagType>(TypePtr)) {
// We are asked to fully qualify and we have a Record Type (which
// may point to a template specialization) or Template
// Specialization Type. We need to fully qualify their arguments.
-
- TypePtr = getFullyQualifiedTemplateType(Ctx, TypePtr, WithGlobalNsPrefix);
+ TypePtr = getFullyQualifiedTemplateType(
+ Ctx, RD, ElaboratedTypeKeyword::None,
+ createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix),
+ WithGlobalNsPrefix);
+ } else if (auto *TST = dyn_cast<TemplateSpecializationType>(TypePtr)) {
+ TypePtr = getFullyQualifiedTemplateType(Ctx, TST, WithGlobalNsPrefix);
}
-
- return NestedNameSpecifier::Create(
- Ctx, createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix), TypePtr);
+ return NestedNameSpecifier(TypePtr);
}
/// Return the fully qualified type, including fully-qualified
@@ -381,7 +383,7 @@ QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx,
Qualifiers Quals = QT.getQualifiers();
// Fully qualify the pointee and class types.
QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
- NestedNameSpecifier *Qualifier = getFullyQualifiedNestedNameSpecifier(
+ NestedNameSpecifier Qualifier = getFullyQualifiedNestedNameSpecifier(
Ctx, MPT->getQualifier(), WithGlobalNsPrefix);
QT = Ctx.getMemberPointerType(QT, Qualifier,
MPT->getMostRecentCXXRecordDecl());
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index a2c77883df419..afccba8778fd2 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -454,10 +454,7 @@ void StmtPrinter::VisitMSDependentExistsStmt(MSDependentExistsStmt *Node) {
else
OS << "__if_not_exists (";
- if (NestedNameSpecifier *Qualifier
- = Node->getQualifierLoc().getNestedNameSpecifier())
- Qualifier->print(OS, Policy);
-
+ Node->getQualifierLoc().getNestedNameSpecifier().print(OS, Policy);
OS << Node->getNameInfo() << ") ";
PrintRawCompoundStmt(Node->getSubStmt());
@@ -1309,8 +1306,7 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
TPOD->printAsExpr(OS, Policy);
return;
}
- if (NestedNameSpecifier *Qualifier = Node->getQualifier())
- Qualifier->print(OS, Policy);
+ Node->getQualifier().print(OS, Policy);
if (Node->hasTemplateKeyword())
OS << "template ";
@@ -1359,8 +1355,7 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
void StmtPrinter::VisitDependentScopeDeclRefExpr(
DependentScopeDeclRefExpr *Node) {
- if (NestedNameSpecifier *Qualifier = Node->getQualifier())
- Qualifier->print(OS, Policy);
+ Node->getQualifier().print(OS, Policy);
if (Node->hasTemplateKeyword())
OS << "template ";
OS << Node->getNameInfo();
@@ -1777,8 +1772,7 @@ void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
if (FD->isAnonymousStructOrUnion())
return;
- if (NestedNameSpecifier *Qualifier = Node->getQualifier())
- Qualifier->print(OS, Policy);
+ Node->getQualifier().print(OS, Policy);
if (Node->hasTemplateKeyword())
OS << "template ";
OS << Node->getMemberNameInfo();
@@ -2176,9 +2170,7 @@ void StmtPrinter::VisitMSPropertyRefExpr(MSPropertyRefExpr *Node) {
OS << "->";
else
OS << ".";
- if (NestedNameSpecifier *Qualifier =
- Node->getQualifierLoc().getNestedNameSpecifier())
- Qualifier->print(OS, Policy);
+ Node->getQualifierLoc().getNestedNameSpecifier().print(OS, Policy);
OS << Node->getPropertyDecl()->getDeclName();
}
@@ -2570,8 +2562,7 @@ void StmtPrinter::VisitCXXDependentScopeMemberExpr(
PrintExpr(Node->getBase());
OS << (Node->isArrow() ? "->" : ".");
}
- if (NestedNameSpecifier *Qualifier = Node->getQualifier())
- Qualifier->print(OS, Policy);
+ Node->getQualifier().print(OS, Policy);
if (Node->hasTemplateKeyword())
OS << "template ";
OS << Node->getMemberNameInfo();
@@ -2584,8 +2575,7 @@ void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
PrintExpr(Node->getBase());
OS << (Node->isArrow() ? "->" : ".");
}
- if (NestedNameSpecifier *Qualifier = Node->getQualifier())
- Qualifier->print(OS, Policy);
+ Node->getQualifier().print(OS, Policy);
if (Node->hasTemplateKeyword())
OS << "template ";
OS << Node->getMemberNameInfo();
@@ -2676,8 +2666,7 @@ void StmtPrinter::VisitCXXParenListInitExpr(CXXParenListInitExpr *Node) {
void StmtPrinter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
NestedNameSpecifierLoc NNS = E->getNestedNameSpecifierLoc();
- if (NNS)
- NNS.getNestedNameSpecifier()->print(OS, Policy);
+ NNS.getNestedNameSpecifier().print(OS, Policy);
if (E->getTemplateKWLoc().isValid())
OS << "template ";
OS << E->getFoundDecl()->getName();
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index c61450e19f1b6..59a18395d109c 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -65,7 +65,7 @@ namespace {
/// Visit a nested-name-specifier that occurs within an expression
/// or statement.
- virtual void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) = 0;
+ virtual void VisitNestedNameSpecifier(NestedNameSpecifier NNS) = 0;
/// Visit a template name that occurs within an expression or
/// statement.
@@ -167,10 +167,10 @@ namespace {
ID.AddPointer(II);
}
- void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) override {
+ void VisitNestedNameSpecifier(NestedNameSpecifier NNS) override {
if (Canonical)
- NNS = Context.getCanonicalNestedNameSpecifier(NNS);
- ID.AddPointer(NNS);
+ NNS = NNS.getCanonical();
+ NNS.Profile(ID);
}
void VisitTemplateName(TemplateName Name) override {
@@ -226,11 +226,10 @@ namespace {
void VisitTemplateName(TemplateName Name) override {
Hash.AddTemplateName(Name);
}
- void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) override {
- ID.AddBoolean(NNS);
- if (NNS) {
+ void VisitNestedNameSpecifier(NestedNameSpecifier NNS) override {
+ ID.AddBoolean(bool(NNS));
+ if (NNS)
Hash.AddNestedNameSpecifier(NNS);
- }
}
};
}
diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp
index 2fae4ab2b0ea3..700675840fd96 100644
--- a/clang/lib/AST/TemplateBase.cpp
+++ b/clang/lib/AST/TemplateBase.cpp
@@ -585,6 +585,29 @@ void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out,
// TemplateArgumentLoc Implementation
//===----------------------------------------------------------------------===//
+TemplateArgumentLoc::TemplateArgumentLoc(ASTContext &Ctx,
+ const TemplateArgument &Argument,
+ SourceLocation TemplateKWLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateNameLoc,
+ SourceLocation EllipsisLoc)
+ : Argument(Argument),
+ LocInfo(Ctx, TemplateKWLoc, QualifierLoc, TemplateNameLoc, EllipsisLoc) {
+ assert(Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion);
+ assert(QualifierLoc.getNestedNameSpecifier() ==
+ Argument.getAsTemplateOrTemplatePattern().getQualifier());
+}
+
+NestedNameSpecifierLoc TemplateArgumentLoc::getTemplateQualifierLoc() const {
+ if (Argument.getKind() != TemplateArgument::Template &&
+ Argument.getKind() != TemplateArgument::TemplateExpansion)
+ return NestedNameSpecifierLoc();
+ return NestedNameSpecifierLoc(
+ Argument.getAsTemplateOrTemplatePattern().getQualifier(),
+ LocInfo.getTemplate()->QualifierLocData);
+}
+
SourceRange TemplateArgumentLoc::getSourceRange() const {
switch (Argument.getKind()) {
case TemplateArgument::Expression:
@@ -691,10 +714,11 @@ const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
}
clang::TemplateArgumentLocInfo::TemplateArgumentLocInfo(
- ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc) {
+ ASTContext &Ctx, SourceLocation TemplateKWLoc,
+ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateNameLoc,
+ SourceLocation EllipsisLoc) {
TemplateTemplateArgLocInfo *Template = new (Ctx) TemplateTemplateArgLocInfo;
- Template->Qualifier = QualifierLoc.getNestedNameSpecifier();
+ Template->TemplateKwLoc = TemplateKWLoc;
Template->QualifierLocData = QualifierLoc.getOpaqueData();
Template->TemplateNameLoc = TemplateNameLoc;
Template->EllipsisLoc = EllipsisLoc;
diff --git a/clang/lib/AST/TemplateName.cpp b/clang/lib/AST/TemplateName.cpp
index 5b7abc4d038a9..c171516c38c10 100644
--- a/clang/lib/AST/TemplateName.cpp
+++ b/clang/lib/AST/TemplateName.cpp
@@ -289,10 +289,30 @@ QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
return dyn_cast_if_present<QualifiedTemplateName *>(Storage);
}
+QualifiedTemplateName *
+TemplateName::getAsAdjustedQualifiedTemplateName() const {
+ for (std::optional<TemplateName> Cur = *this; Cur;
+ Cur = Cur->desugar(/*IgnoreDeduced=*/true))
+ if (QualifiedTemplateName *N = Cur->getAsQualifiedTemplateName())
+ return N;
+ return nullptr;
+}
+
DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
return Storage.dyn_cast<DependentTemplateName *>();
}
+NestedNameSpecifier TemplateName::getQualifier() const {
+ for (std::optional<TemplateName> Cur = *this; Cur;
+ Cur = Cur->desugar(/*IgnoreDeduced=*/true)) {
+ if (DependentTemplateName *N = Cur->getAsDependentTemplateName())
+ return N->getQualifier();
+ if (QualifiedTemplateName *N = Cur->getAsQualifiedTemplateName())
+ return N->getQualifier();
+ }
+ return std::nullopt;
+}
+
UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {
if (Decl *D = Storage.dyn_cast<Decl *>())
if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
@@ -303,24 +323,21 @@ UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {
}
DependentTemplateStorage::DependentTemplateStorage(
- NestedNameSpecifier *Qualifier, IdentifierOrOverloadedOperator Name,
+ NestedNameSpecifier Qualifier, IdentifierOrOverloadedOperator Name,
bool HasTemplateKeyword)
: Qualifier(Qualifier, HasTemplateKeyword), Name(Name) {
- assert((!Qualifier || Qualifier->isDependent()) &&
+ assert((!Qualifier || Qualifier.isDependent()) &&
"Qualifier must be dependent");
}
TemplateNameDependence DependentTemplateStorage::getDependence() const {
- auto D = TemplateNameDependence::DependentInstantiation;
- if (NestedNameSpecifier *Qualifier = getQualifier())
- D |= toTemplateNameDependence(Qualifier->getDependence());
- return D;
+ return toTemplateNameDependence(getQualifier().getDependence()) |
+ TemplateNameDependence::DependentInstantiation;
}
void DependentTemplateStorage::print(raw_ostream &OS,
const PrintingPolicy &Policy) const {
- if (NestedNameSpecifier *NNS = getQualifier())
- NNS->print(OS, Policy);
+ getQualifier().print(OS, Policy);
if (hasTemplateKeyword())
OS << "template ";
@@ -363,16 +380,13 @@ TemplateNameDependence TemplateName::getDependence() const {
case NameKind::QualifiedTemplate: {
QualifiedTemplateName *S = getAsQualifiedTemplateName();
TemplateNameDependence D = S->getUnderlyingTemplate().getDependence();
- if (NestedNameSpecifier *NNS = S->getQualifier())
- D |= toTemplateNameDependence(NNS->getDependence());
+ D |= toTemplateNameDependence(S->getQualifier().getDependence());
return D;
}
case NameKind::DependentTemplate: {
DependentTemplateName *S = getAsDependentTemplateName();
- auto D = TemplateNameDependence::DependentInstantiation;
- if (NestedNameSpecifier *Qualifier = S->getQualifier())
- D |= toTemplateNameDependence(Qualifier->getDependence());
- return D;
+ return toTemplateNameDependence(S->getQualifier().getDependence()) |
+ TemplateNameDependence::DependentInstantiation;
}
case NameKind::SubstTemplateTemplateParm: {
auto *S = getAsSubstTemplateTemplateParm();
@@ -434,18 +448,20 @@ void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
Template = cast<TemplateDecl>(Template->getCanonicalDecl());
if (handleAnonymousTTP(Template, OS))
return;
- if (Qual == Qualified::None)
+ if (Qual == Qualified::None || Policy.SuppressScope) {
OS << *Template;
- else
- Template->printQualifiedName(OS, Policy);
+ } else {
+ PrintingPolicy NestedNamePolicy = Policy;
+ NestedNamePolicy.SuppressUnwrittenScope = true;
+ Template->printQualifiedName(OS, NestedNamePolicy);
+ }
} else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
if (Policy.PrintAsCanonical) {
QTN->getUnderlyingTemplate().print(OS, Policy, Qual);
return;
}
- if (NestedNameSpecifier *NNS = QTN->getQualifier();
- Qual != Qualified::None && NNS)
- NNS->print(OS, Policy);
+ if (Qual != Qualified::None)
+ QTN->getQualifier().print(OS, Policy);
if (QTN->hasTemplateKeyword())
OS << "template ";
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 8aa01bfaf9668..38924aff54634 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -1034,35 +1034,34 @@ void clang::TextNodeDumper::dumpTemplateSpecializationKind(
}
}
-void clang::TextNodeDumper::dumpNestedNameSpecifier(const NestedNameSpecifier *NNS) {
+void clang::TextNodeDumper::dumpNestedNameSpecifier(NestedNameSpecifier NNS) {
if (!NNS)
return;
AddChild([=] {
OS << "NestedNameSpecifier";
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- OS << " Identifier";
- OS << " '" << NNS->getAsIdentifier()->getName() << "'";
- break;
- case NestedNameSpecifier::Namespace:
+ switch (NNS.getKind()) {
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace, Prefix] = NNS.getAsNamespaceAndPrefix();
OS << " "; // "Namespace" is printed as the decl kind.
- dumpBareDeclRef(NNS->getAsNamespace());
+ dumpBareDeclRef(Namespace);
+ dumpNestedNameSpecifier(Prefix);
break;
- case NestedNameSpecifier::TypeSpec:
+ }
+ case NestedNameSpecifier::Kind::Type:
OS << " TypeSpec";
- dumpType(QualType(NNS->getAsType(), 0));
+ dumpType(QualType(NNS.getAsType(), 0));
break;
- case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Kind::Global:
OS << " Global";
break;
- case NestedNameSpecifier::Super:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
OS << " Super";
break;
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
}
-
- dumpNestedNameSpecifier(NNS->getPrefix());
});
}
@@ -2801,8 +2800,7 @@ void TextNodeDumper::VisitTemplateTemplateParmDecl(
void TextNodeDumper::VisitUsingDecl(const UsingDecl *D) {
OS << ' ';
- if (D->getQualifier())
- D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
+ D->getQualifier().print(OS, D->getASTContext().getPrintingPolicy());
OS << D->getDeclName();
dumpNestedNameSpecifier(D->getQualifier());
}
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index d756d22645156..2726d820cae20 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -1959,6 +1959,35 @@ Type::getAsNonAliasTemplateSpecializationType() const {
return TST;
}
+NestedNameSpecifier Type::getPrefix() const {
+ switch (getTypeClass()) {
+ case Type::DependentName:
+ return cast<DependentNameType>(this)->getQualifier();
+ case Type::TemplateSpecialization: {
+ QualifiedTemplateName *S = cast<TemplateSpecializationType>(this)
+ ->getTemplateName()
+ .getAsAdjustedQualifiedTemplateName();
+ return S ? S->getQualifier() : std::nullopt;
+ }
+ case Type::DependentTemplateSpecialization:
+ return cast<DependentTemplateSpecializationType>(this)
+ ->getDependentTemplateName()
+ .getQualifier();
+ case Type::Enum:
+ case Type::Record:
+ case Type::InjectedClassName:
+ return cast<TagType>(this)->getQualifier();
+ case Type::Typedef:
+ return cast<TypedefType>(this)->getQualifier();
+ case Type::UnresolvedUsing:
+ return cast<UnresolvedUsingType>(this)->getQualifier();
+ case Type::Using:
+ return cast<UsingType>(this)->getQualifier();
+ default:
+ return std::nullopt;
+ }
+}
+
bool Type::hasAttr(attr::Kind AK) const {
const Type *Cur = this;
while (const auto *AT = Cur->getAs<AttributedType>()) {
@@ -5435,16 +5464,16 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) {
bool MemberPointerType::isSugared() const {
CXXRecordDecl *D1 = getMostRecentCXXRecordDecl(),
- *D2 = getQualifier()->getAsRecordDecl();
+ *D2 = getQualifier().getAsRecordDecl();
assert(!D1 == !D2);
return D1 != D2 && D1->getCanonicalDecl() != D2->getCanonicalDecl();
}
void MemberPointerType::Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
- const NestedNameSpecifier *Qualifier,
+ const NestedNameSpecifier Qualifier,
const CXXRecordDecl *Cls) {
ID.AddPointer(Pointee.getAsOpaquePtr());
- ID.AddPointer(Qualifier);
+ Qualifier.Profile(ID);
if (Cls)
ID.AddPointer(Cls->getCanonicalDecl());
}
diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp
index 291a63800a910..83099a74aa7b5 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -471,6 +471,134 @@ TypeLoc TypeLoc::findExplicitQualifierLoc() const {
return {};
}
+NestedNameSpecifierLoc TypeLoc::getPrefix() const {
+ switch (getTypeLocClass()) {
+ case TypeLoc::DependentName:
+ return castAs<DependentNameTypeLoc>().getQualifierLoc();
+ case TypeLoc::TemplateSpecialization:
+ return castAs<TemplateSpecializationTypeLoc>().getQualifierLoc();
+ case TypeLoc::DependentTemplateSpecialization:
+ return castAs<DependentTemplateSpecializationTypeLoc>().getQualifierLoc();
+ case TypeLoc::DeducedTemplateSpecialization:
+ return castAs<DeducedTemplateSpecializationTypeLoc>().getQualifierLoc();
+ case TypeLoc::Enum:
+ case TypeLoc::Record:
+ case TypeLoc::InjectedClassName:
+ return castAs<TagTypeLoc>().getQualifierLoc();
+ case TypeLoc::Typedef:
+ return castAs<TypedefTypeLoc>().getQualifierLoc();
+ case TypeLoc::UnresolvedUsing:
+ return castAs<UnresolvedUsingTypeLoc>().getQualifierLoc();
+ case TypeLoc::Using:
+ return castAs<UsingTypeLoc>().getQualifierLoc();
+ default:
+ return NestedNameSpecifierLoc();
+ }
+}
+
+SourceLocation TypeLoc::getNonPrefixBeginLoc() const {
+ switch (getTypeLocClass()) {
+ case TypeLoc::TemplateSpecialization: {
+ auto TL = castAs<TemplateSpecializationTypeLoc>();
+ SourceLocation Loc = TL.getTemplateKeywordLoc();
+ if (!Loc.isValid())
+ Loc = TL.getTemplateNameLoc();
+ return Loc;
+ }
+ case TypeLoc::DependentTemplateSpecialization: {
+ auto TL = castAs<DependentTemplateSpecializationTypeLoc>();
+ SourceLocation Loc = TL.getTemplateKeywordLoc();
+ if (!Loc.isValid())
+ Loc = TL.getTemplateNameLoc();
+ return Loc;
+ }
+ case TypeLoc::DeducedTemplateSpecialization: {
+ auto TL = castAs<DeducedTemplateSpecializationTypeLoc>();
+ SourceLocation Loc = TL.getTemplateKeywordLoc();
+ if (!Loc.isValid())
+ Loc = TL.getTemplateNameLoc();
+ return Loc;
+ }
+ case TypeLoc::DependentName:
+ return castAs<DependentNameTypeLoc>().getNameLoc();
+ case TypeLoc::Enum:
+ case TypeLoc::Record:
+ case TypeLoc::InjectedClassName:
+ return castAs<TagTypeLoc>().getNameLoc();
+ case TypeLoc::Typedef:
+ return castAs<TypedefTypeLoc>().getNameLoc();
+ case TypeLoc::UnresolvedUsing:
+ return castAs<UnresolvedUsingTypeLoc>().getNameLoc();
+ case TypeLoc::Using:
+ return castAs<UsingTypeLoc>().getNameLoc();
+ default:
+ return getBeginLoc();
+ }
+}
+
+SourceLocation TypeLoc::getNonElaboratedBeginLoc() const {
+ // For elaborated types (e.g. `struct a::A`) we want the portion after the
+ // `struct` but including the namespace qualifier, `a::`.
+ switch (getTypeLocClass()) {
+ case TypeLoc::Qualified:
+ return castAs<QualifiedTypeLoc>()
+ .getUnqualifiedLoc()
+ .getNonElaboratedBeginLoc();
+ case TypeLoc::TemplateSpecialization: {
+ auto T = castAs<TemplateSpecializationTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return T.getTemplateNameLoc();
+ }
+ case TypeLoc::DependentTemplateSpecialization: {
+ auto T = castAs<DependentTemplateSpecializationTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return T.getTemplateNameLoc();
+ }
+ case TypeLoc::DeducedTemplateSpecialization: {
+ auto T = castAs<DeducedTemplateSpecializationTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return T.getTemplateNameLoc();
+ }
+ case TypeLoc::DependentName: {
+ auto T = castAs<DependentNameTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return T.getNameLoc();
+ }
+ case TypeLoc::Enum:
+ case TypeLoc::Record:
+ case TypeLoc::InjectedClassName: {
+ auto T = castAs<TagTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return T.getNameLoc();
+ }
+ case TypeLoc::Typedef: {
+ auto T = castAs<TypedefTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return T.getNameLoc();
+ }
+ case TypeLoc::UnresolvedUsing: {
+ auto T = castAs<UnresolvedUsingTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return T.getNameLoc();
+ }
+ case TypeLoc::Using: {
+ auto T = castAs<UsingTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return T.getNameLoc();
+ }
+ default:
+ return getBeginLoc();
+ }
+}
+
void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context,
SourceLocation Loc) {
setNameLoc(Loc);
@@ -544,9 +672,9 @@ static void initializeElaboratedKeyword(TL T, SourceLocation Loc) {
: SourceLocation());
}
-static NestedNameSpecifierLoc
-initializeQualifier(ASTContext &Context, NestedNameSpecifier *Qualifier,
- SourceLocation Loc) {
+static NestedNameSpecifierLoc initializeQualifier(ASTContext &Context,
+ NestedNameSpecifier Qualifier,
+ SourceLocation Loc) {
if (!Qualifier)
return NestedNameSpecifierLoc();
NestedNameSpecifierLocBuilder Builder;
diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index b0fa7f4c95719..d43d1aec71b29 100644
--- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -122,15 +122,15 @@ class MatchChildASTVisitor
else if (const Stmt *S = DynNode.get<Stmt>())
traverse(*S);
else if (const NestedNameSpecifier *NNS =
- DynNode.get<NestedNameSpecifier>())
+ DynNode.get<NestedNameSpecifier>())
traverse(*NNS);
else if (const NestedNameSpecifierLoc *NNSLoc =
DynNode.get<NestedNameSpecifierLoc>())
traverse(*NNSLoc);
else if (const QualType *Q = DynNode.get<QualType>())
- traverse(*Q);
+ traverse(*Q, /*TraverseQualifier=*/true);
else if (const TypeLoc *T = DynNode.get<TypeLoc>())
- traverse(*T);
+ traverse(*T, /*TraverseQualifier=*/true);
else if (const auto *C = DynNode.get<CXXCtorInitializer>())
traverse(*C);
else if (const TemplateArgumentLoc *TALoc =
@@ -217,17 +217,17 @@ class MatchChildASTVisitor
if (!match(TypeLocNode.getType()))
return false;
// The TypeLoc is matched inside traverse.
- return traverse(TypeLocNode);
+ return traverse(TypeLocNode, TraverseQualifier);
}
- bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
+ bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS) {
ScopedIncrement ScopedDepth(&CurrentDepth);
- return (NNS == nullptr) || traverse(*NNS);
+ return !NNS || traverse(NNS);
}
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
if (!NNS)
return true;
ScopedIncrement ScopedDepth(&CurrentDepth);
- if (!match(*NNS.getNestedNameSpecifier()))
+ if (!match(NNS.getNestedNameSpecifier()))
return false;
return traverse(NNS);
}
@@ -340,15 +340,14 @@ class MatchChildASTVisitor
bool baseTraverse(const Stmt &StmtNode) {
return VisitorBase::TraverseStmt(const_cast<Stmt*>(&StmtNode));
}
- bool baseTraverse(QualType TypeNode) {
- return VisitorBase::TraverseType(TypeNode);
+ bool baseTraverse(QualType TypeNode, bool TraverseQualifier) {
+ return VisitorBase::TraverseType(TypeNode, TraverseQualifier);
}
- bool baseTraverse(TypeLoc TypeLocNode) {
- return VisitorBase::TraverseTypeLoc(TypeLocNode);
+ bool baseTraverse(TypeLoc TypeLocNode, bool TraverseQualifier) {
+ return VisitorBase::TraverseTypeLoc(TypeLocNode, TraverseQualifier);
}
- bool baseTraverse(const NestedNameSpecifier &NNS) {
- return VisitorBase::TraverseNestedNameSpecifier(
- const_cast<NestedNameSpecifier*>(&NNS));
+ bool baseTraverse(NestedNameSpecifier NNS) {
+ return VisitorBase::TraverseNestedNameSpecifier(NNS);
}
bool baseTraverse(NestedNameSpecifierLoc NNS) {
return VisitorBase::TraverseNestedNameSpecifierLoc(NNS);
@@ -501,9 +500,9 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
bool TraverseDecl(Decl *DeclNode);
bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr);
- bool TraverseType(QualType TypeNode);
- bool TraverseTypeLoc(TypeLoc TypeNode);
- bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
+ bool TraverseType(QualType TypeNode, bool TraverseQualifier = true);
+ bool TraverseTypeLoc(TypeLoc TypeNode, bool TraverseQualifier = true);
+ bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS);
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit);
bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL);
@@ -1530,11 +1529,12 @@ bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode,
// each TypeLoc.
match(TypeLocNode);
match(TypeLocNode.getType());
- return RecursiveASTVisitor<MatchASTVisitor>::TraverseTypeLoc(TypeLocNode);
+ return RecursiveASTVisitor<MatchASTVisitor>::TraverseTypeLoc(
+ TypeLocNode, TraverseQualifier);
}
-bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
- match(*NNS);
+bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier NNS) {
+ match(NNS);
return RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifier(NNS);
}
@@ -1548,7 +1548,7 @@ bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
// We only match the nested name specifier here (as opposed to traversing it)
// because the traversal is already done in the parallel "Loc"-hierarchy.
if (NNS.hasQualifier())
- match(*NNS.getNestedNameSpecifier());
+ match(NNS.getNestedNameSpecifier());
return
RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifierLoc(NNS);
}
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp
index 5560985af4de6..f9aff893eb0f0 100644
--- a/clang/lib/CodeGen/CGCXX.cpp
+++ b/clang/lib/CodeGen/CGCXX.cpp
@@ -278,14 +278,13 @@ static CGCallee BuildAppleKextVirtualCall(CodeGenFunction &CGF,
/// BuildAppleKextVirtualCall - This routine is to support gcc's kext ABI making
/// indirect call to virtual functions. It makes the call through indexing
/// into the vtable.
-CGCallee
-CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
- NestedNameSpecifier *Qual,
- llvm::Type *Ty) {
- assert((Qual->getKind() == NestedNameSpecifier::TypeSpec) &&
+CGCallee CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
+ NestedNameSpecifier Qual,
+ llvm::Type *Ty) {
+ assert(Qual.getKind() == NestedNameSpecifier::Kind::Type &&
"BuildAppleKextVirtualCall - bad Qual kind");
- const Type *QTy = Qual->getAsType();
+ const Type *QTy = Qual.getAsType();
QualType T = QualType(QTy, 0);
const RecordType *RT = T->getAs<RecordType>();
assert(RT && "BuildAppleKextVirtualCall - Qual type must be record");
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 70b12231d65a3..a92b89def6433 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -206,7 +206,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
}
bool HasQualifier = ME->hasQualifier();
- NestedNameSpecifier *Qualifier = HasQualifier ? ME->getQualifier() : nullptr;
+ NestedNameSpecifier Qualifier = ME->getQualifier();
bool IsArrow = ME->isArrow();
const Expr *Base = ME->getBase();
@@ -217,7 +217,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
const CallExpr *CE, const CXXMethodDecl *MD, ReturnValueSlot ReturnValue,
- bool HasQualifier, NestedNameSpecifier *Qualifier, bool IsArrow,
+ bool HasQualifier, NestedNameSpecifier Qualifier, bool IsArrow,
const Expr *Base, llvm::CallBase **CallOrInvoke) {
assert(isa<CXXMemberCallExpr>(CE) || isa<CXXOperatorCallExpr>(CE));
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 6822113e11b69..c33c215c03e01 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4560,7 +4560,7 @@ class CodeGenFunction : public CodeGenTypeCache {
ArrayRef<llvm::Value *> args);
CGCallee BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
- NestedNameSpecifier *Qual, llvm::Type *Ty);
+ NestedNameSpecifier Qual, llvm::Type *Ty);
CGCallee BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl *DD,
CXXDtorType Type,
@@ -4665,7 +4665,7 @@ class CodeGenFunction : public CodeGenTypeCache {
llvm::CallBase **CallOrInvoke = nullptr);
RValue EmitCXXMemberOrOperatorMemberCallExpr(
const CallExpr *CE, const CXXMethodDecl *MD, ReturnValueSlot ReturnValue,
- bool HasQualifier, NestedNameSpecifier *Qualifier, bool IsArrow,
+ bool HasQualifier, NestedNameSpecifier Qualifier, bool IsArrow,
const Expr *Base, llvm::CallBase **CallOrInvoke);
// Compute the object pointer.
Address EmitCXXMemberDataPointerAddress(
diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp
index 63118d6bd5f12..541af6d587174 100644
--- a/clang/lib/ExtractAPI/DeclarationFragments.cpp
+++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp
@@ -205,45 +205,39 @@ DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) {
// Build declaration fragments for NNS recursively so that we have the USR for
// every part in a qualified name, and also leaves the actual underlying type
// cleaner for its own fragment.
-DeclarationFragments
-DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS,
- ASTContext &Context,
- DeclarationFragments &After) {
+DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNNS(
+ NestedNameSpecifier NNS, ASTContext &Context, DeclarationFragments &After) {
DeclarationFragments Fragments;
- if (NNS->getPrefix())
- Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After));
-
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- Fragments.append(NNS->getAsIdentifier()->getName(),
- DeclarationFragments::FragmentKind::Identifier);
- break;
+ switch (NNS.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ return Fragments;
- case NestedNameSpecifier::Namespace: {
- const NamespaceBaseDecl *NS = NNS->getAsNamespace();
- if (const auto *Namespace = dyn_cast<NamespaceDecl>(NS);
- Namespace && Namespace->isAnonymousNamespace())
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace, Prefix] = NNS.getAsNamespaceAndPrefix();
+ Fragments.append(getFragmentsForNNS(Prefix, Context, After));
+ if (const auto *NS = dyn_cast<NamespaceDecl>(Namespace);
+ NS && NS->isAnonymousNamespace())
return Fragments;
SmallString<128> USR;
- index::generateUSRForDecl(NS, USR);
- Fragments.append(NS->getName(),
- DeclarationFragments::FragmentKind::Identifier, USR, NS);
+ index::generateUSRForDecl(Namespace, USR);
+ Fragments.append(Namespace->getName(),
+ DeclarationFragments::FragmentKind::Identifier, USR,
+ Namespace);
break;
}
- case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Kind::Global:
// The global specifier `::` at the beginning. No stored value.
break;
- case NestedNameSpecifier::Super:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
// Microsoft's `__super` specifier.
Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword);
break;
- case NestedNameSpecifier::TypeSpec: {
- const Type *T = NNS->getAsType();
+ case NestedNameSpecifier::Kind::Type: {
// FIXME: Handle C++ template specialization type
- Fragments.append(getFragmentsForType(T, Context, After));
+ Fragments.append(getFragmentsForType(NNS.getAsType(), Context, After));
break;
}
}
diff --git a/clang/lib/Index/IndexTypeSourceInfo.cpp b/clang/lib/Index/IndexTypeSourceInfo.cpp
index 2bc6f26d34368..9a699c3c896de 100644
--- a/clang/lib/Index/IndexTypeSourceInfo.cpp
+++ b/clang/lib/Index/IndexTypeSourceInfo.cpp
@@ -244,32 +244,28 @@ void IndexingContext::indexTypeLoc(TypeLoc TL,
TypeIndexer(*this, Parent, DC, isBase, isIBType).TraverseTypeLoc(TL);
}
-void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
- const NamedDecl *Parent,
- const DeclContext *DC) {
- if (!NNS)
- return;
-
- if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
- indexNestedNameSpecifierLoc(Prefix, Parent, DC);
-
+void IndexingContext::indexNestedNameSpecifierLoc(
+ NestedNameSpecifierLoc QualifierLoc, const NamedDecl *Parent,
+ const DeclContext *DC) {
if (!DC)
DC = Parent->getLexicalDeclContext();
- SourceLocation Loc = NNS.getLocalBeginLoc();
-
- switch (NNS.getNestedNameSpecifier()->getKind()) {
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
+ switch (NestedNameSpecifier Qualifier = QualifierLoc.getNestedNameSpecifier();
+ Qualifier.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
break;
- case NestedNameSpecifier::Namespace:
- handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
- Loc, Parent, DC, SymbolRoleSet());
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace, Prefix] = QualifierLoc.castAsNamespaceAndPrefix();
+ indexNestedNameSpecifierLoc(Prefix, Parent, DC);
+ handleReference(Namespace, QualifierLoc.getLocalBeginLoc(), Parent, DC,
+ SymbolRoleSet());
break;
+ }
- case NestedNameSpecifier::TypeSpec:
- indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
+ case NestedNameSpecifier::Kind::Type:
+ indexTypeLoc(QualifierLoc.castAsTypeLoc(), Parent, DC);
break;
}
}
diff --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp
index 5b1d1cb698231..9e69ca567e80c 100644
--- a/clang/lib/Index/USRGeneration.cpp
+++ b/clang/lib/Index/USRGeneration.cpp
@@ -653,14 +653,14 @@ bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {
}
static void printQualifier(llvm::raw_ostream &Out, const LangOptions &LangOpts,
- NestedNameSpecifier *NNS) {
+ NestedNameSpecifier NNS) {
// FIXME: Encode the qualifier, don't just print it.
PrintingPolicy PO(LangOpts);
PO.SuppressTagKeyword = true;
PO.SuppressUnwrittenScope = true;
PO.ConstantArraySizeAsWritten = false;
PO.AnonymousTagLocations = false;
- NNS->print(Out, PO);
+ NNS.print(Out, PO);
}
void USRGenerator::VisitType(QualType T) {
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 31392d1dd8d4b..b096d5ee296de 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -591,7 +591,7 @@ bool Parser::ParseUsingDeclarator(DeclaratorContext Context,
NextToken().isRegularKeywordAttribute() ||
NextToken().is(tok::kw___attribute)) &&
D.SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() &&
- D.SS.getScopeRep()->getKind() != NestedNameSpecifier::Namespace) {
+ D.SS.getScopeRep().getKind() != NestedNameSpecifier::Kind::Namespace) {
SourceLocation IdLoc = ConsumeToken();
ParsedType Type =
Actions.getInheritingConstructorName(D.SS, IdLoc, *LastII);
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index b58100c635677..6cbc48102bf73 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -1328,7 +1328,7 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename,
Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
Tok.getAnnotationRange(),
SS);
- if (SS.getScopeRep() && SS.getScopeRep()->isDependent()) {
+ if (SS.getScopeRep().isDependent()) {
RevertingTentativeParsingAction PA(*this);
ConsumeAnnotationToken();
ConsumeToken();
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index d1400cbfc884d..94b1099c4bb90 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -227,14 +227,11 @@ static bool hasRecursiveCallInPath(const FunctionDecl *FD, CFGBlock &Block) {
// Skip function calls which are qualified with a templated class.
if (const DeclRefExpr *DRE =
- dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreParenImpCasts())) {
- if (NestedNameSpecifier *NNS = DRE->getQualifier()) {
- if (NNS->getKind() == NestedNameSpecifier::TypeSpec &&
- isa<TemplateSpecializationType>(NNS->getAsType())) {
+ dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreParenImpCasts()))
+ if (NestedNameSpecifier NNS = DRE->getQualifier();
+ NNS.getKind() == NestedNameSpecifier::Kind::Type)
+ if (isa_and_nonnull<TemplateSpecializationType>(NNS.getAsType()))
continue;
- }
- }
- }
const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE);
if (!MCE || isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) ||
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index 3ea5aa55c1e94..8756ce5f0d850 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -59,19 +59,6 @@ void CXXScopeSpec::Make(ASTContext &Context, TypeLoc TL,
"NestedNameSpecifierLoc range computation incorrect");
}
-void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier,
- SourceLocation IdentifierLoc,
- SourceLocation ColonColonLoc) {
- Builder.Extend(Context, Identifier, IdentifierLoc, ColonColonLoc);
-
- if (Range.getBegin().isInvalid())
- Range.setBegin(IdentifierLoc);
- Range.setEnd(ColonColonLoc);
-
- assert(Range == Builder.getSourceRange() &&
- "NestedNameSpecifierLoc range computation incorrect");
-}
-
void CXXScopeSpec::Extend(ASTContext &Context, NamespaceBaseDecl *Namespace,
SourceLocation NamespaceLoc,
SourceLocation ColonColonLoc) {
@@ -95,10 +82,10 @@ void CXXScopeSpec::MakeGlobal(ASTContext &Context,
"NestedNameSpecifierLoc range computation incorrect");
}
-void CXXScopeSpec::MakeSuper(ASTContext &Context, CXXRecordDecl *RD,
- SourceLocation SuperLoc,
- SourceLocation ColonColonLoc) {
- Builder.MakeSuper(Context, RD, SuperLoc, ColonColonLoc);
+void CXXScopeSpec::MakeMicrosoftSuper(ASTContext &Context, CXXRecordDecl *RD,
+ SourceLocation SuperLoc,
+ SourceLocation ColonColonLoc) {
+ Builder.MakeMicrosoftSuper(Context, RD, SuperLoc, ColonColonLoc);
Range.setBegin(SuperLoc);
Range.setEnd(ColonColonLoc);
@@ -108,7 +95,7 @@ void CXXScopeSpec::MakeSuper(ASTContext &Context, CXXRecordDecl *RD,
}
void CXXScopeSpec::MakeTrivial(ASTContext &Context,
- NestedNameSpecifier *Qualifier, SourceRange R) {
+ NestedNameSpecifier Qualifier, SourceRange R) {
Builder.MakeTrivial(Context, Qualifier, R);
Range = R;
}
diff --git a/clang/lib/Sema/HeuristicResolver.cpp b/clang/lib/Sema/HeuristicResolver.cpp
index 5bd5d15c6709c..9c56dd356421e 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -44,7 +44,7 @@ class HeuristicResolverImpl {
resolveDependentNameType(const DependentNameType *DNT);
std::vector<const NamedDecl *> resolveTemplateSpecializationType(
const DependentTemplateSpecializationType *DTST);
- QualType resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS);
+ QualType resolveNestedNameSpecifierToType(NestedNameSpecifier NNS);
QualType getPointeeType(QualType T);
std::vector<const NamedDecl *>
lookupDependentName(CXXRecordDecl *RD, DeclarationName Name,
@@ -285,7 +285,7 @@ std::vector<const NamedDecl *> HeuristicResolverImpl::resolveMemberExpr(
// an instance method, it's represented as a CXXDependentScopeMemberExpr
// with `this` as the base expression as `X` as the qualifier
// (which could be valid if `X` names a base class after instantiation).
- if (NestedNameSpecifier *NNS = ME->getQualifier()) {
+ if (NestedNameSpecifier NNS = ME->getQualifier()) {
if (QualType QualifierType = resolveNestedNameSpecifierToType(NNS);
!QualifierType.isNull()) {
auto Decls =
@@ -341,7 +341,10 @@ HeuristicResolverImpl::resolveCalleeOfCallExpr(const CallExpr *CE) {
std::vector<const NamedDecl *> HeuristicResolverImpl::resolveUsingValueDecl(
const UnresolvedUsingValueDecl *UUVD) {
- return resolveDependentMember(QualType(UUVD->getQualifier()->getAsType(), 0),
+ NestedNameSpecifier Qualifier = UUVD->getQualifier();
+ if (Qualifier.getKind() != NestedNameSpecifier::Kind::Type)
+ return {};
+ return resolveDependentMember(QualType(Qualifier.getAsType(), 0),
UUVD->getNameInfo().getName(), ValueFilter);
}
@@ -392,23 +395,23 @@ QualType HeuristicResolverImpl::resolveExprToType(const Expr *E) {
}
QualType HeuristicResolverImpl::resolveNestedNameSpecifierToType(
- const NestedNameSpecifier *NNS) {
- if (!NNS)
- return QualType();
-
+ NestedNameSpecifier NNS) {
// The purpose of this function is to handle the dependent (Kind ==
// Identifier) case, but we need to recurse on the prefix because
// that may be dependent as well, so for convenience handle
// the TypeSpec cases too.
- switch (NNS->getKind()) {
- case NestedNameSpecifier::TypeSpec:
- return QualType(NNS->getAsType(), 0);
- case NestedNameSpecifier::Identifier: {
- return resolveDeclsToType(
- resolveDependentMember(
- resolveNestedNameSpecifierToType(NNS->getPrefix()),
- NNS->getAsIdentifier(), TypeFilter),
- Ctx);
+ switch (NNS.getKind()) {
+ case NestedNameSpecifier::Kind::Type: {
+ const auto *T = NNS.getAsType();
+ // FIXME: Should this handle the DependentTemplateSpecializationType as
+ // well?
+ if (const auto *DTN = dyn_cast<DependentNameType>(T))
+ return resolveDeclsToType(
+ resolveDependentMember(
+ resolveNestedNameSpecifierToType(DTN->getQualifier()),
+ DTN->getIdentifier(), TypeFilter),
+ Ctx);
+ return QualType(T, 0);
}
default:
break;
@@ -583,7 +586,7 @@ HeuristicResolver::resolveTemplateSpecializationType(
return HeuristicResolverImpl(Ctx).resolveTemplateSpecializationType(DTST);
}
QualType HeuristicResolver::resolveNestedNameSpecifierToType(
- const NestedNameSpecifier *NNS) const {
+ NestedNameSpecifier NNS) const {
return HeuristicResolverImpl(Ctx).resolveNestedNameSpecifierToType(NNS);
}
std::vector<const NamedDecl *> HeuristicResolver::lookupDependentName(
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index a82129821b884..45de8ff3ba264 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -51,18 +51,17 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
if (!SS.isSet() || SS.isInvalid())
return nullptr;
- NestedNameSpecifier *NNS = SS.getScopeRep();
- if (NNS->isDependent()) {
+ NestedNameSpecifier NNS = SS.getScopeRep();
+ if (NNS.isDependent()) {
// If this nested-name-specifier refers to the current
// instantiation, return its DeclContext.
if (CXXRecordDecl *Record = getCurrentInstantiationOf(NNS))
return Record;
if (EnteringContext) {
- const Type *NNSType = NNS->getAsType();
- if (!NNSType) {
+ if (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);
@@ -129,24 +128,25 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
return nullptr;
}
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- llvm_unreachable("Dependent nested-name-specifier has no DeclContext");
-
- case NestedNameSpecifier::Namespace:
- return NNS->getAsNamespace()->getNamespace();
+ switch (NNS.getKind()) {
+ case NestedNameSpecifier::Kind::Namespace:
+ return const_cast<NamespaceDecl *>(
+ NNS.getAsNamespaceAndPrefix().Namespace->getNamespace());
- case NestedNameSpecifier::TypeSpec: {
- const TagType *Tag = NNS->getAsType()->getAs<TagType>();
- assert(Tag && "Non-tag type in nested-name-specifier");
- return Tag->getDecl();
+ case NestedNameSpecifier::Kind::Type: {
+ auto *TD = NNS.getAsType()->getAsTagDecl();
+ assert(TD && "Non-tag type in nested-name-specifier");
+ return TD;
}
- case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Kind::Global:
return Context.getTranslationUnitDecl();
- case NestedNameSpecifier::Super:
- return NNS->getAsRecordDecl();
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ return NNS.getAsMicrosoftSuper();
+
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
}
llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
@@ -156,17 +156,17 @@ bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) {
if (!SS.isSet() || SS.isInvalid())
return false;
- return SS.getScopeRep()->isDependent();
+ return SS.getScopeRep().isDependent();
}
-CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) {
+CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier NNS) {
assert(getLangOpts().CPlusPlus && "Only callable in C++");
- assert(NNS->isDependent() && "Only dependent nested-name-specifier allowed");
+ assert(NNS.isDependent() && "Only dependent nested-name-specifier allowed");
- if (!NNS->getAsType())
+ if (NNS.getKind() != NestedNameSpecifier::Kind::Type)
return nullptr;
- QualType T = QualType(NNS->getAsType(), 0);
+ QualType T = QualType(NNS.getAsType(), 0);
return ::getCurrentInstantiationOf(T, CurContext);
}
@@ -301,7 +301,7 @@ bool Sema::ActOnSuperScopeSpecifier(SourceLocation SuperLoc,
return true;
}
- SS.MakeSuper(Context, RD, SuperLoc, ColonColonLoc);
+ SS.MakeMicrosoftSuper(Context, RD, SuperLoc, ColonColonLoc);
return false;
}
@@ -338,32 +338,42 @@ bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD,
if (IsExtension)
*IsExtension = true;
}
+ if (auto *TD = dyn_cast<TagDecl>(SD)) {
+ if (TD->isDependentType())
+ return true;
+ } else if (Context.getCanonicalTypeDeclType(cast<TypeDecl>(SD))
+ ->isDependentType()) {
+ return true;
+ }
return false;
}
-NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
- if (!S || !NNS)
+NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier NNS) {
+ if (!S)
return nullptr;
- while (NNS->getPrefix())
- NNS = NNS->getPrefix();
-
- if (NNS->getKind() != NestedNameSpecifier::Identifier)
- return nullptr;
+ while (NNS.getKind() == NestedNameSpecifier::Kind::Type) {
+ const Type *T = NNS.getAsType();
+ if ((NNS = T->getPrefix()))
+ continue;
- LookupResult Found(*this, NNS->getAsIdentifier(), SourceLocation(),
- LookupNestedNameSpecifierName);
- LookupName(Found, S);
- assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet");
+ const auto *DNT = dyn_cast<DependentNameType>(T);
+ if (!DNT)
+ break;
- if (!Found.isSingleResult())
- return nullptr;
+ LookupResult Found(*this, DNT->getIdentifier(), SourceLocation(),
+ LookupNestedNameSpecifierName);
+ LookupName(Found, S);
+ assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet");
- NamedDecl *Result = Found.getFoundDecl();
- if (isAcceptableNestedNameSpecifier(Result))
- return Result;
+ if (!Found.isSingleResult())
+ return nullptr;
+ NamedDecl *Result = Found.getFoundDecl();
+ if (isAcceptableNestedNameSpecifier(Result))
+ return Result;
+ }
return nullptr;
}
@@ -899,7 +909,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
DependentTemplateSpecializationTypeLoc SpecTL
= Builder.push<DependentTemplateSpecializationTypeLoc>(T);
SpecTL.setElaboratedKeywordLoc(SourceLocation());
- SpecTL.setQualifierLoc(NestedNameSpecifierLoc());
+ SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
SpecTL.setTemplateNameLoc(TemplateNameLoc);
SpecTL.setLAngleLoc(LAngleLoc);
@@ -962,7 +972,7 @@ namespace {
/// A structure that stores a nested-name-specifier annotation,
/// including both the nested-name-specifier
struct NestedNameSpecifierAnnotation {
- NestedNameSpecifier *NNS;
+ NestedNameSpecifier NNS = std::nullopt;
};
}
@@ -1001,8 +1011,6 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
if (isa<ObjCContainerDecl>(CurContext) || isa<ObjCMethodDecl>(CurContext))
return false;
- NestedNameSpecifier *Qualifier = SS.getScopeRep();
-
// There are only two places a well-formed program may qualify a
// declarator: first, when defining a namespace or class member
// out-of-line, and second, when naming an explicitly-qualified
@@ -1017,18 +1025,20 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
// granting friendship.
// i.e. we don't push a scope unless it's a class member.
- switch (Qualifier->getKind()) {
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Namespace:
+ switch (SS.getScopeRep().getKind()) {
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::Namespace:
// These are always namespace scopes. We never want to enter a
// namespace scope from anything but a file context.
return CurContext->getRedeclContext()->isFileContext();
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::Super:
+ case NestedNameSpecifier::Kind::Type:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
// These are never namespace scopes.
return true;
+
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
}
llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 0c86a1f97046a..99492cea4e6c2 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -732,7 +732,7 @@ ResultBuilder::ShadowMapEntry::end() const {
///
/// \returns a nested name specifier that refers into the target context, or
/// NULL if no qualification is needed.
-static NestedNameSpecifier *
+static NestedNameSpecifier
getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
const DeclContext *TargetContext) {
SmallVector<const DeclContext *, 4> TargetParents;
@@ -747,7 +747,7 @@ getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
TargetParents.push_back(CommonAncestor);
}
- NestedNameSpecifier *Result = nullptr;
+ NestedNameSpecifier Result = std::nullopt;
while (!TargetParents.empty()) {
const DeclContext *Parent = TargetParents.pop_back_val();
@@ -755,10 +755,12 @@ getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
if (!Namespace->getIdentifier())
continue;
- Result = NestedNameSpecifier::Create(Context, Result, Namespace);
- } else if (const auto *TD = dyn_cast<TagDecl>(Parent))
- Result = NestedNameSpecifier::Create(
- Context, Result, Context.getTypeDeclType(TD).getTypePtr());
+ Result = NestedNameSpecifier(Context, Namespace, Result);
+ } else if (const auto *TD = dyn_cast<TagDecl>(Parent)) {
+ QualType TT = Context.getTagType(ElaboratedTypeKeyword::None, Result, TD,
+ /*OwnsTag=*/false);
+ Result = NestedNameSpecifier(TT.getTypePtr());
+ }
}
return Result;
}
@@ -937,11 +939,12 @@ SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
/// Get the type that a given expression will have if this declaration
/// is used as an expression in its "typical" code-completion form.
-QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
+QualType clang::getDeclUsageType(ASTContext &C, NestedNameSpecifier Qualifier,
+ const NamedDecl *ND) {
ND = ND->getUnderlyingDecl();
if (const auto *Type = dyn_cast<TypeDecl>(ND))
- return C.getTypeDeclType(Type);
+ return C.getTypeDeclType(ElaboratedTypeKeyword::None, Qualifier, Type);
if (const auto *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
return C.getObjCInterfaceType(Iface);
@@ -1217,11 +1220,13 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
const DeclContext *Ctx = R.Declaration->getDeclContext();
if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
R.Qualifier =
- NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
+ NestedNameSpecifier(SemaRef.Context, Namespace, std::nullopt);
else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
- R.Qualifier = NestedNameSpecifier::Create(
- SemaRef.Context, nullptr,
- SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
+ R.Qualifier = NestedNameSpecifier(
+ SemaRef.Context
+ .getTagType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, Tag, /*OwnsTag=*/false)
+ .getTypePtr());
else
R.QualifierIsInformative = false;
}
@@ -1406,11 +1411,13 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
const DeclContext *Ctx = R.Declaration->getDeclContext();
if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx))
R.Qualifier =
- NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
+ NestedNameSpecifier(SemaRef.Context, Namespace, std::nullopt);
else if (const auto *Tag = dyn_cast<TagDecl>(Ctx))
- R.Qualifier = NestedNameSpecifier::Create(
- SemaRef.Context, nullptr,
- SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
+ R.Qualifier = NestedNameSpecifier(
+ SemaRef.Context
+ .getTagType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, Tag, /*OwnsTag=*/false)
+ .getTypePtr());
else
R.QualifierIsInformative = false;
}
@@ -3385,7 +3392,7 @@ static void AddTemplateParameterChunks(
/// Add a qualifier to the given code-completion string, if the
/// provided nested-name-specifier is non-NULL.
static void AddQualifierToCompletionString(CodeCompletionBuilder &Result,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifier Qualifier,
bool QualifierIsInformative,
ASTContext &Context,
const PrintingPolicy &Policy) {
@@ -4500,12 +4507,12 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
// If we need a nested-name-specifier, add one now.
if (!InContext) {
- NestedNameSpecifier *NNS = getRequiredQualification(
+ NestedNameSpecifier NNS = getRequiredQualification(
S.Context, CurContext, Overridden->getDeclContext());
if (NNS) {
std::string Str;
llvm::raw_string_ostream OS(Str);
- NNS->print(OS, Policy);
+ NNS.print(OS, Policy);
Builder.AddTextChunk(Results.getAllocator().CopyString(Str));
}
} else if (!InContext->Equals(Overridden->getDeclContext()))
@@ -4914,14 +4921,14 @@ namespace {
/// Information that allows to avoid completing redundant enumerators.
struct CoveredEnumerators {
llvm::SmallPtrSet<EnumConstantDecl *, 8> Seen;
- NestedNameSpecifier *SuggestedQualifier = nullptr;
+ NestedNameSpecifier SuggestedQualifier = std::nullopt;
};
} // namespace
static void AddEnumerators(ResultBuilder &Results, ASTContext &Context,
EnumDecl *Enum, DeclContext *CurContext,
const CoveredEnumerators &Enumerators) {
- NestedNameSpecifier *Qualifier = Enumerators.SuggestedQualifier;
+ NestedNameSpecifier Qualifier = Enumerators.SuggestedQualifier;
if (Context.getLangOpts().CPlusPlus && !Qualifier && Enumerators.Seen.empty()) {
// If there are no prior enumerators in C++, check whether we have to
// qualify the names of the enumerators that we suggest, because they
@@ -5607,15 +5614,18 @@ class ConceptInfo {
// In T::foo, `foo` is a static member function/variable.
bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) override {
- if (E->getQualifier() && isApprox(E->getQualifier()->getAsType(), T))
+ NestedNameSpecifier Qualifier = E->getQualifier();
+ if (Qualifier.getKind() == NestedNameSpecifier::Kind::Type &&
+ isApprox(Qualifier.getAsType(), T))
addValue(E, E->getDeclName(), Member::Colons);
return true;
}
// In T::typename foo, `foo` is a type.
bool VisitDependentNameType(DependentNameType *DNT) override {
- const auto *Q = DNT->getQualifier();
- if (Q && isApprox(Q->getAsType(), T))
+ NestedNameSpecifier Q = DNT->getQualifier();
+ if (Q.getKind() == NestedNameSpecifier::Kind::Type &&
+ isApprox(Q.getAsType(), T))
addType(DNT->getIdentifier());
return true;
}
@@ -5624,10 +5634,15 @@ class ConceptInfo {
// VisitNNS() doesn't exist, and TraverseNNS isn't always called :-(
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSL) override {
if (NNSL) {
- NestedNameSpecifier *NNS = NNSL.getNestedNameSpecifier();
- const auto *Q = NNS->getPrefix();
- if (Q && isApprox(Q->getAsType(), T))
- addType(NNS->getAsIdentifier());
+ NestedNameSpecifier NNS = NNSL.getNestedNameSpecifier();
+ if (NNS.getKind() == NestedNameSpecifier::Kind::Type) {
+ const Type *NNST = NNS.getAsType();
+ if (NestedNameSpecifier Q = NNST->getPrefix();
+ Q.getKind() == NestedNameSpecifier::Kind::Type &&
+ isApprox(Q.getAsType(), T))
+ if (const auto *DNT = dyn_cast_or_null<DependentNameType>(NNST))
+ addType(DNT->getIdentifier());
+ }
}
// FIXME: also handle T::foo<X>::bar
return DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNSL);
@@ -6882,8 +6897,8 @@ void SemaCodeCompletion::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
// Try to instantiate any non-dependent declaration contexts before
// we look in them. Bail out if we fail.
- NestedNameSpecifier *NNS = SS.getScopeRep();
- if (NNS != nullptr && SS.isValid() && !NNS->isDependent()) {
+ NestedNameSpecifier NNS = SS.getScopeRep();
+ if (NNS && !NNS.isDependent()) {
if (Ctx == nullptr || SemaRef.RequireCompleteDeclContext(SS, Ctx))
return;
}
@@ -6897,14 +6912,13 @@ void SemaCodeCompletion::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
// The "template" keyword can follow "::" in the grammar, but only
// put it into the grammar if the nested-name-specifier is dependent.
// FIXME: results is always empty, this appears to be dead.
- if (!Results.empty() && NNS && NNS->isDependent())
+ if (!Results.empty() && NNS.isDependent())
Results.AddResult("template");
// If the scope is a concept-constrained type parameter, infer nested
// members based on the constraints.
- if (NNS) {
- if (const auto *TTPT =
- dyn_cast_or_null<TemplateTypeParmType>(NNS->getAsType())) {
+ if (NNS.getKind() == NestedNameSpecifier::Kind::Type) {
+ if (const auto *TTPT = dyn_cast<TemplateTypeParmType>(NNS.getAsType())) {
for (const auto &R : ConceptInfo(*TTPT, S).members()) {
if (R.Operator != ConceptInfo::Member::Colons)
continue;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e70177f5e574d..583fe4df7c567 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -307,9 +307,10 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
if (AllowImplicitTypename == ImplicitTypenameContext::No)
return nullptr;
SourceLocation QualifiedLoc = SS->getRange().getBegin();
- auto DB =
- DiagCompat(QualifiedLoc, diag_compat::implicit_typename)
- << NestedNameSpecifier::Create(Context, SS->getScopeRep(), &II);
+ // FIXME: Defer the diagnostic after we build the type and use it.
+ auto DB = DiagCompat(QualifiedLoc, diag_compat::implicit_typename)
+ << Context.getDependentNameType(ElaboratedTypeKeyword::None,
+ SS->getScopeRep(), &II);
if (!getLangOpts().CPlusPlus20)
DB << FixItHint::CreateInsertion(QualifiedLoc, "typename ");
}
@@ -389,7 +390,7 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
bool MemberOfUnknownSpecialization;
UnqualifiedId TemplateName;
TemplateName.setIdentifier(NewII, NameLoc);
- NestedNameSpecifier *NNS = Correction.getCorrectionSpecifier();
+ NestedNameSpecifier NNS = Correction.getCorrectionSpecifier();
CXXScopeSpec NewSS, *NewSSPtr = SS;
if (SS && NNS) {
NewSS.MakeTrivial(Context, NNS, SourceRange(NameLoc));
@@ -568,41 +569,38 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
} else if (AllowDeducedTemplate) {
if (auto *TD = getAsTypeTemplateDecl(IIDecl)) {
assert(!FoundUsingShadow || FoundUsingShadow->getTargetDecl() == TD);
+ // FIXME: Support UsingType here.
TemplateName Template = Context.getQualifiedTemplateName(
- SS ? SS->getScopeRep() : nullptr, /*TemplateKeyword=*/false,
+ SS ? SS->getScopeRep() : std::nullopt, /*TemplateKeyword=*/false,
FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD));
- T = Context.getDeducedTemplateSpecializationType(Template, QualType(),
- false);
- // Don't wrap in a further UsingType.
- FoundUsingShadow = nullptr;
+ QualType T = Context.getDeducedTemplateSpecializationType(
+ ElaboratedTypeKeyword::None, Template, QualType(), false);
+ auto TL = TLB.push<DeducedTemplateSpecializationTypeLoc>(T);
+ TL.setElaboratedKWLoc(SourceLocation());
+ TL.setNameLoc(NameLoc);
+ TL.setQualifierLoc(SS ? SS->getWithLocInContext(Context)
+ : NestedNameSpecifierLoc());
+ return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
}
}
- if (T.isNull()) {
- // If it's not plausibly a type, suppress diagnostics.
- Result.suppressDiagnostics();
- return nullptr;
- }
-
- if (FoundUsingShadow)
- T = Context.getUsingType(FoundUsingShadow, T);
-
- return buildNamedType(*this, SS, T, NameLoc, WantNontrivialTypeSourceInfo);
+ // As it's not plausibly a type, suppress diagnostics.
+ Result.suppressDiagnostics();
+ return nullptr;
}
// Builds a fake NNS for the given decl context.
-static NestedNameSpecifier *
+static NestedNameSpecifier
synthesizeCurrentNestedNameSpecifier(ASTContext &Context, DeclContext *DC) {
for (;; DC = DC->getLookupParent()) {
DC = DC->getPrimaryContext();
auto *ND = dyn_cast<NamespaceDecl>(DC);
if (ND && !ND->isInline() && !ND->isAnonymousNamespace())
- return NestedNameSpecifier::Create(Context, nullptr, ND);
+ return NestedNameSpecifier(Context, ND, std::nullopt);
if (auto *RD = dyn_cast<CXXRecordDecl>(DC))
- return NestedNameSpecifier::Create(Context, nullptr,
- RD->getTypeForDecl());
+ return NestedNameSpecifier(Context.getCanonicalTagType(RD)->getTypePtr());
if (isa<TranslationUnitDecl>(DC))
- return NestedNameSpecifier::GlobalSpecifier(Context);
+ return NestedNameSpecifier::getGlobal();
}
llvm_unreachable("something isn't in TU scope?");
}
@@ -627,7 +625,7 @@ ParsedType Sema::ActOnMSVCUnknownTypeName(const IdentifierInfo &II,
bool IsTemplateTypeArg) {
assert(getLangOpts().MSVCCompat && "shouldn't be called in non-MSVC mode");
- NestedNameSpecifier *NNS = nullptr;
+ NestedNameSpecifier NNS = std::nullopt;
if (IsTemplateTypeArg && getCurScope()->isTemplateParamScope()) {
// If we weren't able to parse a default template argument, delay lookup
// until instantiation time by making a non-dependent DependentTypeName. We
@@ -642,7 +640,7 @@ ParsedType Sema::ActOnMSVCUnknownTypeName(const IdentifierInfo &II,
findRecordWithDependentBasesOfEnclosingMethod(CurContext)) {
// Build a DependentNameType that will perform lookup into RD at
// instantiation time.
- NNS = NestedNameSpecifier::Create(Context, nullptr, RD->getTypeForDecl());
+ NNS = NestedNameSpecifier(Context.getCanonicalTagType(RD)->getTypePtr());
// Diagnose that this identifier was undeclared, and retry the lookup during
// template instantiation.
@@ -695,19 +693,22 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
}
bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S) {
- if (CurContext->isRecord()) {
- if (SS->getScopeRep()->getKind() == NestedNameSpecifier::Super)
- return true;
-
- const Type *Ty = SS->getScopeRep()->getAsType();
+ if (!CurContext->isRecord())
+ return CurContext->isFunctionOrMethod() || S->isFunctionPrototypeScope();
- CXXRecordDecl *RD = cast<CXXRecordDecl>(CurContext);
- for (const auto &Base : RD->bases())
- if (Ty && Context.hasSameUnqualifiedType(QualType(Ty, 1), Base.getType()))
+ switch (SS->getScopeRep().getKind()) {
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ return true;
+ case NestedNameSpecifier::Kind::Type: {
+ QualType T(SS->getScopeRep().getAsType(), 0);
+ for (const auto &Base : cast<CXXRecordDecl>(CurContext)->bases())
+ if (Context.hasSameUnqualifiedType(T, Base.getType()))
return true;
+ [[fallthrough]];
+ }
+ default:
return S->isFunctionPrototypeScope();
}
- return CurContext->isFunctionOrMethod() || S->isFunctionPrototypeScope();
}
void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
@@ -811,12 +812,13 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
if (getLangOpts().MSVCCompat && isMicrosoftMissingTypename(SS, S))
DiagID = diag::ext_typename_missing;
+ SuggestedType =
+ ActOnTypenameType(S, SourceLocation(), *SS, *II, IILoc).get();
+
Diag(SS->getRange().getBegin(), DiagID)
- << NestedNameSpecifier::Create(Context, SS->getScopeRep(), II)
+ << GetTypeFromParser(SuggestedType)
<< SourceRange(SS->getRange().getBegin(), IILoc)
<< FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename ");
- SuggestedType = ActOnTypenameType(S, SourceLocation(),
- *SS, *II, IILoc).get();
} else {
assert(SS && SS->isInvalid() &&
"Invalid scope specifier has already been diagnosed");
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 5ed59afd77e59..0477d37cac4c5 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -12456,9 +12456,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc,
S = S->getDeclParent();
UsingDirectiveDecl *UDir = nullptr;
- NestedNameSpecifier *Qualifier = nullptr;
- if (SS.isSet())
- Qualifier = SS.getScopeRep();
+ NestedNameSpecifier Qualifier = SS.getScopeRep();
// Lookup namespace name.
LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName);
@@ -12470,14 +12468,16 @@ Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc,
R.clear();
// Allow "using namespace std;" or "using namespace ::std;" even if
// "std" hasn't been defined yet, for GCC compatibility.
- if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) &&
+ if ((!Qualifier ||
+ Qualifier.getKind() == NestedNameSpecifier::Kind::Global) &&
NamespcName->isStr("std")) {
Diag(IdentLoc, diag::ext_using_undefined_std);
R.addDecl(getOrCreateStdNamespace());
R.resolveKind();
}
// Otherwise, attempt typo correction.
- else TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, NamespcName);
+ else
+ TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, NamespcName);
}
if (!R.empty()) {
@@ -12955,7 +12955,7 @@ namespace {
class UsingValidatorCCC final : public CorrectionCandidateCallback {
public:
UsingValidatorCCC(bool HasTypenameKeyword, bool IsInstantiation,
- NestedNameSpecifier *NNS, CXXRecordDecl *RequireMemberOf)
+ NestedNameSpecifier NNS, CXXRecordDecl *RequireMemberOf)
: HasTypenameKeyword(HasTypenameKeyword),
IsInstantiation(IsInstantiation), OldNNS(NNS),
RequireMemberOf(RequireMemberOf) {}
@@ -12982,24 +12982,23 @@ class UsingValidatorCCC final : public CorrectionCandidateCallback {
ASTContext &Ctx = ND->getASTContext();
if (!Ctx.getLangOpts().CPlusPlus11)
return false;
- QualType FoundType = Ctx.getRecordType(FoundRecord);
+ CanQualType FoundType = Ctx.getCanonicalTagType(FoundRecord);
// Check that the injected-class-name is named as a member of its own
// type; we don't want to suggest 'using Derived::Base;', since that
// means something else.
- NestedNameSpecifier *Specifier =
- Candidate.WillReplaceSpecifier()
- ? Candidate.getCorrectionSpecifier()
- : OldNNS;
- if (!Specifier->getAsType() ||
- !Ctx.hasSameType(QualType(Specifier->getAsType(), 0), FoundType))
+ NestedNameSpecifier Specifier = Candidate.WillReplaceSpecifier()
+ ? Candidate.getCorrectionSpecifier()
+ : OldNNS;
+ if (Specifier.getKind() != NestedNameSpecifier::Kind::Type ||
+ !Ctx.hasSameType(QualType(Specifier.getAsType(), 0), FoundType))
return false;
// Check that this inheriting constructor declaration actually names a
// direct base class of the current class.
bool AnyDependentBases = false;
if (!findDirectBaseWithType(RequireMemberOf,
- Ctx.getRecordType(FoundRecord),
+ Ctx.getCanonicalTagType(FoundRecord),
AnyDependentBases) &&
!AnyDependentBases)
return false;
@@ -13029,7 +13028,7 @@ class UsingValidatorCCC final : public CorrectionCandidateCallback {
private:
bool HasTypenameKeyword;
bool IsInstantiation;
- NestedNameSpecifier *OldNNS;
+ NestedNameSpecifier OldNNS;
CXXRecordDecl *RequireMemberOf;
};
} // end anonymous namespace
@@ -13411,7 +13410,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
const CXXScopeSpec &SS,
SourceLocation NameLoc,
const LookupResult &Prev) {
- NestedNameSpecifier *Qual = SS.getScopeRep();
+ NestedNameSpecifier Qual = SS.getScopeRep();
// C++03 [namespace.udecl]p8:
// C++0x [namespace.udecl]p10:
@@ -13443,13 +13442,12 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
return false;
}
- const NestedNameSpecifier *CNNS =
- Context.getCanonicalNestedNameSpecifier(Qual);
+ NestedNameSpecifier CNNS = Qual.getCanonical();
for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) {
NamedDecl *D = *I;
bool DTypename;
- NestedNameSpecifier *DQual;
+ NestedNameSpecifier DQual = std::nullopt;
if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) {
DTypename = UD->hasTypename();
DQual = UD->getQualifier();
@@ -13470,7 +13468,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
// using decls differ if they name different scopes (but note that
// template instantiation can cause this check to trigger when it
// didn't before instantiation).
- if (CNNS != Context.getCanonicalNestedNameSpecifier(DQual))
+ if (CNNS != DQual.getCanonical())
continue;
Diag(NameLoc, diag::err_using_decl_redeclaration) << SS.getRange();
@@ -14903,10 +14901,9 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
// reference to operator=; this is required to suppress the virtual
// call mechanism.
CXXScopeSpec SS;
+ // FIXME: Don't canonicalize this.
const Type *CanonicalT = S.Context.getCanonicalType(T.getTypePtr());
- SS.MakeTrivial(S.Context,
- NestedNameSpecifier::Create(S.Context, nullptr, CanonicalT),
- Loc);
+ SS.MakeTrivial(S.Context, NestedNameSpecifier(CanonicalT), Loc);
// Create the reference to operator=.
ExprResult OpEqualRef
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 3de6936eef9bb..813cf42862353 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2704,8 +2704,7 @@ recoverFromMSUnqualifiedLookup(Sema &S, ASTContext &Context,
// Synthesize a fake NNS that points to the derived class. This will
// perform name lookup during template instantiation.
CXXScopeSpec SS;
- auto *NNS =
- NestedNameSpecifier::Create(Context, nullptr, RD->getTypeForDecl());
+ NestedNameSpecifier NNS(Context.getCanonicalTagType(RD)->getTypePtr());
SS.MakeTrivial(Context, NNS, SourceRange(Loc, Loc));
return DependentScopeDeclRefExpr::Create(
Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo,
@@ -2995,11 +2994,10 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr(
return BuildDeclarationNameExpr(SS, R, /*ADL=*/false);
}
-ExprResult
-Sema::PerformObjectMemberConversion(Expr *From,
- NestedNameSpecifier *Qualifier,
- NamedDecl *FoundDecl,
- NamedDecl *Member) {
+ExprResult Sema::PerformObjectMemberConversion(Expr *From,
+ NestedNameSpecifier Qualifier,
+ NamedDecl *FoundDecl,
+ NamedDecl *Member) {
const auto *RD = dyn_cast<CXXRecordDecl>(Member->getDeclContext());
if (!RD)
return From;
@@ -3088,8 +3086,8 @@ Sema::PerformObjectMemberConversion(Expr *From,
// x = 17; // error: ambiguous base subobjects
// Derived1::x = 17; // okay, pick the Base subobject of Derived1
// }
- if (Qualifier && Qualifier->getAsType()) {
- QualType QType = QualType(Qualifier->getAsType(), 0);
+ if (Qualifier.getKind() == NestedNameSpecifier::Kind::Type) {
+ QualType QType = QualType(Qualifier.getAsType(), 0);
assert(QType->isRecordType() && "lookup done with non-record type");
QualType QRecordType = QualType(QType->castAs<RecordType>(), 0);
@@ -21230,7 +21228,7 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
NamedDecl *Temp = *ULE->decls_begin();
const bool IsTypeAliasTemplateDecl = isa<TypeAliasTemplateDecl>(Temp);
- NestedNameSpecifier *NNS = ULE->getQualifierLoc().getNestedNameSpecifier();
+ NestedNameSpecifier NNS = ULE->getQualifierLoc().getNestedNameSpecifier();
// FIXME: AssumedTemplate is not very appropriate for error recovery here,
// as it models only the unqualified-id case, where this case can clearly be
// qualified. Thus we can't just qualify an assumed template.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index de064834314fa..c3e57c1f7eff9 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -57,11 +57,11 @@ using namespace sema;
ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS,
SourceLocation NameLoc,
const IdentifierInfo &Name) {
- NestedNameSpecifier *NNS = SS.getScopeRep();
- if ([[maybe_unused]] const IdentifierInfo *II = NNS->getAsIdentifier())
- assert(II == &Name && "not a constructor name");
+ NestedNameSpecifier NNS = SS.getScopeRep();
+ QualType Type(NNS.getAsType(), 0);
+ if ([[maybe_unused]] const auto *DNT = dyn_cast<DependentNameType>(Type))
+ assert(DNT->getIdentifier() == &Name && "not a constructor name");
- QualType Type(NNS->translateToType(Context), 0);
// This reference to the type is located entirely at the location of the
// final identifier in the qualified-id.
return CreateParsedType(Type,
@@ -310,15 +310,23 @@ ParsedType Sema::getDestructorName(const IdentifierInfo &II,
// If both lookups succeed and find a dependent result, which result should
// we retain? (Same question for p->~type-name().)
- if (NestedNameSpecifier *Prefix =
- SS.isSet() ? SS.getScopeRep()->getPrefix() : nullptr) {
+ auto Prefix = [&]() -> NestedNameSpecifierLoc {
+ NestedNameSpecifierLoc NNS = SS.getWithLocInContext(Context);
+ if (!NNS)
+ return NestedNameSpecifierLoc();
+ if (auto TL = NNS.getAsTypeLoc())
+ return TL.getPrefix();
+ return NNS.getAsNamespaceAndPrefix().Prefix;
+ }();
+
+ if (Prefix) {
// This is
//
// nested-name-specifier type-name :: ~ type-name
//
// Look for the second type-name in the nested-name-specifier.
CXXScopeSpec PrefixSS;
- PrefixSS.Adopt(NestedNameSpecifierLoc(Prefix, SS.location_data()));
+ PrefixSS.Adopt(Prefix);
if (ParsedType T = LookupInNestedNameSpec(PrefixSS))
return T;
} else {
@@ -502,12 +510,8 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
<< II << static_cast<int>(Status) << Hint;
}
- if (!SS.isValid())
- return false;
-
- switch (SS.getScopeRep()->getKind()) {
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::TypeSpec:
+ switch (SS.getScopeRep().getKind()) {
+ case NestedNameSpecifier::Kind::Type:
// Per C++11 [over.literal]p2, literal operators can only be declared at
// namespace scope. Therefore, this unqualified-id cannot name anything.
// Reject it early, because we have no AST representation for this in the
@@ -516,9 +520,10 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
<< SS.getScopeRep();
return true;
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
- case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ case NestedNameSpecifier::Kind::Namespace:
return false;
}
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 89f5ccadbc416..ba0f783411427 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -2702,12 +2702,10 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
CXXScopeSpec &SS) {
- auto *NNS = SS.getScopeRep();
- if (NNS && NNS->getKind() == NestedNameSpecifier::Super)
- return LookupInSuper(R, NNS->getAsRecordDecl());
- else
-
- return LookupQualifiedName(R, LookupCtx);
+ NestedNameSpecifier Qualifier = SS.getScopeRep();
+ if (Qualifier.getKind() == NestedNameSpecifier::Kind::MicrosoftSuper)
+ return LookupInSuper(R, Qualifier.getAsMicrosoftSuper());
+ return LookupQualifiedName(R, LookupCtx);
}
bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
@@ -2744,9 +2742,9 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
// FIXME: '__super' lookup semantics could be implemented by a
// LookupResult::isSuperLookup flag which skips the initial search of
// the lookup context in LookupQualified.
- if (NestedNameSpecifier *NNS = SS->getScopeRep();
- NNS->getKind() == NestedNameSpecifier::Super)
- return LookupInSuper(R, NNS->getAsRecordDecl());
+ if (NestedNameSpecifier Qualifier = SS->getScopeRep();
+ Qualifier.getKind() == NestedNameSpecifier::Kind::MicrosoftSuper)
+ return LookupInSuper(R, Qualifier.getAsMicrosoftSuper());
}
IsDependent = !DC && isDependentScopeSpecifier(*SS);
} else {
@@ -4553,40 +4551,101 @@ static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) {
// the given NestedNameSpecifier (i.e. given a NestedNameSpecifier "foo::bar::",
// fill the vector with the IdentifierInfo pointers for "foo" and "bar").
static void getNestedNameSpecifierIdentifiers(
- NestedNameSpecifier *NNS,
- SmallVectorImpl<const IdentifierInfo*> &Identifiers) {
- if (NestedNameSpecifier *Prefix = NNS->getPrefix())
- getNestedNameSpecifierIdentifiers(Prefix, Identifiers);
- else
+ NestedNameSpecifier NNS,
+ SmallVectorImpl<const IdentifierInfo *> &Identifiers) {
+ switch (NNS.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
Identifiers.clear();
+ return;
- const IdentifierInfo *II = nullptr;
-
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- II = NNS->getAsIdentifier();
- break;
-
- case NestedNameSpecifier::Namespace: {
- const NamespaceBaseDecl *Namespace = NNS->getAsNamespace();
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace, Prefix] = NNS.getAsNamespaceAndPrefix();
+ getNestedNameSpecifierIdentifiers(Prefix, Identifiers);
if (const auto *NS = dyn_cast<NamespaceDecl>(Namespace);
NS && NS->isAnonymousNamespace())
return;
- II = Namespace->getIdentifier();
- break;
+ Identifiers.push_back(Namespace->getIdentifier());
+ return;
}
- case NestedNameSpecifier::TypeSpec:
- II = QualType(NNS->getAsType(), 0).getBaseTypeIdentifier();
+ case NestedNameSpecifier::Kind::Type: {
+ for (const Type *T = NNS.getAsType(); /**/; /**/) {
+ switch (T->getTypeClass()) {
+ case Type::DependentName: {
+ auto *DT = cast<DependentNameType>(T);
+ getNestedNameSpecifierIdentifiers(DT->getQualifier(), Identifiers);
+ Identifiers.push_back(DT->getIdentifier());
+ return;
+ }
+ case Type::TemplateSpecialization: {
+ TemplateName Name =
+ cast<TemplateSpecializationType>(T)->getTemplateName();
+ if (const QualifiedTemplateName *QTN =
+ Name.getAsAdjustedQualifiedTemplateName()) {
+ getNestedNameSpecifierIdentifiers(QTN->getQualifier(), Identifiers);
+ Name = QTN->getUnderlyingTemplate();
+ }
+ if (const auto *TD = Name.getAsTemplateDecl(/*IgnoreDeduced=*/true))
+ Identifiers.push_back(TD->getIdentifier());
+ return;
+ }
+ case Type::DependentTemplateSpecialization: {
+ const DependentTemplateStorage &S =
+ cast<DependentTemplateSpecializationType>(T)
+ ->getDependentTemplateName();
+ getNestedNameSpecifierIdentifiers(S.getQualifier(), Identifiers);
+ // FIXME: Should this dig into the Name as well?
+ // Identifiers.push_back(S.getName().getIdentifier());
+ return;
+ }
+ case Type::SubstTemplateTypeParm:
+ T = cast<SubstTemplateTypeParmType>(T)
+ ->getReplacementType()
+ .getTypePtr();
+ continue;
+ case Type::TemplateTypeParm:
+ Identifiers.push_back(cast<TemplateTypeParmType>(T)->getIdentifier());
+ return;
+ case Type::Decltype:
+ return;
+ case Type::Enum:
+ case Type::Record:
+ case Type::InjectedClassName: {
+ auto *TT = cast<TagType>(T);
+ getNestedNameSpecifierIdentifiers(TT->getQualifier(), Identifiers);
+ Identifiers.push_back(TT->getOriginalDecl()->getIdentifier());
+ return;
+ }
+ case Type::Typedef: {
+ auto *TT = cast<TypedefType>(T);
+ getNestedNameSpecifierIdentifiers(TT->getQualifier(), Identifiers);
+ Identifiers.push_back(TT->getDecl()->getIdentifier());
+ return;
+ }
+ case Type::Using: {
+ auto *TT = cast<UsingType>(T);
+ getNestedNameSpecifierIdentifiers(TT->getQualifier(), Identifiers);
+ Identifiers.push_back(TT->getDecl()->getIdentifier());
+ return;
+ }
+ case Type::UnresolvedUsing: {
+ auto *TT = cast<UnresolvedUsingType>(T);
+ getNestedNameSpecifierIdentifiers(TT->getQualifier(), Identifiers);
+ Identifiers.push_back(TT->getDecl()->getIdentifier());
+ return;
+ }
+ default:
+ Identifiers.push_back(QualType(T, 0).getBaseTypeIdentifier());
+ return;
+ }
+ }
break;
+ }
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
return;
}
-
- if (II)
- Identifiers.push_back(II);
}
void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
@@ -4619,11 +4678,11 @@ void TypoCorrectionConsumer::FoundName(StringRef Name) {
void TypoCorrectionConsumer::addKeywordResult(StringRef Keyword) {
// Compute the edit distance between the typo and this keyword,
// and add the keyword to the list of results.
- addName(Keyword, nullptr, nullptr, true);
+ addName(Keyword, /*ND=*/nullptr, /*NNS=*/std::nullopt, /*isKeyword=*/true);
}
void TypoCorrectionConsumer::addName(StringRef Name, NamedDecl *ND,
- NestedNameSpecifier *NNS, bool isKeyword) {
+ NestedNameSpecifier NNS, bool isKeyword) {
// Use a simple length-based heuristic to determine the minimum possible
// edit distance. If the minimum isn't good enough, bail out early.
StringRef TypoStr = Typo->getName();
@@ -4715,10 +4774,10 @@ void TypoCorrectionConsumer::addNamespaces(
Namespaces.addNameSpecifier(KNPair.first);
bool SSIsTemplate = false;
- if (NestedNameSpecifier *NNS =
- (SS && SS->isValid()) ? SS->getScopeRep() : nullptr) {
- if (const Type *T = NNS->getAsType())
- SSIsTemplate = T->getTypeClass() == Type::TemplateSpecialization;
+ if (NestedNameSpecifier NNS = (SS ? SS->getScopeRep() : std::nullopt)) {
+ if (NNS.getKind() == NestedNameSpecifier::Kind::Type)
+ SSIsTemplate =
+ NNS.getAsType()->getTypeClass() == Type::TemplateSpecialization;
}
// Do not transform this into an iterator-based loop. The loop body can
// trigger the creation of further types (through lazy deserialization) and
@@ -4820,17 +4879,15 @@ void TypoCorrectionConsumer::performQualifiedLookups() {
for (const TypoCorrection &QR : QualifiedResults) {
for (const auto &NSI : Namespaces) {
DeclContext *Ctx = NSI.DeclCtx;
- const Type *NSType = NSI.NameSpecifier->getAsType();
+ CXXRecordDecl *NamingClass = NSI.NameSpecifier.getAsRecordDecl();
// If the current NestedNameSpecifier refers to a class and the
// current correction candidate is the name of that class, then skip
// it as it is unlikely a qualified version of the class' constructor
// is an appropriate correction.
- if (CXXRecordDecl *NSDecl = NSType ? NSType->getAsCXXRecordDecl() :
- nullptr) {
- if (NSDecl->getIdentifier() == QR.getCorrectionAsIdentifierInfo())
- continue;
- }
+ if (NamingClass &&
+ NamingClass->getIdentifier() == QR.getCorrectionAsIdentifierInfo())
+ continue;
TypoCorrection TC(QR);
TC.ClearCorrectionDecls();
@@ -4895,10 +4952,10 @@ void TypoCorrectionConsumer::performQualifiedLookups() {
TypoCorrectionConsumer::NamespaceSpecifierSet::NamespaceSpecifierSet(
ASTContext &Context, DeclContext *CurContext, CXXScopeSpec *CurScopeSpec)
: Context(Context), CurContextChain(buildContextChain(CurContext)) {
- if (NestedNameSpecifier *NNS =
- CurScopeSpec ? CurScopeSpec->getScopeRep() : nullptr) {
+ if (NestedNameSpecifier NNS =
+ CurScopeSpec ? CurScopeSpec->getScopeRep() : std::nullopt) {
llvm::raw_string_ostream SpecifierOStream(CurNameSpecifier);
- NNS->print(SpecifierOStream, Context.getPrintingPolicy());
+ NNS.print(SpecifierOStream, Context.getPrintingPolicy());
getNestedNameSpecifierIdentifiers(NNS, CurNameSpecifierIdentifiers);
}
@@ -4912,7 +4969,7 @@ TypoCorrectionConsumer::NamespaceSpecifierSet::NamespaceSpecifierSet(
// Add the global context as a NestedNameSpecifier
SpecifierInfo SI = {cast<DeclContext>(Context.getTranslationUnitDecl()),
- NestedNameSpecifier::GlobalSpecifier(Context), 1};
+ NestedNameSpecifier::getGlobal(), 1};
DistanceMap[1].push_back(SI);
}
@@ -4932,14 +4989,16 @@ auto TypoCorrectionConsumer::NamespaceSpecifierSet::buildContextChain(
unsigned
TypoCorrectionConsumer::NamespaceSpecifierSet::buildNestedNameSpecifier(
- DeclContextList &DeclChain, NestedNameSpecifier *&NNS) {
+ DeclContextList &DeclChain, NestedNameSpecifier &NNS) {
unsigned NumSpecifiers = 0;
for (DeclContext *C : llvm::reverse(DeclChain)) {
if (auto *ND = dyn_cast_or_null<NamespaceDecl>(C)) {
- NNS = NestedNameSpecifier::Create(Context, NNS, ND);
+ NNS = NestedNameSpecifier(Context, ND, NNS);
++NumSpecifiers;
} else if (auto *RD = dyn_cast_or_null<RecordDecl>(C)) {
- NNS = NestedNameSpecifier::Create(Context, NNS, RD->getTypeForDecl());
+ QualType T = Context.getTagType(ElaboratedTypeKeyword::None, NNS, RD,
+ /*OwnsTag=*/false);
+ NNS = NestedNameSpecifier(T.getTypePtr());
++NumSpecifiers;
}
}
@@ -4948,7 +5007,7 @@ TypoCorrectionConsumer::NamespaceSpecifierSet::buildNestedNameSpecifier(
void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier(
DeclContext *Ctx) {
- NestedNameSpecifier *NNS = nullptr;
+ NestedNameSpecifier NNS = std::nullopt;
unsigned NumSpecifiers = 0;
DeclContextList NamespaceDeclChain(buildContextChain(Ctx));
DeclContextList FullNamespaceDeclChain(NamespaceDeclChain);
@@ -4966,7 +5025,7 @@ void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier(
// Add an explicit leading '::' specifier if needed.
if (NamespaceDeclChain.empty()) {
// Rebuild the NestedNameSpecifier as a globally-qualified specifier.
- NNS = NestedNameSpecifier::GlobalSpecifier(Context);
+ NNS = NestedNameSpecifier::getGlobal();
NumSpecifiers =
buildNestedNameSpecifier(FullNamespaceDeclChain, NNS);
} else if (NamedDecl *ND =
@@ -4978,12 +5037,12 @@ void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier(
llvm::raw_string_ostream SpecifierOStream(NewNameSpecifier);
SmallVector<const IdentifierInfo *, 4> NewNameSpecifierIdentifiers;
getNestedNameSpecifierIdentifiers(NNS, NewNameSpecifierIdentifiers);
- NNS->print(SpecifierOStream, Context.getPrintingPolicy());
+ NNS.print(SpecifierOStream, Context.getPrintingPolicy());
SameNameSpecifier = NewNameSpecifier == CurNameSpecifier;
}
if (SameNameSpecifier || llvm::is_contained(CurContextIdentifiers, Name)) {
// Rebuild the NestedNameSpecifier as a globally-qualified specifier.
- NNS = NestedNameSpecifier::GlobalSpecifier(Context);
+ NNS = NestedNameSpecifier::getGlobal();
NumSpecifiers =
buildNestedNameSpecifier(FullNamespaceDeclChain, NNS);
}
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 1f87f4db5cb53..c02e205dc9cde 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -3639,12 +3639,12 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion(
CXXRecordDecl *FromClass = FromPtrType->getMostRecentCXXRecordDecl(),
*ToClass = ToPtrType->getMostRecentCXXRecordDecl();
- auto DiagCls = [](PartialDiagnostic &PD, NestedNameSpecifier *Qual,
- const CXXRecordDecl *Cls) {
- if (declaresSameEntity(Qual->getAsRecordDecl(), Cls))
+ auto DiagCls = [&](PartialDiagnostic &PD, NestedNameSpecifier Qual,
+ const CXXRecordDecl *Cls) {
+ if (declaresSameEntity(Qual.getAsRecordDecl(), Cls))
PD << Qual;
else
- PD << QualType(Cls->getTypeForDecl(), 0);
+ PD << Context.getCanonicalTagType(Cls);
};
auto DiagFromTo = [&](PartialDiagnostic &PD) -> PartialDiagnostic & {
DiagCls(PD, FromPtrType->getQualifier(), FromClass);
@@ -3689,8 +3689,8 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion(
? diag::err_upcast_to_inaccessible_base
: diag::err_downcast_from_inaccessible_base,
[&](PartialDiagnostic &PD) {
- NestedNameSpecifier *BaseQual = FromPtrType->getQualifier(),
- *DerivedQual = ToPtrType->getQualifier();
+ NestedNameSpecifier BaseQual = FromPtrType->getQualifier(),
+ DerivedQual = ToPtrType->getQualifier();
if (Direction == MemberPointerConversionDirection::Upcast)
std::swap(BaseQual, DerivedQual);
DiagCls(PD, DerivedQual, Derived);
@@ -6062,7 +6062,7 @@ static ImplicitConversionSequence TryObjectArgumentInitialization(
/// the implicit object parameter for the given Method with the given
/// expression.
ExprResult Sema::PerformImplicitObjectArgumentInitialization(
- Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl,
+ Expr *From, NestedNameSpecifier Qualifier, NamedDecl *FoundDecl,
CXXMethodDecl *Method) {
QualType FromRecordType, DestType;
QualType ImplicitParamRecordType = Method->getFunctionObjectParameterType();
@@ -16081,7 +16081,7 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
CXXMethodDecl *Method = nullptr;
bool HadMultipleCandidates = false;
DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_public);
- NestedNameSpecifier *Qualifier = nullptr;
+ NestedNameSpecifier Qualifier = std::nullopt;
if (isa<MemberExpr>(NakedMemExpr)) {
MemExpr = cast<MemberExpr>(NakedMemExpr);
Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl());
@@ -16951,7 +16951,7 @@ ExprResult Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
assert(isa<DeclRefExpr>(SubExpr.get()) &&
"fixed to something other than a decl ref");
- NestedNameSpecifier *Qualifier =
+ NestedNameSpecifier Qualifier =
cast<DeclRefExpr>(SubExpr.get())->getQualifier();
assert(Qualifier &&
"fixed to a member ref with no nested name qualifier");
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index c80c845c5d8f3..5cac63b1303f3 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -291,7 +291,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD);
assert(!FoundUsingShadow || FoundUsingShadow->getTargetDecl() == TD);
if (!SS.isInvalid()) {
- NestedNameSpecifier *Qualifier = SS.getScopeRep();
+ NestedNameSpecifier Qualifier = SS.getScopeRep();
Template = Context.getQualifiedTemplateName(Qualifier, hasTemplateKeyword,
Template);
}
@@ -363,9 +363,8 @@ bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II,
// The code is missing a 'template' keyword prior to the dependent template
// name.
- NestedNameSpecifier *Qualifier = (NestedNameSpecifier *)SS->getScopeRep();
SuggestedTemplate = TemplateTy::make(Context.getDependentTemplateName(
- {Qualifier, &II, /*HasTemplateKeyword=*/false}));
+ {SS->getScopeRep(), &II, /*HasTemplateKeyword=*/false}));
Diag(IILoc, diag::err_template_kw_missing)
<< SuggestedTemplate.get()
<< FixItHint::CreateInsertion(IILoc, "template ");
@@ -2105,11 +2104,11 @@ DeclResult Sema::CheckClassTemplate(
bool ShouldAddRedecl =
!(TUK == TagUseKind::Friend && CurContext->isDependentContext());
- CXXRecordDecl *NewClass =
- CXXRecordDecl::Create(Context, Kind, SemanticContext, KWLoc, NameLoc, Name,
- PrevClassTemplate && ShouldAddRedecl ?
- PrevClassTemplate->getTemplatedDecl() : nullptr,
- /*DelayTypeCreation=*/true);
+ CXXRecordDecl *NewClass = CXXRecordDecl::Create(
+ Context, Kind, SemanticContext, KWLoc, NameLoc, Name,
+ PrevClassTemplate && ShouldAddRedecl
+ ? PrevClassTemplate->getTemplatedDecl()
+ : nullptr);
SetNestedNameSpecifier(*this, NewClass, SS);
if (NumOuterTemplateParamLists > 0)
NewClass->setTemplateParameterListsInfo(
@@ -2697,14 +2696,14 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context,
QualType T,
const CXXScopeSpec &SS) {
NestedNameSpecifierLoc NNSLoc(SS.getScopeRep(), SS.location_data());
- while (NestedNameSpecifier *NNS = NNSLoc.getNestedNameSpecifier()) {
- if (const Type *CurType = NNS->getAsType()) {
- if (Context.hasSameUnqualifiedType(T, QualType(CurType, 0)))
- return NNSLoc.getTypeLoc().getSourceRange();
- } else
+ for (;;) {
+ NestedNameSpecifier NNS = NNSLoc.getNestedNameSpecifier();
+ if (NNS.getKind() != NestedNameSpecifier::Kind::Type)
break;
-
- NNSLoc = NNSLoc.getPrefix();
+ if (Context.hasSameUnqualifiedType(T, QualType(NNS.getAsType(), 0)))
+ return NNSLoc.castAsTypeLoc().getSourceRange();
+ // FIXME: This will always be empty.
+ NNSLoc = NNSLoc.getAsNamespaceAndPrefix().Prefix;
}
return SourceRange();
@@ -2723,12 +2722,13 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
// by the nested-name-specifier and walking out until we run out of types.
SmallVector<QualType, 4> NestedTypes;
QualType T;
- if (SS.getScopeRep()) {
- if (CXXRecordDecl *Record
- = dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS, true)))
- T = Context.getTypeDeclType(Record);
+ if (NestedNameSpecifier Qualifier = SS.getScopeRep();
+ Qualifier.getKind() == NestedNameSpecifier::Kind::Type) {
+ if (CXXRecordDecl *Record =
+ dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS, true)))
+ T = Context.getCanonicalTagType(Record);
else
- T = QualType(SS.getScopeRep()->getAsType(), 0);
+ T = QualType(Qualifier.getAsType(), 0);
}
// If we found an explicit specialization that prevents us from needing
@@ -2776,9 +2776,10 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
// Look one step prior in a dependent template specialization type.
if (const DependentTemplateSpecializationType *DependentTST
= T->getAs<DependentTemplateSpecializationType>()) {
- if (NestedNameSpecifier *NNS =
- DependentTST->getDependentTemplateName().getQualifier())
- T = QualType(NNS->getAsType(), 0);
+ if (NestedNameSpecifier NNS =
+ DependentTST->getDependentTemplateName().getQualifier();
+ NNS.getKind() == NestedNameSpecifier::Kind::Type)
+ T = QualType(NNS.getAsType(), 0);
else
T = QualType();
continue;
@@ -2786,8 +2787,9 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
// Look one step prior in a dependent name type.
if (const DependentNameType *DependentName = T->getAs<DependentNameType>()){
- if (NestedNameSpecifier *NNS = DependentName->getQualifier())
- T = QualType(NNS->getAsType(), 0);
+ if (NestedNameSpecifier NNS = DependentName->getQualifier();
+ NNS.getKind() == NestedNameSpecifier::Kind::Type)
+ T = QualType(NNS.getAsType(), 0);
else
T = QualType();
continue;
@@ -3874,8 +3876,9 @@ TypeResult Sema::ActOnTemplateIdType(
// elaborated-type-specifier (7.1.5.3).
if (!LookupCtx && isDependentScopeSpecifier(SS)) {
// C++2a relaxes some of those restrictions in [temp.res]p5.
- NestedNameSpecifier *NNS =
- NestedNameSpecifier::Create(Context, SS.getScopeRep(), TemplateII);
+ QualType DNT = Context.getDependentNameType(ElaboratedTypeKeyword::None,
+ SS.getScopeRep(), TemplateII);
+ NestedNameSpecifier NNS(DNT.getTypePtr());
if (AllowImplicitTypename == ImplicitTypenameContext::Yes) {
auto DB = DiagCompat(SS.getBeginLoc(), diag_compat::implicit_typename)
<< NNS;
@@ -4939,7 +4942,7 @@ TemplateNameKind Sema::ActOnTemplateName(Scope *S,
return TNK_Non_template;
}
- NestedNameSpecifier *Qualifier = SS.getScopeRep();
+ NestedNameSpecifier Qualifier = SS.getScopeRep();
switch (Name.getKind()) {
case UnqualifiedIdKind::IK_Identifier:
@@ -5227,8 +5230,9 @@ static bool SubstDefaultTemplateArgument(
///
/// \returns the substituted template argument, or NULL if an error occurred.
static TemplateName SubstDefaultTemplateArgument(
- Sema &SemaRef, TemplateDecl *Template, SourceLocation TemplateLoc,
- SourceLocation RAngleLoc, TemplateTemplateParmDecl *Param,
+ Sema &SemaRef, TemplateDecl *Template, SourceLocation TemplateKWLoc,
+ SourceLocation TemplateLoc, SourceLocation RAngleLoc,
+ TemplateTemplateParmDecl *Param,
ArrayRef<TemplateArgument> SugaredConverted,
ArrayRef<TemplateArgument> CanonicalConverted,
NestedNameSpecifierLoc &QualifierLoc) {
@@ -5245,25 +5249,17 @@ static TemplateName SubstDefaultTemplateArgument(
TemplateArgLists.addOuterTemplateArguments(std::nullopt);
Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
- // Substitute into the nested-name-specifier first,
- QualifierLoc = Param->getDefaultArgument().getTemplateQualifierLoc();
- if (QualifierLoc) {
- QualifierLoc =
- SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgLists);
- if (!QualifierLoc)
- return TemplateName();
- }
- return SemaRef.SubstTemplateName(
- QualifierLoc,
- Param->getDefaultArgument().getArgument().getAsTemplate(),
- Param->getDefaultArgument().getTemplateNameLoc(),
- TemplateArgLists);
+ const TemplateArgumentLoc &A = Param->getDefaultArgument();
+ QualifierLoc = A.getTemplateQualifierLoc();
+ return SemaRef.SubstTemplateName(TemplateKWLoc, QualifierLoc,
+ A.getArgument().getAsTemplate(),
+ A.getTemplateNameLoc(), TemplateArgLists);
}
TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable(
- TemplateDecl *Template, SourceLocation TemplateLoc,
- SourceLocation RAngleLoc, Decl *Param,
+ TemplateDecl *Template, SourceLocation TemplateKWLoc,
+ SourceLocation TemplateNameLoc, SourceLocation RAngleLoc, Decl *Param,
ArrayRef<TemplateArgument> SugaredConverted,
ArrayRef<TemplateArgument> CanonicalConverted, bool &HasDefaultArg) {
HasDefaultArg = false;
@@ -5301,17 +5297,16 @@ TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable(
return TemplateArgumentLoc();
HasDefaultArg = true;
+ const TemplateArgumentLoc &A = TempTempParm->getDefaultArgument();
NestedNameSpecifierLoc QualifierLoc;
TemplateName TName = SubstDefaultTemplateArgument(
- *this, Template, TemplateLoc, RAngleLoc, TempTempParm, SugaredConverted,
- CanonicalConverted, QualifierLoc);
+ *this, Template, TemplateKWLoc, TemplateNameLoc, RAngleLoc, TempTempParm,
+ SugaredConverted, CanonicalConverted, QualifierLoc);
if (TName.isNull())
return TemplateArgumentLoc();
- return TemplateArgumentLoc(
- Context, TemplateArgument(TName),
- TempTempParm->getDefaultArgument().getTemplateQualifierLoc(),
- TempTempParm->getDefaultArgument().getTemplateNameLoc());
+ return TemplateArgumentLoc(Context, TemplateArgument(TName), TemplateKWLoc,
+ QualifierLoc, A.getTemplateNameLoc());
}
/// Convert a template-argument that we parsed as a type into a template, if
@@ -5319,33 +5314,24 @@ TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable(
/// template template arguments and as template type arguments.
static TemplateArgumentLoc
convertTypeTemplateArgumentToTemplate(ASTContext &Context, TypeLoc TLoc) {
- // Extract and step over any surrounding nested-name-specifier.
- NestedNameSpecifierLoc QualLoc;
- if (auto ETLoc = TLoc.getAs<ElaboratedTypeLoc>()) {
- if (ETLoc.getTypePtr()->getKeyword() != ElaboratedTypeKeyword::None)
- return TemplateArgumentLoc();
+ auto TagLoc = TLoc.getAs<TagTypeLoc>();
+ if (!TagLoc)
+ return TemplateArgumentLoc();
- QualLoc = ETLoc.getQualifierLoc();
- TLoc = ETLoc.getNamedTypeLoc();
- }
// If this type was written as an injected-class-name, it can be used as a
// template template argument.
- if (auto InjLoc = TLoc.getAs<InjectedClassNameTypeLoc>())
- return TemplateArgumentLoc(Context, InjLoc.getTypePtr()->getTemplateName(),
- QualLoc, InjLoc.getNameLoc());
-
// If this type was written as an injected-class-name, it may have been
// converted to a RecordType during instantiation. If the RecordType is
// *not* wrapped in a TemplateSpecializationType and denotes a class
// template specialization, it must have come from an injected-class-name.
- if (auto RecLoc = TLoc.getAs<RecordTypeLoc>())
- if (auto *CTSD =
- dyn_cast<ClassTemplateSpecializationDecl>(RecLoc.getDecl()))
- return TemplateArgumentLoc(Context,
- TemplateName(CTSD->getSpecializedTemplate()),
- QualLoc, RecLoc.getNameLoc());
- return TemplateArgumentLoc();
+ TemplateName Name = TagLoc.getTypePtr()->getTemplateName(Context);
+ if (Name.isNull())
+ return TemplateArgumentLoc();
+
+ return TemplateArgumentLoc(Context, Name,
+ /*TemplateKWLoc=*/SourceLocation(),
+ TagLoc.getQualifierLoc(), TagLoc.getNameLoc());
}
bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc,
@@ -6023,7 +6009,7 @@ namespace {
#include "clang/AST/TypeNodes.inc"
bool VisitTagDecl(const TagDecl *Tag);
- bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS);
+ bool VisitNestedNameSpecifier(NestedNameSpecifier NNS);
};
} // end anonymous namespace
@@ -6202,10 +6188,7 @@ bool UnnamedLocalNoLinkageFinder::VisitDependentNameType(
bool UnnamedLocalNoLinkageFinder::VisitDependentTemplateSpecializationType(
const DependentTemplateSpecializationType* T) {
- if (auto *Q = T->getDependentTemplateName().getQualifier())
- return VisitNestedNameSpecifier(Q);
-
- return false;
+ return VisitNestedNameSpecifier(T->getDependentTemplateName().getQualifier());
}
bool UnnamedLocalNoLinkageFinder::VisitPackExpansionType(
@@ -6271,20 +6254,15 @@ bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) {
}
bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier(
- NestedNameSpecifier *NNS) {
- assert(NNS);
- if (NNS->getPrefix() && VisitNestedNameSpecifier(NNS->getPrefix()))
- return true;
-
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
+ NestedNameSpecifier NNS) {
+ switch (NNS.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Namespace:
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
return false;
-
- case NestedNameSpecifier::TypeSpec:
- return Visit(QualType(NNS->getAsType(), 0));
+ case NestedNameSpecifier::Kind::Type:
+ return Visit(QualType(NNS.getAsType(), 0));
}
llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
}
@@ -7708,10 +7686,9 @@ ExprResult Sema::BuildExpressionFromDeclTemplateArgument(
assert(VD->getDeclContext()->isRecord() &&
(isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD) ||
isa<IndirectFieldDecl>(VD)));
- QualType ClassType
- = Context.getTypeDeclType(cast<RecordDecl>(VD->getDeclContext()));
- NestedNameSpecifier *Qualifier =
- NestedNameSpecifier::Create(Context, nullptr, ClassType.getTypePtr());
+ CanQualType ClassType =
+ Context.getCanonicalTagType(cast<RecordDecl>(VD->getDeclContext()));
+ NestedNameSpecifier Qualifier(ClassType.getTypePtr());
SS.MakeTrivial(Context, Qualifier, Loc);
}
@@ -8716,13 +8693,12 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
}
// Create a new class template partial specialization declaration node.
- ClassTemplatePartialSpecializationDecl *PrevPartial
- = cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl);
+ ClassTemplatePartialSpecializationDecl *PrevPartial =
+ cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl);
ClassTemplatePartialSpecializationDecl *Partial =
ClassTemplatePartialSpecializationDecl::Create(
Context, Kind, DC, KWLoc, TemplateNameLoc, TemplateParams,
- ClassTemplate, CTAI.CanonicalConverted, WrittenTy->getType(),
- PrevPartial);
+ ClassTemplate, CTAI.CanonicalConverted, CanonType, PrevPartial);
Partial->setTemplateArgsAsWritten(TemplateArgs);
SetNestedNameSpecifier(*this, Partial, SS);
if (TemplateParameterLists.size() > 1 && SS.isSet()) {
@@ -9876,12 +9852,14 @@ static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) {
// name shall be a simple-template-id.
//
// C++98 has the same restriction, just worded differently.
- for (NestedNameSpecifier *NNS = SS.getScopeRep(); NNS;
- NNS = NNS->getPrefix())
- if (const Type *T = NNS->getAsType())
- if (isa<TemplateSpecializationType>(T))
- return true;
-
+ for (NestedNameSpecifier NNS = SS.getScopeRep();
+ NNS.getKind() == NestedNameSpecifier::Kind::Type;
+ /**/) {
+ const Type *T = NNS.getAsType();
+ if (isa<TemplateSpecializationType>(T))
+ return true;
+ NNS = T->getPrefix();
+ }
return false;
}
@@ -10783,7 +10761,7 @@ TypeResult Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// This has to hold, because SS is expected to be defined.
assert(Name && "Expected a name in a dependent tag");
- NestedNameSpecifier *NNS = SS.getScopeRep();
+ NestedNameSpecifier NNS = SS.getScopeRep();
if (!NNS)
return true;
@@ -10921,11 +10899,12 @@ static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II,
return false;
// ... within an explicitly-written template specialization...
- if (!NNS || !NNS.getNestedNameSpecifier()->getAsType())
+ if (NNS.getNestedNameSpecifier().getKind() != NestedNameSpecifier::Kind::Type)
return false;
- TypeLoc EnableIfTy = NNS.getTypeLoc();
- TemplateSpecializationTypeLoc EnableIfTSTLoc =
- EnableIfTy.getAs<TemplateSpecializationTypeLoc>();
+
+ // FIXME: Look through sugar.
+ auto EnableIfTSTLoc =
+ NNS.castAsTypeLoc().getAs<TemplateSpecializationTypeLoc>();
if (!EnableIfTSTLoc || EnableIfTSTLoc.getNumArgs() == 0)
return false;
const TemplateSpecializationType *EnableIfTST = EnableIfTSTLoc.getTypePtr();
@@ -11022,7 +11001,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
if (!Ctx) {
// If the nested-name-specifier is dependent and couldn't be
// resolved to a type, build a typename type.
- assert(QualifierLoc.getNestedNameSpecifier()->isDependent());
+ assert(QualifierLoc.getNestedNameSpecifier().isDependent());
return Context.getDependentNameType(Keyword,
QualifierLoc.getNestedNameSpecifier(),
&II);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 902b97e99cc8a..2506f0d0c7df5 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2103,26 +2103,19 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
Result != TemplateDeductionResult::Success)
return Result;
- QualType TP;
- if (MPP->isSugared()) {
- TP = S.Context.getTypeDeclType(MPP->getMostRecentCXXRecordDecl());
- } else {
- NestedNameSpecifier *QP = MPP->getQualifier();
- if (QP->getKind() == NestedNameSpecifier::Identifier)
- // Skip translation if it's a non-deduced context anyway.
- return TemplateDeductionResult::Success;
- TP = QualType(QP->translateToType(S.Context), 0);
- }
+ QualType TP =
+ MPP->isSugared()
+ ? S.Context.getCanonicalTagType(MPP->getMostRecentCXXRecordDecl())
+ : QualType(MPP->getQualifier().getAsType(), 0);
assert(!TP.isNull() && "member pointer with non-type class");
- QualType TA;
- if (MPA->isSugared()) {
- TA = S.Context.getTypeDeclType(MPA->getMostRecentCXXRecordDecl());
- } else {
- NestedNameSpecifier *QA = MPA->getQualifier();
- TA = QualType(QA->translateToType(S.Context), 0).getUnqualifiedType();
- }
+ QualType TA =
+ MPA->isSugared()
+ ? S.Context.getCanonicalTagType(MPA->getMostRecentCXXRecordDecl())
+ : QualType(MPA->getQualifier().getAsType(), 0)
+ .getUnqualifiedType();
assert(!TA.isNull() && "member pointer with non-type class");
+
return DeduceTemplateArgumentsByTypeMatch(
S, TemplateParams, TP, TA, Info, Deduced, SubTDF,
degradeCallPartialOrderingKind(POK),
@@ -6668,19 +6661,13 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
/// Mark the template parameters that are used by the given
/// nested name specifier.
-static void
-MarkUsedTemplateParameters(ASTContext &Ctx,
- NestedNameSpecifier *NNS,
- bool OnlyDeduced,
- unsigned Depth,
- llvm::SmallBitVector &Used) {
- if (!NNS)
+static void MarkUsedTemplateParameters(ASTContext &Ctx, NestedNameSpecifier NNS,
+ bool OnlyDeduced, unsigned Depth,
+ llvm::SmallBitVector &Used) {
+ if (NNS.getKind() != NestedNameSpecifier::Kind::Type)
return;
-
- MarkUsedTemplateParameters(Ctx, NNS->getPrefix(), OnlyDeduced, Depth,
- Used);
- MarkUsedTemplateParameters(Ctx, QualType(NNS->getAsType(), 0),
- OnlyDeduced, Depth, Used);
+ MarkUsedTemplateParameters(Ctx, QualType(NNS.getAsType(), 0), OnlyDeduced,
+ Depth, Used);
}
/// Mark the template parameters that are used by the given
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index 037001a0b2bbc..c8ac720dbe632 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -180,10 +180,17 @@ class ExtractTypeForDeductionGuide
MaterializedTypedefs.push_back(Decl);
}
- QualType TDTy = Context.getTypedefType(Decl);
- TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(TDTy);
- TypedefTL.setNameLoc(TL.getNameLoc());
+ NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc();
+ if (QualifierLoc) {
+ QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc);
+ if (!QualifierLoc)
+ return QualType();
+ }
+ QualType TDTy = Context.getTypedefType(
+ T->getKeyword(), QualifierLoc.getNestedNameSpecifier(), Decl);
+ TLB.push<TypedefTypeLoc>(TDTy).set(TL.getElaboratedKeywordLoc(),
+ QualifierLoc, TL.getNameLoc());
return TDTy;
}
};
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 5c14d890f94d5..1e01723fbc93f 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -353,45 +353,50 @@ Response HandleFunctionTemplateDecl(Sema &SemaRef,
SemaRef.Context),
/*Final=*/false);
- NestedNameSpecifier *NNS = FTD->getTemplatedDecl()->getQualifier();
-
- while (const Type *Ty = NNS ? NNS->getAsType() : nullptr) {
- if (NNS->isInstantiationDependent()) {
- if (const auto *TSTy = Ty->getAs<TemplateSpecializationType>()) {
- ArrayRef<TemplateArgument> Arguments = TSTy->template_arguments();
- // Prefer template arguments from the injected-class-type if possible.
- // For example,
- // ```cpp
- // template <class... Pack> struct S {
- // template <class T> void foo();
- // };
- // template <class... Pack> template <class T>
- // ^^^^^^^^^^^^^ InjectedTemplateArgs
- // They're of kind TemplateArgument::Pack, not of
- // TemplateArgument::Type.
- // void S<Pack...>::foo() {}
- // ^^^^^^^
- // TSTy->template_arguments() (which are of PackExpansionType)
- // ```
- // This meets the contract in
- // TreeTransform::TryExpandParameterPacks that the template arguments
- // for unexpanded parameters should be of a Pack kind.
- if (TSTy->isCurrentInstantiation()) {
- auto *RD = TSTy->getCanonicalTypeInternal()->getAsCXXRecordDecl();
- if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate())
- Arguments = CTD->getInjectedTemplateArgs(SemaRef.Context);
- else if (auto *Specialization =
- dyn_cast<ClassTemplateSpecializationDecl>(RD))
- Arguments =
- Specialization->getTemplateInstantiationArgs().asArray();
- }
- Result.addOuterTemplateArguments(
- TSTy->getTemplateName().getAsTemplateDecl(), Arguments,
- /*Final=*/false);
- }
- }
+ NestedNameSpecifier NNS = FTD->getTemplatedDecl()->getQualifier();
+
+ for (const Type *Ty = NNS.getKind() == NestedNameSpecifier::Kind::Type
+ ? NNS.getAsType()
+ : nullptr,
+ *NextTy = nullptr;
+ Ty && Ty->isInstantiationDependentType();
+ Ty = std::exchange(NextTy, nullptr)) {
+ if (NestedNameSpecifier P = Ty->getPrefix();
+ P.getKind() == NestedNameSpecifier::Kind::Type)
+ NextTy = P.getAsType();
+ const auto *TSTy = dyn_cast<TemplateSpecializationType>(Ty);
+ if (!TSTy)
+ continue;
- NNS = NNS->getPrefix();
+ ArrayRef<TemplateArgument> Arguments = TSTy->template_arguments();
+ // Prefer template arguments from the injected-class-type if possible.
+ // For example,
+ // ```cpp
+ // template <class... Pack> struct S {
+ // template <class T> void foo();
+ // };
+ // template <class... Pack> template <class T>
+ // ^^^^^^^^^^^^^ InjectedTemplateArgs
+ // They're of kind TemplateArgument::Pack, not of
+ // TemplateArgument::Type.
+ // void S<Pack...>::foo() {}
+ // ^^^^^^^
+ // TSTy->template_arguments() (which are of PackExpansionType)
+ // ```
+ // This meets the contract in
+ // TreeTransform::TryExpandParameterPacks that the template arguments
+ // for unexpanded parameters should be of a Pack kind.
+ if (TSTy->isCurrentInstantiation()) {
+ auto *RD = TSTy->getCanonicalTypeInternal()->getAsCXXRecordDecl();
+ if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate())
+ Arguments = CTD->getInjectedTemplateArgs(SemaRef.Context);
+ else if (auto *Specialization =
+ dyn_cast<ClassTemplateSpecializationDecl>(RD))
+ Arguments = Specialization->getTemplateInstantiationArgs().asArray();
+ }
+ Result.addOuterTemplateArguments(
+ TSTy->getTemplateName().getAsTemplateDecl(), Arguments,
+ /*Final=*/false);
}
}
@@ -1595,15 +1600,9 @@ namespace {
VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
TypeSourceInfo *TSInfo, QualType T);
- /// Check for tag mismatches when instantiating an
- /// elaborated type.
- QualType RebuildElaboratedType(SourceLocation KeywordLoc,
- ElaboratedTypeKeyword Keyword,
- NestedNameSpecifierLoc QualifierLoc,
- QualType T);
-
TemplateName
- TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
+ TransformTemplateName(NestedNameSpecifierLoc &QualifierLoc,
+ SourceLocation TemplateKWLoc, TemplateName Name,
SourceLocation NameLoc,
QualType ObjectType = QualType(),
NamedDecl *FirstQualifierInScope = nullptr,
@@ -2080,9 +2079,9 @@ VarDecl *TemplateInstantiator::RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
}
TemplateName TemplateInstantiator::TransformTemplateName(
- CXXScopeSpec &SS, TemplateName Name, SourceLocation NameLoc,
- QualType ObjectType, NamedDecl *FirstQualifierInScope,
- bool AllowInjectedClassName) {
+ NestedNameSpecifierLoc &QualifierLoc, SourceLocation TemplateKWLoc,
+ TemplateName Name, SourceLocation NameLoc, QualType ObjectType,
+ NamedDecl *FirstQualifierInScope, bool AllowInjectedClassName) {
if (TemplateTemplateParmDecl *TTP
= dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl())) {
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
@@ -2129,6 +2128,12 @@ TemplateName TemplateInstantiator::TransformTemplateName(
TemplateName Template = Arg.getAsTemplate();
assert(!Template.isNull() && "Null template template argument");
+ if (NestedNameSpecifier Qualifier = Template.getQualifier()) {
+ NestedNameSpecifierLocBuilder Builder;
+ Builder.MakeTrivial(SemaRef.Context, Qualifier, NameLoc);
+ QualifierLoc = Builder.getWithLocInContext(SemaRef.Context);
+ }
+
return getSema().Context.getSubstTemplateTemplateParm(
Template, AssociatedDecl, TTP->getIndex(), PackIndex, Final);
}
@@ -4519,14 +4524,14 @@ Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
}
TemplateName
-Sema::SubstTemplateName(NestedNameSpecifierLoc QualifierLoc,
- TemplateName Name, SourceLocation Loc,
+Sema::SubstTemplateName(SourceLocation TemplateKWLoc,
+ NestedNameSpecifierLoc &QualifierLoc, TemplateName Name,
+ SourceLocation NameLoc,
const MultiLevelTemplateArgumentList &TemplateArgs) {
- TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
+ TemplateInstantiator Instantiator(*this, TemplateArgs, NameLoc,
DeclarationName());
- CXXScopeSpec SS;
- SS.Adopt(QualifierLoc);
- return Instantiator.TransformTemplateName(SS, Name, Loc);
+ return Instantiator.TransformTemplateName(QualifierLoc, TemplateKWLoc, Name,
+ NameLoc);
}
static const Decl *getCanonicalParmVarDecl(const Decl *D) {
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 5e49645ec2379..755cbb6e4547d 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3783,19 +3783,18 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
D->getPosition(), D->isParameterPack(), D->getIdentifier(),
D->wasDeclaredWithTypename(), InstParams);
if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) {
- NestedNameSpecifierLoc QualifierLoc =
- D->getDefaultArgument().getTemplateQualifierLoc();
- QualifierLoc =
- SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgs);
+ const TemplateArgumentLoc &A = D->getDefaultArgument();
+ NestedNameSpecifierLoc QualifierLoc = A.getTemplateQualifierLoc();
+ // FIXME: Pass in the template keyword location.
TemplateName TName = SemaRef.SubstTemplateName(
- QualifierLoc, D->getDefaultArgument().getArgument().getAsTemplate(),
- D->getDefaultArgument().getTemplateNameLoc(), TemplateArgs);
+ A.getTemplateKWLoc(), QualifierLoc, A.getArgument().getAsTemplate(),
+ A.getTemplateNameLoc(), TemplateArgs);
if (!TName.isNull())
Param->setDefaultArgument(
SemaRef.Context,
TemplateArgumentLoc(SemaRef.Context, TemplateArgument(TName),
- D->getDefaultArgument().getTemplateQualifierLoc(),
- D->getDefaultArgument().getTemplateNameLoc()));
+ A.getTemplateKWLoc(), QualifierLoc,
+ A.getTemplateNameLoc()));
}
Param->setAccess(AS_public);
Param->setImplicit(D->isImplicit());
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 2bb95a738e0ab..05ab55c6d304c 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -3654,11 +3654,22 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) {
// here: even (e.g.) "int ::x" is visually ambiguous even though it's
// formally unambiguous.
if (StartsWithDeclaratorId && D.getCXXScopeSpec().isValid()) {
- for (NestedNameSpecifier *NNS = D.getCXXScopeSpec().getScopeRep(); NNS;
- NNS = NNS->getPrefix()) {
- if (NNS->getKind() == NestedNameSpecifier::Global)
+ NestedNameSpecifier NNS = D.getCXXScopeSpec().getScopeRep();
+ for (;;) {
+ switch (NNS.getKind()) {
+ case NestedNameSpecifier::Kind::Global:
return;
+ case NestedNameSpecifier::Kind::Type:
+ NNS = NNS.getAsType()->getPrefix();
+ continue;
+ case NestedNameSpecifier::Kind::Namespace:
+ NNS = NNS.getAsNamespaceAndPrefix().Prefix;
+ continue;
+ default:
+ goto out;
+ }
}
+ out:;
}
S.Diag(Paren.Loc, diag::warn_redundant_parens_around_declarator)
@@ -5321,7 +5332,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
state.getDeclarator()
.getCXXScopeSpec()
.getScopeRep()
- ->getKind() == NestedNameSpecifier::TypeSpec) ||
+ .getKind() == NestedNameSpecifier::Kind::Type) ||
state.getDeclarator().getContext() ==
DeclaratorContext::Member ||
state.getDeclarator().getContext() ==
diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp
index eddad958a7ceb..9b9dd172003a0 100644
--- a/clang/lib/Sema/SemaTypeTraits.cpp
+++ b/clang/lib/Sema/SemaTypeTraits.cpp
@@ -2016,11 +2016,10 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) {
// std::is_xxx<>::value
if (const auto *VD = dyn_cast<VarDecl>(Ref->getDecl());
Ref->hasQualifier() && VD && VD->getIdentifier()->isStr("value")) {
- const Type *T = Ref->getQualifier()->getAsType();
- if (!T)
+ NestedNameSpecifier Qualifier = Ref->getQualifier();
+ if (Qualifier.getKind() != NestedNameSpecifier::Kind::Type)
return std::nullopt;
- const TemplateSpecializationType *Ts =
- T->getAs<TemplateSpecializationType>();
+ const auto *Ts = Qualifier.getAsType()->getAs<TemplateSpecializationType>();
if (!Ts)
return std::nullopt;
const TemplateDecl *D = Ts->getTemplateName().getAsTemplateDecl();
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 1537d63161fcb..2f357c837e502 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -591,12 +591,12 @@ class TreeTransform {
/// By default, transforms the template name by transforming the declarations
/// and nested-name-specifiers that occur within the template name.
/// Subclasses may override this function to provide alternate behavior.
- TemplateName
- TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
- SourceLocation NameLoc,
- QualType ObjectType = QualType(),
- NamedDecl *FirstQualifierInScope = nullptr,
- bool AllowInjectedClassName = false);
+ TemplateName TransformTemplateName(NestedNameSpecifierLoc &QualifierLoc,
+ SourceLocation TemplateKWLoc,
+ TemplateName Name, SourceLocation NameLoc,
+ QualType ObjectType = QualType(),
+ NamedDecl *FirstQualifierInScope = nullptr,
+ bool AllowInjectedClassName = false);
/// Transform the given template argument.
///
@@ -1149,7 +1149,7 @@ class TreeTransform {
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
- if (QualifierLoc.getNestedNameSpecifier()->isDependent()) {
+ if (QualifierLoc.getNestedNameSpecifier().isDependent()) {
// If the name is still dependent, just build a new dependent name type.
if (!SemaRef.computeDeclContext(SS))
return SemaRef.Context.getDependentNameType(Keyword,
@@ -4583,7 +4583,7 @@ NestedNameSpecifierLoc TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
auto insertNNS = [&Qualifiers](NestedNameSpecifierLoc NNS) {
for (NestedNameSpecifierLoc Qualifier = NNS; Qualifier;
- Qualifier = Qualifier.getPrefix())
+ Qualifier = Qualifier.getAsNamespaceAndPrefix().Prefix)
Qualifiers.push_back(Qualifier);
};
insertNNS(NNS);
@@ -4591,76 +4591,87 @@ NestedNameSpecifierLoc TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
CXXScopeSpec SS;
while (!Qualifiers.empty()) {
NestedNameSpecifierLoc Q = Qualifiers.pop_back_val();
- NestedNameSpecifier *QNNS = Q.getNestedNameSpecifier();
-
- switch (QNNS->getKind()) {
- case NestedNameSpecifier::Identifier: {
- Sema::NestedNameSpecInfo IdInfo(QNNS->getAsIdentifier(),
- Q.getLocalBeginLoc(), Q.getLocalEndLoc(),
- ObjectType);
- if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/nullptr, IdInfo, false,
- SS, FirstQualifierInScope, false))
- return NestedNameSpecifierLoc();
- break;
- }
+ NestedNameSpecifier QNNS = Q.getNestedNameSpecifier();
- case NestedNameSpecifier::Namespace: {
+ switch (QNNS.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
+
+ case NestedNameSpecifier::Kind::Namespace: {
auto *NS = cast<NamespaceBaseDecl>(getDerived().TransformDecl(
- Q.getLocalBeginLoc(), QNNS->getAsNamespace()));
+ Q.getLocalBeginLoc(), const_cast<NamespaceBaseDecl *>(
+ QNNS.getAsNamespaceAndPrefix().Namespace)));
SS.Extend(SemaRef.Context, NS, Q.getLocalBeginLoc(), Q.getLocalEndLoc());
break;
}
- case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Kind::Global:
// There is no meaningful transformation that one could perform on the
// global scope.
SS.MakeGlobal(SemaRef.Context, Q.getBeginLoc());
break;
- case NestedNameSpecifier::Super: {
- CXXRecordDecl *RD =
- cast_or_null<CXXRecordDecl>(getDerived().TransformDecl(
- SourceLocation(), QNNS->getAsRecordDecl()));
- SS.MakeSuper(SemaRef.Context, RD, Q.getBeginLoc(), Q.getEndLoc());
+ case NestedNameSpecifier::Kind::MicrosoftSuper: {
+ CXXRecordDecl *RD = cast_or_null<CXXRecordDecl>(
+ getDerived().TransformDecl(SourceLocation(), QNNS.getAsRecordDecl()));
+ SS.MakeMicrosoftSuper(SemaRef.Context, RD, Q.getBeginLoc(),
+ Q.getEndLoc());
break;
}
- case NestedNameSpecifier::TypeSpec: {
- TypeLoc TL = TransformTypeInObjectScope(Q.getTypeLoc(), ObjectType,
- FirstQualifierInScope, SS);
-
- if (!TL)
- return NestedNameSpecifierLoc();
+ case NestedNameSpecifier::Kind::Type: {
+ assert(SS.isEmpty());
+ TypeLoc TL = Q.castAsTypeLoc();
+
+ if (auto DNT = TL.getAs<DependentNameTypeLoc>()) {
+ NestedNameSpecifierLoc QualifierLoc = DNT.getQualifierLoc();
+ if (QualifierLoc) {
+ QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(
+ QualifierLoc, ObjectType, FirstQualifierInScope);
+ if (!QualifierLoc)
+ return NestedNameSpecifierLoc();
+ ObjectType = QualType();
+ FirstQualifierInScope = nullptr;
+ }
+ SS.Adopt(QualifierLoc);
+ Sema::NestedNameSpecInfo IdInfo(
+ const_cast<IdentifierInfo *>(DNT.getTypePtr()->getIdentifier()),
+ DNT.getNameLoc(), Q.getLocalEndLoc(), ObjectType);
+ if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/nullptr, IdInfo,
+ false, SS,
+ FirstQualifierInScope, false))
+ return NestedNameSpecifierLoc();
+ return SS.getWithLocInContext(SemaRef.Context);
+ }
QualType T = TL.getType();
+ TypeLocBuilder TLB;
+ if (!getDerived().AlreadyTransformed(T)) {
+ T = TransformTypeInObjectScope(TLB, TL, ObjectType,
+ FirstQualifierInScope);
+ if (T.isNull())
+ return NestedNameSpecifierLoc();
+ TL = TLB.getTypeLocInContext(SemaRef.Context, T);
+ }
+
if (T->isDependentType() || T->isRecordType() ||
(SemaRef.getLangOpts().CPlusPlus11 && T->isEnumeralType())) {
if (T->isEnumeralType())
SemaRef.Diag(TL.getBeginLoc(),
diag::warn_cxx98_compat_enum_nested_name_spec);
-
- if (const auto ETL = TL.getAs<ElaboratedTypeLoc>()) {
- SS.Adopt(ETL.getQualifierLoc());
- TL = ETL.getNamedTypeLoc();
- }
-
- SS.Extend(SemaRef.Context, TL, Q.getLocalEndLoc());
+ SS.Make(SemaRef.Context, TL, Q.getLocalEndLoc());
break;
}
// If the nested-name-specifier is an invalid type def, don't emit an
// error because a previous error should have already been emitted.
TypedefTypeLoc TTL = TL.getAsAdjusted<TypedefTypeLoc>();
- if (!TTL || !TTL.getTypedefNameDecl()->isInvalidDecl()) {
+ if (!TTL || !TTL.getDecl()->isInvalidDecl()) {
SemaRef.Diag(TL.getBeginLoc(), diag::err_nested_name_spec_non_tag)
<< T << SS.getRange();
}
return NestedNameSpecifierLoc();
}
}
-
- // The qualifier-in-scope and object type only apply to the leftmost entity.
- FirstQualifierInScope = nullptr;
- ObjectType = QualType();
}
// Don't rebuild the nested-name-specifier if we don't have to.
@@ -4746,30 +4757,32 @@ template <typename Derived>
TemplateName TreeTransform<Derived>::RebuildTemplateName(
CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
IdentifierOrOverloadedOperator IO, SourceLocation NameLoc,
- QualType ObjectType, NamedDecl *FirstQualifierInScope,
- bool AllowInjectedClassName) {
- if (const IdentifierInfo *II = IO.getIdentifier()) {
+ QualType ObjectType, bool AllowInjectedClassName) {
+ if (const IdentifierInfo *II = IO.getIdentifier())
return getDerived().RebuildTemplateName(SS, TemplateKWLoc, *II, NameLoc,
- ObjectType, FirstQualifierInScope,
- AllowInjectedClassName);
- }
+ ObjectType, AllowInjectedClassName);
return getDerived().RebuildTemplateName(SS, TemplateKWLoc, IO.getOperator(),
NameLoc, ObjectType,
AllowInjectedClassName);
}
-template<typename Derived>
-TemplateName
-TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
- TemplateName Name,
- SourceLocation NameLoc,
- QualType ObjectType,
- NamedDecl *FirstQualifierInScope,
- bool AllowInjectedClassName) {
+template <typename Derived>
+TemplateName TreeTransform<Derived>::TransformTemplateName(
+ NestedNameSpecifierLoc &QualifierLoc, SourceLocation TemplateKWLoc,
+ TemplateName Name, SourceLocation NameLoc, QualType ObjectType,
+ NamedDecl *FirstQualifierInScope, bool AllowInjectedClassName) {
if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
+ // FIXME: Preserve UsingTemplateName.
TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl();
assert(Template && "qualified template name must refer to a template");
+ if (QualifierLoc) {
+ QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(
+ QualifierLoc, ObjectType, FirstQualifierInScope);
+ if (!QualifierLoc)
+ return TemplateName();
+ }
+
TemplateDecl *TransTemplate
= cast_or_null<TemplateDecl>(getDerived().TransformDecl(NameLoc,
Template));
@@ -4777,41 +4790,67 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
return TemplateName();
if (!getDerived().AlwaysRebuild() &&
- SS.getScopeRep() == QTN->getQualifier() &&
+ QualifierLoc.getNestedNameSpecifier() == QTN->getQualifier() &&
TransTemplate == Template)
return Name;
-
+ CXXScopeSpec SS;
+ SS.Adopt(QualifierLoc);
return getDerived().RebuildTemplateName(SS, QTN->hasTemplateKeyword(),
TransTemplate);
}
if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
- if (SS.getScopeRep()) {
- // These apply to the scope specifier, not the template.
+ if (QualifierLoc) {
+ QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(
+ QualifierLoc, ObjectType, FirstQualifierInScope);
+ if (!QualifierLoc)
+ return TemplateName();
+ // The qualifier-in-scope and object type only apply to the leftmost
+ // entity.
ObjectType = QualType();
- FirstQualifierInScope = nullptr;
}
if (!getDerived().AlwaysRebuild() &&
- SS.getScopeRep() == DTN->getQualifier() &&
+ QualifierLoc.getNestedNameSpecifier() == DTN->getQualifier() &&
ObjectType.isNull())
return Name;
- // FIXME: Preserve the location of the "template" keyword.
- SourceLocation TemplateKWLoc = NameLoc;
- return getDerived().RebuildTemplateName(
- SS, TemplateKWLoc, DTN->getName(), NameLoc, ObjectType,
+ CXXScopeSpec SS;
+ SS.Adopt(QualifierLoc);
+ return getDerived().RebuildTemplateName(SS, TemplateKWLoc, DTN->getName(),
+ NameLoc, ObjectType,
+ AllowInjectedClassName);
+ }
+
+ if (SubstTemplateTemplateParmStorage *S =
+ Name.getAsSubstTemplateTemplateParm()) {
+ TemplateName NewName = getDerived().TransformTemplateName(
+ QualifierLoc, TemplateKWLoc, S->getReplacement(), NameLoc, ObjectType,
FirstQualifierInScope, AllowInjectedClassName);
+ if (NewName.isNull())
+ return TemplateName();
+ Decl *AssociatedDecl =
+ getDerived().TransformDecl(NameLoc, S->getAssociatedDecl());
+ if (!getDerived().AlwaysRebuild() && NewName == S->getReplacement() &&
+ AssociatedDecl == S->getAssociatedDecl())
+ return Name;
+ return SemaRef.Context.getSubstTemplateTemplateParm(
+ NewName, AssociatedDecl, S->getIndex(), S->getPackIndex(),
+ S->getFinal());
}
- // FIXME: Try to preserve more of the TemplateName.
+ assert(!Name.getAsDeducedTemplateName() &&
+ "DeducedTemplateName should not escape partial ordering");
+
if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+ assert(!QualifierLoc && "missed a Qualified Template");
TemplateDecl *TransTemplate
= cast_or_null<TemplateDecl>(getDerived().TransformDecl(NameLoc,
Template));
if (!TransTemplate)
return TemplateName();
+ CXXScopeSpec SS;
return getDerived().RebuildTemplateName(SS, /*TemplateKeyword=*/false,
TransTemplate);
}
@@ -4903,21 +4942,16 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
case TemplateArgument::Template: {
NestedNameSpecifierLoc QualifierLoc = Input.getTemplateQualifierLoc();
- if (QualifierLoc) {
- QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc);
- if (!QualifierLoc)
- return true;
- }
- CXXScopeSpec SS;
- SS.Adopt(QualifierLoc);
TemplateName Template = getDerived().TransformTemplateName(
- SS, Arg.getAsTemplate(), Input.getTemplateNameLoc());
+ QualifierLoc, Input.getTemplateKWLoc(), Arg.getAsTemplate(),
+ Input.getTemplateNameLoc());
if (Template.isNull())
return true;
Output = TemplateArgumentLoc(SemaRef.Context, TemplateArgument(Template),
- QualifierLoc, Input.getTemplateNameLoc());
+ Input.getTemplateKWLoc(), QualifierLoc,
+ Input.getTemplateNameLoc());
return false;
}
@@ -6620,23 +6654,38 @@ QualType TreeTransform<Derived>::TransformFunctionNoProtoType(
template <typename Derived>
QualType TreeTransform<Derived>::TransformUnresolvedUsingType(
TypeLocBuilder &TLB, UnresolvedUsingTypeLoc TL) {
+
const UnresolvedUsingType *T = TL.getTypePtr();
- Decl *D = getDerived().TransformDecl(TL.getNameLoc(), T->getDecl());
+ bool Changed = false;
+
+ NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc();
+ if (NestedNameSpecifierLoc OldQualifierLoc = QualifierLoc) {
+ QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc);
+ if (!QualifierLoc)
+ return QualType();
+ Changed |= QualifierLoc != OldQualifierLoc;
+ }
+
+ auto *D = getDerived().TransformDecl(TL.getNameLoc(), T->getDecl());
if (!D)
return QualType();
+ Changed |= D != T->getDecl();
QualType Result = TL.getType();
- if (getDerived().AlwaysRebuild() || D != T->getDecl()) {
- Result = getDerived().RebuildUnresolvedUsingType(TL.getNameLoc(), D);
+ if (getDerived().AlwaysRebuild() || Changed) {
+ Result = getDerived().RebuildUnresolvedUsingType(
+ T->getKeyword(), QualifierLoc.getNestedNameSpecifier(), TL.getNameLoc(),
+ D);
if (Result.isNull())
return QualType();
}
- // We might get an arbitrary type spec type back. We should at
- // least always get a type spec type, though.
- TypeSpecTypeLoc NewTL = TLB.pushTypeSpec(Result);
- NewTL.setNameLoc(TL.getNameLoc());
-
+ if (isa<UsingType>(Result))
+ TLB.push<UsingTypeLoc>(Result).set(TL.getElaboratedKeywordLoc(),
+ QualifierLoc, TL.getNameLoc());
+ else
+ TLB.push<UnresolvedUsingTypeLoc>(Result).set(TL.getElaboratedKeywordLoc(),
+ QualifierLoc, TL.getNameLoc());
return Result;
}
@@ -6644,25 +6693,37 @@ template <typename Derived>
QualType TreeTransform<Derived>::TransformUsingType(TypeLocBuilder &TLB,
UsingTypeLoc TL) {
const UsingType *T = TL.getTypePtr();
+ bool Changed = false;
+
+ NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc();
+ if (NestedNameSpecifierLoc OldQualifierLoc = QualifierLoc) {
+ QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc);
+ if (!QualifierLoc)
+ return QualType();
+ Changed |= QualifierLoc != OldQualifierLoc;
+ }
- auto *Found = cast_or_null<UsingShadowDecl>(getDerived().TransformDecl(
- TL.getLocalSourceRange().getBegin(), T->getFoundDecl()));
- if (!Found)
+ auto *D = cast_or_null<UsingShadowDecl>(
+ getDerived().TransformDecl(TL.getNameLoc(), T->getDecl()));
+ if (!D)
return QualType();
+ Changed |= D != T->getDecl();
- QualType Underlying = getDerived().TransformType(T->desugar());
- if (Underlying.isNull())
+ QualType UnderlyingType = getDerived().TransformType(T->desugar());
+ if (UnderlyingType.isNull())
return QualType();
+ Changed |= UnderlyingType != T->desugar();
QualType Result = TL.getType();
- if (getDerived().AlwaysRebuild() || Found != T->getFoundDecl() ||
- Underlying != T->getUnderlyingType()) {
- Result = getDerived().RebuildUsingType(Found, Underlying);
+ if (getDerived().AlwaysRebuild() || Changed) {
+ Result = getDerived().RebuildUsingType(
+ T->getKeyword(), QualifierLoc.getNestedNameSpecifier(), D,
+ UnderlyingType);
if (Result.isNull())
return QualType();
}
-
- TLB.pushTypeSpec(Result).setNameLoc(TL.getNameLoc());
+ TLB.push<UsingTypeLoc>(Result).set(TL.getElaboratedKeywordLoc(), QualifierLoc,
+ TL.getNameLoc());
return Result;
}
@@ -6670,23 +6731,34 @@ template<typename Derived>
QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB,
TypedefTypeLoc TL) {
const TypedefType *T = TL.getTypePtr();
- TypedefNameDecl *Typedef
- = cast_or_null<TypedefNameDecl>(getDerived().TransformDecl(TL.getNameLoc(),
- T->getDecl()));
+ bool Changed = false;
+
+ NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc();
+ if (NestedNameSpecifierLoc OldQualifierLoc = QualifierLoc) {
+ QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc);
+ if (!QualifierLoc)
+ return QualType();
+ Changed |= QualifierLoc != OldQualifierLoc;
+ }
+
+ auto *Typedef = cast_or_null<TypedefNameDecl>(
+ getDerived().TransformDecl(TL.getNameLoc(), T->getDecl()));
if (!Typedef)
return QualType();
+ Changed |= Typedef != T->getDecl();
+
+ // FIXME: Transform the UnderlyingType if different from decl.
QualType Result = TL.getType();
- if (getDerived().AlwaysRebuild() ||
- Typedef != T->getDecl()) {
- Result = getDerived().RebuildTypedefType(Typedef);
+ if (getDerived().AlwaysRebuild() || Changed) {
+ Result = getDerived().RebuildTypedefType(
+ T->getKeyword(), QualifierLoc.getNestedNameSpecifier(), Typedef);
if (Result.isNull())
return QualType();
}
- TypedefTypeLoc NewTL = TLB.push<TypedefTypeLoc>(Result);
- NewTL.setNameLoc(TL.getNameLoc());
-
+ TLB.push<TypedefTypeLoc>(Result).set(TL.getElaboratedKeywordLoc(),
+ QualifierLoc, TL.getNameLoc());
return Result;
}
@@ -6922,9 +6994,10 @@ QualType TreeTransform<Derived>::TransformDeducedTemplateSpecializationType(
TypeLocBuilder &TLB, DeducedTemplateSpecializationTypeLoc TL) {
const DeducedTemplateSpecializationType *T = TL.getTypePtr();
- CXXScopeSpec SS;
+ NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc();
TemplateName TemplateName = getDerived().TransformTemplateName(
- SS, T->getTemplateName(), TL.getTemplateNameLoc());
+ QualifierLoc, /*TemplateKELoc=*/SourceLocation(), T->getTemplateName(),
+ TL.getTemplateNameLoc());
if (TemplateName.isNull())
return QualType();
@@ -7301,9 +7374,16 @@ QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB,
template <typename Derived>
QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
- TypeLocBuilder &TLB,
- TemplateSpecializationTypeLoc TL,
- TemplateName Template) {
+ TypeLocBuilder &TLB, TemplateSpecializationTypeLoc TL) {
+ const TemplateSpecializationType *T = TL.getTypePtr();
+
+ NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc();
+ TemplateName Template = getDerived().TransformTemplateName(
+ QualifierLoc, TL.getTemplateKeywordLoc(), T->getTemplateName(),
+ TL.getTemplateNameLoc());
+ if (Template.isNull())
+ return QualType();
+
TemplateArgumentListInfo NewTemplateArgs;
NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
@@ -7538,15 +7618,22 @@ QualType TreeTransform<Derived>::TransformDependentNameType(
return TransformDependentNameType(TLB, TL, false);
}
-template<typename Derived>
+template <typename Derived>
QualType TreeTransform<Derived>::TransformDependentNameType(
- TypeLocBuilder &TLB, DependentNameTypeLoc TL, bool DeducedTSTContext) {
+ TypeLocBuilder &TLB, DependentNameTypeLoc TL, bool DeducedTSTContext,
+ QualType ObjectType, NamedDecl *UnqualLookup) {
const DependentNameType *T = TL.getTypePtr();
- NestedNameSpecifierLoc QualifierLoc
- = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc());
- if (!QualifierLoc)
- return QualType();
+ NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc();
+ if (QualifierLoc) {
+ QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(
+ QualifierLoc, ObjectType, UnqualLookup);
+ if (!QualifierLoc)
+ return QualType();
+ } else {
+ assert((ObjectType.isNull() && !UnqualLookup) &&
+ "must be transformed by TransformNestedNameSpecifierLoc");
+ }
QualType Result
= getDerived().RebuildDependentNameType(T->getKeyword(),
@@ -7580,33 +7667,34 @@ QualType TreeTransform<Derived>::TransformDependentNameType(
return Result;
}
-template<typename Derived>
-QualType TreeTransform<Derived>::
- TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
- DependentTemplateSpecializationTypeLoc TL) {
- NestedNameSpecifierLoc QualifierLoc;
- if (TL.getQualifierLoc()) {
- QualifierLoc
- = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc());
- if (!QualifierLoc)
- return QualType();
- }
-
- CXXScopeSpec SS;
- SS.Adopt(QualifierLoc);
- return getDerived().TransformDependentTemplateSpecializationType(TLB, TL, SS);
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformDependentTemplateSpecializationType(
+ TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL) {
+ return getDerived().TransformDependentTemplateSpecializationType(
+ TLB, TL, QualType(), nullptr, false);
}
template <typename Derived>
QualType TreeTransform<Derived>::TransformDependentTemplateSpecializationType(
TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL,
- CXXScopeSpec &SS) {
+ QualType ObjectType, NamedDecl *UnqualLookup, bool AllowInjectedClassName) {
const DependentTemplateSpecializationType *T = TL.getTypePtr();
- TemplateArgumentListInfo NewTemplateArgs;
- NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
- NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
+ NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc();
+ if (QualifierLoc) {
+ QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(
+ QualifierLoc, ObjectType, UnqualLookup);
+ if (!QualifierLoc)
+ return QualType();
+ // These only apply to the leftmost prefix.
+ ObjectType = QualType();
+ UnqualLookup = nullptr;
+ }
+ CXXScopeSpec SS;
+ SS.Adopt(QualifierLoc);
+ TemplateArgumentListInfo NewTemplateArgs(TL.getLAngleLoc(),
+ TL.getRAngleLoc());
auto ArgsRange = llvm::make_range<TemplateArgumentLocContainerIterator<
DependentTemplateSpecializationTypeLoc>>({TL, 0}, {TL, TL.getNumArgs()});
@@ -7623,43 +7711,27 @@ QualType TreeTransform<Derived>::TransformDependentTemplateSpecializationType(
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() || SS.getScopeRep() != DTN.getQualifier() ||
- TemplateArgumentsChanged) {
+ TemplateArgumentsChanged || !ObjectType.isNull()) {
TemplateName Name = getDerived().RebuildTemplateName(
SS, TL.getTemplateKeywordLoc(), DTN.getName(), TL.getTemplateNameLoc(),
- /*ObjectType=*/QualType(), /*FirstQualifierInScope=*/nullptr,
- /*AllowInjectedClassName=*/false);
+ ObjectType, AllowInjectedClassName);
if (Name.isNull())
return QualType();
Result = getDerived().RebuildDependentTemplateSpecializationType(
- T->getKeyword(), SS.getScopeRep(), TL.getTemplateKeywordLoc(), Name,
+ T->getKeyword(), TL.getTemplateKeywordLoc(), Name,
TL.getTemplateNameLoc(), NewTemplateArgs,
/*AllowInjectedClassName=*/false);
if (Result.isNull())
return QualType();
}
- NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(SemaRef.Context);
- if (const ElaboratedType *ElabT = dyn_cast<ElaboratedType>(Result)) {
- QualType NamedT = ElabT->getNamedType();
-
- // Copy information relevant to the template specialization.
- TemplateSpecializationTypeLoc NamedTL
- = TLB.push<TemplateSpecializationTypeLoc>(NamedT);
- NamedTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc());
- NamedTL.setTemplateNameLoc(TL.getTemplateNameLoc());
- NamedTL.setLAngleLoc(TL.getLAngleLoc());
- NamedTL.setRAngleLoc(TL.getRAngleLoc());
- for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I)
- NamedTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo());
-
- // Copy information relevant to the elaborated type.
- ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
- NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc());
- NewTL.setQualifierLoc(QualifierLoc);
+ QualifierLoc = SS.getWithLocInContext(SemaRef.Context);
+ if (isa<TemplateSpecializationType>(Result)) {
+ TLB.push<TemplateSpecializationTypeLoc>(Result).set(
+ TL.getElaboratedKeywordLoc(), QualifierLoc, TL.getTemplateKeywordLoc(),
+ TL.getTemplateNameLoc(), NewTemplateArgs);
} else {
- assert(isa<DependentTemplateSpecializationType>(Result));
- DependentTemplateSpecializationTypeLoc SpecTL
- = TLB.push<DependentTemplateSpecializationTypeLoc>(Result);
+ auto SpecTL = TLB.push<DependentTemplateSpecializationTypeLoc>(Result);
SpecTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc());
SpecTL.setQualifierLoc(QualifierLoc);
SpecTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc());
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index bdef6d5a0fcae..f8e7e3e35df23 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -7978,18 +7978,15 @@ ASTRecordReader::readTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind) {
return readExpr();
case TemplateArgument::Type:
return readTypeSourceInfo();
- case TemplateArgument::Template: {
- NestedNameSpecifierLoc QualifierLoc =
- readNestedNameSpecifierLoc();
- SourceLocation TemplateNameLoc = readSourceLocation();
- return TemplateArgumentLocInfo(getASTContext(), QualifierLoc,
- TemplateNameLoc, SourceLocation());
- }
+ case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion: {
+ SourceLocation TemplateKWLoc = readSourceLocation();
NestedNameSpecifierLoc QualifierLoc = readNestedNameSpecifierLoc();
SourceLocation TemplateNameLoc = readSourceLocation();
- SourceLocation EllipsisLoc = readSourceLocation();
- return TemplateArgumentLocInfo(getASTContext(), QualifierLoc,
+ SourceLocation EllipsisLoc = Kind == TemplateArgument::TemplateExpansion
+ ? readSourceLocation()
+ : SourceLocation();
+ return TemplateArgumentLocInfo(getASTContext(), TemplateKWLoc, QualifierLoc,
TemplateNameLoc, EllipsisLoc);
}
case TemplateArgument::Null:
@@ -10113,41 +10110,37 @@ ASTRecordReader::readNestedNameSpecifierLoc() {
for (unsigned I = 0; I != N; ++I) {
auto Kind = readNestedNameSpecifierKind();
switch (Kind) {
- case NestedNameSpecifier::Identifier: {
- IdentifierInfo *II = readIdentifier();
- SourceRange Range = readSourceRange();
- Builder.Extend(Context, II, Range.getBegin(), Range.getEnd());
- break;
- }
-
- case NestedNameSpecifier::Namespace: {
+ case NestedNameSpecifier::Kind::Namespace: {
auto *NS = readDeclAs<NamespaceBaseDecl>();
SourceRange Range = readSourceRange();
Builder.Extend(Context, NS, Range.getBegin(), Range.getEnd());
break;
}
- case NestedNameSpecifier::TypeSpec: {
+ case NestedNameSpecifier::Kind::Type: {
TypeSourceInfo *T = readTypeSourceInfo();
if (!T)
return NestedNameSpecifierLoc();
SourceLocation ColonColonLoc = readSourceLocation();
- Builder.Extend(Context, T->getTypeLoc(), ColonColonLoc);
+ Builder.Make(Context, T->getTypeLoc(), ColonColonLoc);
break;
}
- case NestedNameSpecifier::Global: {
+ case NestedNameSpecifier::Kind::Global: {
SourceLocation ColonColonLoc = readSourceLocation();
Builder.MakeGlobal(Context, ColonColonLoc);
break;
}
- case NestedNameSpecifier::Super: {
+ case NestedNameSpecifier::Kind::MicrosoftSuper: {
CXXRecordDecl *RD = readDeclAs<CXXRecordDecl>();
SourceRange Range = readSourceRange();
- Builder.MakeSuper(Context, RD, Range.getBegin(), Range.getEnd());
+ Builder.MakeMicrosoftSuper(Context, RD, Range.getBegin(), Range.getEnd());
break;
}
+
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
}
}
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index ef7190da062ea..0f19805dd12c4 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -7075,49 +7075,50 @@ void ASTRecordWriter::AddQualifierInfo(const QualifierInfo &Info) {
AddTemplateParameterList(Info.TemplParamLists[i]);
}
-void ASTRecordWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+void ASTRecordWriter::AddNestedNameSpecifierLoc(
+ NestedNameSpecifierLoc QualifierLoc) {
// Nested name specifiers usually aren't too long. I think that 8 would
// typically accommodate the vast majority.
SmallVector<NestedNameSpecifierLoc , 8> NestedNames;
// Push each of the nested-name-specifiers's onto a stack for
// serialization in reverse order.
- while (NNS) {
- NestedNames.push_back(NNS);
- NNS = NNS.getPrefix();
+ while (QualifierLoc) {
+ NestedNames.push_back(QualifierLoc);
+ QualifierLoc = QualifierLoc.getAsNamespaceAndPrefix().Prefix;
}
Record->push_back(NestedNames.size());
while(!NestedNames.empty()) {
- NNS = NestedNames.pop_back_val();
- NestedNameSpecifier::SpecifierKind Kind
- = NNS.getNestedNameSpecifier()->getKind();
- Record->push_back(Kind);
+ QualifierLoc = NestedNames.pop_back_val();
+ NestedNameSpecifier Qualifier = QualifierLoc.getNestedNameSpecifier();
+ NestedNameSpecifier::Kind Kind = Qualifier.getKind();
+ Record->push_back(llvm::to_underlying(Kind));
switch (Kind) {
- case NestedNameSpecifier::Identifier:
- AddIdentifierRef(NNS.getNestedNameSpecifier()->getAsIdentifier());
- AddSourceRange(NNS.getLocalSourceRange());
+ case NestedNameSpecifier::Kind::Namespace:
+ AddDeclRef(Qualifier.getAsNamespaceAndPrefix().Namespace);
+ AddSourceRange(QualifierLoc.getLocalSourceRange());
break;
- case NestedNameSpecifier::Namespace:
- AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespace());
- AddSourceRange(NNS.getLocalSourceRange());
+ case NestedNameSpecifier::Kind::Type: {
+ TypeLoc TL = QualifierLoc.castAsTypeLoc();
+ AddTypeRef(TL.getType());
+ AddTypeLoc(TL);
+ AddSourceLocation(QualifierLoc.getLocalSourceRange().getEnd());
break;
+ }
- case NestedNameSpecifier::TypeSpec:
- AddTypeRef(NNS.getTypeLoc().getType());
- AddTypeLoc(NNS.getTypeLoc());
- AddSourceLocation(NNS.getLocalSourceRange().getEnd());
+ case NestedNameSpecifier::Kind::Global:
+ AddSourceLocation(QualifierLoc.getLocalSourceRange().getEnd());
break;
- case NestedNameSpecifier::Global:
- AddSourceLocation(NNS.getLocalSourceRange().getEnd());
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ AddDeclRef(Qualifier.getAsMicrosoftSuper());
+ AddSourceRange(QualifierLoc.getLocalSourceRange());
break;
- case NestedNameSpecifier::Super:
- AddDeclRef(NNS.getNestedNameSpecifier()->getAsRecordDecl());
- AddSourceRange(NNS.getLocalSourceRange());
- break;
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
}
}
}
diff --git a/clang/lib/Tooling/Refactoring/Lookup.cpp b/clang/lib/Tooling/Refactoring/Lookup.cpp
index 8372371aff368..dedde860516ab 100644
--- a/clang/lib/Tooling/Refactoring/Lookup.cpp
+++ b/clang/lib/Tooling/Refactoring/Lookup.cpp
@@ -108,16 +108,6 @@ static StringRef getBestNamespaceSubstr(const DeclContext *DeclA,
}
}
-/// Check if the name specifier begins with a written "::".
-static bool isFullyQualified(const NestedNameSpecifier *NNS) {
- while (NNS) {
- if (NNS->getKind() == NestedNameSpecifier::Global)
- return true;
- NNS = NNS->getPrefix();
- }
- return false;
-}
-
// Adds more scope specifier to the spelled name until the spelling is not
// ambiguous. A spelling is ambiguous if the resolution of the symbol is
// ambiguous. For example, if QName is "::y::bar", the spelling is "y::bar", and
@@ -182,7 +172,7 @@ static std::string disambiguateSpellingInScope(StringRef Spelling,
return Disambiguated;
}
-std::string tooling::replaceNestedName(const NestedNameSpecifier *Use,
+std::string tooling::replaceNestedName(NestedNameSpecifier Use,
SourceLocation UseLoc,
const DeclContext *UseContext,
const NamedDecl *FromDecl,
diff --git a/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp b/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
index 7d153ec958bef..d9444110d421c 100644
--- a/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
+++ b/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
@@ -107,45 +107,83 @@ class USRLocFindingASTVisitor
};
SourceLocation StartLocationForType(TypeLoc TL) {
+ if (auto QTL = TL.getAs<QualifiedTypeLoc>())
+ TL = QTL.getUnqualifiedLoc();
+
// For elaborated types (e.g. `struct a::A`) we want the portion after the
- // `struct` but including the namespace qualifier, `a::`.
- if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>()) {
- NestedNameSpecifierLoc NestedNameSpecifier =
- ElaboratedTypeLoc.getQualifierLoc();
- if (NestedNameSpecifier.getNestedNameSpecifier())
- return NestedNameSpecifier.getBeginLoc();
- TL = TL.getNextTypeLoc();
+ // `struct`, including the namespace qualifier, `a::`.
+ switch (TL.getTypeLocClass()) {
+ case TypeLoc::Record:
+ case TypeLoc::InjectedClassName:
+ case TypeLoc::Enum: {
+ auto TTL = TL.castAs<TagTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return TTL.getNameLoc();
+ }
+ case TypeLoc::Typedef: {
+ auto TTL = TL.castAs<TypedefTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return TTL.getNameLoc();
+ }
+ case TypeLoc::UnresolvedUsing: {
+ auto TTL = TL.castAs<UnresolvedUsingTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return TTL.getNameLoc();
+ }
+ case TypeLoc::Using: {
+ auto TTL = TL.castAs<UsingTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return TTL.getNameLoc();
+ }
+ case TypeLoc::TemplateSpecialization: {
+ auto TTL = TL.castAs<TemplateSpecializationTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return TTL.getTemplateNameLoc();
+ }
+ case TypeLoc::DeducedTemplateSpecialization: {
+ auto DTL = TL.castAs<clang::DeducedTemplateSpecializationTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = DTL.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return DTL.getTemplateNameLoc();
+ }
+ case TypeLoc::DependentName: {
+ auto TTL = TL.castAs<DependentNameTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return TTL.getNameLoc();
+ }
+ case TypeLoc::DependentTemplateSpecialization: {
+ auto TTL = TL.castAs<DependentTemplateSpecializationTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return TTL.getTemplateNameLoc();
+ }
+ default:
+ llvm_unreachable("unhandled TypeLoc class");
}
- return TL.getBeginLoc();
}
SourceLocation EndLocationForType(TypeLoc TL) {
- // Dig past any namespace or keyword qualifications.
- while (TL.getTypeLocClass() == TypeLoc::Elaborated ||
- TL.getTypeLocClass() == TypeLoc::Qualified)
- TL = TL.getNextTypeLoc();
+ if (auto QTL = TL.getAs<QualifiedTypeLoc>())
+ TL = 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
// before the `<` character.
- if (TL.getTypeLocClass() == TypeLoc::TemplateSpecialization) {
- return TL.castAs<TemplateSpecializationTypeLoc>()
- .getLAngleLoc()
- .getLocWithOffset(-1);
- }
+ if (auto TTL = TL.getAs<TemplateSpecializationTypeLoc>())
+ return TTL.getLAngleLoc().getLocWithOffset(-1);
return TL.getEndLoc();
}
-NestedNameSpecifier *GetNestedNameForType(TypeLoc TL) {
- // Dig past any keyword qualifications.
- while (TL.getTypeLocClass() == TypeLoc::Qualified)
- TL = TL.getNextTypeLoc();
-
- // For elaborated types (e.g. `struct a::A`) we want the portion after the
- // `struct` but including the namespace qualifier, `a::`.
- if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>())
- return ElaboratedTypeLoc.getQualifierLoc().getNestedNameSpecifier();
- return nullptr;
+NestedNameSpecifier GetNestedNameForType(TypeLoc TL) {
+ if (auto QTL = TL.getAs<QualifiedTypeLoc>())
+ TL = QTL.getUnqualifiedLoc();
+ return TL.getPrefix().getNestedNameSpecifier();
}
// Find all locations identified by the given USRs for rename.
@@ -168,14 +206,14 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
const NamedDecl *FromDecl;
// The declaration in which the nested name is contained (can be nullptr).
const Decl *Context;
- // The nested name being replaced (can be nullptr).
- const NestedNameSpecifier *Specifier;
+ // The nested name being replaced.
+ NestedNameSpecifier Specifier;
// Determine whether the prefix qualifiers of the NewName should be ignored.
// Normally, we set it to true for the symbol declaration and definition to
// avoid adding prefix qualifiers.
// For example, if it is true and NewName is "a::b::foo", then the symbol
// occurrence which the RenameInfo points to will be renamed to "foo".
- bool IgnorePrefixQualifers;
+ bool IgnorePrefixQualifiers;
};
bool VisitNamedDecl(const NamedDecl *Decl) {
@@ -350,18 +388,18 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
}
bool VisitNestedNameSpecifierLocations(NestedNameSpecifierLoc NestedLoc) {
- if (!NestedLoc.getNestedNameSpecifier()->getAsType())
+ TypeLoc TL = NestedLoc.getAsTypeLoc();
+ if (!TL)
return true;
- if (const auto *TargetDecl =
- getSupportedDeclFromTypeLoc(NestedLoc.getTypeLoc())) {
+ if (const auto *TargetDecl = getSupportedDeclFromTypeLoc(TL)) {
if (isInUSRSet(TargetDecl)) {
RenameInfo Info = {NestedLoc.getBeginLoc(),
- EndLocationForType(NestedLoc.getTypeLoc()),
+ EndLocationForType(TL),
TargetDecl,
getClosestAncestorDecl(NestedLoc),
- NestedLoc.getNestedNameSpecifier()->getPrefix(),
- /*IgnorePrefixQualifers=*/false};
+ /*Specifier=*/std::nullopt,
+ /*IgnorePrefixQualifiers=*/false};
RenameInfos.push_back(Info);
}
}
diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp
index 2e43714b16c1c..546161cee33f4 100644
--- a/clang/lib/Tooling/Syntax/BuildTree.cpp
+++ b/clang/lib/Tooling/Syntax/BuildTree.cpp
@@ -918,97 +918,91 @@ class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
return true;
}
- // FIXME: Fix `NestedNameSpecifierLoc::getLocalSourceRange` for the
- // `DependentTemplateSpecializationType` case.
- /// Given a nested-name-specifier return the range for the last name
- /// specifier.
- ///
- /// e.g. `std::T::template X<U>::` => `template X<U>::`
- SourceRange getLocalSourceRange(const NestedNameSpecifierLoc &NNSLoc) {
- auto SR = NNSLoc.getLocalSourceRange();
-
- // The method `NestedNameSpecifierLoc::getLocalSourceRange` *should*
- // return the desired `SourceRange`, but there is a corner case. For a
- // `DependentTemplateSpecializationType` this method returns its
- // qualifiers as well, in other words in the example above this method
- // returns `T::template X<U>::` instead of only `template X<U>::`
- if (auto TL = NNSLoc.getTypeLoc()) {
- if (auto DependentTL =
- TL.getAs<DependentTemplateSpecializationTypeLoc>()) {
- // The 'template' keyword is always present in dependent template
- // specializations. Except in the case of incorrect code
- // TODO: Treat the case of incorrect code.
- SR.setBegin(DependentTL.getTemplateKeywordLoc());
- }
- }
-
- return SR;
- }
-
- syntax::NodeKind getNameSpecifierKind(const NestedNameSpecifier &NNS) {
- switch (NNS.getKind()) {
- case NestedNameSpecifier::Global:
- return syntax::NodeKind::GlobalNameSpecifier;
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::Identifier:
- return syntax::NodeKind::IdentifierNameSpecifier;
- case NestedNameSpecifier::TypeSpec: {
- const auto *NNSType = NNS.getAsType();
- assert(NNSType);
- if (isa<DecltypeType>(NNSType))
- return syntax::NodeKind::DecltypeNameSpecifier;
- if (isa<TemplateSpecializationType, DependentTemplateSpecializationType>(
- NNSType))
- return syntax::NodeKind::SimpleTemplateNameSpecifier;
- return syntax::NodeKind::IdentifierNameSpecifier;
- }
- default:
- // FIXME: Support Microsoft's __super
- llvm::report_fatal_error("We don't yet support the __super specifier",
- true);
- }
+ syntax::NameSpecifier *buildIdentifier(SourceRange SR,
+ bool DropBack = false) {
+ auto NameSpecifierTokens = Builder.getRange(SR).drop_back(DropBack);
+ assert(NameSpecifierTokens.size() == 1);
+ Builder.markChildToken(NameSpecifierTokens.begin(),
+ syntax::NodeRole::Unknown);
+ auto *NS = new (allocator()) syntax::IdentifierNameSpecifier;
+ Builder.foldNode(NameSpecifierTokens, NS, nullptr);
+ return NS;
+ }
+
+ syntax::NameSpecifier *buildSimpleTemplateName(SourceRange SR) {
+ auto NameSpecifierTokens = Builder.getRange(SR);
+ // TODO: Build `SimpleTemplateNameSpecifier` children and implement
+ // accessors to them.
+ // Be aware, we cannot do that simply by calling `TraverseTypeLoc`,
+ // some `TypeLoc`s have inside them the previous name specifier and
+ // we want to treat them independently.
+ auto *NS = new (allocator()) syntax::SimpleTemplateNameSpecifier;
+ Builder.foldNode(NameSpecifierTokens, NS, nullptr);
+ return NS;
}
syntax::NameSpecifier *
buildNameSpecifier(const NestedNameSpecifierLoc &NNSLoc) {
assert(NNSLoc.hasQualifier());
- auto NameSpecifierTokens =
- Builder.getRange(getLocalSourceRange(NNSLoc)).drop_back();
- switch (getNameSpecifierKind(*NNSLoc.getNestedNameSpecifier())) {
- case syntax::NodeKind::GlobalNameSpecifier:
+ switch (NNSLoc.getNestedNameSpecifier().getKind()) {
+ case NestedNameSpecifier::Kind::Global:
return new (allocator()) syntax::GlobalNameSpecifier;
- case syntax::NodeKind::IdentifierNameSpecifier: {
- assert(NameSpecifierTokens.size() == 1);
- Builder.markChildToken(NameSpecifierTokens.begin(),
- syntax::NodeRole::Unknown);
- auto *NS = new (allocator()) syntax::IdentifierNameSpecifier;
- Builder.foldNode(NameSpecifierTokens, NS, nullptr);
- return NS;
- }
- case syntax::NodeKind::SimpleTemplateNameSpecifier: {
- // TODO: Build `SimpleTemplateNameSpecifier` children and implement
- // accessors to them.
- // Be aware, we cannot do that simply by calling `TraverseTypeLoc`,
- // some `TypeLoc`s have inside them the previous name specifier and
- // we want to treat them independently.
- auto *NS = new (allocator()) syntax::SimpleTemplateNameSpecifier;
- Builder.foldNode(NameSpecifierTokens, NS, nullptr);
- return NS;
- }
- case syntax::NodeKind::DecltypeNameSpecifier: {
- const auto TL = NNSLoc.getTypeLoc().castAs<DecltypeTypeLoc>();
- if (!RecursiveASTVisitor::TraverseDecltypeTypeLoc(TL))
- return nullptr;
- auto *NS = new (allocator()) syntax::DecltypeNameSpecifier;
- // TODO: Implement accessor to `DecltypeNameSpecifier` inner
- // `DecltypeTypeLoc`.
- // For that add mapping from `TypeLoc` to `syntax::Node*` then:
- // Builder.markChild(TypeLoc, syntax::NodeRole);
- Builder.foldNode(NameSpecifierTokens, NS, nullptr);
- return NS;
+
+ case NestedNameSpecifier::Kind::Namespace:
+ return buildIdentifier(NNSLoc.getLocalSourceRange(), /*DropBack=*/true);
+
+ case NestedNameSpecifier::Kind::Type: {
+ TypeLoc TL = NNSLoc.castAsTypeLoc();
+ switch (TL.getTypeLocClass()) {
+ case TypeLoc::Record:
+ case TypeLoc::InjectedClassName:
+ case TypeLoc::Enum:
+ return buildIdentifier(TL.castAs<TagTypeLoc>().getNameLoc());
+ case TypeLoc::Typedef:
+ return buildIdentifier(TL.castAs<TypedefTypeLoc>().getNameLoc());
+ case TypeLoc::UnresolvedUsing:
+ return buildIdentifier(
+ TL.castAs<UnresolvedUsingTypeLoc>().getNameLoc());
+ case TypeLoc::Using:
+ return buildIdentifier(TL.castAs<UsingTypeLoc>().getNameLoc());
+ case TypeLoc::DependentName:
+ return buildIdentifier(TL.castAs<DependentNameTypeLoc>().getNameLoc());
+ case TypeLoc::TemplateSpecialization: {
+ auto TST = TL.castAs<TemplateSpecializationTypeLoc>();
+ SourceLocation BeginLoc = TST.getTemplateKeywordLoc();
+ if (BeginLoc.isInvalid())
+ BeginLoc = TST.getTemplateNameLoc();
+ return buildSimpleTemplateName({BeginLoc, TST.getEndLoc()});
+ }
+ case TypeLoc::DependentTemplateSpecialization: {
+ auto DT = TL.castAs<DependentTemplateSpecializationTypeLoc>();
+ SourceLocation BeginLoc = DT.getTemplateKeywordLoc();
+ if (BeginLoc.isInvalid())
+ BeginLoc = DT.getTemplateNameLoc();
+ return buildSimpleTemplateName({BeginLoc, DT.getEndLoc()});
+ }
+ case TypeLoc::Decltype: {
+ const auto DTL = TL.castAs<DecltypeTypeLoc>();
+ if (!RecursiveASTVisitor::TraverseDecltypeTypeLoc(
+ DTL, /*TraverseQualifier=*/true))
+ return nullptr;
+ auto *NS = new (allocator()) syntax::DecltypeNameSpecifier;
+ // TODO: Implement accessor to `DecltypeNameSpecifier` inner
+ // `DecltypeTypeLoc`.
+ // For that add mapping from `TypeLoc` to `syntax::Node*` then:
+ // Builder.markChild(TypeLoc, syntax::NodeRole);
+ Builder.foldNode(Builder.getRange(DTL.getLocalSourceRange()), NS,
+ nullptr);
+ return NS;
+ }
+ default:
+ return buildIdentifier(TL.getLocalSourceRange());
+ }
}
default:
- llvm_unreachable("getChildKind() does not return this value");
+ // FIXME: Support Microsoft's __super
+ llvm::report_fatal_error("We don't yet support the __super specifier",
+ true);
}
}
@@ -1019,12 +1013,16 @@ class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc QualifierLoc) {
if (!QualifierLoc)
return true;
- for (auto It = QualifierLoc; It; It = It.getPrefix()) {
+ for (auto It = QualifierLoc; It; /**/) {
auto *NS = buildNameSpecifier(It);
if (!NS)
return false;
Builder.markChild(NS, syntax::NodeRole::ListElement);
Builder.markChildToken(It.getEndLoc(), syntax::NodeRole::ListDelimiter);
+ if (TypeLoc TL = It.getAsTypeLoc())
+ It = TL.getPrefix();
+ else
+ It = It.getAsNamespaceAndPrefix().Prefix;
}
Builder.foldNode(Builder.getRange(QualifierLoc.getSourceRange()),
new (allocator()) syntax::NestedNameSpecifier,
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index d4f0794a8e0af..239c9c536f243 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -1420,79 +1420,25 @@ bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) {
llvm_unreachable("Invalid DeclarationName::Kind!");
}
-bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS,
- SourceRange Range) {
- // FIXME: This whole routine is a hack to work around the lack of proper
- // source information in nested-name-specifiers (PR5791). Since we do have
- // a beginning source location, we can visit the first component of the
- // nested-name-specifier, if it's a single-token component.
- if (!NNS)
- return false;
-
- // Get the first component in the nested-name-specifier.
- while (NestedNameSpecifier *Prefix = NNS->getPrefix())
- NNS = Prefix;
-
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Namespace:
- return Visit(
- MakeCursorNamespaceRef(NNS->getAsNamespace(), Range.getBegin(), TU));
-
- case NestedNameSpecifier::TypeSpec: {
- // If the type has a form where we know that the beginning of the source
- // range matches up with a reference cursor. Visit the appropriate reference
- // cursor.
- const Type *T = NNS->getAsType();
- if (const TypedefType *Typedef = dyn_cast<TypedefType>(T))
- return Visit(MakeCursorTypeRef(Typedef->getDecl(), Range.getBegin(), TU));
- if (const TagType *Tag = dyn_cast<TagType>(T))
- return Visit(MakeCursorTypeRef(Tag->getDecl(), Range.getBegin(), TU));
- if (const TemplateSpecializationType *TST =
- dyn_cast<TemplateSpecializationType>(T))
- return VisitTemplateName(TST->getTemplateName(), Range.getBegin());
- break;
- }
-
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Super:
- break;
- }
-
- return false;
-}
-
bool CursorVisitor::VisitNestedNameSpecifierLoc(
NestedNameSpecifierLoc Qualifier) {
- SmallVector<NestedNameSpecifierLoc, 4> Qualifiers;
- for (; Qualifier; Qualifier = Qualifier.getPrefix())
- Qualifiers.push_back(Qualifier);
-
- while (!Qualifiers.empty()) {
- NestedNameSpecifierLoc Q = Qualifiers.pop_back_val();
- NestedNameSpecifier *NNS = Q.getNestedNameSpecifier();
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Namespace:
- if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(),
- Q.getLocalBeginLoc(), TU)))
- return true;
-
- break;
-
- case NestedNameSpecifier::TypeSpec:
- if (Visit(Q.getTypeLoc()))
- return true;
-
- break;
-
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Super:
- break;
- }
+ NestedNameSpecifier NNS = Qualifier.getNestedNameSpecifier();
+ switch (NNS.getKind()) {
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace, Prefix] = Qualifier.castAsNamespaceAndPrefix();
+ if (VisitNestedNameSpecifierLoc(Prefix))
+ return true;
+ return Visit(
+ MakeCursorNamespaceRef(Namespace, Qualifier.getLocalBeginLoc(), TU));
}
-
- return false;
+ case NestedNameSpecifier::Kind::Type:
+ return Visit(Qualifier.castAsTypeLoc());
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ return false;
+ }
+ llvm_unreachable("unexpected nested name specifier kind");
}
bool CursorVisitor::VisitTemplateParameters(
@@ -1515,16 +1461,23 @@ bool CursorVisitor::VisitTemplateParameters(
return false;
}
-bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation Loc) {
+bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation NameLoc,
+ NestedNameSpecifierLoc NNS) {
switch (Name.getKind()) {
+ case TemplateName::QualifiedTemplate: {
+ const QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName();
+ assert(QTN->getQualifier() == NNS.getNestedNameSpecifier());
+ if (VisitNestedNameSpecifierLoc(NNS))
+ return true;
+ return VisitTemplateName(QTN->getUnderlyingTemplate(), NameLoc, /*NNS=*/{});
+ }
case TemplateName::Template:
case TemplateName::UsingTemplate:
- case TemplateName::QualifiedTemplate: // FIXME: Visit nested-name-specifier.
- return Visit(MakeCursorTemplateRef(Name.getAsTemplateDecl(), Loc, TU));
+ return Visit(MakeCursorTemplateRef(Name.getAsTemplateDecl(), NameLoc, TU));
case TemplateName::OverloadedTemplate:
// Visit the overloaded template set.
- if (Visit(MakeCursorOverloadedDeclRef(Name, Loc, TU)))
+ if (Visit(MakeCursorOverloadedDeclRef(Name, NameLoc, TU)))
return true;
return false;
@@ -1533,17 +1486,19 @@ bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation Loc) {
// FIXME: Visit DeclarationName?
return false;
- case TemplateName::DependentTemplate:
- // FIXME: Visit nested-name-specifier.
- return false;
+ case TemplateName::DependentTemplate: {
+ assert(Name.getAsDependentTemplateName()->getQualifier() ==
+ NNS.getNestedNameSpecifier());
+ return VisitNestedNameSpecifierLoc(NNS);
+ }
case TemplateName::SubstTemplateTemplateParm:
return Visit(MakeCursorTemplateRef(
- Name.getAsSubstTemplateTemplateParm()->getParameter(), Loc, TU));
+ Name.getAsSubstTemplateTemplateParm()->getParameter(), NameLoc, TU));
case TemplateName::SubstTemplateTemplateParmPack:
return Visit(MakeCursorTemplateRef(
- Name.getAsSubstTemplateTemplateParmPack()->getParameterPack(), Loc,
+ Name.getAsSubstTemplateTemplateParmPack()->getParameterPack(), NameLoc,
TU));
case TemplateName::DeducedTemplate:
@@ -1587,11 +1542,9 @@ bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
- if (VisitNestedNameSpecifierLoc(TAL.getTemplateQualifierLoc()))
- return true;
-
return VisitTemplateName(TAL.getArgument().getAsTemplateOrTemplatePattern(),
- TAL.getTemplateNameLoc());
+ TAL.getTemplateNameLoc(),
+ TAL.getTemplateQualifierLoc());
}
llvm_unreachable("Invalid TemplateArgument::Kind!");
@@ -1669,7 +1622,10 @@ bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
}
bool CursorVisitor::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
- return Visit(MakeCursorTypeRef(TL.getTypedefNameDecl(), TL.getNameLoc(), TU));
+ if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
+ return true;
+
+ return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
}
bool CursorVisitor::VisitPredefinedSugarTypeLoc(PredefinedSugarTypeLoc TL) {
@@ -1880,8 +1836,7 @@ bool CursorVisitor::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
bool CursorVisitor::VisitDependentTemplateSpecializationTypeLoc(
DependentTemplateSpecializationTypeLoc TL) {
- // Visit the nested-name-specifier, if there is one.
- if (TL.getQualifierLoc() && VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
+ if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
return true;
// Visit the template arguments.
@@ -2067,7 +2022,7 @@ class NestedNameSpecifierLocVisit : public VisitorJob {
public:
NestedNameSpecifierLocVisit(NestedNameSpecifierLoc Qualifier, CXCursor parent)
: VisitorJob(parent, VisitorJob::NestedNameSpecifierLocVisitKind,
- Qualifier.getNestedNameSpecifier(),
+ Qualifier.getNestedNameSpecifier().getAsVoidPointer(),
Qualifier.getOpaqueData()) {}
static bool classof(const VisitorJob *VJ) {
@@ -2076,8 +2031,7 @@ class NestedNameSpecifierLocVisit : public VisitorJob {
NestedNameSpecifierLoc get() const {
return NestedNameSpecifierLoc(
- const_cast<NestedNameSpecifier *>(
- static_cast<const NestedNameSpecifier *>(data[0])),
+ NestedNameSpecifier::getFromVoidPointer(data[0]),
const_cast<void *>(data[1]));
}
};
diff --git a/clang/tools/libclang/CursorVisitor.h b/clang/tools/libclang/CursorVisitor.h
index 949b73908c315..d5ab699756988 100644
--- a/clang/tools/libclang/CursorVisitor.h
+++ b/clang/tools/libclang/CursorVisitor.h
@@ -255,12 +255,12 @@ class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
// Name visitor
bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
- bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
// Template visitors
bool VisitTemplateParameters(const TemplateParameterList *Params);
- bool VisitTemplateName(TemplateName Name, SourceLocation Loc);
+ bool VisitTemplateName(TemplateName Name, SourceLocation NameLoc,
+ NestedNameSpecifierLoc NNS);
bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
// Type visitors
diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index 4fd7dcdad2d7e..d58bc00c995e0 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -5765,38 +5765,33 @@ TEST(NNS, DescendantsOfNestedNameSpecifiers) {
"namespace a { struct A { struct B { struct C {}; }; }; };"
"void f() { a::A::B::C c; }";
EXPECT_TRUE(matches(
- Fragment,
- nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
- hasDescendant(nestedNameSpecifier(
- specifiesNamespace(hasName("a")))))));
+ Fragment, nestedNameSpecifier(specifiesType(asString("a::A::B")),
+ hasDescendant(nestedNameSpecifier(
+ specifiesNamespace(hasName("a")))))));
EXPECT_TRUE(notMatches(
- Fragment,
- nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
- has(nestedNameSpecifier(
- specifiesNamespace(hasName("a")))))));
+ Fragment, nestedNameSpecifier(specifiesType(asString("a::A::B")),
+ has(nestedNameSpecifier(
+ specifiesNamespace(hasName("a")))))));
EXPECT_TRUE(matches(
- Fragment,
- nestedNameSpecifier(specifiesType(asString("struct a::A")),
- has(nestedNameSpecifier(
- specifiesNamespace(hasName("a")))))));
+ Fragment, nestedNameSpecifier(specifiesType(asString("a::A")),
+ has(nestedNameSpecifier(
+ specifiesNamespace(hasName("a")))))));
// Not really useful because a NestedNameSpecifier can af at most one child,
// but to complete the interface.
EXPECT_TRUE(matchAndVerifyResultTrue(
- Fragment,
- nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
- forEach(nestedNameSpecifier().bind("x"))),
- std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifier>>("x", 1)));
+ Fragment,
+ nestedNameSpecifier(specifiesType(asString("a::A::B")),
+ forEach(nestedNameSpecifier().bind("x"))),
+ std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifier>>("x", 1)));
}
TEST(NNS, NestedNameSpecifiersAsDescendants) {
StringRef Fragment =
"namespace a { struct A { struct B { struct C {}; }; }; };"
"void f() { a::A::B::C c; }";
- EXPECT_TRUE(matches(
- Fragment,
- decl(hasDescendant(nestedNameSpecifier(specifiesType(
- asString("struct a::A")))))));
+ EXPECT_TRUE(matches(Fragment, decl(hasDescendant(nestedNameSpecifier(
+ specifiesType(asString("a::A")))))));
EXPECT_TRUE(matchAndVerifyResultTrue(
Fragment,
functionDecl(hasName("f"),
@@ -5809,37 +5804,34 @@ TEST(NNSLoc, DescendantsOfNestedNameSpecifierLocs) {
StringRef Fragment =
"namespace a { struct A { struct B { struct C {}; }; }; };"
"void f() { a::A::B::C c; }";
- EXPECT_TRUE(matches(
- Fragment,
- nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
- hasDescendant(loc(nestedNameSpecifier(
- specifiesNamespace(hasName("a"))))))));
+ EXPECT_TRUE(matches(Fragment, nestedNameSpecifierLoc(
+ loc(specifiesType(asString("a::A::B"))),
+ hasDescendant(loc(nestedNameSpecifier(
+ specifiesNamespace(hasName("a"))))))));
EXPECT_TRUE(notMatches(
- Fragment,
- nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
- has(loc(nestedNameSpecifier(
- specifiesNamespace(hasName("a"))))))));
+ Fragment,
+ nestedNameSpecifierLoc(
+ loc(specifiesType(asString("a::A::B"))),
+ has(loc(nestedNameSpecifier(specifiesNamespace(hasName("a"))))))));
EXPECT_TRUE(matches(
- Fragment,
- nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A"))),
- has(loc(nestedNameSpecifier(
- specifiesNamespace(hasName("a"))))))));
+ Fragment,
+ nestedNameSpecifierLoc(
+ loc(specifiesType(asString("a::A"))),
+ has(loc(nestedNameSpecifier(specifiesNamespace(hasName("a"))))))));
EXPECT_TRUE(matchAndVerifyResultTrue(
- Fragment,
- nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
- forEach(nestedNameSpecifierLoc().bind("x"))),
- std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifierLoc>>("x", 1)));
+ Fragment,
+ nestedNameSpecifierLoc(loc(specifiesType(asString("a::A::B"))),
+ forEach(nestedNameSpecifierLoc().bind("x"))),
+ std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifierLoc>>("x", 1)));
}
TEST(NNSLoc, NestedNameSpecifierLocsAsDescendants) {
StringRef Fragment =
"namespace a { struct A { struct B { struct C {}; }; }; };"
"void f() { a::A::B::C c; }";
- EXPECT_TRUE(matches(
- Fragment,
- decl(hasDescendant(loc(nestedNameSpecifier(specifiesType(
- asString("struct a::A"))))))));
+ EXPECT_TRUE(matches(Fragment, decl(hasDescendant(loc(nestedNameSpecifier(
+ specifiesType(asString("a::A"))))))));
EXPECT_TRUE(matchAndVerifyResultTrue(
Fragment,
functionDecl(hasName("f"),
diff --git a/clang/unittests/Sema/HeuristicResolverTest.cpp b/clang/unittests/Sema/HeuristicResolverTest.cpp
index 817654af10918..7df25e01e66d4 100644
--- a/clang/unittests/Sema/HeuristicResolverTest.cpp
+++ b/clang/unittests/Sema/HeuristicResolverTest.cpp
@@ -648,15 +648,16 @@ TEST(HeuristicResolver, NestedNameSpecifier) {
// expected by expectResolution() (returning a vector of decls).
ResolveFnT<NestedNameSpecifier> ResolveFn =
[](const HeuristicResolver *H,
- const NestedNameSpecifier *NNS) -> std::vector<const NamedDecl *> {
+ NestedNameSpecifier NNS) -> std::vector<const NamedDecl *> {
return {H->resolveNestedNameSpecifierToType(NNS)->getAsCXXRecordDecl()};
};
- expectResolution(Code, ResolveFn,
- nestedNameSpecifier(hasPrefix(specifiesType(hasDeclaration(
- classTemplateDecl(hasName("A"))))))
- .bind("input"),
- classTemplateDecl(has(cxxRecordDecl(
- has(cxxRecordDecl(hasName("B")).bind("output"))))));
+ expectResolution<NestedNameSpecifier>(
+ Code, ResolveFn,
+ nestedNameSpecifier(hasPrefix(specifiesType(
+ hasDeclaration(classTemplateDecl(hasName("A"))))))
+ .bind("input"),
+ classTemplateDecl(
+ has(cxxRecordDecl(has(cxxRecordDecl(hasName("B")).bind("output"))))));
}
TEST(HeuristicResolver, TemplateSpecializationType) {
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp
index 64bad8a134111..4181cd2881054 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp
@@ -22,13 +22,16 @@ class NestedNameSpecifiersVisitor : public ExpectedLocationVisitor {
return true;
}
- bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) override {
- if (!NNS)
- return true;
- if (const auto *ND = dyn_cast_if_present<NamespaceDecl>(
- NNS.getNestedNameSpecifier()->getAsNamespace()))
- Match(ND->getName(), NNS.getLocalBeginLoc());
- return ExpectedLocationVisitor::TraverseNestedNameSpecifierLoc(NNS);
+ bool
+ TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc QualifierLoc) override {
+ NestedNameSpecifier Qualifier = QualifierLoc.getNestedNameSpecifier();
+ if (Qualifier.getKind() == NestedNameSpecifier::Kind::Namespace) {
+ if (const auto *ND = dyn_cast<NamespaceDecl>(
+ Qualifier.getAsNamespaceAndPrefix().Namespace))
+ Match(ND->getName(), QualifierLoc.getLocalBeginLoc());
+ }
+ return ExpectedLocationVisitor::TraverseNestedNameSpecifierLoc(
+ QualifierLoc);
}
};
diff --git a/clang/unittests/Tooling/RefactoringTest.cpp b/clang/unittests/Tooling/RefactoringTest.cpp
index 35d114343b517..250a2630c00cf 100644
--- a/clang/unittests/Tooling/RefactoringTest.cpp
+++ b/clang/unittests/Tooling/RefactoringTest.cpp
@@ -747,9 +747,12 @@ TEST(Replacement, TemplatedFunctionCall) {
class NestedNameSpecifierAVisitor : public TestVisitor {
public:
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLoc) override {
- if (NNSLoc.getNestedNameSpecifier()) {
- if (const auto *NS = dyn_cast_if_present<NamespaceDecl>(
- NNSLoc.getNestedNameSpecifier()->getAsNamespace())) {
+ if (NestedNameSpecifier NNS = NNSLoc.getNestedNameSpecifier();
+ NNS.getKind() == NestedNameSpecifier::Kind::Namespace) {
+ if (const auto *NS =
+ dyn_cast<NamespaceDecl>(NNSLoc.getNestedNameSpecifier()
+ .getAsNamespaceAndPrefix()
+ .Namespace)) {
if (NS->getName() == "a") {
Replace = Replacement(*SM, &NNSLoc, "", Context->getLangOpts());
}
More information about the llvm-branch-commits
mailing list