[clang] [Clang] remove redundant uses of dyn_cast (NFC) (PR #189106)

via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 27 13:54:09 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-clang-temporal-safety

Author: Henrik G. Olsson (hnrklssn)

<details>
<summary>Changes</summary>

This removes dyn_cast invocations where the argument is already of the target type (including through subtyping). This was created by adding a static assert in dyn_cast and letting an LLM iterate until the code base compiled. I then went through each example and cleaned it up. This does not commit the static assert in dyn_cast, because it would prevent a lot of uses in templated code. To prevent backsliding we should instead add an LLVM aware version of https://clang.llvm.org/extra/clang-tidy/checks/readability/redundant-casting.html (or expand the existing one).

---
Full diff: https://github.com/llvm/llvm-project/pull/189106.diff


15 Files Affected:

- (modified) clang/lib/AST/ExprCXX.cpp (+1-3) 
- (modified) clang/lib/AST/ItaniumMangle.cpp (+2-2) 
- (modified) clang/lib/Analysis/CFG.cpp (+1-3) 
- (modified) clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp (+4-6) 
- (modified) clang/lib/Analysis/LiveVariables.cpp (+1-2) 
- (modified) clang/lib/Analysis/UnsafeBufferUsage.cpp (+2-2) 
- (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+8-9) 
- (modified) clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp (+5-5) 
- (modified) clang/lib/Interpreter/InterpreterUtils.cpp (+1-1) 
- (modified) clang/lib/Sema/Sema.cpp (+12-16) 
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+1-1) 
- (modified) clang/lib/Sema/SemaExpr.cpp (+2-2) 
- (modified) clang/lib/Sema/SemaFunctionEffects.cpp (+3-4) 
- (modified) clang/lib/Sema/SemaOpenACC.cpp (+1-1) 
- (modified) clang/tools/driver/cc1gen_reproducer_main.cpp (+4-6) 


