[llvm-branch-commits] [clang-tools-extra] [PATCH 4/4] [clang] Improve nested name specifier AST representation (PR #148015)
Matheus Izvekov via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Jul 14 14:46:58 PDT 2025
https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/148015
>From fa2a2df2ec2ed63dad3e34fb5d2bb15bf75baab6 Mon Sep 17 00:00:00 2001
From: Matheus Izvekov <mizvekov at gmail.com>
Date: Thu, 10 Jul 2025 14:07:34 -0300
Subject: [PATCH] [PATCH 4/4] [clang] Improve nested name specifier AST
representation
clang tools extra changes
---
.../ChangeNamespace.cpp | 53 +++-----
clang-tools-extra/clang-doc/Serialize.cpp | 4 +-
.../find-all-symbols/FindAllSymbols.cpp | 3 +-
.../ClangTidyDiagnosticConsumer.cpp | 3 +-
.../CrtpConstructorAccessibilityCheck.cpp | 6 +-
.../EasilySwappableParametersCheck.cpp | 14 +-
.../ForwardDeclarationNamespaceCheck.cpp | 11 +-
.../ForwardingReferenceOverloadCheck.cpp | 18 +--
.../bugprone/IncorrectEnableIfCheck.cpp | 19 ++-
.../bugprone/MoveForwardingReferenceCheck.cpp | 17 ++-
.../bugprone/SizeofExpressionCheck.cpp | 10 +-
.../NoSuspendWithLockCheck.cpp | 4 +-
.../ProTypeMemberInitCheck.cpp | 2 +-
.../cppcoreguidelines/SlicingCheck.cpp | 2 +-
.../fuchsia/MultipleInheritanceCheck.cpp | 8 +-
.../google/AvoidCStyleCastsCheck.cpp | 31 ++++-
.../google/ExplicitConstructorCheck.cpp | 2 +-
.../google/UpgradeGoogletestCaseCheck.cpp | 9 +-
.../clang-tidy/misc/ConstCorrectnessCheck.cpp | 11 +-
.../clang-tidy/misc/MisplacedConstCheck.cpp | 14 +-
.../misc/RedundantExpressionCheck.cpp | 13 +-
.../clang-tidy/misc/UnusedAliasDeclsCheck.cpp | 9 +-
.../clang-tidy/misc/UnusedUsingDeclsCheck.cpp | 8 +-
.../DeprecatedIosBaseAliasesCheck.cpp | 11 +-
.../clang-tidy/modernize/PassByValueCheck.cpp | 3 +-
.../modernize/ReplaceAutoPtrCheck.cpp | 15 +--
.../clang-tidy/modernize/TypeTraitsCheck.cpp | 63 ++++-----
.../clang-tidy/modernize/UseAutoCheck.cpp | 18 ++-
.../modernize/UseConstraintsCheck.cpp | 7 +-
.../clang-tidy/modernize/UseEmplaceCheck.cpp | 53 ++++----
.../modernize/UseScopedLockCheck.cpp | 43 +++---
.../modernize/UseTrailingReturnTypeCheck.cpp | 93 +++++++------
.../modernize/UseTransparentFunctorsCheck.cpp | 16 +--
.../performance/NoAutomaticMoveCheck.cpp | 8 +-
.../portability/StdAllocatorConstCheck.cpp | 11 +-
.../StaticAccessedThroughInstanceCheck.cpp | 26 ++--
.../SuspiciousCallArgumentCheck.cpp | 4 +-
.../readability/UseStdMinMaxCheck.cpp | 6 +-
.../utils/ExceptionSpecAnalyzer.cpp | 3 +-
.../utils/FormatStringConverter.cpp | 5 +-
.../clang-tidy/utils/Matchers.cpp | 2 +-
.../utils/RenamerClangTidyCheck.cpp | 36 ++---
.../clang-tidy/utils/TypeTraits.cpp | 3 +-
clang-tools-extra/clangd/AST.cpp | 92 ++++++++-----
clang-tools-extra/clangd/AST.h | 3 +-
clang-tools-extra/clangd/CodeComplete.cpp | 17 +--
clang-tools-extra/clangd/DumpAST.cpp | 42 +++---
clang-tools-extra/clangd/FindTarget.cpp | 126 +++++++-----------
clang-tools-extra/clangd/Hover.cpp | 20 +--
clang-tools-extra/clangd/IncludeFixer.cpp | 23 ++--
clang-tools-extra/clangd/InlayHints.cpp | 28 ++--
clang-tools-extra/clangd/Selection.cpp | 17 ++-
.../clangd/SemanticHighlighting.cpp | 15 ---
clang-tools-extra/clangd/XRefs.cpp | 13 +-
.../clangd/refactor/tweaks/AddUsing.cpp | 123 +++++++++++------
.../refactor/tweaks/ExtractFunction.cpp | 7 +-
.../clangd/refactor/tweaks/PopulateSwitch.cpp | 2 +-
.../clangd/unittests/ASTTests.cpp | 7 +-
.../clangd/unittests/DumpASTTests.cpp | 15 +--
.../clangd/unittests/FindTargetTests.cpp | 4 +-
.../clangd/unittests/HoverTests.cpp | 10 +-
.../clangd/unittests/InlayHintTests.cpp | 9 +-
.../clangd/unittests/QualityTests.cpp | 14 +-
.../clangd/unittests/SelectionTests.cpp | 4 +-
.../include-cleaner/lib/WalkAST.cpp | 29 ++--
.../bugprone/copy-constructor-init.cpp | 1 -
.../unused-local-non-trivial-variable.cpp | 6 +-
.../portability/std-allocator-const.cpp | 22 +--
68 files changed, 656 insertions(+), 690 deletions(-)
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-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp
index 7a0e00c6d9c2d..2b1f0f3c90c0c 100644
--- a/clang-tools-extra/clang-doc/Serialize.cpp
+++ b/clang-tools-extra/clang-doc/Serialize.cpp
@@ -895,8 +895,8 @@ parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir,
return;
for (const CXXBaseSpecifier &B : D->bases()) {
if (const RecordType *Ty = B.getType()->getAs<RecordType>()) {
- if (const CXXRecordDecl *Base =
- cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition())) {
+ if (const CXXRecordDecl *Base = cast_or_null<CXXRecordDecl>(
+ Ty->getOriginalDecl()->getDefinition())) {
// Initialized without USR and name, this will be set in the following
// if-else stmt.
BaseRecordInfo BI(
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbols.cpp b/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbols.cpp
index bb48883f88815..1f30d27c0a54f 100644
--- a/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbols.cpp
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbols.cpp
@@ -216,8 +216,7 @@ void FindAllSymbols::registerMatchers(MatchFinder *MatchFinder) {
// Uses of most types: just look at what the typeLoc refers to.
MatchFinder->addMatcher(
typeLoc(isExpansionInMainFile(),
- loc(qualType(allOf(unless(elaboratedType()),
- hasDeclaration(Types.bind("use")))))),
+ loc(qualType(hasDeclaration(Types.bind("use"))))),
this);
// Uses of typedefs: these are often transparent to hasDeclaration, so we need
// to handle them explicitly.
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/CrtpConstructorAccessibilityCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/CrtpConstructorAccessibilityCheck.cpp
index 6565fa3f7c85b..0625468d9da88 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CrtpConstructorAccessibilityCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/CrtpConstructorAccessibilityCheck.cpp
@@ -43,7 +43,8 @@ static bool isDerivedClassBefriended(const CXXRecordDecl *CRTP,
return false;
}
- return FriendType->getType()->getAsCXXRecordDecl() == Derived;
+ return declaresSameEntity(FriendType->getType()->getAsCXXRecordDecl(),
+ Derived);
});
}
@@ -55,7 +56,8 @@ getDerivedParameter(const ClassTemplateSpecializationDecl *CRTP,
CRTP->getTemplateArgs().asArray(), [&](const TemplateArgument &Arg) {
++Idx;
return Arg.getKind() == TemplateArgument::Type &&
- Arg.getAsType()->getAsCXXRecordDecl() == Derived;
+ declaresSameEntity(Arg.getAsType()->getAsCXXRecordDecl(),
+ Derived);
});
return AnyOf ? CRTP->getSpecializedTemplate()
diff --git a/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp
index a179d4bf66b4d..3cacb90cace52 100644
--- a/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp
@@ -577,7 +577,7 @@ approximateImplicitConversion(const TheCheck &Check, QualType LType,
ImplicitConversionModellingMode ImplicitMode);
static inline bool isUselessSugar(const Type *T) {
- return isa<AttributedType, DecayedType, ElaboratedType, ParenType>(T);
+ return isa<AttributedType, DecayedType, ParenType>(T);
}
namespace {
@@ -1040,7 +1040,9 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From,
const auto *ToRecord = To->getAsCXXRecordDecl();
if (isDerivedToBase(FromRecord, ToRecord)) {
LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Derived To Base.\n");
- WorkType = QualType{ToRecord->getTypeForDecl(), FastQualifiersToApply};
+ WorkType = QualType{
+ ToRecord->getASTContext().getCanonicalTagType(ToRecord)->getTypePtr(),
+ FastQualifiersToApply};
}
if (Ctx.getLangOpts().CPlusPlus17 && FromPtr && ToPtr) {
@@ -1072,9 +1074,9 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From,
WorkType = To;
}
- if (WorkType == To) {
+ if (Ctx.hasSameType(WorkType, To)) {
LLVM_DEBUG(llvm::dbgs() << "<<< approximateStdConv. Reached 'To' type.\n");
- return {WorkType};
+ return {Ctx.getCommonSugaredType(WorkType, To)};
}
LLVM_DEBUG(llvm::dbgs() << "<<< approximateStdConv. Did not reach 'To'.\n");
@@ -1219,7 +1221,7 @@ tryConversionOperators(const TheCheck &Check, const CXXRecordDecl *RD,
if (std::optional<UserDefinedConversionSelector::PreparedConversion>
SelectedConversion = ConversionSet()) {
- QualType RecordType{RD->getTypeForDecl(), 0};
+ CanQualType RecordType = RD->getASTContext().getCanonicalTagType(RD);
ConversionSequence Result{RecordType, ToType};
// The conversion from the operator call's return type to ToType was
@@ -1270,7 +1272,7 @@ tryConvertingConstructors(const TheCheck &Check, QualType FromType,
if (std::optional<UserDefinedConversionSelector::PreparedConversion>
SelectedConversion = ConversionSet()) {
- QualType RecordType{RD->getTypeForDecl(), 0};
+ CanQualType RecordType = RD->getASTContext().getCanonicalTagType(RD);
ConversionSequence Result{FromType, RecordType};
Result.AfterFirstStandard = SelectedConversion->Seq.AfterFirstStandard;
diff --git a/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp
index 75ef628436738..070ed04efffc4 100644
--- a/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp
@@ -69,10 +69,9 @@ void ForwardDeclarationNamespaceCheck::check(
// struct B { friend A; };
// \endcode
// `A` will not be marked as "referenced" in the AST.
- if (const TypeSourceInfo *Tsi = Decl->getFriendType()) {
- QualType Desugared = Tsi->getType().getDesugaredType(*Result.Context);
- FriendTypes.insert(Desugared.getTypePtr());
- }
+ if (const TypeSourceInfo *Tsi = Decl->getFriendType())
+ FriendTypes.insert(
+ Tsi->getType()->getCanonicalTypeUnqualified().getTypePtr());
}
}
@@ -119,7 +118,9 @@ void ForwardDeclarationNamespaceCheck::onEndOfTranslationUnit() {
if (CurDecl->hasDefinition() || CurDecl->isReferenced()) {
continue; // Skip forward declarations that are used/referenced.
}
- if (FriendTypes.contains(CurDecl->getTypeForDecl())) {
+ if (FriendTypes.contains(CurDecl->getASTContext()
+ .getCanonicalTagType(CurDecl)
+ ->getTypePtr())) {
continue; // Skip forward declarations referenced as friend.
}
if (CurDecl->getLocation().isMacroID() ||
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/IncorrectEnableIfCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp
index 75f1107904fce..07cd90d64c2a4 100644
--- a/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp
@@ -32,13 +32,10 @@ AST_MATCHER_P(TemplateTypeParmDecl, hasUnnamedDefaultArgument,
void IncorrectEnableIfCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
templateTypeParmDecl(
- hasUnnamedDefaultArgument(
- elaboratedTypeLoc(
- hasNamedTypeLoc(templateSpecializationTypeLoc(
- loc(qualType(hasDeclaration(namedDecl(
- hasName("::std::enable_if"))))))
- .bind("enable_if_specialization")))
- .bind("elaborated")))
+ hasUnnamedDefaultArgument(templateSpecializationTypeLoc(
+ loc(qualType(hasDeclaration(namedDecl(
+ hasName("::std::enable_if"))))))
+ .bind("enable_if_specialization")))
.bind("enable_if"),
this);
}
@@ -46,13 +43,11 @@ void IncorrectEnableIfCheck::registerMatchers(MatchFinder *Finder) {
void IncorrectEnableIfCheck::check(const MatchFinder::MatchResult &Result) {
const auto *EnableIf =
Result.Nodes.getNodeAs<TemplateTypeParmDecl>("enable_if");
- const auto *ElaboratedLoc =
- Result.Nodes.getNodeAs<ElaboratedTypeLoc>("elaborated");
const auto *EnableIfSpecializationLoc =
Result.Nodes.getNodeAs<TemplateSpecializationTypeLoc>(
"enable_if_specialization");
- if (!EnableIf || !ElaboratedLoc || !EnableIfSpecializationLoc)
+ if (!EnableIf || !EnableIfSpecializationLoc)
return;
const SourceManager &SM = *Result.SourceManager;
@@ -62,8 +57,10 @@ void IncorrectEnableIfCheck::check(const MatchFinder::MatchResult &Result) {
auto Diag = diag(EnableIf->getBeginLoc(),
"incorrect std::enable_if usage detected; use "
"'typename std::enable_if<...>::type'");
+ // FIXME: This should handle the enable_if specialization already having an
+ // elaborated keyword.
if (!getLangOpts().CPlusPlus20) {
- Diag << FixItHint::CreateInsertion(ElaboratedLoc->getBeginLoc(),
+ Diag << FixItHint::CreateInsertion(EnableIfSpecializationLoc->getBeginLoc(),
"typename ");
}
Diag << FixItHint::CreateInsertion(RAngleLoc.getLocWithOffset(1), "::type");
diff --git a/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp
index 33642c407a3a9..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 NamespaceDecl *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/bugprone/SizeofExpressionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
index 88e048e65d4e8..8da6227e172cd 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
@@ -425,7 +425,7 @@ void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) {
"suspicious usage of 'sizeof(array)/sizeof(...)';"
" denominator differs from the size of array elements")
<< E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
- } else if (NumTy && DenomTy && NumTy == DenomTy &&
+ } else if (NumTy && DenomTy && Ctx.hasSameType(NumTy, DenomTy) &&
!NumTy->isDependentType()) {
// Dependent type should not be compared.
diag(E->getOperatorLoc(),
@@ -434,7 +434,7 @@ void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) {
<< E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
} else if (!WarnOnSizeOfPointer) {
// When 'WarnOnSizeOfPointer' is enabled, these messages become redundant:
- if (PointedTy && DenomTy && PointedTy == DenomTy) {
+ if (PointedTy && DenomTy && Ctx.hasSameType(PointedTy, DenomTy)) {
diag(E->getOperatorLoc(),
"suspicious usage of 'sizeof(...)/sizeof(...)'; size of pointer "
"is divided by size of pointed type")
@@ -463,7 +463,8 @@ void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) {
const auto *SizeOfExpr =
Result.Nodes.getNodeAs<UnaryExprOrTypeTraitExpr>("sizeof-ptr-mul-expr");
- if ((LPtrTy == RPtrTy) && (LPtrTy == SizeofArgTy)) {
+ if (Ctx.hasSameType(LPtrTy, RPtrTy) &&
+ Ctx.hasSameType(LPtrTy, SizeofArgTy)) {
diag(SizeOfExpr->getBeginLoc(), "suspicious usage of 'sizeof(...)' in "
"pointer arithmetic")
<< SizeOfExpr->getSourceRange() << E->getOperatorLoc()
@@ -477,7 +478,8 @@ void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) {
const auto *SizeOfExpr =
Result.Nodes.getNodeAs<UnaryExprOrTypeTraitExpr>("sizeof-ptr-div-expr");
- if ((LPtrTy == RPtrTy) && (LPtrTy == SizeofArgTy)) {
+ if (Ctx.hasSameType(LPtrTy, RPtrTy) &&
+ Ctx.hasSameType(LPtrTy, SizeofArgTy)) {
diag(SizeOfExpr->getBeginLoc(), "suspicious usage of 'sizeof(...)' in "
"pointer arithmetic")
<< SizeOfExpr->getSourceRange() << E->getOperatorLoc()
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.cpp
index ca293178c78b4..29470b1f725fb 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.cpp
@@ -23,9 +23,9 @@ void NoSuspendWithLockCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
}
void NoSuspendWithLockCheck::registerMatchers(MatchFinder *Finder) {
- auto LockType = elaboratedType(namesType(templateSpecializationType(
+ auto LockType = templateSpecializationType(
hasDeclaration(namedDecl(matchers::matchesAnyListedName(
- utils::options::parseStringList(LockGuards)))))));
+ utils::options::parseStringList(LockGuards)))));
StatementMatcher Lock =
declStmt(has(varDecl(hasType(LockType)).bind("lock-decl")))
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
index b413b12cd37ab..40607597297b5 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
@@ -190,7 +190,7 @@ struct InitializerInsertion {
// Convenience utility to get a RecordDecl from a QualType.
const RecordDecl *getCanonicalRecordDecl(const QualType &Type) {
if (const auto *RT = Type.getCanonicalType()->getAs<RecordType>())
- return RT->getDecl();
+ return RT->getOriginalDecl();
return nullptr;
}
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp
index 76754394de760..40fd15c08f0a1 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp
@@ -92,7 +92,7 @@ void SlicingCheck::diagnoseSlicedOverriddenMethods(
for (const auto &Base : DerivedDecl.bases()) {
if (const auto *BaseRecordType = Base.getType()->getAs<RecordType>()) {
if (const auto *BaseRecord = cast_or_null<CXXRecordDecl>(
- BaseRecordType->getDecl()->getDefinition()))
+ BaseRecordType->getOriginalDecl()->getDefinition()))
diagnoseSlicedOverriddenMethods(Call, *BaseRecord, BaseDecl);
}
}
diff --git a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp
index 80ff97a762134..0302a5ad4957c 100644
--- a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp
+++ b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp
@@ -74,7 +74,7 @@ bool MultipleInheritanceCheck::isInterface(const CXXRecordDecl *Node) {
const auto *Ty = I.getType()->getAs<RecordType>();
if (!Ty)
continue;
- const RecordDecl *D = Ty->getDecl()->getDefinition();
+ const RecordDecl *D = Ty->getOriginalDecl()->getDefinition();
if (!D)
continue;
const auto *Base = cast<CXXRecordDecl>(D);
@@ -106,7 +106,8 @@ void MultipleInheritanceCheck::check(const MatchFinder::MatchResult &Result) {
const auto *Ty = I.getType()->getAs<RecordType>();
if (!Ty)
continue;
- const auto *Base = cast<CXXRecordDecl>(Ty->getDecl()->getDefinition());
+ const auto *Base =
+ cast<CXXRecordDecl>(Ty->getOriginalDecl()->getDefinition());
if (!isInterface(Base))
NumConcrete++;
}
@@ -117,7 +118,8 @@ void MultipleInheritanceCheck::check(const MatchFinder::MatchResult &Result) {
const auto *Ty = V.getType()->getAs<RecordType>();
if (!Ty)
continue;
- const auto *Base = cast<CXXRecordDecl>(Ty->getDecl()->getDefinition());
+ const auto *Base =
+ cast<CXXRecordDecl>(Ty->getOriginalDecl()->getDefinition());
if (!isInterface(Base))
NumConcrete++;
}
diff --git a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp b/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp
index e076b39b5d978..14e11eb0bc697 100644
--- a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp
@@ -89,6 +89,30 @@ static StringRef getDestTypeString(const SourceManager &SM,
SM, LangOpts);
}
+static bool sameTypeAsWritten(QualType X, QualType Y) {
+ if (X.getCanonicalType() != Y.getCanonicalType())
+ return false;
+
+ auto TC = X->getTypeClass();
+ if (TC != Y->getTypeClass())
+ return false;
+
+ switch (TC) {
+ case Type::Typedef:
+ return declaresSameEntity(cast<TypedefType>(X)->getDecl(),
+ cast<TypedefType>(Y)->getDecl());
+ case Type::Pointer:
+ return sameTypeAsWritten(cast<PointerType>(X)->getPointeeType(),
+ cast<PointerType>(Y)->getPointeeType());
+ case Type::RValueReference:
+ case Type::LValueReference:
+ return sameTypeAsWritten(cast<ReferenceType>(X)->getPointeeType(),
+ cast<ReferenceType>(Y)->getPointeeType());
+ default:
+ return true;
+ }
+}
+
void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) {
const auto *CastExpr = Result.Nodes.getNodeAs<ExplicitCastExpr>("cast");
@@ -128,12 +152,7 @@ void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) {
// case of overloaded functions, so detection of redundant casts is trickier
// in this case. Don't emit "redundant cast" warnings for function
// pointer/reference types.
- QualType Src = SourceTypeAsWritten, Dst = DestTypeAsWritten;
- if (const auto *ElTy = dyn_cast<ElaboratedType>(Src))
- Src = ElTy->getNamedType();
- if (const auto *ElTy = dyn_cast<ElaboratedType>(Dst))
- Dst = ElTy->getNamedType();
- if (Src == Dst) {
+ if (sameTypeAsWritten(SourceTypeAsWritten, DestTypeAsWritten)) {
diag(CastExpr->getBeginLoc(), "redundant cast to the same type")
<< FixItHint::CreateRemoval(ReplaceRange);
return;
diff --git a/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp b/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp
index 3deea0620514b..68233ec6bd441 100644
--- a/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp
+++ b/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp
@@ -72,7 +72,7 @@ static bool isStdInitializerList(QualType Type) {
}
if (const auto *RT = Type->getAs<RecordType>()) {
if (const auto *Specialization =
- dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl()))
+ dyn_cast<ClassTemplateSpecializationDecl>(RT->getOriginalDecl()))
return declIsStdInitializerList(Specialization->getSpecializedTemplate());
}
return false;
diff --git a/clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp b/clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp
index 805dcaf3ce402..274b8afa98bd6 100644
--- a/clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp
+++ b/clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp
@@ -257,8 +257,13 @@ getAliasNameRange(const MatchFinder::MatchResult &Result) {
return CharSourceRange::getTokenRange(
Using->getNameInfo().getSourceRange());
}
- return CharSourceRange::getTokenRange(
- Result.Nodes.getNodeAs<TypeLoc>("typeloc")->getSourceRange());
+ TypeLoc TL = *Result.Nodes.getNodeAs<TypeLoc>("typeloc");
+ if (auto QTL = TL.getAs<QualifiedTypeLoc>())
+ TL = QTL.getUnqualifiedLoc();
+
+ if (auto TTL = TL.getAs<TypedefTypeLoc>())
+ return CharSourceRange::getTokenRange(TTL.getNameLoc());
+ return CharSourceRange::getTokenRange(TL.castAs<UsingTypeLoc>().getNameLoc());
}
void UpgradeGoogletestCaseCheck::check(const MatchFinder::MatchResult &Result) {
diff --git a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp
index 697398a54332d..b32507d66cbac 100644
--- a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp
@@ -98,11 +98,12 @@ void ConstCorrectnessCheck::registerMatchers(MatchFinder *Finder) {
hasType(referenceType(pointee(hasCanonicalType(templateTypeParmType())))),
hasType(referenceType(pointee(substTemplateTypeParmType()))));
- const auto AllowedType = hasType(qualType(anyOf(
- hasDeclaration(namedDecl(matchers::matchesAnyListedName(AllowedTypes))),
- references(namedDecl(matchers::matchesAnyListedName(AllowedTypes))),
- pointerType(pointee(hasDeclaration(
- namedDecl(matchers::matchesAnyListedName(AllowedTypes))))))));
+ auto AllowedTypeDecl = namedDecl(
+ anyOf(matchers::matchesAnyListedName(AllowedTypes), usingShadowDecl()));
+
+ const auto AllowedType = hasType(qualType(
+ anyOf(hasDeclaration(AllowedTypeDecl), references(AllowedTypeDecl),
+ pointerType(pointee(hasDeclaration(AllowedTypeDecl))))));
const auto AutoTemplateType = varDecl(
anyOf(hasType(autoType()), hasType(referenceType(pointee(autoType()))),
diff --git a/clang-tools-extra/clang-tidy/misc/MisplacedConstCheck.cpp b/clang-tools-extra/clang-tidy/misc/MisplacedConstCheck.cpp
index 0cdd48c13b2a6..bb64a5618620c 100644
--- a/clang-tools-extra/clang-tidy/misc/MisplacedConstCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/MisplacedConstCheck.cpp
@@ -19,13 +19,13 @@ void MisplacedConstCheck::registerMatchers(MatchFinder *Finder) {
pointee(anyOf(isConstQualified(), ignoringParens(functionType()))))));
Finder->addMatcher(
- valueDecl(hasType(qualType(
- isConstQualified(),
- elaboratedType(namesType(typedefType(hasDeclaration(
- anyOf(typedefDecl(NonConstAndNonFunctionPointerType)
- .bind("typedef"),
- typeAliasDecl(NonConstAndNonFunctionPointerType)
- .bind("typeAlias")))))))))
+ valueDecl(
+ hasType(qualType(isConstQualified(),
+ typedefType(hasDeclaration(anyOf(
+ typedefDecl(NonConstAndNonFunctionPointerType)
+ .bind("typedef"),
+ typeAliasDecl(NonConstAndNonFunctionPointerType)
+ .bind("typeAlias")))))))
.bind("decl"),
this);
}
diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
index 9b2af2a8ca7d8..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;
@@ -104,9 +96,8 @@ static bool areEquivalentExpr(const Expr *Left, const Expr *Right) {
if (cast<DependentScopeDeclRefExpr>(Left)->getDeclName() !=
cast<DependentScopeDeclRefExpr>(Right)->getDeclName())
return false;
- return areEquivalentNameSpecifier(
- cast<DependentScopeDeclRefExpr>(Left)->getQualifier(),
- cast<DependentScopeDeclRefExpr>(Right)->getQualifier());
+ return cast<DependentScopeDeclRefExpr>(Left)->getQualifier() ==
+ cast<DependentScopeDeclRefExpr>(Right)->getQualifier();
case Stmt::DeclRefExprClass:
return cast<DeclRefExpr>(Left)->getDecl() ==
cast<DeclRefExpr>(Right)->getDecl();
diff --git a/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp b/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp
index 2dfaca19a8981..4fa679aa8dd88 100644
--- a/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp
@@ -35,11 +35,12 @@ void UnusedAliasDeclsCheck::check(const MatchFinder::MatchResult &Result) {
}
if (const auto *NestedName =
- Result.Nodes.getNodeAs<NestedNameSpecifier>("nns")) {
- if (const auto *AliasDecl = NestedName->getAsNamespaceAlias()) {
+ 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/misc/UnusedUsingDeclsCheck.cpp b/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
index d5c5fa3364d63..8211a0ec6a5e1 100644
--- a/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
@@ -71,11 +71,7 @@ void UnusedUsingDeclsCheck::registerMatchers(MatchFinder *Finder) {
templateArgument().bind("used")))),
this);
Finder->addMatcher(userDefinedLiteral().bind("used"), this);
- Finder->addMatcher(
- loc(elaboratedType(unless(hasQualifier(nestedNameSpecifier())),
- hasUnqualifiedDesugaredType(
- type(asTagDecl(tagDecl().bind("used")))))),
- this);
+ Finder->addMatcher(loc(asTagDecl(tagDecl().bind("used"))), this);
// Cases where we can identify the UsingShadowDecl directly, rather than
// just its target.
// FIXME: cover more cases in this way, as the AST supports it.
@@ -136,7 +132,7 @@ void UnusedUsingDeclsCheck::check(const MatchFinder::MatchResult &Result) {
}
if (const auto *ECD = dyn_cast<EnumConstantDecl>(Used)) {
if (const auto *ET = ECD->getType()->getAs<EnumType>())
- removeFromFoundDecls(ET->getDecl());
+ removeFromFoundDecls(ET->getOriginalDecl());
}
};
// We rely on the fact that the clang AST is walked in order, usages are only
diff --git a/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp b/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp
index f22f48d831608..2aca61021166d 100644
--- a/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp
@@ -29,8 +29,7 @@ static std::optional<const char *> getReplacementType(StringRef Type) {
void DeprecatedIosBaseAliasesCheck::registerMatchers(MatchFinder *Finder) {
auto IoStateDecl = typedefDecl(hasAnyName(DeprecatedTypes)).bind("TypeDecl");
- auto IoStateType =
- qualType(hasDeclaration(IoStateDecl), unless(elaboratedType()));
+ auto IoStateType = typedefType(hasDeclaration(IoStateDecl));
Finder->addMatcher(typeLoc(loc(IoStateType)).bind("TypeLoc"), this);
}
@@ -43,12 +42,14 @@ void DeprecatedIosBaseAliasesCheck::check(
StringRef TypeName = Typedef->getName();
auto Replacement = getReplacementType(TypeName);
- const auto *TL = Result.Nodes.getNodeAs<TypeLoc>("TypeLoc");
- SourceLocation IoStateLoc = TL->getBeginLoc();
+ TypeLoc TL = *Result.Nodes.getNodeAs<TypeLoc>("TypeLoc");
+ if (auto QTL = TL.getAs<QualifiedTypeLoc>())
+ TL = QTL.getUnqualifiedLoc();
+ SourceLocation IoStateLoc = TL.castAs<TypedefTypeLoc>().getNameLoc();
// Do not generate fixits for matches depending on template arguments and
// macro expansions.
- bool Fix = Replacement && !TL->getType()->isDependentType();
+ bool Fix = Replacement && !TL.getType()->isDependentType();
if (IoStateLoc.isMacroID()) {
IoStateLoc = SM.getSpellingLoc(IoStateLoc);
Fix = false;
diff --git a/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp b/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp
index 1e271dfa768ce..a54d0721a5b7d 100644
--- a/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp
@@ -77,8 +77,7 @@ AST_MATCHER_P(CXXRecordDecl, isMoveConstructibleInBoundCXXRecordDecl, StringRef,
static TypeMatcher notTemplateSpecConstRefType() {
return lValueReferenceType(
- pointee(unless(elaboratedType(namesType(templateSpecializationType()))),
- isConstQualified()));
+ pointee(unless(templateSpecializationType()), isConstQualified()));
}
static TypeMatcher nonConstValueType() {
diff --git a/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
index 1ad31d315dc2a..f2142b810a126 100644
--- a/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
@@ -48,7 +48,7 @@ void ReplaceAutoPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
void ReplaceAutoPtrCheck::registerMatchers(MatchFinder *Finder) {
auto AutoPtrDecl = recordDecl(hasName("auto_ptr"), isInStdNamespace());
- auto AutoPtrType = qualType(hasDeclaration(AutoPtrDecl));
+ auto AutoPtrType = hasCanonicalType(recordType(hasDeclaration(AutoPtrDecl)));
// std::auto_ptr<int> a;
// ^~~~~~~~~~~~~
@@ -58,11 +58,7 @@ void ReplaceAutoPtrCheck::registerMatchers(MatchFinder *Finder) {
//
// std::auto_ptr<int> fn(std::auto_ptr<int>);
// ^~~~~~~~~~~~~ ^~~~~~~~~~~~~
- Finder->addMatcher(typeLoc(loc(qualType(AutoPtrType,
- // Skip elaboratedType() as the named
- // type will match soon thereafter.
- unless(elaboratedType()))))
- .bind(AutoPtrTokenId),
+ Finder->addMatcher(typeLoc(loc(qualType(AutoPtrType))).bind(AutoPtrTokenId),
this);
// using std::auto_ptr;
@@ -118,10 +114,13 @@ void ReplaceAutoPtrCheck::check(const MatchFinder::MatchResult &Result) {
}
SourceLocation AutoPtrLoc;
- if (const auto *TL = Result.Nodes.getNodeAs<TypeLoc>(AutoPtrTokenId)) {
+ if (const auto *PTL = Result.Nodes.getNodeAs<TypeLoc>(AutoPtrTokenId)) {
+ auto TL = *PTL;
+ if (auto QTL = TL.getAs<QualifiedTypeLoc>())
+ TL = QTL.getUnqualifiedLoc();
// std::auto_ptr<int> i;
// ^
- if (auto Loc = TL->getAs<TemplateSpecializationTypeLoc>())
+ if (auto Loc = TL.getAs<TemplateSpecializationTypeLoc>())
AutoPtrLoc = Loc.getTemplateNameLoc();
} else if (const auto *D =
Result.Nodes.getNodeAs<UsingDecl>(AutoPtrTokenId)) {
diff --git a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp
index ff0b3213cb58f..de2d42d760550 100644
--- a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp
@@ -168,19 +168,6 @@ static DeclarationName getName(const DeclRefExpr &D) {
return D.getDecl()->getDeclName();
}
-static bool isNamedType(const ElaboratedTypeLoc &ETL) {
- if (const auto *TFT =
- ETL.getNamedTypeLoc().getTypePtr()->getAs<TypedefType>()) {
- const TypedefNameDecl *Decl = TFT->getDecl();
- return Decl->getDeclName().isIdentifier() && Decl->getName() == "type";
- }
- return false;
-}
-
-static bool isNamedType(const DependentNameTypeLoc &DTL) {
- return DTL.getTypePtr()->getIdentifier()->getName() == "type";
-}
-
namespace {
AST_POLYMORPHIC_MATCHER(isValue, AST_POLYMORPHIC_SUPPORTED_TYPES(
DeclRefExpr, DependentScopeDeclRefExpr)) {
@@ -188,10 +175,14 @@ AST_POLYMORPHIC_MATCHER(isValue, AST_POLYMORPHIC_SUPPORTED_TYPES(
return Ident && Ident->isStr("value");
}
-AST_POLYMORPHIC_MATCHER(isType,
- AST_POLYMORPHIC_SUPPORTED_TYPES(ElaboratedTypeLoc,
- DependentNameTypeLoc)) {
- return Node.getBeginLoc().isValid() && isNamedType(Node);
+AST_MATCHER(TypeLoc, isType) {
+ if (auto TL = Node.getAs<TypedefTypeLoc>()) {
+ const auto *TD = TL.getDecl();
+ return TD->getDeclName().isIdentifier() && TD->getName() == "type";
+ }
+ if (auto TL = Node.getAs<DependentNameTypeLoc>())
+ return TL.getTypePtr()->getIdentifier()->getName() == "type";
+ return false;
}
} // namespace
@@ -214,10 +205,7 @@ void TypeTraitsCheck::registerMatchers(MatchFinder *Finder) {
.bind(Bind),
this);
}
- Finder->addMatcher(mapAnyOf(elaboratedTypeLoc, dependentNameTypeLoc)
- .with(isType())
- .bind(Bind),
- this);
+ Finder->addMatcher(typeLoc(isType()).bind(Bind), this);
}
static bool isNamedDeclInStdTraitsSet(const NamedDecl *ND,
@@ -226,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()) {
@@ -250,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());
@@ -274,8 +259,8 @@ void TypeTraitsCheck::check(const MatchFinder::MatchResult &Result) {
SourceLocation EndLoc,
SourceLocation TypenameLoc) {
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());
@@ -301,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/UseAutoCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp
index f4b63087b7234..b601620633cee 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp
@@ -186,16 +186,14 @@ TypeMatcher nestedIterator() {
/// declarations and which name standard iterators for standard containers.
TypeMatcher iteratorFromUsingDeclaration() {
auto HasIteratorDecl = hasDeclaration(namedDecl(hasStdIteratorName()));
- // Types resulting from using declarations are represented by elaboratedType.
- return elaboratedType(
- // Unwrap the nested name specifier to test for one of the standard
- // containers.
- hasQualifier(specifiesType(templateSpecializationType(hasDeclaration(
- namedDecl(hasStdContainerName(), isInStdNamespace()))))),
- // the named type is what comes after the final '::' in the type. It
- // should name one of the standard iterator names.
- namesType(
- anyOf(typedefType(HasIteratorDecl), recordType(HasIteratorDecl))));
+ // Unwrap the nested name specifier to test for one of the standard
+ // containers.
+ auto Qualifier = hasQualifier(specifiesType(templateSpecializationType(
+ hasDeclaration(namedDecl(hasStdContainerName(), isInStdNamespace())))));
+ // the named type is what comes after the final '::' in the type. It should
+ // name one of the standard iterator names.
+ return anyOf(typedefType(HasIteratorDecl, Qualifier),
+ recordType(HasIteratorDecl, Qualifier));
}
/// This matcher returns declaration statements that contain variable
diff --git a/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
index e9b96c4016af6..07274d0376207 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
@@ -60,9 +60,11 @@ matchEnableIfSpecializationImplTypename(TypeLoc TheType) {
Keyword != ElaboratedTypeKeyword::None)) {
return std::nullopt;
}
- TheType = Dep.getQualifierLoc().getTypeLoc();
+ TheType = Dep.getQualifierLoc().getAsTypeLoc();
if (TheType.isNull())
return std::nullopt;
+ } else {
+ return std::nullopt;
}
if (const auto SpecializationLoc =
@@ -89,9 +91,6 @@ matchEnableIfSpecializationImplTypename(TypeLoc TheType) {
static std::optional<TemplateSpecializationTypeLoc>
matchEnableIfSpecializationImplTrait(TypeLoc TheType) {
- if (const auto Elaborated = TheType.getAs<ElaboratedTypeLoc>())
- TheType = Elaborated.getNamedTypeLoc();
-
if (const auto SpecializationLoc =
TheType.getAs<TemplateSpecializationTypeLoc>()) {
diff --git a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp
index aaf24eaa33c1b..ee49d8a7cb0b0 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp
@@ -164,10 +164,10 @@ void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) {
auto CallEmplacy = cxxMemberCallExpr(
hasDeclaration(
functionDecl(hasAnyNameIgnoringTemplates(EmplacyFunctions))),
- on(hasTypeOrPointeeType(hasCanonicalType(hasDeclaration(
- has(typedefNameDecl(hasName("value_type"),
- hasType(type(hasUnqualifiedDesugaredType(
- recordType().bind("value_type")))))))))));
+ on(hasTypeOrPointeeType(
+ hasCanonicalType(hasDeclaration(has(typedefNameDecl(
+ hasName("value_type"),
+ hasType(hasCanonicalType(recordType().bind("value_type"))))))))));
// We can't replace push_backs of smart pointer because
// if emplacement fails (f.e. bad_alloc in vector) we will have leak of
@@ -241,17 +241,16 @@ void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) {
auto HasConstructExprWithValueTypeType =
has(ignoringImplicit(cxxConstructExpr(
- SoughtConstructExpr, hasType(type(hasUnqualifiedDesugaredType(
- type(equalsBoundNode("value_type"))))))));
-
- auto HasBracedInitListWithValueTypeType =
- anyOf(allOf(HasConstructInitListExpr,
- has(initListExpr(hasType(type(hasUnqualifiedDesugaredType(
- type(equalsBoundNode("value_type")))))))),
- has(cxxBindTemporaryExpr(
- HasConstructInitListExpr,
- has(initListExpr(hasType(type(hasUnqualifiedDesugaredType(
- type(equalsBoundNode("value_type"))))))))));
+ SoughtConstructExpr,
+ hasType(hasCanonicalType(type(equalsBoundNode("value_type")))))));
+
+ auto HasBracedInitListWithValueTypeType = anyOf(
+ allOf(HasConstructInitListExpr,
+ has(initListExpr(hasType(
+ hasCanonicalType(type(equalsBoundNode("value_type"))))))),
+ has(cxxBindTemporaryExpr(HasConstructInitListExpr,
+ has(initListExpr(hasType(hasCanonicalType(
+ type(equalsBoundNode("value_type")))))))));
auto HasConstructExprWithValueTypeTypeAsLastArgument = hasLastArgument(
materializeTemporaryExpr(
@@ -289,19 +288,17 @@ void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) {
this);
Finder->addMatcher(
- traverse(
- TK_AsIs,
- cxxMemberCallExpr(
- CallEmplacy,
- on(hasType(cxxRecordDecl(has(typedefNameDecl(
- hasName("value_type"),
- hasType(type(
- hasUnqualifiedDesugaredType(recordType(hasDeclaration(
- cxxRecordDecl(hasAnyName(SmallVector<StringRef, 2>(
- TupleTypes.begin(), TupleTypes.end()))))))))))))),
- has(MakeTuple), hasSameNumArgsAsDeclNumParams(),
- unless(isInTemplateInstantiation()))
- .bind("emplacy_call")),
+ traverse(TK_AsIs,
+ cxxMemberCallExpr(
+ CallEmplacy,
+ on(hasType(cxxRecordDecl(has(typedefNameDecl(
+ hasName("value_type"),
+ hasType(hasCanonicalType(recordType(hasDeclaration(
+ cxxRecordDecl(hasAnyName(SmallVector<StringRef, 2>(
+ TupleTypes.begin(), TupleTypes.end())))))))))))),
+ has(MakeTuple), hasSameNumArgsAsDeclNumParams(),
+ unless(isInTemplateInstantiation()))
+ .bind("emplacy_call")),
this);
}
diff --git a/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp
index 52e9a9f8d49e0..5310f2fd25381 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp
@@ -29,7 +29,7 @@ static bool isLockGuardDecl(const NamedDecl *Decl) {
static bool isLockGuard(const QualType &Type) {
if (const auto *Record = Type->getAs<RecordType>())
- if (const RecordDecl *Decl = Record->getDecl())
+ if (const RecordDecl *Decl = Record->getOriginalDecl())
return isLockGuardDecl(Decl);
if (const auto *TemplateSpecType = Type->getAs<TemplateSpecializationType>())
@@ -89,17 +89,6 @@ findLocksInCompoundStmt(const CompoundStmt *Block,
return LockGuardGroups;
}
-static TemplateSpecializationTypeLoc
-getTemplateLockGuardTypeLoc(const TypeSourceInfo *SourceInfo) {
- const TypeLoc Loc = SourceInfo->getTypeLoc();
-
- const auto ElaboratedLoc = Loc.getAs<ElaboratedTypeLoc>();
- if (!ElaboratedLoc)
- return {};
-
- return ElaboratedLoc.getNamedTypeLoc().getAs<TemplateSpecializationTypeLoc>();
-}
-
// Find the exact source range of the 'lock_guard' token
static SourceRange getLockGuardRange(const TypeSourceInfo *SourceInfo) {
const TypeLoc LockGuardTypeLoc = SourceInfo->getTypeLoc();
@@ -110,7 +99,7 @@ static SourceRange getLockGuardRange(const TypeSourceInfo *SourceInfo) {
// Find the exact source range of the 'lock_guard' name token
static SourceRange getLockGuardNameRange(const TypeSourceInfo *SourceInfo) {
const TemplateSpecializationTypeLoc TemplateLoc =
- getTemplateLockGuardTypeLoc(SourceInfo);
+ SourceInfo->getTypeLoc().getAs<TemplateSpecializationTypeLoc>();
if (!TemplateLoc)
return {};
@@ -136,11 +125,11 @@ void UseScopedLockCheck::registerMatchers(MatchFinder *Finder) {
const auto LockGuardClassDecl =
namedDecl(hasName("lock_guard"), isInStdNamespace());
- const auto LockGuardType = qualType(anyOf(
- hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(LockGuardClassDecl))),
- elaboratedType(namesType(hasUnqualifiedDesugaredType(
- templateSpecializationType(hasDeclaration(LockGuardClassDecl)))))));
+ const auto LockGuardType =
+ qualType(anyOf(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(LockGuardClassDecl))),
+ hasUnqualifiedDesugaredType(templateSpecializationType(
+ hasDeclaration(LockGuardClassDecl)))));
const auto LockVarDecl = varDecl(hasType(LockGuardType));
@@ -165,18 +154,16 @@ void UseScopedLockCheck::registerMatchers(MatchFinder *Finder) {
if (WarnOnUsingAndTypedef) {
// Match 'typedef std::lock_guard<std::mutex> Lock'
Finder->addMatcher(typedefDecl(unless(isExpansionInSystemHeader()),
- hasUnderlyingType(LockGuardType))
+ hasType(hasUnderlyingType(LockGuardType)))
.bind("lock-guard-typedef"),
this);
// Match 'using Lock = std::lock_guard<std::mutex>'
- Finder->addMatcher(
- typeAliasDecl(
- unless(isExpansionInSystemHeader()),
- hasType(elaboratedType(namesType(templateSpecializationType(
- hasDeclaration(LockGuardClassDecl))))))
- .bind("lock-guard-using-alias"),
- this);
+ Finder->addMatcher(typeAliasDecl(unless(isExpansionInSystemHeader()),
+ hasType(templateSpecializationType(
+ hasDeclaration(LockGuardClassDecl))))
+ .bind("lock-guard-using-alias"),
+ this);
// Match 'using std::lock_guard'
Finder->addMatcher(
@@ -288,8 +275,8 @@ void UseScopedLockCheck::diagOnSourceInfo(
const ast_matchers::MatchFinder::MatchResult &Result) {
const TypeLoc TL = LockGuardSourceInfo->getTypeLoc();
- if (const auto ElaboratedTL = TL.getAs<ElaboratedTypeLoc>()) {
- auto Diag = diag(ElaboratedTL.getBeginLoc(), UseScopedLockMessage);
+ if (const auto TTL = TL.getAs<TemplateSpecializationTypeLoc>()) {
+ auto Diag = diag(TTL.getBeginLoc(), UseScopedLockMessage);
const SourceRange LockGuardRange =
getLockGuardNameRange(LockGuardSourceInfo);
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/modernize/UseTransparentFunctorsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp
index a053c07f95ce2..2373a26fe48b4 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp
@@ -37,15 +37,13 @@ void UseTransparentFunctorsCheck::registerMatchers(MatchFinder *Finder) {
// Non-transparent functor mentioned as a template parameter. FIXIT.
Finder->addMatcher(
- loc(qualType(
- unless(elaboratedType()),
- hasDeclaration(classTemplateSpecializationDecl(
- unless(hasAnyTemplateArgument(templateArgument(refersToType(
- qualType(pointsTo(qualType(isAnyCharacter()))))))),
- hasAnyTemplateArgument(
- templateArgument(refersToType(qualType(hasDeclaration(
- TransparentFunctors))))
- .bind("Functor"))))))
+ loc(qualType(hasDeclaration(classTemplateSpecializationDecl(
+ unless(hasAnyTemplateArgument(templateArgument(refersToType(
+ qualType(pointsTo(qualType(isAnyCharacter()))))))),
+ hasAnyTemplateArgument(
+ templateArgument(refersToType(qualType(
+ hasDeclaration(TransparentFunctors))))
+ .bind("Functor"))))))
.bind("FunctorParentLoc"),
this);
diff --git a/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp b/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
index 7022e9d784fa7..1c018999432e3 100644
--- a/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
+++ b/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
@@ -42,11 +42,11 @@ void NoAutomaticMoveCheck::registerMatchers(MatchFinder *Finder) {
// A matcher for a `DstT::DstT(const Src&)` where DstT also has a
// `DstT::DstT(Src&&)`.
const auto LValueRefCtor = cxxConstructorDecl(
- hasParameter(0,
- hasType(lValueReferenceType(pointee(type().bind("SrcT"))))),
+ hasParameter(0, hasType(hasCanonicalType(
+ lValueReferenceType(pointee(type().bind("SrcT")))))),
ofClass(cxxRecordDecl(hasMethod(cxxConstructorDecl(
- hasParameter(0, hasType(rValueReferenceType(
- pointee(type(equalsBoundNode("SrcT")))))))))));
+ hasParameter(0, hasType(hasCanonicalType(rValueReferenceType(
+ pointee(type(equalsBoundNode("SrcT"))))))))))));
// A matcher for `DstT::DstT(const Src&&)`, which typically comes from an
// instantiation of `template <typename U> DstT::DstT(U&&)`.
diff --git a/clang-tools-extra/clang-tidy/portability/StdAllocatorConstCheck.cpp b/clang-tools-extra/clang-tidy/portability/StdAllocatorConstCheck.cpp
index 3b4d65be7dfa1..5a3c9a4203eb9 100644
--- a/clang-tools-extra/clang-tidy/portability/StdAllocatorConstCheck.cpp
+++ b/clang-tools-extra/clang-tidy/portability/StdAllocatorConstCheck.cpp
@@ -15,10 +15,11 @@ namespace clang::tidy::portability {
void StdAllocatorConstCheck::registerMatchers(MatchFinder *Finder) {
// Match std::allocator<const T>.
- auto AllocatorConst =
+ auto AllocatorConst = qualType(hasCanonicalType(
recordType(hasDeclaration(classTemplateSpecializationDecl(
hasName("::std::allocator"),
- hasTemplateArgument(0, refersToType(qualType(isConstQualified()))))));
+ hasTemplateArgument(0,
+ refersToType(qualType(isConstQualified()))))))));
auto HasContainerName =
hasAnyName("::std::vector", "::std::deque", "::std::list",
@@ -31,8 +32,10 @@ void StdAllocatorConstCheck::registerMatchers(MatchFinder *Finder) {
// aren't caught.
Finder->addMatcher(
typeLoc(
- templateSpecializationTypeLoc(),
- loc(hasUnqualifiedDesugaredType(anyOf(
+ anyOf(templateSpecializationTypeLoc(),
+ qualifiedTypeLoc(
+ hasUnqualifiedLoc(templateSpecializationTypeLoc()))),
+ loc(qualType(anyOf(
recordType(hasDeclaration(classTemplateSpecializationDecl(
HasContainerName,
anyOf(
diff --git a/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp b/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
index fffb136e5a332..8392f9ad685e2 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::Super:
+ 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/readability/SuspiciousCallArgumentCheck.cpp b/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp
index 5a04029e4a6fa..447c2437666cf 100644
--- a/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp
@@ -414,9 +414,9 @@ static bool areTypesCompatible(QualType ArgType, QualType ParamType,
// Arithmetic types are interconvertible, except scoped enums.
if (ParamType->isArithmeticType() && ArgType->isArithmeticType()) {
if ((ParamType->isEnumeralType() &&
- ParamType->castAs<EnumType>()->getDecl()->isScoped()) ||
+ ParamType->castAs<EnumType>()->getOriginalDecl()->isScoped()) ||
(ArgType->isEnumeralType() &&
- ArgType->castAs<EnumType>()->getDecl()->isScoped()))
+ ArgType->castAs<EnumType>()->getOriginalDecl()->isScoped()))
return false;
return true;
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 6f6b8a853a91e..718467ed02f0a 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -67,11 +67,7 @@ static QualType getNonTemplateAlias(QualType QT) {
if (!TT->getDecl()->getDescribedTemplate() &&
!TT->getDecl()->getDeclContext()->isDependentContext())
return QT;
- QT = TT->getDecl()->getUnderlyingType();
- }
- // cast to elaborated type
- else if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(QT)) {
- QT = ET->getNamedType();
+ QT = TT->desugar();
} else {
break;
}
diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp
index 0637d0eff688c..aa6aefcf0c493 100644
--- a/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp
+++ b/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp
@@ -66,7 +66,8 @@ ExceptionSpecAnalyzer::analyzeBase(const CXXBaseSpecifier &Base,
if (!RecType)
return State::Unknown;
- const auto *BaseClass = cast<CXXRecordDecl>(RecType->getDecl());
+ const auto *BaseClass =
+ cast<CXXRecordDecl>(RecType->getOriginalDecl())->getDefinitionOrSelf();
return analyzeRecord(BaseClass, Kind);
}
diff --git a/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp b/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
index 7f4ccca84faa5..3229efb957067 100644
--- a/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
+++ b/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
@@ -465,8 +465,9 @@ bool FormatStringConverter::emitIntegerArgument(
// the signedness based on the format string, so we need to do the
// same.
if (const auto *ET = ArgType->getAs<EnumType>()) {
- if (const std::optional<std::string> MaybeCastType =
- castTypeForArgument(ArgKind, ET->getDecl()->getIntegerType()))
+ if (const std::optional<std::string> MaybeCastType = castTypeForArgument(
+ ArgKind,
+ ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType()))
ArgFixes.emplace_back(
ArgIndex, (Twine("static_cast<") + *MaybeCastType + ">(").str());
else
diff --git a/clang-tools-extra/clang-tidy/utils/Matchers.cpp b/clang-tools-extra/clang-tidy/utils/Matchers.cpp
index 4974a9cdb9f4b..bd7b03eb39ad7 100644
--- a/clang-tools-extra/clang-tidy/utils/Matchers.cpp
+++ b/clang-tools-extra/clang-tidy/utils/Matchers.cpp
@@ -34,7 +34,7 @@ bool MatchesAnyListedTypeNameMatcher::matches(
PrintingPolicy PrintingPolicyWithSuppressedTag(
Finder->getASTContext().getLangOpts());
PrintingPolicyWithSuppressedTag.PrintAsCanonical = CanonicalTypes;
- PrintingPolicyWithSuppressedTag.SuppressElaboration = true;
+ PrintingPolicyWithSuppressedTag.FullyQualifiedName = true;
PrintingPolicyWithSuppressedTag.SuppressScope = false;
PrintingPolicyWithSuppressedTag.SuppressTagKeyword = true;
PrintingPolicyWithSuppressedTag.SuppressUnwrittenScope = true;
diff --git a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp
index 6cf38ddf3d914..3cf6e57ca4df5 100644
--- a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp
+++ b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp
@@ -281,8 +281,10 @@ class RenamerClangTidyVisitor
}
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc Loc) {
- if (const NestedNameSpecifier *Spec = Loc.getNestedNameSpecifier()) {
- if (const NamespaceDecl *Decl = Spec->getAsNamespace())
+ if (NestedNameSpecifier Spec = Loc.getNestedNameSpecifier();
+ Spec.getKind() == NestedNameSpecifier::Kind::Namespace) {
+ if (const auto *Decl =
+ dyn_cast<NamespaceDecl>(Spec.getAsNamespaceAndPrefix().Namespace))
Check->addUsage(Decl, Loc.getLocalSourceRange(), SM);
}
@@ -322,48 +324,34 @@ class RenamerClangTidyVisitor
}
bool VisitTypedefTypeLoc(const TypedefTypeLoc &Loc) {
- Check->addUsage(Loc.getTypedefNameDecl(), Loc.getSourceRange(), SM);
+ Check->addUsage(Loc.getDecl(), Loc.getNameLoc(), SM);
return true;
}
bool VisitTagTypeLoc(const TagTypeLoc &Loc) {
- Check->addUsage(Loc.getDecl(), Loc.getSourceRange(), SM);
- return true;
- }
-
- bool VisitInjectedClassNameTypeLoc(const InjectedClassNameTypeLoc &Loc) {
- Check->addUsage(Loc.getDecl(), Loc.getSourceRange(), SM);
+ Check->addUsage(Loc.getOriginalDecl(), Loc.getNameLoc(), SM);
return true;
}
bool VisitUnresolvedUsingTypeLoc(const UnresolvedUsingTypeLoc &Loc) {
- Check->addUsage(Loc.getDecl(), Loc.getSourceRange(), SM);
+ Check->addUsage(Loc.getDecl(), Loc.getNameLoc(), SM);
return true;
}
bool VisitTemplateTypeParmTypeLoc(const TemplateTypeParmTypeLoc &Loc) {
- Check->addUsage(Loc.getDecl(), Loc.getSourceRange(), SM);
+ Check->addUsage(Loc.getDecl(), Loc.getNameLoc(), SM);
return true;
}
bool
VisitTemplateSpecializationTypeLoc(const TemplateSpecializationTypeLoc &Loc) {
const TemplateDecl *Decl =
- Loc.getTypePtr()->getTemplateName().getAsTemplateDecl();
+ Loc.getTypePtr()->getTemplateName().getAsTemplateDecl(
+ /*IgnoreDeduced=*/true);
- SourceRange Range(Loc.getTemplateNameLoc(), Loc.getTemplateNameLoc());
- if (const auto *ClassDecl = dyn_cast<TemplateDecl>(Decl)) {
+ if (const auto *ClassDecl = dyn_cast<TemplateDecl>(Decl))
if (const NamedDecl *TemplDecl = ClassDecl->getTemplatedDecl())
- Check->addUsage(TemplDecl, Range, SM);
- }
-
- return true;
- }
-
- bool VisitDependentTemplateSpecializationTypeLoc(
- const DependentTemplateSpecializationTypeLoc &Loc) {
- if (const TagDecl *Decl = Loc.getTypePtr()->getAsTagDecl())
- Check->addUsage(Decl, Loc.getSourceRange(), SM);
+ Check->addUsage(TemplDecl, Loc.getTemplateNameLoc(), SM);
return true;
}
diff --git a/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp b/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp
index 44db0c2aed607..96d3a5bbd86a2 100644
--- a/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp
+++ b/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp
@@ -124,7 +124,8 @@ bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context) {
return true;
if (const auto *RT = CanonicalType->getAs<RecordType>()) {
- return recordIsTriviallyDefaultConstructible(*RT->getDecl(), Context);
+ return recordIsTriviallyDefaultConstructible(
+ *RT->getOriginalDecl()->getDefinitionOrSelf(), Context);
}
// No other types can match.
diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp
index e274236527817..a7ba8a1e16891 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();
}
@@ -187,6 +211,7 @@ std::string printQualifiedName(const NamedDecl &ND) {
// include them, but at query time it's hard to find all the inline
// namespaces to query: the preamble doesn't have a dedicated list.
Policy.SuppressUnwrittenScope = true;
+ Policy.SuppressScope = true;
// (unnamed struct), not (unnamed struct at /path/to/foo.cc:42:1).
// In clangd, context is usually available and paths are mostly noise.
Policy.AnonymousTagLocations = false;
@@ -213,8 +238,7 @@ std::string printUsingNamespaceName(const ASTContext &Ctx,
std::string Name;
llvm::raw_string_ostream Out(Name);
- if (auto *Qual = D.getQualifier())
- Qual->print(Out, PP);
+ D.getQualifier().print(Out, PP);
D.getNominatedNamespaceAsWritten()->printName(Out);
return Out.str();
}
@@ -229,8 +253,7 @@ std::string printName(const ASTContext &Ctx, const NamedDecl &ND) {
// Handle 'using namespace'. They all have the same name - <using-directive>.
if (auto *UD = llvm::dyn_cast<UsingDirectiveDecl>(&ND)) {
Out << "using namespace ";
- if (auto *Qual = UD->getQualifier())
- Qual->print(Out, PP);
+ UD->getQualifier().print(Out, PP);
UD->getNominatedNamespaceAsWritten()->printName(Out);
return Out.str();
}
@@ -250,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.
@@ -391,12 +413,13 @@ preferredIncludeDirective(llvm::StringRef FileName, const LangOptions &LangOpts,
}
std::string printType(const QualType QT, const DeclContext &CurContext,
- const llvm::StringRef Placeholder) {
+ const llvm::StringRef Placeholder, bool FullyQualify) {
std::string Result;
llvm::raw_string_ostream OS(Result);
PrintingPolicy PP(CurContext.getParentASTContext().getPrintingPolicy());
PP.SuppressTagKeyword = true;
PP.SuppressUnwrittenScope = true;
+ PP.FullyQualifiedName = FullyQualify;
class PrintCB : public PrintingCallbacks {
public:
@@ -439,6 +462,7 @@ QualType declaredType(const TypeDecl *D) {
if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D))
if (const auto *Args = CTSD->getTemplateArgsAsWritten())
return Context.getTemplateSpecializationType(
+ ElaboratedTypeKeyword::None,
TemplateName(CTSD->getSpecializedTemplate()), Args->arguments(),
/*CanonicalArgs=*/{});
return Context.getTypeDeclType(D);
@@ -664,11 +688,10 @@ std::string getQualification(ASTContext &Context,
auto VisibleNamespaceDecls =
getUsingNamespaceDirectives(DestContext, InsertionPoint);
return getQualification(
- Context, DestContext, ND->getDeclContext(),
- [&](NestedNameSpecifier *NNS) {
- if (NNS->getKind() != NestedNameSpecifier::Namespace)
+ Context, DestContext, ND->getDeclContext(), [&](const Decl *D) {
+ if (D->getKind() != Decl::Namespace)
return false;
- const auto *CanonNSD = NNS->getAsNamespace()->getCanonicalDecl();
+ const auto *CanonNSD = cast<NamespaceDecl>(D)->getCanonicalDecl();
return llvm::any_of(VisibleNamespaceDecls,
[CanonNSD](const NamespaceDecl *NSD) {
return NSD->getCanonicalDecl() == CanonNSD;
@@ -685,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/AST.h b/clang-tools-extra/clangd/AST.h
index fb0722d697cd0..1538d12172593 100644
--- a/clang-tools-extra/clangd/AST.h
+++ b/clang-tools-extra/clangd/AST.h
@@ -135,7 +135,8 @@ preferredIncludeDirective(llvm::StringRef FileName, const LangOptions &LangOpts,
/// Returns a QualType as string. The result doesn't contain unwritten scopes
/// like anonymous/inline namespace.
std::string printType(const QualType QT, const DeclContext &CurContext,
- llvm::StringRef Placeholder = "");
+ llvm::StringRef Placeholder = "",
+ bool FullyQualify = false);
/// Indicates if \p D is a template instantiation implicitly generated by the
/// compiler, e.g.
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index d5907e3143bf6..c4cf00075e5f1 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -1462,20 +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:
- case NestedNameSpecifier::NamespaceAlias:
+ 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::Super:
+ 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 8f24477ecd3de..aea568d1c3a6e 100644
--- a/clang-tools-extra/clangd/DumpAST.cpp
+++ b/clang-tools-extra/clangd/DumpAST.cpp
@@ -147,18 +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(NamespaceAlias);
#undef NNS_KIND
}
llvm_unreachable("Unhandled SpecifierKind enum");
@@ -262,7 +261,7 @@ class DumpVisitor : public RecursiveASTVisitor<DumpVisitor> {
return TL.getType().getLocalQualifiers().getAsString(
Ctx.getPrintingPolicy());
if (const auto *TT = dyn_cast<TagType>(TL.getTypePtr()))
- return getDetail(TT->getDecl());
+ return getDetail(TT->getOriginalDecl());
if (const auto *DT = dyn_cast<DeducedType>(TL.getTypePtr()))
if (DT->isDeduced())
return DT->getDeducedType().getAsString(Ctx.getPrintingPolicy());
@@ -274,18 +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() + "::";
- case NestedNameSpecifier::NamespaceAlias:
- return NNS.getAsNamespaceAlias()->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())
@@ -349,8 +341,10 @@ class DumpVisitor : public RecursiveASTVisitor<DumpVisitor> {
return !D || isInjectedClassName(D) ||
traverseNode("declaration", D, [&] { Base::TraverseDecl(D); });
}
- bool TraverseTypeLoc(TypeLoc TL) {
- return !TL || traverseNode("type", TL, [&] { Base::TraverseTypeLoc(TL); });
+ bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) {
+ return !TL || traverseNode("type", TL, [&] {
+ Base::TraverseTypeLoc(TL, TraverseQualifier);
+ });
}
bool TraverseTemplateName(const TemplateName &TN) {
return traverseNode("template name", TN,
@@ -392,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.
@@ -423,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 91fd3b0f8567b..92ce7a5290751 100644
--- a/clang-tools-extra/clangd/FindTarget.cpp
+++ b/clang-tools-extra/clangd/FindTarget.cpp
@@ -366,19 +366,11 @@ struct TargetFinder {
Visitor(TargetFinder &Outer, RelSet Flags) : Outer(Outer), Flags(Flags) {}
void VisitTagType(const TagType *TT) {
- Outer.add(TT->getAsTagDecl(), Flags);
- }
-
- void VisitElaboratedType(const ElaboratedType *ET) {
- Outer.add(ET->desugar(), Flags);
+ Outer.add(cast<TagType>(TT)->getOriginalDecl(), Flags);
}
void VisitUsingType(const UsingType *ET) {
- Outer.add(ET->getFoundDecl(), Flags);
- }
-
- void VisitInjectedClassNameType(const InjectedClassNameType *ICNT) {
- Outer.add(ICNT->getDecl(), Flags);
+ Outer.add(ET->getDecl(), Flags);
}
void VisitDecltypeType(const DecltypeType *DTT) {
@@ -483,33 +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::NamespaceAlias:
- add(NNS->getAsNamespaceAlias(), 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::Super:
+ add(NNS.getAsSuper(), 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) {
@@ -558,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>())
@@ -864,32 +850,25 @@ 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.getDecl()}});
+ {L.getOriginalDecl()}});
}
void VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc L) {
@@ -909,25 +888,18 @@ 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)});
}
- void VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
- Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
- TL.getNameLoc(),
- /*IsDecl=*/false,
- {TL.getDecl()}});
- }
-
void VisitDependentTemplateSpecializationTypeLoc(
DependentTemplateSpecializationTypeLoc L) {
Refs.push_back(
@@ -946,12 +918,12 @@ refInTypeLoc(TypeLoc L, const HeuristicResolver *Resolver) {
}
void VisitTypedefTypeLoc(TypedefTypeLoc L) {
- if (shouldSkipTypedef(L.getTypedefNameDecl()))
+ if (shouldSkipTypedef(L.getDecl()))
return;
- Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+ Refs.push_back(ReferenceLoc{L.getQualifierLoc(),
L.getNameLoc(),
/*IsDecl=*/false,
- {L.getTypedefNameDecl()}});
+ {L.getDecl()}});
}
void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc L) {
@@ -983,17 +955,6 @@ class ExplicitReferenceCollector
return true;
}
- bool TraverseElaboratedTypeLoc(ElaboratedTypeLoc L) {
- // ElaboratedTypeLoc will reports information for its inner type loc.
- // Otherwise we loose information about inner types loc's qualifier.
- TypeLoc Inner = L.getNamedTypeLoc().getUnqualifiedLoc();
- if (L.getBeginLoc() == Inner.getBeginLoc())
- return RecursiveASTVisitor::TraverseTypeLoc(Inner);
- else
- TypeLocsToSkip.insert(Inner.getBeginLoc());
- return RecursiveASTVisitor::TraverseElaboratedTypeLoc(L);
- }
-
bool VisitStmt(Stmt *S) {
visitNode(DynTypedNode::create(*S));
return true;
@@ -1054,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);
}
@@ -1095,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);
@@ -1213,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/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index e39d8bfcf83f3..f4b312cde6349 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -169,13 +169,14 @@ HoverInfo::PrintedType printType(QualType QT, ASTContext &ASTCtx,
QT = QT->castAs<DecltypeType>()->getUnderlyingType();
HoverInfo::PrintedType Result;
llvm::raw_string_ostream OS(Result.Type);
- // Special case: if the outer type is a tag type without qualifiers, then
- // include the tag for extra clarity.
- // This isn't very idiomatic, so don't attempt it for complex cases, including
- // pointers/references, template specializations, etc.
+ // Special case: if the outer type is a canonical tag type, then include the
+ // tag for extra clarity. This isn't very idiomatic, so don't attempt it for
+ // complex cases, including pointers/references, template specializations,
+ // etc.
if (!QT.isNull() && !QT.hasQualifiers() && PP.SuppressTagKeyword) {
- if (auto *TT = llvm::dyn_cast<TagType>(QT.getTypePtr()))
- OS << TT->getDecl()->getKindName() << " ";
+ if (auto *TT = llvm::dyn_cast<TagType>(QT.getTypePtr());
+ TT && TT->isCanonicalUnqualified())
+ OS << TT->getOriginalDecl()->getKindName() << " ";
}
QT.print(OS, PP);
@@ -451,7 +452,7 @@ std::optional<std::string> printExprValue(const Expr *E,
// Compare to int64_t to avoid bit-width match requirements.
int64_t Val = Constant.Val.getInt().getExtValue();
for (const EnumConstantDecl *ECD :
- T->castAs<EnumType>()->getDecl()->enumerators())
+ T->castAs<EnumType>()->getOriginalDecl()->enumerators())
if (ECD->getInitVal() == Val)
return llvm::formatv("{0} ({1})", ECD->getNameAsString(),
printHex(Constant.Val.getInt()))
@@ -1002,10 +1003,11 @@ void addLayoutInfo(const NamedDecl &ND, HoverInfo &HI) {
const auto &Ctx = ND.getASTContext();
if (auto *RD = llvm::dyn_cast<RecordDecl>(&ND)) {
- if (auto Size = Ctx.getTypeSizeInCharsIfKnown(RD->getTypeForDecl()))
+ CanQualType RT = Ctx.getCanonicalTagType(RD);
+ if (auto Size = Ctx.getTypeSizeInCharsIfKnown(RT))
HI.Size = Size->getQuantity() * 8;
if (!RD->isDependentType() && RD->isCompleteDefinition())
- HI.Align = Ctx.getTypeAlign(RD->getTypeForDecl());
+ HI.Align = Ctx.getTypeAlign(RT);
return;
}
diff --git a/clang-tools-extra/clangd/IncludeFixer.cpp b/clang-tools-extra/clangd/IncludeFixer.cpp
index 4ff021c4c390a..e89318a9500a2 100644
--- a/clang-tools-extra/clangd/IncludeFixer.cpp
+++ b/clang-tools-extra/clangd/IncludeFixer.cpp
@@ -173,7 +173,7 @@ std::vector<Fix> IncludeFixer::fix(DiagnosticsEngine::Level DiagLevel,
// `enum x : int;' is not formally an incomplete type.
// We may need a full definition anyway.
if (auto * ET = llvm::dyn_cast<EnumType>(T))
- if (!ET->getDecl()->getDefinition())
+ if (!ET->getOriginalDecl()->getDefinition())
return fixIncompleteType(*T);
}
}
@@ -400,10 +400,12 @@ 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 auto *NS = Nested->getAsNamespace()) {
+ 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);
@@ -420,13 +422,14 @@ std::optional<CheapUnresolvedName> extractUnresolvedNameCheaply(
} else {
Result.UnresolvedScope = std::move(*Spelling);
}
- } else if (const auto *ANS = Nested->getAsNamespaceAlias()) {
- Result.ResolvedScope = printNamespaceScope(*ANS->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;
+ const auto *ANS = cast<NamespaceAliasDecl>(NSB);
+ Result.ResolvedScope = printNamespaceScope(*ANS->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/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp
index 197c62c40dcf0..cd479e1b7c9bc 100644
--- a/clang-tools-extra/clangd/InlayHints.cpp
+++ b/clang-tools-extra/clangd/InlayHints.cpp
@@ -55,18 +55,24 @@ void stripLeadingUnderscores(StringRef &Name) { Name = Name.ltrim('_'); }
// getDeclForType() returns the decl responsible for Type's spelling.
// This is the inverse of ASTContext::getTypeDeclType().
-template <typename Ty, typename = decltype(((Ty *)nullptr)->getDecl())>
-const NamedDecl *getDeclForTypeImpl(const Ty *T) {
- return T->getDecl();
-}
-const NamedDecl *getDeclForTypeImpl(const void *T) { return nullptr; }
const NamedDecl *getDeclForType(const Type *T) {
switch (T->getTypeClass()) {
-#define ABSTRACT_TYPE(TY, BASE)
-#define TYPE(TY, BASE) \
- case Type::TY: \
- return getDeclForTypeImpl(llvm::cast<TY##Type>(T));
-#include "clang/AST/TypeNodes.inc"
+ case Type::Enum:
+ case Type::Record:
+ case Type::InjectedClassName:
+ return cast<TagType>(T)->getOriginalDecl();
+ case Type::TemplateSpecialization:
+ return cast<TemplateSpecializationType>(T)
+ ->getTemplateName()
+ .getAsTemplateDecl(/*IgnoreDeduced=*/true);
+ case Type::Typedef:
+ return cast<TypedefType>(T)->getDecl();
+ case Type::UnresolvedUsing:
+ return cast<UnresolvedUsingType>(T)->getDecl();
+ case Type::Using:
+ return cast<UsingType>(T)->getDecl();
+ default:
+ return nullptr;
}
llvm_unreachable("Unknown TypeClass enum");
}
@@ -81,8 +87,6 @@ llvm::StringRef getSimpleName(const NamedDecl &D) {
return getSimpleName(D.getDeclName());
}
llvm::StringRef getSimpleName(QualType T) {
- if (const auto *ET = llvm::dyn_cast<ElaboratedType>(T))
- return getSimpleName(ET->getNamedType());
if (const auto *BT = llvm::dyn_cast<BuiltinType>(T)) {
PrintingPolicy PP(LangOptions{});
PP.adjustForCPlusPlus();
diff --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp
index 277cb8769a1b1..06165dfbbcdd2 100644
--- a/clang-tools-extra/clangd/Selection.cpp
+++ b/clang-tools-extra/clangd/Selection.cpp
@@ -62,7 +62,8 @@ void recordMetrics(const SelectionTree &S, const LangOptions &Lang) {
}
// Return the range covering a node and all its children.
-SourceRange getSourceRange(const DynTypedNode &N) {
+SourceRange getSourceRange(const DynTypedNode &N,
+ bool IncludeQualifier = false) {
// MemberExprs to implicitly access anonymous fields should not claim any
// tokens for themselves. Given:
// struct A { struct { int b; }; };
@@ -80,7 +81,7 @@ SourceRange getSourceRange(const DynTypedNode &N) {
? getSourceRange(DynTypedNode::create(*ME->getBase()))
: SourceRange();
}
- return N.getSourceRange();
+ return N.getSourceRange(IncludeQualifier);
}
// An IntervalSet maintains a set of disjoint subranges of an array.
@@ -643,8 +644,9 @@ class SelectionVisitor : public RecursiveASTVisitor<SelectionVisitor> {
}
return traverseNode(X, [&] { return Base::TraverseDecl(X); });
}
- bool TraverseTypeLoc(TypeLoc X) {
- return traverseNode(&X, [&] { return Base::TraverseTypeLoc(X); });
+ bool TraverseTypeLoc(TypeLoc X, bool TraverseQualifier = true) {
+ return traverseNode(
+ &X, [&] { return Base::TraverseTypeLoc(X, TraverseQualifier); });
}
bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &X) {
return traverseNode(&X,
@@ -690,7 +692,8 @@ class SelectionVisitor : public RecursiveASTVisitor<SelectionVisitor> {
// 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 QX) {
+ bool TraverseQualifiedTypeLoc(QualifiedTypeLoc QX,
+ bool TraverseQualifier = true) {
return traverseNode<TypeLoc>(
&QX, [&] { return TraverseTypeLoc(QX.getUnqualifiedLoc()); });
}
@@ -698,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
@@ -798,7 +801,7 @@ class SelectionVisitor : public RecursiveASTVisitor<SelectionVisitor> {
// An optimization for a common case: nodes outside macro expansions that
// don't intersect the selection may be recursively skipped.
bool canSafelySkipNode(const DynTypedNode &N) {
- SourceRange S = getSourceRange(N);
+ SourceRange S = getSourceRange(N, /*IncludeQualifier=*/true);
if (auto *TL = N.get<TypeLoc>()) {
// FIXME: TypeLoc::getBeginLoc()/getEndLoc() are pretty fragile
// heuristics. We should consider only pruning critical TypeLoc nodes, to
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/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp
index 089f8158c9aa5..731ae0fe119d0 100644
--- a/clang-tools-extra/clangd/XRefs.cpp
+++ b/clang-tools-extra/clangd/XRefs.cpp
@@ -1935,7 +1935,8 @@ std::vector<const CXXRecordDecl *> findRecordTypeAt(ParsedAST &AST,
// Return the type most associated with an AST node.
// This isn't precisely defined: we want "go to type" to do something useful.
-static QualType typeForNode(const SelectionTree::Node *N) {
+static QualType typeForNode(const ASTContext &Ctx,
+ const SelectionTree::Node *N) {
// If we're looking at a namespace qualifier, walk up to what it's qualifying.
// (If we're pointing at a *class* inside a NNS, N will be a TypeLoc).
while (N && N->ASTNode.get<NestedNameSpecifierLoc>())
@@ -1969,10 +1970,13 @@ static QualType typeForNode(const SelectionTree::Node *N) {
if (const Decl *D = N->ASTNode.get<Decl>()) {
struct Visitor : ConstDeclVisitor<Visitor, QualType> {
+ const ASTContext &Ctx;
+ Visitor(const ASTContext &Ctx) : Ctx(Ctx) {}
+
QualType VisitValueDecl(const ValueDecl *D) { return D->getType(); }
// Declaration of a type => that type.
QualType VisitTypeDecl(const TypeDecl *D) {
- return QualType(D->getTypeForDecl(), 0);
+ return Ctx.getTypeDeclType(D);
}
// Exception: alias declaration => the underlying type, not the alias.
QualType VisitTypedefNameDecl(const TypedefNameDecl *D) {
@@ -1982,7 +1986,7 @@ static QualType typeForNode(const SelectionTree::Node *N) {
QualType VisitTemplateDecl(const TemplateDecl *D) {
return Visit(D->getTemplatedDecl());
}
- } V;
+ } V(Ctx);
return V.Visit(D);
}
@@ -2126,7 +2130,8 @@ std::vector<LocatedSymbol> findType(ParsedAST &AST, Position Pos,
// unique_ptr<unique_ptr<T>>. Let's *not* remove them, because it gives you some
// information about the type you may have not known before
// (since unique_ptr<unique_ptr<T>> != unique_ptr<T>).
- for (const QualType& Type : unwrapFindType(typeForNode(N), AST.getHeuristicResolver()))
+ for (const QualType &Type : unwrapFindType(
+ typeForNode(AST.getASTContext(), N), AST.getHeuristicResolver()))
llvm::copy(locateSymbolForType(AST, Type, Index),
std::back_inserter(LocatedSymbols));
diff --git a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
index 00c05ebdb5216..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,17 +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 = 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();
}
@@ -231,8 +227,12 @@ findInsertionPoint(const Tweak::Selection &Inputs,
}
bool isNamespaceForbidden(const Tweak::Selection &Inputs,
- const NestedNameSpecifier &Namespace) {
- std::string NamespaceStr = printNamespaceScope(*Namespace.getAsNamespace());
+ NestedNameSpecifier Namespace) {
+ const auto *NS =
+ dyn_cast<NamespaceDecl>(Namespace.getAsNamespaceAndPrefix().Namespace);
+ if (!NS)
+ return true;
+ std::string NamespaceStr = printNamespaceScope(*NS);
for (StringRef Banned : Config::current().Style.FullyQualifiedNamespaces) {
StringRef PrefixMatch = NamespaceStr;
@@ -243,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();
}
@@ -272,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;
}
@@ -303,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
@@ -380,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 cd07cbf73635c..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;
@@ -455,13 +455,12 @@ std::string NewFunction::renderQualifiers() const {
}
std::string NewFunction::renderDeclarationName(FunctionDeclKind K) const {
- if (DefinitionQualifier == nullptr || K != OutOfLineDefinition) {
+ if (!DefinitionQualifier || K != OutOfLineDefinition)
return Name;
- }
std::string QualifierName;
llvm::raw_string_ostream Oss(QualifierName);
- DefinitionQualifier->print(Oss, *LangOpts);
+ DefinitionQualifier.print(Oss, *LangOpts);
return llvm::formatv("{0}{1}", QualifierName, Name);
}
diff --git a/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp b/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
index 43cfc769f7f71..7e616968c6046 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
@@ -116,7 +116,7 @@ bool PopulateSwitch::prepare(const Selection &Sel) {
EnumT = Cond->getType().getCanonicalType()->getAsAdjusted<EnumType>();
if (!EnumT)
return false;
- EnumD = EnumT->getDecl();
+ EnumD = EnumT->getOriginalDecl();
if (!EnumD || EnumD->isDependentType())
return false;
diff --git a/clang-tools-extra/clangd/unittests/ASTTests.cpp b/clang-tools-extra/clangd/unittests/ASTTests.cpp
index d0bc3c4d7db98..76d46bad82224 100644
--- a/clang-tools-extra/clangd/unittests/ASTTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ASTTests.cpp
@@ -421,7 +421,7 @@ TEST(ClangdAST, GetQualification) {
{
R"cpp(
namespace ns1 { namespace ns2 { void Foo(); } }
- void insert(); // ns2::Foo
+ void insert(); // ns1::ns2::Foo
namespace ns1 {
void insert(); // ns2::Foo
namespace ns2 {
@@ -429,7 +429,7 @@ TEST(ClangdAST, GetQualification) {
}
}
)cpp",
- {"ns2::", "ns2::", ""},
+ {"ns1::ns2::", "ns2::", ""},
{"ns1::"},
},
{
@@ -531,7 +531,8 @@ TEST(ClangdAST, PrintType) {
ASSERT_EQ(InsertionPoints.size(), Case.Types.size());
for (size_t I = 0, E = InsertionPoints.size(); I != E; ++I) {
const auto *DC = InsertionPoints[I];
- EXPECT_EQ(printType(AST.getASTContext().getTypeDeclType(TargetDecl), *DC),
+ EXPECT_EQ(printType(AST.getASTContext().getTypeDeclType(TargetDecl), *DC,
+ /*Placeholder=*/"", /*FullyQualify=*/true),
Case.Types[I]);
}
}
diff --git a/clang-tools-extra/clangd/unittests/DumpASTTests.cpp b/clang-tools-extra/clangd/unittests/DumpASTTests.cpp
index cb2c17ad4ef0d..5c857d0b8ae3e 100644
--- a/clang-tools-extra/clangd/unittests/DumpASTTests.cpp
+++ b/clang-tools-extra/clangd/unittests/DumpASTTests.cpp
@@ -72,15 +72,14 @@ declaration: Namespace - root
expression: BinaryOperator - +
expression: ImplicitCast - LValueToRValue
expression: DeclRef - x
- specifier: TypeSpec
+ specifier: Type
type: Record - S
expression: ImplicitCast - LValueToRValue
expression: Member - x
expression: CXXBindTemporary
expression: CXXTemporaryObject - S
- type: Elaborated
+ type: Record - S
specifier: Namespace - root::
- type: Record - S
)"},
{R"cpp(
namespace root {
@@ -104,14 +103,13 @@ declaration: Namespace - root
expression: BinaryOperator - +
expression: ImplicitCast - LValueToRValue
expression: DeclRef - x
- specifier: TypeSpec
+ specifier: Type
type: Record - S
expression: ImplicitCast - LValueToRValue
expression: Member - x
expression: CXXTemporaryObject - S
- type: Elaborated
+ type: Record - S
specifier: Namespace - root::
- type: Record - S
)"},
{R"cpp(
namespace root {
@@ -138,7 +136,7 @@ declaration: Namespace - root
type: Builtin - unsigned int
statement: Return
expression: DependentScopeDeclRef - value
- specifier: TypeSpec
+ specifier: Type
type: TemplateTypeParm - T
)"},
{R"cpp(
@@ -154,8 +152,7 @@ declaration: Var - root
expression: DeclRef - operator+
expression: MaterializeTemporary - lvalue
expression: CXXTemporaryObject - Foo
- type: Elaborated
- type: Record - Foo
+ type: Record - Foo
expression: IntegerLiteral - 42
)"},
{R"cpp(
diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index 602f61d9ecb41..a2593df9c201d 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/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 775278ccf694b..931b1c975d978 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -2893,7 +2893,7 @@ TEST(Hover, All) {
)cpp",
[](HoverInfo &HI) {
HI.Name = "this";
- HI.Definition = "const Foo<T> *";
+ HI.Definition = "const ns::Foo<T> *";
}},
{
R"cpp(// this expr for specialization class
@@ -2909,7 +2909,7 @@ TEST(Hover, All) {
)cpp",
[](HoverInfo &HI) {
HI.Name = "this";
- HI.Definition = "Foo<int> *";
+ HI.Definition = "ns::Foo<int> *";
}},
{
R"cpp(// this expr for partial specialization struct
@@ -2925,7 +2925,7 @@ TEST(Hover, All) {
)cpp",
[](HoverInfo &HI) {
HI.Name = "this";
- HI.Definition = "const Foo<int, F> *";
+ HI.Definition = "const ns::Foo<int, F> *";
}},
{
R"cpp(
@@ -3045,8 +3045,8 @@ TEST(Hover, All) {
HI.Kind = index::SymbolKind::Function;
HI.NamespaceScope = "";
HI.Definition = "MyRect foobar()";
- HI.Type = {"MyRect ()", "MyRect ()"};
- HI.ReturnType = {"MyRect", "MyRect"};
+ HI.Type = {"MyRect ()", "struct MyRect ()"};
+ HI.ReturnType = {"MyRect", "struct MyRect"};
HI.Parameters.emplace();
}},
{R"cpp(
diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
index e0cd955bb1c9a..99e728c40063d 100644
--- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
+++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
@@ -1295,14 +1295,7 @@ TEST(TypeHints, NoQualifiers) {
}
}
)cpp",
- ExpectedHint{": S1", "x"},
- // FIXME: We want to suppress scope specifiers
- // here because we are into the whole
- // brevity thing, but the ElaboratedType
- // printer does not honor the SuppressScope
- // flag by design, so we need to extend the
- // PrintingPolicy to support this use case.
- ExpectedHint{": S2::Inner<int>", "y"});
+ ExpectedHint{": S1", "x"}, ExpectedHint{": Inner<int>", "y"});
}
TEST(TypeHints, Lambda) {
diff --git a/clang-tools-extra/clangd/unittests/QualityTests.cpp b/clang-tools-extra/clangd/unittests/QualityTests.cpp
index 619ea32115357..4954659a45e02 100644
--- a/clang-tools-extra/clangd/unittests/QualityTests.cpp
+++ b/clang-tools-extra/clangd/unittests/QualityTests.cpp
@@ -121,7 +121,9 @@ TEST(QualityTests, SymbolRelevanceSignalExtraction) {
SymbolRelevanceSignals Relevance;
Relevance.merge(CodeCompletionResult(&findDecl(AST, "deprecated"),
- /*Priority=*/42, nullptr, false,
+ /*Priority=*/42,
+ /*Qualifier=*/std::nullopt,
+ /*QualifierIsInformative=*/false,
/*Accessible=*/false));
EXPECT_EQ(Relevance.NameMatch, SymbolRelevanceSignals().NameMatch);
EXPECT_TRUE(Relevance.Forbidden);
@@ -487,13 +489,15 @@ TEST(QualityTests, ItemWithFixItsRankedDown) {
auto AST = Header.build();
SymbolRelevanceSignals RelevanceWithFixIt;
- RelevanceWithFixIt.merge(CodeCompletionResult(&findDecl(AST, "x"), 0, nullptr,
- false, true, {FixItHint{}}));
+ RelevanceWithFixIt.merge(CodeCompletionResult(
+ &findDecl(AST, "x"), /*Priority=*/0, /*Qualifier=*/std::nullopt,
+ /*QualifierIsInformative=*/false, /*Accessible=*/true, {FixItHint{}}));
EXPECT_TRUE(RelevanceWithFixIt.NeedsFixIts);
SymbolRelevanceSignals RelevanceWithoutFixIt;
- RelevanceWithoutFixIt.merge(
- CodeCompletionResult(&findDecl(AST, "x"), 0, nullptr, false, true, {}));
+ RelevanceWithoutFixIt.merge(CodeCompletionResult(
+ &findDecl(AST, "x"), /*Priority=*/0, /*Qualifier=*/std::nullopt,
+ /*QualifierIsInformative=*/false, /*Accessible=*/true, {}));
EXPECT_FALSE(RelevanceWithoutFixIt.NeedsFixIts);
EXPECT_LT(RelevanceWithFixIt.evaluateHeuristics(),
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 baff90faa6eae..6e7be9c414246 100644
--- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
+++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
@@ -60,14 +60,10 @@ class ASTWalker : public RecursiveASTVisitor<ASTWalker> {
NamedDecl *getMemberProvider(QualType Base) {
if (Base->isPointerType())
return getMemberProvider(Base->getPointeeType());
- // Unwrap the sugar ElaboratedType.
- if (const auto *ElTy = dyn_cast<ElaboratedType>(Base))
- return getMemberProvider(ElTy->getNamedType());
-
if (const auto *TT = dyn_cast<TypedefType>(Base))
return TT->getDecl();
if (const auto *UT = dyn_cast<UsingType>(Base))
- return UT->getFoundDecl();
+ return UT->getDecl();
// A heuristic: to resolve a template type to **only** its template name.
// We're only using this method for the base type of MemberExpr, in general
// the template provides the member, and the critical case `unique_ptr<Foo>`
@@ -135,17 +131,14 @@ class ASTWalker : public RecursiveASTVisitor<ASTWalker> {
}
bool qualifierIsNamespaceOrNone(DeclRefExpr *DRE) {
- const auto *Qual = DRE->getQualifier();
- if (!Qual)
- return true;
- switch (Qual->getKind()) {
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::NamespaceAlias:
- case NestedNameSpecifier::Global:
+ NestedNameSpecifier Qual = DRE->getQualifier();
+ switch (Qual.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Namespace:
+ case NestedNameSpecifier::Kind::Global:
return true;
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::Super:
- case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Kind::Type:
+ case NestedNameSpecifier::Kind::Super:
return false;
}
llvm_unreachable("Unknown value for NestedNameSpecifierKind");
@@ -342,17 +335,17 @@ class ASTWalker : public RecursiveASTVisitor<ASTWalker> {
}
bool VisitUsingTypeLoc(UsingTypeLoc TL) {
- reportType(TL.getNameLoc(), TL.getFoundDecl());
+ reportType(TL.getNameLoc(), TL.getDecl());
return true;
}
bool VisitTagTypeLoc(TagTypeLoc TTL) {
- reportType(TTL.getNameLoc(), TTL.getDecl());
+ reportType(TTL.getNameLoc(), TTL.getOriginalDecl());
return true;
}
bool VisitTypedefTypeLoc(TypedefTypeLoc TTL) {
- reportType(TTL.getNameLoc(), TTL.getTypedefNameDecl());
+ reportType(TTL.getNameLoc(), TTL.getDecl());
return true;
}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/copy-constructor-init.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/copy-constructor-init.cpp
index b42d3fcd2b62b..35314d12b59bf 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/copy-constructor-init.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/copy-constructor-init.cpp
@@ -165,7 +165,6 @@ FROMMACRO
class X15 : public CopyableAlias2 {
X15(const X15 &other) {}
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
- // CHECK-FIXES: X15(const X15 &other) : Copyable5(other) {}
};
class X16 : public NonCopyable {
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable.cpp
index 721c55b1fb538..5dd23871b21b3 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable.cpp
@@ -69,14 +69,14 @@ template<typename T>
T qux(T Generic) {
async::Future<Units> PendingA = acquireUnits();
auto PendingB = acquireUnits();
- // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: unused local variable 'PendingB' of type 'a::Future<Units>' (aka 'Future<Units>') [bugprone-unused-local-non-trivial-variable]
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: unused local variable 'PendingB' of type 'a::Future<Units>' (aka 'async::Future<Units>') [bugprone-unused-local-non-trivial-variable]
async::Future<Units> MustBeUsed;
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: unused local variable 'MustBeUsed' of type 'async::Future<Units>' [bugprone-unused-local-non-trivial-variable]
PendingA.get();
async::Future<T> TemplateType;
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unused local variable 'TemplateType' of type 'async::Future<T>' [bugprone-unused-local-non-trivial-variable]
a::Future<T> AliasTemplateType;
- // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: unused local variable 'AliasTemplateType' of type 'a::Future<T>' (aka 'Future<T>') [bugprone-unused-local-non-trivial-variable]
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: unused local variable 'AliasTemplateType' of type 'a::Future<T>' (aka 'async::Future<T>') [bugprone-unused-local-non-trivial-variable]
[[maybe_unused]] async::Future<Units> MaybeUnused;
return Generic;
}
@@ -86,7 +86,7 @@ async::Future<int> Global;
int bar(int Num) {
a::Future<Units> PendingA = acquireUnits();
a::Future<Units> PendingB = acquireUnits(); // not used at all, unused variable not fired because of destructor side effect
- // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unused local variable 'PendingB' of type 'a::Future<Units>' (aka 'Future<Units>') [bugprone-unused-local-non-trivial-variable]
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unused local variable 'PendingB' of type 'a::Future<Units>' (aka 'async::Future<Units>') [bugprone-unused-local-non-trivial-variable]
auto Num2 = PendingA.get();
auto Num3 = qux(Num);
async::Ptr<a::Future<Units>> Shared = async::Ptr<a::Future<Units>>(acquireUnits());
diff --git a/clang-tools-extra/test/clang-tidy/checkers/portability/std-allocator-const.cpp b/clang-tools-extra/test/clang-tidy/checkers/portability/std-allocator-const.cpp
index 732cf5d34aca9..a38594aa94cbb 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/portability/std-allocator-const.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/portability/std-allocator-const.cpp
@@ -43,25 +43,25 @@ template <class T>
class allocator {};
void simple(const std::vector<const char> &v, std::deque<const short> *d) {
- // CHECK-MESSAGES: [[#@LINE-1]]:24: warning: container using std::allocator<const T> is a deprecated libc++ extension; remove const for compatibility with other standard libraries
- // CHECK-MESSAGES: [[#@LINE-2]]:52: warning: container
+ // CHECK-MESSAGES: [[#@LINE-1]]:19: warning: container using std::allocator<const T> is a deprecated libc++ extension; remove const for compatibility with other standard libraries
+ // CHECK-MESSAGES: [[#@LINE-2]]:47: warning: container
std::list<const long> l;
- // CHECK-MESSAGES: [[#@LINE-1]]:8: warning: container
+ // CHECK-MESSAGES: [[#@LINE-1]]:3: warning: container
std::multiset<int *const> ms;
- // CHECK-MESSAGES: [[#@LINE-1]]:8: warning: container
+ // CHECK-MESSAGES: [[#@LINE-1]]:3: warning: container
std::set<const std::hash<int>> s;
- // CHECK-MESSAGES: [[#@LINE-1]]:8: warning: container
+ // CHECK-MESSAGES: [[#@LINE-1]]:3: warning: container
std::unordered_multiset<int *const> ums;
- // CHECK-MESSAGES: [[#@LINE-1]]:8: warning: container
+ // CHECK-MESSAGES: [[#@LINE-1]]:3: warning: container
std::unordered_set<const int> us;
- // CHECK-MESSAGES: [[#@LINE-1]]:8: warning: container
+ // CHECK-MESSAGES: [[#@LINE-1]]:3: warning: container
absl::flat_hash_set<const int> fhs;
- // CHECK-MESSAGES: [[#@LINE-1]]:9: warning: container
+ // CHECK-MESSAGES: [[#@LINE-1]]:3: warning: container
using my_vector = std::vector<const int>;
- // CHECK-MESSAGES: [[#@LINE-1]]:26: warning: container
+ // CHECK-MESSAGES: [[#@LINE-1]]:21: warning: container
my_vector v1;
using my_vector2 = my_vector;
@@ -76,7 +76,7 @@ void simple(const std::vector<const char> &v, std::deque<const short> *d) {
template <class T>
void temp1() {
std::vector<const T> v;
- // CHECK-MESSAGES: [[#@LINE-1]]:8: warning: container
+ // CHECK-MESSAGES: [[#@LINE-1]]:3: warning: container
std::vector<T> neg1;
std::forward_list<const T> neg2;
@@ -87,7 +87,7 @@ template <class T>
void temp2() {
// Match std::vector<const dependent> for the uninstantiated temp2.
std::vector<const T> v;
- // CHECK-MESSAGES: [[#@LINE-1]]:8: warning: container
+ // CHECK-MESSAGES: [[#@LINE-1]]:3: warning: container
std::vector<T> neg1;
std::forward_list<const T> neg2;
More information about the llvm-branch-commits
mailing list