llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangd

Author: Matheus Izvekov (mizvekov)

<details>
<summary>Changes</summary>

Before this patch, the application of getAs and castAs on a leaf type would 
always produce a canonical type, which is undesirable because some of these 
types can be sugared.

The user expectation is that getAs only removes top level sugar nodes, leaving 
all the type sugar on the returned node, but it had an optimization intended 
for type nodes with no sugar: for these, we can skip the expensive traversal of 
the top level sugar with a simple canonicalization followed by dyn_cast.

The problem is that the concept of leaf type does not map well to what is 
correct to apply this optimization to.

This patch replaces the concept of leaf types with 'always canonical' types, 
and only applies the canonicalization strategy on them.

In order to avoid the performance regression this would cause, as most current 
users do not care about type sugar, this patch also replaces all of these uses 
with alternative cast fucntions which operate through canonicalization.

* Introduces castAs variants to complement the getAsTagDecl and derived 
variants.
* Introduces getAsEnumDecl and castAsEnumDecl, complementing the current set, 
so that all TagDecls are covered.
* Introduces getAsCanonical and castAsCanonical, for faster casting when only 
the canonical type is desired.

The getAsTagDecl and related functions are not provided inline, because of the 
circular dependencies that would involve. So this patch causes a small overall 
performance regression:
&lt;img width="1461" height="18" alt="image" 
src="https://github.com/user-attachments/assets/061dfb14-9506-4623-91ec-0f02f585d1dd";
 /&gt;

This will be fixed in a later patch, brining the whole thing back to a positive 
performance improvement overall:
&lt;img width="1462" height="18" alt="image" 
src="https://github.com/user-attachments/assets/c237e68f-f696-44f4-acc6-a7c7ba5b0976";
 /&gt;


---

Patch is 395.08 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/155028.diff


170 Files Affected:

