https://github.com/hnrklssn updated https://github.com/llvm/llvm-project/pull/189274
>From 3c91a0e1744ce531af38404ffa7c20409937d79b Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" <[email protected]> Date: Sun, 29 Mar 2026 10:39:21 -0700 Subject: [PATCH 1/3] [clang-tidy] detect redundant uses of LLVM's cast, dyn_cast Warns when casting to the same pointee type, or when the target pointee type is a super type of the argument's pointee type. Supported functions: - cast - cast_if_present - cast_or_null - dyn_cast - dyn_cast_if_present - dyn_cast_or_null --- .../clang-tidy/llvm/CMakeLists.txt | 1 + .../clang-tidy/llvm/LLVMTidyModule.cpp | 3 + .../clang-tidy/llvm/RedundantCastingCheck.cpp | 131 ++++++++++++++ .../clang-tidy/llvm/RedundantCastingCheck.h | 33 ++++ clang-tools-extra/docs/ReleaseNotes.rst | 5 + .../docs/clang-tidy/checks/list.rst | 1 + .../checks/llvm/redundant-casting.rst | 24 +++ .../checkers/llvm/redundant-casting.cpp | 163 ++++++++++++++++++ 8 files changed, 361 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/llvm/RedundantCastingCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/llvm/RedundantCastingCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/llvm/redundant-casting.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/llvm/redundant-casting.cpp diff --git a/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt b/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt index a807f0ab65f87..c81882e0e2024 100644 --- a/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt @@ -10,6 +10,7 @@ add_clang_library(clangTidyLLVMModule STATIC PreferIsaOrDynCastInConditionalsCheck.cpp PreferRegisterOverUnsignedCheck.cpp PreferStaticOverAnonymousNamespaceCheck.cpp + RedundantCastingCheck.cpp TwineLocalCheck.cpp TypeSwitchCaseTypesCheck.cpp UseNewMLIROpBuilderCheck.cpp diff --git a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp index c180574bdeed6..104fcf63712f7 100644 --- a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp @@ -16,6 +16,7 @@ #include "PreferIsaOrDynCastInConditionalsCheck.h" #include "PreferRegisterOverUnsignedCheck.h" #include "PreferStaticOverAnonymousNamespaceCheck.h" +#include "RedundantCastingCheck.h" #include "TwineLocalCheck.h" #include "TypeSwitchCaseTypesCheck.h" #include "UseNewMLIROpBuilderCheck.h" @@ -43,6 +44,8 @@ class LLVMModule : public ClangTidyModule { "llvm-prefer-static-over-anonymous-namespace"); CheckFactories.registerCheck<readability::QualifiedAutoCheck>( "llvm-qualified-auto"); + CheckFactories.registerCheck<RedundantCastingCheck>( + "llvm-redundant-casting"); CheckFactories.registerCheck<TwineLocalCheck>("llvm-twine-local"); CheckFactories.registerCheck<TypeSwitchCaseTypesCheck>( "llvm-type-switch-case-types"); diff --git a/clang-tools-extra/clang-tidy/llvm/RedundantCastingCheck.cpp b/clang-tools-extra/clang-tidy/llvm/RedundantCastingCheck.cpp new file mode 100644 index 0000000000000..a29701cc012b6 --- /dev/null +++ b/clang-tools-extra/clang-tidy/llvm/RedundantCastingCheck.cpp @@ -0,0 +1,131 @@ +//===----------------------------------------------------------------------===// +// +// 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 "RedundantCastingCheck.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/TemplateBase.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Lex/Lexer.h" +#include "llvm/ADT/STLExtras.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::llvm_check { + +namespace { +AST_MATCHER(Expr, isMacroID) { return Node.getExprLoc().isMacroID(); } +AST_MATCHER_P(OverloadExpr, hasAnyUnresolvedName, ArrayRef<StringRef>, Names) { + auto DeclName = Node.getName(); + if (!DeclName.isIdentifier()) + return false; + const IdentifierInfo *II = DeclName.getAsIdentifierInfo(); + return llvm::any_of(Names, [II](StringRef Name) { return II->isStr(Name); }); +} +} // namespace + +static StringRef FunctionNames[] = { + "cast", "cast_or_null", "cast_if_present", + "dyn_cast", "dyn_cast_or_null", "dyn_cast_if_present"}; + +void RedundantCastingCheck::registerMatchers(MatchFinder *Finder) { + auto AnyCalleeName = [](ArrayRef<StringRef> CalleeName) { + return allOf(unless(isMacroID()), unless(cxxMemberCallExpr()), + callee(expr(ignoringImpCasts( + declRefExpr(to(namedDecl(hasAnyName(CalleeName))), + hasAnyTemplateArgumentLoc(anything())) + .bind("callee"))))); + }; + auto AnyCalleeNameInUninstantiatedTemplate = + [](ArrayRef<StringRef> CalleeName) { + return allOf(unless(isMacroID()), unless(cxxMemberCallExpr()), + callee(expr(ignoringImpCasts( + unresolvedLookupExpr(hasAnyUnresolvedName(CalleeName)) + .bind("callee"))))); + }; + Finder->addMatcher( + callExpr( + AnyCalleeName(FunctionNames), + hasAncestor(functionDecl().bind("context"))) + .bind("call"), + this); + Finder->addMatcher( + callExpr(AnyCalleeNameInUninstantiatedTemplate(FunctionNames)) + .bind("call"), + this); +} + +static QualType stripPointerOrReference(QualType Ty) { + QualType Pointee = Ty->getPointeeType(); + if (Pointee.isNull()) + return Ty; + return Pointee; +} + +void RedundantCastingCheck::check(const MatchFinder::MatchResult &Result) { + const auto &Nodes = Result.Nodes; + const auto *Call = Nodes.getNodeAs<CallExpr>("call"); + if (Call->getNumArgs() != 1) + return; + + CanQualType RetTy; + std::string FuncName; + if (const auto *ResolvedCallee = Nodes.getNodeAs<DeclRefExpr>("callee")) { + const auto *F = dyn_cast<FunctionDecl>(ResolvedCallee->getDecl()); + const auto *SurroundingFunc = Nodes.getNodeAs<FunctionDecl>("context"); + // Casts can be redundant for some instantiations but not others. + // Only emit warnings in templates in the uninstantated versions. + if (SurroundingFunc->isTemplateInstantiation()) + return; + + RetTy = stripPointerOrReference(F->getReturnType()) + ->getCanonicalTypeUnqualified(); + FuncName = F->getName(); + } else if (const auto *UnresolvedCallee = + Nodes.getNodeAs<UnresolvedLookupExpr>("callee")) { + if (UnresolvedCallee->getNumTemplateArgs() != 1) + return; + auto TArg = UnresolvedCallee->template_arguments()[0].getArgument(); + if (TArg.getKind() != TemplateArgument::Type) + return; + + RetTy = TArg.getAsType()->getCanonicalTypeUnqualified(); + FuncName = UnresolvedCallee->getName().getAsString(); + } else { + return; + } + + const auto *Arg = Call->getArg(0); + const CanQualType FromTy = + stripPointerOrReference(Arg->getType())->getCanonicalTypeUnqualified(); + const auto *FromDecl = FromTy->getAsCXXRecordDecl(); + const auto *RetDecl = RetTy->getAsCXXRecordDecl(); + const bool IsDerived = FromDecl && RetDecl && FromDecl->isDerivedFrom(RetDecl); + if (FromTy != RetTy && !IsDerived) + return; + + auto GetText = [&](SourceRange R) { + return Lexer::getSourceText(CharSourceRange::getTokenRange(R), + *Result.SourceManager, getLangOpts()); + }; + StringRef ArgText = GetText(Arg->getSourceRange()); + diag(Call->getExprLoc(), "redundant use of '%0'") + << FuncName + << FixItHint::CreateReplacement(Call->getSourceRange(), ArgText); + diag(Arg->getExprLoc(), "source expression %0 has type %1", + DiagnosticIDs::Note) + << Arg << Arg->IgnoreParenImpCasts()->getType(); + + if (FromTy != RetTy) { + diag(Arg->getExprLoc(), "%0 is a subtype of %1", DiagnosticIDs::Note) + << FromTy << RetTy; + } +} + +} // namespace clang::tidy::llvm_check diff --git a/clang-tools-extra/clang-tidy/llvm/RedundantCastingCheck.h b/clang-tools-extra/clang-tidy/llvm/RedundantCastingCheck.h new file mode 100644 index 0000000000000..3243616976014 --- /dev/null +++ b/clang-tools-extra/clang-tidy/llvm/RedundantCastingCheck.h @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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_LLVM_REDUNDANTCASTINGCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_REDUNDANTCASTINGCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::llvm_check { + +/// Detect redundant uses of LLVM's cast and dyn_cast functions. +/// +/// For the user-facing documentation see: +/// https://clang.llvm.org/extra/clang-tidy/checks/llvm/redundant-casting.html +class RedundantCastingCheck : public ClangTidyCheck { +public: + RedundantCastingCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus; + } +}; + +} // namespace clang::tidy::llvm_check + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_REDUNDANTCASTINGCHECK_H diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index eb735e6e62ee4..43d67e0831fd9 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -114,6 +114,11 @@ New checks Finds functions where throwing exceptions is unsafe but the function is still marked as potentially throwing. +- New :doc:`llvm-redundant-casting + <clang-tidy/checks/llvm/redundant-casting>` check. + + Detect redundant uses of LLVM's cast functions. + - New :doc:`llvm-type-switch-case-types <clang-tidy/checks/llvm/type-switch-case-types>` check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index ceab1e9414951..03ed10217fe45 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -251,6 +251,7 @@ Clang-Tidy Checks :doc:`llvm-prefer-isa-or-dyn-cast-in-conditionals <llvm/prefer-isa-or-dyn-cast-in-conditionals>`, "Yes" :doc:`llvm-prefer-register-over-unsigned <llvm/prefer-register-over-unsigned>`, "Yes" :doc:`llvm-prefer-static-over-anonymous-namespace <llvm/prefer-static-over-anonymous-namespace>`, + :doc:`llvm-redundant-casting <llvm/redundant-casting>`, "Yes" :doc:`llvm-twine-local <llvm/twine-local>`, "Yes" :doc:`llvm-type-switch-case-types <llvm/type-switch-case-types>`, "Yes" :doc:`llvm-use-new-mlir-op-builder <llvm/use-new-mlir-op-builder>`, "Yes" diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvm/redundant-casting.rst b/clang-tools-extra/docs/clang-tidy/checks/llvm/redundant-casting.rst new file mode 100644 index 0000000000000..c09bc40dd207e --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/redundant-casting.rst @@ -0,0 +1,24 @@ +.. title:: clang-tidy - llvm-redundant-casting + +llvm-redundant-casting +====================== + +Points out uses of ``cast<>``, ``dyn_cast<>`` and their ``or_null`` variants +that are unnecessary because the argument already is of the target type, or a +derived type thereof. + +.. code-block:: c++ + + struct A {}; + A a; + // Finds: + A x = cast<A>(a); + // replaced by: + A x = a; + + struct B : public A {}; + B b; + // Finds: + A y = cast<A>(b); + // replaced by: + A y = b; diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/redundant-casting.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/redundant-casting.cpp new file mode 100644 index 0000000000000..4027933f95c4b --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/redundant-casting.cpp @@ -0,0 +1,163 @@ +// RUN: %check_clang_tidy -std=c++17 %s llvm-redundant-casting %t + +namespace llvm { +#define CAST_FUNCTION(name) \ +template <typename To, typename From> \ +[[nodiscard]] inline decltype(auto) name(const From &Val) { \ + return static_cast<const To&>(Val); \ +} \ +template <typename To, typename From> \ +[[nodiscard]] inline decltype(auto) name(From &Val) { \ + return static_cast<To&>(Val); \ +} \ +template <typename To, typename From> \ +[[nodiscard]] inline decltype(auto) name(const From *Val) { \ + return static_cast<const To*>(Val); \ +} \ +template <typename To, typename From> \ +[[nodiscard]] inline decltype(auto) name(From *Val) { \ + return static_cast<To*>(Val); \ +} +CAST_FUNCTION(cast) +CAST_FUNCTION(dyn_cast) +CAST_FUNCTION(cast_or_null) +CAST_FUNCTION(cast_if_present) +CAST_FUNCTION(dyn_cast_or_null) +CAST_FUNCTION(dyn_cast_if_present) +} + +struct A {}; +struct B : A {}; +A &getA(); + +void testCast(A& value) { + A& a1 = llvm::cast<A>(value); + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant use of 'cast' [llvm-redundant-casting] + // CHECK-MESSAGES: :[[@LINE-2]]:25: note: source expression 'value' has type 'A' + // CHECK-FIXES: A& a1 = value; + (void)a1; +} + +void testDynCast(A& value) { + A& a2 = llvm::dyn_cast<A>(value); + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant use of 'dyn_cast' [llvm-redundant-casting] + // CHECK-MESSAGES: :[[@LINE-2]]:29: note: source expression 'value' has type 'A' + // CHECK-FIXES: A& a2 = value; + (void)a2; +} + +void testCastOrNull(A& value) { + A& a3 = llvm::cast_or_null<A>(value); + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant use of 'cast_or_null' [llvm-redundant-casting] + // CHECK-MESSAGES: :[[@LINE-2]]:33: note: source expression 'value' has type 'A' + // CHECK-FIXES: A& a3 = value; + (void)a3; +} + +void testCastIfPresent(A& value) { + A& a4 = llvm::cast_if_present<A>(value); + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant use of 'cast_if_present' [llvm-redundant-casting] + // CHECK-MESSAGES: :[[@LINE-2]]:36: note: source expression 'value' has type 'A' + // CHECK-FIXES: A& a4 = value; + (void)a4; +} + +void testDynCastOrNull(A& value) { + A& a5 = llvm::dyn_cast_or_null<A>(value); + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant use of 'dyn_cast_or_null' [llvm-redundant-casting] + // CHECK-MESSAGES: :[[@LINE-2]]:37: note: source expression 'value' has type 'A' + // CHECK-FIXES: A& a5 = value; + (void)a5; +} + +void testDynCastIfPresent(A& value) { + A& a6 = llvm::dyn_cast_if_present<A>(value); + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant use of 'dyn_cast_if_present' [llvm-redundant-casting] + // CHECK-MESSAGES: :[[@LINE-2]]:40: note: source expression 'value' has type 'A' + // CHECK-FIXES: A& a6 = value; + (void)a6; +} + +void testCastNonDeclRef() { + A& a7 = llvm::cast<A>((getA())); + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant use of 'cast' [llvm-redundant-casting] + // CHECK-MESSAGES: :[[@LINE-2]]:25: note: source expression '(getA())' has type 'A' + // CHECK-FIXES: A& a7 = (getA()); + (void)a7; +} + +void testUpcast(B& value) { + A& a8 = llvm::cast<A>(value); + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant use of 'cast' [llvm-redundant-casting] + // CHECK-MESSAGES: :[[@LINE-2]]:25: note: source expression 'value' has type 'B' + // CHECK-MESSAGES: :[[@LINE-3]]:25: note: 'B' is a subtype of 'A' + // CHECK-FIXES: A& a8 = value; + (void)a8; +} + +void testDowncast(A& value) { + B& a9 = llvm::cast<B>(value); + // CHECK-MESSAGES-NOT: warning + // CHECK-FIXES-NOT: A& a9 = value; + (void)a9; +} + +namespace llvm { +void testCastInLLVM(A& value) { + A& a11 = cast<A>(value); + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant use of 'cast' [llvm-redundant-casting] + // CHECK-MESSAGES: :[[@LINE-2]]:20: note: source expression 'value' has type 'A' + // CHECK-FIXES: A& a11 = value; + (void)a11; +} +} // namespace llvm + +void testCastPointer(A* value) { + A *a12 = llvm::cast<A>(value); + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant use of 'cast' [llvm-redundant-casting] + // CHECK-MESSAGES: :[[@LINE-2]]:26: note: source expression 'value' has type 'A *' + // CHECK-FIXES: A *a12 = value; + (void)a12; +} + +template <typename T> +void testCastTemplateIgnore(T* value) { + A *a13 = llvm::cast<A>(value); + // CHECK-MESSAGES-NOT: warning + // CHECK-FIXES-NOT: A *a13 = value; + (void)a13; +} +template void testCastTemplateIgnore<A>(A *value); + +template <typename T> +struct testCastTemplateIgnoreStruct { + void method(T* value) { + A *a14 = llvm::cast<A>(value); + // CHECK-MESSAGES-NOT: warning + // CHECK-FIXES-NOT: A *a14 = value; + (void)a14; + } +}; + +void call(testCastTemplateIgnoreStruct<A> s, A *a) { + s.method(a); +} + +template <typename T> +void testCastTemplateTrigger1(T* value) { + T *a15 = llvm::cast<T>(value); + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant use of 'cast' [llvm-redundant-casting] + // CHECK-MESSAGES: :[[@LINE-2]]:26: note: source expression 'value' has type 'T *' + // CHECK-FIXES: T *a15 = value; + (void)a15; +} + +template <typename T> +void testCastTemplateTrigger2(A* value, T other) { + A *a16 = llvm::cast<A>(value); + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant use of 'cast' [llvm-redundant-casting] + // CHECK-MESSAGES: :[[@LINE-2]]:26: note: source expression 'value' has type 'A *' + // CHECK-FIXES: A *a16 = value; + (void)a16; (void) other; +} + >From 2f63c0e1dfd8a163858695c1f6cdec1002786a06 Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" <[email protected]> Date: Sun, 29 Mar 2026 11:52:24 -0700 Subject: [PATCH 2/3] attempt to fix windows ci failure --- .../test/clang-tidy/checkers/llvm/redundant-casting.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/redundant-casting.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/redundant-casting.cpp index 4027933f95c4b..aad3d6a701fa4 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/llvm/redundant-casting.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/redundant-casting.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy -std=c++17 %s llvm-redundant-casting %t +// RUN: %check_clang_tidy -std=c++17 %s llvm-redundant-casting %t -- -- -fno-delayed-template-parsing namespace llvm { #define CAST_FUNCTION(name) \ >From 6102c8bea704ca8cdb0de0bcff08eaa371fc666f Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" <[email protected]> Date: Sun, 29 Mar 2026 13:54:31 -0700 Subject: [PATCH 3/3] Apply suggestions from code review Co-authored-by: Victor Chernyakin <[email protected]> --- .../clang-tidy/llvm/RedundantCastingCheck.cpp | 8 ++++---- .../test/clang-tidy/checkers/llvm/redundant-casting.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-tidy/llvm/RedundantCastingCheck.cpp b/clang-tools-extra/clang-tidy/llvm/RedundantCastingCheck.cpp index a29701cc012b6..16c6914897e07 100644 --- a/clang-tools-extra/clang-tidy/llvm/RedundantCastingCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvm/RedundantCastingCheck.cpp @@ -30,7 +30,7 @@ AST_MATCHER_P(OverloadExpr, hasAnyUnresolvedName, ArrayRef<StringRef>, Names) { } } // namespace -static StringRef FunctionNames[] = { +static constexpr StringRef FunctionNames[] = { "cast", "cast_or_null", "cast_if_present", "dyn_cast", "dyn_cast_or_null", "dyn_cast_if_present"}; @@ -98,7 +98,7 @@ void RedundantCastingCheck::check(const MatchFinder::MatchResult &Result) { RetTy = TArg.getAsType()->getCanonicalTypeUnqualified(); FuncName = UnresolvedCallee->getName().getAsString(); } else { - return; + llvm_unreachable(""); } const auto *Arg = Call->getArg(0); @@ -118,9 +118,9 @@ void RedundantCastingCheck::check(const MatchFinder::MatchResult &Result) { diag(Call->getExprLoc(), "redundant use of '%0'") << FuncName << FixItHint::CreateReplacement(Call->getSourceRange(), ArgText); - diag(Arg->getExprLoc(), "source expression %0 has type %1", + diag(Arg->getExprLoc(), "source expression has type %1", DiagnosticIDs::Note) - << Arg << Arg->IgnoreParenImpCasts()->getType(); + << Arg->getSourceRange() << Arg->IgnoreParenImpCasts()->getType(); if (FromTy != RetTy) { diag(Arg->getExprLoc(), "%0 is a subtype of %1", DiagnosticIDs::Note) diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/redundant-casting.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/redundant-casting.cpp index aad3d6a701fa4..11445c982d8fc 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/llvm/redundant-casting.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/redundant-casting.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy -std=c++17 %s llvm-redundant-casting %t -- -- -fno-delayed-template-parsing +// RUN: %check_clang_tidy -std=c++17-or-later %s llvm-redundant-casting %t -- -- -fno-delayed-template-parsing namespace llvm { #define CAST_FUNCTION(name) \ _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
