diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index bcab4f1b8a729..506cc0a3b0e8f 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -901,9 +901,8 @@ parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir, if (!D->isThisDeclarationADefinition()) return; for (const CXXBaseSpecifier &B : D->bases()) { - if (const RecordType *Ty = B.getType()->getAs()) { - if (const CXXRecordDecl *Base = cast_or_null( - Ty->getOriginalDecl()->getDefinition())) { + if (const auto *Base = B.getType()->getAsCXXRecordDecl()) { + if (Base->isCompleteDefinition()) { // Initialized without USR and name, this will be set in the following // if-else stmt. BaseRecordInfo BI( diff --git a/clang-tools-extra/clang-tidy/cert/DefaultOperatorNewAlignmentCheck.cpp b/clang-tools-extra/clang-tidy/cert/DefaultOperatorNewAlignmentCheck.cpp index 2a0d0ada42b28..2c2248afb69e7 100644 --- a/clang-tools-extra/clang-tidy/cert/DefaultOperatorNewAlignmentCheck.cpp +++ b/clang-tools-extra/clang-tidy/cert/DefaultOperatorNewAlignmentCheck.cpp @@ -31,7 +31,7 @@ void DefaultOperatorNewAlignmentCheck::check( return; const TagDecl *D = T->getAsTagDecl(); // Alignment can not be obtained for undefined type. - if (!D || !D->getDefinition() || !D->isCompleteDefinition()) + if (!D || !D->isCompleteDefinition()) return; ASTContext &Context = D->getASTContext(); diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp index 40fd15c08f0a1..6508bfd5ca808 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp @@ -90,9 +90,8 @@ void SlicingCheck::diagnoseSlicedOverriddenMethods( } // Recursively process bases. for (const auto &Base : DerivedDecl.bases()) { - if (const auto *BaseRecordType = Base.getType()->getAs()) { - if (const auto *BaseRecord = cast_or_null( - BaseRecordType->getOriginalDecl()->getDefinition())) + if (const auto *BaseRecord = Base.getType()->getAsCXXRecordDecl()) { + if (BaseRecord->isCompleteDefinition()) diagnoseSlicedOverriddenMethods(Call, *BaseRecord, BaseDecl); } } diff --git a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp index 0302a5ad4957c..36b6007b58a51 100644 --- a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp +++ b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp @@ -71,13 +71,10 @@ bool MultipleInheritanceCheck::isInterface(const CXXRecordDecl *Node) { for (const auto &I : Node->bases()) { if (I.isVirtual()) continue; - const auto *Ty = I.getType()->getAs(); - if (!Ty) + const auto *Base = I.getType()->getAsCXXRecordDecl(); + if (!Base) continue; - const RecordDecl *D = Ty->getOriginalDecl()->getDefinition(); - if (!D) - continue; - const auto *Base = cast(D); + assert(Base->isCompleteDefinition()); if (!isInterface(Base)) { addNodeToInterfaceMap(Node, false); return false; @@ -103,11 +100,10 @@ void MultipleInheritanceCheck::check(const MatchFinder::MatchResult &Result) { for (const auto &I : D->bases()) { if (I.isVirtual()) continue; - const auto *Ty = I.getType()->getAs(); - if (!Ty) + const auto *Base = I.getType()->getAsCXXRecordDecl(); + if (!Base) continue; - const auto *Base = - cast(Ty->getOriginalDecl()->getDefinition()); + assert(Base->isCompleteDefinition()); if (!isInterface(Base)) NumConcrete++; } @@ -115,11 +111,10 @@ void MultipleInheritanceCheck::check(const MatchFinder::MatchResult &Result) { // Check virtual bases to see if there is more than one concrete // non-virtual base. for (const auto &V : D->vbases()) { - const auto *Ty = V.getType()->getAs(); - if (!Ty) + const auto *Base = V.getType()->getAsCXXRecordDecl(); + if (!Base) continue; - const auto *Base = - cast(Ty->getOriginalDecl()->getDefinition()); + assert(Base->isCompleteDefinition()); if (!isInterface(Base)) NumConcrete++; } diff --git a/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp b/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp index 5518afd32e7f0..f944306171135 100644 --- a/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp +++ b/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp @@ -119,9 +119,8 @@ bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context) { if (CanonicalType->isScalarType() || CanonicalType->isVectorType()) return true; - if (const auto *RT = CanonicalType->getAs()) { - return recordIsTriviallyDefaultConstructible( - *RT->getOriginalDecl()->getDefinitionOrSelf(), Context); + if (const auto *RD = CanonicalType->getAsRecordDecl()) { + return recordIsTriviallyDefaultConstructible(*RD, Context); } // No other types can match. diff --git a/clang/include/clang/AST/AbstractBasicReader.h b/clang/include/clang/AST/AbstractBasicReader.h index 26052b8086cf7..0d187eb49d6ca 100644 --- a/clang/include/clang/AST/AbstractBasicReader.h +++ b/clang/include/clang/AST/AbstractBasicReader.h @@ -193,7 +193,7 @@ class DataStreamBasicReader : public BasicReaderBase { auto elemTy = origTy; unsigned pathLength = asImpl().readUInt32(); for (unsigned i = 0; i < pathLength; ++i) { - if (elemTy->template getAs()) { + if (elemTy->isRecordType()) { unsigned int_ = asImpl().readUInt32(); Decl *decl = asImpl().template readDeclAs(); if (auto *recordDecl = dyn_cast(decl)) diff --git a/clang/include/clang/AST/AbstractBasicWriter.h b/clang/include/clang/AST/AbstractBasicWriter.h index d41e655986ef9..8ea0c29cf5070 100644 --- a/clang/include/clang/AST/AbstractBasicWriter.h +++ b/clang/include/clang/AST/AbstractBasicWriter.h @@ -176,7 +176,7 @@ class DataStreamBasicWriter : public BasicWriterBase { asImpl().writeUInt32(path.size()); auto &ctx = ((BasicWriterBase *)this)->getASTContext(); for (auto elem : path) { - if (elemTy->getAs()) { + if (elemTy->isRecordType()) { asImpl().writeUInt32(elem.getAsBaseOrMember().getInt()); const Decl *baseOrMember = elem.getAsBaseOrMember().getPointer(); if (const auto *recordDecl = dyn_cast(baseOrMember)) { diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 1d2ef0f4f2319..3ee03122f50cf 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -3825,7 +3825,9 @@ class UsingEnumDecl : public BaseUsingDecl, public Mergeable { void setEnumType(TypeSourceInfo *TSI) { EnumType = TSI; } public: - EnumDecl *getEnumDecl() const { return cast(EnumType->getType()->getAsTagDecl()); } + EnumDecl *getEnumDecl() const { + return cast(EnumType->getType())->getOriginalDecl(); + } static UsingEnumDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation UsingL, SourceLocation EnumL, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index a78f5635f44da..c3fb57774c8dc 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5404,7 +5404,7 @@ class Sema final : public SemaBase { /// FinalizeVarWithDestructor - Prepare for calling destructor on the /// constructed variable. - void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType); + void FinalizeVarWithDestructor(VarDecl *VD, CXXRecordDecl *DeclInit); /// Helper class that collects exception specifications for /// implicitly-declared special member functions. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index bbb957067c4c8..036df53063568 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -654,9 +654,9 @@ comments::FullComment *ASTContext::getCommentForDecl( // does not have one of its own. QualType QT = TD->getUnderlyingType(); if (const auto *TT = QT->getAs()) - if (const Decl *TD = TT->getOriginalDecl()) - if (comments::FullComment *FC = getCommentForDecl(TD, PP)) - return cloneFullComment(FC, D); + if (comments::FullComment *FC = + getCommentForDecl(TT->getOriginalDecl(), PP)) + return cloneFullComment(FC, D); } else if (const auto *IC = dyn_cast(D)) { while (IC->getSuperClass()) { @@ -1933,12 +1933,9 @@ TypeInfoChars ASTContext::getTypeInfoDataSizeInChars(QualType T) const { // of a base-class subobject. We decide whether that's possible // during class layout, so here we can just trust the layout results. if (getLangOpts().CPlusPlus) { - if (const auto *RT = T->getAs()) { - const auto *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); - if (!RD->isInvalidDecl()) { - const ASTRecordLayout &layout = getASTRecordLayout(RD); - Info.Width = layout.getDataSize(); - } + if (const auto *RD = T->getAsCXXRecordDecl(); RD && !RD->isInvalidDecl()) { + const ASTRecordLayout &layout = getASTRecordLayout(RD); + Info.Width = layout.getDataSize(); } } @@ -2694,9 +2691,7 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { if (!Target->allowsLargerPreferedTypeAlignment()) return ABIAlign; - if (const auto *RT = T->getAs()) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); - + if (const auto *RD = T->getAsRecordDecl()) { // When used as part of a typedef, or together with a 'packed' attribute, // the 'aligned' attribute can be used to decrease alignment. Note that the // 'packed' case is already taken into consideration when computing the @@ -2887,12 +2882,10 @@ structHasUniqueObjectRepresentations(const ASTContext &Context, static std::optional getSubobjectSizeInBits(const FieldDecl *Field, const ASTContext &Context, bool CheckIfTriviallyCopyable) { - if (Field->getType()->isRecordType()) { - const RecordDecl *RD = Field->getType()->getAsRecordDecl(); - if (!RD->isUnion()) - return structHasUniqueObjectRepresentations(Context, RD, - CheckIfTriviallyCopyable); - } + if (const auto *RD = Field->getType()->getAsRecordDecl(); + RD && !RD->isUnion()) + return structHasUniqueObjectRepresentations(Context, RD, + CheckIfTriviallyCopyable); // A _BitInt type may not be unique if it has padding bits // but if it is a bitfield the padding bits are not used. @@ -3047,10 +3040,7 @@ bool ASTContext::hasUniqueObjectRepresentations( if (const auto *MPT = Ty->getAs()) return !ABI->getMemberPointerInfo(MPT).HasPadding; - if (Ty->isRecordType()) { - const RecordDecl *Record = - Ty->castAs()->getOriginalDecl()->getDefinitionOrSelf(); - + if (const auto *Record = Ty->getAsRecordDecl()) { if (Record->isInvalidDecl()) return false; diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 6d83de384ee10..1292c30d47589 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -878,10 +878,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, // Treat the enumeration as its underlying type and use the builtin type // class comparison. if (T1->getTypeClass() == Type::Enum) { - T1 = T1->getAs()->getOriginalDecl()->getIntegerType(); + T1 = cast(T1)->getOriginalDecl()->getIntegerType(); assert(T2->isBuiltinType() && !T1.isNull()); // Sanity check } else if (T2->getTypeClass() == Type::Enum) { - T2 = T2->getAs()->getOriginalDecl()->getIntegerType(); + T2 = cast(T2)->getOriginalDecl()->getIntegerType(); assert(T1->isBuiltinType() && !T2.isNull()); // Sanity check } TC = Type::Builtin; diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 2e28814abfddb..e245f24e614e5 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -3303,11 +3303,8 @@ bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E, switch (Node.getKind()) { case OffsetOfNode::Field: { const FieldDecl *MemberDecl = Node.getField(); - const RecordType *RT = CurrentType->getAs(); - if (!RT) - return false; - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); - if (RD->isInvalidDecl()) + const auto *RD = CurrentType->getAsRecordDecl(); + if (!RD || RD->isInvalidDecl()) return false; const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD); unsigned FieldIndex = MemberDecl->getFieldIndex(); @@ -3336,23 +3333,19 @@ bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E, return false; // Find the layout of the class whose base we are looking into. - const RecordType *RT = CurrentType->getAs(); - if (!RT) - return false; - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); - if (RD->isInvalidDecl()) + const auto *RD = CurrentType->getAsCXXRecordDecl(); + if (!RD || RD->isInvalidDecl()) return false; const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD); // Find the base class itself. CurrentType = BaseSpec->getType(); - const RecordType *BaseRT = CurrentType->getAs(); - if (!BaseRT) + const auto *BaseRD = CurrentType->getAsCXXRecordDecl(); + if (!BaseRD) return false; // Add the offset to the base. - Result += RL.getBaseClassOffset(cast( - BaseRT->getOriginalDecl()->getDefinitionOrSelf())); + Result += RL.getBaseClassOffset(BaseRD); break; } case OffsetOfNode::Identifier: diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp index 5d72044af969e..139cae7afc87e 100644 --- a/clang/lib/AST/ByteCode/Program.cpp +++ b/clang/lib/AST/ByteCode/Program.cpp @@ -332,10 +332,9 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { continue; // In error cases, the base might not be a RecordType. - const auto *RT = Spec.getType()->getAs(); - if (!RT) + const auto *BD = Spec.getType()->getAsCXXRecordDecl(); + if (!BD) return nullptr; - const RecordDecl *BD = RT->getOriginalDecl()->getDefinitionOrSelf(); const Record *BR = getOrCreateRecord(BD); const Descriptor *Desc = GetBaseDesc(BD, BR); @@ -408,9 +407,8 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, const Expr *Init) { // Classes and structures. - if (const auto *RT = Ty->getAs()) { - if (const auto *Record = - getOrCreateRecord(RT->getOriginalDecl()->getDefinitionOrSelf())) + if (const auto *RD = Ty->getAsRecordDecl()) { + if (const auto *Record = getOrCreateRecord(RD)) return allocateDescriptor(D, Record, MDSize, IsConst, IsTemporary, IsMutable, IsVolatile); return allocateDescriptor(D, MDSize); diff --git a/clang/lib/AST/ByteCode/Record.cpp b/clang/lib/AST/ByteCode/Record.cpp index a7934ccb4e55e..c20ec184f34f4 100644 --- a/clang/lib/AST/ByteCode/Record.cpp +++ b/clang/lib/AST/ByteCode/Record.cpp @@ -50,10 +50,8 @@ const Record::Base *Record::getBase(const RecordDecl *FD) const { } const Record::Base *Record::getBase(QualType T) const { - if (auto *RT = T->getAs()) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + if (auto *RD = T->getAsCXXRecordDecl()) return BaseMap.lookup(RD); - } return nullptr; } diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp index e4b77edc063dc..0ced210900b1a 100644 --- a/clang/lib/AST/CXXInheritance.cpp +++ b/clang/lib/AST/CXXInheritance.cpp @@ -128,17 +128,11 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches) const { const CXXRecordDecl *Record = this; while (true) { for (const auto &I : Record->bases()) { - const RecordType *Ty = I.getType()->getAs(); - if (!Ty) + const auto *Base = I.getType()->getAsCXXRecordDecl(); + if (!Base || !(Base->isBeingDefined() || Base->isCompleteDefinition())) return false; - - CXXRecordDecl *Base = cast_if_present( - Ty->getOriginalDecl()->getDefinition()); - if (!Base || - (Base->isDependentContext() && - !Base->isCurrentInstantiation(Record))) { + if (Base->isDependentContext() && !Base->isCurrentInstantiation(Record)) return false; - } Queue.push_back(Base); if (!BaseMatches(Base)) @@ -255,9 +249,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, const TemplateSpecializationType *TST = BaseSpec.getType()->getAs(); if (!TST) { - if (auto *RT = BaseSpec.getType()->getAs()) - BaseRecord = cast(RT->getOriginalDecl()) - ->getDefinitionOrSelf(); + BaseRecord = BaseSpec.getType()->getAsCXXRecordDecl(); } else { TemplateName TN = TST->getTemplateName(); if (auto *TD = @@ -347,11 +339,8 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback BaseMatches, // base is a subobject of any other path; if so, then the // declaration in this path are hidden by that patch. for (const CXXBasePath &HidingP : Paths) { - CXXRecordDecl *HidingClass = nullptr; - if (const RecordType *Record = - HidingP.back().Base->getType()->getAs()) - HidingClass = cast(Record->getOriginalDecl()) - ->getDefinitionOrSelf(); + auto *HidingClass = + HidingP.back().Base->getType()->getAsCXXRecordDecl(); if (!HidingClass) break; @@ -470,9 +459,7 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, = ++SubobjectCount[cast(RD->getCanonicalDecl())]; for (const auto &Base : RD->bases()) { - if (const RecordType *RT = Base.getType()->getAs()) { - const CXXRecordDecl *BaseDecl = - cast(RT->getOriginalDecl())->getDefinitionOrSelf(); + if (const auto *BaseDecl = Base.getType()->getAsCXXRecordDecl()) { if (!BaseDecl->isPolymorphic()) continue; diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 4507f415ce606..c44bf739dca2d 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2861,9 +2861,8 @@ VarDecl::needsDestruction(const ASTContext &Ctx) const { bool VarDecl::hasFlexibleArrayInit(const ASTContext &Ctx) const { assert(hasInit() && "Expect initializer to check for flexible array init"); - auto *Ty = getType()->getAs(); - if (!Ty || - !Ty->getOriginalDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember()) + auto *D = getType()->getAsRecordDecl(); + if (!D || !D->hasFlexibleArrayMember()) return false; auto *List = dyn_cast(getInit()->IgnoreParens()); if (!List) @@ -2877,11 +2876,8 @@ bool VarDecl::hasFlexibleArrayInit(const ASTContext &Ctx) const { CharUnits VarDecl::getFlexibleArrayInitChars(const ASTContext &Ctx) const { assert(hasInit() && "Expect initializer to check for flexible array init"); - auto *Ty = getType()->getAs(); - if (!Ty) - return CharUnits::Zero(); - const RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf(); - if (!Ty || !RD->hasFlexibleArrayMember()) + auto *RD = getType()->getAsRecordDecl(); + if (!RD || !RD->hasFlexibleArrayMember()) return CharUnits::Zero(); auto *List = dyn_cast(getInit()->IgnoreParens()); if (!List || List->getNumInits() == 0) @@ -4738,7 +4734,7 @@ bool FieldDecl::isZeroSize(const ASTContext &Ctx) const { // MS ABI: has nonzero size if it is a class type with class type fields, // whether or not they have nonzero size return !llvm::any_of(CXXRD->fields(), [](const FieldDecl *Field) { - return Field->getType()->getAs(); + return Field->getType()->isRecordType(); }); } @@ -5274,10 +5270,8 @@ const FieldDecl *RecordDecl::findFirstNamedDataMember() const { if (I->getIdentifier()) return I; - if (const auto *RT = I->getType()->getAs()) - if (const FieldDecl *NamedDataMember = RT->getOriginalDecl() - ->getDefinitionOrSelf() - ->findFirstNamedDataMember()) + if (const auto *RD = I->getType()->getAsRecordDecl()) + if (const FieldDecl *NamedDataMember = RD->findFirstNamedDataMember()) return NamedDataMember; } diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 50b1a1d000090..62eb4de8c6a96 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1207,9 +1207,8 @@ void CXXRecordDecl::addedMember(Decl *D) { // those because they are always unnamed. bool IsZeroSize = Field->isZeroSize(Context); - if (const auto *RecordTy = T->getAs()) { - auto *FieldRec = cast(RecordTy->getOriginalDecl()); - if (FieldRec->getDefinition()) { + if (auto *FieldRec = T->getAsCXXRecordDecl()) { + if (FieldRec->isBeingDefined() || FieldRec->isCompleteDefinition()) { addedClassSubobject(FieldRec); // We may need to perform overload resolution to determine whether a @@ -1908,15 +1907,14 @@ static void CollectVisibleConversions( // Collect information recursively from any base classes. for (const auto &I : Record->bases()) { - const auto *RT = I.getType()->getAs(); - if (!RT) continue; + const auto *Base = I.getType()->getAsCXXRecordDecl(); + if (!Base) + continue; AccessSpecifier BaseAccess = CXXRecordDecl::MergeAccess(Access, I.getAccessSpecifier()); bool BaseInVirtual = InVirtual || I.isVirtual(); - auto *Base = - cast(RT->getOriginalDecl())->getDefinitionOrSelf(); CollectVisibleConversions(Context, Base, BaseInVirtual, BaseAccess, *HiddenTypes, Output, VOutput, HiddenVBaseCs); } @@ -1951,14 +1949,13 @@ static void CollectVisibleConversions(ASTContext &Context, // Recursively collect conversions from base classes. for (const auto &I : Record->bases()) { - const auto *RT = I.getType()->getAs(); - if (!RT) continue; + const auto *Base = I.getType()->getAsCXXRecordDecl(); + if (!Base) + continue; - CollectVisibleConversions( - Context, - cast(RT->getOriginalDecl())->getDefinitionOrSelf(), - I.isVirtual(), I.getAccessSpecifier(), HiddenTypes, Output, VBaseCs, - HiddenVBaseCs); + CollectVisibleConversions(Context, Base, I.isVirtual(), + I.getAccessSpecifier(), HiddenTypes, Output, + VBaseCs, HiddenVBaseCs); } // Add any unhidden conversions provided by virtual bases. @@ -2472,11 +2469,9 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD, }; for (const auto &I : RD->bases()) { - const RecordType *RT = I.getType()->getAs(); - if (!RT) + const auto *Base = I.getType()->getAsCXXRecordDecl(); + if (!Base) continue; - const auto *Base = - cast(RT->getOriginalDecl())->getDefinitionOrSelf(); if (CXXMethodDecl *D = this->getCorrespondingMethodInClass(Base)) AddFinalOverrider(D); } diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index b91b4670c63a3..3162857aac5d0 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -730,15 +730,15 @@ void TemplateTypeParmDecl::setDefaultArgument( } unsigned TemplateTypeParmDecl::getDepth() const { - return getTypeForDecl()->castAs()->getDepth(); + return dyn_cast(getTypeForDecl())->getDepth(); } unsigned TemplateTypeParmDecl::getIndex() const { - return getTypeForDecl()->castAs()->getIndex(); + return dyn_cast(getTypeForDecl())->getIndex(); } bool TemplateTypeParmDecl::isParameterPack() const { - return getTypeForDecl()->castAs()->isParameterPack(); + return dyn_cast(getTypeForDecl())->isParameterPack(); } void TemplateTypeParmDecl::setTypeConstraint( diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index cdb63dbe3daf4..ee0ac4effab0e 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -15407,10 +15407,9 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) { case OffsetOfNode::Field: { FieldDecl *MemberDecl = ON.getField(); - const RecordType *RT = CurrentType->getAs(); - if (!RT) + const auto *RD = CurrentType->getAsRecordDecl(); + if (!RD) return Error(OOE); - RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD); unsigned i = MemberDecl->getFieldIndex(); @@ -15429,22 +15428,20 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) { return Error(OOE); // Find the layout of the class whose base we are looking into. - const RecordType *RT = CurrentType->getAs(); - if (!RT) + const auto *RD = CurrentType->getAsCXXRecordDecl(); + if (!RD) return Error(OOE); - RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD); // Find the base class itself. CurrentType = BaseSpec->getType(); - const RecordType *BaseRT = CurrentType->getAs(); - if (!BaseRT) + const auto *BaseRD = CurrentType->getAsCXXRecordDecl(); + if (!BaseRD) return Error(OOE); // Add the offset to the base. - Result += RL.getBaseClassOffset(cast( - BaseRT->getOriginalDecl()->getDefinitionOrSelf())); + Result += RL.getBaseClassOffset(BaseRD); break; } } diff --git a/clang/lib/AST/FormatString.cpp b/clang/lib/AST/FormatString.cpp index 502a3e6b145e3..a73c02734e558 100644 --- a/clang/lib/AST/FormatString.cpp +++ b/clang/lib/AST/FormatString.cpp @@ -655,7 +655,7 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { // to Objective-C objects. Since the compiler doesn't know which // structs can be toll-free bridged, we just accept them all. QualType pointee = PT->getPointeeType(); - if (pointee->getAsStructureType() || pointee->isVoidType()) + if (pointee->isStructureType() || pointee->isVoidType()) return Match; } return NoMatch; diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 112678fb2714a..c7eaad47710df 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -6997,8 +6997,8 @@ static bool hasMangledSubstitutionQualifiers(QualType T) { bool CXXNameMangler::mangleSubstitution(QualType T) { if (!hasMangledSubstitutionQualifiers(T)) { - if (const RecordType *RT = T->getAs()) - return mangleSubstitution(RT->getOriginalDecl()->getDefinitionOrSelf()); + if (const auto *RD = T->getAsCXXRecordDecl()) + return mangleSubstitution(RD); } uintptr_t TypePtr = reinterpret_cast(T.getAsOpaquePtr()); @@ -7168,8 +7168,8 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) { void CXXNameMangler::addSubstitution(QualType T) { if (!hasMangledSubstitutionQualifiers(T)) { - if (const RecordType *RT = T->getAs()) { - addSubstitution(RT->getOriginalDecl()->getDefinitionOrSelf()); + if (const auto *RD = T->getAsCXXRecordDecl()) { + addSubstitution(RD); return; } } diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index f1f21f426f944..e6729f8fbba70 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -204,15 +204,13 @@ void EmptySubobjectMap::ComputeEmptySubobjectSizes() { // Check the fields. for (const FieldDecl *FD : Class->fields()) { - const RecordType *RT = - Context.getBaseElementType(FD->getType())->getAs(); - - // We only care about record types. - if (!RT) + // We only care about records. + const auto *MemberDecl = + Context.getBaseElementType(FD->getType())->getAsCXXRecordDecl(); + if (!MemberDecl) continue; CharUnits EmptySize; - const CXXRecordDecl *MemberDecl = RT->getAsCXXRecordDecl(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(MemberDecl); if (MemberDecl->isEmpty()) { // If the class decl is empty, get its size. @@ -433,11 +431,10 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD, // If we have an array type we need to look at every element. if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) { QualType ElemTy = Context.getBaseElementType(AT); - const RecordType *RT = ElemTy->getAs(); - if (!RT) + const auto *RD = ElemTy->getAsCXXRecordDecl(); + if (!RD) return true; - const CXXRecordDecl *RD = RT->getAsCXXRecordDecl(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); uint64_t NumElements = Context.getConstantArrayElementCount(AT); @@ -533,11 +530,10 @@ void EmptySubobjectMap::UpdateEmptyFieldSubobjects( // If we have an array type we need to update every element. if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) { QualType ElemTy = Context.getBaseElementType(AT); - const RecordType *RT = ElemTy->getAs(); - if (!RT) + const auto *RD = ElemTy->getAsCXXRecordDecl(); + if (!RD) return; - const CXXRecordDecl *RD = RT->getAsCXXRecordDecl(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); uint64_t NumElements = Context.getConstantArrayElementCount(AT); @@ -3695,9 +3691,9 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, Offset + C.toCharUnitsFromBits(LocalFieldOffsetInBits); // Recursively dump fields of record type. - if (auto RT = Field->getType()->getAs()) { - DumpRecordLayout(OS, RT->getOriginalDecl()->getDefinitionOrSelf(), C, - FieldOffset, IndentLevel, Field->getName().data(), + if (const auto *RD = Field->getType()->getAsRecordDecl()) { + DumpRecordLayout(OS, RD, C, FieldOffset, IndentLevel, + Field->getName().data(), /*PrintSizeInfo=*/false, /*IncludeVirtualBases=*/true); continue; diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index a70bc5424009c..9df01b8b361c1 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -113,10 +113,8 @@ const IdentifierInfo *QualType::getBaseTypeIdentifier() const { return DNT->getIdentifier(); if (ty->isPointerOrReferenceType()) return ty->getPointeeType().getBaseTypeIdentifier(); - if (ty->isRecordType()) - ND = ty->castAs()->getOriginalDecl(); - else if (ty->isEnumeralType()) - ND = ty->castAs()->getOriginalDecl(); + if (const auto *TT = ty->getAs()) + ND = TT->getOriginalDecl(); else if (ty->getTypeClass() == Type::Typedef) ND = ty->castAs()->getDecl(); else if (ty->isArrayType()) @@ -2459,8 +2457,8 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const { /// includes union types. bool Type::isAggregateType() const { if (const auto *Record = dyn_cast(CanonicalType)) { - if (const auto *ClassDecl = dyn_cast( - Record->getOriginalDecl()->getDefinitionOrSelf())) + if (const auto *ClassDecl = + dyn_cast(Record->getOriginalDecl())) return ClassDecl->isAggregate(); return true; @@ -2573,7 +2571,7 @@ bool Type::isAlwaysIncompleteType() const { // Forward declarations of structs, classes, enums, and unions could be later // completed in a compilation unit by providing a type definition. - if (getAsTagDecl()) + if (isa(CanonicalType)) return false; // Other types are incompletable. @@ -2797,7 +2795,7 @@ bool QualType::isCXX98PODType(const ASTContext &Context) const { case Type::Record: if (const auto *ClassDecl = dyn_cast( cast(CanonicalType)->getOriginalDecl())) - return ClassDecl->getDefinitionOrSelf()->isPOD(); + return ClassDecl->isPOD(); // C struct/union is POD. return true; @@ -2837,23 +2835,22 @@ bool QualType::isTrivialType(const ASTContext &Context) const { // As an extension, Clang treats vector types as Scalar types. if (CanonicalType->isScalarType() || CanonicalType->isVectorType()) return true; - if (const auto *RT = CanonicalType->getAs()) { - if (const auto *ClassDecl = - dyn_cast(RT->getOriginalDecl())) { - // C++20 [class]p6: - // A trivial class is a class that is trivially copyable, and - // has one or more eligible default constructors such that each is - // trivial. - // FIXME: We should merge this definition of triviality into - // CXXRecordDecl::isTrivial. Currently it computes the wrong thing. - return ClassDecl->hasTrivialDefaultConstructor() && - !ClassDecl->hasNonTrivialDefaultConstructor() && - ClassDecl->isTriviallyCopyable(); - } - return true; + if (const auto *ClassDecl = CanonicalType->getAsCXXRecordDecl()) { + // C++20 [class]p6: + // A trivial class is a class that is trivially copyable, and + // has one or more eligible default constructors such that each is + // trivial. + // FIXME: We should merge this definition of triviality into + // CXXRecordDecl::isTrivial. Currently it computes the wrong thing. + return ClassDecl->hasTrivialDefaultConstructor() && + !ClassDecl->hasNonTrivialDefaultConstructor() && + ClassDecl->isTriviallyCopyable(); } + if (isa(CanonicalType)) + return true; + // No other types can match. return false; } @@ -2897,18 +2894,13 @@ static bool isTriviallyCopyableTypeImpl(const QualType &type, if (CanonicalType->isMFloat8Type()) return true; - if (const auto *RT = CanonicalType->getAs()) { - if (const auto *ClassDecl = - dyn_cast(RT->getOriginalDecl())) { - if (IsCopyConstructible) { + if (const auto *RD = CanonicalType->getAsRecordDecl()) { + if (const auto *ClassDecl = dyn_cast(RD)) { + if (IsCopyConstructible) return ClassDecl->isTriviallyCopyConstructible(); - } else { - return ClassDecl->isTriviallyCopyable(); - } + return ClassDecl->isTriviallyCopyable(); } - return !RT->getOriginalDecl() - ->getDefinitionOrSelf() - ->isNonTrivialToPrimitiveCopy(); + return !RD->isNonTrivialToPrimitiveCopy(); } // No other types can match. return false; @@ -2996,11 +2988,9 @@ bool QualType::isWebAssemblyFuncrefType() const { QualType::PrimitiveDefaultInitializeKind QualType::isNonTrivialToPrimitiveDefaultInitialize() const { - if (const auto *RT = - getTypePtr()->getBaseElementTypeUnsafe()->getAs()) - if (RT->getOriginalDecl() - ->getDefinitionOrSelf() - ->isNonTrivialToPrimitiveDefaultInitialize()) + if (const auto *RD = + getTypePtr()->getBaseElementTypeUnsafe()->getAsRecordDecl()) + if (RD->isNonTrivialToPrimitiveDefaultInitialize()) return PDIK_Struct; switch (getQualifiers().getObjCLifetime()) { @@ -3014,11 +3004,9 @@ QualType::isNonTrivialToPrimitiveDefaultInitialize() const { } QualType::PrimitiveCopyKind QualType::isNonTrivialToPrimitiveCopy() const { - if (const auto *RT = - getTypePtr()->getBaseElementTypeUnsafe()->getAs()) - if (RT->getOriginalDecl() - ->getDefinitionOrSelf() - ->isNonTrivialToPrimitiveCopy()) + if (const auto *RD = + getTypePtr()->getBaseElementTypeUnsafe()->getAsRecordDecl()) + if (RD->isNonTrivialToPrimitiveCopy()) return PCK_Struct; Qualifiers Qs = getQualifiers(); @@ -3075,7 +3063,7 @@ bool Type::isLiteralType(const ASTContext &Ctx) const { if (BaseTy->isReferenceType()) return true; // -- a class type that has all of the following properties: - if (const auto *RT = BaseTy->getAs()) { + if (const auto *RD = BaseTy->getAsRecordDecl()) { // -- a trivial destructor, // -- every constructor call and full-expression in the // brace-or-equal-initializers for non-static data members (if any) @@ -3086,8 +3074,8 @@ bool Type::isLiteralType(const ASTContext &Ctx) const { // -- all non-static data members and base classes of literal types // // We resolve DR1361 by ignoring the second bullet. - if (const auto *ClassDecl = dyn_cast(RT->getOriginalDecl())) - return ClassDecl->getDefinitionOrSelf()->isLiteral(); + if (const auto *ClassDecl = dyn_cast(RD)) + return ClassDecl->isLiteral(); return true; } @@ -3139,10 +3127,10 @@ bool Type::isStandardLayoutType() const { // As an extension, Clang treats vector types as Scalar types. if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true; - if (const auto *RT = BaseTy->getAs()) { - if (const auto *ClassDecl = dyn_cast(RT->getOriginalDecl())) - if (!ClassDecl->getDefinitionOrSelf()->isStandardLayout()) - return false; + if (const auto *RD = BaseTy->getAsRecordDecl()) { + if (const auto *ClassDecl = dyn_cast(RD); + ClassDecl && !ClassDecl->isStandardLayout()) + return false; // Default to 'true' for non-C++ class types. // FIXME: This is a bit dubious, but plain C structs should trivially meet @@ -3182,10 +3170,8 @@ bool QualType::isCXX11PODType(const ASTContext &Context) const { // As an extension, Clang treats vector types as Scalar types. if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true; - if (const auto *RT = BaseTy->getAs()) { - if (const auto *ClassDecl = - dyn_cast(RT->getOriginalDecl())) { - ClassDecl = ClassDecl->getDefinitionOrSelf(); + if (const auto *RD = BaseTy->getAsRecordDecl()) { + if (const auto *ClassDecl = dyn_cast(RD)) { // C++11 [class]p10: // A POD struct is a non-union class that is both a trivial class [...] if (!ClassDecl->isTrivial()) @@ -5503,8 +5489,7 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) { return DK_objc_weak_lifetime; } - if (const auto *RT = type->getBaseElementTypeUnsafe()->getAs()) { - const RecordDecl *RD = RT->getOriginalDecl(); + if (const auto *RD = type->getBaseElementTypeUnsafe()->getAsRecordDecl()) { if (const auto *CXXRD = dyn_cast(RD)) { /// Check if this is a C++ object with a non-trivial destructor. if (CXXRD->hasDefinition() && !CXXRD->hasTrivialDestructor()) @@ -5512,7 +5497,7 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) { } else { /// Check if this is a C struct that is non-trivial to destroy or an array /// that contains such a struct. - if (RD->getDefinitionOrSelf()->isNonTrivialToPrimitiveDestroy()) + if (RD->isNonTrivialToPrimitiveDestroy()) return DK_nontrivial_c_struct; } } diff --git a/clang/lib/Analysis/ExprMutationAnalyzer.cpp b/clang/lib/Analysis/ExprMutationAnalyzer.cpp index 823d7543f085f..3fcd3481c2d6b 100644 --- a/clang/lib/Analysis/ExprMutationAnalyzer.cpp +++ b/clang/lib/Analysis/ExprMutationAnalyzer.cpp @@ -703,7 +703,8 @@ ExprMutationAnalyzer::Analyzer::findFunctionArgMutation(const Expr *Exp) { // definition and see whether the param is mutated inside. if (const auto *RefType = ParmType->getAs()) { if (!RefType->getPointeeType().getQualifiers() && - RefType->getPointeeType()->getAs()) { + isa( + RefType->getPointeeType().getCanonicalType())) { FunctionParmMutationAnalyzer *Analyzer = FunctionParmMutationAnalyzer::getFunctionParmMutationAnalyzer( *Func, Context, Memorized); diff --git a/clang/lib/Analysis/ThreadSafetyCommon.cpp b/clang/lib/Analysis/ThreadSafetyCommon.cpp index f560dd8ae1dd1..68c27eeb7e8e6 100644 --- a/clang/lib/Analysis/ThreadSafetyCommon.cpp +++ b/clang/lib/Analysis/ThreadSafetyCommon.cpp @@ -83,13 +83,11 @@ static std::pair classifyCapability(QualType QT) { // We need to look at the declaration of the type of the value to determine // which it is. The type should either be a record or a typedef, or a pointer // or reference thereof. - if (const auto *RT = QT->getAs()) { - if (const auto *RD = RT->getOriginalDecl()) - return classifyCapability(*RD->getDefinitionOrSelf()); - } else if (const auto *TT = QT->getAs()) { - if (const auto *TD = TT->getDecl()) - return classifyCapability(*TD); - } else if (QT->isPointerOrReferenceType()) + if (const auto *RD = QT->getAsRecordDecl()) + return classifyCapability(*RD); + if (const auto *TT = QT->getAs()) + return classifyCapability(*TT->getDecl()); + if (QT->isPointerOrReferenceType()) return classifyCapability(QT->getPointeeType()); return ClassifyCapabilityFallback; diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 2b74b27100402..d679e1c1ff732 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -1265,17 +1265,11 @@ static void pushTemporaryCleanup(CIRGenFunction &cgf, case SD_Static: case SD_Thread: { CXXDestructorDecl *referenceTemporaryDtor = nullptr; - if (const clang::RecordType *rt = e->getType() - ->getBaseElementTypeUnsafe() - ->getAs()) { + if (const auto *classDecl = + e->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); + classDecl && !classDecl->hasTrivialDestructor()) // Get the destructor for the reference temporary. - if (const auto *classDecl = dyn_cast( - rt->getOriginalDecl()->getDefinitionOrSelf())) { - if (!classDecl->hasTrivialDestructor()) - referenceTemporaryDtor = - classDecl->getDefinitionOrSelf()->getDestructor(); - } - } + referenceTemporaryDtor = classDecl->getDestructor(); if (!referenceTemporaryDtor) return; diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp index ced3c2273e865..23132eae3214e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp @@ -949,7 +949,7 @@ mlir::Value CIRGenModule::emitNullConstant(QualType t, mlir::Location loc) { errorNYI("CIRGenModule::emitNullConstant ConstantArrayType"); } - if (t->getAs()) + if (t->isRecordType()) errorNYI("CIRGenModule::emitNullConstant RecordType"); assert(t->isMemberDataPointerType() && diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index 706c14ae962a8..deabb94b7d129 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -356,12 +356,8 @@ static bool mayDropFunctionReturn(const ASTContext &astContext, QualType returnType) { // 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 *recordType = - returnType.getCanonicalType()->getAs()) { - if (const auto *classDecl = dyn_cast( - recordType->getOriginalDecl()->getDefinitionOrSelf())) - return classDecl->hasTrivialDestructor(); - } + if (const auto *classDecl = returnType->getAsCXXRecordDecl()) + return classDecl->hasTrivialDestructor(); return returnType.isTriviallyCopyableType(astContext); } @@ -829,14 +825,9 @@ std::string CIRGenFunction::getCounterAggTmpAsString() { void CIRGenFunction::emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty) { // Ignore empty classes in C++. - if (getLangOpts().CPlusPlus) { - if (const RecordType *rt = ty->getAs()) { - if (cast(rt->getOriginalDecl()) - ->getDefinitionOrSelf() - ->isEmpty()) - return; - } - } + if (getLangOpts().CPlusPlus) + if (const auto *rd = ty->getAsCXXRecordDecl(); rd && rd->isEmpty()) + return; // Cast the dest ptr to the appropriate i8 pointer type. if (builder.isInt8Ty(destPtr.getElementType())) { diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 43554519ebd4d..08b40e08c51de 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -1077,8 +1077,7 @@ static bool isVarDeclStrongDefinition(const ASTContext &astContext, if (astContext.isAlignmentRequired(varType)) return true; - if (const auto *rt = varType->getAs()) { - const RecordDecl *rd = rt->getOriginalDecl()->getDefinitionOrSelf(); + if (const auto *rd = varType->getAsRecordDecl()) { for (const FieldDecl *fd : rd->fields()) { if (fd->isBitField()) continue; diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp index 4ad15e6922ddd..5e1bc8631cac8 100644 --- a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp @@ -506,8 +506,9 @@ class OpenACCClauseCIREmitter final const VarDecl *varRecipe, const VarDecl *temporary, DeclContext *dc, QualType baseType, mlir::Value mainOp) { - mlir::ModuleOp mod = - builder.getBlock()->getParent()->getParentOfType(); + mlir::ModuleOp mod = builder.getBlock() + ->getParent() + ->template getParentOfType(); std::string recipeName = getRecipeName(varRef->getSourceRange(), baseType); diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp index aada6094d0fd5..44b631934ffaf 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -185,9 +185,8 @@ isSafeToConvert(QualType qt, CIRGenTypes &cgt, qt = at->getValueType(); // If this is a record, check it. - if (const auto *rt = qt->getAs()) - return isSafeToConvert(rt->getOriginalDecl()->getDefinitionOrSelf(), cgt, - alreadyChecked); + if (const auto *rd = qt->getAsRecordDecl()) + return isSafeToConvert(rd, cgt, alreadyChecked); // If this is an array, check the elements, which are embedded inline. if (const auto *at = cgt.getASTContext().getAsArrayType(qt)) @@ -571,10 +570,8 @@ bool CIRGenTypes::isZeroInitializable(clang::QualType t) { return true; } - if (const RecordType *rt = t->getAs()) { - const RecordDecl *rd = rt->getOriginalDecl()->getDefinitionOrSelf(); + if (const auto *rd = t->getAsRecordDecl()) return isZeroInitializable(rd); - } if (t->getAs()) { cgm.errorNYI(SourceLocation(), "isZeroInitializable for MemberPointerType", diff --git a/clang/lib/CIR/CodeGen/TargetInfo.cpp b/clang/lib/CIR/CodeGen/TargetInfo.cpp index 7b6259b04122d..62a8c59abe604 100644 --- a/clang/lib/CIR/CodeGen/TargetInfo.cpp +++ b/clang/lib/CIR/CodeGen/TargetInfo.cpp @@ -6,12 +6,10 @@ using namespace clang::CIRGen; bool clang::CIRGen::isEmptyRecordForLayout(const ASTContext &context, QualType t) { - const RecordType *rt = t->getAs(); - if (!rt) + const auto *rd = t->getAsRecordDecl(); + if (!rd) return false; - const RecordDecl *rd = rt->getOriginalDecl()->getDefinitionOrSelf(); - // If this is a C++ record, check the bases first. if (const CXXRecordDecl *cxxrd = dyn_cast(rd)) { if (cxxrd->isDynamicClass()) diff --git a/clang/lib/CodeGen/ABIInfo.cpp b/clang/lib/CodeGen/ABIInfo.cpp index 83cc6377d502c..acd678193b5a8 100644 --- a/clang/lib/CodeGen/ABIInfo.cpp +++ b/clang/lib/CodeGen/ABIInfo.cpp @@ -67,8 +67,7 @@ bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base, if (!isHomogeneousAggregate(AT->getElementType(), Base, Members)) return false; Members *= NElements; - } else if (const RecordType *RT = Ty->getAs()) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + } else if (const auto *RD = Ty->getAsRecordDecl()) { if (RD->hasFlexibleArrayMember()) return false; diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp index 79dbe70a0c8eb..989a3a4387cf4 100644 --- a/clang/lib/CodeGen/ABIInfoImpl.cpp +++ b/clang/lib/CodeGen/ABIInfoImpl.cpp @@ -124,13 +124,11 @@ bool CodeGen::classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, const ABIInfo &Info) { QualType Ty = FI.getReturnType(); - if (const auto *RT = Ty->getAs()) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); - if (!isa(RD) && !RD->canPassInRegisters()) { - FI.getReturnInfo() = Info.getNaturalAlignIndirect( - Ty, Info.getDataLayout().getAllocaAddrSpace()); - return true; - } + if (const auto *RD = Ty->getAsRecordDecl(); + RD && !isa(RD) && !RD->canPassInRegisters()) { + FI.getReturnInfo() = Info.getNaturalAlignIndirect( + Ty, Info.getDataLayout().getAllocaAddrSpace()); + return true; } return CXXABI.classifyReturnType(FI); @@ -285,10 +283,9 @@ bool CodeGen::isEmptyField(ASTContext &Context, const FieldDecl *FD, bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, bool AsIfNoUniqueAddr) { - const RecordType *RT = T->getAs(); - if (!RT) + const auto *RD = T->getAsRecordDecl(); + if (!RD) return false; - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->hasFlexibleArrayMember()) return false; @@ -316,12 +313,10 @@ bool CodeGen::isEmptyFieldForLayout(const ASTContext &Context, } bool CodeGen::isEmptyRecordForLayout(const ASTContext &Context, QualType T) { - const RecordType *RT = T->getAs(); - if (!RT) + const auto *RD = T->getAsRecordDecl(); + if (!RD) return false; - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); - // If this is a C++ record, check the bases first. if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) { if (CXXRD->isDynamicClass()) @@ -340,11 +335,10 @@ bool CodeGen::isEmptyRecordForLayout(const ASTContext &Context, QualType T) { } const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) { - const RecordType *RT = T->getAs(); - if (!RT) + const auto *RD = T->getAsRecordDecl(); + if (!RD) return nullptr; - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->hasFlexibleArrayMember()) return nullptr; @@ -460,10 +454,9 @@ bool CodeGen::isSIMDVectorType(ASTContext &Context, QualType Ty) { } bool CodeGen::isRecordWithSIMDVectorType(ASTContext &Context, QualType Ty) { - const RecordType *RT = Ty->getAs(); - if (!RT) + const auto *RD = Ty->getAsRecordDecl(); + if (!RD) return false; - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); // If this is a C++ record, check the bases first. if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 74d92ef038eb9..597127abc9120 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -420,14 +420,11 @@ static void addBlockLayout(CharUnits align, CharUnits size, /// Determines if the given type is safe for constant capture in C++. static bool isSafeForCXXConstantCapture(QualType type) { - const RecordType *recordType = - type->getBaseElementTypeUnsafe()->getAs(); + const auto *record = type->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); // Only records can be unsafe. - if (!recordType) return true; - - const auto *record = - cast(recordType->getOriginalDecl())->getDefinitionOrSelf(); + if (!record) + return true; // Maintain semantics for classes with non-trivial dtors or copy ctors. if (!record->hasTrivialDestructor()) return false; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index d9cc37d123fb4..9ef38e0a340c3 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -997,9 +997,8 @@ static const FieldDecl *FindFlexibleArrayMemberField(CodeGenFunction &CGF, /*IgnoreTemplateOrMacroSubstitution=*/true)) return FD; - if (auto RT = FD->getType()->getAs()) - if (const FieldDecl *FD = - FindFlexibleArrayMemberField(CGF, Ctx, RT->getAsRecordDecl())) + if (const auto *RD = FD->getType()->getAsRecordDecl()) + if (const FieldDecl *FD = FindFlexibleArrayMemberField(CGF, Ctx, RD)) return FD; } @@ -1025,8 +1024,8 @@ static bool GetFieldOffset(ASTContext &Ctx, const RecordDecl *RD, return true; } - if (auto RT = Field->getType()->getAs()) { - if (GetFieldOffset(Ctx, RT->getAsRecordDecl(), FD, Offset)) { + if (const auto *RD = Field->getType()->getAsRecordDecl()) { + if (GetFieldOffset(Ctx, RD, FD, Offset)) { Offset += Layout.getFieldOffset(FieldNo); return true; } diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index cca675838644e..30e5dc2b6cbd9 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -165,10 +165,7 @@ bool CGCXXABI::mayNeedDestruction(const VarDecl *VD) const { // If the variable has an incomplete class type (or array thereof), it // might need destruction. const Type *T = VD->getType()->getBaseElementTypeUnsafe(); - if (T->getAs() && T->isIncompleteType()) - return true; - - return false; + return T->isRecordType() && T->isIncompleteType(); } bool CGCXXABI::isEmittedWithConstantInitializer( diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 9c4fa12f18b20..89eb6d2b393a3 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1005,10 +1005,9 @@ getTypeExpansion(QualType Ty, const ASTContext &Context) { return std::make_unique(AT->getElementType(), AT->getZExtSize()); } - if (const RecordType *RT = Ty->getAs()) { + if (const auto *RD = Ty->getAsRecordDecl()) { SmallVector Bases; SmallVector Fields; - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); assert(!RD->hasFlexibleArrayMember() && "Cannot expand structure with flexible array."); if (RD->isUnion()) { diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index e9a92ae0f01cb..10e4543a6ab20 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -1408,13 +1408,10 @@ FieldHasTrivialDestructorBody(ASTContext &Context, { QualType FieldBaseElementType = Context.getBaseElementType(Field->getType()); - const RecordType *RT = FieldBaseElementType->getAs(); - if (!RT) + auto *FieldClassDecl = FieldBaseElementType->getAsCXXRecordDecl(); + if (!FieldClassDecl) return true; - auto *FieldClassDecl = - cast(RT->getOriginalDecl())->getDefinitionOrSelf(); - // The destructor for an implicit anonymous union member is never invoked. if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion()) return true; @@ -2850,13 +2847,10 @@ void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, Address Derived, if (!getLangOpts().CPlusPlus) return; - auto *ClassTy = T->getAs(); - if (!ClassTy) + const auto *ClassDecl = T->getAsCXXRecordDecl(); + if (!ClassDecl) return; - const auto *ClassDecl = - cast(ClassTy->getOriginalDecl())->getDefinitionOrSelf(); - if (!ClassDecl->isCompleteDefinition() || !ClassDecl->isDynamicClass()) return; diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 8a1675848e13c..8693f3c71ea80 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -1568,10 +1568,9 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { ReturnValue.getElementType(), ReturnValue.getAlignment()); address = MaybeCastStackAddressSpace(AllocaAddr, Ty.getAddressSpace()); - if (const RecordType *RecordTy = Ty->getAs()) { - const auto *RD = RecordTy->getOriginalDecl()->getDefinitionOrSelf(); - const auto *CXXRD = dyn_cast(RD); - if ((CXXRD && !CXXRD->hasTrivialDestructor()) || + if (const auto *RD = Ty->getAsRecordDecl()) { + if (const auto *CXXRD = dyn_cast(RD); + (CXXRD && !CXXRD->hasTrivialDestructor()) || RD->isNonTrivialToPrimitiveDestroy()) { // Create a flag that is used to indicate when the NRVO was applied // to this variable. Set it to zero to indicate that NRVO was not diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 0f9de6fe3e0cb..e8942aceb9b09 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -414,14 +414,11 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, case SD_Static: case SD_Thread: { CXXDestructorDecl *ReferenceTemporaryDtor = nullptr; - if (const RecordType *RT = - E->getType()->getBaseElementTypeUnsafe()->getAs()) { + if (const auto *ClassDecl = + E->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); + ClassDecl && !ClassDecl->hasTrivialDestructor()) // Get the destructor for the reference temporary. - if (auto *ClassDecl = dyn_cast(RT->getOriginalDecl()); - ClassDecl && !ClassDecl->hasTrivialDestructor()) - ReferenceTemporaryDtor = - ClassDecl->getDefinitionOrSelf()->getDestructor(); - } + ReferenceTemporaryDtor = ClassDecl->getDestructor(); if (!ReferenceTemporaryDtor) return; @@ -2038,7 +2035,7 @@ bool CodeGenFunction::EmitScalarRangeCheck(llvm::Value *Value, QualType Ty, bool IsBool = (Ty->hasBooleanRepresentation() && !Ty->isVectorType()) || NSAPI(CGM.getContext()).isObjCBOOLType(Ty); bool NeedsBoolCheck = HasBoolCheck && IsBool; - bool NeedsEnumCheck = HasEnumCheck && Ty->getAs(); + bool NeedsEnumCheck = HasEnumCheck && Ty->isEnumeralType(); if (!NeedsBoolCheck && !NeedsEnumCheck) return false; diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 04e125c54b1ca..ed90e987b180d 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -268,11 +268,11 @@ void AggExprEmitter::EmitAggLoadOfLValue(const Expr *E) { /// True if the given aggregate type requires special GC API calls. bool AggExprEmitter::TypeRequiresGCollection(QualType T) { // Only record types have members that might require garbage collection. - const RecordType *RecordTy = T->getAs(); - if (!RecordTy) return false; + const auto *Record = T->getAsRecordDecl(); + if (!Record) + return false; // Don't mess with non-trivial C++ types. - RecordDecl *Record = RecordTy->getOriginalDecl()->getDefinitionOrSelf(); if (isa(Record) && (cast(Record)->hasNonTrivialCopyConstructor() || !cast(Record)->hasTrivialDestructor())) @@ -2294,9 +2294,7 @@ void CodeGenFunction::EmitAggregateCopy(LValue Dest, LValue Src, QualType Ty, Address SrcPtr = Src.getAddress(); if (getLangOpts().CPlusPlus) { - if (const RecordType *RT = Ty->getAs()) { - auto *Record = - cast(RT->getOriginalDecl())->getDefinitionOrSelf(); + if (const auto *Record = Ty->getAsCXXRecordDecl()) { assert((Record->hasTrivialCopyConstructor() || Record->hasTrivialCopyAssignment() || Record->hasTrivialMoveConstructor() || @@ -2379,8 +2377,7 @@ void CodeGenFunction::EmitAggregateCopy(LValue Dest, LValue Src, QualType Ty, // Don't do any of the memmove_collectable tests if GC isn't set. if (CGM.getLangOpts().getGC() == LangOptions::NonGC) { // fall through - } else if (const RecordType *RecordTy = Ty->getAs()) { - RecordDecl *Record = RecordTy->getOriginalDecl()->getDefinitionOrSelf(); + } else if (const auto *Record = Ty->getAsRecordDecl()) { if (Record->hasObjectMember()) { CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr, SizeVal); @@ -2388,10 +2385,8 @@ void CodeGenFunction::EmitAggregateCopy(LValue Dest, LValue Src, QualType Ty, } } else if (Ty->isArrayType()) { QualType BaseType = getContext().getBaseElementType(Ty); - if (const RecordType *RecordTy = BaseType->getAs()) { - if (RecordTy->getOriginalDecl() - ->getDefinitionOrSelf() - ->hasObjectMember()) { + if (const auto *Record = BaseType->getAsRecordDecl()) { + if (Record->hasObjectMember()) { CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr, SizeVal); return; diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 57d7eecc62ee1..b6868c1fb1f42 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -1973,9 +1973,7 @@ static bool EmitObjectDelete(CodeGenFunction &CGF, // Find the destructor for the type, if applicable. If the // destructor is virtual, we'll just emit the vcall and return. const CXXDestructorDecl *Dtor = nullptr; - if (const RecordType *RT = ElementType->getAs()) { - auto *RD = - cast(RT->getOriginalDecl())->getDefinitionOrSelf(); + if (const auto *RD = ElementType->getAsCXXRecordDecl()) { if (RD->hasDefinition() && !RD->hasTrivialDestructor()) { Dtor = RD->getDestructor(); diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 3c1bdf9120d21..c4679bd734de9 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1511,10 +1511,8 @@ class ConstExprEmitter llvm::Type *ValTy = CGM.getTypes().ConvertType(destType); bool HasFlexibleArray = false; - if (const auto *RT = destType->getAs()) - HasFlexibleArray = RT->getOriginalDecl() - ->getDefinitionOrSelf() - ->hasFlexibleArrayMember(); + if (const auto *RD = destType->getAsRecordDecl()) + HasFlexibleArray = RD->hasFlexibleArrayMember(); return Const.build(ValTy, HasFlexibleArray); } @@ -2757,10 +2755,9 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { return llvm::ConstantArray::get(ATy, Array); } - if (const RecordType *RT = T->getAs()) - return ::EmitNullConstant(*this, - RT->getOriginalDecl()->getDefinitionOrSelf(), - /*complete object*/ true); + if (const auto *RD = T->getAsRecordDecl()) + return ::EmitNullConstant(*this, RD, + /*asCompleteObject=*/true); assert(T->isMemberDataPointerType() && "Should only see pointers to data members here!"); diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index b5f17b812222a..b01d5471a9836 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -999,10 +999,8 @@ PropertyImplStrategy::PropertyImplStrategy(CodeGenModule &CGM, // Compute whether the ivar has strong members. if (CGM.getLangOpts().getGC()) - if (const RecordType *recordType = ivarType->getAs()) - HasStrong = recordType->getOriginalDecl() - ->getDefinitionOrSelf() - ->hasObjectMember(); + if (const auto *RD = ivarType->getAsRecordDecl()) + HasStrong = RD->hasObjectMember(); // We can never access structs with object members with a native // access, because we need to use write barriers. This is what diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index eb4904050ae0f..d1fb05d594058 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -3353,9 +3353,8 @@ static bool hasWeakMember(QualType type) { return true; } - if (auto recType = type->getAs()) { - for (auto *field : - recType->getOriginalDecl()->getDefinitionOrSelf()->fields()) { + if (auto *RD = type->getAsRecordDecl()) { + for (auto *field : RD->fields()) { if (hasWeakMember(field->getType())) return true; } diff --git a/clang/lib/CodeGen/CGObjCRuntime.cpp b/clang/lib/CodeGen/CGObjCRuntime.cpp index cbf99534d2ce6..76e0054f4c9da 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.cpp +++ b/clang/lib/CodeGen/CGObjCRuntime.cpp @@ -439,10 +439,8 @@ void CGObjCRuntime::destroyCalleeDestroyedArguments(CodeGenFunction &CGF, CGF.EmitARCRelease(RV.getScalarVal(), ARCImpreciseLifetime); } else { QualType QT = param->getType(); - auto *RT = QT->getAs(); - if (RT && RT->getOriginalDecl() - ->getDefinitionOrSelf() - ->isParamDestroyedInCallee()) { + auto *RD = QT->getAsRecordDecl(); + if (RD && RD->isParamDestroyedInCallee()) { RValue RV = I->getRValue(CGF); QualType::DestructionKind DtorKind = QT.isDestructedType(); switch (DtorKind) { diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 9854dae33d6f3..b2fe9171372d8 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -2221,14 +2221,9 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType, void CodeGenFunction::EmitNullInitialization(Address DestPtr, QualType Ty) { // Ignore empty classes in C++. - if (getLangOpts().CPlusPlus) { - if (const RecordType *RT = Ty->getAs()) { - if (cast(RT->getOriginalDecl()) - ->getDefinitionOrSelf() - ->isEmpty()) - return; - } - } + if (getLangOpts().CPlusPlus) + if (const auto *RD = Ty->getAsCXXRecordDecl(); RD && RD->isEmpty()) + return; if (DestPtr.getElementType() != Int8Ty) DestPtr = DestPtr.withElementType(Int8Ty); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index fc65199a0f154..a562a6a1ea6e1 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2979,10 +2979,8 @@ class CodeGenFunction : public CodeGenTypeCache { /// hasVolatileMember - returns true if aggregate type has a volatile /// member. bool hasVolatileMember(QualType T) { - if (const RecordType *RT = T->getAs()) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + if (const auto *RD = T->getAsRecordDecl()) return RD->hasVolatileMember(); - } return false; } diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 677d8bc82cb0a..eae4ae65cb608 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -6075,8 +6075,7 @@ static bool isVarDeclStrongDefinition(const ASTContext &Context, if (Context.isAlignmentRequired(VarType)) return true; - if (const auto *RT = VarType->getAs()) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + if (const auto *RD = VarType->getAsRecordDecl()) { for (const FieldDecl *FD : RD->fields()) { if (FD->isBitField()) continue; diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp index bd2442f01cc50..8cb8024960176 100644 --- a/clang/lib/CodeGen/CodeGenTBAA.cpp +++ b/clang/lib/CodeGen/CodeGenTBAA.cpp @@ -142,10 +142,9 @@ static bool TypeHasMayAlias(QualType QTy) { /// Check if the given type is a valid base type to be used in access tags. static bool isValidBaseType(QualType QTy) { - if (const RecordType *TTy = QTy->getAs()) { - const RecordDecl *RD = TTy->getOriginalDecl()->getDefinition(); + if (const auto *RD = QTy->getAsRecordDecl()) { // Incomplete types are not valid base access types. - if (!RD) + if (!RD->isCompleteDefinition()) return false; if (RD->hasFlexibleArrayMember()) return false; diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index f2a0a649a88fd..d3fbb4a2a9364 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -311,12 +311,12 @@ llvm::Type *CodeGenTypes::ConvertFunctionTypeInternal(QualType QFT) { // Force conversion of all the relevant record types, to make sure // we re-convert the FunctionType when appropriate. - if (const RecordType *RT = FT->getReturnType()->getAs()) - ConvertRecordDeclType(RT->getOriginalDecl()->getDefinitionOrSelf()); + if (const auto *RD = FT->getReturnType()->getAsRecordDecl()) + ConvertRecordDeclType(RD); if (const FunctionProtoType *FPT = dyn_cast(FT)) for (unsigned i = 0, e = FPT->getNumParams(); i != e; i++) - if (const RecordType *RT = FPT->getParamType(i)->getAs()) - ConvertRecordDeclType(RT->getOriginalDecl()->getDefinitionOrSelf()); + if (const auto *RD = FPT->getParamType(i)->getAsRecordDecl()) + ConvertRecordDeclType(RD); SkippedLayout = true; @@ -875,10 +875,8 @@ bool CodeGenTypes::isZeroInitializable(QualType T) { // Records are non-zero-initializable if they contain any // non-zero-initializable subobjects. - if (const RecordType *RT = T->getAs()) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + if (const auto *RD = T->getAsRecordDecl()) return isZeroInitializable(RD); - } // We have to ask the ABI about member pointers. if (const MemberPointerType *MPT = T->getAs()) diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 4ed3775f156c9..569fbe9e3bd3a 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -1484,21 +1484,18 @@ void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) { // The address of the destructor. If the exception type has a // trivial destructor (or isn't a record), we just pass null. llvm::Constant *Dtor = nullptr; - if (const RecordType *RecordTy = ThrowType->getAs()) { - CXXRecordDecl *Record = - cast(RecordTy->getOriginalDecl())->getDefinitionOrSelf(); - if (!Record->hasTrivialDestructor()) { - // __cxa_throw is declared to take its destructor as void (*)(void *). We - // must match that if function pointers can be authenticated with a - // discriminator based on their type. - const ASTContext &Ctx = getContext(); - QualType DtorTy = Ctx.getFunctionType(Ctx.VoidTy, {Ctx.VoidPtrTy}, - FunctionProtoType::ExtProtoInfo()); - - CXXDestructorDecl *DtorD = Record->getDestructor(); - Dtor = CGM.getAddrOfCXXStructor(GlobalDecl(DtorD, Dtor_Complete)); - Dtor = CGM.getFunctionPointer(Dtor, DtorTy); - } + if (const auto *Record = ThrowType->getAsCXXRecordDecl(); + Record && !Record->hasTrivialDestructor()) { + // __cxa_throw is declared to take its destructor as void (*)(void *). We + // must match that if function pointers can be authenticated with a + // discriminator based on their type. + const ASTContext &Ctx = getContext(); + QualType DtorTy = Ctx.getFunctionType(Ctx.VoidTy, {Ctx.VoidPtrTy}, + FunctionProtoType::ExtProtoInfo()); + + CXXDestructorDecl *DtorD = Record->getDestructor(); + Dtor = CGM.getAddrOfCXXStructor(GlobalDecl(DtorD, Dtor_Complete)); + Dtor = CGM.getFunctionPointer(Dtor, DtorTy); } if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy); diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index 289f8a9dcf211..1a878222cde18 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -493,10 +493,9 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn, auto ContainsOnlyPointers = [&](const auto &Self, QualType Ty) { if (isEmptyRecord(getContext(), Ty, true)) return false; - const RecordType *RT = Ty->getAs(); - if (!RT) + const auto *RD = Ty->getAsRecordDecl(); + if (!RD) return false; - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) { for (const auto &I : CXXRD->bases()) if (!Self(Self, I.getType())) diff --git a/clang/lib/CodeGen/Targets/AMDGPU.cpp b/clang/lib/CodeGen/Targets/AMDGPU.cpp index 41bccbb5721b2..0fcbf7e458a34 100644 --- a/clang/lib/CodeGen/Targets/AMDGPU.cpp +++ b/clang/lib/CodeGen/Targets/AMDGPU.cpp @@ -95,8 +95,7 @@ unsigned AMDGPUABIInfo::numRegsForType(QualType Ty) const { return EltNumRegs * VT->getNumElements(); } - if (const RecordType *RT = Ty->getAs()) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + if (const auto *RD = Ty->getAsRecordDecl()) { assert(!RD->hasFlexibleArrayMember()); for (const FieldDecl *Field : RD->fields()) { @@ -152,11 +151,9 @@ ABIArgInfo AMDGPUABIInfo::classifyReturnType(QualType RetTy) const { if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext())) return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); - if (const RecordType *RT = RetTy->getAs()) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); - if (RD->hasFlexibleArrayMember()) - return DefaultABIInfo::classifyReturnType(RetTy); - } + if (const auto *RD = RetTy->getAsRecordDecl(); + RD && RD->hasFlexibleArrayMember()) + return DefaultABIInfo::classifyReturnType(RetTy); // Pack aggregates <= 4 bytes into single VGPR or pair. uint64_t Size = getContext().getTypeSize(RetTy); @@ -245,11 +242,9 @@ ABIArgInfo AMDGPUABIInfo::classifyArgumentType(QualType Ty, bool Variadic, if (const Type *SeltTy = isSingleElementStruct(Ty, getContext())) return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); - if (const RecordType *RT = Ty->getAs()) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); - if (RD->hasFlexibleArrayMember()) - return DefaultABIInfo::classifyArgumentType(Ty); - } + if (const auto *RD = Ty->getAsRecordDecl(); + RD && RD->hasFlexibleArrayMember()) + return DefaultABIInfo::classifyArgumentType(Ty); // Pack aggregates <= 8 bytes into single VGPR or pair. uint64_t Size = getContext().getTypeSize(Ty); diff --git a/clang/lib/CodeGen/Targets/ARM.cpp b/clang/lib/CodeGen/Targets/ARM.cpp index 3739e16788c3e..c87a0ab52557d 100644 --- a/clang/lib/CodeGen/Targets/ARM.cpp +++ b/clang/lib/CodeGen/Targets/ARM.cpp @@ -718,9 +718,8 @@ bool ARMABIInfo::containsAnyFP16Vectors(QualType Ty) const { if (NElements == 0) return false; return containsAnyFP16Vectors(AT->getElementType()); - } else if (const RecordType *RT = Ty->getAs()) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); - + } + if (const auto *RD = Ty->getAsRecordDecl()) { // If this is a C++ record, check the bases first. if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) if (llvm::any_of(CXXRD->bases(), [this](const CXXBaseSpecifier &B) { diff --git a/clang/lib/CodeGen/Targets/CSKY.cpp b/clang/lib/CodeGen/Targets/CSKY.cpp index 7e5a16f30727f..14deaf106e01e 100644 --- a/clang/lib/CodeGen/Targets/CSKY.cpp +++ b/clang/lib/CodeGen/Targets/CSKY.cpp @@ -91,7 +91,7 @@ ABIArgInfo CSKYABIInfo::classifyArgumentType(QualType Ty, int &ArgGPRsLeft, if (isEmptyRecord(getContext(), Ty, true)) return ABIArgInfo::getIgnore(); - if (!Ty->getAsUnionType()) + if (!Ty->isUnionType()) if (const Type *SeltTy = isSingleElementStruct(Ty, getContext())) return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); diff --git a/clang/lib/CodeGen/Targets/NVPTX.cpp b/clang/lib/CodeGen/Targets/NVPTX.cpp index e874617796f86..106251fb27024 100644 --- a/clang/lib/CodeGen/Targets/NVPTX.cpp +++ b/clang/lib/CodeGen/Targets/NVPTX.cpp @@ -130,10 +130,9 @@ bool NVPTXABIInfo::isUnsupportedType(QualType T) const { return true; if (const auto *AT = T->getAsArrayTypeUnsafe()) return isUnsupportedType(AT->getElementType()); - const auto *RT = T->getAs(); - if (!RT) + const auto *RD = T->getAsRecordDecl(); + if (!RD) return false; - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); // If this is a C++ record, check the bases first. if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index 38e76399299ec..a297833a57ef4 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -294,10 +294,7 @@ void AIXTargetCodeGenInfo::setTargetAttributes( ASTContext &Context = D->getASTContext(); unsigned Alignment = Context.toBits(Context.getDeclAlign(D)) / 8; const auto *Ty = VarD->getType().getTypePtr(); - const RecordDecl *RDecl = - Ty->isRecordType() - ? Ty->getAs()->getOriginalDecl()->getDefinitionOrSelf() - : nullptr; + const RecordDecl *RDecl = Ty->getAsRecordDecl(); bool EmitDiagnostic = UserSpecifiedTOC && GV->hasExternalLinkage(); auto reportUnsupportedWarning = [&](bool ShouldEmitWarning, StringRef Msg) { diff --git a/clang/lib/CodeGen/Targets/SPIR.cpp b/clang/lib/CodeGen/Targets/SPIR.cpp index 237aea755fa29..ababb25736203 100644 --- a/clang/lib/CodeGen/Targets/SPIR.cpp +++ b/clang/lib/CodeGen/Targets/SPIR.cpp @@ -118,11 +118,9 @@ ABIArgInfo SPIRVABIInfo::classifyReturnType(QualType RetTy) const { if (!isAggregateTypeForABI(RetTy) || getRecordArgABI(RetTy, getCXXABI())) return DefaultABIInfo::classifyReturnType(RetTy); - if (const RecordType *RT = RetTy->getAs()) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); - if (RD->hasFlexibleArrayMember()) - return DefaultABIInfo::classifyReturnType(RetTy); - } + if (const auto *RD = RetTy->getAsRecordDecl(); + RD && RD->hasFlexibleArrayMember()) + return DefaultABIInfo::classifyReturnType(RetTy); // TODO: The AMDGPU ABI is non-trivial to represent in SPIR-V; in order to // avoid encoding various architecture specific bits here we return everything @@ -186,11 +184,9 @@ ABIArgInfo SPIRVABIInfo::classifyArgumentType(QualType Ty) const { return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), RAA == CGCXXABI::RAA_DirectInMemory); - if (const RecordType *RT = Ty->getAs()) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); - if (RD->hasFlexibleArrayMember()) - return DefaultABIInfo::classifyArgumentType(Ty); - } + if (const auto *RD = Ty->getAsRecordDecl(); + RD && RD->hasFlexibleArrayMember()) + return DefaultABIInfo::classifyArgumentType(Ty); return ABIArgInfo::getDirect(CGT.ConvertType(Ty), 0u, nullptr, false); } @@ -431,8 +427,7 @@ static llvm::Type *getInlineSpirvType(CodeGenModule &CGM, } case SpirvOperandKind::TypeId: { QualType TypeOperand = Operand.getResultType(); - if (auto *RT = TypeOperand->getAs()) { - auto *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + if (const auto *RD = TypeOperand->getAsRecordDecl()) { assert(RD->isCompleteDefinition() && "Type completion should have been required in Sema"); diff --git a/clang/lib/CodeGen/Targets/SystemZ.cpp b/clang/lib/CodeGen/Targets/SystemZ.cpp index 38cc4d39126be..c3f0cba4cbef6 100644 --- a/clang/lib/CodeGen/Targets/SystemZ.cpp +++ b/clang/lib/CodeGen/Targets/SystemZ.cpp @@ -452,10 +452,9 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const { /*ByVal=*/false); // Handle small structures. - if (const RecordType *RT = Ty->getAs()) { + if (const auto *RD = Ty->getAsRecordDecl()) { // Structures with flexible arrays have variable length, so really // fail the size test above. - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->hasFlexibleArrayMember()) return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), /*ByVal=*/false); @@ -525,8 +524,7 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty, if (Ty->isVectorType() && Ctx.getTypeSize(Ty) / 8 >= 16) return true; - if (const auto *RecordTy = Ty->getAs()) { - const RecordDecl *RD = RecordTy->getOriginalDecl()->getDefinitionOrSelf(); + if (const auto *RD = Ty->getAsRecordDecl()) { if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) if (CXXRD->hasDefinition()) for (const auto &I : CXXRD->bases()) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 61b833a9c1b43..f04d24db26a25 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -352,15 +352,15 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, return shouldReturnTypeInRegister(AT->getElementType(), Context); // Otherwise, it must be a record type. - const RecordType *RT = Ty->getAs(); - if (!RT) return false; + const auto *RD = Ty->getAsRecordDecl(); + if (!RD) + return false; // FIXME: Traverse bases here too. // Structure types are passed in register if all fields would be // passed in a register. - for (const auto *FD : - RT->getOriginalDecl()->getDefinitionOrSelf()->fields()) { + for (const auto *FD : RD->fields()) { // Empty fields are ignored. if (isEmptyField(Context, FD, true)) continue; @@ -427,11 +427,10 @@ static bool addBaseAndFieldSizes(ASTContext &Context, const CXXRecordDecl *RD, /// optimizations. bool X86_32ABIInfo::canExpandIndirectArgument(QualType Ty) const { // We can only expand structure types. - const RecordType *RT = Ty->getAs(); - if (!RT) + const RecordDecl *RD = Ty->getAsRecordDecl(); + if (!RD) return false; uint64_t Size = 0; - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (const auto *CXXRD = dyn_cast(RD)) { if (!IsWin32StructABI) { // On non-Windows, we have to conservatively match our old bitcode @@ -508,13 +507,10 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, } if (isAggregateTypeForABI(RetTy)) { - if (const RecordType *RT = RetTy->getAs()) { + if (const auto *RD = RetTy->getAsRecordDecl(); + RD && RD->hasFlexibleArrayMember()) // Structures with flexible arrays are always indirect. - if (RT->getOriginalDecl() - ->getDefinitionOrSelf() - ->hasFlexibleArrayMember()) - return getIndirectReturnResult(RetTy, State); - } + return getIndirectReturnResult(RetTy, State); // If specified, structs and unions are always indirect. if (!IsRetSmallStructInRegABI && !RetTy->isAnyComplexType()) @@ -2354,8 +2350,7 @@ static bool BitsContainNoUserData(QualType Ty, unsigned StartBit, return true; } - if (const RecordType *RT = Ty->getAs()) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + if (const auto *RD = Ty->getAsRecordDecl()) { const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); // If this is a C++ record, check the bases first. diff --git a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp index 627a1d6fb3dd5..40f8348241ecc 100644 --- a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp +++ b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -1011,7 +1011,7 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg, if ((MK == NSAPI::NSNumberWithInteger || MK == NSAPI::NSNumberWithUnsignedInteger) && !isTruncated) { - if (OrigTy->getAs() || isEnumConstant(OrigArg)) + if (OrigTy->isEnumeralType() || isEnumConstant(OrigArg)) break; if ((MK==NSAPI::NSNumberWithInteger) == OrigTy->isSignedIntegerType() && OrigTySize >= Ctx.getTypeSize(Ctx.IntTy)) diff --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp index 2b55820b38804..f57ccd30c59b9 100644 --- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -3733,15 +3733,7 @@ void RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDec auto *IDecl = dyn_cast(fieldDecl->getDeclContext()); - TagDecl *TD = nullptr; - if (Type->isRecordType()) { - TD = Type->castAs()->getOriginalDecl()->getDefinitionOrSelf(); - } - else if (Type->isEnumeralType()) { - TD = Type->castAs()->getOriginalDecl()->getDefinitionOrSelf(); - } - - if (TD) { + if (auto *TD = Type->getAsTagDecl()) { if (GlobalDefinedTags.count(TD)) return; diff --git a/clang/lib/Interpreter/Value.cpp b/clang/lib/Interpreter/Value.cpp index 84ba508e9cbc8..2ef057bc5d0a5 100644 --- a/clang/lib/Interpreter/Value.cpp +++ b/clang/lib/Interpreter/Value.cpp @@ -147,15 +147,12 @@ Value::Value(const Interpreter *In, void *Ty) : Interp(In), OpaqueType(Ty) { } while (ArrTy); ElementsSize = static_cast(ArrSize.getZExtValue()); } - if (const auto *RT = DtorTy->getAs()) { - if (CXXRecordDecl *CXXRD = - llvm::dyn_cast(RT->getOriginalDecl())) { - if (llvm::Expected Addr = - Interp.CompileDtorCall(CXXRD->getDefinitionOrSelf())) - DtorF = reinterpret_cast(Addr->getValue()); - else - llvm::logAllUnhandledErrors(Addr.takeError(), llvm::errs()); - } + if (auto *CXXRD = DtorTy->getAsCXXRecordDecl()) { + if (llvm::Expected Addr = + Interp.CompileDtorCall(CXXRD)) + DtorF = reinterpret_cast(Addr->getValue()); + else + llvm::logAllUnhandledErrors(Addr.takeError(), llvm::errs()); } size_t AllocSize = diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index b870c5af1e588..39fa25f66f3b7 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1882,23 +1882,21 @@ class DeferredDiagnosticsEmitter // Visit the dtors of all members for (const FieldDecl *FD : RD->fields()) { QualType FT = FD->getType(); - if (const auto *RT = FT->getAs()) - if (const auto *ClassDecl = - dyn_cast(RT->getOriginalDecl())) - if (const auto *Def = ClassDecl->getDefinition()) - if (CXXDestructorDecl *MemberDtor = Def->getDestructor()) - asImpl().visitUsedDecl(MemberDtor->getLocation(), MemberDtor); + if (const auto *ClassDecl = FT->getAsCXXRecordDecl(); + ClassDecl && + (ClassDecl->isBeingDefined() || ClassDecl->isCompleteDefinition())) + if (CXXDestructorDecl *MemberDtor = ClassDecl->getDestructor()) + asImpl().visitUsedDecl(MemberDtor->getLocation(), MemberDtor); } // Also visit base class dtors for (const auto &Base : RD->bases()) { QualType BaseType = Base.getType(); - if (const auto *RT = BaseType->getAs()) - if (const auto *BaseDecl = - dyn_cast(RT->getOriginalDecl())) - if (const auto *Def = BaseDecl->getDefinition()) - if (CXXDestructorDecl *BaseDtor = Def->getDestructor()) - asImpl().visitUsedDecl(BaseDtor->getLocation(), BaseDtor); + if (const auto *BaseDecl = BaseType->getAsCXXRecordDecl(); + BaseDecl && + (BaseDecl->isBeingDefined() || BaseDecl->isCompleteDefinition())) + if (CXXDestructorDecl *BaseDtor = BaseDecl->getDestructor()) + asImpl().visitUsedDecl(BaseDtor->getLocation(), BaseDtor); } } @@ -1909,12 +1907,11 @@ class DeferredDiagnosticsEmitter if (VD->isThisDeclarationADefinition() && VD->needsDestruction(S.Context)) { QualType VT = VD->getType(); - if (const auto *RT = VT->getAs()) - if (const auto *ClassDecl = - dyn_cast(RT->getOriginalDecl())) - if (const auto *Def = ClassDecl->getDefinition()) - if (CXXDestructorDecl *Dtor = Def->getDestructor()) - asImpl().visitUsedDecl(Dtor->getLocation(), Dtor); + if (const auto *ClassDecl = VT->getAsCXXRecordDecl(); + ClassDecl && (ClassDecl->isBeingDefined() || + ClassDecl->isCompleteDefinition())) + if (CXXDestructorDecl *Dtor = ClassDecl->getDestructor()) + asImpl().visitUsedDecl(Dtor->getLocation(), Dtor); } Inherited::VisitDeclStmt(DS); diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index ba560d3c52340..7ceea76012e0c 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -439,10 +439,8 @@ static AccessResult MatchesFriend(Sema &S, static AccessResult MatchesFriend(Sema &S, const EffectiveContext &EC, CanQualType Friend) { - if (const RecordType *RT = Friend->getAs()) - return MatchesFriend( - S, EC, - cast(RT->getOriginalDecl())->getDefinitionOrSelf()); + if (const auto *RD = Friend->getAsCXXRecordDecl()) + return MatchesFriend(S, EC, RD); // TODO: we can do better than this if (Friend->isDependentType()) diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp index fbf64d3d57050..2e3cbb336a0c8 100644 --- a/clang/lib/Sema/SemaCUDA.cpp +++ b/clang/lib/Sema/SemaCUDA.cpp @@ -421,13 +421,10 @@ bool SemaCUDA::inferTargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, } for (const auto *B : Bases) { - const RecordType *BaseType = B->getType()->getAs(); - if (!BaseType) { + auto *BaseClassDecl = B->getType()->getAsCXXRecordDecl(); + if (!BaseClassDecl) continue; - } - CXXRecordDecl *BaseClassDecl = - cast(BaseType->getOriginalDecl())->getDefinitionOrSelf(); Sema::SpecialMemberOverloadResult SMOR = SemaRef.LookupSpecialMember(BaseClassDecl, CSM, /* ConstArg */ ConstRHS, @@ -466,15 +463,11 @@ bool SemaCUDA::inferTargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, continue; } - const RecordType *FieldType = - getASTContext().getBaseElementType(F->getType())->getAs(); - if (!FieldType) { + auto *FieldRecDecl = + getASTContext().getBaseElementType(F->getType())->getAsCXXRecordDecl(); + if (!FieldRecDecl) continue; - } - CXXRecordDecl *FieldRecDecl = - cast(FieldType->getOriginalDecl()) - ->getDefinitionOrSelf(); Sema::SpecialMemberOverloadResult SMOR = SemaRef.LookupSpecialMember(FieldRecDecl, CSM, /* ConstArg */ ConstRHS && !F->isMutable(), diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index da43848a1a7d0..933a6c558e7ac 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -595,13 +595,11 @@ static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType, DifferentPtrness--; } if (!DifferentPtrness) { - auto RecFrom = From->getAs(); - auto RecTo = To->getAs(); - if (RecFrom && RecTo) { - auto DeclFrom = RecFrom->getAsCXXRecordDecl(); + if (auto *DeclFrom = From->getAsCXXRecordDecl(), + *DeclTo = To->getAsCXXRecordDecl(); + DeclFrom && DeclTo) { if (!DeclFrom->isCompleteDefinition()) S.Diag(DeclFrom->getLocation(), diag::note_type_incomplete) << DeclFrom; - auto DeclTo = RecTo->getAsCXXRecordDecl(); if (!DeclTo->isCompleteDefinition()) S.Diag(DeclTo->getLocation(), diag::note_type_incomplete) << DeclTo; } @@ -1454,7 +1452,7 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, // C++0x 5.2.9p9: A value of a scoped enumeration type can be explicitly // converted to an integral type. [...] A value of a scoped enumeration type // can also be explicitly converted to a floating-point type [...]. - if (const EnumType *Enum = SrcType->getAs()) { + if (const EnumType *Enum = dyn_cast(SrcType)) { if (Enum->getOriginalDecl()->isScoped()) { if (DestType->isBooleanType()) { Kind = CK_IntegralToBoolean; @@ -1581,11 +1579,11 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, // See if it looks like the user is trying to convert between // related record types, and select a better diagnostic if so. - if (auto SrcPointer = SrcType->getAs()) - if (auto DestPointer = DestType->getAs()) - if (SrcPointer->getPointeeType()->getAs() && - DestPointer->getPointeeType()->getAs()) - msg = diag::err_bad_cxx_cast_unrelated_class; + if (const auto *SrcPointer = SrcType->getAs()) + if (const auto *DestPointer = DestType->getAs()) + if (SrcPointer->getPointeeType()->isRecordType() && + DestPointer->getPointeeType()->isRecordType()) + msg = diag::err_bad_cxx_cast_unrelated_class; if (SrcType->isMatrixType() && DestType->isMatrixType()) { if (Self.CheckMatrixCast(OpRange, DestType, SrcType, Kind)) { diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 6e777fb9aec8e..908ac31c6ac98 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -7891,16 +7891,10 @@ bool DecomposePrintfHandler::HandlePrintfSpecifier( template static llvm::SmallPtrSet CXXRecordMembersNamed(StringRef Name, Sema &S, QualType Ty) { - const RecordType *RT = Ty->getAs(); + auto *RD = Ty->getAsCXXRecordDecl(); llvm::SmallPtrSet Results; - if (!RT) - return Results; - CXXRecordDecl *RD = dyn_cast(RT->getOriginalDecl()); - if (!RD) - return Results; - RD = RD->getDefinition(); - if (!RD) + if (!RD || !(RD->isBeingDefined() || RD->isCompleteDefinition())) return Results; LookupResult R(S, &S.Context.Idents.get(Name), SourceLocation(), @@ -10063,17 +10057,16 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, PDiag(diag::warn_arc_object_memaccess) << ArgIdx << FnName << PointeeTy << Call->getCallee()->getSourceRange()); - else if (const auto *RT = PointeeTy->getAs()) { + else if (const auto *RD = PointeeTy->getAsRecordDecl()) { // FIXME: Do not consider incomplete types even though they may be // completed later. GCC does not diagnose such code, but we may want to // consider diagnosing it in the future, perhaps under a different, but // related, diagnostic group. bool NonTriviallyCopyableCXXRecord = - getLangOpts().CPlusPlus && !RT->isIncompleteType() && - !RT->desugar().isTriviallyCopyableType(Context); + getLangOpts().CPlusPlus && RD->isCompleteDefinition() && + !PointeeTy.isTriviallyCopyableType(Context); - const auto *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) && RD->isNonTrivialToPrimitiveDefaultInitialize()) { DiagRuntimeBehavior(Dest->getExprLoc(), Dest, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 160d7353cacd9..8a5b9fc19cd1f 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5291,14 +5291,9 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, // UNION_TYPE; <- where UNION_TYPE is a typedef union. if ((Tag && Tag->getDeclName()) || DS.getTypeSpecType() == DeclSpec::TST_typename) { - RecordDecl *Record = nullptr; - if (Tag) - Record = dyn_cast(Tag); - else if (const RecordType *RT = - DS.getRepAsType().get()->getAsStructureType()) - Record = RT->getOriginalDecl()->getDefinitionOrSelf(); - else if (const RecordType *UT = DS.getRepAsType().get()->getAsUnionType()) - Record = UT->getOriginalDecl()->getDefinitionOrSelf(); + RecordDecl *Record = dyn_cast_or_null(Tag); + if (!Record) + Record = DS.getRepAsType().get()->getAsRecordDecl(); if (Record && getLangOpts().MicrosoftExt) { Diag(DS.getBeginLoc(), diag::ext_ms_anonymous_record) @@ -14480,11 +14475,8 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { // version of one of these types, or an array of one of the preceding // types and is declared without an initializer. if (getLangOpts().CPlusPlus && Var->hasLocalStorage()) { - if (const RecordType *Record - = Context.getBaseElementType(Type)->getAs()) { - CXXRecordDecl *CXXRecord = - cast(Record->getOriginalDecl()) - ->getDefinitionOrSelf(); + if (const auto *CXXRecord = + Context.getBaseElementType(Type)->getAsCXXRecordDecl()) { // Mark the function (if we're in one) for further checking even if the // looser rules of C++11 do not require such checks, so that we can // diagnose incompatibilities with C++98. @@ -14947,8 +14939,8 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { // Require the destructor. if (!type->isDependentType()) - if (const RecordType *recordType = baseType->getAs()) - FinalizeVarWithDestructor(var, recordType); + if (auto *RD = baseType->getAsCXXRecordDecl()) + FinalizeVarWithDestructor(var, RD); // If this variable must be emitted, add it as an initializer for the current // module. @@ -19119,17 +19111,16 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, if (!InvalidDecl && getLangOpts().CPlusPlus) { if (Record->isUnion()) { - if (const RecordType *RT = EltTy->getAs()) { - CXXRecordDecl *RDecl = cast(RT->getOriginalDecl()); - if (RDecl->getDefinition()) { - // C++ [class.union]p1: An object of a class with a non-trivial - // constructor, a non-trivial copy constructor, a non-trivial - // destructor, or a non-trivial copy assignment operator - // cannot be a member of a union, nor can an array of such - // objects. - if (CheckNontrivialField(NewFD)) - NewFD->setInvalidDecl(); - } + if (const auto *RD = EltTy->getAsCXXRecordDecl(); + RD && (RD->isBeingDefined() || RD->isCompleteDefinition())) { + + // C++ [class.union]p1: An object of a class with a non-trivial + // constructor, a non-trivial copy constructor, a non-trivial + // destructor, or a non-trivial copy assignment operator + // cannot be a member of a union, nor can an array of such + // objects. + if (CheckNontrivialField(NewFD)) + NewFD->setInvalidDecl(); } // C++ [class.union]p1: If a union contains a member of reference type, @@ -19185,55 +19176,51 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { return false; QualType EltTy = Context.getBaseElementType(FD->getType()); - if (const RecordType *RT = EltTy->getAs()) { - CXXRecordDecl *RDecl = - cast(RT->getOriginalDecl())->getDefinitionOrSelf(); - if (RDecl->getDefinition()) { - // We check for copy constructors before constructors - // because otherwise we'll never get complaints about - // copy constructors. - - CXXSpecialMemberKind member = CXXSpecialMemberKind::Invalid; - // We're required to check for any non-trivial constructors. Since the - // implicit default constructor is suppressed if there are any - // user-declared constructors, we just need to check that there is a - // trivial default constructor and a trivial copy constructor. (We don't - // worry about move constructors here, since this is a C++98 check.) - if (RDecl->hasNonTrivialCopyConstructor()) - member = CXXSpecialMemberKind::CopyConstructor; - else if (!RDecl->hasTrivialDefaultConstructor()) - member = CXXSpecialMemberKind::DefaultConstructor; - else if (RDecl->hasNonTrivialCopyAssignment()) - member = CXXSpecialMemberKind::CopyAssignment; - else if (RDecl->hasNonTrivialDestructor()) - member = CXXSpecialMemberKind::Destructor; - - if (member != CXXSpecialMemberKind::Invalid) { - if (!getLangOpts().CPlusPlus11 && - getLangOpts().ObjCAutoRefCount && RDecl->hasObjectMember()) { - // Objective-C++ ARC: it is an error to have a non-trivial field of - // a union. However, system headers in Objective-C programs - // occasionally have Objective-C lifetime objects within unions, - // and rather than cause the program to fail, we make those - // members unavailable. - SourceLocation Loc = FD->getLocation(); - if (getSourceManager().isInSystemHeader(Loc)) { - if (!FD->hasAttr()) - FD->addAttr(UnavailableAttr::CreateImplicit(Context, "", - UnavailableAttr::IR_ARCFieldWithOwnership, Loc)); - return false; - } + if (const auto *RDecl = EltTy->getAsCXXRecordDecl(); + RDecl && (RDecl->isBeingDefined() || RDecl->isCompleteDefinition())) { + // We check for copy constructors before constructors + // because otherwise we'll never get complaints about + // copy constructors. + + CXXSpecialMemberKind member = CXXSpecialMemberKind::Invalid; + // We're required to check for any non-trivial constructors. Since the + // implicit default constructor is suppressed if there are any + // user-declared constructors, we just need to check that there is a + // trivial default constructor and a trivial copy constructor. (We don't + // worry about move constructors here, since this is a C++98 check.) + if (RDecl->hasNonTrivialCopyConstructor()) + member = CXXSpecialMemberKind::CopyConstructor; + else if (!RDecl->hasTrivialDefaultConstructor()) + member = CXXSpecialMemberKind::DefaultConstructor; + else if (RDecl->hasNonTrivialCopyAssignment()) + member = CXXSpecialMemberKind::CopyAssignment; + else if (RDecl->hasNonTrivialDestructor()) + member = CXXSpecialMemberKind::Destructor; + + if (member != CXXSpecialMemberKind::Invalid) { + if (!getLangOpts().CPlusPlus11 && getLangOpts().ObjCAutoRefCount && + RDecl->hasObjectMember()) { + // Objective-C++ ARC: it is an error to have a non-trivial field of + // a union. However, system headers in Objective-C programs + // occasionally have Objective-C lifetime objects within unions, + // and rather than cause the program to fail, we make those + // members unavailable. + SourceLocation Loc = FD->getLocation(); + if (getSourceManager().isInSystemHeader(Loc)) { + if (!FD->hasAttr()) + FD->addAttr(UnavailableAttr::CreateImplicit( + Context, "", UnavailableAttr::IR_ARCFieldWithOwnership, Loc)); + return false; } - - Diag( - FD->getLocation(), - getLangOpts().CPlusPlus11 - ? diag::warn_cxx98_compat_nontrivial_union_or_anon_struct_member - : diag::err_illegal_union_or_anon_struct_member) - << FD->getParent()->isUnion() << FD->getDeclName() << member; - DiagnoseNontrivial(RDecl, member); - return !getLangOpts().CPlusPlus11; } + + Diag(FD->getLocation(), + getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_nontrivial_union_or_anon_struct_member + : diag::err_illegal_union_or_anon_struct_member) + << FD->getParent()->isUnion() << FD->getDeclName() << member; + DiagnoseNontrivial(RDecl, member); + return !getLangOpts().CPlusPlus11; } } @@ -19509,11 +19496,9 @@ bool Sema::EntirelyFunctionPointers(const RecordDecl *Record) { return PointeeType.getDesugaredType(Context)->isFunctionType(); } // If a member is a struct entirely of function pointers, that counts too. - if (const RecordType *RT = FieldType->getAs()) { - const RecordDecl *Record = RT->getOriginalDecl()->getDefinitionOrSelf(); - if (Record->isStruct() && EntirelyFunctionPointers(Record)) - return true; - } + if (const auto *Record = FieldType->getAsRecordDecl(); + Record && Record->isStruct() && EntirelyFunctionPointers(Record)) + return true; return false; }; @@ -19667,10 +19652,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, FD->setInvalidDecl(); EnclosingDecl->setInvalidDecl(); continue; - } else if (const RecordType *FDTTy = FDTy->getAs()) { - if (Record && FDTTy->getOriginalDecl() - ->getDefinitionOrSelf() - ->hasFlexibleArrayMember()) { + } else if (const auto *RD = FDTy->getAsRecordDecl()) { + if (Record && RD->hasFlexibleArrayMember()) { // A type which contains a flexible array member is considered to be a // flexible array member. Record->setHasFlexibleArrayMember(true); @@ -19696,7 +19679,6 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, // Ivars can not have abstract class types FD->setInvalidDecl(); } - const RecordDecl *RD = FDTTy->getOriginalDecl()->getDefinitionOrSelf(); if (Record && RD->hasObjectMember()) Record->setHasObjectMember(true); if (Record && RD->hasVolatileMember()) @@ -19730,10 +19712,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, Record->setHasObjectMember(true); else if (Context.getAsArrayType(FD->getType())) { QualType BaseType = Context.getBaseElementType(FD->getType()); - if (BaseType->isRecordType() && BaseType->castAs() - ->getOriginalDecl() - ->getDefinitionOrSelf() - ->hasObjectMember()) + if (const auto *RD = BaseType->getAsRecordDecl(); + RD && RD->hasObjectMember()) Record->setHasObjectMember(true); else if (BaseType->isObjCObjectPointerType() || BaseType.isObjCGCStrong()) @@ -19765,10 +19745,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, Record->setHasNonTrivialToPrimitiveDestructCUnion(true); } - if (const auto *RT = FT->getAs()) { - if (RT->getOriginalDecl() - ->getDefinitionOrSelf() - ->getArgPassingRestrictions() == + if (const auto *RD = FT->getAsRecordDecl()) { + if (RD->getArgPassingRestrictions() == RecordArgPassingKind::CanNeverPassInRegs) Record->setArgPassingRestrictions( RecordArgPassingKind::CanNeverPassInRegs); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 3685bcefbf764..c3a61741cc874 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -169,7 +169,7 @@ static bool isIntOrBool(Expr *Exp) { // Check to see if the type is a smart pointer of some kind. We assume // it's a smart pointer if it defines both operator-> and operator*. -static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) { +static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordDecl *Record) { auto IsOverloadedOperatorPresent = [&S](const RecordDecl *Record, OverloadedOperatorKind Op) { DeclContextLookupResult Result = @@ -177,7 +177,6 @@ static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) { return !Result.empty(); }; - const RecordDecl *Record = RT->getOriginalDecl()->getDefinitionOrSelf(); bool foundStarOperator = IsOverloadedOperatorPresent(Record, OO_Star); bool foundArrowOperator = IsOverloadedOperatorPresent(Record, OO_Arrow); if (foundStarOperator && foundArrowOperator) @@ -212,14 +211,14 @@ static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D, if (QT->isAnyPointerType()) return true; - if (const auto *RT = QT->getAs()) { + if (const auto *RD = QT->getAsRecordDecl()) { // If it's an incomplete type, it could be a smart pointer; skip it. // (We don't want to force template instantiation if we can avoid it, // since that would alter the order in which templates are instantiated.) - if (RT->isIncompleteType()) + if (!RD->isCompleteDefinition()) return true; - if (threadSafetyCheckIsSmartPointer(S, RT)) + if (threadSafetyCheckIsSmartPointer(S, RD)) return true; } @@ -229,13 +228,13 @@ static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D, /// Checks that the passed in QualType either is of RecordType or points /// to RecordType. Returns the relevant RecordType, null if it does not exit. -static const RecordType *getRecordType(QualType QT) { - if (const auto *RT = QT->getAs()) - return RT; +static const RecordDecl *getRecordDecl(QualType QT) { + if (const auto *RD = QT->getAsRecordDecl()) + return RD; - // Now check if we point to record type. + // Now check if we point to a record. if (const auto *PT = QT->getAs()) - return PT->getPointeeType()->getAs(); + return PT->getPointeeType()->getAsRecordDecl(); return nullptr; } @@ -257,36 +256,34 @@ static bool checkRecordDeclForAttr(const RecordDecl *RD) { } static bool checkRecordTypeForCapability(Sema &S, QualType Ty) { - const RecordType *RT = getRecordType(Ty); + const auto *RD = getRecordDecl(Ty); - if (!RT) + if (!RD) return false; // Don't check for the capability if the class hasn't been defined yet. - if (RT->isIncompleteType()) + if (!RD->isCompleteDefinition()) return true; // Allow smart pointers to be used as capability objects. // FIXME -- Check the type that the smart pointer points to. - if (threadSafetyCheckIsSmartPointer(S, RT)) + if (threadSafetyCheckIsSmartPointer(S, RD)) return true; - return checkRecordDeclForAttr( - RT->getOriginalDecl()->getDefinitionOrSelf()); + return checkRecordDeclForAttr(RD); } static bool checkRecordTypeForScopedCapability(Sema &S, QualType Ty) { - const RecordType *RT = getRecordType(Ty); + const auto *RD = getRecordDecl(Ty); - if (!RT) + if (!RD) return false; // Don't check for the capability if the class hasn't been defined yet. - if (RT->isIncompleteType()) + if (!RD->isCompleteDefinition()) return true; - return checkRecordDeclForAttr( - RT->getOriginalDecl()->getDefinitionOrSelf()); + return checkRecordDeclForAttr(RD); } static bool checkTypedefTypeForCapability(QualType Ty) { @@ -401,10 +398,10 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D, ArgTy = DRE->getDecl()->getType(); // First see if we can just cast to record type, or pointer to record type. - const RecordType *RT = getRecordType(ArgTy); + const auto *RD = getRecordDecl(ArgTy); // Now check if we index into a record type function param. - if(!RT && ParamIdxOk) { + if (!RD && ParamIdxOk) { const auto *FD = dyn_cast(D); const auto *IL = dyn_cast(ArgExp); if(FD && IL) { @@ -3639,7 +3636,7 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { QualType T = cast(D)->getType(); if (S.Context.getAsArrayType(T)) T = S.Context.getBaseElementType(T); - if (!T->getAs()) { + if (!T->isRecordType()) { S.Diag(AL.getLoc(), diag::err_init_priority_object_attr); AL.setInvalid(); return; @@ -4163,10 +4160,7 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { RecordDecl *RD = nullptr; const auto *TD = dyn_cast(D); if (TD && TD->getUnderlyingType()->isUnionType()) - RD = TD->getUnderlyingType() - ->getAsUnionType() - ->getOriginalDecl() - ->getDefinitionOrSelf(); + RD = TD->getUnderlyingType()->getAsRecordDecl(); else RD = dyn_cast(D); @@ -4739,14 +4733,14 @@ void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI, // GCC allows 'mode' attribute on enumeration types (even incomplete), except // for vector modes. So, 'enum X __attribute__((mode(QI)));' forms a complete // type, 'enum { A } __attribute__((mode(V4SI)))' is rejected. - if ((isa(D) || OldElemTy->getAs()) && + if ((isa(D) || OldElemTy->isEnumeralType()) && VectorSize.getBoolValue()) { Diag(AttrLoc, diag::err_enum_mode_vector_type) << Name << CI.getRange(); return; } bool IntegralOrAnyEnumType = (OldElemTy->isIntegralOrEnumerationType() && !OldElemTy->isBitIntType()) || - OldElemTy->getAs(); + OldElemTy->isEnumeralType(); if (!OldElemTy->getAs() && !OldElemTy->isComplexType() && !IntegralOrAnyEnumType) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index bb57968830a65..34e46fba8250f 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2925,9 +2925,7 @@ NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set, { // Even though the incoming type is a base, it might not be // a class -- it could be a template parm, for instance. - if (auto Rec = Type->getAs()) { - auto Decl = Rec->getAsCXXRecordDecl(); - + if (const auto *Decl = Type->getAsCXXRecordDecl()) { // Iterate over its bases. for (const auto &BaseSpec : Decl->bases()) { QualType Base = Context.getCanonicalType(BaseSpec.getType()) @@ -2986,9 +2984,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, if (Bases.size() > 1) NoteIndirectBases(Context, IndirectBaseTypes, NewBaseType); - if (const RecordType *Record = NewBaseType->getAs()) { - const CXXRecordDecl *RD = cast(Record->getOriginalDecl()) - ->getDefinitionOrSelf(); + if (const auto *RD = NewBaseType->getAsCXXRecordDecl()) { if (Class->isInterface() && (!RD->isInterfaceLike() || KnownBase->getAccessSpecifier() != AS_public)) { @@ -7611,12 +7607,9 @@ static bool defaultedSpecialMemberIsConstexpr( // class is a constexpr function, and if (!S.getLangOpts().CPlusPlus23) { for (const auto &B : ClassDecl->bases()) { - const RecordType *BaseType = B.getType()->getAs(); - if (!BaseType) + auto *BaseClassDecl = B.getType()->getAsCXXRecordDecl(); + if (!BaseClassDecl) continue; - CXXRecordDecl *BaseClassDecl = - cast(BaseType->getOriginalDecl()) - ->getDefinitionOrSelf(); if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg, InheritedCtor, Inherited)) return false; @@ -13937,12 +13930,10 @@ struct SpecialMemberExceptionSpecInfo } bool SpecialMemberExceptionSpecInfo::visitBase(CXXBaseSpecifier *Base) { - auto *RT = Base->getType()->getAs(); - if (!RT) + auto *BaseClass = Base->getType()->getAsCXXRecordDecl(); + if (!BaseClass) return false; - auto *BaseClass = - cast(RT->getOriginalDecl())->getDefinitionOrSelf(); Sema::SpecialMemberOverloadResult SMOR = lookupInheritedCtor(BaseClass); if (auto *BaseCtor = SMOR.getMethod()) { visitSubobjectCall(Base, BaseCtor); @@ -13966,11 +13957,9 @@ bool SpecialMemberExceptionSpecInfo::visitField(FieldDecl *FD) { E = S.BuildCXXDefaultInitExpr(Loc, FD).get(); if (E) ExceptSpec.CalledExpr(E); - } else if (auto *RT = S.Context.getBaseElementType(FD->getType()) - ->getAs()) { - visitClassSubobject( - cast(RT->getOriginalDecl())->getDefinitionOrSelf(), FD, - FD->getType().getCVRQualifiers()); + } else if (auto *RD = S.Context.getBaseElementType(FD->getType()) + ->getAsCXXRecordDecl()) { + visitClassSubobject(RD, FD, FD->getType().getCVRQualifiers()); } return false; } @@ -14785,11 +14774,9 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T, S.Context, To, UO_AddrOf, S.Context.getPointerType(To->getType()), VK_PRValue, OK_Ordinary, Loc, false, S.CurFPFeatureOverrides()); - const Type *E = T->getBaseElementTypeUnsafe(); - bool NeedsCollectableMemCpy = E->isRecordType() && E->castAs() - ->getOriginalDecl() - ->getDefinitionOrSelf() - ->hasObjectMember(); + bool NeedsCollectableMemCpy = false; + if (auto *RD = T->getBaseElementTypeUnsafe()->getAsRecordDecl()) + NeedsCollectableMemCpy = RD->hasObjectMember(); // Create a reference to the __builtin_objc_memmove_collectable function StringRef MemCpyName = NeedsCollectableMemCpy ? @@ -14865,10 +14852,7 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, // the class is used (as if by explicit qualification; that is, // ignoring any possible virtual overriding functions in more derived // classes); - if (const RecordType *RecordTy = T->getAs()) { - CXXRecordDecl *ClassDecl = - cast(RecordTy->getOriginalDecl())->getDefinitionOrSelf(); - + if (auto *ClassDecl = T->getAsCXXRecordDecl()) { // Look for operator=. DeclarationName Name = S.Context.DeclarationNames.getCXXOperatorName(OO_Equal); @@ -15340,7 +15324,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, // Check for members of const-qualified, non-class type. QualType BaseType = Context.getBaseElementType(Field->getType()); - if (!BaseType->getAs() && BaseType.isConstQualified()) { + if (!BaseType->isRecordType() && BaseType.isConstQualified()) { Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) << Context.getCanonicalTagType(ClassDecl) << 1 << Field->getDeclName(); @@ -15729,7 +15713,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, // Check for members of const-qualified, non-class type. QualType BaseType = Context.getBaseElementType(Field->getType()); - if (!BaseType->getAs() && BaseType.isConstQualified()) { + if (!BaseType->isRecordType() && BaseType.isConstQualified()) { Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) << Context.getCanonicalTagType(ClassDecl) << 1 << Field->getDeclName(); @@ -16322,15 +16306,14 @@ ExprResult Sema::BuildCXXConstructExpr( Constructor); } -void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { +void Sema::FinalizeVarWithDestructor(VarDecl *VD, CXXRecordDecl *ClassDecl) { if (VD->isInvalidDecl()) return; // If initializing the variable failed, don't also diagnose problems with // the destructor, they're likely related. if (VD->getInit() && VD->getInit()->containsErrors()) return; - CXXRecordDecl *ClassDecl = - cast(Record->getOriginalDecl())->getDefinitionOrSelf(); + ClassDecl = ClassDecl->getDefinitionOrSelf(); if (ClassDecl->isInvalidDecl()) return; if (ClassDecl->hasIrrelevantDestructor()) return; if (ClassDecl->isDependentContext()) return; @@ -17337,7 +17320,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo, Invalid = true; if (!Invalid && !ExDeclType->isDependentType()) { - if (const RecordType *recordType = ExDeclType->getAs()) { + if (auto *ClassDecl = ExDeclType->getAsCXXRecordDecl()) { // Insulate this from anything else we might currently be parsing. EnterExpressionEvaluationContext scope( *this, ExpressionEvaluationContext::PotentiallyEvaluated); @@ -17374,7 +17357,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo, } // And make sure it's destructable. - FinalizeVarWithDestructor(ExDecl, recordType); + FinalizeVarWithDestructor(ExDecl, ClassDecl); } } } @@ -18813,8 +18796,8 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, // that of B::f, the class type in the return type of D::f shall be // complete at the point of declaration of D::f or shall be the class // type D. - if (const RecordType *RT = NewClassTy->getAs()) { - if (!RT->getOriginalDecl()->isEntityBeingDefined() && + if (const auto *RD = NewClassTy->getAsCXXRecordDecl()) { + if (!RD->isBeingDefined() && RequireCompleteType(New->getLocation(), NewClassTy, diag::err_covariant_return_incomplete, New->getDeclName())) diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 88ed83eca243e..98eb5afb7c992 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -3848,10 +3848,8 @@ SemaObjC::ObjCContainerKind SemaObjC::getObjCContainerKind() const { static bool IsVariableSizedType(QualType T) { if (T->isIncompleteArrayType()) return true; - const auto *RecordTy = T->getAs(); - return (RecordTy && RecordTy->getOriginalDecl() - ->getDefinitionOrSelf() - ->hasFlexibleArrayMember()); + const auto *RD = T->getAsRecordDecl(); + return RD && RD->hasFlexibleArrayMember(); } static void DiagnoseVariableSizedIvars(Sema &S, ObjCContainerDecl *OCD) { @@ -3896,15 +3894,11 @@ static void DiagnoseVariableSizedIvars(Sema &S, ObjCContainerDecl *OCD) { << ivar->getDeclName() << IvarTy << TagTypeKind::Class; // Use "class" for Obj-C. IsInvalidIvar = true; - } else if (const RecordType *RecordTy = IvarTy->getAs()) { - if (RecordTy->getOriginalDecl() - ->getDefinitionOrSelf() - ->hasFlexibleArrayMember()) { - S.Diag(ivar->getLocation(), - diag::err_objc_variable_sized_type_not_at_end) - << ivar->getDeclName() << IvarTy; - IsInvalidIvar = true; - } + } else if (const auto *RD = IvarTy->getAsRecordDecl(); + RD && RD->hasFlexibleArrayMember()) { + S.Diag(ivar->getLocation(), diag::err_objc_variable_sized_type_not_at_end) + << ivar->getDeclName() << IvarTy; + IsInvalidIvar = true; } if (IsInvalidIvar) { S.Diag(ivar->getNextIvar()->getLocation(), @@ -5541,11 +5535,8 @@ void SemaObjC::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { AllToInit.push_back(Member); // Be sure that the destructor is accessible and is marked as referenced. - if (const RecordType *RecordTy = - Context.getBaseElementType(Field->getType()) - ->getAs()) { - CXXRecordDecl *RD = cast(RecordTy->getOriginalDecl()) - ->getDefinitionOrSelf(); + if (auto *RD = Context.getBaseElementType(Field->getType()) + ->getAsCXXRecordDecl()) { if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(RD)) { SemaRef.MarkFunctionReferenced(Field->getLocation(), Destructor); SemaRef.CheckDestructorAccess( diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index 94413b5b92d22..552c92996dc2e 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -163,9 +163,8 @@ bool Sema::CheckSpecifiedExceptionType(QualType &T, SourceRange Range) { DiagID = diag::ext_incomplete_in_exception_spec; ReturnValueOnError = false; } - if (!(PointeeT->isRecordType() && PointeeT->castAs() - ->getOriginalDecl() - ->isEntityBeingDefined()) && + if (auto *RD = PointeeT->getAsRecordDecl(); + !(RD && RD->isBeingDefined()) && RequireCompleteType(Range.getBegin(), PointeeT, DiagID, Kind, Range)) return ReturnValueOnError; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5a6b6ea9588b7..6e5cc7837ecc1 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -8641,16 +8641,11 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, // If both operands are the same structure or union type, the result is that // type. - if (const RecordType *LHSRT = LHSTy->getAs()) { // C99 6.5.15p3 - if (const RecordType *RHSRT = RHSTy->getAs()) - if (declaresSameEntity(LHSRT->getOriginalDecl(), - RHSRT->getOriginalDecl())) - // "If both the operands have structure or union type, the result has - // that type." This implies that CV qualifiers are dropped. - return Context.getCommonSugaredType(LHSTy.getUnqualifiedType(), - RHSTy.getUnqualifiedType()); - // FIXME: Type of conditional expression must be complete in C mode. - } + // FIXME: Type of conditional expression must be complete in C mode. + if (LHSTy->isRecordType() && + Context.hasSameUnqualifiedType(LHSTy, RHSTy)) // C99 6.5.15p3 + return Context.getCommonSugaredType(LHSTy.getUnqualifiedType(), + RHSTy.getUnqualifiedType()); // C99 6.5.15p5: "If both operands have void type, the result has void type." // The following || allows only one side to be void (a GCC-ism). @@ -16259,11 +16254,10 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, return ExprError(); // Look for the designated field. - const RecordType *RC = CurrentType->getAs(); - if (!RC) + auto *RD = CurrentType->getAsRecordDecl(); + if (!RD) return ExprError(Diag(OC.LocEnd, diag::err_offsetof_record_type) << CurrentType); - RecordDecl *RD = RC->getOriginalDecl()->getDefinitionOrSelf(); // C++ [lib.support.types]p5: // The macro offsetof accepts a restricted set of type arguments in this @@ -16660,8 +16654,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, auto *Var = cast(Cap.getVariable()); Expr *CopyExpr = nullptr; if (getLangOpts().CPlusPlus && Cap.isCopyCapture()) { - if (const RecordType *Record = - Cap.getCaptureType()->getAs()) { + if (auto *Record = Cap.getCaptureType()->getAsCXXRecordDecl()) { // The capture logic needs the destructor, so make sure we mark it. // Usually this is unnecessary because most local variables have // their destructors marked at declaration time, but parameters are @@ -18888,19 +18881,16 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, ValueDecl *Var, } // Prohibit structs with flexible array members too. // We cannot capture what is in the tail end of the struct. - if (const RecordType *VTTy = Var->getType()->getAs()) { - if (VTTy->getOriginalDecl() - ->getDefinitionOrSelf() - ->hasFlexibleArrayMember()) { - if (Diagnose) { - if (IsBlock) - S.Diag(Loc, diag::err_ref_flexarray_type); - else - S.Diag(Loc, diag::err_lambda_capture_flexarray_type) << Var; - S.Diag(Var->getLocation(), diag::note_previous_decl) << Var; - } - return false; + if (const auto *VTD = Var->getType()->getAsRecordDecl(); + VTD && VTD->hasFlexibleArrayMember()) { + if (Diagnose) { + if (IsBlock) + S.Diag(Loc, diag::err_ref_flexarray_type); + else + S.Diag(Loc, diag::err_lambda_capture_flexarray_type) << Var; + S.Diag(Var->getLocation(), diag::note_previous_decl) << Var; } + return false; } const bool HasBlocksAttr = Var->hasAttr(); // Lambdas and captured statements are not allowed to capture __block @@ -19980,7 +19970,7 @@ ExprResult Sema::CheckLValueToRValueConversionOperand(Expr *E) { // C++2a [basic.def.odr]p4: // [...] an expression of non-volatile-qualified non-class type to which // the lvalue-to-rvalue conversion is applied [...] - if (E->getType().isVolatileQualified() || E->getType()->getAs()) + if (E->getType().isVolatileQualified() || E->getType()->isRecordType()) return E; ExprResult Result = diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 2a82842095446..b257df438c019 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -543,7 +543,7 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, QualType T = Context.getUnqualifiedArrayType(Operand->getType().getNonReferenceType(), Quals); - if (T->getAs() && + if (T->isRecordType() && RequireCompleteType(TypeidLoc, T, diag::err_incomplete_typeid)) return ExprError(); @@ -570,9 +570,7 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, } QualType T = E->getType(); - if (const RecordType *RecordT = T->getAs()) { - CXXRecordDecl *RecordD = cast(RecordT->getOriginalDecl()) - ->getDefinitionOrSelf(); + if (auto *RecordD = T->getAsCXXRecordDecl()) { // C++ [expr.typeid]p3: // [...] If the type of the expression is a class type, the class // shall be completely-defined. @@ -2297,8 +2295,7 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, ConvertedSize = PerformImplicitConversion( *ArraySize, Context.getSizeType(), AssignmentAction::Converting); - if (!ConvertedSize.isInvalid() && - (*ArraySize)->getType()->getAs()) + if (!ConvertedSize.isInvalid() && (*ArraySize)->getType()->isRecordType()) // Diagnose the compatibility of this conversion. Diag(StartLoc, diag::warn_cxx98_compat_array_size_conversion) << (*ArraySize)->getType() << 0 << "'size_t'"; @@ -4070,9 +4067,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, ? diag::err_delete_incomplete : diag::warn_delete_incomplete, Ex.get())) { - if (const RecordType *RT = PointeeElem->getAs()) - PointeeRD = - cast(RT->getOriginalDecl())->getDefinitionOrSelf(); + PointeeRD = PointeeElem->getAsCXXRecordDecl(); } } diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index f87715950c74c..1b4e0952fe346 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -236,9 +236,8 @@ static unsigned calculateLegacyCbufferFieldAlign(const ASTContext &Context, static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T) { constexpr unsigned CBufferAlign = 16; - if (const RecordType *RT = T->getAs()) { + if (const auto *RD = T->getAsRecordDecl()) { unsigned Size = 0; - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); for (const FieldDecl *Field : RD->fields()) { QualType Ty = Field->getType(); unsigned FieldSize = calculateLegacyCbufferSize(Context, Ty); @@ -364,8 +363,8 @@ static bool isInvalidConstantBufferLeafElementType(const Type *Ty) { Ty = Ty->getUnqualifiedDesugaredType(); if (Ty->isHLSLResourceRecord() || Ty->isHLSLResourceRecordArray()) return true; - if (Ty->isRecordType()) - return Ty->getAsCXXRecordDecl()->isEmpty(); + if (const auto *RD = Ty->getAsCXXRecordDecl()) + return RD->isEmpty(); if (Ty->isConstantArrayType() && isZeroSizedArray(cast(Ty))) return true; @@ -459,8 +458,7 @@ static FieldDecl *createFieldForHostLayoutStruct(Sema &S, const Type *Ty, if (isInvalidConstantBufferLeafElementType(Ty)) return nullptr; - if (Ty->isRecordType()) { - CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); + if (auto *RD = Ty->getAsCXXRecordDecl()) { if (requiresImplicitBufferLayoutStructure(RD)) { RD = createHostLayoutStruct(S, RD); if (!RD) @@ -3194,10 +3192,7 @@ static void BuildFlattenedTypeList(QualType BaseTy, List.insert(List.end(), VT->getNumElements(), VT->getElementType()); continue; } - if (const auto *RT = dyn_cast(T)) { - const CXXRecordDecl *RD = RT->getAsCXXRecordDecl(); - assert(RD && "HLSL record types should all be CXXRecordDecls!"); - + if (const auto *RD = T->getAsCXXRecordDecl()) { if (RD->isStandardLayout()) RD = RD->getStandardLayoutBaseWithFields(); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 60f9d449fc037..0242671aecdb3 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -921,8 +921,7 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, if (ILE->isTransparent()) return; - if (const RecordType *RType = ILE->getType()->getAs()) { - const RecordDecl *RDecl = RType->getOriginalDecl()->getDefinitionOrSelf(); + if (const auto *RDecl = ILE->getType()->getAsRecordDecl()) { if (RDecl->isUnion() && ILE->getInitializedFieldInUnion()) { FillInEmptyInitForField(0, ILE->getInitializedFieldInUnion(), Entity, ILE, RequiresSecondPass, FillWithNoInit); @@ -5718,64 +5717,60 @@ static void TryValueInitialization(Sema &S, // -- if T is an array type, then each element is value-initialized; T = S.Context.getBaseElementType(T); - if (const RecordType *RT = T->getAs()) { - if (CXXRecordDecl *ClassDecl = - dyn_cast(RT->getOriginalDecl())) { - ClassDecl = ClassDecl->getDefinitionOrSelf(); - bool NeedZeroInitialization = true; - // C++98: - // -- if T is a class type (clause 9) with a user-declared constructor - // (12.1), then the default constructor for T is called (and the - // initialization is ill-formed if T has no accessible default - // constructor); - // C++11: - // -- if T is a class type (clause 9) with either no default constructor - // (12.1 [class.ctor]) or a default constructor that is user-provided - // or deleted, then the object is default-initialized; - // - // Note that the C++11 rule is the same as the C++98 rule if there are no - // defaulted or deleted constructors, so we just use it unconditionally. - CXXConstructorDecl *CD = S.LookupDefaultConstructor(ClassDecl); - if (!CD || !CD->getCanonicalDecl()->isDefaulted() || CD->isDeleted()) - NeedZeroInitialization = false; - - // -- if T is a (possibly cv-qualified) non-union class type without a - // user-provided or deleted default constructor, then the object is - // zero-initialized and, if T has a non-trivial default constructor, - // default-initialized; - // The 'non-union' here was removed by DR1502. The 'non-trivial default - // constructor' part was removed by DR1507. - if (NeedZeroInitialization) - Sequence.AddZeroInitializationStep(Entity.getType()); - - // C++03: - // -- if T is a non-union class type without a user-declared constructor, - // then every non-static data member and base class component of T is - // value-initialized; - // [...] A program that calls for [...] value-initialization of an - // entity of reference type is ill-formed. - // - // C++11 doesn't need this handling, because value-initialization does not - // occur recursively there, and the implicit default constructor is - // defined as deleted in the problematic cases. - if (!S.getLangOpts().CPlusPlus11 && - ClassDecl->hasUninitializedReferenceMember()) { - Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForReference); - return; - } - - // If this is list-value-initialization, pass the empty init list on when - // building the constructor call. This affects the semantics of a few - // things (such as whether an explicit default constructor can be called). - Expr *InitListAsExpr = InitList; - MultiExprArg Args(&InitListAsExpr, InitList ? 1 : 0); - bool InitListSyntax = InitList; + if (auto *ClassDecl = T->getAsCXXRecordDecl()) { + bool NeedZeroInitialization = true; + // C++98: + // -- if T is a class type (clause 9) with a user-declared constructor + // (12.1), then the default constructor for T is called (and the + // initialization is ill-formed if T has no accessible default + // constructor); + // C++11: + // -- if T is a class type (clause 9) with either no default constructor + // (12.1 [class.ctor]) or a default constructor that is user-provided + // or deleted, then the object is default-initialized; + // + // Note that the C++11 rule is the same as the C++98 rule if there are no + // defaulted or deleted constructors, so we just use it unconditionally. + CXXConstructorDecl *CD = S.LookupDefaultConstructor(ClassDecl); + if (!CD || !CD->getCanonicalDecl()->isDefaulted() || CD->isDeleted()) + NeedZeroInitialization = false; + + // -- if T is a (possibly cv-qualified) non-union class type without a + // user-provided or deleted default constructor, then the object is + // zero-initialized and, if T has a non-trivial default constructor, + // default-initialized; + // The 'non-union' here was removed by DR1502. The 'non-trivial default + // constructor' part was removed by DR1507. + if (NeedZeroInitialization) + Sequence.AddZeroInitializationStep(Entity.getType()); - // FIXME: Instead of creating a CXXConstructExpr of array type here, - // wrap a class-typed CXXConstructExpr in an ArrayInitLoopExpr. - return TryConstructorInitialization( - S, Entity, Kind, Args, T, Entity.getType(), Sequence, InitListSyntax); + // C++03: + // -- if T is a non-union class type without a user-declared constructor, + // then every non-static data member and base class component of T is + // value-initialized; + // [...] A program that calls for [...] value-initialization of an + // entity of reference type is ill-formed. + // + // C++11 doesn't need this handling, because value-initialization does not + // occur recursively there, and the implicit default constructor is + // defined as deleted in the problematic cases. + if (!S.getLangOpts().CPlusPlus11 && + ClassDecl->hasUninitializedReferenceMember()) { + Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForReference); + return; } + + // If this is list-value-initialization, pass the empty init list on when + // building the constructor call. This affects the semantics of a few + // things (such as whether an explicit default constructor can be called). + Expr *InitListAsExpr = InitList; + MultiExprArg Args(&InitListAsExpr, InitList ? 1 : 0); + bool InitListSyntax = InitList; + + // FIXME: Instead of creating a CXXConstructExpr of array type here, + // wrap a class-typed CXXConstructExpr in an ArrayInitLoopExpr. + return TryConstructorInitialization( + S, Entity, Kind, Args, T, Entity.getType(), Sequence, InitListSyntax); } Sequence.AddZeroInitializationStep(Entity.getType()); @@ -5917,10 +5912,8 @@ static void TryOrBuildParenListInitialization( AT->getElementType(), llvm::APInt(/*numBits=*/32, ArrayLength), /*SizeExpr=*/nullptr, ArraySizeModifier::Normal, 0); } - } else if (auto *RT = Entity.getType()->getAs()) { - bool IsUnion = RT->isUnionType(); - const auto *RD = - cast(RT->getOriginalDecl())->getDefinitionOrSelf(); + } else if (auto *RD = Entity.getType()->getAsCXXRecordDecl()) { + bool IsUnion = RD->isUnion(); if (RD->isInvalidDecl()) { // Exit early to avoid confusion when processing members. // We do the same for braced list initialization in @@ -6237,7 +6230,7 @@ static void TryUserDefinedConversion(Sema &S, Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType, HadMultipleCandidates); - if (ConvType->getAs()) { + if (ConvType->isRecordType()) { // The call is used to direct-initialize [...] the object that is the // destination of the copy-initialization. // @@ -7180,10 +7173,7 @@ static ExprResult CopyObject(Sema &S, return CurInit; // Determine which class type we're copying to. Expr *CurInitExpr = (Expr *)CurInit.get(); - CXXRecordDecl *Class = nullptr; - if (const RecordType *Record = T->getAs()) - Class = - cast(Record->getOriginalDecl())->getDefinitionOrSelf(); + auto *Class = T->getAsCXXRecordDecl(); if (!Class) return CurInit; @@ -7328,7 +7318,7 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S, Expr *CurInitExpr) { assert(S.getLangOpts().CPlusPlus11); - const RecordType *Record = CurInitExpr->getType()->getAs(); + auto *Record = CurInitExpr->getType()->getAsCXXRecordDecl(); if (!Record) return; @@ -7338,8 +7328,7 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S, // Find constructors which would have been considered. OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); - DeclContext::lookup_result Ctors = S.LookupConstructors( - cast(Record->getOriginalDecl())->getDefinitionOrSelf()); + DeclContext::lookup_result Ctors = S.LookupConstructors(Record); // Perform overload resolution. OverloadCandidateSet::iterator Best; @@ -7803,7 +7792,7 @@ ExprResult InitializationSequence::Perform(Sema &S, DiagID = diag::ext_default_init_const; S.Diag(Kind.getLocation(), DiagID) - << DestType << (bool)DestType->getAs() + << DestType << DestType->isRecordType() << FixItHint::CreateInsertion(ZeroInitializationFixitLoc, ZeroInitializationFixit); } @@ -9242,8 +9231,7 @@ bool InitializationSequence::Diagnose(Sema &S, S.Diag(Entity.getDecl()->getLocation(), diag::note_member_declared_at); - if (const RecordType *Record - = Entity.getType()->getAs()) + if (const auto *Record = Entity.getType()->getAs()) S.Diag(Record->getOriginalDecl()->getLocation(), diag::note_previous_decl) << S.Context.getCanonicalTagType(Record->getOriginalDecl()); @@ -9326,7 +9314,7 @@ bool InitializationSequence::Diagnose(Sema &S, << VD; } else { S.Diag(Kind.getLocation(), diag::err_default_init_const) - << DestType << (bool)DestType->getAs(); + << DestType << DestType->isRecordType(); } break; @@ -10021,7 +10009,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( // dependent. e.g. // using AliasFoo = Foo; if (const auto *CTSD = llvm::dyn_cast( - RT->getAsCXXRecordDecl())) + RT->getOriginalDecl())) Template = CTSD->getSpecializedTemplate(); } } diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index e28492b579564..68f7af139af46 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -3114,17 +3114,15 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, // Visit the base classes. for (const auto &Base : Class->bases()) { - const RecordType *BaseType = Base.getType()->getAs(); + CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); // In dependent contexts, we do ADL twice, and the first time around, // the base type might be a dependent TemplateSpecializationType, or a // TemplateTypeParmType. If that happens, simply ignore it. // FIXME: If we want to support export, we probably need to add the // namespace of the template in a TemplateSpecializationType, or even // the classes and namespaces of known non-dependent arguments. - if (!BaseType) + if (!BaseDecl) continue; - CXXRecordDecl *BaseDecl = cast(BaseType->getOriginalDecl()) - ->getDefinitionOrSelf(); if (Result.addClassTransitive(BaseDecl)) { // Find the associated namespace for this base class. DeclContext *BaseCtx = BaseDecl->getDeclContext(); @@ -4262,10 +4260,9 @@ class LookupVisibleHelper { continue; RD = TD->getTemplatedDecl(); } else { - const auto *Record = BaseType->getAs(); - if (!Record) + RD = BaseType->getAsCXXRecordDecl(); + if (!RD) continue; - RD = Record->getOriginalDecl()->getDefinitionOrSelf(); } // FIXME: It would be nice to be able to determine whether referencing diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index bf6c364e40cc4..1880cec6ec8e5 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -1320,10 +1320,8 @@ Decl *SemaObjC::ActOnPropertyImplDecl( CompleteTypeErr = true; } if (!CompleteTypeErr) { - const RecordType *RecordTy = PropertyIvarType->getAs(); - if (RecordTy && RecordTy->getOriginalDecl() - ->getDefinitionOrSelf() - ->hasFlexibleArrayMember()) { + if (const auto *RD = PropertyIvarType->getAsRecordDecl(); + RD && RD->hasFlexibleArrayMember()) { Diag(PropertyIvarLoc, diag::err_synthesize_variable_sized_ivar) << PropertyIvarType; CompleteTypeErr = true; // suppress later diagnostics about the ivar diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 7c4405b414c47..5678804d87f1f 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1058,13 +1058,12 @@ static bool shouldAddReversedEqEq(Sema &S, SourceLocation OpLoc, if (isa(EqFD)) { // If F is a class member, search scope is class type of first operand. QualType RHS = FirstOperand->getType(); - auto *RHSRec = RHS->getAs(); + auto *RHSRec = RHS->getAsCXXRecordDecl(); if (!RHSRec) return true; LookupResult Members(S, NotEqOp, OpLoc, Sema::LookupNameKind::LookupMemberName); - S.LookupQualifiedName(Members, - RHSRec->getOriginalDecl()->getDefinitionOrSelf()); + S.LookupQualifiedName(Members, RHSRec); Members.suppressAccessDiagnostics(); for (NamedDecl *Op : Members) if (FunctionsCorrespond(S.Context, EqFD, Op->getAsFunction())) @@ -1802,7 +1801,7 @@ TryImplicitConversion(Sema &S, Expr *From, QualType ToType, // constructor (i.e., a user-defined conversion function) is // called for those cases. QualType FromType = From->getType(); - if (ToType->getAs() && FromType->getAs() && + if (ToType->isRecordType() && (S.Context.hasSameUnqualifiedType(FromType, ToType) || S.IsDerivedFrom(From->getBeginLoc(), FromType, ToType))) { ICS.setStandard(); @@ -3979,7 +3978,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // that class. The argument list is the expression-list within // the parentheses of the initializer. if (S.Context.hasSameUnqualifiedType(ToType, From->getType()) || - (From->getType()->getAs() && + (From->getType()->isRecordType() && S.IsDerivedFrom(From->getBeginLoc(), From->getType(), ToType))) ConstructorsOnly = true; @@ -8742,10 +8741,9 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, // defined, the set of member candidates is the result of the // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise, // the set of member candidates is empty. - if (const RecordType *T1Rec = T1->getAs()) { + if (T1->isRecordType()) { bool IsComplete = isCompleteType(OpLoc, T1); - CXXRecordDecl *T1RD = - cast(T1Rec->getOriginalDecl())->getDefinition(); + auto *T1RD = T1->getAsCXXRecordDecl(); // Complete the type if it can be completed. // If the type is neither complete nor being defined, bail out now. if (!T1RD || (!IsComplete && !T1RD->isBeingDefined())) @@ -9054,8 +9052,8 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, Ty = Ty.getLocalUnqualifiedType(); // Flag if we ever add a non-record type. - const RecordType *TyRec = Ty->getAs(); - HasNonRecordTypes = HasNonRecordTypes || !TyRec; + bool TyIsRec = Ty->isRecordType(); + HasNonRecordTypes = HasNonRecordTypes || !TyIsRec; // Flag if we encounter an arithmetic type. HasArithmeticOrEnumeralTypes = @@ -9090,13 +9088,14 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, MatrixTypes.insert(Ty); } else if (Ty->isNullPtrType()) { HasNullPtrType = true; - } else if (AllowUserConversions && TyRec) { + } else if (AllowUserConversions && TyIsRec) { // No conversion functions in incomplete types. if (!SemaRef.isCompleteType(Loc, Ty)) return; auto *ClassDecl = - cast(TyRec->getOriginalDecl())->getDefinitionOrSelf(); + cast(Ty->getAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); for (NamedDecl *D : ClassDecl->getVisibleConversionFunctions()) { if (isa(D)) D = cast(D)->getTargetDecl(); diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp index cd8b98c7444eb..f797756450298 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -944,16 +944,15 @@ Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member, /*FirstQualifierFoundInScope=*/nullptr, NameInfo, /*TemplateArgs=*/nullptr); } - const RecordType *RT = T->getAs(); + auto *RD = T->getAsRecordDecl(); // FIXME: Diagnose this as field access into a scalar type. - if (!RT) + if (!RD) return ExprResult(); LookupResult FieldResult(*this, &Context.Idents.get(Member), AsmLoc, LookupMemberName); - if (!LookupQualifiedName(FieldResult, - RT->getOriginalDecl()->getDefinitionOrSelf())) + if (!LookupQualifiedName(FieldResult, RD)) return ExprResult(); // Only normal and indirect field results will work. diff --git a/clang/lib/Sema/SemaSwift.cpp b/clang/lib/Sema/SemaSwift.cpp index a99222c5ed55f..d21d79344d5c7 100644 --- a/clang/lib/Sema/SemaSwift.cpp +++ b/clang/lib/Sema/SemaSwift.cpp @@ -129,9 +129,9 @@ static bool isErrorParameter(Sema &S, QualType QT) { // Check for CFError**. if (const auto *PT = Pointee->getAs()) - if (const auto *RT = PT->getPointeeType()->getAs()) - if (S.ObjC().isCFError(RT->getOriginalDecl()->getDefinitionOrSelf())) - return true; + if (auto *RD = PT->getPointeeType()->getAsRecordDecl(); + RD && S.ObjC().isCFError(RD)) + return true; return false; } @@ -271,12 +271,10 @@ static void checkSwiftAsyncErrorBlock(Sema &S, Decl *D, } // Check for CFError *. if (const auto *PtrTy = Param->getAs()) { - if (const auto *RT = PtrTy->getPointeeType()->getAs()) { - if (S.ObjC().isCFError( - RT->getOriginalDecl()->getDefinitionOrSelf())) { - AnyErrorParams = true; - break; - } + if (auto *RD = PtrTy->getPointeeType()->getAsRecordDecl(); + RD && S.ObjC().isCFError(RD)) { + AnyErrorParams = true; + break; } } } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 36bffc5e5e3c9..ff273ab6fd2f5 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4087,7 +4087,7 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, // Check the tag kind if (const RecordType *RT = Result->getAs()) { - RecordDecl *D = RT->getOriginalDecl()->getDefinitionOrSelf(); + RecordDecl *D = RT->getOriginalDecl(); IdentifierInfo *Id = D->getIdentifier(); assert(Id && "templated class must have an identifier"); diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 93983bf6d1607..f481a009edab8 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3559,7 +3559,7 @@ static bool isSimpleTemplateIdType(QualType T) { // // This only arises during class template argument deduction for a copy // deduction candidate, where it permits slicing. - if (T->getAs()) + if (isa(T.getCanonicalType())) return true; return false; diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index 604591408728c..7a7aca8a52d68 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -995,8 +995,8 @@ getRHSTemplateDeclAndArgs(Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate) { // Cases where template arguments in the RHS of the alias are not // dependent. e.g. // using AliasFoo = Foo; - if (const auto *CTSD = llvm::dyn_cast( - RT->getAsCXXRecordDecl())) { + if (const auto *CTSD = + dyn_cast(RT->getOriginalDecl())) { Template = CTSD->getSpecializedTemplate(); AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray(); } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 681ee796440f3..ee1b520fa46e9 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -6973,19 +6973,15 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, // If our context used to be dependent, we may need to instantiate // it before performing lookup into that context. bool IsBeingInstantiated = false; - if (CXXRecordDecl *Spec = dyn_cast(ParentDC)) { + if (auto *Spec = dyn_cast(ParentDC)) { if (!Spec->isDependentContext()) { - CanQualType T = Context.getCanonicalTagType(Spec); - const RecordType *Tag = T->getAs(); - assert(Tag && "type of non-dependent record is not a RecordType"); - auto *TagDecl = - cast(Tag->getOriginalDecl())->getDefinitionOrSelf(); - if (TagDecl->isBeingDefined()) + if (Spec->isEntityBeingDefined()) IsBeingInstantiated = true; - else if (RequireCompleteType(Loc, T, diag::err_incomplete_type)) + else if (RequireCompleteType(Loc, Context.getCanonicalTagType(Spec), + diag::err_incomplete_type)) return nullptr; - ParentDC = TagDecl; + ParentDC = Spec->getDefinitionOrSelf(); } } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index d745cdbf0526f..015fb0577df39 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2115,12 +2115,10 @@ QualType Sema::BuildArrayType(QualType T, ArraySizeModifier ASM, return QualType(); } - if (const RecordType *EltTy = T->getAs()) { + if (const auto *RD = T->getAsRecordDecl()) { // If the element type is a struct or union that contains a variadic // array, accept it as a GNU extension: C99 6.7.2.1p2. - if (EltTy->getOriginalDecl() - ->getDefinitionOrSelf() - ->hasFlexibleArrayMember()) + if (RD->hasFlexibleArrayMember()) Diag(Loc, diag::ext_flexible_array_in_array) << T; } else if (T->isObjCObjectType()) { Diag(Loc, diag::err_objc_array_of_interfaces) << T; @@ -3975,10 +3973,7 @@ classifyPointerDeclarator(Sema &S, QualType type, Declarator &declarator, if (numNormalPointers == 0) return PointerDeclaratorKind::NonPointer; - if (auto recordType = type->getAs()) { - RecordDecl *recordDecl = - recordType->getOriginalDecl()->getDefinitionOrSelf(); - + if (auto *recordDecl = type->getAsRecordDecl()) { // If this is CFErrorRef*, report it as such. if (numNormalPointers == 2 && numTypeSpecifierPointers < 2 && S.ObjC().isCFError(recordDecl)) { diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 0b4d5916f8dc3..051bf1462685f 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -556,13 +556,11 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, } } -static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op, +static bool HasNoThrowOperator(CXXRecordDecl *RD, OverloadedOperatorKind Op, Sema &Self, SourceLocation KeyLoc, ASTContext &C, bool (CXXRecordDecl::*HasTrivial)() const, bool (CXXRecordDecl::*HasNonTrivial)() const, bool (CXXMethodDecl::*IsDesiredOp)() const) { - CXXRecordDecl *RD = - cast(RT->getOriginalDecl())->getDefinitionOrSelf(); if ((RD->*HasTrivial)() && !(RD->*HasNonTrivial)()) return true; @@ -1007,8 +1005,8 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, if (T.isPODType(C) || T->isObjCLifetimeType()) return true; - if (const RecordType *RT = T->getAs()) - return HasNoThrowOperator(RT, OO_Equal, Self, KeyLoc, C, + if (auto *RD = T->getAsCXXRecordDecl()) + return HasNoThrowOperator(RD, OO_Equal, Self, KeyLoc, C, &CXXRecordDecl::hasTrivialCopyAssignment, &CXXRecordDecl::hasNonTrivialCopyAssignment, &CXXMethodDecl::isCopyAssignmentOperator); @@ -1020,8 +1018,8 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, if (T.isPODType(C)) return true; - if (const RecordType *RT = C.getBaseElementType(T)->getAs()) - return HasNoThrowOperator(RT, OO_Equal, Self, KeyLoc, C, + if (auto *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) + return HasNoThrowOperator(RD, OO_Equal, Self, KeyLoc, C, &CXXRecordDecl::hasTrivialMoveAssignment, &CXXRecordDecl::hasNonTrivialMoveAssignment, &CXXMethodDecl::isMoveAssignmentOperator); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 87550614f645b..b9404c60f3bd1 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -14369,9 +14369,9 @@ TreeTransform::TransformCXXTypeidExpr(CXXTypeidExpr *E) { Expr *Op = E->getExprOperand(); auto EvalCtx = Sema::ExpressionEvaluationContext::Unevaluated; if (E->isGLValue()) - if (auto *RecordT = Op->getType()->getAs()) - if (cast(RecordT->getOriginalDecl())->isPolymorphic()) - EvalCtx = SemaRef.ExprEvalContexts.back().Context; + if (auto *RD = Op->getType()->getAsCXXRecordDecl(); + RD && RD->isPolymorphic()) + EvalCtx = SemaRef.ExprEvalContexts.back().Context; EnterExpressionEvaluationContext Unevaluated(SemaRef, EvalCtx, Sema::ReuseLambdaContextDecl); @@ -14612,12 +14612,9 @@ TreeTransform::TransformCXXNewExpr(CXXNewExpr *E) { if (E->isArray() && !E->getAllocatedType()->isDependentType()) { QualType ElementType = SemaRef.Context.getBaseElementType(E->getAllocatedType()); - if (const RecordType *RecordT = ElementType->getAs()) { - CXXRecordDecl *Record = cast(RecordT->getOriginalDecl()) - ->getDefinitionOrSelf(); - if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(Record)) { + if (CXXRecordDecl *Record = ElementType->getAsCXXRecordDecl()) { + if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(Record)) SemaRef.MarkFunctionReferenced(E->getBeginLoc(), Destructor); - } } } @@ -14683,13 +14680,9 @@ TreeTransform::TransformCXXDeleteExpr(CXXDeleteExpr *E) { if (!E->getArgument()->isTypeDependent()) { QualType Destroyed = SemaRef.Context.getBaseElementType( E->getDestroyedType()); - if (const RecordType *DestroyedRec = Destroyed->getAs()) { - CXXRecordDecl *Record = - cast(DestroyedRec->getOriginalDecl()) - ->getDefinitionOrSelf(); + if (auto *Record = Destroyed->getAsCXXRecordDecl()) SemaRef.MarkFunctionReferenced(E->getBeginLoc(), SemaRef.LookupDestructor(Record)); - } } return E; @@ -17671,13 +17664,11 @@ TreeTransform::RebuildCXXPseudoDestructorExpr(Expr *Base, } SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller. - return getSema().BuildMemberReferenceExpr(Base, BaseType, - OperatorLoc, isArrow, - SS, TemplateKWLoc, - /*FIXME: FirstQualifier*/ nullptr, - NameInfo, - /*TemplateArgs*/ nullptr, - /*S*/nullptr); + return getSema().BuildMemberReferenceExpr( + Base, Base->getType(), OperatorLoc, isArrow, SS, TemplateKWLoc, + /*FIXME: FirstQualifier*/ nullptr, NameInfo, + /*TemplateArgs*/ nullptr, + /*S*/ nullptr); } template diff --git a/clang/lib/Sema/UsedDeclVisitor.h b/clang/lib/Sema/UsedDeclVisitor.h index ad475ab0f42ae..546b3a9e66e21 100644 --- a/clang/lib/Sema/UsedDeclVisitor.h +++ b/clang/lib/Sema/UsedDeclVisitor.h @@ -70,12 +70,10 @@ class UsedDeclVisitor : public EvaluatedExprVisitor { QualType DestroyedOrNull = E->getDestroyedType(); if (!DestroyedOrNull.isNull()) { QualType Destroyed = S.Context.getBaseElementType(DestroyedOrNull); - if (const RecordType *DestroyedRec = Destroyed->getAs()) { - CXXRecordDecl *Record = - cast(DestroyedRec->getOriginalDecl()); - if (auto *Def = Record->getDefinition()) - asImpl().visitUsedDecl(E->getBeginLoc(), S.LookupDestructor(Def)); - } + if (auto *Record = Destroyed->getAsCXXRecordDecl(); + Record && + (Record->isBeingDefined() || Record->isCompleteDefinition())) + asImpl().visitUsedDecl(E->getBeginLoc(), S.LookupDestructor(Record)); } Inherited::VisitCXXDeleteExpr(E); diff --git a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp index 731e506a5d259..e98710aadacf2 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp @@ -258,7 +258,7 @@ class FindUninitializedField { const FieldRegion *FR = MrMgr.getFieldRegion(I, R); FieldChain.push_back(I); T = I->getType(); - if (T->getAsStructureType()) { + if (T->isStructureType()) { if (Find(FR)) return true; } else { diff --git a/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp index 90c6537d71d9d..781216da77f73 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp @@ -49,11 +49,10 @@ class CastSizeChecker : public Checker< check::PreStmt > { /// of struct bar. static bool evenFlexibleArraySize(ASTContext &Ctx, CharUnits RegionSize, CharUnits TypeSize, QualType ToPointeeTy) { - const RecordType *RT = ToPointeeTy->getAs(); - if (!RT) + const auto *RD = ToPointeeTy->getAsRecordDecl(); + if (!RD) return false; - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); RecordDecl::field_iterator Iter(RD->field_begin()); RecordDecl::field_iterator End(RD->field_end()); const FieldDecl *Last = nullptr; diff --git a/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp index 828b6f91d81c2..91faefde43b00 100644 --- a/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp @@ -195,14 +195,10 @@ static bool IsPartOfAST(const CXXRecordDecl *R) { if (IsClangStmt(R) || IsClangType(R) || IsClangDecl(R) || IsClangAttr(R)) return true; - for (const auto &BS : R->bases()) { - QualType T = BS.getType(); - if (const RecordType *baseT = T->getAs()) { - CXXRecordDecl *baseD = cast(baseT->getOriginalDecl()); - if (IsPartOfAST(baseD)) - return true; - } - } + for (const auto &BS : R->bases()) + if (const auto *baseD = BS.getType()->getAsCXXRecordDecl(); + baseD && IsPartOfAST(baseD)) + return true; return false; } @@ -243,11 +239,9 @@ void ASTFieldVisitor::Visit(FieldDecl *D) { if (AllocatesMemory(T)) ReportError(T); - if (const RecordType *RT = T->getAs()) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinition(); + if (const auto *RD = T->getAsRecordDecl()) for (auto *I : RD->fields()) Visit(I); - } FieldChain.pop_back(); } diff --git a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp index 7ef659518ab1b..1554604b374ca 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp @@ -118,12 +118,12 @@ class PaddingChecker : public Checker> { Elts = CArrTy->getZExtSize(); if (Elts == 0) return; - const RecordType *RT = ArrTy->getElementType()->getAs(); - if (RT == nullptr) + const auto *RD = ArrTy->getElementType()->getAsRecordDecl(); + if (!RD) return; // TODO: Recurse into the fields to see if they have excess padding. - visitRecord(RT->getOriginalDecl()->getDefinitionOrSelf(), Elts); + visitRecord(RD, Elts); } bool shouldSkipDecl(const RecordDecl *RD) const { diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index c853c00019c10..785cdfa15bf04 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -3165,7 +3165,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) { // feasible then it shouldn't be considered for making 'default:' reachable. const SwitchStmt *SS = builder.getSwitch(); const Expr *CondExpr = SS->getCond()->IgnoreParenImpCasts(); - if (CondExpr->getType()->getAs()) { + if (CondExpr->getType()->isEnumeralType()) { if (SS->isAllEnumCasesCovered()) return; } diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index e1aa9bb0721f8..858423a06576a 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1728,7 +1728,7 @@ bool CursorVisitor::VisitUsingTypeLoc(UsingTypeLoc TL) { if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc())) return true; - auto *underlyingDecl = TL.getTypePtr()->desugar()->getAsTagDecl(); + auto *underlyingDecl = TL.getTypePtr()->getAsTagDecl(); if (underlyingDecl) { return Visit(MakeCursorTypeRef(underlyingDecl, TL.getNameLoc(), TU)); } diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 15df9af889386..5badbd7d65e48 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -9189,7 +9189,7 @@ struct ImportInjectedClassNameType : public ASTImporterOptionSpecificTestBase { .getTypePtr(); ASSERT_TRUE(Ty); EXPECT_FALSE(Ty->isCanonicalUnqualified()); - const auto *InjTy = Ty->castAs(); + const auto *InjTy = dyn_cast(Ty); EXPECT_TRUE(InjTy); for (const Decl *ReD : D->redecls()) { if (ReD == D) @@ -9204,8 +9204,6 @@ struct ImportInjectedClassNameType : public ASTImporterOptionSpecificTestBase { EXPECT_FALSE(ReTy->isCanonicalUnqualified()); EXPECT_NE(ReTy, Ty); EXPECT_TRUE(Ctx.hasSameType(ReTy, Ty)); - const auto *ReInjTy = Ty->castAs(); - EXPECT_TRUE(ReInjTy); } } diff --git a/clang/unittests/AST/RandstructTest.cpp b/clang/unittests/AST/RandstructTest.cpp index cba446fc529e1..a90665b2c0631 100644 --- a/clang/unittests/AST/RandstructTest.cpp +++ b/clang/unittests/AST/RandstructTest.cpp @@ -531,8 +531,7 @@ TEST(RANDSTRUCT_TEST, AnonymousStructsAndUnionsRetainFieldOrder) { for (const Decl *D : RD->decls()) if (const FieldDecl *FD = dyn_cast(D)) { - if (const auto *Record = FD->getType()->getAs()) { - RD = Record->getOriginalDecl()->getDefinitionOrSelf(); + if (const auto *RD = FD->getType()->getAsRecordDecl()) { if (RD->isAnonymousStructOrUnion()) { // These field orders shouldn't change. if (RD->isUnion()) {