- (modified) clang-tools-extra/clang-doc/Serialize.cpp (+2-3) 
- (modified) 
clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp (+1-1) 
- (modified) 
clang-tools-extra/clang-tidy/bugprone/TaggedUnionMemberCountCheck.cpp (+2-9) 
- (modified) 
clang-tools-extra/clang-tidy/cert/DefaultOperatorNewAlignmentCheck.cpp (+1-1) 
- (modified) 
clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp 
(+1-1) 
- (modified) 
clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp 
(+1-1) 
- (modified) clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp 
(+2-3) 
- (modified) clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp 
(+9-14) 
- (modified) clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp (+1-1) 
- (modified) clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp 
(+1-1) 
- (modified) 
clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp (+4-3) 
- (modified) clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp 
(+1-4) 
- (modified) clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp 
(+3-4) 
- (modified) clang-tools-extra/clang-tidy/utils/TypeTraits.cpp (+2-3) 
- (modified) clang-tools-extra/clangd/Hover.cpp (+2-3) 
- (modified) clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp (+3-3) 
- (modified) clang/include/clang/AST/AbstractBasicReader.h (+1-1) 
- (modified) clang/include/clang/AST/AbstractBasicWriter.h (+1-1) 
- (modified) clang/include/clang/AST/Decl.h (+4) 
- (modified) clang/include/clang/AST/DeclCXX.h (+3-1) 
- (modified) clang/include/clang/AST/Type.h (+41-9) 
- (modified) clang/include/clang/Basic/TypeNodes.td (+9-18) 
- (modified) clang/include/clang/Sema/Sema.h (+1-1) 
- (modified) clang/lib/AST/APValue.cpp (+1-2) 
- (modified) clang/lib/AST/ASTContext.cpp (+40-60) 
- (modified) clang/lib/AST/ASTStructuralEquivalence.cpp (+2-2) 
- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+3-4) 
- (modified) clang/lib/AST/ByteCode/Context.cpp (+1-2) 
- (modified) clang/lib/AST/ByteCode/InterpBuiltin.cpp (+7-14) 
- (modified) clang/lib/AST/ByteCode/Pointer.cpp (+1-1) 
- (modified) clang/lib/AST/ByteCode/Program.cpp (+5-11) 
- (modified) clang/lib/AST/ByteCode/Record.cpp (+1-3) 
- (modified) clang/lib/AST/CXXInheritance.cpp (+11-27) 
- (modified) clang/lib/AST/Decl.cpp (+12-18) 
- (modified) clang/lib/AST/DeclCXX.cpp (+18-26) 
- (modified) clang/lib/AST/DeclTemplate.cpp (+3-3) 
- (modified) clang/lib/AST/DeclarationName.cpp (+2-2) 
- (modified) clang/lib/AST/Expr.cpp (+4-13) 
- (modified) clang/lib/AST/ExprConstant.cpp (+21-37) 
- (modified) clang/lib/AST/FormatString.cpp (+4-6) 
- (modified) clang/lib/AST/InheritViz.cpp (+2-2) 
- (modified) clang/lib/AST/ItaniumCXXABI.cpp (+1-2) 
- (modified) clang/lib/AST/ItaniumMangle.cpp (+7-10) 
- (modified) clang/lib/AST/JSONNodeDumper.cpp (+1-1) 
- (modified) clang/lib/AST/PrintfFormatString.cpp (+2-2) 
- (modified) clang/lib/AST/RecordLayoutBuilder.cpp (+15-18) 
- (modified) clang/lib/AST/ScanfFormatString.cpp (+1-2) 
- (modified) clang/lib/AST/TemplateBase.cpp (+2-2) 
- (modified) clang/lib/AST/TextNodeDumper.cpp (+1-1) 
- (modified) clang/lib/AST/Type.cpp (+94-106) 
- (modified) clang/lib/AST/TypePrinter.cpp (+1-1) 
- (modified) clang/lib/AST/VTTBuilder.cpp (+3-13) 
- (modified) clang/lib/Analysis/ExprMutationAnalyzer.cpp (+2-1) 
- (modified) clang/lib/Analysis/ThreadSafetyCommon.cpp (+5-7) 
- (modified) clang/lib/CIR/CodeGen/CIRGenCall.cpp (+3-8) 
- (modified) clang/lib/CIR/CodeGen/CIRGenClass.cpp (+3-9) 
- (modified) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+5-15) 
- (modified) clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp (+1-4) 
- (modified) clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp (+2-4) 
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+5-14) 
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.cpp (+2-6) 
- (modified) clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp (+3-2) 
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+5-12) 
- (modified) clang/lib/CIR/CodeGen/TargetInfo.cpp (+2-4) 
- (modified) clang/lib/CodeGen/ABIInfo.cpp (+1-2) 
- (modified) clang/lib/CodeGen/ABIInfoImpl.cpp (+19-26) 
- (modified) clang/lib/CodeGen/CGBlocks.cpp (+3-6) 
- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+4-5) 
- (modified) clang/lib/CodeGen/CGCUDANV.cpp (+1-2) 
- (modified) clang/lib/CodeGen/CGCXX.cpp (+3-13) 
- (modified) clang/lib/CodeGen/CGCXXABI.cpp (+1-4) 
- (modified) clang/lib/CodeGen/CGCall.cpp (+9-18) 
- (modified) clang/lib/CodeGen/CGClass.cpp (+13-47) 
- (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+2-3) 
- (modified) clang/lib/CodeGen/CGDecl.cpp (+4-8) 
- (modified) clang/lib/CodeGen/CGExpr.cpp (+9-23) 
- (modified) clang/lib/CodeGen/CGExprAgg.cpp (+12-22) 
- (modified) clang/lib/CodeGen/CGExprCXX.cpp (+8-13) 
- (modified) clang/lib/CodeGen/CGExprConstant.cpp (+10-26) 
- (modified) clang/lib/CodeGen/CGExprScalar.cpp (+3-7) 
- (modified) clang/lib/CodeGen/CGNonTrivialStruct.cpp (+3-3) 
- (modified) clang/lib/CodeGen/CGObjC.cpp (+2-4) 
- (modified) clang/lib/CodeGen/CGObjCMac.cpp (+8-9) 
- (modified) clang/lib/CodeGen/CGObjCRuntime.cpp (+2-4) 
- (modified) clang/lib/CodeGen/CGOpenMPRuntime.cpp (+12-17) 
- (modified) clang/lib/CodeGen/CodeGenFunction.cpp (+3-8) 
- (modified) clang/lib/CodeGen/CodeGenFunction.h (+1-3) 
- (modified) clang/lib/CodeGen/CodeGenModule.cpp (+3-3) 
- (modified) clang/lib/CodeGen/CodeGenTBAA.cpp (+4-5) 
- (modified) clang/lib/CodeGen/CodeGenTypes.cpp (+7-13) 
- (modified) clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp (+13-15) 
- (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+18-36) 
- (modified) clang/lib/CodeGen/SwiftCallingConv.cpp (+1-1) 
- (modified) clang/lib/CodeGen/Targets/AArch64.cpp (+7-9) 
- (modified) clang/lib/CodeGen/Targets/AMDGPU.cpp (+7-12) 
- (modified) clang/lib/CodeGen/Targets/ARC.cpp (+3-3) 
- (modified) clang/lib/CodeGen/Targets/ARM.cpp (+7-9) 
- (modified) clang/lib/CodeGen/Targets/BPF.cpp (+4-5) 
- (modified) clang/lib/CodeGen/Targets/CSKY.cpp (+2-2) 
- (modified) clang/lib/CodeGen/Targets/Hexagon.cpp (+4-5) 
- (modified) clang/lib/CodeGen/Targets/Lanai.cpp (+3-3) 
- (modified) clang/lib/CodeGen/Targets/LoongArch.cpp (+5-8) 
- (modified) clang/lib/CodeGen/Targets/Mips.cpp (+6-6) 
- (modified) clang/lib/CodeGen/Targets/NVPTX.cpp (+6-7) 
- (modified) clang/lib/CodeGen/Targets/PPC.cpp (+5-8) 
- (modified) clang/lib/CodeGen/Targets/RISCV.cpp (+5-8) 
- (modified) clang/lib/CodeGen/Targets/SPIR.cpp (+7-12) 
- (modified) clang/lib/CodeGen/Targets/Sparc.cpp (+2-2) 
- (modified) clang/lib/CodeGen/Targets/SystemZ.cpp (+6-10) 
- (modified) clang/lib/CodeGen/Targets/WebAssembly.cpp (+2-4) 
- (modified) clang/lib/CodeGen/Targets/X86.cpp (+31-46) 
- (modified) clang/lib/CodeGen/Targets/XCore.cpp (+1-1) 
- (modified) clang/lib/Edit/RewriteObjCFoundationAPI.cpp (+1-1) 
- (modified) clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp (+24-37) 
- (modified) clang/lib/Frontend/Rewrite/RewriteObjC.cpp (+1-4) 
- (modified) clang/lib/Index/IndexTypeSourceInfo.cpp (+1-1) 
- (modified) clang/lib/Index/USRGeneration.cpp (+2-1) 
- (modified) clang/lib/Interpreter/InterpreterValuePrinter.cpp (+4-8) 
- (modified) clang/lib/Interpreter/Value.cpp (+8-11) 
- (modified) clang/lib/Sema/Sema.cpp (+15-18) 
- (modified) clang/lib/Sema/SemaAccess.cpp (+3-8) 
- (modified) clang/lib/Sema/SemaBPF.cpp (+4-10) 
- (modified) clang/lib/Sema/SemaCUDA.cpp (+5-12) 
- (modified) clang/lib/Sema/SemaCXXScopeSpec.cpp (+2-5) 
- (modified) clang/lib/Sema/SemaCast.cpp (+14-16) 
- (modified) clang/lib/Sema/SemaChecking.cpp (+31-65) 
- (modified) clang/lib/Sema/SemaCodeComplete.cpp (+3-10) 
- (modified) clang/lib/Sema/SemaDecl.cpp (+71-94) 
- (modified) clang/lib/Sema/SemaDeclAttr.cpp (+25-31) 
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+38-65) 
- (modified) clang/lib/Sema/SemaDeclObjC.cpp (+9-18) 
- (modified) clang/lib/Sema/SemaExceptionSpec.cpp (+2-3) 
- (modified) clang/lib/Sema/SemaExpr.cpp (+30-40) 
- (modified) clang/lib/Sema/SemaExprCXX.cpp (+14-26) 
- (modified) clang/lib/Sema/SemaExprObjC.cpp (+2-3) 
- (modified) clang/lib/Sema/SemaHLSL.cpp (+29-35) 
- (modified) clang/lib/Sema/SemaInit.cpp (+90-136) 
- (modified) clang/lib/Sema/SemaLambda.cpp (+2-3) 
- (modified) clang/lib/Sema/SemaLookup.cpp (+6-13) 
- (modified) clang/lib/Sema/SemaObjC.cpp (+2-2) 
- (modified) clang/lib/Sema/SemaObjCProperty.cpp (+2-4) 
- (modified) clang/lib/Sema/SemaOpenMP.cpp (+3-3) 
- (modified) clang/lib/Sema/SemaOverload.cpp (+29-46) 
- (modified) clang/lib/Sema/SemaPPC.cpp (+1-4) 
- (modified) clang/lib/Sema/SemaStmt.cpp (+6-9) 
- (modified) clang/lib/Sema/SemaStmtAsm.cpp (+8-8) 
- (modified) clang/lib/Sema/SemaSwift.cpp (+7-9) 
- (modified) clang/lib/Sema/SemaTemplate.cpp (+13-14) 
- (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+9-9) 
- (modified) clang/lib/Sema/SemaTemplateDeductionGuide.cpp (+3-3) 
- (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+5-9) 
- (modified) clang/lib/Sema/SemaType.cpp (+5-13) 
- (modified) clang/lib/Sema/SemaTypeTraits.cpp (+9-11) 
- (modified) clang/lib/Sema/TreeTransform.h (+17-25) 
- (modified) clang/lib/Sema/UsedDeclVisitor.h (+4-6) 
- (modified) clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp (+2-3) 
- (modified) clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp 
(+2-9) 
- (modified) clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp 
(+6-12) 
- (modified) clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp (+3-3) 
- (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
(+1-1) 
- (modified) clang/lib/StaticAnalyzer/Core/ExprEngine.cpp (+1-1) 
- (modified) clang/lib/StaticAnalyzer/Core/RegionStore.cpp (+2-4) 
- (modified) clang/test/CXX/drs/cwg0xx.cpp (+2-2) 
- (modified) clang/test/CXX/drs/cwg3xx.cpp (+1-1) 
- (modified) clang/test/ExtractAPI/class_template_param_inheritance.cpp (+1-1) 
- (modified) clang/tools/libclang/CIndex.cpp (+1-1) 
- (modified) clang/unittests/AST/ASTImporterTest.cpp (+1-3) 
- (modified) clang/unittests/AST/RandstructTest.cpp (+1-2) 
- (modified) clang/utils/TableGen/ASTTableGen.h (+1-1) 
- (modified) clang/utils/TableGen/ClangTypeNodesEmitter.cpp (+13-11) 


``````````diff
diff --git a/clang-tools-extra/clang-doc/Serialize.cpp 
b/clang-tools-extra/clang-doc/Serialize.cpp
index bcab4f1b8a729..506cc0a3b0e8f 100644
--- a/clang-tools-extra/clang-doc/Serialize.cpp
+++ b/clang-tools-extra/clang-doc/Serialize.cpp
@@ -901,9 +901,8 @@ parseBases(RecordInfo &I, const CXXRecordDecl *D, bool 
IsFileInRootDir,
   if (!D->isThisDeclarationADefinition())
     return;
   for (const CXXBaseSpecifier &B : D->bases()) {
-    if (const RecordType *Ty = B.getType()->getAs<RecordType>()) {
-      if (const CXXRecordDecl *Base = cast_or_null<CXXRecordDecl>(
-              Ty->getOriginalDecl()->getDefinition())) {
+    if (const auto *Base = B.getType()->getAsCXXRecordDecl()) {
+      if (Base->isCompleteDefinition()) {
         // Initialized without USR and name, this will be set in the following
         // if-else stmt.
         BaseRecordInfo BI(
diff --git 
a/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp
index 7f1eeef8ea0fd..3c718f1ddbe95 100644
--- a/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp
@@ -997,7 +997,7 @@ approximateStandardConversionSequence(const TheCheck 
&Check, QualType From,
     WorkType = QualType{ToBuiltin, FastQualifiersToApply};
   }
 
-  const auto *FromEnum = WorkType->getAs<EnumType>();
+  const auto *FromEnum = WorkType->getAsCanonical<EnumType>();
   const auto *ToEnum = To->getAs<EnumType>();
   if (FromEnum && ToNumeric && FromEnum->isUnscopedEnumerationType()) {
     // Unscoped enumerations (or enumerations in C) convert to numerics.
diff --git 
a/clang-tools-extra/clang-tidy/bugprone/TaggedUnionMemberCountCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/TaggedUnionMemberCountCheck.cpp
index ddbb14e3ac62b..02f4421efdbf4 100644
--- a/clang-tools-extra/clang-tidy/bugprone/TaggedUnionMemberCountCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/TaggedUnionMemberCountCheck.cpp
@@ -169,15 +169,8 @@ void TaggedUnionMemberCountCheck::check(
   if (!Root || !UnionField || !TagField)
     return;
 
-  const auto *UnionDef =
-      UnionField->getType().getCanonicalType().getTypePtr()->getAsRecordDecl();
-  const auto *EnumDef = llvm::dyn_cast<EnumDecl>(
-      TagField->getType().getCanonicalType().getTypePtr()->getAsTagDecl());
-
-  assert(UnionDef && "UnionDef is missing!");
-  assert(EnumDef && "EnumDef is missing!");
-  if (!UnionDef || !EnumDef)
-    return;
+  const auto *UnionDef = UnionField->getType()->castAsRecordDecl();
+  const auto *EnumDef = TagField->getType()->castAsEnumDecl();
 
   const std::size_t UnionMemberCount = llvm::range_size(UnionDef->fields());
   auto [TagCount, CountingEnumConstantDecl] = getNumberOfEnumValues(EnumDef);
diff --git 
a/clang-tools-extra/clang-tidy/cert/DefaultOperatorNewAlignmentCheck.cpp 
b/clang-tools-extra/clang-tidy/cert/DefaultOperatorNewAlignmentCheck.cpp
index 2a0d0ada42b28..2c2248afb69e7 100644
--- a/clang-tools-extra/clang-tidy/cert/DefaultOperatorNewAlignmentCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cert/DefaultOperatorNewAlignmentCheck.cpp
@@ -31,7 +31,7 @@ void DefaultOperatorNewAlignmentCheck::check(
     return;
   const TagDecl *D = T->getAsTagDecl();
   // Alignment can not be obtained for undefined type.
-  if (!D || !D->getDefinition() || !D->isCompleteDefinition())
+  if (!D || !D->isCompleteDefinition())
     return;
 
   ASTContext &Context = D->getASTContext();
diff --git 
a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp 
b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
index 82d1cf13440bc..75da6de9b5f13 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
@@ -45,7 +45,7 @@ AST_MATCHER(ParmVarDecl, isTemplateTypeParameter) {
 
   QualType ParamType =
       Node.getType().getNonPackExpansionType()->getPointeeType();
-  const auto *TemplateType = ParamType->getAs<TemplateTypeParmType>();
+  const auto *TemplateType = ParamType->getAsCanonical<TemplateTypeParmType>();
   if (!TemplateType)
     return false;
 
diff --git 
a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp 
b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
index 40607597297b5..e6e79f0f0342a 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
@@ -189,7 +189,7 @@ struct InitializerInsertion {
 
 // Convenience utility to get a RecordDecl from a QualType.
 const RecordDecl *getCanonicalRecordDecl(const QualType &Type) {
-  if (const auto *RT = Type.getCanonicalType()->getAs<RecordType>())
+  if (const auto *RT = Type->getAsCanonical<RecordType>())
     return RT->getOriginalDecl();
   return nullptr;
 }
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp 
b/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp
index 40fd15c08f0a1..6508bfd5ca808 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp
@@ -90,9 +90,8 @@ void SlicingCheck::diagnoseSlicedOverriddenMethods(
   }
   // Recursively process bases.
   for (const auto &Base : DerivedDecl.bases()) {
-    if (const auto *BaseRecordType = Base.getType()->getAs<RecordType>()) {
-      if (const auto *BaseRecord = cast_or_null<CXXRecordDecl>(
-              BaseRecordType->getOriginalDecl()->getDefinition()))
+    if (const auto *BaseRecord = Base.getType()->getAsCXXRecordDecl()) {
+      if (BaseRecord->isCompleteDefinition())
         diagnoseSlicedOverriddenMethods(Call, *BaseRecord, BaseDecl);
     }
   }
diff --git a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp 
b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp
index 0302a5ad4957c..36b6007b58a51 100644
--- a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp
+++ b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp
@@ -71,13 +71,10 @@ bool MultipleInheritanceCheck::isInterface(const 
CXXRecordDecl *Node) {
   for (const auto &I : Node->bases()) {
     if (I.isVirtual())
       continue;
-    const auto *Ty = I.getType()->getAs<RecordType>();
-    if (!Ty)
+    const auto *Base = I.getType()->getAsCXXRecordDecl();
+    if (!Base)
       continue;
-    const RecordDecl *D = Ty->getOriginalDecl()->getDefinition();
-    if (!D)
-      continue;
-    const auto *Base = cast<CXXRecordDecl>(D);
+    assert(Base->isCompleteDefinition());
     if (!isInterface(Base)) {
       addNodeToInterfaceMap(Node, false);
       return false;
@@ -103,11 +100,10 @@ void MultipleInheritanceCheck::check(const 
MatchFinder::MatchResult &Result) {
     for (const auto &I : D->bases()) {
       if (I.isVirtual())
         continue;
-      const auto *Ty = I.getType()->getAs<RecordType>();
-      if (!Ty)
+      const auto *Base = I.getType()->getAsCXXRecordDecl();
+      if (!Base)
         continue;
-      const auto *Base =
-          cast<CXXRecordDecl>(Ty->getOriginalDecl()->getDefinition());
+      assert(Base->isCompleteDefinition());
       if (!isInterface(Base))
         NumConcrete++;
     }
@@ -115,11 +111,10 @@ void MultipleInheritanceCheck::check(const 
MatchFinder::MatchResult &Result) {
     // Check virtual bases to see if there is more than one concrete
     // non-virtual base.
     for (const auto &V : D->vbases()) {
-      const auto *Ty = V.getType()->getAs<RecordType>();
-      if (!Ty)
+      const auto *Base = V.getType()->getAsCXXRecordDecl();
+      if (!Base)
         continue;
-      const auto *Base =
-          cast<CXXRecordDecl>(Ty->getOriginalDecl()->getDefinition());
+      assert(Base->isCompleteDefinition());
       if (!isInterface(Base))
         NumConcrete++;
     }
diff --git a/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp 
b/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
index 8211a0ec6a5e1..49432073ce1d7 100644
--- a/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
@@ -131,7 +131,7 @@ void UnusedUsingDeclsCheck::check(const 
MatchFinder::MatchResult &Result) {
       return;
     }
     if (const auto *ECD = dyn_cast<EnumConstantDecl>(Used)) {
-      if (const auto *ET = ECD->getType()->getAs<EnumType>())
+      if (const auto *ET = ECD->getType()->getAsCanonical<EnumType>())
         removeFromFoundDecls(ET->getOriginalDecl());
     }
   };
diff --git a/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp
index 5310f2fd25381..c74db0ed861b4 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp
@@ -28,7 +28,7 @@ static bool isLockGuardDecl(const NamedDecl *Decl) {
 }
 
 static bool isLockGuard(const QualType &Type) {
-  if (const auto *Record = Type->getAs<RecordType>())
+  if (const auto *Record = Type->getAsCanonical<RecordType>())
     if (const RecordDecl *Decl = Record->getOriginalDecl())
       return isLockGuardDecl(Decl);
 
diff --git 
a/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp
index 447c2437666cf..a80637dee18f4 100644
--- a/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp
@@ -413,10 +413,11 @@ static bool areTypesCompatible(QualType ArgType, QualType 
ParamType,
 
   // Arithmetic types are interconvertible, except scoped enums.
   if (ParamType->isArithmeticType() && ArgType->isArithmeticType()) {
-    if ((ParamType->isEnumeralType() &&
-         ParamType->castAs<EnumType>()->getOriginalDecl()->isScoped()) ||
+    if ((ParamType->isEnumeralType() && ParamType->castAsCanonical<EnumType>()
+                                            ->getOriginalDecl()
+                                            ->isScoped()) ||
         (ArgType->isEnumeralType() &&
-         ArgType->castAs<EnumType>()->getOriginalDecl()->isScoped()))
+         ArgType->castAsCanonical<EnumType>()->getOriginalDecl()->isScoped()))
       return false;
 
     return true;
diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp 
b/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp
index aa6aefcf0c493..4314817e4f69d 100644
--- a/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp
+++ b/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp
@@ -66,10 +66,7 @@ ExceptionSpecAnalyzer::analyzeBase(const CXXBaseSpecifier 
&Base,
   if (!RecType)
     return State::Unknown;
 
-  const auto *BaseClass =
-      cast<CXXRecordDecl>(RecType->getOriginalDecl())->getDefinitionOrSelf();
-
-  return analyzeRecord(BaseClass, Kind);
+  return analyzeRecord(RecType->getAsCXXRecordDecl(), Kind);
 }
 
 ExceptionSpecAnalyzer::State
diff --git a/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp 
b/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
index 0df8e913100fc..0d0834dc38fc6 100644
--- a/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
+++ b/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
@@ -460,10 +460,9 @@ bool FormatStringConverter::emitIntegerArgument(
     // be passed as its underlying type. However, printf will have forced
     // the signedness based on the format string, so we need to do the
     // same.
-    if (const auto *ET = ArgType->getAs<EnumType>()) {
-      if (const std::optional<std::string> MaybeCastType = castTypeForArgument(
-              ArgKind,
-              ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType()))
+    if (const auto *ED = ArgType->getAsEnumDecl()) {
+      if (const std::optional<std::string> MaybeCastType =
+              castTypeForArgument(ArgKind, ED->getIntegerType()))
         ArgFixes.emplace_back(
             ArgIndex, (Twine("static_cast<") + *MaybeCastType + ">(").str());
       else
diff --git a/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp 
b/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp
index 5518afd32e7f0..f944306171135 100644
--- a/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp
+++ b/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp
@@ -119,9 +119,8 @@ bool isTriviallyDefaultConstructible(QualType Type, const 
ASTContext &Context) {
   if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
     return true;
 
-  if (const auto *RT = CanonicalType->getAs<RecordType>()) {
-    return recordIsTriviallyDefaultConstructible(
-        *RT->getOriginalDecl()->getDefinitionOrSelf(), Context);
+  if (const auto *RD = CanonicalType->getAsRecordDecl()) {
+    return recordIsTriviallyDefaultConstructible(*RD, Context);
   }
 
   // No other types can match.
diff --git a/clang-tools-extra/clangd/Hover.cpp 
b/clang-tools-extra/clangd/Hover.cpp
index a7cf45c632827..6e45c9ae4f8bf 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -454,8 +454,7 @@ std::optional<std::string> printExprValue(const Expr *E,
       Constant.Val.getInt().getSignificantBits() <= 64) {
     // Compare to int64_t to avoid bit-width match requirements.
     int64_t Val = Constant.Val.getInt().getExtValue();
-    for (const EnumConstantDecl *ECD :
-         T->castAs<EnumType>()->getOriginalDecl()->enumerators())
+    for (const EnumConstantDecl *ECD : T->castAsEnumDecl()->enumerators())
       if (ECD->getInitVal() == Val)
         return llvm::formatv("{0} ({1})", ECD->getNameAsString(),
                              printHex(Constant.Val.getInt()))
@@ -832,7 +831,7 @@ std::optional<HoverInfo> getThisExprHoverContents(const 
CXXThisExpr *CTE,
                                                   ASTContext &ASTCtx,
                                                   const PrintingPolicy &PP) {
   QualType OriginThisType = CTE->getType()->getPointeeType();
-  QualType ClassType = declaredType(OriginThisType->getAsTagDecl());
+  QualType ClassType = declaredType(OriginThisType->castAsTagDecl());
   // For partial specialization class, origin `this` pointee type will be
   // parsed as `InjectedClassNameType`, which will ouput template arguments
   // like "type-parameter-0-0". So we retrieve user written class type in this
diff --git a/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp 
b/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
index 7e616968c6046..2c9841762b869 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
@@ -113,11 +113,11 @@ bool PopulateSwitch::prepare(const Selection &Sel) {
   // Ignore implicit casts, since enums implicitly cast to integer types.
   Cond = Cond->IgnoreParenImpCasts();
   // Get the canonical type to handle typedefs.
-  EnumT = Cond->getType().getCanonicalType()->getAsAdjusted<EnumType>();
+  EnumT = Cond->getType()->getAsCanonical<EnumType>();
   if (!EnumT)
     return false;
-  EnumD = EnumT->getOriginalDecl();
-  if (!EnumD || EnumD->isDependentType())
+  EnumD = EnumT->getOriginalDecl()->getDefinitionOrSelf();
+  if (EnumD->isDependentType())
     return false;
 
   // Finally, check which cases exist and which are covered.
diff --git a/clang/include/clang/AST/AbstractBasicReader.h 
b/clang/include/clang/AST/AbstractBasicReader.h
index 26052b8086cf7..0d187eb49d6ca 100644
--- a/clang/include/clang/AST/AbstractBasicReader.h
+++ b/clang/include/clang/AST/AbstractBasicReader.h
@@ -193,7 +193,7 @@ class DataStreamBasicReader : public BasicReaderBase<Impl> {
     auto elemTy = origTy;
     unsigned pathLength = asImpl().readUInt32();
     for (unsigned i = 0; i < pathLength; ++i) {
-      if (elemTy->template getAs<RecordType>()) {
+      if (elemTy->isRecordType()) {
         unsigned int_ = asImpl().readUInt32();
         Decl *decl = asImpl().template readDeclAs<Decl>();
         if (auto *recordDecl = dyn_cast<CXXRecordDecl>(decl))
diff --git a/clang/include/clang/AST/AbstractBasicWriter.h 
b/clang/include/clang/AST/AbstractBasicWriter.h
index d41e655986ef9..8ea0c29cf5070 100644
--- a/clang/include/clang/AST/AbstractBasicWriter.h
+++ b/clang/include/clang/AST/AbstractBasicWriter.h
@@ -176,7 +176,7 @@ class DataStreamBasicWriter : public BasicWriterBase<Impl> {
     asImpl().writeUInt32(path.size());
     auto &ctx = ((BasicWriterBase<Impl> *)this)->getASTContext();
     for (auto elem : path) {
-      if (elemTy->getAs<RecordType>()) {
+      if (elemTy->isRecordType()) {
         asImpl().writeUInt32(elem.getAsBaseOrMember().getInt());
         const Decl *baseOrMember = elem.getAsBaseOrMember().getPointer();
         if (const auto *recordDecl = dyn_cast<CXXRecordDecl>(baseOrMember)) {
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index bebbde3661a33..79636a67dafba 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -3915,6 +3915,10 @@ class TagDecl : public TypeDecl,
   bool isUnion() const { return getTagKind() == TagTypeKind::Union; }
   bool isEnum() const { return getTagKind() == TagTypeKind::Enum; }
 
+  bool isStructureOrClass() const {
+    return isStruct() || isClass() || isInterface();
+  }
+
   /// Is this tag type named, either directly or via being defined in
   /// a typedef of this type?
   ///
diff --git a/clang/include/clang/AST/DeclCXX.h 
b/clang/include/clang/AST/DeclCXX.h
index 1d2ef0f4f2319..3ee03122f50cf 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -3825,7 +3825,9 @@ class UsingEnumDecl : public BaseUsingDecl, public 
Mergeable<UsingEnumDecl> {
   void setEnumType(TypeSourceInfo *TSI) { EnumType = TSI; }
 
 public:
-  EnumDecl *getEnumDecl() const { return 
cast<EnumDecl>(EnumType->getType()->getAsTagDecl()); }
+  EnumDecl *getEnumDecl() const {
+    return cast<clang::EnumType>(EnumType->getType())->getOriginalDecl();
+  }
 
   static UsingEnumDecl *Create(ASTContext &C, DeclContext *DC,
                                SourceLocation UsingL, SourceLocation EnumL,
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index adf5cb0462154..5b78da5c52e4a 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -2883,14 +2883,23 @@ class alignas(TypeAlignment) Type : public 
ExtQualsTypeCommonBase {
   /// because the type is a RecordType or because it is the injected-class-name
   /// type of a class template or class template partial specialization.
   CXXRecordDecl *getAsCXXRecordDecl() const;
+  CXXRecordDecl *castAsCXXRecordDecl() const;
 
   /// Retrieves the RecordDecl this type refers to.
   RecordDecl *getAsRecordDecl() const;
+  RecordDecl *castAsRecordDecl() const;
+
+  /// Retrieves the TagDecl that this type refers to, either
+  /// because the type is a TagType or because it is the injected-class-name
+  /// type of a class template or class template partial specialization.
+  EnumDecl *getAsEnumDecl() const;
+  EnumDecl *castAsEnumDecl() const;
 
   /// Retrieves the TagDecl that this type refers to, either
   /// because the type is a TagType or because it is the injected-class-name
   /// type of a class template or class template partial specialization.
   TagDecl *getAsTagDecl() const;
+  TagDecl *castAsTagDecl() const;
 
   /// If this is a pointer or reference to a RecordType, return the
   /// CXXRecordDecl that the type refers to.
@@ -2922,8 +2931,31 @@ class alignas(TypeAlignment) Type : public 
ExtQualsTypeCommonBase {
   ///
   /// There are some specializations of this member template listed
   /// immediately following this class.
+  ///
+  /// If you are interested only in the canonical properties of this type,
+  /// consider using getAsCanonical instead, as that is much faster.
   template <typename T> const T *getAs() const;
 
+  /// If this type is canonically the specified type, return its canonical type
+  /// cast to that specified type, otherwise returns null.
+  template <typename T> const T *getAsCanonical() const {
+    return dyn_cast<T>(CanonicalType);
+  }
+
+  /// Return this type's canonical type cast to the specified type.
+  /// If the...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/155028
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to