https://github.com/unterumarmung updated https://github.com/llvm/llvm-project/pull/180404
>From 4f449c728d6b8b298f001a868428a8ae847158fb Mon Sep 17 00:00:00 2001 From: Daniil Dudkin <[email protected]> Date: Sun, 8 Feb 2026 14:16:43 +0300 Subject: [PATCH 1/5] [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 | 256 ++++++++++++++++++ .../RedundantQualifiedAliasCheck.h | 37 +++ clang-tools-extra/docs/ReleaseNotes.rst | 6 + .../docs/clang-tidy/checks/list.rst | 1 + .../readability/redundant-qualified-alias.rst | 29 ++ .../readability/redundant-qualified-alias.cpp | 122 +++++++++ 8 files changed, 455 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..c6f59cf0e0306 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/RedundantQualifiedAliasCheck.cpp @@ -0,0 +1,256 @@ +//===----------------------------------------------------------------------===// +// +// 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/Decl.h" +#include "clang/AST/TypeLoc.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Lex/Lexer.h" +#include <optional> + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +namespace { + +struct NominalTypeLocInfo { + TypeLoc Loc; + bool HasQualifier = false; +}; + +struct EqualTokenInfo { + SourceLocation AfterEqualLoc; + bool SawComment = false; +}; + +} // namespace + +static bool isInNamespaceOrTU(const Decl *D) { + const DeclContext *DC = D->getDeclContext(); + return DC && (DC->isTranslationUnit() || isa<NamespaceDecl>(DC)); +} + +static bool isAliasTemplate(const TypeAliasDecl *Alias) { + return Alias->getDescribedAliasTemplate() != nullptr; +} + +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<NominalTypeLocInfo> peelToNominalTypeLoc(TypeLoc TL) { + while (!TL.isNull()) { + if (const auto ParenTL = TL.getAs<ParenTypeLoc>()) { + TL = ParenTL.getInnerLoc(); + continue; + } + if (const auto AttrTL = TL.getAs<AttributedTypeLoc>()) { + // Preserve any attributes by rewriting only the alias name and '='. + TL = AttrTL.getModifiedLoc(); + continue; + } + + if (const auto TypedefTL = TL.getAs<TypedefTypeLoc>()) { + // Avoid rewriting aliases that use an elaborated keyword + // (class/struct/enum). + if (TypedefTL.getElaboratedKeywordLoc().isValid()) + return std::nullopt; + const bool HasQualifier = static_cast<bool>( + TypedefTL.getQualifierLoc().getNestedNameSpecifier()); + return NominalTypeLocInfo{TypedefTL, HasQualifier}; + } + + if (const auto TagTL = TL.getAs<TagTypeLoc>()) { + // Avoid rewriting aliases that use an elaborated keyword + // (class/struct/enum). + if (TagTL.getElaboratedKeywordLoc().isValid()) + return std::nullopt; + const bool HasQualifier = + static_cast<bool>(TagTL.getQualifierLoc().getNestedNameSpecifier()); + return NominalTypeLocInfo{TagTL, HasQualifier}; + } + + return std::nullopt; + } + return std::nullopt; +} + +static const NamedDecl *getNamedDeclFromNominalTypeLoc(TypeLoc TL) { + if (const auto TypedefTL = TL.getAs<TypedefTypeLoc>()) + return TypedefTL.getTypePtr()->getDecl(); + if (const auto TagTL = TL.getAs<TagTypeLoc>()) + return TagTL.getDecl(); + return nullptr; +} + +static bool hasSameUnqualifiedName(const TypeAliasDecl *Alias, + const NamedDecl *Target) { + return Alias->getName() == Target->getName(); +} + +static std::optional<EqualTokenInfo> +findEqualTokenAfter(SourceLocation StartLoc, SourceLocation LimitLoc, + const SourceManager &SM, const LangOptions &LangOpts) { + if (StartLoc.isInvalid() || LimitLoc.isInvalid()) + return std::nullopt; + if (StartLoc.isMacroID() || LimitLoc.isMacroID()) + return std::nullopt; + if (!SM.isBeforeInTranslationUnit(StartLoc, LimitLoc)) + return std::nullopt; + + const SourceLocation SpellingStart = SM.getSpellingLoc(StartLoc); + const SourceLocation SpellingLimit = SM.getSpellingLoc(LimitLoc); + const FileID File = SM.getFileID(SpellingStart); + if (File != SM.getFileID(SpellingLimit)) + return std::nullopt; + + const StringRef Buf = SM.getBufferData(File); + const char *StartChar = SM.getCharacterData(SpellingStart); + Lexer Lex(SpellingStart, LangOpts, StartChar, StartChar, Buf.end()); + Lex.SetCommentRetentionState(true); + + Token Tok; + bool SawComment = false; + do { + Lex.LexFromRawLexer(Tok); + if (Tok.is(tok::comment)) + SawComment = true; + if (Tok.is(tok::equal)) { + Token NextTok; + Lex.LexFromRawLexer(NextTok); + // Return the location *after* '=' so removal is token-preserving. + return EqualTokenInfo{NextTok.getLocation(), SawComment}; + } + } while (Tok.isNot(tok::eof) && Tok.getLocation() < SpellingLimit); + + return std::nullopt; +} + +static std::optional<FixItHint> buildRemovalFixItAfterEqual( + const TypeAliasDecl *Alias, SourceLocation AfterEqualLoc, + const SourceManager &SM, const LangOptions &LangOpts) { + SourceLocation AliasLoc = Alias->getLocation(); + if (AliasLoc.isInvalid() || AfterEqualLoc.isInvalid()) + return std::nullopt; + if (AliasLoc.isMacroID() || AfterEqualLoc.isMacroID()) + return std::nullopt; + + AliasLoc = Lexer::GetBeginningOfToken(AliasLoc, SM, LangOpts); + if (AliasLoc.isInvalid()) + return std::nullopt; + + const CharSourceRange RemovalRange = Lexer::makeFileCharRange( + CharSourceRange::getCharRange(AliasLoc, AfterEqualLoc), SM, LangOpts); + if (RemovalRange.isInvalid()) + return std::nullopt; + + if (hasMacroInRange(RemovalRange.getAsRange(), SM, LangOpts)) + // Avoid rewriting tokens that come from macro expansions. + return std::nullopt; + + return FixItHint::CreateRemoval(RemovalRange); +} + +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) { + Finder->addMatcher(typeAliasDecl().bind("alias"), this); +} + +void RedundantQualifiedAliasCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *Alias = Result.Nodes.getNodeAs<TypeAliasDecl>("alias"); + if (!Alias) + return; + + if (OnlyNamespaceScope && !isInNamespaceOrTU(Alias)) + return; + + if (isAliasTemplate(Alias)) + return; + + if (Alias->getLocation().isInvalid() || Alias->getLocation().isMacroID()) + return; + + const TypeSourceInfo *TSI = Alias->getTypeSourceInfo(); + if (!TSI) + return; + + const TypeLoc WrittenTL = TSI->getTypeLoc(); + if (WrittenTL.isNull()) + return; + + if (WrittenTL.getType()->isDependentType()) + return; + + const SourceManager &SM = *Result.SourceManager; + const LangOptions &LangOpts = getLangOpts(); + if (hasMacroInRange(WrittenTL.getSourceRange(), SM, LangOpts)) + return; + + const std::optional<NominalTypeLocInfo> NominalInfo = + peelToNominalTypeLoc(WrittenTL); + if (!NominalInfo) + return; + + if (!NominalInfo->HasQualifier) + // Unqualified RHS would not gain anything from a using-declaration. + return; + + const TypeLoc NominalTL = NominalInfo->Loc; + const NamedDecl *Target = getNamedDeclFromNominalTypeLoc(NominalTL); + if (!Target) + return; + + if (!hasSameUnqualifiedName(Alias, Target)) + return; + + const SourceLocation AliasLoc = Alias->getLocation(); + const SourceLocation RhsBeginLoc = WrittenTL.getBeginLoc(); + const CharSourceRange AliasToRhsRange = Lexer::makeFileCharRange( + CharSourceRange::getCharRange(AliasLoc, RhsBeginLoc), SM, LangOpts); + if (AliasToRhsRange.isInvalid()) + return; + if (hasMacroInRange(AliasToRhsRange.getAsRange(), SM, LangOpts)) + return; + + std::optional<EqualTokenInfo> EqualInfo = + findEqualTokenAfter(AliasLoc, RhsBeginLoc, SM, LangOpts); + if (!EqualInfo || EqualInfo->AfterEqualLoc.isInvalid()) + return; + + auto Diag = diag(Alias->getLocation(), + "type alias is redundant; use a using-declaration instead"); + + if (EqualInfo->SawComment) { + // Suppress fix-it: avoid deleting comments between alias name and '='. + return; + } + + if (const std::optional<FixItHint> Fix = buildRemovalFixItAfterEqual( + Alias, EqualInfo->AfterEqualLoc, SM, LangOpts)) { + Diag << *Fix; + } +} + +} // 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..201ce73f3594a --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/RedundantQualifiedAliasCheck.h @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// 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; // C++11 or later. + } + 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 5c0060877a67f..9d99fb972606c 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -133,6 +133,12 @@ New checks Finds and removes redundant conversions from ``std::[w|u8|u16|u32]string_view`` to ``std::[...]string`` in call expressions expecting ``std::[...]string_view``. +- New :doc:`readability-redundant-qualified-alias + <clang-tidy/checks/readability/redundant-qualified-alias>` check. + + Finds redundant identity type aliases of the form ``using X = ns::X;`` and + suggests rewriting them as using-declarations when safe. + - 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 0eabd9929dc39..75bc868cf0066 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -414,6 +414,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..37b2551c70a3d --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-qualified-alias.rst @@ -0,0 +1,29 @@ +.. title:: clang-tidy - readability-redundant-qualified-alias + +readability-redundant-qualified-alias +===================================== + +Finds redundant identity type aliases that simply re-expose a qualified name +and can be replaced with a using-declaration. + +.. code-block:: c++ + + using CommentToken = clang::tidy::utils::lexer::CommentToken; + + // becomes + + using clang::tidy::utils::lexer::CommentToken; + +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 or comments between the alias name and ``=``. + +Options +------- + +.. option:: OnlyNamespaceScope + + When false (default), consider aliases declared in any scope. When true, + only consider aliases declared in a namespace or the translation unit. 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..ef5f391934eb2 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-qualified-alias.cpp @@ -0,0 +1,122 @@ +// 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 }}' + +namespace n1 { +struct Foo {}; +struct Bar {}; +struct Attr {}; +struct Commented {}; +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 {}; + +using Foo = n1::Foo; +// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-MESSAGES-NS: :[[@LINE-2]]:{{[0-9]+}}: 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]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-MESSAGES-NS: :[[@LINE-2]]:{{[0-9]+}}: 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: :[[@LINE-1]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-MESSAGES-NS: :[[@LINE-2]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-FIXES: using n1::Attr __attribute__((aligned(8))); + +using Deep = n2::n3::Deep; +// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-MESSAGES-NS: :[[@LINE-2]]:{{[0-9]+}}: 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]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-MESSAGES-NS: :[[@LINE-2]]:{{[0-9]+}}: 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]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-MESSAGES-NS: :[[@LINE-2]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-FIXES: using ::GlobalType; + +using Builtin = int; +// CHECK-FIXES: using Builtin = int; + +using PtrType = n1::PtrType *; +// CHECK-FIXES: using PtrType = n1::PtrType *; + +namespace templ { +template <typename T> +struct Vec {}; +} // namespace templ + +using Vec = templ::Vec<int>; +// CHECK-FIXES: using Vec = templ::Vec<int>; + +namespace templ_alias { +template <typename T> +using Foo = n1::Foo; +} // namespace templ_alias + +template <typename T> +struct Dependent { + using X = typename T::X; +}; + +using Elab = class n1::Elab; +// CHECK-FIXES: using Elab = class n1::Elab; + +using Commented /*comment*/ = n1::Commented; +// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-MESSAGES-NS: :[[@LINE-2]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// CHECK-FIXES: using Commented /*comment*/ = n1::Commented; + +#define ALIAS MacroType +using ALIAS = n1::MacroType; +// CHECK-FIXES: #define ALIAS MacroType +// CHECK-FIXES: using ALIAS = n1::MacroType; + +#define RHS n1::MacroType +using MacroType = RHS; +// CHECK-FIXES: #define RHS n1::MacroType +// CHECK-FIXES: using MacroType = RHS; + +#define EQ = +using MacroEq EQ n1::MacroEq; +// CHECK-FIXES: #define EQ = +// CHECK-FIXES: using MacroEq EQ n1::MacroEq; + +struct Base { + using T = n1::Foo; +}; + +struct Derived : Base { + using T = Base::T; + // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] + // CHECK-FIXES: using Base::T; + // CHECK-FIXES-NS: using T = Base::T; +}; + +void local_scope() { + using LocalType = n1::LocalType; + // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] + // CHECK-FIXES: using n1::LocalType; + // CHECK-FIXES-NS: using LocalType = n1::LocalType; +} >From eba18f6c72a93e450453bc8f6ae23693467e7689 Mon Sep 17 00:00:00 2001 From: Daniil Dudkin <[email protected]> Date: Sun, 8 Feb 2026 17:52:11 +0300 Subject: [PATCH 2/5] Fix review comments --- .../readability/redundant-qualified-alias.cpp | 63 +++++++++++-------- 1 file changed, 36 insertions(+), 27 deletions(-) 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 index ef5f391934eb2..32931c7d6191b 100644 --- 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 @@ -27,40 +27,42 @@ typedef n1::Foo TypedefFoo; struct GlobalType {}; using Foo = n1::Foo; -// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] -// CHECK-MESSAGES-NS: :[[@LINE-2]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// 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]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] -// CHECK-MESSAGES-NS: :[[@LINE-2]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// 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: :[[@LINE-1]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] -// CHECK-MESSAGES-NS: :[[@LINE-2]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// 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::Attr __attribute__((aligned(8))); using Deep = n2::n3::Deep; -// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] -// CHECK-MESSAGES-NS: :[[@LINE-2]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// 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]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] -// CHECK-MESSAGES-NS: :[[@LINE-2]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// 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]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] -// CHECK-MESSAGES-NS: :[[@LINE-2]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// 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 Builtin = int; -// CHECK-FIXES: 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-FIXES: 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> @@ -68,40 +70,45 @@ struct Vec {}; } // namespace templ using Vec = templ::Vec<int>; -// CHECK-FIXES: 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-FIXES: 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]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] -// CHECK-MESSAGES-NS: :[[@LINE-2]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] +// 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 Commented /*comment*/ = n1::Commented; - #define ALIAS MacroType using ALIAS = n1::MacroType; -// CHECK-FIXES: #define ALIAS MacroType -// CHECK-FIXES: 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-FIXES: #define RHS n1::MacroType -// CHECK-FIXES: 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-FIXES: #define EQ = -// CHECK-FIXES: 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; @@ -109,14 +116,16 @@ struct Base { struct Derived : Base { using T = Base::T; - // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] + // 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; // CHECK-FIXES-NS: using T = Base::T; }; void local_scope() { using LocalType = n1::LocalType; - // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: type alias is redundant; use a using-declaration instead [readability-redundant-qualified-alias] + // 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; // CHECK-FIXES-NS: using LocalType = n1::LocalType; } >From 9cc26307480f8b5953c4172c9b217e729c6da986 Mon Sep 17 00:00:00 2001 From: Daniil Dudkin <[email protected]> Date: Sun, 8 Feb 2026 18:59:11 +0300 Subject: [PATCH 3/5] fix docs --- clang-tools-extra/docs/ReleaseNotes.rst | 4 ++-- .../checks/readability/redundant-qualified-alias.rst | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 9d99fb972606c..fff0b16c85d45 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -136,8 +136,8 @@ New checks - New :doc:`readability-redundant-qualified-alias <clang-tidy/checks/readability/redundant-qualified-alias>` check. - Finds redundant identity type aliases of the form ``using X = ns::X;`` and - suggests rewriting them as using-declarations when safe. + 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/readability/redundant-qualified-alias.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-qualified-alias.rst index 37b2551c70a3d..d75c71ed76af5 100644 --- 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 @@ -3,8 +3,8 @@ readability-redundant-qualified-alias ===================================== -Finds redundant identity type aliases that simply re-expose a qualified name -and can be replaced with a using-declaration. +Finds redundant identity type aliases that re-expose a qualified name and can +be replaced with a ``using`` declaration. .. code-block:: c++ @@ -25,5 +25,6 @@ Options .. option:: OnlyNamespaceScope - When false (default), consider aliases declared in any scope. When true, - only consider aliases declared in a namespace or the translation unit. + 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``. >From dac7d39e158de5fb19fbfd7a6dda0f46f5d90a5f Mon Sep 17 00:00:00 2001 From: Daniil Dudkin <[email protected]> Date: Wed, 11 Feb 2026 23:35:04 +0300 Subject: [PATCH 4/5] add ast matchers --- .../RedundantQualifiedAliasCheck.cpp | 46 ++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/RedundantQualifiedAliasCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantQualifiedAliasCheck.cpp index c6f59cf0e0306..496158669226b 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantQualifiedAliasCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantQualifiedAliasCheck.cpp @@ -34,15 +34,6 @@ struct EqualTokenInfo { } // namespace -static bool isInNamespaceOrTU(const Decl *D) { - const DeclContext *DC = D->getDeclContext(); - return DC && (DC->isTranslationUnit() || isa<NamespaceDecl>(DC)); -} - -static bool isAliasTemplate(const TypeAliasDecl *Alias) { - return Alias->getDescribedAliasTemplate() != nullptr; -} - static bool hasMacroInRange(SourceRange Range, const SourceManager &SM, const LangOptions &LangOpts) { if (Range.isInvalid()) @@ -87,6 +78,19 @@ static std::optional<NominalTypeLocInfo> peelToNominalTypeLoc(TypeLoc TL) { return std::nullopt; } +namespace { + +AST_MATCHER(TypeAliasDecl, isAliasTemplate) { + return Node.getDescribedAliasTemplate() != nullptr; +} + +AST_MATCHER(TypeLoc, hasQualifiedNominalTypeLoc) { + std::optional<NominalTypeLocInfo> Result = peelToNominalTypeLoc(Node); + return Result && Result->HasQualifier; +} + +} // namespace + static const NamedDecl *getNamedDeclFromNominalTypeLoc(TypeLoc TL) { if (const auto TypedefTL = TL.getAs<TypedefTypeLoc>()) return TypedefTL.getTypePtr()->getDecl(); @@ -174,7 +178,23 @@ void RedundantQualifiedAliasCheck::storeOptions( } void RedundantQualifiedAliasCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher(typeAliasDecl().bind("alias"), this); + if (OnlyNamespaceScope) { + Finder->addMatcher( + typeAliasDecl( + unless(isAliasTemplate()), unless(isImplicit()), + unless(isExpansionInSystemHeader()), + hasTypeLoc(hasQualifiedNominalTypeLoc()), + hasDeclContext(anyOf(translationUnitDecl(), namespaceDecl()))) + .bind("alias"), + this); + return; + } + Finder->addMatcher(typeAliasDecl(unless(isAliasTemplate()), + unless(isImplicit()), + unless(isExpansionInSystemHeader()), + hasTypeLoc(hasQualifiedNominalTypeLoc())) + .bind("alias"), + this); } void RedundantQualifiedAliasCheck::check( @@ -183,12 +203,6 @@ void RedundantQualifiedAliasCheck::check( if (!Alias) return; - if (OnlyNamespaceScope && !isInNamespaceOrTU(Alias)) - return; - - if (isAliasTemplate(Alias)) - return; - if (Alias->getLocation().isInvalid() || Alias->getLocation().isMacroID()) return; >From 927472ab681f2db7a51945d1f945365b4ba33ee6 Mon Sep 17 00:00:00 2001 From: Daniil Dudkin <[email protected]> Date: Sat, 14 Feb 2026 15:35:04 +0300 Subject: [PATCH 5/5] address review comment --- .../RedundantQualifiedAliasCheck.cpp | 40 +++++++++++++++---- .../readability/redundant-qualified-alias.cpp | 34 +++++++++++++++- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/RedundantQualifiedAliasCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantQualifiedAliasCheck.cpp index 496158669226b..04ffe77cf1126 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantQualifiedAliasCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantQualifiedAliasCheck.cpp @@ -8,12 +8,17 @@ #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/StmtCXX.h" #include "clang/AST/TypeLoc.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Lexer.h" +#include "llvm/ADT/TypeSwitch.h" +#include <cassert> #include <optional> using namespace clang::ast_matchers; @@ -43,10 +48,6 @@ static bool hasMacroInRange(SourceRange Range, const SourceManager &SM, static std::optional<NominalTypeLocInfo> peelToNominalTypeLoc(TypeLoc TL) { while (!TL.isNull()) { - if (const auto ParenTL = TL.getAs<ParenTypeLoc>()) { - TL = ParenTL.getInnerLoc(); - continue; - } if (const auto AttrTL = TL.getAs<AttributedTypeLoc>()) { // Preserve any attributes by rewriting only the alias name and '='. TL = AttrTL.getModifiedLoc(); @@ -104,6 +105,28 @@ static bool hasSameUnqualifiedName(const TypeAliasDecl *Alias, return Alias->getName() == Target->getName(); } +static bool isControlFlowInitParent(const DeclStmt *DeclS, + const DynTypedNode &Parent) { + return llvm::TypeSwitch<const Stmt *, bool>(Parent.get<Stmt>()) + .Case<IfStmt, SwitchStmt, ForStmt, CXXForRangeStmt>( + [&](const auto *S) { return S->getInit() == DeclS; }) + .Default(false); +} + +static bool isInControlFlowInitStatement(const TypeAliasDecl *Alias, + ASTContext &Context) { + for (const DynTypedNode &AliasParent : Context.getParents(*Alias)) { + const auto *DeclS = AliasParent.get<DeclStmt>(); + if (!DeclS) + continue; + + for (const DynTypedNode &DeclSParent : Context.getParents(*DeclS)) + if (isControlFlowInitParent(DeclS, DeclSParent)) + return true; + } + return false; +} + static std::optional<EqualTokenInfo> findEqualTokenAfter(SourceLocation StartLoc, SourceLocation LimitLoc, const SourceManager &SM, const LangOptions &LangOpts) { @@ -182,7 +205,6 @@ void RedundantQualifiedAliasCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( typeAliasDecl( unless(isAliasTemplate()), unless(isImplicit()), - unless(isExpansionInSystemHeader()), hasTypeLoc(hasQualifiedNominalTypeLoc()), hasDeclContext(anyOf(translationUnitDecl(), namespaceDecl()))) .bind("alias"), @@ -191,7 +213,6 @@ void RedundantQualifiedAliasCheck::registerMatchers(MatchFinder *Finder) { } Finder->addMatcher(typeAliasDecl(unless(isAliasTemplate()), unless(isImplicit()), - unless(isExpansionInSystemHeader()), hasTypeLoc(hasQualifiedNominalTypeLoc())) .bind("alias"), this); @@ -200,12 +221,15 @@ void RedundantQualifiedAliasCheck::registerMatchers(MatchFinder *Finder) { void RedundantQualifiedAliasCheck::check( const MatchFinder::MatchResult &Result) { const auto *Alias = Result.Nodes.getNodeAs<TypeAliasDecl>("alias"); - if (!Alias) - return; + assert(Alias && "matcher must bind alias"); if (Alias->getLocation().isInvalid() || Alias->getLocation().isMacroID()) return; + assert(Result.Context && "match result should always carry ASTContext"); + if (isInControlFlowInitStatement(Alias, *Result.Context)) + return; + const TypeSourceInfo *TSI = Alias->getTypeSourceInfo(); if (!TSI) return; 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 index 32931c7d6191b..197b8d9677767 100644 --- 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 @@ -1,6 +1,9 @@ // 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 %s readability-redundant-qualified-alias %t +// RUN: %check_clang_tidy -check-suffixes=NS,NS-CXX23 -std=c++23 %s readability-redundant-qualified-alias %t -- \ +// RUN: -config='{CheckOptions: { readability-redundant-qualified-alias.OnlyNamespaceScope: true }}' namespace n1 { struct Foo {}; @@ -119,7 +122,6 @@ struct Derived : Base { // 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; - // CHECK-FIXES-NS: using T = Base::T; }; void local_scope() { @@ -127,5 +129,33 @@ void local_scope() { // 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; - // CHECK-FIXES-NS: using LocalType = 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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
