Author: Matheus Izvekov Date: 2025-08-27T06:20:14-03:00 New Revision: 88438ba1f37fa4e0c2db203cd5556e52c9c34c08
URL: https://github.com/llvm/llvm-project/commit/88438ba1f37fa4e0c2db203cd5556e52c9c34c08 DIFF: https://github.com/llvm/llvm-project/commit/88438ba1f37fa4e0c2db203cd5556e52c9c34c08.diff LOG: [clang] AST: fix getAs canonicalization of leaf types (#155028) Added: Modified: clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp clang/include/clang/AST/Type.h clang/include/clang/Basic/TypeNodes.td clang/lib/AST/ASTContext.cpp clang/lib/AST/ByteCode/Compiler.cpp clang/lib/AST/ByteCode/Pointer.cpp clang/lib/AST/CXXInheritance.cpp clang/lib/AST/Decl.cpp clang/lib/AST/DeclCXX.cpp clang/lib/AST/DeclarationName.cpp clang/lib/AST/ExprConstant.cpp clang/lib/AST/InheritViz.cpp clang/lib/AST/ItaniumMangle.cpp clang/lib/AST/JSONNodeDumper.cpp clang/lib/AST/RecordLayoutBuilder.cpp clang/lib/AST/TextNodeDumper.cpp clang/lib/AST/Type.cpp clang/lib/AST/TypePrinter.cpp clang/lib/CodeGen/ABIInfoImpl.cpp clang/lib/CodeGen/CGCall.cpp clang/lib/CodeGen/CGDebugInfo.cpp clang/lib/CodeGen/CGExprAgg.cpp clang/lib/CodeGen/CGExprCXX.cpp clang/lib/CodeGen/CGExprScalar.cpp clang/lib/CodeGen/CGNonTrivialStruct.cpp clang/lib/CodeGen/CGObjCMac.cpp clang/lib/CodeGen/CodeGenModule.cpp clang/lib/CodeGen/CodeGenTBAA.cpp clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp clang/lib/CodeGen/SwiftCallingConv.cpp clang/lib/CodeGen/Targets/AArch64.cpp clang/lib/CodeGen/Targets/ARC.cpp clang/lib/CodeGen/Targets/ARM.cpp clang/lib/CodeGen/Targets/DirectX.cpp clang/lib/CodeGen/Targets/Lanai.cpp clang/lib/CodeGen/Targets/LoongArch.cpp clang/lib/CodeGen/Targets/Mips.cpp clang/lib/CodeGen/Targets/RISCV.cpp clang/lib/CodeGen/Targets/SPIR.cpp clang/lib/CodeGen/Targets/X86.cpp clang/lib/CodeGen/Targets/XCore.cpp clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp clang/lib/Index/USRGeneration.cpp clang/lib/Sema/SemaBPF.cpp clang/lib/Sema/SemaCast.cpp clang/lib/Sema/SemaChecking.cpp clang/lib/Sema/SemaDeclAttr.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaExprCXX.cpp clang/lib/Sema/SemaExprObjC.cpp clang/lib/Sema/SemaInit.cpp clang/lib/Sema/SemaObjC.cpp clang/lib/Sema/SemaOverload.cpp clang/lib/Sema/SemaStmt.cpp clang/lib/Sema/SemaStmtAsm.cpp clang/lib/Sema/SemaTemplate.cpp clang/lib/Sema/SemaTemplateDeduction.cpp clang/lib/Sema/SemaTemplateDeductionGuide.cpp clang/lib/Sema/SemaTypeTraits.cpp clang/lib/Sema/TreeTransform.h clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp clang/lib/StaticAnalyzer/Core/RegionStore.cpp clang/test/CXX/drs/cwg0xx.cpp clang/test/CXX/drs/cwg3xx.cpp clang/test/ExtractAPI/class_template_param_inheritance.cpp clang/utils/TableGen/ASTTableGen.h clang/utils/TableGen/ClangTypeNodesEmitter.cpp Removed: ################################################################################ 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/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/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 3d652bcc874f2..dca05b41aee77 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2615,10 +2615,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 { @@ -3553,8 +3553,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 @@ -9278,8 +9277,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()) @@ -9322,8 +9321,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); @@ -9380,7 +9379,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: @@ -9447,7 +9446,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")) { @@ -11819,10 +11818,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 51d2fd21f0ba5..aa1f5a1146599 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -2314,7 +2314,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 c93a2186a93e1..0b1637af240cd 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 c6896fc70a169..e6113128a3e04 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,33 +698,31 @@ 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; } 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; } 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; } @@ -735,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; } @@ -1910,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; @@ -3233,7 +3231,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()) @@ -3243,7 +3241,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()) @@ -4414,7 +4412,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); } @@ -5418,7 +5416,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; @@ -5428,7 +5426,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>(); @@ -5437,7 +5435,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 29f825b49104e..d383544e54329 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 diff erent 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 diff erent 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 da372340fc60d..37552331478f1 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(); 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"; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits