https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/155028
>From 63542d5cdeccb17b9125430d0a984f45d58e208c Mon Sep 17 00:00:00 2001 From: Matheus Izvekov <mizve...@gmail.com> Date: Fri, 22 Aug 2025 19:10:05 -0300 Subject: [PATCH 1/2] meat and potatoes --- clang/include/clang/AST/Type.h | 41 +++++++++++++++---- clang/include/clang/Basic/TypeNodes.td | 27 ++++-------- clang/lib/AST/Type.cpp | 6 +-- clang/test/CXX/drs/cwg0xx.cpp | 4 +- clang/test/CXX/drs/cwg3xx.cpp | 2 +- .../class_template_param_inheritance.cpp | 2 +- clang/utils/TableGen/ASTTableGen.h | 2 +- .../utils/TableGen/ClangTypeNodesEmitter.cpp | 24 ++++++----- 8 files changed, 61 insertions(+), 47 deletions(-) diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 187e54f5cb54b..8236a14a2daef 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2929,8 +2929,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 type is not canonically that specified type, the behaviour is + /// undefined. + template <typename T> const T *castAsCanonical() const { + return cast<T>(CanonicalType); + } + +// It is not helpful to use these on types which are never canonical +#define TYPE(Class, Base) +#define NEVER_CANONICAL_TYPE(Class) \ + template <> inline const Class##Type *Type::getAsCanonical() const = delete; \ + template <> inline const Class##Type *Type::castAsCanonical() const = delete; +#include "clang/AST/TypeNodes.inc" + /// Look through sugar for an instance of TemplateSpecializationType which /// is not a type alias, or null if there is no such type. /// This is used when you want as-written template arguments or the template @@ -3142,16 +3165,16 @@ template <> const BoundsAttributedType *Type::getAs() const; /// sugar until it reaches an CountAttributedType or a non-sugared type. template <> const CountAttributedType *Type::getAs() const; -// We can do canonical leaf types faster, because we don't have to -// worry about preserving child type decoration. +// We can do always canonical types faster, because we don't have to +// worry about preserving decoration. #define TYPE(Class, Base) -#define LEAF_TYPE(Class) \ -template <> inline const Class##Type *Type::getAs() const { \ - return dyn_cast<Class##Type>(CanonicalType); \ -} \ -template <> inline const Class##Type *Type::castAs() const { \ - return cast<Class##Type>(CanonicalType); \ -} +#define ALWAYS_CANONICAL_TYPE(Class) \ + template <> inline const Class##Type *Type::getAs() const { \ + return dyn_cast<Class##Type>(CanonicalType); \ + } \ + template <> inline const Class##Type *Type::castAs() const { \ + return cast<Class##Type>(CanonicalType); \ + } #include "clang/AST/TypeNodes.inc" /// This class is used for builtin types like 'int'. Builtin diff --git a/clang/include/clang/Basic/TypeNodes.td b/clang/include/clang/Basic/TypeNodes.td index c8d45dec78816..fb6862b90987f 100644 --- a/clang/include/clang/Basic/TypeNodes.td +++ b/clang/include/clang/Basic/TypeNodes.td @@ -37,21 +37,12 @@ class NeverCanonical {} /// canonical types can ignore these nodes. class NeverCanonicalUnlessDependent {} -/// A type node which never has component type structure. Some code may be -/// able to operate on leaf types faster than they can on non-leaf types. -/// -/// For example, the function type `void (int)` is not a leaf type because it -/// is structurally composed of component types (`void` and `int`). -/// -/// A struct type is a leaf type because its field types are not part of its -/// type-expression. -/// -/// Nodes like `TypedefType` which are syntactically leaves but can desugar -/// to types that may not be leaves should not declare this. -class LeafType {} +/// A type node which is always a canonical type, that is, types for which +/// `T.getCanonicalType() == T` always holds. +class AlwaysCanonical {} def Type : TypeNode<?, 1>; -def BuiltinType : TypeNode<Type>, LeafType; +def BuiltinType : TypeNode<Type>, AlwaysCanonical; def ComplexType : TypeNode<Type>; def PointerType : TypeNode<Type>; def BlockPointerType : TypeNode<Type>; @@ -88,14 +79,14 @@ def TypeOfType : TypeNode<Type>, NeverCanonicalUnlessDependent; def DecltypeType : TypeNode<Type>, NeverCanonicalUnlessDependent; def UnaryTransformType : TypeNode<Type>, NeverCanonicalUnlessDependent; def TagType : TypeNode<Type, 1>; -def RecordType : TypeNode<TagType>, LeafType; -def EnumType : TypeNode<TagType>, LeafType; -def InjectedClassNameType : TypeNode<TagType>, AlwaysDependent, LeafType; +def RecordType : TypeNode<TagType>; +def EnumType : TypeNode<TagType>; +def InjectedClassNameType : TypeNode<TagType>, AlwaysDependent; def AttributedType : TypeNode<Type>, NeverCanonical; def BTFTagAttributedType : TypeNode<Type>, NeverCanonical; def HLSLAttributedResourceType : TypeNode<Type>; def HLSLInlineSpirvType : TypeNode<Type>; -def TemplateTypeParmType : TypeNode<Type>, AlwaysDependent, LeafType; +def TemplateTypeParmType : TypeNode<Type>, AlwaysDependent; def SubstTemplateTypeParmType : TypeNode<Type>, NeverCanonical; def SubstPackType : TypeNode<Type, 1>; def SubstTemplateTypeParmPackType : TypeNode<SubstPackType>, AlwaysDependent; @@ -110,7 +101,7 @@ def PackExpansionType : TypeNode<Type>, AlwaysDependent; def PackIndexingType : TypeNode<Type>, NeverCanonicalUnlessDependent; def ObjCTypeParamType : TypeNode<Type>, NeverCanonical; def ObjCObjectType : TypeNode<Type>; -def ObjCInterfaceType : TypeNode<ObjCObjectType>, LeafType; +def ObjCInterfaceType : TypeNode<ObjCObjectType>, AlwaysCanonical; def ObjCObjectPointerType : TypeNode<Type>; def BoundsAttributedType : TypeNode<Type, 1>; def CountAttributedType : TypeNode<BoundsAttributedType>, NeverCanonical; diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index b0f865bab5d77..ea5e39740bb08 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -704,10 +704,8 @@ bool Type::isInterfaceType() const { } bool Type::isStructureOrClassType() const { - if (const auto *RT = getAs<RecordType>()) { - RecordDecl *RD = RT->getOriginalDecl(); - return RD->isStruct() || RD->isClass() || RD->isInterface(); - } + if (const auto *RT = getAsCanonical<RecordType>()) + return RT->getOriginalDecl()->isStructureOrClass(); return false; } diff --git a/clang/test/CXX/drs/cwg0xx.cpp b/clang/test/CXX/drs/cwg0xx.cpp index 9aeee7a76903d..805be67f2dc1a 100644 --- a/clang/test/CXX/drs/cwg0xx.cpp +++ b/clang/test/CXX/drs/cwg0xx.cpp @@ -244,7 +244,7 @@ namespace cwg16 { // cwg16: 2.8 // expected-error@#cwg16-A-f-call {{'A' is a private member of 'cwg16::A'}} // expected-note@#cwg16-B {{constrained by implicitly private inheritance here}} // expected-note@#cwg16-A {{member is declared here}} - // expected-error@#cwg16-A-f-call {{cannot cast 'cwg16::C' to its private base class 'cwg16::A'}} + // expected-error@#cwg16-A-f-call {{cannot cast 'cwg16::C' to its private base class 'A'}} // expected-note@#cwg16-B {{implicitly declared private here}} } }; @@ -838,7 +838,7 @@ namespace cwg52 { // cwg52: 2.8 // expected-error@#cwg52-k {{'A' is a private member of 'cwg52::A'}} // expected-note@#cwg52-B {{constrained by private inheritance here}} // expected-note@#cwg52-A {{member is declared here}} - // expected-error@#cwg52-k {{cannot cast 'struct B' to its private base class 'cwg52::A'}} + // expected-error@#cwg52-k {{cannot cast 'struct B' to its private base class 'A'}} // expected-note@#cwg52-B {{declared private here}} } // namespace cwg52 diff --git a/clang/test/CXX/drs/cwg3xx.cpp b/clang/test/CXX/drs/cwg3xx.cpp index 5d09697a3cf6b..bbd87c060801a 100644 --- a/clang/test/CXX/drs/cwg3xx.cpp +++ b/clang/test/CXX/drs/cwg3xx.cpp @@ -1321,7 +1321,7 @@ namespace cwg381 { // cwg381: 2.7 void f() { E e; e.B::a = 0; - /* expected-error@-1 {{ambiguous conversion from derived class 'E' to base class 'cwg381::B': + /* expected-error@-1 {{ambiguous conversion from derived class 'E' to base class 'B': struct cwg381::E -> C -> B struct cwg381::E -> D -> B}} */ F f; diff --git a/clang/test/ExtractAPI/class_template_param_inheritance.cpp b/clang/test/ExtractAPI/class_template_param_inheritance.cpp index 53b331e0b460b..5f0056456c730 100644 --- a/clang/test/ExtractAPI/class_template_param_inheritance.cpp +++ b/clang/test/ExtractAPI/class_template_param_inheritance.cpp @@ -44,7 +44,7 @@ template<typename T> class Foo : public T {}; { "kind": "inheritsFrom", "source": "c:@ST>1#T@Foo", - "target": "", + "target": "c:input.h@9", "targetFallback": "T" } ], diff --git a/clang/utils/TableGen/ASTTableGen.h b/clang/utils/TableGen/ASTTableGen.h index 02b97636cf5f2..e9a86f3d5edd3 100644 --- a/clang/utils/TableGen/ASTTableGen.h +++ b/clang/utils/TableGen/ASTTableGen.h @@ -38,7 +38,7 @@ #define AlwaysDependentClassName "AlwaysDependent" #define NeverCanonicalClassName "NeverCanonical" #define NeverCanonicalUnlessDependentClassName "NeverCanonicalUnlessDependent" -#define LeafTypeClassName "LeafType" +#define AlwaysCanonicalTypeClassName "AlwaysCanonical" // Cases of various non-ASTNode structured types like DeclarationName. #define TypeKindClassName "PropertyTypeKind" diff --git a/clang/utils/TableGen/ClangTypeNodesEmitter.cpp b/clang/utils/TableGen/ClangTypeNodesEmitter.cpp index 37039361cfc22..2e1eaef6c1823 100644 --- a/clang/utils/TableGen/ClangTypeNodesEmitter.cpp +++ b/clang/utils/TableGen/ClangTypeNodesEmitter.cpp @@ -40,8 +40,9 @@ // There is a sixth macro, independent of the others. Most clients // will not need to use it. // -// LEAF_TYPE(Class) - A type that never has inner types. Clients -// which can operate on such types more efficiently may wish to do so. +// ALWAYS_CANONICAL_TYPE(Class) - A type which is always identical to its +// canonical type. Clients which can operate on such types more efficiently +// may wish to do so. // //===----------------------------------------------------------------------===// @@ -66,7 +67,7 @@ using namespace clang::tblgen; #define NonCanonicalUnlessDependentTypeMacroName "NON_CANONICAL_UNLESS_DEPENDENT_TYPE" #define TypeMacroArgs "(Class, Base)" #define LastTypeMacroName "LAST_TYPE" -#define LeafTypeMacroName "LEAF_TYPE" +#define AlwaysCanonicalTypeMacroName "ALWAYS_CANONICAL_TYPE" #define TypeClassName "Type" @@ -90,7 +91,7 @@ class TypeNodeEmitter { void emitNodeInvocations(); void emitLastNodeInvocation(TypeNode lastType); - void emitLeafNodeInvocations(); + void emitAlwaysCanonicalNodeInvocations(); void addMacroToUndef(StringRef macroName); void emitUndefs(); @@ -109,12 +110,12 @@ void TypeNodeEmitter::emit() { emitFallbackDefine(AbstractTypeMacroName, TypeMacroName, TypeMacroArgs); emitFallbackDefine(NonCanonicalTypeMacroName, TypeMacroName, TypeMacroArgs); emitFallbackDefine(DependentTypeMacroName, TypeMacroName, TypeMacroArgs); - emitFallbackDefine(NonCanonicalUnlessDependentTypeMacroName, TypeMacroName, + emitFallbackDefine(NonCanonicalUnlessDependentTypeMacroName, TypeMacroName, TypeMacroArgs); // Invocations. emitNodeInvocations(); - emitLeafNodeInvocations(); + emitAlwaysCanonicalNodeInvocations(); // Postmatter emitUndefs(); @@ -178,15 +179,16 @@ void TypeNodeEmitter::emitLastNodeInvocation(TypeNode type) { "#endif\n"; } -void TypeNodeEmitter::emitLeafNodeInvocations() { - Out << "#ifdef " LeafTypeMacroName "\n"; +void TypeNodeEmitter::emitAlwaysCanonicalNodeInvocations() { + Out << "#ifdef " AlwaysCanonicalTypeMacroName "\n"; for (TypeNode type : Types) { - if (!type.isSubClassOf(LeafTypeClassName)) continue; - Out << LeafTypeMacroName "(" << type.getId() << ")\n"; + if (!type.isSubClassOf(AlwaysCanonicalTypeClassName)) + continue; + Out << AlwaysCanonicalTypeMacroName "(" << type.getId() << ")\n"; } - Out << "#undef " LeafTypeMacroName "\n" + Out << "#undef " AlwaysCanonicalTypeMacroName "\n" "#endif\n"; } >From 39b94875ca70f92580b1d297f92c039c927132c4 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov <mizve...@gmail.com> Date: Wed, 20 Aug 2025 00:23:48 -0300 Subject: [PATCH 2/2] [clang] AST: fix getAs canonicalization of leaf types 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 functions 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: <img width="1461" height="18" alt="image" src="https://github.com/user-attachments/assets/061dfb14-9506-4623-91ec-0f02f585d1dd" /> This will be fixed in a later patch, bringing the whole thing back to a positive performance improvement overall: <img width="1462" height="18" alt="image" src="https://github.com/user-attachments/assets/c237e68f-f696-44f4-acc6-a7c7ba5b0976" /> --- .../EasilySwappableParametersCheck.cpp | 2 +- .../MissingStdForwardCheck.cpp | 2 +- .../ProTypeMemberInitCheck.cpp | 2 +- .../clang-tidy/misc/UnusedUsingDeclsCheck.cpp | 2 +- .../modernize/UseScopedLockCheck.cpp | 2 +- .../SuspiciousCallArgumentCheck.cpp | 7 ++-- .../clangd/refactor/tweaks/PopulateSwitch.cpp | 6 ++-- clang/lib/AST/ASTContext.cpp | 23 +++++++------ clang/lib/AST/ByteCode/Compiler.cpp | 4 +-- clang/lib/AST/ByteCode/Pointer.cpp | 2 +- clang/lib/AST/CXXInheritance.cpp | 2 +- clang/lib/AST/Decl.cpp | 10 +++--- clang/lib/AST/DeclCXX.cpp | 2 +- clang/lib/AST/DeclarationName.cpp | 4 +-- clang/lib/AST/ExprConstant.cpp | 17 +++++----- clang/lib/AST/InheritViz.cpp | 4 +-- clang/lib/AST/ItaniumMangle.cpp | 4 +-- clang/lib/AST/JSONNodeDumper.cpp | 2 +- clang/lib/AST/RecordLayoutBuilder.cpp | 7 ++-- clang/lib/AST/TextNodeDumper.cpp | 2 +- clang/lib/AST/Type.cpp | 32 +++++++++---------- clang/lib/AST/TypePrinter.cpp | 2 +- clang/lib/CodeGen/ABIInfoImpl.cpp | 4 +-- clang/lib/CodeGen/CGCall.cpp | 8 ++--- clang/lib/CodeGen/CGDebugInfo.cpp | 2 +- clang/lib/CodeGen/CGExprAgg.cpp | 5 +-- clang/lib/CodeGen/CGExprCXX.cpp | 7 ++-- clang/lib/CodeGen/CGExprScalar.cpp | 2 +- clang/lib/CodeGen/CGNonTrivialStruct.cpp | 3 +- clang/lib/CodeGen/CGObjCMac.cpp | 12 +++---- clang/lib/CodeGen/CodeGenModule.cpp | 3 +- clang/lib/CodeGen/CodeGenTBAA.cpp | 4 +-- clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp | 8 ++--- clang/lib/CodeGen/SwiftCallingConv.cpp | 2 +- clang/lib/CodeGen/Targets/AArch64.cpp | 2 +- clang/lib/CodeGen/Targets/ARC.cpp | 2 +- clang/lib/CodeGen/Targets/ARM.cpp | 2 +- clang/lib/CodeGen/Targets/DirectX.cpp | 3 +- clang/lib/CodeGen/Targets/Lanai.cpp | 2 +- clang/lib/CodeGen/Targets/LoongArch.cpp | 4 +-- clang/lib/CodeGen/Targets/Mips.cpp | 4 +-- clang/lib/CodeGen/Targets/RISCV.cpp | 4 +-- clang/lib/CodeGen/Targets/SPIR.cpp | 3 +- clang/lib/CodeGen/Targets/X86.cpp | 10 +++--- clang/lib/CodeGen/Targets/XCore.cpp | 7 ++-- .../Frontend/Rewrite/RewriteModernObjC.cpp | 5 +-- clang/lib/Index/USRGeneration.cpp | 3 +- clang/lib/Sema/SemaBPF.cpp | 7 +--- clang/lib/Sema/SemaCast.cpp | 7 ++-- clang/lib/Sema/SemaChecking.cpp | 4 +-- clang/lib/Sema/SemaDeclAttr.cpp | 2 +- clang/lib/Sema/SemaDeclCXX.cpp | 24 +++++++------- clang/lib/Sema/SemaExpr.cpp | 14 +++++--- clang/lib/Sema/SemaExprCXX.cpp | 8 ++--- clang/lib/Sema/SemaExprObjC.cpp | 2 +- clang/lib/Sema/SemaInit.cpp | 2 +- clang/lib/Sema/SemaObjC.cpp | 4 +-- clang/lib/Sema/SemaOverload.cpp | 10 +++--- clang/lib/Sema/SemaStmt.cpp | 4 +-- clang/lib/Sema/SemaStmtAsm.cpp | 9 +++--- clang/lib/Sema/SemaTemplate.cpp | 10 +++--- clang/lib/Sema/SemaTemplateDeduction.cpp | 16 +++++----- clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 2 +- clang/lib/Sema/SemaTypeTraits.cpp | 8 ++--- clang/lib/Sema/TreeTransform.h | 11 ++++--- .../Checkers/LLVMConventionsChecker.cpp | 2 +- .../Checkers/WebKit/PtrTypesSemantics.cpp | 2 +- clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 2 +- 68 files changed, 206 insertions(+), 195 deletions(-) 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/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/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/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/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 06e7a2d5b857b..089c328485dfe 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2614,10 +2614,10 @@ unsigned ASTContext::getTypeUnadjustedAlign(const Type *T) const { return I->second; unsigned UnadjustedAlign; - if (const auto *RT = T->getAs<RecordType>()) { + if (const auto *RT = T->getAsCanonical<RecordType>()) { const ASTRecordLayout &Layout = getASTRecordLayout(RT->getOriginalDecl()); UnadjustedAlign = toBits(Layout.getUnadjustedAlignment()); - } else if (const auto *ObjCI = T->getAs<ObjCInterfaceType>()) { + } else if (const auto *ObjCI = T->getAsCanonical<ObjCInterfaceType>()) { const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl()); UnadjustedAlign = toBits(Layout.getUnadjustedAlignment()); } else { @@ -3552,8 +3552,7 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx, llvm_unreachable("should never get here"); } case Type::Record: { - const RecordDecl *RD = - T->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf(); + const RecordDecl *RD = T->castAsCanonical<RecordType>()->getOriginalDecl(); const IdentifierInfo *II = RD->getIdentifier(); // In C++, an immediate typedef of an anonymous struct or union @@ -9277,8 +9276,8 @@ static char getObjCEncodingForPrimitiveType(const ASTContext *C, llvm_unreachable("invalid BuiltinType::Kind value"); } -static char ObjCEncodingForEnumType(const ASTContext *C, const EnumType *ET) { - EnumDecl *Enum = ET->getOriginalDecl()->getDefinitionOrSelf(); +static char ObjCEncodingForEnumDecl(const ASTContext *C, const EnumDecl *ED) { + EnumDecl *Enum = ED->getDefinitionOrSelf(); // The encoding of an non-fixed enum type is always 'i', regardless of size. if (!Enum->isFixed()) @@ -9321,8 +9320,8 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S, S += llvm::utostr(Offset); - if (const auto *ET = T->getAs<EnumType>()) - S += ObjCEncodingForEnumType(Ctx, ET); + if (const auto *ET = T->getAsCanonical<EnumType>()) + S += ObjCEncodingForEnumDecl(Ctx, ET->getOriginalDecl()); else { const auto *BT = T->castAs<BuiltinType>(); S += getObjCEncodingForPrimitiveType(Ctx, BT); @@ -9379,7 +9378,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S, if (const auto *BT = dyn_cast<BuiltinType>(CT)) S += getObjCEncodingForPrimitiveType(this, BT); else - S += ObjCEncodingForEnumType(this, cast<EnumType>(CT)); + S += ObjCEncodingForEnumDecl(this, cast<EnumType>(CT)->getOriginalDecl()); return; case Type::Complex: @@ -9446,7 +9445,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S, S += '*'; return; } - } else if (const auto *RTy = PointeeTy->getAs<RecordType>()) { + } else if (const auto *RTy = PointeeTy->getAsCanonical<RecordType>()) { const IdentifierInfo *II = RTy->getOriginalDecl()->getIdentifier(); // GCC binary compat: Need to convert "struct objc_class *" to "#". if (II == &Idents.get("objc_class")) { @@ -11818,10 +11817,10 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, bool OfBlockPointer, if (LHSClass != RHSClass) { // Note that we only have special rules for turning block enum // returns into block int returns, not vice-versa. - if (const auto *ETy = LHS->getAs<EnumType>()) { + if (const auto *ETy = LHS->getAsCanonical<EnumType>()) { return mergeEnumWithInteger(*this, ETy, RHS, false); } - if (const EnumType* ETy = RHS->getAs<EnumType>()) { + if (const EnumType *ETy = RHS->getAsCanonical<EnumType>()) { return mergeEnumWithInteger(*this, ETy, LHS, BlockReturnType); } // allow block pointer type to match an 'id' type. diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 0079d937e885b..6e64fc0a2a7ad 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -4609,8 +4609,8 @@ UnsignedOrNone Compiler<Emitter>::allocateTemporary(const Expr *E) { template <class Emitter> const RecordType *Compiler<Emitter>::getRecordTy(QualType Ty) { if (const PointerType *PT = dyn_cast<PointerType>(Ty)) - return PT->getPointeeType()->getAs<RecordType>(); - return Ty->getAs<RecordType>(); + return PT->getPointeeType()->getAsCanonical<RecordType>(); + return Ty->getAsCanonical<RecordType>(); } template <class Emitter> Record *Compiler<Emitter>::getRecord(QualType Ty) { diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index c3c67227d0236..9fc5b5183f5f6 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -700,7 +700,7 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx, return true; } - if (const auto *RT = Ty->getAs<RecordType>()) { + if (const auto *RT = Ty->getAsCanonical<RecordType>()) { const auto *Record = Ptr.getRecord(); assert(Record && "Missing record descriptor"); diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp index 94f01c86a16ca..7a3e7ea4e5b8f 100644 --- a/clang/lib/AST/CXXInheritance.cpp +++ b/clang/lib/AST/CXXInheritance.cpp @@ -190,7 +190,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, if (isDetectingVirtual() && DetectedVirtual == nullptr) { // If this is the first virtual we find, remember it. If it turns out // there is no base path here, we'll reset it later. - DetectedVirtual = BaseType->getAs<RecordType>(); + DetectedVirtual = BaseType->getAsCanonical<RecordType>(); SetVirtual = true; } } else { diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index c44bf739dca2d..343673069e15e 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2988,7 +2988,7 @@ bool ParmVarDecl::isDestroyedInCallee() const { // FIXME: isParamDestroyedInCallee() should probably imply // isDestructedType() - const auto *RT = getType()->getAs<RecordType>(); + const auto *RT = getType()->getAsCanonical<RecordType>(); if (RT && RT->getOriginalDecl() ->getDefinitionOrSelf() @@ -3503,7 +3503,7 @@ bool FunctionDecl::isUsableAsGlobalAllocationFunctionInConstantEvaluation( while (const auto *TD = T->getAs<TypedefType>()) T = TD->getDecl()->getUnderlyingType(); const IdentifierInfo *II = - T->castAs<EnumType>()->getOriginalDecl()->getIdentifier(); + T->castAsCanonical<EnumType>()->getOriginalDecl()->getIdentifier(); if (II && II->isStr("__hot_cold_t")) Consume(); } @@ -4653,7 +4653,7 @@ bool FieldDecl::isAnonymousStructOrUnion() const { if (!isImplicit() || getDeclName()) return false; - if (const auto *Record = getType()->getAs<RecordType>()) + if (const auto *Record = getType()->getAsCanonical<RecordType>()) return Record->getOriginalDecl()->isAnonymousStructOrUnion(); return false; @@ -4711,7 +4711,7 @@ bool FieldDecl::isZeroSize(const ASTContext &Ctx) const { return false; // -- is not of class type, or - const auto *RT = getType()->getAs<RecordType>(); + const auto *RT = getType()->getAsCanonical<RecordType>(); if (!RT) return false; const RecordDecl *RD = RT->getOriginalDecl()->getDefinition(); @@ -5138,7 +5138,7 @@ bool RecordDecl::isOrContainsUnion() const { if (const RecordDecl *Def = getDefinition()) { for (const FieldDecl *FD : Def->fields()) { - const RecordType *RT = FD->getType()->getAs<RecordType>(); + const RecordType *RT = FD->getType()->getAsCanonical<RecordType>(); if (RT && RT->getOriginalDecl()->isOrContainsUnion()) return true; } diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 86d3b136ce0b5..97fdbe3c42bc8 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -2307,7 +2307,7 @@ bool CXXRecordDecl::mayBeAbstract() const { for (const auto &B : bases()) { const auto *BaseDecl = cast<CXXRecordDecl>( - B.getType()->castAs<RecordType>()->getOriginalDecl()); + B.getType()->castAsCanonical<RecordType>()->getOriginalDecl()); if (BaseDecl->isAbstract()) return true; } diff --git a/clang/lib/AST/DeclarationName.cpp b/clang/lib/AST/DeclarationName.cpp index 6c7b995d57567..74f2eec69461a 100644 --- a/clang/lib/AST/DeclarationName.cpp +++ b/clang/lib/AST/DeclarationName.cpp @@ -114,12 +114,12 @@ static void printCXXConstructorDestructorName(QualType ClassType, // We know we're printing C++ here. Ensure we print types properly. Policy.adjustForCPlusPlus(); - if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) { + if (const RecordType *ClassRec = ClassType->getAsCanonical<RecordType>()) { ClassRec->getOriginalDecl()->printName(OS, Policy); return; } if (Policy.SuppressTemplateArgsInCXXConstructors) { - if (auto *InjTy = ClassType->getAs<InjectedClassNameType>()) { + if (auto *InjTy = ClassType->getAsCanonical<InjectedClassNameType>()) { InjTy->getOriginalDecl()->printName(OS, Policy); return; } diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 19703e40d2696..de01faf5182aa 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -4100,7 +4100,8 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, } // Next subobject is a class, struct or union field. - RecordDecl *RD = ObjType->castAs<RecordType>()->getOriginalDecl(); + RecordDecl *RD = + ObjType->castAsCanonical<RecordType>()->getOriginalDecl(); if (RD->isUnion()) { const FieldDecl *UnionField = O->getUnionField(); if (!UnionField || @@ -8581,10 +8582,9 @@ class ExprEvaluatorBase const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl()); if (!FD) return Error(E); assert(!FD->getType()->isReferenceType() && "prvalue reference?"); - assert( - BaseTy->castAs<RecordType>()->getOriginalDecl()->getCanonicalDecl() == - FD->getParent()->getCanonicalDecl() && - "record / field mismatch"); + assert(BaseTy->castAsCanonical<RecordType>()->getOriginalDecl() == + FD->getParent()->getCanonicalDecl() && + "record / field mismatch"); // Note: there is no lvalue base here. But this case should only ever // happen in C or in C++98, where we cannot be evaluating a constexpr @@ -8811,10 +8811,9 @@ class LValueExprEvaluatorBase const ValueDecl *MD = E->getMemberDecl(); if (const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl())) { - assert( - BaseTy->castAs<RecordType>()->getOriginalDecl()->getCanonicalDecl() == - FD->getParent()->getCanonicalDecl() && - "record / field mismatch"); + assert(BaseTy->castAsCanonical<RecordType>()->getOriginalDecl() == + FD->getParent()->getCanonicalDecl() && + "record / field mismatch"); (void)BaseTy; if (!HandleLValueMember(this->Info, E, Result, FD)) return false; diff --git a/clang/lib/AST/InheritViz.cpp b/clang/lib/AST/InheritViz.cpp index c03492c64b161..3c4a5a8e2c4a6 100644 --- a/clang/lib/AST/InheritViz.cpp +++ b/clang/lib/AST/InheritViz.cpp @@ -89,8 +89,8 @@ void InheritanceHierarchyWriter::WriteNode(QualType Type, bool FromVirtual) { Out << " \"];\n"; // Display the base classes. - const auto *Decl = static_cast<const CXXRecordDecl *>( - Type->castAs<RecordType>()->getOriginalDecl()); + const auto *Decl = cast<CXXRecordDecl>( + Type->castAsCanonical<RecordType>()->getOriginalDecl()); for (const auto &Base : Decl->bases()) { QualType CanonBaseType = Context.getCanonicalType(Base.getType()); diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 1ba224b74a606..ffadfce67d631 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -4726,7 +4726,7 @@ void CXXNameMangler::mangleIntegerLiteral(QualType T, void CXXNameMangler::mangleMemberExprBase(const Expr *Base, bool IsArrow) { // Ignore member expressions involving anonymous unions. - while (const auto *RT = Base->getType()->getAs<RecordType>()) { + while (const auto *RT = Base->getType()->getAsCanonical<RecordType>()) { if (!RT->getOriginalDecl()->isAnonymousStructOrUnion()) break; const auto *ME = dyn_cast<MemberExpr>(Base); @@ -7031,7 +7031,7 @@ bool CXXNameMangler::isSpecializedAs(QualType S, llvm::StringRef Name, if (S.isNull()) return false; - const RecordType *RT = S->getAs<RecordType>(); + const RecordType *RT = S->getAsCanonical<RecordType>(); if (!RT) return false; diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index b3f12a1cce2ec..ca8e2af284c2b 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -396,7 +396,7 @@ llvm::json::Array JSONNodeDumper::createCastPath(const CastExpr *C) { for (auto I = C->path_begin(), E = C->path_end(); I != E; ++I) { const CXXBaseSpecifier *Base = *I; const auto *RD = cast<CXXRecordDecl>( - Base->getType()->castAs<RecordType>()->getOriginalDecl()); + Base->getType()->castAsCanonical<RecordType>()->getOriginalDecl()); llvm::json::Object Val{{"name", RD->getName()}}; if (Base->isVirtual()) diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index e6729f8fbba70..4b312c559bf2a 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2007,7 +2007,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D, CTy->getElementType()->castAs<BuiltinType>()); } else if (const BuiltinType *BTy = BaseTy->getAs<BuiltinType>()) { performBuiltinTypeAlignmentUpgrade(BTy); - } else if (const RecordType *RT = BaseTy->getAs<RecordType>()) { + } else if (const RecordType *RT = BaseTy->getAsCanonical<RecordType>()) { const RecordDecl *RD = RT->getOriginalDecl(); const ASTRecordLayout &FieldRecord = Context.getASTRecordLayout(RD); PreferredAlign = FieldRecord.getPreferredAlignment(); @@ -2707,8 +2707,9 @@ MicrosoftRecordLayoutBuilder::getAdjustedElementInfo( // alignment when it is applied to bitfields. Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment); else { - if (auto RT = - FD->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()) { + if (const auto *RT = FD->getType() + ->getBaseElementTypeUnsafe() + ->getAsCanonical<RecordType>()) { auto const &Layout = Context.getASTRecordLayout(RT->getOriginalDecl()); EndsWithZeroSizedObject = Layout.endsWithZeroSizedObject(); FieldRequiredAlignment = std::max(FieldRequiredAlignment, diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 085616049373e..9dca5cf088a85 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1401,7 +1401,7 @@ static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) { OS << " -> "; const auto *RD = cast<CXXRecordDecl>( - Base->getType()->castAs<RecordType>()->getOriginalDecl()); + Base->getType()->castAsCanonical<RecordType>()->getOriginalDecl()); if (Base->isVirtual()) OS << "virtual "; diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index ea5e39740bb08..8cb2fb337e167 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -670,19 +670,19 @@ const Type *Type::getUnqualifiedDesugaredType() const { } bool Type::isClassType() const { - if (const auto *RT = getAs<RecordType>()) + if (const auto *RT = getAsCanonical<RecordType>()) return RT->getOriginalDecl()->isClass(); return false; } bool Type::isStructureType() const { - if (const auto *RT = getAs<RecordType>()) + if (const auto *RT = getAsCanonical<RecordType>()) return RT->getOriginalDecl()->isStruct(); return false; } bool Type::isStructureTypeWithFlexibleArrayMember() const { - const auto *RT = getAs<RecordType>(); + const auto *RT = getAsCanonical<RecordType>(); if (!RT) return false; const auto *Decl = RT->getOriginalDecl(); @@ -698,7 +698,7 @@ bool Type::isObjCBoxableRecordType() const { } bool Type::isInterfaceType() const { - if (const auto *RT = getAs<RecordType>()) + if (const auto *RT = getAsCanonical<RecordType>()) return RT->getOriginalDecl()->isInterface(); return false; } @@ -710,19 +710,19 @@ bool Type::isStructureOrClassType() const { } bool Type::isVoidPointerType() const { - if (const auto *PT = getAs<PointerType>()) + if (const auto *PT = getAsCanonical<PointerType>()) return PT->getPointeeType()->isVoidType(); return false; } bool Type::isUnionType() const { - if (const auto *RT = getAs<RecordType>()) + if (const auto *RT = getAsCanonical<RecordType>()) return RT->getOriginalDecl()->isUnion(); return false; } bool Type::isComplexType() const { - if (const auto *CT = dyn_cast<ComplexType>(CanonicalType)) + if (const auto *CT = getAsCanonical<ComplexType>()) return CT->getElementType()->isFloatingType(); return false; } @@ -733,7 +733,7 @@ bool Type::isComplexIntegerType() const { } bool Type::isScopedEnumeralType() const { - if (const auto *ET = getAs<EnumType>()) + if (const auto *ET = getAsCanonical<EnumType>()) return ET->getOriginalDecl()->isScoped(); return false; } @@ -1908,9 +1908,9 @@ const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const { const CXXRecordDecl *Type::getPointeeCXXRecordDecl() const { QualType PointeeType; - if (const auto *PT = getAs<PointerType>()) + if (const auto *PT = getAsCanonical<PointerType>()) PointeeType = PT->getPointeeType(); - else if (const auto *RT = getAs<ReferenceType>()) + else if (const auto *RT = getAsCanonical<ReferenceType>()) PointeeType = RT->getPointeeType(); else return nullptr; @@ -3211,7 +3211,7 @@ bool Type::isNothrowT() const { } bool Type::isAlignValT() const { - if (const auto *ET = getAs<EnumType>()) { + if (const auto *ET = getAsCanonical<EnumType>()) { const auto *ED = ET->getOriginalDecl(); IdentifierInfo *II = ED->getIdentifier(); if (II && II->isStr("align_val_t") && ED->isInStdNamespace()) @@ -3221,7 +3221,7 @@ bool Type::isAlignValT() const { } bool Type::isStdByteType() const { - if (const auto *ET = getAs<EnumType>()) { + if (const auto *ET = getAsCanonical<EnumType>()) { const auto *ED = ET->getOriginalDecl(); IdentifierInfo *II = ED->getIdentifier(); if (II && II->isStr("byte") && ED->isInStdNamespace()) @@ -4392,7 +4392,7 @@ bool RecordType::hasConstFields() const { if (FieldTy.isConstQualified()) return true; FieldTy = FieldTy.getCanonicalType(); - if (const auto *FieldRecTy = FieldTy->getAs<RecordType>()) { + if (const auto *FieldRecTy = FieldTy->getAsCanonical<RecordType>()) { if (!llvm::is_contained(RecordTypeList, FieldRecTy)) RecordTypeList.push_back(FieldRecTy); } @@ -5396,7 +5396,7 @@ bool Type::isObjCARCBridgableType() const { /// Determine whether the given type T is a "bridgeable" C type. bool Type::isCARCBridgableType() const { - const auto *Pointer = getAs<PointerType>(); + const auto *Pointer = getAsCanonical<PointerType>(); if (!Pointer) return false; @@ -5406,7 +5406,7 @@ bool Type::isCARCBridgableType() const { /// Check if the specified type is the CUDA device builtin surface type. bool Type::isCUDADeviceBuiltinSurfaceType() const { - if (const auto *RT = getAs<RecordType>()) + if (const auto *RT = getAsCanonical<RecordType>()) return RT->getOriginalDecl() ->getMostRecentDecl() ->hasAttr<CUDADeviceBuiltinSurfaceTypeAttr>(); @@ -5415,7 +5415,7 @@ bool Type::isCUDADeviceBuiltinSurfaceType() const { /// Check if the specified type is the CUDA device builtin texture type. bool Type::isCUDADeviceBuiltinTextureType() const { - if (const auto *RT = getAs<RecordType>()) + if (const auto *RT = getAsCanonical<RecordType>()) return RT->getOriginalDecl() ->getMostRecentDecl() ->hasAttr<CUDADeviceBuiltinTextureTypeAttr>(); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 52ff0d5b5771b..54ca42d2035ad 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -2382,7 +2382,7 @@ static bool isSubstitutedType(ASTContext &Ctx, QualType T, QualType Pattern, return true; // A type parameter matches its argument. - if (auto *TTPT = Pattern->getAs<TemplateTypeParmType>()) { + if (auto *TTPT = Pattern->getAsCanonical<TemplateTypeParmType>()) { if (TTPT->getDepth() == Depth && TTPT->getIndex() < Args.size() && Args[TTPT->getIndex()].getKind() == TemplateArgument::Type) { QualType SubstArg = Ctx.getQualifiedType( diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp index 72d359e4862b9..13c837a0fb680 100644 --- a/clang/lib/CodeGen/ABIInfoImpl.cpp +++ b/clang/lib/CodeGen/ABIInfoImpl.cpp @@ -114,7 +114,7 @@ CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(const RecordType *RT, } CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(QualType T, CGCXXABI &CXXABI) { - const RecordType *RT = T->getAs<RecordType>(); + const RecordType *RT = T->getAsCanonical<RecordType>(); if (!RT) return CGCXXABI::RAA_Default; return getRecordArgABI(RT, CXXABI); @@ -260,7 +260,7 @@ bool CodeGen::isEmptyField(ASTContext &Context, const FieldDecl *FD, WasArray = true; } - const RecordType *RT = FT->getAs<RecordType>(); + const RecordType *RT = FT->getAsCanonical<RecordType>(); if (!RT) return false; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index f61d3d987b3c9..5b0dd235b58da 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1896,7 +1896,7 @@ bool CodeGenModule::MayDropFunctionReturn(const ASTContext &Context, // We can't just discard the return value for a record type with a // complex destructor or a non-trivially copyable type. if (const RecordType *RT = - ReturnType.getCanonicalType()->getAs<RecordType>()) { + ReturnType.getCanonicalType()->getAsCanonical<RecordType>()) { if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) return ClassDecl->hasTrivialDestructor(); } @@ -3886,7 +3886,7 @@ static void setUsedBits(CodeGenModule &CGM, const ConstantArrayType *ATy, // the type `QTy`. static void setUsedBits(CodeGenModule &CGM, QualType QTy, int Offset, SmallVectorImpl<uint64_t> &Bits) { - if (const auto *RTy = QTy->getAs<RecordType>()) + if (const auto *RTy = QTy->getAsCanonical<RecordType>()) return setUsedBits(CGM, RTy, Offset, Bits); ASTContext &Context = CGM.getContext(); @@ -3930,7 +3930,7 @@ llvm::Value *CodeGenFunction::EmitCMSEClearRecord(llvm::Value *Src, const llvm::DataLayout &DataLayout = CGM.getDataLayout(); int Size = DataLayout.getTypeStoreSize(ITy); SmallVector<uint64_t, 4> Bits(Size); - setUsedBits(CGM, QTy->castAs<RecordType>(), 0, Bits); + setUsedBits(CGM, QTy->castAsCanonical<RecordType>(), 0, Bits); int CharWidth = CGM.getContext().getCharWidth(); uint64_t Mask = @@ -3947,7 +3947,7 @@ llvm::Value *CodeGenFunction::EmitCMSEClearRecord(llvm::Value *Src, const llvm::DataLayout &DataLayout = CGM.getDataLayout(); int Size = DataLayout.getTypeStoreSize(ATy); SmallVector<uint64_t, 16> Bits(Size); - setUsedBits(CGM, QTy->castAs<RecordType>(), 0, Bits); + setUsedBits(CGM, QTy->castAsCanonical<RecordType>(), 0, Bits); // Clear each element of the LLVM array. int CharWidth = CGM.getContext().getCharWidth(); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 560749f8ab308..0385dbdac869b 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2359,7 +2359,7 @@ void CGDebugInfo::CollectCXXBasesAux( for (const auto &BI : Bases) { const auto *Base = cast<CXXRecordDecl>( - BI.getType()->castAs<RecordType>()->getOriginalDecl()) + BI.getType()->castAsCanonical<RecordType>()->getOriginalDecl()) ->getDefinition(); if (!SeenTypes.insert(Base).second) continue; diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 50575362d304b..b8150a24d45fc 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -2114,7 +2114,7 @@ static CharUnits GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) { // InitListExprs for structs have to be handled carefully. If there are // reference members, we need to consider the size of the reference, not the // referencee. InitListExprs for unions and arrays can't have references. - if (const RecordType *RT = E->getType()->getAs<RecordType>()) { + if (const RecordType *RT = E->getType()->getAsCanonical<RecordType>()) { if (!RT->isUnionType()) { RecordDecl *SD = RT->getOriginalDecl()->getDefinitionOrSelf(); CharUnits NumNonZeroBytes = CharUnits::Zero(); @@ -2167,7 +2167,8 @@ static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E, // C++ objects with a user-declared constructor don't need zero'ing. if (CGF.getLangOpts().CPlusPlus) if (const RecordType *RT = CGF.getContext() - .getBaseElementType(E->getType())->getAs<RecordType>()) { + .getBaseElementType(E->getType()) + ->getAsCanonical<RecordType>()) { const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getOriginalDecl()); if (RD->hasUserDeclaredConstructor()) return; diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 810a2ab8c1fcd..1e4c72a210f9a 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -1234,9 +1234,10 @@ void CodeGenFunction::EmitNewArrayInitializer( // If we have a struct whose every field is value-initialized, we can // usually use memset. if (auto *ILE = dyn_cast<InitListExpr>(Init)) { - if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) { - const RecordDecl *RD = RType->getOriginalDecl()->getDefinitionOrSelf(); - if (RD->isStruct()) { + if (const RecordType *RType = + ILE->getType()->getAsCanonical<RecordType>()) { + if (RType->getOriginalDecl()->isStruct()) { + const RecordDecl *RD = RType->getOriginalDecl()->getDefinitionOrSelf(); unsigned NumElements = 0; if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) NumElements = CXXRD->getNumBases(); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 43d295599c4c8..2338cbd74f002 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -3549,7 +3549,7 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) { } const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout( - CurrentType->castAs<RecordType>()->getOriginalDecl()); + CurrentType->castAsCanonical<RecordType>()->getOriginalDecl()); // Save the element type. CurrentType = ON.getBase()->getType(); diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/clang/lib/CodeGen/CGNonTrivialStruct.cpp index b78d89fd1e348..2d70e4c2e0394 100644 --- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp +++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp @@ -673,7 +673,8 @@ struct GenDefaultInitialize CharUnits Size = Ctx.getTypeSizeInChars(QualType(AT, 0)); QualType EltTy = Ctx.getBaseElementType(QualType(AT, 0)); - if (Size < CharUnits::fromQuantity(16) || EltTy->getAs<RecordType>()) { + if (Size < CharUnits::fromQuantity(16) || + EltTy->getAsCanonical<RecordType>()) { GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStructOffset, Addrs); return; } diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index d1fb05d594058..60f30a1334d6d 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -2315,7 +2315,7 @@ void IvarLayoutBuilder::visitBlock(const CGBlockInfo &blockInfo) { } assert(!type->isArrayType() && "array variable should not be caught"); - if (const RecordType *record = type->getAs<RecordType>()) { + if (const RecordType *record = type->getAsCanonical<RecordType>()) { visitRecord(record, fieldOffset); continue; } @@ -2409,7 +2409,7 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, if (FQT->isUnionType()) HasUnion = true; - BuildRCBlockVarRecordLayout(FQT->castAs<RecordType>(), + BuildRCBlockVarRecordLayout(FQT->castAsCanonical<RecordType>(), BytePos + FieldOffset, HasUnion); continue; } @@ -2426,7 +2426,7 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, } if (FQT->isRecordType() && ElCount) { int OldIndex = RunSkipBlockVars.size() - 1; - auto *RT = FQT->castAs<RecordType>(); + auto *RT = FQT->castAsCanonical<RecordType>(); BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset, HasUnion); // Replicate layout information for each array element. Note that @@ -2831,7 +2831,7 @@ void CGObjCCommonMac::fillRunSkipBlockVars(CodeGenModule &CGM, assert(!type->isArrayType() && "array variable should not be caught"); if (!CI.isByRef()) - if (const RecordType *record = type->getAs<RecordType>()) { + if (const auto *record = type->getAsCanonical<RecordType>()) { BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion); continue; } @@ -2865,7 +2865,7 @@ llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM, CharUnits fieldOffset; RunSkipBlockVars.clear(); bool hasUnion = false; - if (const RecordType *record = T->getAs<RecordType>()) { + if (const auto *record = T->getAsCanonical<RecordType>()) { BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */); llvm::Constant *Result = getBitmapBlockLayout(true); @@ -5246,7 +5246,7 @@ void IvarLayoutBuilder::visitField(const FieldDecl *field, return; // Recurse if the base element type is a record type. - if (auto recType = fieldType->getAs<RecordType>()) { + if (const auto *recType = fieldType->getAsCanonical<RecordType>()) { size_t oldEnd = IvarsInfo.size(); visitRecord(recType, fieldOffset); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 7064421fe0613..323823c964a79 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -4195,7 +4195,8 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // Check if T is a class type with a destructor that's not dllimport. static bool HasNonDllImportDtor(QualType T) { - if (const auto *RT = T->getBaseElementTypeUnsafe()->getAs<RecordType>()) + if (const auto *RT = + T->getBaseElementTypeUnsafe()->getAsCanonical<RecordType>()) if (auto *RD = dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) { RD = RD->getDefinitionOrSelf(); if (RD->getDestructor() && !RD->getDestructor()->hasAttr<DLLImportAttr>()) diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp index 8cb8024960176..f8c7d64cc1aa2 100644 --- a/clang/lib/CodeGen/CodeGenTBAA.cpp +++ b/clang/lib/CodeGen/CodeGenTBAA.cpp @@ -295,7 +295,7 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) { // Be conservative if the type isn't a RecordType. We are specifically // required to do this for member pointers until we implement the // similar-types rule. - const auto *RT = Ty->getAs<RecordType>(); + const auto *RT = Ty->getAsCanonical<RecordType>(); if (!RT) return getAnyPtr(PtrDepth); @@ -424,7 +424,7 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset, bool MayAlias) { /* Things not handled yet include: C++ base classes, bitfields, */ - if (const RecordType *TTy = QTy->getAs<RecordType>()) { + if (const auto *TTy = QTy->getAsCanonical<RecordType>()) { if (TTy->isUnionType()) { uint64_t Size = Context.getTypeSizeInChars(QTy).getQuantity(); llvm::MDNode *TBAAType = getChar(); diff --git a/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp b/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp index 4e25e887c4133..a21feaa1120c6 100644 --- a/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp +++ b/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp @@ -201,8 +201,8 @@ bool HLSLBufferLayoutBuilder::layoutField(const FieldDecl *FD, // For array of structures, create a new array with a layout type // instead of the structure type. if (Ty->isStructureOrClassType()) { - llvm::Type *NewTy = - cast<llvm::TargetExtType>(createLayoutType(Ty->getAs<RecordType>())); + llvm::Type *NewTy = cast<llvm::TargetExtType>( + createLayoutType(Ty->getAsCanonical<RecordType>())); if (!NewTy) return false; assert(isa<llvm::TargetExtType>(NewTy) && "expected target type"); @@ -220,8 +220,8 @@ bool HLSLBufferLayoutBuilder::layoutField(const FieldDecl *FD, } else if (FieldTy->isStructureOrClassType()) { // Create a layout type for the structure - ElemLayoutTy = - createLayoutType(cast<RecordType>(FieldTy->getAs<RecordType>())); + ElemLayoutTy = createLayoutType( + cast<RecordType>(FieldTy->getAsCanonical<RecordType>())); if (!ElemLayoutTy) return false; assert(isa<llvm::TargetExtType>(ElemLayoutTy) && "expected target type"); diff --git a/clang/lib/CodeGen/SwiftCallingConv.cpp b/clang/lib/CodeGen/SwiftCallingConv.cpp index de58e0d95a866..4d894fd99db05 100644 --- a/clang/lib/CodeGen/SwiftCallingConv.cpp +++ b/clang/lib/CodeGen/SwiftCallingConv.cpp @@ -65,7 +65,7 @@ void SwiftAggLowering::addTypedData(QualType type, CharUnits begin) { // Deal with various aggregate types as special cases: // Record types. - if (auto recType = type->getAs<RecordType>()) { + if (auto recType = type->getAsCanonical<RecordType>()) { addTypedData(recType->getOriginalDecl(), begin); // Array types. diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index 6bdfdbcf0e89a..d7deece232a9f 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -736,7 +736,7 @@ bool AArch64ABIInfo::passAsPureScalableType( return true; } - if (const RecordType *RT = Ty->getAs<RecordType>()) { + if (const RecordType *RT = Ty->getAsCanonical<RecordType>()) { // If the record cannot be passed in registers, then it's not a PST. if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()); RAA != CGCXXABI::RAA_Default) diff --git a/clang/lib/CodeGen/Targets/ARC.cpp b/clang/lib/CodeGen/Targets/ARC.cpp index 56bbae0eace94..67275877cbd9e 100644 --- a/clang/lib/CodeGen/Targets/ARC.cpp +++ b/clang/lib/CodeGen/Targets/ARC.cpp @@ -94,7 +94,7 @@ RValue ARCABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, ABIArgInfo ARCABIInfo::classifyArgumentType(QualType Ty, uint8_t FreeRegs) const { // Handle the generic C++ ABI. - const RecordType *RT = Ty->getAs<RecordType>(); + const RecordType *RT = Ty->getAsCanonical<RecordType>(); if (RT) { CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()); if (RAA == CGCXXABI::RAA_Indirect) diff --git a/clang/lib/CodeGen/Targets/ARM.cpp b/clang/lib/CodeGen/Targets/ARM.cpp index d5c86e19fd358..c84c9f2f643ee 100644 --- a/clang/lib/CodeGen/Targets/ARM.cpp +++ b/clang/lib/CodeGen/Targets/ARM.cpp @@ -512,7 +512,7 @@ static bool isIntegerLikeType(QualType Ty, ASTContext &Context, // above, but they are not. // Otherwise, it must be a record type. - const RecordType *RT = Ty->getAs<RecordType>(); + const RecordType *RT = Ty->getAsCanonical<RecordType>(); if (!RT) return false; // Ignore records with flexible arrays. diff --git a/clang/lib/CodeGen/Targets/DirectX.cpp b/clang/lib/CodeGen/Targets/DirectX.cpp index 96a1284661394..b4cebb9a32aca 100644 --- a/clang/lib/CodeGen/Targets/DirectX.cpp +++ b/clang/lib/CodeGen/Targets/DirectX.cpp @@ -77,7 +77,8 @@ llvm::Type *DirectXTargetCodeGenInfo::getHLSLType( llvm::Type *BufferLayoutTy = HLSLBufferLayoutBuilder(CGM, "dx.Layout") - .createLayoutType(ContainedTy->getAsStructureType(), Packoffsets); + .createLayoutType(ContainedTy->castAsCanonical<RecordType>(), + Packoffsets); if (!BufferLayoutTy) return nullptr; diff --git a/clang/lib/CodeGen/Targets/Lanai.cpp b/clang/lib/CodeGen/Targets/Lanai.cpp index 675009f0e5748..e76431a484e70 100644 --- a/clang/lib/CodeGen/Targets/Lanai.cpp +++ b/clang/lib/CodeGen/Targets/Lanai.cpp @@ -88,7 +88,7 @@ ABIArgInfo LanaiABIInfo::getIndirectResult(QualType Ty, bool ByVal, ABIArgInfo LanaiABIInfo::classifyArgumentType(QualType Ty, CCState &State) const { // Check with the C++ ABI first. - const RecordType *RT = Ty->getAs<RecordType>(); + const RecordType *RT = Ty->getAsCanonical<RecordType>(); if (RT) { CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()); if (RAA == CGCXXABI::RAA_Indirect) { diff --git a/clang/lib/CodeGen/Targets/LoongArch.cpp b/clang/lib/CodeGen/Targets/LoongArch.cpp index 0ea08ff533916..1f344d6582510 100644 --- a/clang/lib/CodeGen/Targets/LoongArch.cpp +++ b/clang/lib/CodeGen/Targets/LoongArch.cpp @@ -149,7 +149,7 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper( QualType EltTy = ATy->getElementType(); // Non-zero-length arrays of empty records make the struct ineligible to be // passed via FARs in C++. - if (const auto *RTy = EltTy->getAs<RecordType>()) { + if (const auto *RTy = EltTy->getAsCanonical<RecordType>()) { if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getOriginalDecl()) && isEmptyRecord(getContext(), EltTy, true, true)) return false; @@ -164,7 +164,7 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper( return true; } - if (const auto *RTy = Ty->getAs<RecordType>()) { + if (const auto *RTy = Ty->getAsCanonical<RecordType>()) { // Structures with either a non-trivial destructor or a non-trivial // copy constructor are not eligible for the FP calling convention. if (getRecordArgABI(Ty, CGT.getCXXABI())) diff --git a/clang/lib/CodeGen/Targets/Mips.cpp b/clang/lib/CodeGen/Targets/Mips.cpp index 9c3016fa1f5a5..f26ab974d699e 100644 --- a/clang/lib/CodeGen/Targets/Mips.cpp +++ b/clang/lib/CodeGen/Targets/Mips.cpp @@ -153,7 +153,7 @@ llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize) const { if (Ty->isComplexType()) return CGT.ConvertType(Ty); - const RecordType *RT = Ty->getAs<RecordType>(); + const RecordType *RT = Ty->getAsCanonical<RecordType>(); // Unions/vectors are passed in integer registers. if (!RT || !RT->isStructureOrClassType()) { @@ -261,7 +261,7 @@ MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const { llvm::Type* MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size) const { - const RecordType *RT = RetTy->getAs<RecordType>(); + const RecordType *RT = RetTy->getAsCanonical<RecordType>(); SmallVector<llvm::Type*, 8> RTList; if (RT && RT->isStructureOrClassType()) { diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp index 049f61bb86b1e..0ef39b68eb6e3 100644 --- a/clang/lib/CodeGen/Targets/RISCV.cpp +++ b/clang/lib/CodeGen/Targets/RISCV.cpp @@ -233,7 +233,7 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, QualType EltTy = ATy->getElementType(); // Non-zero-length arrays of empty records make the struct ineligible for // the FP calling convention in C++. - if (const auto *RTy = EltTy->getAs<RecordType>()) { + if (const auto *RTy = EltTy->getAsCanonical<RecordType>()) { if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getOriginalDecl()) && isEmptyRecord(getContext(), EltTy, true, true)) return false; @@ -249,7 +249,7 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, return true; } - if (const auto *RTy = Ty->getAs<RecordType>()) { + if (const auto *RTy = Ty->getAsCanonical<RecordType>()) { // Structures with either a non-trivial destructor or a non-trivial // copy constructor are not eligible for the FP calling convention. if (getRecordArgABI(Ty, CGT.getCXXABI())) diff --git a/clang/lib/CodeGen/Targets/SPIR.cpp b/clang/lib/CodeGen/Targets/SPIR.cpp index ababb25736203..4f0c4d0d906b1 100644 --- a/clang/lib/CodeGen/Targets/SPIR.cpp +++ b/clang/lib/CodeGen/Targets/SPIR.cpp @@ -500,7 +500,8 @@ llvm::Type *CommonSPIRTargetCodeGenInfo::getHLSLType( llvm::Type *BufferLayoutTy = HLSLBufferLayoutBuilder(CGM, "spirv.Layout") - .createLayoutType(ContainedTy->getAsStructureType(), Packoffsets); + .createLayoutType(ContainedTy->castAsCanonical<RecordType>(), + Packoffsets); uint32_t StorageClass = /* Uniform storage class */ 2; return llvm::TargetExtType::get(Ctx, "spirv.VulkanBuffer", {BufferLayoutTy}, {StorageClass, false}); diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 386772a96c7ff..71db63bb89645 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -752,7 +752,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State, TypeInfo TI = getContext().getTypeInfo(Ty); // Check with the C++ ABI first. - const RecordType *RT = Ty->getAs<RecordType>(); + const RecordType *RT = Ty->getAsCanonical<RecordType>(); if (RT) { CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()); if (RAA == CGCXXABI::RAA_Indirect) { @@ -2039,7 +2039,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, return; } - if (const RecordType *RT = Ty->getAs<RecordType>()) { + if (const RecordType *RT = Ty->getAsCanonical<RecordType>()) { uint64_t Size = getContext().getTypeSize(Ty); // AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger @@ -3309,14 +3309,14 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs, if (Ty->isVoidType()) return ABIArgInfo::getIgnore(); - if (const EnumType *EnumTy = Ty->getAs<EnumType>()) - Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); + if (const auto *ED = Ty->getAsEnumDecl()) + Ty = ED->getIntegerType(); TypeInfo Info = getContext().getTypeInfo(Ty); uint64_t Width = Info.Width; CharUnits Align = getContext().toCharUnitsFromBits(Info.Align); - const RecordType *RT = Ty->getAs<RecordType>(); + const RecordType *RT = Ty->getAsCanonical<RecordType>(); if (RT) { if (!IsReturnType) { if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI())) diff --git a/clang/lib/CodeGen/Targets/XCore.cpp b/clang/lib/CodeGen/Targets/XCore.cpp index d65af5f82b7f8..ab0115467e521 100644 --- a/clang/lib/CodeGen/Targets/XCore.cpp +++ b/clang/lib/CodeGen/Targets/XCore.cpp @@ -615,13 +615,10 @@ static bool appendType(SmallStringEnc &Enc, QualType QType, if (const PointerType *PT = QT->getAs<PointerType>()) return appendPointerType(Enc, PT, CGM, TSC); - if (const EnumType *ET = QT->getAs<EnumType>()) + if (const EnumType *ET = QT->getAsCanonical<EnumType>()) return appendEnumType(Enc, ET, TSC, QT.getBaseTypeIdentifier()); - if (const RecordType *RT = QT->getAsStructureType()) - return appendRecordType(Enc, RT, CGM, TSC, QT.getBaseTypeIdentifier()); - - if (const RecordType *RT = QT->getAsUnionType()) + if (const RecordType *RT = QT->getAsCanonical<RecordType>()) return appendRecordType(Enc, RT, CGM, TSC, QT.getBaseTypeIdentifier()); if (const FunctionType *FT = QT->getAs<FunctionType>()) diff --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp index ad8916f817486..42f2d6591b213 100644 --- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -852,7 +852,7 @@ RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) { IvarT = GetGroupRecordTypeForObjCIvarBitfield(D); if (!IvarT->getAs<TypedefType>() && IvarT->isRecordType()) { - RecordDecl *RD = IvarT->castAs<RecordType>()->getOriginalDecl(); + RecordDecl *RD = IvarT->castAsCanonical<RecordType>()->getOriginalDecl(); RD = RD->getDefinition(); if (RD && !RD->getDeclName().getAsIdentifierInfo()) { // decltype(((Foo_IMPL*)0)->bar) * @@ -7453,7 +7453,8 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { IvarT = GetGroupRecordTypeForObjCIvarBitfield(D); if (!IvarT->getAs<TypedefType>() && IvarT->isRecordType()) { - RecordDecl *RD = IvarT->castAs<RecordType>()->getOriginalDecl(); + RecordDecl *RD = + IvarT->castAsCanonical<RecordType>()->getOriginalDecl(); RD = RD->getDefinition(); if (RD && !RD->getDeclName().getAsIdentifierInfo()) { // decltype(((Foo_IMPL*)0)->bar) * diff --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp index 6bdddcc6967c9..c78d66f9502dd 100644 --- a/clang/lib/Index/USRGeneration.cpp +++ b/clang/lib/Index/USRGeneration.cpp @@ -931,7 +931,8 @@ void USRGenerator::VisitType(QualType T) { VisitObjCProtocolDecl(Prot); return; } - if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) { + if (const TemplateTypeParmType *TTP = + T->getAsCanonical<TemplateTypeParmType>()) { Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); return; } diff --git a/clang/lib/Sema/SemaBPF.cpp b/clang/lib/Sema/SemaBPF.cpp index c5e97484dab78..be890ab7fa75f 100644 --- a/clang/lib/Sema/SemaBPF.cpp +++ b/clang/lib/Sema/SemaBPF.cpp @@ -56,14 +56,9 @@ static bool isValidPreserveTypeInfoArg(Expr *Arg) { return true; // Record type or Enum type. - const Type *Ty = ArgType->getUnqualifiedDesugaredType(); - if (const auto *RT = Ty->getAs<RecordType>()) { + if (const auto *RT = ArgType->getAsCanonical<TagType>()) if (!RT->getOriginalDecl()->getDeclName().isEmpty()) return true; - } else if (const auto *ET = Ty->getAs<EnumType>()) { - if (!ET->getOriginalDecl()->getDeclName().isEmpty()) - return true; - } return false; } diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index de22419ee35de..8ee3e0c7105b9 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -863,7 +863,7 @@ void CastOperation::CheckDynamicCast() { return; } - const RecordType *DestRecord = DestPointee->getAs<RecordType>(); + const auto *DestRecord = DestPointee->getAsCanonical<RecordType>(); if (DestPointee->isVoidType()) { assert(DestPointer && "Reference to void is not possible"); } else if (DestRecord) { @@ -910,7 +910,7 @@ void CastOperation::CheckDynamicCast() { SrcPointee = SrcType; } - const RecordType *SrcRecord = SrcPointee->getAs<RecordType>(); + const auto *SrcRecord = SrcPointee->getAsCanonical<RecordType>(); if (SrcRecord) { if (Self.RequireCompleteType(OpRange.getBegin(), SrcPointee, diag::err_bad_cast_incomplete, @@ -3094,7 +3094,8 @@ void CastOperation::CheckCStyleCast() { if (!DestType->isScalarType() && !DestType->isVectorType() && !DestType->isMatrixType()) { - if (const RecordType *DestRecordTy = DestType->getAs<RecordType>()) { + if (const RecordType *DestRecordTy = + DestType->getAsCanonical<RecordType>()) { if (Self.Context.hasSameUnqualifiedType(DestType, SrcType)) { // GCC struct/union extension: allow cast to self. Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_nonscalar) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 1a30793f8ca44..4e475e56af85c 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -12692,8 +12692,8 @@ void Sema::CheckImplicitConversion(Expr *E, QualType T, SourceLocation CC, // type, to give us better diagnostics. Source = Context.getCanonicalType(SourceType).getTypePtr(); - if (const EnumType *SourceEnum = Source->getAs<EnumType>()) - if (const EnumType *TargetEnum = Target->getAs<EnumType>()) + if (const EnumType *SourceEnum = Source->getAsCanonical<EnumType>()) + if (const EnumType *TargetEnum = Target->getAsCanonical<EnumType>()) if (SourceEnum->getOriginalDecl()->hasNameForLinkage() && TargetEnum->getOriginalDecl()->hasNameForLinkage() && SourceEnum != TargetEnum) { diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index c3a61741cc874..3ded60cd8b073 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -233,7 +233,7 @@ static const RecordDecl *getRecordDecl(QualType QT) { return RD; // Now check if we point to a record. - if (const auto *PT = QT->getAs<PointerType>()) + if (const auto *PT = QT->getAsCanonical<PointerType>()) return PT->getPointeeType()->getAsRecordDecl(); return nullptr; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 5dc0a7eb4c29d..4b0dead182543 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -5472,7 +5472,8 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors, CXXCtorInitializer *Member = Initializers[i]; if (Member->isBaseInitializer()) - Info.AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member; + Info.AllBaseFields[Member->getBaseClass()->getAsCanonical<RecordType>()] = + Member; else { Info.AllBaseFields[Member->getAnyMember()->getCanonicalDecl()] = Member; @@ -5500,8 +5501,8 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors, // Push virtual bases before others. for (auto &VBase : ClassDecl->vbases()) { - if (CXXCtorInitializer *Value - = Info.AllBaseFields.lookup(VBase.getType()->getAs<RecordType>())) { + if (CXXCtorInitializer *Value = Info.AllBaseFields.lookup( + VBase.getType()->getAsCanonical<RecordType>())) { // [class.base.init]p7, per DR257: // A mem-initializer where the mem-initializer-id names a virtual base // class is ignored during execution of a constructor of any class that @@ -5539,8 +5540,8 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors, if (Base.isVirtual()) continue; - if (CXXCtorInitializer *Value - = Info.AllBaseFields.lookup(Base.getType()->getAs<RecordType>())) { + if (CXXCtorInitializer *Value = Info.AllBaseFields.lookup( + Base.getType()->getAsCanonical<RecordType>())) { Info.AllToInit.push_back(Value); } else if (!AnyErrors) { CXXCtorInitializer *CXXBaseInit; @@ -5628,7 +5629,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors, } static void PopulateKeysForFields(FieldDecl *Field, SmallVectorImpl<const void*> &IdealInits) { - if (const RecordType *RT = Field->getType()->getAs<RecordType>()) { + if (const RecordType *RT = Field->getType()->getAsCanonical<RecordType>()) { const RecordDecl *RD = RT->getOriginalDecl(); if (RD->isAnonymousStructOrUnion()) { for (auto *Field : RD->getDefinitionOrSelf()->fields()) @@ -7628,7 +7629,7 @@ static bool defaultedSpecialMemberIsConstexpr( F->hasInClassInitializer()) continue; QualType BaseType = S.Context.getBaseElementType(F->getType()); - if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) { + if (const RecordType *RecordTy = BaseType->getAsCanonical<RecordType>()) { CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getOriginalDecl()) ->getDefinitionOrSelf(); @@ -10623,7 +10624,8 @@ void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) { return; } - if (const auto *RT = FT->getBaseElementTypeUnsafe()->getAs<RecordType>()) + if (const auto *RT = + FT->getBaseElementTypeUnsafe()->getAsCanonical<RecordType>()) if (!RT->isDependentType() && !cast<CXXRecordDecl>(RT->getOriginalDecl()->getDefinitionOrSelf()) ->canPassInRegisters()) { @@ -16961,9 +16963,9 @@ checkLiteralOperatorTemplateParameterList(Sema &SemaRef, // first template parameter as its type. if (PmType && PmArgs && !PmType->isTemplateParameterPack() && PmArgs->isTemplateParameterPack()) { - const TemplateTypeParmType *TArgs = - PmArgs->getType()->getAs<TemplateTypeParmType>(); - if (TArgs && TArgs->getDepth() == PmType->getDepth() && + if (const auto *TArgs = + PmArgs->getType()->getAsCanonical<TemplateTypeParmType>(); + TArgs && TArgs->getDepth() == PmType->getDepth() && TArgs->getIndex() == PmType->getIndex()) { if (!SemaRef.inTemplateInstantiation()) SemaRef.Diag(TpDecl->getLocation(), diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 6797353db14bf..553965ff00f68 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1529,8 +1529,12 @@ void Sema::checkEnumArithmeticConversions(Expr *LHS, Expr *RHS, // are ill-formed. if (getLangOpts().CPlusPlus26) DiagID = diag::warn_conv_mixed_enum_types_cxx26; - else if (!L->castAs<EnumType>()->getOriginalDecl()->hasNameForLinkage() || - !R->castAs<EnumType>()->getOriginalDecl()->hasNameForLinkage()) { + else if (!L->castAsCanonical<EnumType>() + ->getOriginalDecl() + ->hasNameForLinkage() || + !R->castAsCanonical<EnumType>() + ->getOriginalDecl() + ->hasNameForLinkage()) { // If either enumeration type is unnamed, it's less likely that the // user cares about this, but this situation is still deprecated in // C++2a. Use a different warning group. @@ -11495,7 +11499,7 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS, } static bool isScopedEnumerationType(QualType T) { - if (const EnumType *ET = T->getAs<EnumType>()) + if (const EnumType *ET = T->getAsCanonical<EnumType>()) return ET->getOriginalDecl()->isScoped(); return false; } @@ -13819,7 +13823,7 @@ static void DiagnoseRecursiveConstFields(Sema &S, const ValueDecl *VD, // Then we append it to the list to check next in order. FieldTy = FieldTy.getCanonicalType(); - if (const auto *FieldRecTy = FieldTy->getAs<RecordType>()) { + if (const auto *FieldRecTy = FieldTy->getAsCanonical<RecordType>()) { if (!llvm::is_contained(RecordTypeList, FieldRecTy)) RecordTypeList.push_back(FieldRecTy); } @@ -13835,7 +13839,7 @@ static void DiagnoseRecursiveConstFields(Sema &S, const Expr *E, QualType Ty = E->getType(); assert(Ty->isRecordType() && "lvalue was not record?"); SourceRange Range = E->getSourceRange(); - const RecordType *RTy = Ty.getCanonicalType()->getAs<RecordType>(); + const auto *RTy = Ty->getAsCanonical<RecordType>(); bool DiagEmitted = false; if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 763fc0747eb82..5a9279d928465 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1973,8 +1973,8 @@ static UsualDeallocFnInfo resolveDeallocationOverload( static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc, TypeAwareAllocationMode PassType, QualType allocType) { - const RecordType *record = - allocType->getBaseElementTypeUnsafe()->getAs<RecordType>(); + const auto *record = + allocType->getBaseElementTypeUnsafe()->getAsCanonical<RecordType>(); if (!record) return false; // Try to find an operator delete[] in class scope. @@ -5519,8 +5519,8 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To, // the same or one is a base class of the other: QualType FTy = From->getType(); QualType TTy = To->getType(); - const RecordType *FRec = FTy->getAs<RecordType>(); - const RecordType *TRec = TTy->getAs<RecordType>(); + const RecordType *FRec = FTy->getAsCanonical<RecordType>(); + const RecordType *TRec = TTy->getAsCanonical<RecordType>(); bool FDerivedFromT = FRec && TRec && FRec != TRec && Self.IsDerivedFrom(QuestionLoc, FTy, TTy); if (FRec && TRec && (FRec == TRec || FDerivedFromT || diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 5684e53a6bcaa..331f6e585555b 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -3845,7 +3845,7 @@ static inline T *getObjCBridgeAttr(const TypedefType *TD) { QualType QT = TDNDecl->getUnderlyingType(); if (QT->isPointerType()) { QT = QT->getPointeeType(); - if (const RecordType *RT = QT->getAs<RecordType>()) { + if (const RecordType *RT = QT->getAsCanonical<RecordType>()) { for (auto *Redecl : RT->getOriginalDecl()->getMostRecentDecl()->redecls()) { if (auto *attr = Redecl->getAttr<T>()) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 4dfeebdea7919..c97129336736b 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -774,7 +774,7 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, = InitializedEntity::InitializeMember(Field, &ParentEntity); if (Init >= NumInits || !ILE->getInit(Init)) { - if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) + if (const RecordType *RType = ILE->getType()->getAsCanonical<RecordType>()) if (!RType->getOriginalDecl()->isUnion()) assert((Init < NumInits || VerifyOnly) && "This ILE should have been expanded"); diff --git a/clang/lib/Sema/SemaObjC.cpp b/clang/lib/Sema/SemaObjC.cpp index 8d8d5e87afe73..4f9470a361d2d 100644 --- a/clang/lib/Sema/SemaObjC.cpp +++ b/clang/lib/Sema/SemaObjC.cpp @@ -1380,7 +1380,7 @@ SemaObjC::ObjCSubscriptKind SemaObjC::CheckSubscriptingKind(Expr *FromE) { // If we don't have a class type in C++, there's no way we can get an // expression of integral or enumeration type. - const RecordType *RecordTy = T->getAs<RecordType>(); + const RecordType *RecordTy = T->getAsCanonical<RecordType>(); if (!RecordTy && (T->isObjCObjectPointerType() || T->isVoidPointerType())) // All other scalar cases are assumed to be dictionary indexing which // caller handles, with diagnostics if needed. @@ -1507,7 +1507,7 @@ bool SemaObjC::isCFStringType(QualType T) { if (!PT) return false; - const auto *RT = PT->getPointeeType()->getAs<RecordType>(); + const auto *RT = PT->getPointeeType()->getAsCanonical<RecordType>(); if (!RT) return false; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index d24550060893b..14fa8478fe317 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -3966,7 +3966,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // If the type we are conversion to is a class type, enumerate its // constructors. - if (const RecordType *ToRecordType = ToType->getAs<RecordType>()) { + if (const RecordType *ToRecordType = ToType->getAsCanonical<RecordType>()) { // C++ [over.match.ctor]p1: // When objects of class type are direct-initialized (8.5), or // copy-initialized from an expression of the same or a @@ -4056,7 +4056,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, } else if (!S.isCompleteType(From->getBeginLoc(), From->getType())) { // No conversion functions from incomplete types. } else if (const RecordType *FromRecordType = - From->getType()->getAs<RecordType>()) { + From->getType()->getAsCanonical<RecordType>()) { if (auto *FromRecordDecl = dyn_cast<CXXRecordDecl>(FromRecordType->getOriginalDecl())) { FromRecordDecl = FromRecordDecl->getDefinitionOrSelf(); @@ -6813,7 +6813,7 @@ ExprResult Sema::PerformContextualImplicitConversion( // We can only perform contextual implicit conversions on objects of class // type. - const RecordType *RecordTy = T->getAs<RecordType>(); + const RecordType *RecordTy = T->getAsCanonical<RecordType>(); if (!RecordTy || !getLangOpts().CPlusPlus) { if (!Converter.Suppress) Converter.diagnoseNoMatch(*this, Loc, T) << From->getSourceRange(); @@ -10195,7 +10195,9 @@ class BuiltinOperatorOverloadBuilder { if (S.getLangOpts().CPlusPlus11) { for (QualType EnumTy : CandidateTypes[ArgIdx].enumeration_types()) { - if (!EnumTy->castAs<EnumType>()->getOriginalDecl()->isScoped()) + if (!EnumTy->castAsCanonical<EnumType>() + ->getOriginalDecl() + ->isScoped()) continue; if (!AddedTypes.insert(S.Context.getCanonicalType(EnumTy)).second) diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index dda4e00119212..5625fb359807a 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -1271,8 +1271,8 @@ static void checkEnumTypesInSwitchStmt(Sema &S, const Expr *Cond, QualType CondType = Cond->getType(); QualType CaseType = Case->getType(); - const EnumType *CondEnumType = CondType->getAs<EnumType>(); - const EnumType *CaseEnumType = CaseType->getAs<EnumType>(); + const EnumType *CondEnumType = CondType->getAsCanonical<EnumType>(); + const EnumType *CaseEnumType = CaseType->getAsCanonical<EnumType>(); if (!CondEnumType || !CaseEnumType) return; diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp index f797756450298..0438af752a69e 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -885,18 +885,19 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member, for (StringRef NextMember : Members) { const RecordType *RT = nullptr; if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl)) - RT = VD->getType()->getAs<RecordType>(); + RT = VD->getType()->getAsCanonical<RecordType>(); else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(FoundDecl)) { MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false); // MS InlineAsm often uses struct pointer aliases as a base QualType QT = TD->getUnderlyingType(); if (const auto *PT = QT->getAs<PointerType>()) QT = PT->getPointeeType(); - RT = QT->getAs<RecordType>(); + RT = QT->getAsCanonical<RecordType>(); } else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl)) - RT = Context.getTypeDeclType(TD)->getAs<RecordType>(); + RT = QualType(Context.getCanonicalTypeDeclType(TD)) + ->getAsCanonical<RecordType>(); else if (FieldDecl *TD = dyn_cast<FieldDecl>(FoundDecl)) - RT = TD->getType()->getAs<RecordType>(); + RT = TD->getType()->getAsCanonical<RecordType>(); if (!RT) return true; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index e7d981a3210d1..3d8416ac7dc1b 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2859,14 +2859,14 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( } // Retrieve the parent of an enumeration type. - if (const EnumType *EnumT = T->getAs<EnumType>()) { + if (const EnumType *EnumT = T->getAsCanonical<EnumType>()) { // FIXME: Forward-declared enums require a TSK_ExplicitSpecialization // check here. EnumDecl *Enum = EnumT->getOriginalDecl(); // Get to the parent type. if (TypeDecl *Parent = dyn_cast<TypeDecl>(Enum->getParent())) - T = Context.getTypeDeclType(Parent); + T = Context.getCanonicalTypeDeclType(Parent); else T = QualType(); continue; @@ -3313,7 +3313,7 @@ static bool isInVkNamespace(const RecordType *RT) { static SpirvOperand checkHLSLSpirvTypeOperand(Sema &SemaRef, QualType OperandArg, SourceLocation Loc) { - if (auto *RT = OperandArg->getAs<RecordType>()) { + if (auto *RT = OperandArg->getAsCanonical<RecordType>()) { bool Literal = false; SourceLocation LiteralLoc; if (isInVkNamespace(RT) && RT->getOriginalDecl()->getName() == "Literal") { @@ -3323,7 +3323,7 @@ static SpirvOperand checkHLSLSpirvTypeOperand(Sema &SemaRef, const TemplateArgumentList &LiteralArgs = SpecDecl->getTemplateArgs(); QualType ConstantType = LiteralArgs[0].getAsType(); - RT = ConstantType->getAs<RecordType>(); + RT = ConstantType->getAsCanonical<RecordType>(); Literal = true; LiteralLoc = SpecDecl->getSourceRange().getBegin(); } @@ -4132,7 +4132,7 @@ static bool isTemplateArgumentTemplateParameter(const TemplateArgument &Arg, case TemplateArgument::Type: { QualType Type = Arg.getAsType(); const TemplateTypeParmType *TPT = - Arg.getAsType()->getAs<TemplateTypeParmType>(); + Arg.getAsType()->getAsCanonical<TemplateTypeParmType>(); return TPT && !Type.hasQualifiers() && TPT->getDepth() == Depth && TPT->getIndex() == Index; } diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index f481a009edab8..cce40c0c91f95 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -698,9 +698,8 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams, TNP = TP->getTemplateName(); // FIXME: To preserve sugar, the TST needs to carry sugared resolved // arguments. - PResolved = TP->getCanonicalTypeInternal() - ->castAs<TemplateSpecializationType>() - ->template_arguments(); + PResolved = + TP->castAsCanonical<TemplateSpecializationType>()->template_arguments(); } else { const auto *TT = P->castAs<InjectedClassNameType>(); TNP = TT->getTemplateName(S.Context); @@ -1437,7 +1436,8 @@ static bool isForwardingReference(QualType Param, unsigned FirstInnerIndex) { if (auto *ParamRef = Param->getAs<RValueReferenceType>()) { if (ParamRef->getPointeeType().getQualifiers()) return false; - auto *TypeParm = ParamRef->getPointeeType()->getAs<TemplateTypeParmType>(); + auto *TypeParm = + ParamRef->getPointeeType()->getAsCanonical<TemplateTypeParmType>(); return TypeParm && TypeParm->getIndex() >= FirstInnerIndex; } return false; @@ -1702,7 +1702,7 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( // // T // cv-list T - if (const auto *TTP = P->getAs<TemplateTypeParmType>()) { + if (const auto *TTP = P->getAsCanonical<TemplateTypeParmType>()) { // Just skip any attempts to deduce from a placeholder type or a parameter // at a different depth. if (A->isPlaceholderType() || Info.getDeducedDepth() != TTP->getDepth()) @@ -5596,7 +5596,7 @@ static TemplateDeductionResult CheckDeductionConsistency( // so let it transform their specializations instead. bool IsDeductionGuide = isa<CXXDeductionGuideDecl>(FTD->getTemplatedDecl()); if (IsDeductionGuide) { - if (auto *Injected = P->getAs<InjectedClassNameType>()) + if (auto *Injected = P->getAsCanonical<InjectedClassNameType>()) P = Injected->getOriginalDecl()->getCanonicalTemplateSpecializationType( S.Context); } @@ -5617,10 +5617,10 @@ static TemplateDeductionResult CheckDeductionConsistency( auto T1 = S.Context.getUnqualifiedArrayType(InstP.getNonReferenceType()); auto T2 = S.Context.getUnqualifiedArrayType(A.getNonReferenceType()); if (IsDeductionGuide) { - if (auto *Injected = T1->getAs<InjectedClassNameType>()) + if (auto *Injected = T1->getAsCanonical<InjectedClassNameType>()) T1 = Injected->getOriginalDecl()->getCanonicalTemplateSpecializationType( S.Context); - if (auto *Injected = T2->getAs<InjectedClassNameType>()) + if (auto *Injected = T2->getAsCanonical<InjectedClassNameType>()) T2 = Injected->getOriginalDecl()->getCanonicalTemplateSpecializationType( S.Context); } diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index 7a7aca8a52d68..3d54d1eb4373a 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -1056,7 +1056,7 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef, // The (trailing) return type of the deduction guide. const TemplateSpecializationType *FReturnType = RType->getAs<TemplateSpecializationType>(); - if (const auto *ICNT = RType->getAs<InjectedClassNameType>()) + if (const auto *ICNT = RType->getAsCanonical<InjectedClassNameType>()) // implicitly-generated deduction guide. FReturnType = cast<TemplateSpecializationType>( ICNT->getOriginalDecl()->getCanonicalTemplateSpecializationType( diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 051bf1462685f..8686bd94f1a2d 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -1583,8 +1583,8 @@ bool Sema::BuiltinIsBaseOf(SourceLocation RhsTLoc, QualType LhsT, // Base and Derived are not unions and name the same class type without // regard to cv-qualifiers. - const RecordType *lhsRecord = LhsT->getAs<RecordType>(); - const RecordType *rhsRecord = RhsT->getAs<RecordType>(); + const RecordType *lhsRecord = LhsT->getAsCanonical<RecordType>(); + const RecordType *rhsRecord = RhsT->getAsCanonical<RecordType>(); if (!rhsRecord || !lhsRecord) { const ObjCObjectType *LHSObjTy = LhsT->getAs<ObjCObjectType>(); const ObjCObjectType *RHSObjTy = RhsT->getAs<ObjCObjectType>(); @@ -1643,8 +1643,8 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, return Self.BuiltinIsBaseOf(Rhs->getTypeLoc().getBeginLoc(), LhsT, RhsT); case BTT_IsVirtualBaseOf: { - const RecordType *BaseRecord = LhsT->getAs<RecordType>(); - const RecordType *DerivedRecord = RhsT->getAs<RecordType>(); + const RecordType *BaseRecord = LhsT->getAsCanonical<RecordType>(); + const RecordType *DerivedRecord = RhsT->getAsCanonical<RecordType>(); if (!BaseRecord || !DerivedRecord) { DiagnoseVLAInCXXTypeTrait(Self, Lhs, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 79aca11839802..b089745bf5e03 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -17631,12 +17631,13 @@ TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base, SourceLocation CCLoc, SourceLocation TildeLoc, PseudoDestructorTypeStorage Destroyed) { - QualType BaseType = Base->getType(); + QualType CanonicalBaseType = Base->getType().getCanonicalType(); if (Base->isTypeDependent() || Destroyed.getIdentifier() || - (!isArrow && !BaseType->getAs<RecordType>()) || - (isArrow && BaseType->getAs<PointerType>() && - !BaseType->castAs<PointerType>()->getPointeeType() - ->template getAs<RecordType>())){ + (!isArrow && !isa<RecordType>(CanonicalBaseType)) || + (isArrow && isa<PointerType>(CanonicalBaseType) && + !cast<PointerType>(CanonicalBaseType) + ->getPointeeType() + ->getAsCanonical<RecordType>())) { // This pseudo-destructor expression is still a pseudo-destructor. return SemaRef.BuildPseudoDestructorExpr( Base, OperatorLoc, isArrow ? tok::arrow : tok::period, SS, ScopeType, diff --git a/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp index 91faefde43b00..c0727ae5dc8ba 100644 --- a/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp @@ -27,7 +27,7 @@ using namespace ento; //===----------------------------------------------------------------------===// static bool IsLLVMStringRef(QualType T) { - const RecordType *RT = T->getAs<RecordType>(); + const RecordType *RT = T->getAsCanonical<RecordType>(); if (!RT) return false; diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp index 36c12582a5787..884dbe90e7b12 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp @@ -241,7 +241,7 @@ void RetainTypeChecker::visitTypedef(const TypedefDecl *TD) { return; auto PointeeQT = QT->getPointeeType(); - const RecordType *RT = PointeeQT->getAs<RecordType>(); + const RecordType *RT = PointeeQT->getAsCanonical<RecordType>(); if (!RT) { if (TD->hasAttr<ObjCBridgeAttr>() || TD->hasAttr<ObjCBridgeMutableAttr>()) { RecordlessTypes.insert(TD->getASTContext() diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index 6a82aa7ba3936..8f18533af68b9 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -2454,7 +2454,7 @@ NonLoc RegionStoreManager::createLazyBinding(RegionBindingsConstRef B, SVal RegionStoreManager::getBindingForStruct(RegionBindingsConstRef B, const TypedValueRegion *R) { const RecordDecl *RD = - R->getValueType()->castAs<RecordType>()->getOriginalDecl(); + R->getValueType()->castAsCanonical<RecordType>()->getOriginalDecl(); if (!RD->getDefinition()) return UnknownVal(); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits