https://github.com/unterumarmung updated https://github.com/llvm/llvm-project/pull/180404
>From 570f2496be1272fa20f3667b0569dbc3fc47af95 Mon Sep 17 00:00:00 2001 From: Daniil Dudkin <[email protected]> Date: Sun, 8 Feb 2026 14:16:43 +0300 Subject: [PATCH] [clang-tidy] Add redundant qualified alias check Introduce `readability-redundant-qualified-alias` to flag identity type aliases that repeat a qualified name and suggest using-declarations when safe. The check is conservative: it skips macros, elaborated keywords, dependent types, and templates, and it suppresses fix-its when comments appear between the alias name and '='. `OnlyNamespaceScope` controls whether local/class scopes are included (default false). --- .../clang-tidy/readability/CMakeLists.txt | 1 + .../readability/ReadabilityTidyModule.cpp | 3 + .../RedundantQualifiedAliasCheck.cpp | 227 ++++++++++++++++++ .../RedundantQualifiedAliasCheck.h | 40 +++ clang-tools-extra/docs/ReleaseNotes.rst | 6 + .../docs/clang-tidy/checks/list.rst | 1 + .../readability/redundant-qualified-alias.rst | 30 +++ .../readability/redundant-qualified-alias.cpp | 203 ++++++++++++++++ 8 files changed, 511 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/readability/RedundantQualifiedAliasCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/readability/RedundantQualifiedAliasCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/readability/redundant-qualified-alias.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/redundant-qualified-alias.cpp diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt index f1f3cde32feff..686e7c19d650b 100644 --- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt @@ -47,6 +47,7 @@ add_clang_library(clangTidyReadabilityModule STATIC RedundantMemberInitCheck.cpp RedundantParenthesesCheck.cpp RedundantPreprocessorCheck.cpp + RedundantQualifiedAliasCheck.cpp RedundantSmartptrGetCheck.cpp RedundantStringCStrCheck.cpp RedundantStringInitCheck.cpp diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp index c582dc98eac6b..8e9e00b23c84a 100644 --- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -49,6 +49,7 @@ #include "RedundantMemberInitCheck.h" #include "RedundantParenthesesCheck.h" #include "RedundantPreprocessorCheck.h" +#include "RedundantQualifiedAliasCheck.h" #include "RedundantSmartptrGetCheck.h" #include "RedundantStringCStrCheck.h" #include "RedundantStringInitCheck.h" @@ -148,6 +149,8 @@ class ReadabilityModule : public ClangTidyModule { "readability-redundant-parentheses"); CheckFactories.registerCheck<RedundantPreprocessorCheck>( "readability-redundant-preprocessor"); + CheckFactories.registerCheck<RedundantQualifiedAliasCheck>( + "readability-redundant-qualified-alias"); CheckFactories.registerCheck<RedundantTypenameCheck>( "readability-redundant-typename"); CheckFactories.registerCheck<ReferenceToConstructedTemporaryCheck>( diff --git a/clang-tools-extra/clang-tidy/readability/RedundantQualifiedAliasCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantQualifiedAliasCheck.cpp new file mode 100644 index 0000000000000..2293bec3b8bf4 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/RedundantQualifiedAliasCheck.cpp @@ -0,0 +1,227 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "RedundantQualifiedAliasCheck.h" +#include "../utils/LexerUtils.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/TypeLoc.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Basic/SourceManager.h" +#include <cassert> +#include <optional> + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +namespace { + +struct TypeLocInfo { + TypeLoc Loc; + bool HasQualifier = false; +}; + +} // namespace + +static bool hasMacroInRange(SourceRange Range, const SourceManager &SM, + const LangOptions &LangOpts) { + if (Range.isInvalid()) + return true; + return utils::lexer::rangeContainsExpansionsOrDirectives(Range, SM, LangOpts); +} + +static std::optional<TypeLocInfo> getTypeLocInfo(TypeLoc TL) { + if (TL.isNull()) + return std::nullopt; + + const auto MakeTypeLocInfo = [](auto TypeTL) { + const bool HasQualifier = + static_cast<bool>(TypeTL.getQualifierLoc().getNestedNameSpecifier()); + return TypeLocInfo{TypeTL, HasQualifier}; + }; + + if (const auto TypedefTL = TL.getAs<TypedefTypeLoc>()) + return MakeTypeLocInfo(TypedefTL); + + if (const auto TagTL = TL.getAs<TagTypeLoc>()) + return MakeTypeLocInfo(TagTL); + + return std::nullopt; +} + +static const NamedDecl *getNamedDeclFromTypeLoc(TypeLoc TL) { + if (const auto TypedefTL = TL.getAs<TypedefTypeLoc>()) + return TypedefTL.getDecl(); + if (const auto TagTL = TL.getAs<TagTypeLoc>()) + return TagTL.getDecl(); + return nullptr; +} + +static bool hasSameUnqualifiedName(const NamedDecl *LHS, const NamedDecl *RHS) { + return LHS->getName() == RHS->getName(); +} + +static bool isNamespaceLikeDeclContext(const DeclContext *DC) { + return isa<TranslationUnitDecl, NamespaceDecl>(DC); +} + +static bool canUseUsingDeclarationForTarget(const TypeAliasDecl *Alias, + const NamedDecl *Target) { + const DeclContext *AliasContext = Alias->getDeclContext()->getRedeclContext(); + const DeclContext *TargetContext = + Target->getDeclContext()->getRedeclContext(); + + const auto *AliasRecord = dyn_cast<CXXRecordDecl>(AliasContext); + if (!AliasRecord) + return isNamespaceLikeDeclContext(TargetContext); + + const auto *TargetRecord = dyn_cast<CXXRecordDecl>(TargetContext); + return TargetRecord && AliasRecord->isDerivedFrom(TargetRecord); +} + +static bool hasTrailingSyntaxAfterRhsType(TypeLoc TL, const SourceManager &SM, + const LangOptions &LangOpts) { + const SourceLocation TypeEndLoc = TL.getEndLoc(); + if (TypeEndLoc.isInvalid() || TypeEndLoc.isMacroID()) + return true; + const std::optional<Token> NextToken = + utils::lexer::findNextTokenSkippingComments(TypeEndLoc, SM, LangOpts); + return !NextToken || NextToken->isNot(tok::semi); +} + +namespace { + +AST_MATCHER(TypeAliasDecl, isAliasTemplate) { + return Node.getDescribedAliasTemplate() != nullptr; +} + +AST_MATCHER(NamedDecl, isInMacro) { return Node.getLocation().isMacroID(); } + +AST_MATCHER(TypeAliasDecl, hasAliasAttributes) { + if (Node.hasAttrs()) + return true; + const TypeSourceInfo *TSI = Node.getTypeSourceInfo(); + if (!TSI) + return false; + for (TypeLoc CurTL = TSI->getTypeLoc(); !CurTL.isNull(); + CurTL = CurTL.getNextTypeLoc()) + if (CurTL.getAs<AttributedTypeLoc>()) + return true; + return false; +} + +AST_MATCHER(TypeLoc, isNonDependentTypeLoc) { + return !Node.getType().isNull() && !Node.getType()->isDependentType(); +} + +AST_MATCHER(TypeLoc, isNonElaboratedNominalTypeLoc) { + const auto IsNonElaboratedTypeLoc = [](auto TL) { + return !TL.isNull() && !TL.getElaboratedKeywordLoc().isValid(); + }; + return IsNonElaboratedTypeLoc(Node.getAs<TypedefTypeLoc>()) || + IsNonElaboratedTypeLoc(Node.getAs<TagTypeLoc>()); +} + +AST_MATCHER(TypeLoc, isMacroFreeTypeLoc) { + const ASTContext &Context = Finder->getASTContext(); + return !hasMacroInRange(Node.getSourceRange(), Context.getSourceManager(), + Context.getLangOpts()); +} + +AST_MATCHER(TypeLoc, hasNoTrailingSyntaxAfterTypeLoc) { + const ASTContext &Context = Finder->getASTContext(); + return !hasTrailingSyntaxAfterRhsType(Node, Context.getSourceManager(), + Context.getLangOpts()); +} + +AST_MATCHER(TypeAliasDecl, hasUsingDeclarationEquivalentTarget) { + const TypeSourceInfo *TSI = Node.getTypeSourceInfo(); + if (!TSI) + return false; + const std::optional<TypeLocInfo> TypeInfo = getTypeLocInfo(TSI->getTypeLoc()); + if (!TypeInfo || !TypeInfo->HasQualifier) + return false; + const NamedDecl *Target = getNamedDeclFromTypeLoc(TypeInfo->Loc); + return Target && hasSameUnqualifiedName(&Node, Target) && + canUseUsingDeclarationForTarget(&Node, Target); +} + +} // namespace + +RedundantQualifiedAliasCheck::RedundantQualifiedAliasCheck( + StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + OnlyNamespaceScope(Options.get("OnlyNamespaceScope", false)) {} + +void RedundantQualifiedAliasCheck::storeOptions( + ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "OnlyNamespaceScope", OnlyNamespaceScope); +} + +void RedundantQualifiedAliasCheck::registerMatchers(MatchFinder *Finder) { + const auto ControlFlowInitStatementMatcher = stmt( + anyOf(mapAnyOf(ifStmt, switchStmt, cxxForRangeStmt) + .with(hasInitStatement(stmt(equalsBoundNode("initDeclStmt")))), + forStmt(hasLoopInit(stmt(equalsBoundNode("initDeclStmt")))))); + + const auto AliasPreconditions = + allOf(unless(isInMacro()), unless(isAliasTemplate()), + unless(hasAliasAttributes())); + const auto InControlFlowInit = + allOf(hasParent(declStmt().bind("initDeclStmt")), + hasAncestor(ControlFlowInitStatementMatcher)); + const auto RewriteableTypeLoc = + typeLoc(allOf(isNonDependentTypeLoc(), isNonElaboratedNominalTypeLoc(), + isMacroFreeTypeLoc(), hasNoTrailingSyntaxAfterTypeLoc())) + .bind("loc"); + + const auto RedundantQualifiedAliasMatcher = typeAliasDecl( + AliasPreconditions, unless(InControlFlowInit), + hasUsingDeclarationEquivalentTarget(), hasTypeLoc(RewriteableTypeLoc)); + + if (OnlyNamespaceScope) { + Finder->addMatcher(typeAliasDecl(RedundantQualifiedAliasMatcher, + hasDeclContext(anyOf(translationUnitDecl(), + namespaceDecl()))) + .bind("alias"), + this); + return; + } + Finder->addMatcher(RedundantQualifiedAliasMatcher.bind("alias"), this); +} + +void RedundantQualifiedAliasCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *Alias = Result.Nodes.getNodeAs<TypeAliasDecl>("alias"); + assert(Alias && "matcher must bind alias"); + const auto *WrittenTLNode = Result.Nodes.getNodeAs<TypeLoc>("loc"); + assert(WrittenTLNode && "matcher must bind loc"); + const TypeLoc WrittenTL = *WrittenTLNode; + + const SourceManager &SM = *Result.SourceManager; + const LangOptions &LangOpts = getLangOpts(); + + const SourceLocation AliasLoc = Alias->getLocation(); + const SourceLocation RhsBeginLoc = WrittenTL.getBeginLoc(); + const CharSourceRange EqualRange = utils::lexer::findTokenTextInRange( + CharSourceRange::getCharRange(AliasLoc, RhsBeginLoc), SM, LangOpts, + [](const Token &Tok) { return Tok.is(tok::equal); }); + if (EqualRange.isInvalid()) + return; + + auto Diag = diag(Alias->getLocation(), + "type alias is redundant; use a using-declaration instead"); + + Diag << FixItHint::CreateRemoval(Alias->getLocation()) + << FixItHint::CreateRemoval(EqualRange.getBegin()); +} + +} // namespace clang::tidy::readability diff --git a/clang-tools-extra/clang-tidy/readability/RedundantQualifiedAliasCheck.h b/clang-tools-extra/clang-tidy/readability/RedundantQualifiedAliasCheck.h new file mode 100644 index 0000000000000..4290f36c70952 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/RedundantQualifiedAliasCheck.h @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTQUALIFIEDALIASCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTQUALIFIEDALIASCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::readability { + +/// Finds identity type aliases to qualified names that can be expressed as +/// using-declarations. +/// +/// For the user-facing documentation see: +/// https://clang.llvm.org/extra/clang-tidy/checks/readability/redundant-qualified-alias.html +class RedundantQualifiedAliasCheck : public ClangTidyCheck { +public: + RedundantQualifiedAliasCheck(StringRef Name, ClangTidyContext *Context); + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus11; + } + std::optional<TraversalKind> getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + const bool OnlyNamespaceScope; +}; + +} // namespace clang::tidy::readability + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTQUALIFIEDALIASCHECK_H diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index b0b4cd646c3bd..99afb578f3c00 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -148,6 +148,12 @@ New checks Suggests insertion of ``std::move(...)`` to turn copy assignment operator calls into move assignment ones, when deemed valid and profitable. +- New :doc:`readability-redundant-qualified-alias + <clang-tidy/checks/readability/redundant-qualified-alias>` check. + + Finds redundant identity type aliases that re-expose a qualified name and can + be replaced with a ``using`` declaration. + - New :doc:`readability-trailing-comma <clang-tidy/checks/readability/trailing-comma>` check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 068431fb5c94c..c4af0d4ae7193 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -416,6 +416,7 @@ Clang-Tidy Checks :doc:`readability-redundant-member-init <readability/redundant-member-init>`, "Yes" :doc:`readability-redundant-parentheses <readability/redundant-parentheses>`, "Yes" :doc:`readability-redundant-preprocessor <readability/redundant-preprocessor>`, + :doc:`readability-redundant-qualified-alias <readability/redundant-qualified-alias>`, "Yes" :doc:`readability-redundant-smartptr-get <readability/redundant-smartptr-get>`, "Yes" :doc:`readability-redundant-string-cstr <readability/redundant-string-cstr>`, "Yes" :doc:`readability-redundant-string-init <readability/redundant-string-init>`, "Yes" diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-qualified-alias.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-qualified-alias.rst new file mode 100644 index 0000000000000..b1af171ae5093 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-qualified-alias.rst @@ -0,0 +1,30 @@ +.. title:: clang-tidy - readability-redundant-qualified-alias + +readability-redundant-qualified-alias +===================================== + +Finds redundant identity type aliases that re-expose a qualified name and can +be replaced with a ``using`` declaration. + +.. code-block:: c++ + + using seconds = std::chrono::seconds; + + // becomes + + using std::chrono::seconds; + +The check is conservative and only warns when the alias name exactly matches +the unqualified name of a non-dependent, non-specialized named type written +with a qualifier. It skips alias templates, dependent forms, elaborated +keywords (``class``, ``struct``, ``enum``, ``typename``), and cases involving +macros. + +Options +------- + +.. option:: OnlyNamespaceScope + + When `true`, only consider aliases declared in a namespace or the + translation unit. When `false`, also consider aliases declared inside + classes, functions, and lambdas. Default is `false`. diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-qualified-alias.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-qualified-alias.cpp new file mode 100644 index 0000000000000..28d4bda079488 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-qualified-alias.cpp @@ -0,0 +1,203 @@ +// RUN: %check_clang_tidy -std=c++11-or-later %s readability-redundant-qualified-alias %t +// RUN: %check_clang_tidy -check-suffix=NS -std=c++11-or-later %s readability-redundant-qualified-alias %t -- \ +// RUN: -config='{CheckOptions: { readability-redundant-qualified-alias.OnlyNamespaceScope: true }}' +// RUN: %check_clang_tidy -check-suffixes=,CXX23 -std=c++23-or-later %s readability-redundant-qualified-alias %t +// RUN: %check_clang_tidy -check-suffixes=NS,NS-CXX23 -std=c++23-or-later %s readability-redundant-qualified-alias %t -- \ +// RUN: -config='{CheckOptions: { readability-redundant-qualified-alias.OnlyNamespaceScope: true }}' + +namespace n1 { +struct Foo {}; +struct Bar {}; +struct Attr {}; +enum PlainEnum { V0 }; +enum class ScopedEnum { V1 }; +struct Commented {}; +struct AfterType {}; +struct Elab {}; +struct MacroEq {}; +struct MacroType {}; +struct PtrType {}; +struct LocalType {}; +} // namespace n1 + +namespace n2 { +namespace n3 { +struct Deep {}; +} // namespace n3 +} // namespace n2 + +namespace td { +typedef n1::Foo TypedefFoo; +} // namespace td + +struct GlobalType {}; +struct Outer { + struct Inner {}; +}; + +using Foo = n1::Foo; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-MESSAGES-NS: :[[@LINE-2]]:7: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-FIXES: using n1::Foo; + +using Bar = ::n1::Bar; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-MESSAGES-NS: :[[@LINE-2]]:7: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-FIXES: using ::n1::Bar; + +using Attr = n1::Attr __attribute__((aligned(8))); +// CHECK-MESSAGES-NOT: warning: type alias is redundant; use a using-declaration instead +// CHECK-MESSAGES-NS-NOT: warning: type alias is redundant; use a using-declaration instead + +namespace alias_attr { +using Foo [[deprecated("alias attr")]] = n1::Foo; +// CHECK-MESSAGES-NOT: warning: type alias is redundant; use a using-declaration instead +// CHECK-MESSAGES-NS-NOT: warning: type alias is redundant; use a using-declaration instead +} // namespace alias_attr + +using Deep = n2::n3::Deep; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-MESSAGES-NS: :[[@LINE-2]]:7: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-FIXES: using n2::n3::Deep; + +using TypedefFoo = td::TypedefFoo; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-MESSAGES-NS: :[[@LINE-2]]:7: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-FIXES: using td::TypedefFoo; + +using GlobalType = ::GlobalType; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-MESSAGES-NS: :[[@LINE-2]]:7: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-FIXES: using ::GlobalType; + +using PlainEnum = n1::PlainEnum; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-MESSAGES-NS: :[[@LINE-2]]:7: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-FIXES: using n1::PlainEnum; + +using ScopedEnum = n1::ScopedEnum; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-MESSAGES-NS: :[[@LINE-2]]:7: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-FIXES: using n1::ScopedEnum; + +using Inner = Outer::Inner; +// CHECK-MESSAGES-NOT: warning: type alias is redundant; use a using-declaration instead +// CHECK-MESSAGES-NS-NOT: warning: type alias is redundant; use a using-declaration instead + +using Builtin = int; +// CHECK-MESSAGES-NOT: warning: type alias is redundant; use a using-declaration instead +// CHECK-MESSAGES-NS-NOT: warning: type alias is redundant; use a using-declaration instead + +using PtrType = n1::PtrType *; +// CHECK-MESSAGES-NOT: warning: type alias is redundant; use a using-declaration instead +// CHECK-MESSAGES-NS-NOT: warning: type alias is redundant; use a using-declaration instead + +namespace templ { +template <typename T> +struct Vec {}; +} // namespace templ + +using Vec = templ::Vec<int>; +// CHECK-MESSAGES-NOT: warning: type alias is redundant; use a using-declaration instead +// CHECK-MESSAGES-NS-NOT: warning: type alias is redundant; use a using-declaration instead + +namespace templ_alias { +template <typename T> +using Foo = n1::Foo; +// CHECK-MESSAGES-NOT: warning: type alias is redundant; use a using-declaration instead +// CHECK-MESSAGES-NS-NOT: warning: type alias is redundant; use a using-declaration instead +} // namespace templ_alias + +template <typename T> +struct Dependent { + using X = typename T::X; + // CHECK-MESSAGES-NOT: warning: type alias is redundant; use a using-declaration instead + // CHECK-MESSAGES-NS-NOT: warning: type alias is redundant; use a using-declaration instead +}; + +using Elab = class n1::Elab; +// CHECK-MESSAGES-NOT: warning: type alias is redundant; use a using-declaration instead +// CHECK-MESSAGES-NS-NOT: warning: type alias is redundant; use a using-declaration instead + +using Commented /*comment*/ = n1::Commented; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-MESSAGES-NS: :[[@LINE-2]]:7: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-FIXES: using{{[ ]+}}/*comment*/{{[ ]+}}n1::Commented; + +using AfterType = n1::AfterType /*rhs-comment*/; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-MESSAGES-NS: :[[@LINE-2]]:7: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-FIXES: using n1::AfterType /*rhs-comment*/; + +#define DECL_END ; +using MacroDeclEnd = n1::MacroType DECL_END +// CHECK-MESSAGES-NOT: warning: type alias is redundant; use a using-declaration instead +// CHECK-MESSAGES-NS-NOT: warning: type alias is redundant; use a using-declaration instead + +#define ALIAS MacroType +using ALIAS = n1::MacroType; +// CHECK-MESSAGES-NOT: warning: type alias is redundant; use a using-declaration instead +// CHECK-MESSAGES-NS-NOT: warning: type alias is redundant; use a using-declaration instead + +#define RHS n1::MacroType +using MacroType = RHS; +// CHECK-MESSAGES-NOT: warning: type alias is redundant; use a using-declaration instead +// CHECK-MESSAGES-NS-NOT: warning: type alias is redundant; use a using-declaration instead + +#define EQ = +using MacroEq EQ n1::MacroEq; +// CHECK-MESSAGES-NOT: warning: type alias is redundant; use a using-declaration instead +// CHECK-MESSAGES-NS-NOT: warning: type alias is redundant; use a using-declaration instead + +struct Base { + using T = n1::Foo; +}; + +struct Derived : Base { + using T = Base::T; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] + // CHECK-MESSAGES-NS-NOT: warning: type alias is redundant; use a using-declaration instead + // CHECK-FIXES: using Base::T; +}; + +struct ClassScopeNamespaceAlias { + using Foo = n1::Foo; + // CHECK-MESSAGES-NOT: warning: type alias is redundant; use a using-declaration instead + // CHECK-MESSAGES-NS-NOT: warning: type alias is redundant; use a using-declaration instead +}; + +void local_scope() { + using LocalType = n1::LocalType; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] + // CHECK-MESSAGES-NS-NOT: warning: type alias is redundant; use a using-declaration instead + // CHECK-FIXES: using n1::LocalType; +} + +#if __cplusplus >= 202302L +void cxx23_init_statement_scope(bool Cond) { + if (using Foo = n1::Foo; Cond) { + } + // CHECK-MESSAGES-CXX23-NOT: warning: type alias is redundant; use a using-declaration instead + // CHECK-MESSAGES-NS-CXX23-NOT: warning: type alias is redundant; use a using-declaration instead + + switch (using Bar = ::n1::Bar; 0) { + default: + break; + } + // CHECK-MESSAGES-CXX23-NOT: warning: type alias is redundant; use a using-declaration instead + // CHECK-MESSAGES-NS-CXX23-NOT: warning: type alias is redundant; use a using-declaration instead + + for (using Deep = n2::n3::Deep; Cond;) { + Cond = false; + } + // CHECK-MESSAGES-CXX23-NOT: warning: type alias is redundant; use a using-declaration instead + // CHECK-MESSAGES-NS-CXX23-NOT: warning: type alias is redundant; use a using-declaration instead + + int Values[] = {0}; + for (using GlobalType = ::GlobalType; int V : Values) { + (void)V; + } + // CHECK-MESSAGES-CXX23-NOT: warning: type alias is redundant; use a using-declaration instead + // CHECK-MESSAGES-NS-CXX23-NOT: warning: type alias is redundant; use a using-declaration instead +} +#endif // __cplusplus >= 202302L _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