``````````diff
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index bcc481fc8399f..dd603bf548926 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -1749,9 +1749,7 @@ PackIndexingExpr *PackIndexingExpr::Create(
 
 NamedDecl *PackIndexingExpr::getPackDecl() const {
   if (auto *D = dyn_cast<DeclRefExpr>(getPackIdExpression()); D) {
-    NamedDecl *ND = dyn_cast<NamedDecl>(D->getDecl());
-    assert(ND && "exected a named decl");
-    return ND;
+    return D->getDecl();
   }
   assert(false && "invalid declaration kind in pack indexing expression");
   return nullptr;
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index eea04b14eaf09..ccf5717073fbf 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -643,8 +643,8 @@ static const CXXRecordDecl *getLambdaForInitCapture(const VarDecl *VD) {
     return nullptr;
 
   const auto *Method = cast<CXXMethodDecl>(VD->getDeclContext());
-  const auto *Lambda = dyn_cast<CXXRecordDecl>(Method->getParent());
-  if (!Lambda || !Lambda->isLambda())
+  const CXXRecordDecl *Lambda = Method->getParent();
+  if (!Lambda->isLambda())
     return nullptr;
 
   return Lambda;
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index a5a8cfb02b2b3..543b9d8424488 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -4179,9 +4179,7 @@ CFGBlock *CFGBuilder::VisitArrayInitLoopExpr(ArrayInitLoopExpr *A,
   if (CFGBlock *R = Visit(A->getSubExpr()))
     B = R;
 
-  auto *OVE = dyn_cast<OpaqueValueExpr>(A->getCommonExpr());
-  assert(OVE && "ArrayInitLoopExpr->getCommonExpr() should be wrapped in an "
-                "OpaqueValueExpr!");
+  OpaqueValueExpr *OVE = A->getCommonExpr();
   if (CFGBlock *R = Visit(OVE->getSourceExpr()))
     B = R;
 
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index 80a73a2bf687e..6b61d7fd64fd7 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -71,12 +71,10 @@ void FactsGenerator::flow(OriginList *Dst, OriginList *Src, bool Kill) {
 /// \param DRE The declaration reference expression that initiates the borrow.
 /// \return The new Loan on success, nullptr otherwise.
 static const Loan *createLoan(FactManager &FactMgr, const DeclRefExpr *DRE) {
-  if (const auto *VD = dyn_cast<ValueDecl>(DRE->getDecl())) {
-    AccessPath Path(VD);
-    // The loan is created at the location of the DeclRefExpr.
-    return FactMgr.getLoanMgr().createLoan(Path, DRE);
-  }
-  return nullptr;
+  const ValueDecl *VD = DRE->getDecl();
+  AccessPath Path(VD);
+  // The loan is created at the location of the DeclRefExpr.
+  return FactMgr.getLoanMgr().createLoan(Path, DRE);
 }
 
 /// Creates a loan for the storage location of a temporary object.
diff --git a/clang/lib/Analysis/LiveVariables.cpp b/clang/lib/Analysis/LiveVariables.cpp
index 74b930bf26fb6..c529ca52abcb2 100644
--- a/clang/lib/Analysis/LiveVariables.cpp
+++ b/clang/lib/Analysis/LiveVariables.cpp
@@ -197,8 +197,7 @@ static const VariableArrayType *FindVA(QualType Ty) {
 
 static const Expr *LookThroughExpr(const Expr *E) {
   while (E) {
-    if (const Expr *Ex = dyn_cast<Expr>(E))
-      E = Ex->IgnoreParens();
+    E = E->IgnoreParens();
     if (const FullExpr *FE = dyn_cast<FullExpr>(E)) {
       E = FE->getSubExpr();
       continue;
diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index c44a42dc93c13..3dba15cff3b52 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -2287,7 +2287,7 @@ class UnsafeFormatAttributedFunctionCallGadget : public WarningGadget {
     auto *CE = dyn_cast<CallExpr>(S);
     if (!CE || !CE->getDirectCallee())
       return false;
-    const auto *FD = dyn_cast<FunctionDecl>(CE->getDirectCallee());
+    const FunctionDecl *FD = CE->getDirectCallee();
     if (!FD)
       return false;
 
@@ -2495,7 +2495,7 @@ class PointerDereferenceGadget : public FixableGadget {
       const auto *UO = dyn_cast<UnaryOperator>(S);
       if (!UO || UO->getOpcode() != UO_Deref)
         return;
-      const auto *CE = dyn_cast<Expr>(UO->getSubExpr());
+      const Expr *CE = UO->getSubExpr();
       if (!CE)
         return;
       CE = CE->IgnoreParenImpCasts();
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 0fd17b98570fc..3b19b88b0a5f8 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -5979,15 +5979,14 @@ struct ReconstitutableType : public RecursiveASTVisitor<ReconstitutableType> {
   bool TraverseEnumType(EnumType *ET, bool = false) {
     // Unnamed enums can't be reconstituted due to a lack of column info we
     // produce in the DWARF, so we can't get Clang's full name back.
-    if (const auto *ED = dyn_cast<EnumDecl>(ET->getDecl())) {
-      if (!ED->getIdentifier()) {
-        Reconstitutable = false;
-        return false;
-      }
-      if (!ED->getDefinitionOrSelf()->isExternallyVisible()) {
-        Reconstitutable = false;
-        return false;
-      }
+    const EnumDecl *ED = ET->getDecl();
+    if (!ED->getIdentifier()) {
+      Reconstitutable = false;
+      return false;
+    }
+    if (!ED->getDefinitionOrSelf()->isExternallyVisible()) {
+      Reconstitutable = false;
+      return false;
     }
     return true;
   }
diff --git a/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp b/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp
index d7cfd23bb0a7a..1f5c3ed5375db 100644
--- a/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp
+++ b/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp
@@ -70,9 +70,9 @@ class InterfaceStubFunctionsConsumer : public ASTConsumer {
             !Instance.getLangOpts().GNUInline)
           return true;
         if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
-          if (const auto *RC = dyn_cast<CXXRecordDecl>(MD->getParent()))
-            if (isa<ClassTemplateDecl>(RC->getParent()) || !isVisible(RC))
-              return true;
+          const CXXRecordDecl *RC = MD->getParent();
+          if (isa<ClassTemplateDecl>(RC->getParent()) || !isVisible(RC))
+            return true;
           if (MD->isDependentContext() || !MD->hasBody())
             return true;
         }
@@ -151,13 +151,13 @@ class InterfaceStubFunctionsConsumer : public ASTConsumer {
   void HandleTemplateSpecializations(const FunctionTemplateDecl &FTD,
                                      MangledSymbols &Symbols, int RDO) {
     for (const auto *D : FTD.specializations())
-      HandleNamedDecl(dyn_cast<NamedDecl>(D), Symbols, RDO);
+      HandleNamedDecl(D, Symbols, RDO);
   }
 
   void HandleTemplateSpecializations(const ClassTemplateDecl &CTD,
                                      MangledSymbols &Symbols, int RDO) {
     for (const auto *D : CTD.specializations())
-      HandleNamedDecl(dyn_cast<NamedDecl>(D), Symbols, RDO);
+      HandleNamedDecl(D, Symbols, RDO);
   }
 
   bool HandleNamedDecl(const NamedDecl *ND, MangledSymbols &Symbols, int RDO) {
diff --git a/clang/lib/Interpreter/InterpreterUtils.cpp b/clang/lib/Interpreter/InterpreterUtils.cpp
index a1f164a3946e8..526cd491dbc6d 100644
--- a/clang/lib/Interpreter/InterpreterUtils.cpp
+++ b/clang/lib/Interpreter/InterpreterUtils.cpp
@@ -98,7 +98,7 @@ NamedDecl *LookupNamed(Sema &S, llvm::StringRef Name,
   R.resolveKind();
 
   if (R.isSingleResult())
-    return dyn_cast<NamedDecl>(R.getFoundDecl());
+    return R.getFoundDecl();
 
   return nullptr;
 }
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 98318fc597f36..0799d1f039f9f 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1420,22 +1420,18 @@ void Sema::ActOnEndOfTranslationUnit() {
   // in the module purview but has no definition before the end of the TU or
   // the start of a Private Module Fragment (if one is present).
   if (!PendingInlineFuncDecls.empty()) {
-    for (auto *D : PendingInlineFuncDecls) {
-      if (auto *FD = dyn_cast<FunctionDecl>(D)) {
-        bool DefInPMF = false;
-        if (auto *FDD = FD->getDefinition()) {
-          DefInPMF = FDD->getOwningModule()->isPrivateModule();
-          if (!DefInPMF)
-            continue;
-        }
-        Diag(FD->getLocation(), diag::err_export_inline_not_defined)
-            << DefInPMF;
-        // If we have a PMF it should be at the end of the ModuleScopes.
-        if (DefInPMF &&
-            ModuleScopes.back().Module->Kind == Module::PrivateModuleFragment) {
-          Diag(ModuleScopes.back().BeginLoc,
-               diag::note_private_module_fragment);
-        }
+    for (auto *FD : PendingInlineFuncDecls) {
+      bool DefInPMF = false;
+      if (auto *FDD = FD->getDefinition()) {
+        DefInPMF = FDD->getOwningModule()->isPrivateModule();
+        if (!DefInPMF)
+          continue;
+      }
+      Diag(FD->getLocation(), diag::err_export_inline_not_defined) << DefInPMF;
+      // If we have a PMF it should be at the end of the ModuleScopes.
+      if (DefInPMF &&
+          ModuleScopes.back().Module->Kind == Module::PrivateModuleFragment) {
+        Diag(ModuleScopes.back().BeginLoc, diag::note_private_module_fragment);
       }
     }
     PendingInlineFuncDecls.clear();
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 441df43d3d184..b3a02a3fd5d02 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -98,7 +98,7 @@ bool CheckDefaultArgumentVisitor::VisitExpr(const Expr *Node) {
 /// determine whether this declaration can be used in the default
 /// argument expression.
 bool CheckDefaultArgumentVisitor::VisitDeclRefExpr(const DeclRefExpr *DRE) {
-  const ValueDecl *Decl = dyn_cast<ValueDecl>(DRE->getDecl());
+  const ValueDecl *Decl = DRE->getDecl();
 
   if (!isa<VarDecl, BindingDecl>(Decl))
     return false;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index cbbb4f791ee80..d1116e1d5a2b2 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -13962,10 +13962,10 @@ static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) {
   if (!DRE) return NCCK_None;
   if (!DRE->refersToEnclosingVariableOrCapture()) return NCCK_None;
 
-  ValueDecl *Value = dyn_cast<ValueDecl>(DRE->getDecl());
+  ValueDecl *Value = DRE->getDecl();
 
   // The declaration must be a value which is not declared 'const'.
-  if (!Value || Value->getType().isConstQualified())
+  if (Value->getType().isConstQualified())
     return NCCK_None;
 
   BindingDecl *Binding = dyn_cast<BindingDecl>(Value);
diff --git a/clang/lib/Sema/SemaFunctionEffects.cpp b/clang/lib/Sema/SemaFunctionEffects.cpp
index 12cc02965e7d3..124e23cc97556 100644
--- a/clang/lib/Sema/SemaFunctionEffects.cpp
+++ b/clang/lib/Sema/SemaFunctionEffects.cpp
@@ -987,7 +987,7 @@ class Analyzer {
       // The target function may have implicit code paths beyond the
       // body: member and base destructors. Visit these first.
       if (auto *Dtor = dyn_cast<CXXDestructorDecl>(CurrentCaller.CDecl))
-        followDestructor(dyn_cast<CXXRecordDecl>(Dtor->getParent()), Dtor);
+        followDestructor(Dtor->getParent(), Dtor);
 
       if (auto *FD = dyn_cast<FunctionDecl>(CurrentCaller.CDecl)) {
         TrailingRequiresClause = FD->getTrailingRequiresClause().ConstraintExpr;
@@ -1095,9 +1095,8 @@ class Analyzer {
       for (const FieldDecl *Field : Rec->fields())
         followTypeDtor(Field->getType(), DtorLoc);
 
-      if (const auto *Class = dyn_cast<CXXRecordDecl>(Rec))
-        for (const CXXBaseSpecifier &Base : Class->bases())
-          followTypeDtor(Base.getType(), DtorLoc);
+      for (const CXXBaseSpecifier &Base : Rec->bases())
+        followTypeDtor(Base.getType(), DtorLoc);
     }
 
     void followTypeDtor(QualType QT, SourceLocation CallSite) {
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index 1115efbb8305c..30e07d7b145af 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -1231,7 +1231,7 @@ const ValueDecl *getDeclFromExpr(const Expr *E) {
   if (!E)
     return nullptr;
   if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
-    return dyn_cast<ValueDecl>(DRE->getDecl());
+    return DRE->getDecl();
 
   if (const auto *ME = dyn_cast<MemberExpr>(E))
     if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
diff --git a/clang/tools/driver/cc1gen_reproducer_main.cpp b/clang/tools/driver/cc1gen_reproducer_main.cpp
index 851d252015c44..d8e4a0d470bc5 100644
--- a/clang/tools/driver/cc1gen_reproducer_main.cpp
+++ b/clang/tools/driver/cc1gen_reproducer_main.cpp
@@ -136,12 +136,10 @@ generateReproducerForInvocationArguments(
   std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(Argv));
   if (C && !C->containsError()) {
     for (const auto &J : C->getJobs()) {
-      if (const Command *Cmd = dyn_cast<Command>(&J)) {
-        Driver::CompilationDiagnosticReport Report;
-        TheDriver.generateCompilationDiagnostics(
-            *C, *Cmd, generateReproducerMetaInfo(Info), &Report);
-        return Report;
-      }
+      Driver::CompilationDiagnosticReport Report;
+      TheDriver.generateCompilationDiagnostics(
+          *C, J, generateReproducerMetaInfo(Info), &Report);
+      return Report;
     }
   }
 

``````````

</details>


https://github.com/llvm/llvm-project/pull/189106


More information about the cfe-commits mailing list