[clang] [Clang][Sema] Use llvm::dyn_cast instead of dyn_cast on PointerUnion (PR #216353)

Marc Auberer via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 14 09:46:33 PDT 2026


https://github.com/marcauberer created https://github.com/llvm/llvm-project/pull/216353

This is part of the migration from `PointerUnion<PTs>::dyn_cast<T>()` to `llvm::dyn_cast<T>(PointerUnion)`.
The dyn_cast method on PointerUnion is simply a wrapper around `llvm::dyn_cast_if_present`, which means that it can be replaced with `llvm::dyn_cast` for all non-optional types.

>From 130a2655d14e1e66ea117c0dd02bbff6f7da4cd2 Mon Sep 17 00:00:00 2001
From: Marc Auberer <marc.auberer at chillibits.com>
Date: Fri, 14 Aug 2026 18:45:19 +0200
Subject: [PATCH] [Clang][Sema] Use llvm::dyn_cast instead of dyn_cast on
 PointerUnion

---
 clang/lib/Sema/SemaConcept.cpp                |  9 ++---
 clang/lib/Sema/SemaDeclCXX.cpp                |  8 ++---
 clang/lib/Sema/SemaLifetimeSafety.h           |  4 +--
 clang/lib/Sema/SemaOverload.cpp               |  6 ++--
 clang/lib/Sema/SemaSYCL.cpp                   |  4 +--
 clang/lib/Sema/SemaTemplate.cpp               | 10 +++---
 clang/lib/Sema/SemaTemplateInstantiate.cpp    | 12 +++----
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  |  4 +--
 clang/lib/Sema/SemaTemplateVariadic.cpp       | 35 ++++++++-----------
 clang/lib/Sema/TreeTransform.h                |  2 +-
 10 files changed, 43 insertions(+), 51 deletions(-)

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index ce91099cd037c..fd80277fb2bc6 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -1318,7 +1318,7 @@ bool Sema::CheckConstraintSatisfaction(
     OutSatisfaction.IsSatisfied = true;
     return false;
   }
-  const auto *Template = Entity.dyn_cast<const NamedDecl *>();
+  const auto *Template = dyn_cast<const NamedDecl *>(Entity);
   if (!Template) {
     return ::CheckConstraintSatisfaction(
         *this, nullptr, AssociatedConstraints, TemplateArgsLists,
@@ -2047,9 +2047,7 @@ static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
 static void diagnoseUnsatisfiedConstraintExpr(
     Sema &S, const UnsatisfiedConstraintRecord &Record, SourceLocation Loc,
     bool First, concepts::NestedRequirement *Req) {
-  if (auto *Diag =
-          Record
-              .template dyn_cast<const ConstraintSubstitutionDiagnostic *>()) {
+  if (auto *Diag = dyn_cast<const ConstraintSubstitutionDiagnostic *>(Record)) {
     if (Req)
       S.Diag(Diag->first, diag::note_nested_requirement_substitution_error)
           << (int)First << Req->getInvalidConstraintEntity() << Diag->second;
@@ -2551,8 +2549,7 @@ const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints(
   }
 
   // FIXME: ConstrainedDeclOrNestedReq is never a NestedRequirement!
-  const NamedDecl *ND =
-      ConstrainedDeclOrNestedReq.dyn_cast<const NamedDecl *>();
+  const NamedDecl *ND = dyn_cast<const NamedDecl *>(ConstrainedDeclOrNestedReq);
   auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);
   if (CacheEntry == NormalizationCache.end()) {
     auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 5c425a176ff41..dffe9b07f4910 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9632,7 +9632,7 @@ bool SpecialMemberDeletionInfo::isAccessible(Subobject Subobj,
   /// type of this special member.
   CanQualType objectTy;
   AccessSpecifier access = target->getAccess();
-  if (CXXBaseSpecifier *base = Subobj.dyn_cast<CXXBaseSpecifier*>()) {
+  if (CXXBaseSpecifier *base = dyn_cast<CXXBaseSpecifier *>(Subobj)) {
     objectTy = S.Context.getCanonicalTagType(MD->getParent());
     access = CXXRecordDecl::MergeAccess(base->getAccessSpecifier(), access);
 
@@ -9651,7 +9651,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
     Subobject Subobj, Sema::SpecialMemberOverloadResult SMOR,
     bool IsDtorCallInCtor) {
   CXXMethodDecl *Decl = SMOR.getMethod();
-  FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>();
+  FieldDecl *Field = dyn_cast<FieldDecl *>(Subobj);
 
   enum {
     NotSet = -1,
@@ -9730,7 +9730,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
 /// direct or virtual base class or non-static data member of class type M.
 bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject(
     CXXRecordDecl *Class, Subobject Subobj, unsigned Quals) {
-  FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>();
+  FieldDecl *Field = dyn_cast<FieldDecl *>(Subobj);
   bool IsMutable = Field && Field->isMutable();
 
   // C++11 [class.ctor]p5:
@@ -14134,7 +14134,7 @@ bool SpecialMemberExceptionSpecInfo::visitField(FieldDecl *FD) {
 void SpecialMemberExceptionSpecInfo::visitClassSubobject(CXXRecordDecl *Class,
                                                          Subobject Subobj,
                                                          unsigned Quals) {
-  FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>();
+  FieldDecl *Field = dyn_cast<FieldDecl *>(Subobj);
   bool IsMutable = Field && Field->isMutable();
   visitSubobjectCall(Subobj, lookupIn(Class, Quals, IsMutable));
 }
diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h
index bffe1d61b0234..6d8dc1016626d 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -308,11 +308,11 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
         << ParmToAnnotate->getSourceRange()
         << FixItHint::CreateInsertion(InsertionPoint, FixItText);
 
-    if (const auto *EscapeExpr = Target.dyn_cast<const Expr *>())
+    if (const auto *EscapeExpr = dyn_cast<const Expr *>(Target))
       S.Diag(EscapeExpr->getBeginLoc(),
              diag::note_lifetime_safety_suggestion_returned_here)
           << EscapeExpr->getSourceRange();
-    else if (const auto *EscapeField = Target.dyn_cast<const FieldDecl *>())
+    else if (const auto *EscapeField = dyn_cast<const FieldDecl *>(Target))
       S.Diag(EscapeField->getLocation(),
              diag::note_lifetime_safety_escapes_to_field_here)
           << EscapeField->getSourceRange();
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 403bd784ddc7b..9a163bbe4349b 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -12410,9 +12410,9 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
                                  bool TakingCandidateAddress) {
   TemplateParameter Param = DeductionFailure.getTemplateParameter();
   NamedDecl *ParamD;
-  (ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
-  (ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) ||
-  (ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>());
+  (ParamD = dyn_cast<TemplateTypeParmDecl *>(Param)) ||
+      (ParamD = dyn_cast<NonTypeTemplateParmDecl *>(Param)) ||
+      (ParamD = dyn_cast<TemplateTemplateParmDecl *>(Param));
   switch (DeductionFailure.getResult()) {
   case TemplateDeductionResult::Success:
     llvm_unreachable(
diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp
index b942f19761f40..e180b3655bd73 100644
--- a/clang/lib/Sema/SemaSYCL.cpp
+++ b/clang/lib/Sema/SemaSYCL.cpp
@@ -676,7 +676,7 @@ class KernelParamsChecker : public ConstSubobjectVisitor<KernelParamsChecker> {
 
   void emitObjectAccessPathNotes() {
     for (auto Parent : llvm::reverse(ObjectAccessPath)) {
-      if (auto *FD = Parent.dyn_cast<const FieldDecl *>()) {
+      if (auto *FD = dyn_cast<const FieldDecl *>(Parent)) {
         const CXXRecordDecl *ParentRD = cast<CXXRecordDecl>(FD->getParent());
         if (ParentRD->isLambda()) {
           SemaSYCLRef.Diag(ParentRD->getLocation(), diag::note_within_capture)
@@ -686,7 +686,7 @@ class KernelParamsChecker : public ConstSubobjectVisitor<KernelParamsChecker> {
                            diag::note_within_field_of_type)
               << ParentRD;
         }
-      } else if (auto *BS = Parent.dyn_cast<const CXXBaseSpecifier *>()) {
+      } else if (auto *BS = dyn_cast<const CXXBaseSpecifier *>(Parent)) {
         CXXRecordDecl *RD = BS->getType()->getAsCXXRecordDecl();
         assert(RD);
         SemaSYCLRef.Diag(BS->getBeginLoc(), diag::note_within_base_of_type)
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 643392833759d..104502aa97083 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -5964,7 +5964,7 @@ bool Sema::CheckTemplateArgumentList(
       llvm::SmallVector<UnexpandedParameterPack> Unexpanded;
       collectUnexpandedParameterPacks(TL.getPatternLoc(), Unexpanded);
       for (const auto &UPP : Unexpanded) {
-        auto *TST = UPP.first.dyn_cast<const TemplateSpecializationType *>();
+        auto *TST = dyn_cast<const TemplateSpecializationType *>(UPP.first);
         if (!TST)
           continue;
         assert(isPackProducingBuiltinTemplateName(TST->getTemplateName()));
@@ -11896,10 +11896,10 @@ class ExplicitSpecializationVisibilityChecker {
       return;
 
     auto From = SD->getSpecializedTemplateOrPartial();
-    if (auto *TD = From.dyn_cast<ClassTemplateDecl *>())
+    if (auto *TD = dyn_cast<ClassTemplateDecl *>(From))
       checkTemplate(TD);
     else if (auto *TD =
-                 From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
+                 dyn_cast<ClassTemplatePartialSpecializationDecl *>(From)) {
       if (!CheckDeclaration(TD))
         diagnose(TD, true);
       checkTemplate(TD);
@@ -11912,10 +11912,10 @@ class ExplicitSpecializationVisibilityChecker {
       return;
 
     auto From = SD->getSpecializedTemplateOrPartial();
-    if (auto *TD = From.dyn_cast<VarTemplateDecl *>())
+    if (auto *TD = dyn_cast<VarTemplateDecl *>(From))
       checkTemplate(TD);
     else if (auto *TD =
-                 From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
+                 dyn_cast<VarTemplatePartialSpecializationDecl *>(From)) {
       if (!CheckDeclaration(TD))
         diagnose(TD, true);
       checkTemplate(TD);
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 3e8695a0085ad..e954afe7af5da 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -257,8 +257,8 @@ HandleClassTemplateSpec(const ClassTemplateSpecializationDecl *ClassTemplSpec,
     // specialization, as the ClassTemplateSpecializationDecl's
     // DeclContext/LexicalDeclContext will be for the primary template.
     if (auto *InstFromPartialTempl =
-            ClassTemplSpec->getSpecializedTemplateOrPartial()
-                .dyn_cast<ClassTemplatePartialSpecializationDecl *>())
+            dyn_cast<ClassTemplatePartialSpecializationDecl *>(
+                ClassTemplSpec->getSpecializedTemplateOrPartial()))
       return Response::ChangeDecl(
           InstFromPartialTempl->getLexicalDeclContext());
   }
@@ -1415,7 +1415,7 @@ namespace {
           (SemaRef.inConstraintSubstitution() ||
            SemaRef.inParameterMappingSubstitution())) {
         for (UnexpandedParameterPack ParmPack : Unexpanded) {
-          NamedDecl *VD = ParmPack.first.dyn_cast<NamedDecl *>();
+          NamedDecl *VD = dyn_cast<NamedDecl *>(ParmPack.first);
           if (auto *PVD = dyn_cast_if_present<ParmVarDecl>(VD);
               PVD && maybeInstantiateFunctionParameterToScope(PVD))
             return true;
@@ -2819,7 +2819,7 @@ TemplateInstantiator::TransformExprRequirement(concepts::ExprRequirement *Req) {
     }
   }
   assert(TransRetReq && "All code paths leading here must set TransRetReq");
-  if (Expr *E = TransExpr.dyn_cast<Expr *>())
+  if (Expr *E = dyn_cast<Expr *>(TransExpr))
     return RebuildExprRequirement(E, Req->isSimple(), Req->getNoexceptLoc(),
                                   std::move(*TransRetReq));
   return RebuildExprRequirement(
@@ -3406,7 +3406,7 @@ PreparePackForExpansion(Sema &S, const CXXBaseSpecifier &Base,
       // that required a substituion first.
       bool SawPackTypes =
           llvm::any_of(Unexpanded, [](UnexpandedParameterPack P) {
-            return P.first.dyn_cast<const SubstBuiltinTemplatePackType *>();
+            return dyn_cast<const SubstBuiltinTemplatePackType *>(P.first);
           });
       if (!SawPackTypes) {
         Info.Expand = false;
@@ -4129,7 +4129,7 @@ static ActionResult<CXXRecordDecl *> getPatternForClassTemplateSpecialization(
   CXXRecordDecl *Pattern = nullptr;
   Specialized = ClassTemplateSpec->getSpecializedTemplateOrPartial();
   if (auto *PartialSpec =
-          Specialized.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
+          dyn_cast<ClassTemplatePartialSpecializationDecl *>(Specialized)) {
     // Instantiate using the best class template partial specialization.
     while (PartialSpec->getInstantiatedFromMember()) {
       // If we've found an explicit specialization of this class template,
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 79d106168e9d0..c38589f698850 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -6557,7 +6557,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
                          VarTemplatePartialSpecializationDecl *> PatternPtr =
           VarSpec->getSpecializedTemplateOrPartial();
       if (VarTemplatePartialSpecializationDecl *Partial =
-          PatternPtr.dyn_cast<VarTemplatePartialSpecializationDecl *>())
+              dyn_cast<VarTemplatePartialSpecializationDecl *>(PatternPtr))
         cast<VarTemplateSpecializationDecl>(Var)->setInstantiationOf(
             Partial, &VarSpec->getTemplateInstantiationArgs());
 
@@ -6995,7 +6995,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
     // declarations to their instantiations.
     if (CurrentInstantiationScope) {
       if (auto Found = CurrentInstantiationScope->findInstantiationOf(D)) {
-        if (Decl *FD = Found->dyn_cast<Decl *>()) {
+        if (Decl *FD = dyn_cast<Decl *>(*Found)) {
           if (auto *BD = dyn_cast<BindingDecl>(FD);
               BD && BD->isParameterPack() && ArgPackSubstIndex) {
             return BD->getBindingPackDecls()[*ArgPackSubstIndex];
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index aa818aad7ff68..580435fa55ae4 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -446,7 +446,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
   if (sema::CapturingScopeInfo *CSI = getEnclosingLambdaOrBlock()) {
     for (auto &Pack : Unexpanded) {
       auto DeclaresThisPack = [&](NamedDecl *LocalPack) {
-        if (auto *TTPT = Pack.first.dyn_cast<const TemplateTypeParmType *>()) {
+        if (auto *TTPT = dyn_cast<const TemplateTypeParmType *>(Pack.first)) {
           auto *TTPD = dyn_cast<TemplateTypeParmDecl>(LocalPack);
           return TTPD && TTPD->getTypeForDecl() == TTPT;
         }
@@ -498,10 +498,10 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
 
   for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
     IdentifierInfo *Name = nullptr;
-    if (const TemplateTypeParmType *TTP
-          = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>())
+    if (const TemplateTypeParmType *TTP =
+            dyn_cast<const TemplateTypeParmType *>(Unexpanded[I].first))
       Name = TTP->getIdentifier();
-    else if (NamedDecl *ND = Unexpanded[I].first.dyn_cast<NamedDecl *>())
+    else if (NamedDecl *ND = dyn_cast<NamedDecl *>(Unexpanded[I].first))
       Name = ND->getIdentifier();
 
     if (Name && NamesKnown.insert(Name).second)
@@ -576,7 +576,7 @@ bool Sema::DiagnoseUnexpandedParameterPackInRequiresExpr(RequiresExpr *RE) {
   llvm::SmallPtrSet<NamedDecl *, 8> ParmSet(llvm::from_range, Parms);
   SmallVector<UnexpandedParameterPack, 2> UnexpandedParms;
   for (auto Parm : Unexpanded)
-    if (ParmSet.contains(Parm.first.dyn_cast<NamedDecl *>()))
+    if (ParmSet.contains(dyn_cast<NamedDecl *>(Parm.first)))
       UnexpandedParms.push_back(Parm);
   if (UnexpandedParms.empty())
     return false;
@@ -861,13 +861,12 @@ bool Sema::CheckParameterPacksForExpansion(
     FunctionParmPackExpr *BindingPack = nullptr;
     std::optional<unsigned> NumPrecomputedArguments;
 
-    if (auto *TTP = ParmPack.first.dyn_cast<const TemplateTypeParmType *>()) {
+    if (auto *TTP = dyn_cast<const TemplateTypeParmType *>(ParmPack.first)) {
       Depth = TTP->getDepth();
       Index = TTP->getIndex();
       Name = TTP->getIdentifier();
-    } else if (auto *TST =
-                   ParmPack.first
-                       .dyn_cast<const TemplateSpecializationType *>()) {
+    } else if (auto *TST = dyn_cast<const TemplateSpecializationType *>(
+                   ParmPack.first)) {
       assert(isPackProducingBuiltinTemplateName(TST->getTemplateName()));
       // Delay expansion, substitution is required to know the size.
       ShouldExpand = false;
@@ -882,9 +881,8 @@ bool Sema::CheckParameterPacksForExpansion(
                                                     : EllipsisLoc,
                   diag::err_unsupported_builtin_template_pack_expansion)
              << TST->getTemplateName();
-    } else if (auto *S =
-                   ParmPack.first
-                       .dyn_cast<const SubstBuiltinTemplatePackType *>()) {
+    } else if (auto *S = dyn_cast<const SubstBuiltinTemplatePackType *>(
+                   ParmPack.first)) {
       Name = nullptr;
       NumPrecomputedArguments = S->getNumArgs();
     } else {
@@ -1074,20 +1072,17 @@ UnsignedOrNone Sema::getNumArgumentsInExpansionFromUnexpanded(
     unsigned Index;
 
     if (const TemplateTypeParmType *TTP =
-            Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
+            dyn_cast<const TemplateTypeParmType *>(Unexpanded[I].first)) {
       Depth = TTP->getDepth();
       Index = TTP->getIndex();
-    } else if (auto *TST =
-                   Unexpanded[I]
-                       .first.dyn_cast<const TemplateSpecializationType *>()) {
+    } else if (auto *TST = dyn_cast<const TemplateSpecializationType *>(
+                   Unexpanded[I].first)) {
       // This is a dependent pack, we are not ready to expand it yet.
       assert(isPackProducingBuiltinTemplateName(TST->getTemplateName()));
       (void)TST;
       return std::nullopt;
-    } else if (auto *PST =
-                   Unexpanded[I]
-                       .first
-                       .dyn_cast<const SubstBuiltinTemplatePackType *>()) {
+    } else if (auto *PST = dyn_cast<const SubstBuiltinTemplatePackType *>(
+                   Unexpanded[I].first)) {
       assert((!Result || *Result == PST->getNumArgs()) &&
              "inconsistent pack sizes");
       Result = PST->getNumArgs();
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index e6abb3ad577c6..3604edefb1de7 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -5335,7 +5335,7 @@ bool TreeTransform<Derived>::PreparePackForExpansion(TemplateArgumentLoc In,
       // that required a substituion first.
       bool SawPackTypes =
           llvm::any_of(Unexpanded, [](UnexpandedParameterPack P) {
-            return P.first.dyn_cast<const SubstBuiltinTemplatePackType *>();
+            return dyn_cast<const SubstBuiltinTemplatePackType *>(P.first);
           });
       if (!SawPackTypes) {
         Info.Expand = false;



More information about the cfe-commits mailing list