[clang] NFC: change more places to use Type::getAsTagDecl and friends (#155313)

This changes a bunch of places which use getAs<TagType>, including
derived types, just to obtain the tag definition.

This is preparation for #155028, offloading all the changes that PR used
to introduce which don't depend on any new helpers.
This commit is contained in:
Matheus Izvekov 2025-08-25 20:18:56 -03:00 committed by GitHub
parent 1ba8b36fef
commit dc8596d548
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
100 changed files with 609 additions and 941 deletions

View File

@ -901,9 +901,8 @@ parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir,
if (!D->isThisDeclarationADefinition())
return;
for (const CXXBaseSpecifier &B : D->bases()) {
if (const RecordType *Ty = B.getType()->getAs<RecordType>()) {
if (const CXXRecordDecl *Base = cast_or_null<CXXRecordDecl>(
Ty->getOriginalDecl()->getDefinition())) {
if (const auto *Base = B.getType()->getAsCXXRecordDecl()) {
if (Base->isCompleteDefinition()) {
// Initialized without USR and name, this will be set in the following
// if-else stmt.
BaseRecordInfo BI(

View File

@ -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();

View File

@ -90,9 +90,8 @@ void SlicingCheck::diagnoseSlicedOverriddenMethods(
}
// Recursively process bases.
for (const auto &Base : DerivedDecl.bases()) {
if (const auto *BaseRecordType = Base.getType()->getAs<RecordType>()) {
if (const auto *BaseRecord = cast_or_null<CXXRecordDecl>(
BaseRecordType->getOriginalDecl()->getDefinition()))
if (const auto *BaseRecord = Base.getType()->getAsCXXRecordDecl()) {
if (BaseRecord->isCompleteDefinition())
diagnoseSlicedOverriddenMethods(Call, *BaseRecord, BaseDecl);
}
}

View File

@ -71,13 +71,10 @@ bool MultipleInheritanceCheck::isInterface(const CXXRecordDecl *Node) {
for (const auto &I : Node->bases()) {
if (I.isVirtual())
continue;
const auto *Ty = I.getType()->getAs<RecordType>();
if (!Ty)
const auto *Base = I.getType()->getAsCXXRecordDecl();
if (!Base)
continue;
const RecordDecl *D = Ty->getOriginalDecl()->getDefinition();
if (!D)
continue;
const auto *Base = cast<CXXRecordDecl>(D);
assert(Base->isCompleteDefinition());
if (!isInterface(Base)) {
addNodeToInterfaceMap(Node, false);
return false;
@ -103,11 +100,10 @@ void MultipleInheritanceCheck::check(const MatchFinder::MatchResult &Result) {
for (const auto &I : D->bases()) {
if (I.isVirtual())
continue;
const auto *Ty = I.getType()->getAs<RecordType>();
if (!Ty)
const auto *Base = I.getType()->getAsCXXRecordDecl();
if (!Base)
continue;
const auto *Base =
cast<CXXRecordDecl>(Ty->getOriginalDecl()->getDefinition());
assert(Base->isCompleteDefinition());
if (!isInterface(Base))
NumConcrete++;
}
@ -115,11 +111,10 @@ void MultipleInheritanceCheck::check(const MatchFinder::MatchResult &Result) {
// Check virtual bases to see if there is more than one concrete
// non-virtual base.
for (const auto &V : D->vbases()) {
const auto *Ty = V.getType()->getAs<RecordType>();
if (!Ty)
const auto *Base = V.getType()->getAsCXXRecordDecl();
if (!Base)
continue;
const auto *Base =
cast<CXXRecordDecl>(Ty->getOriginalDecl()->getDefinition());
assert(Base->isCompleteDefinition());
if (!isInterface(Base))
NumConcrete++;
}

View File

@ -119,9 +119,8 @@ bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context) {
if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
return true;
if (const auto *RT = CanonicalType->getAs<RecordType>()) {
return recordIsTriviallyDefaultConstructible(
*RT->getOriginalDecl()->getDefinitionOrSelf(), Context);
if (const auto *RD = CanonicalType->getAsRecordDecl()) {
return recordIsTriviallyDefaultConstructible(*RD, Context);
}
// No other types can match.

View File

@ -193,7 +193,7 @@ public:
auto elemTy = origTy;
unsigned pathLength = asImpl().readUInt32();
for (unsigned i = 0; i < pathLength; ++i) {
if (elemTy->template getAs<RecordType>()) {
if (elemTy->isRecordType()) {
unsigned int_ = asImpl().readUInt32();
Decl *decl = asImpl().template readDeclAs<Decl>();
if (auto *recordDecl = dyn_cast<CXXRecordDecl>(decl))

View File

@ -176,7 +176,7 @@ public:
asImpl().writeUInt32(path.size());
auto &ctx = ((BasicWriterBase<Impl> *)this)->getASTContext();
for (auto elem : path) {
if (elemTy->getAs<RecordType>()) {
if (elemTy->isRecordType()) {
asImpl().writeUInt32(elem.getAsBaseOrMember().getInt());
const Decl *baseOrMember = elem.getAsBaseOrMember().getPointer();
if (const auto *recordDecl = dyn_cast<CXXRecordDecl>(baseOrMember)) {

View File

@ -3825,7 +3825,9 @@ public:
void setEnumType(TypeSourceInfo *TSI) { EnumType = TSI; }
public:
EnumDecl *getEnumDecl() const { return cast<EnumDecl>(EnumType->getType()->getAsTagDecl()); }
EnumDecl *getEnumDecl() const {
return cast<clang::EnumType>(EnumType->getType())->getOriginalDecl();
}
static UsingEnumDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation UsingL, SourceLocation EnumL,

View File

@ -5404,7 +5404,7 @@ public:
/// 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.

View File

@ -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<TagType>())
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<ObjCInterfaceDecl>(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<RecordType>()) {
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<RecordType>()) {
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<int64_t>
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<MemberPointerType>())
return !ABI->getMemberPointerInfo(MPT).HasPadding;
if (Ty->isRecordType()) {
const RecordDecl *Record =
Ty->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
if (const auto *Record = Ty->getAsRecordDecl()) {
if (Record->isInvalidDecl())
return false;

View File

@ -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<EnumType>()->getOriginalDecl()->getIntegerType();
T1 = cast<EnumType>(T1)->getOriginalDecl()->getIntegerType();
assert(T2->isBuiltinType() && !T1.isNull()); // Sanity check
} else if (T2->getTypeClass() == Type::Enum) {
T2 = T2->getAs<EnumType>()->getOriginalDecl()->getIntegerType();
T2 = cast<EnumType>(T2)->getOriginalDecl()->getIntegerType();
assert(T1->isBuiltinType() && !T2.isNull()); // Sanity check
}
TC = Type::Builtin;

View File

@ -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<RecordType>();
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<RecordType>();
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<RecordType>();
if (!BaseRT)
const auto *BaseRD = CurrentType->getAsCXXRecordDecl();
if (!BaseRD)
return false;
// Add the offset to the base.
Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(
BaseRT->getOriginalDecl()->getDefinitionOrSelf()));
Result += RL.getBaseClassOffset(BaseRD);
break;
}
case OffsetOfNode::Identifier:

View File

@ -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<RecordType>();
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<RecordType>()) {
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);

View File

@ -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<RecordType>()) {
const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (auto *RD = T->getAsCXXRecordDecl())
return BaseMap.lookup(RD);
}
return nullptr;
}

View File

@ -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<RecordType>();
if (!Ty)
const auto *Base = I.getType()->getAsCXXRecordDecl();
if (!Base || !(Base->isBeingDefined() || Base->isCompleteDefinition()))
return false;
CXXRecordDecl *Base = cast_if_present<CXXRecordDecl>(
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<TemplateSpecializationType>();
if (!TST) {
if (auto *RT = BaseSpec.getType()->getAs<RecordType>())
BaseRecord = cast<CXXRecordDecl>(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<RecordType>())
HidingClass = cast<CXXRecordDecl>(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<CXXRecordDecl>(RD->getCanonicalDecl())];
for (const auto &Base : RD->bases()) {
if (const RecordType *RT = Base.getType()->getAs<RecordType>()) {
const CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
if (const auto *BaseDecl = Base.getType()->getAsCXXRecordDecl()) {
if (!BaseDecl->isPolymorphic())
continue;

View File

@ -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<RecordType>();
if (!Ty ||
!Ty->getOriginalDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember())
auto *D = getType()->getAsRecordDecl();
if (!D || !D->hasFlexibleArrayMember())
return false;
auto *List = dyn_cast<InitListExpr>(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<RecordType>();
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<InitListExpr>(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<RecordType>();
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<RecordType>())
if (const FieldDecl *NamedDataMember = RT->getOriginalDecl()
->getDefinitionOrSelf()
->findFirstNamedDataMember())
if (const auto *RD = I->getType()->getAsRecordDecl())
if (const FieldDecl *NamedDataMember = RD->findFirstNamedDataMember())
return NamedDataMember;
}

View File

@ -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<RecordType>()) {
auto *FieldRec = cast<CXXRecordDecl>(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<RecordType>();
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<CXXRecordDecl>(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<RecordType>();
if (!RT) continue;
const auto *Base = I.getType()->getAsCXXRecordDecl();
if (!Base)
continue;
CollectVisibleConversions(
Context,
cast<CXXRecordDecl>(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<RecordType>();
if (!RT)
const auto *Base = I.getType()->getAsCXXRecordDecl();
if (!Base)
continue;
const auto *Base =
cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
if (CXXMethodDecl *D = this->getCorrespondingMethodInClass(Base))
AddFinalOverrider(D);
}

View File

@ -730,15 +730,15 @@ void TemplateTypeParmDecl::setDefaultArgument(
}
unsigned TemplateTypeParmDecl::getDepth() const {
return getTypeForDecl()->castAs<TemplateTypeParmType>()->getDepth();
return dyn_cast<TemplateTypeParmType>(getTypeForDecl())->getDepth();
}
unsigned TemplateTypeParmDecl::getIndex() const {
return getTypeForDecl()->castAs<TemplateTypeParmType>()->getIndex();
return dyn_cast<TemplateTypeParmType>(getTypeForDecl())->getIndex();
}
bool TemplateTypeParmDecl::isParameterPack() const {
return getTypeForDecl()->castAs<TemplateTypeParmType>()->isParameterPack();
return dyn_cast<TemplateTypeParmType>(getTypeForDecl())->isParameterPack();
}
void TemplateTypeParmDecl::setTypeConstraint(

View File

@ -15407,10 +15407,9 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) {
case OffsetOfNode::Field: {
FieldDecl *MemberDecl = ON.getField();
const RecordType *RT = CurrentType->getAs<RecordType>();
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<RecordType>();
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<RecordType>();
if (!BaseRT)
const auto *BaseRD = CurrentType->getAsCXXRecordDecl();
if (!BaseRD)
return Error(OOE);
// Add the offset to the base.
Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(
BaseRT->getOriginalDecl()->getDefinitionOrSelf()));
Result += RL.getBaseClassOffset(BaseRD);
break;
}
}

View File

@ -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;

View File

@ -6997,8 +6997,8 @@ static bool hasMangledSubstitutionQualifiers(QualType T) {
bool CXXNameMangler::mangleSubstitution(QualType T) {
if (!hasMangledSubstitutionQualifiers(T)) {
if (const RecordType *RT = T->getAs<RecordType>())
return mangleSubstitution(RT->getOriginalDecl()->getDefinitionOrSelf());
if (const auto *RD = T->getAsCXXRecordDecl())
return mangleSubstitution(RD);
}
uintptr_t TypePtr = reinterpret_cast<uintptr_t>(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<RecordType>()) {
addSubstitution(RT->getOriginalDecl()->getDefinitionOrSelf());
if (const auto *RD = T->getAsCXXRecordDecl()) {
addSubstitution(RD);
return;
}
}

View File

@ -204,15 +204,13 @@ void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
// Check the fields.
for (const FieldDecl *FD : Class->fields()) {
const RecordType *RT =
Context.getBaseElementType(FD->getType())->getAs<RecordType>();
// 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<RecordType>();
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<RecordType>();
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<RecordType>()) {
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;

View File

@ -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<RecordType>()->getOriginalDecl();
else if (ty->isEnumeralType())
ND = ty->castAs<EnumType>()->getOriginalDecl();
if (const auto *TT = ty->getAs<TagType>())
ND = TT->getOriginalDecl();
else if (ty->getTypeClass() == Type::Typedef)
ND = ty->castAs<TypedefType>()->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<RecordType>(CanonicalType)) {
if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(
Record->getOriginalDecl()->getDefinitionOrSelf()))
if (const auto *ClassDecl =
dyn_cast<CXXRecordDecl>(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<TagType>(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<CXXRecordDecl>(
cast<RecordType>(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<RecordType>()) {
if (const auto *ClassDecl =
dyn_cast<CXXRecordDecl>(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<RecordType>(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<RecordType>()) {
if (const auto *ClassDecl =
dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) {
if (IsCopyConstructible) {
if (const auto *RD = CanonicalType->getAsRecordDecl()) {
if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(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<RecordType>())
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<RecordType>())
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<RecordType>()) {
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<CXXRecordDecl>(RT->getOriginalDecl()))
return ClassDecl->getDefinitionOrSelf()->isLiteral();
if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(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<RecordType>()) {
if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getOriginalDecl()))
if (!ClassDecl->getDefinitionOrSelf()->isStandardLayout())
return false;
if (const auto *RD = BaseTy->getAsRecordDecl()) {
if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(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<RecordType>()) {
if (const auto *ClassDecl =
dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) {
ClassDecl = ClassDecl->getDefinitionOrSelf();
if (const auto *RD = BaseTy->getAsRecordDecl()) {
if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(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<RecordType>()) {
const RecordDecl *RD = RT->getOriginalDecl();
if (const auto *RD = type->getBaseElementTypeUnsafe()->getAsRecordDecl()) {
if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(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;
}
}

View File

@ -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<RValueReferenceType>()) {
if (!RefType->getPointeeType().getQualifiers() &&
RefType->getPointeeType()->getAs<TemplateTypeParmType>()) {
isa<TemplateTypeParmType>(
RefType->getPointeeType().getCanonicalType())) {
FunctionParmMutationAnalyzer *Analyzer =
FunctionParmMutationAnalyzer::getFunctionParmMutationAnalyzer(
*Func, Context, Memorized);

View File

@ -83,13 +83,11 @@ static std::pair<StringRef, bool> 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<RecordType>()) {
if (const auto *RD = RT->getOriginalDecl())
return classifyCapability(*RD->getDefinitionOrSelf());
} else if (const auto *TT = QT->getAs<TypedefType>()) {
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<TypedefType>())
return classifyCapability(*TT->getDecl());
if (QT->isPointerOrReferenceType())
return classifyCapability(QT->getPointeeType());
return ClassifyCapabilityFallback;

View File

@ -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<clang::RecordType>()) {
if (const auto *classDecl =
e->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
classDecl && !classDecl->hasTrivialDestructor())
// Get the destructor for the reference temporary.
if (const auto *classDecl = dyn_cast<CXXRecordDecl>(
rt->getOriginalDecl()->getDefinitionOrSelf())) {
if (!classDecl->hasTrivialDestructor())
referenceTemporaryDtor =
classDecl->getDefinitionOrSelf()->getDestructor();
}
}
referenceTemporaryDtor = classDecl->getDestructor();
if (!referenceTemporaryDtor)
return;

View File

@ -949,7 +949,7 @@ mlir::Value CIRGenModule::emitNullConstant(QualType t, mlir::Location loc) {
errorNYI("CIRGenModule::emitNullConstant ConstantArrayType");
}
if (t->getAs<RecordType>())
if (t->isRecordType())
errorNYI("CIRGenModule::emitNullConstant RecordType");
assert(t->isMemberDataPointerType() &&

View File

@ -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<RecordType>()) {
if (const auto *classDecl = dyn_cast<CXXRecordDecl>(
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<RecordType>()) {
if (cast<CXXRecordDecl>(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())) {

View File

@ -1077,8 +1077,7 @@ static bool isVarDeclStrongDefinition(const ASTContext &astContext,
if (astContext.isAlignmentRequired(varType))
return true;
if (const auto *rt = varType->getAs<RecordType>()) {
const RecordDecl *rd = rt->getOriginalDecl()->getDefinitionOrSelf();
if (const auto *rd = varType->getAsRecordDecl()) {
for (const FieldDecl *fd : rd->fields()) {
if (fd->isBitField())
continue;

View File

@ -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>();
mlir::ModuleOp mod = builder.getBlock()
->getParent()
->template getParentOfType<mlir::ModuleOp>();
std::string recipeName =
getRecipeName<RecipeTy>(varRef->getSourceRange(), baseType);

View File

@ -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<RecordType>())
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<RecordType>()) {
const RecordDecl *rd = rt->getOriginalDecl()->getDefinitionOrSelf();
if (const auto *rd = t->getAsRecordDecl())
return isZeroInitializable(rd);
}
if (t->getAs<MemberPointerType>()) {
cgm.errorNYI(SourceLocation(), "isZeroInitializable for MemberPointerType",

View File

@ -6,12 +6,10 @@ using namespace clang::CIRGen;
bool clang::CIRGen::isEmptyRecordForLayout(const ASTContext &context,
QualType t) {
const RecordType *rt = t->getAs<RecordType>();
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<CXXRecordDecl>(rd)) {
if (cxxrd->isDynamicClass())

View File

@ -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<RecordType>()) {
const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
} else if (const auto *RD = Ty->getAsRecordDecl()) {
if (RD->hasFlexibleArrayMember())
return false;

View File

@ -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<RecordType>()) {
const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (!isa<CXXRecordDecl>(RD) && !RD->canPassInRegisters()) {
FI.getReturnInfo() = Info.getNaturalAlignIndirect(
Ty, Info.getDataLayout().getAllocaAddrSpace());
return true;
}
if (const auto *RD = Ty->getAsRecordDecl();
RD && !isa<CXXRecordDecl>(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<RecordType>();
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<RecordType>();
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<CXXRecordDecl>(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<RecordType>();
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<RecordType>();
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<CXXRecordDecl>(RD))

View File

@ -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<RecordType>();
const auto *record = type->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
// Only records can be unsafe.
if (!recordType) return true;
const auto *record =
cast<CXXRecordDecl>(recordType->getOriginalDecl())->getDefinitionOrSelf();
if (!record)
return true;
// Maintain semantics for classes with non-trivial dtors or copy ctors.
if (!record->hasTrivialDestructor()) return false;

View File

@ -997,9 +997,8 @@ static const FieldDecl *FindFlexibleArrayMemberField(CodeGenFunction &CGF,
/*IgnoreTemplateOrMacroSubstitution=*/true))
return FD;
if (auto RT = FD->getType()->getAs<RecordType>())
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<RecordType>()) {
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;
}

View File

@ -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<RecordType>() && T->isIncompleteType())
return true;
return false;
return T->isRecordType() && T->isIncompleteType();
}
bool CGCXXABI::isEmittedWithConstantInitializer(

View File

@ -1005,10 +1005,9 @@ getTypeExpansion(QualType Ty, const ASTContext &Context) {
return std::make_unique<ConstantArrayExpansion>(AT->getElementType(),
AT->getZExtSize());
}
if (const RecordType *RT = Ty->getAs<RecordType>()) {
if (const auto *RD = Ty->getAsRecordDecl()) {
SmallVector<const CXXBaseSpecifier *, 1> Bases;
SmallVector<const FieldDecl *, 1> Fields;
const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
assert(!RD->hasFlexibleArrayMember() &&
"Cannot expand structure with flexible array.");
if (RD->isUnion()) {

View File

@ -1408,13 +1408,10 @@ FieldHasTrivialDestructorBody(ASTContext &Context,
{
QualType FieldBaseElementType = Context.getBaseElementType(Field->getType());
const RecordType *RT = FieldBaseElementType->getAs<RecordType>();
if (!RT)
auto *FieldClassDecl = FieldBaseElementType->getAsCXXRecordDecl();
if (!FieldClassDecl)
return true;
auto *FieldClassDecl =
cast<CXXRecordDecl>(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<RecordType>();
if (!ClassTy)
const auto *ClassDecl = T->getAsCXXRecordDecl();
if (!ClassDecl)
return;
const auto *ClassDecl =
cast<CXXRecordDecl>(ClassTy->getOriginalDecl())->getDefinitionOrSelf();
if (!ClassDecl->isCompleteDefinition() || !ClassDecl->isDynamicClass())
return;

View File

@ -1568,10 +1568,9 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
ReturnValue.getElementType(), ReturnValue.getAlignment());
address = MaybeCastStackAddressSpace(AllocaAddr, Ty.getAddressSpace());
if (const RecordType *RecordTy = Ty->getAs<RecordType>()) {
const auto *RD = RecordTy->getOriginalDecl()->getDefinitionOrSelf();
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
if ((CXXRD && !CXXRD->hasTrivialDestructor()) ||
if (const auto *RD = Ty->getAsRecordDecl()) {
if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(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

View File

@ -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<RecordType>()) {
if (const auto *ClassDecl =
E->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
ClassDecl && !ClassDecl->hasTrivialDestructor())
// Get the destructor for the reference temporary.
if (auto *ClassDecl = dyn_cast<CXXRecordDecl>(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<EnumType>();
bool NeedsEnumCheck = HasEnumCheck && Ty->isEnumeralType();
if (!NeedsBoolCheck && !NeedsEnumCheck)
return false;

View File

@ -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<RecordType>();
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<CXXRecordDecl>(Record) &&
(cast<CXXRecordDecl>(Record)->hasNonTrivialCopyConstructor() ||
!cast<CXXRecordDecl>(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<RecordType>()) {
auto *Record =
cast<CXXRecordDecl>(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<RecordType>()) {
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<RecordType>()) {
if (RecordTy->getOriginalDecl()
->getDefinitionOrSelf()
->hasObjectMember()) {
if (const auto *Record = BaseType->getAsRecordDecl()) {
if (Record->hasObjectMember()) {
CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr,
SizeVal);
return;

View File

@ -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<RecordType>()) {
auto *RD =
cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
if (const auto *RD = ElementType->getAsCXXRecordDecl()) {
if (RD->hasDefinition() && !RD->hasTrivialDestructor()) {
Dtor = RD->getDestructor();

View File

@ -1511,10 +1511,8 @@ public:
llvm::Type *ValTy = CGM.getTypes().ConvertType(destType);
bool HasFlexibleArray = false;
if (const auto *RT = destType->getAs<RecordType>())
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<RecordType>())
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!");

View File

@ -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<RecordType>())
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

View File

@ -3353,9 +3353,8 @@ static bool hasWeakMember(QualType type) {
return true;
}
if (auto recType = type->getAs<RecordType>()) {
for (auto *field :
recType->getOriginalDecl()->getDefinitionOrSelf()->fields()) {
if (auto *RD = type->getAsRecordDecl()) {
for (auto *field : RD->fields()) {
if (hasWeakMember(field->getType()))
return true;
}

View File

@ -439,10 +439,8 @@ void CGObjCRuntime::destroyCalleeDestroyedArguments(CodeGenFunction &CGF,
CGF.EmitARCRelease(RV.getScalarVal(), ARCImpreciseLifetime);
} else {
QualType QT = param->getType();
auto *RT = QT->getAs<RecordType>();
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) {

View File

@ -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<RecordType>()) {
if (cast<CXXRecordDecl>(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);

View File

@ -2979,10 +2979,8 @@ public:
/// hasVolatileMember - returns true if aggregate type has a volatile
/// member.
bool hasVolatileMember(QualType T) {
if (const RecordType *RT = T->getAs<RecordType>()) {
const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (const auto *RD = T->getAsRecordDecl())
return RD->hasVolatileMember();
}
return false;
}

View File

@ -6075,8 +6075,7 @@ static bool isVarDeclStrongDefinition(const ASTContext &Context,
if (Context.isAlignmentRequired(VarType))
return true;
if (const auto *RT = VarType->getAs<RecordType>()) {
const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (const auto *RD = VarType->getAsRecordDecl()) {
for (const FieldDecl *FD : RD->fields()) {
if (FD->isBitField())
continue;

View File

@ -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<RecordType>()) {
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;

View File

@ -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<RecordType>())
ConvertRecordDeclType(RT->getOriginalDecl()->getDefinitionOrSelf());
if (const auto *RD = FT->getReturnType()->getAsRecordDecl())
ConvertRecordDeclType(RD);
if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT))
for (unsigned i = 0, e = FPT->getNumParams(); i != e; i++)
if (const RecordType *RT = FPT->getParamType(i)->getAs<RecordType>())
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<RecordType>()) {
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<MemberPointerType>())

View File

@ -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<RecordType>()) {
CXXRecordDecl *Record =
cast<CXXRecordDecl>(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());
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);
}
CXXDestructorDecl *DtorD = Record->getDestructor();
Dtor = CGM.getAddrOfCXXStructor(GlobalDecl(DtorD, Dtor_Complete));
Dtor = CGM.getFunctionPointer(Dtor, DtorTy);
}
if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);

View File

@ -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<RecordType>();
if (!RT)
const auto *RD = Ty->getAsRecordDecl();
if (!RD)
return false;
const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
for (const auto &I : CXXRD->bases())
if (!Self(Self, I.getType()))

View File

@ -95,8 +95,7 @@ unsigned AMDGPUABIInfo::numRegsForType(QualType Ty) const {
return EltNumRegs * VT->getNumElements();
}
if (const RecordType *RT = Ty->getAs<RecordType>()) {
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<RecordType>()) {
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<RecordType>()) {
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);

View File

@ -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<RecordType>()) {
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<CXXRecordDecl>(RD))
if (llvm::any_of(CXXRD->bases(), [this](const CXXBaseSpecifier &B) {

View File

@ -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)));

View File

@ -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<RecordType>();
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<CXXRecordDecl>(RD))

View File

@ -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<RecordType>()->getOriginalDecl()->getDefinitionOrSelf()
: nullptr;
const RecordDecl *RDecl = Ty->getAsRecordDecl();
bool EmitDiagnostic = UserSpecifiedTOC && GV->hasExternalLinkage();
auto reportUnsupportedWarning = [&](bool ShouldEmitWarning, StringRef Msg) {

View File

@ -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<RecordType>()) {
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<RecordType>()) {
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<RecordType>()) {
auto *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (const auto *RD = TypeOperand->getAsRecordDecl()) {
assert(RD->isCompleteDefinition() &&
"Type completion should have been required in Sema");

View File

@ -452,10 +452,9 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
/*ByVal=*/false);
// Handle small structures.
if (const RecordType *RT = Ty->getAs<RecordType>()) {
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<RecordType>()) {
const RecordDecl *RD = RecordTy->getOriginalDecl()->getDefinitionOrSelf();
if (const auto *RD = Ty->getAsRecordDecl()) {
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
if (CXXRD->hasDefinition())
for (const auto &I : CXXRD->bases())

View File

@ -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<RecordType>();
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<RecordType>();
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<CXXRecordDecl>(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<RecordType>()) {
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<RecordType>()) {
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.

View File

@ -1011,7 +1011,7 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg,
if ((MK == NSAPI::NSNumberWithInteger ||
MK == NSAPI::NSNumberWithUnsignedInteger) &&
!isTruncated) {
if (OrigTy->getAs<EnumType>() || isEnumConstant(OrigArg))
if (OrigTy->isEnumeralType() || isEnumConstant(OrigArg))
break;
if ((MK==NSAPI::NSNumberWithInteger) == OrigTy->isSignedIntegerType() &&
OrigTySize >= Ctx.getTypeSize(Ctx.IntTy))

View File

@ -3733,15 +3733,7 @@ void RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDec
auto *IDecl = dyn_cast<ObjCContainerDecl>(fieldDecl->getDeclContext());
TagDecl *TD = nullptr;
if (Type->isRecordType()) {
TD = Type->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
}
else if (Type->isEnumeralType()) {
TD = Type->castAs<EnumType>()->getOriginalDecl()->getDefinitionOrSelf();
}
if (TD) {
if (auto *TD = Type->getAsTagDecl()) {
if (GlobalDefinedTags.count(TD))
return;

View File

@ -147,15 +147,12 @@ Value::Value(const Interpreter *In, void *Ty) : Interp(In), OpaqueType(Ty) {
} while (ArrTy);
ElementsSize = static_cast<size_t>(ArrSize.getZExtValue());
}
if (const auto *RT = DtorTy->getAs<RecordType>()) {
if (CXXRecordDecl *CXXRD =
llvm::dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) {
if (llvm::Expected<llvm::orc::ExecutorAddr> Addr =
Interp.CompileDtorCall(CXXRD->getDefinitionOrSelf()))
DtorF = reinterpret_cast<void *>(Addr->getValue());
else
llvm::logAllUnhandledErrors(Addr.takeError(), llvm::errs());
}
if (auto *CXXRD = DtorTy->getAsCXXRecordDecl()) {
if (llvm::Expected<llvm::orc::ExecutorAddr> Addr =
Interp.CompileDtorCall(CXXRD))
DtorF = reinterpret_cast<void *>(Addr->getValue());
else
llvm::logAllUnhandledErrors(Addr.takeError(), llvm::errs());
}
size_t AllocSize =

View File

@ -1882,23 +1882,21 @@ public:
// Visit the dtors of all members
for (const FieldDecl *FD : RD->fields()) {
QualType FT = FD->getType();
if (const auto *RT = FT->getAs<RecordType>())
if (const auto *ClassDecl =
dyn_cast<CXXRecordDecl>(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<RecordType>())
if (const auto *BaseDecl =
dyn_cast<CXXRecordDecl>(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 @@ public:
if (VD->isThisDeclarationADefinition() &&
VD->needsDestruction(S.Context)) {
QualType VT = VD->getType();
if (const auto *RT = VT->getAs<RecordType>())
if (const auto *ClassDecl =
dyn_cast<CXXRecordDecl>(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);

View File

@ -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<RecordType>())
return MatchesFriend(
S, EC,
cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf());
if (const auto *RD = Friend->getAsCXXRecordDecl())
return MatchesFriend(S, EC, RD);
// TODO: we can do better than this
if (Friend->isDependentType())

View File

@ -421,13 +421,10 @@ bool SemaCUDA::inferTargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl,
}
for (const auto *B : Bases) {
const RecordType *BaseType = B->getType()->getAs<RecordType>();
if (!BaseType) {
auto *BaseClassDecl = B->getType()->getAsCXXRecordDecl();
if (!BaseClassDecl)
continue;
}
CXXRecordDecl *BaseClassDecl =
cast<CXXRecordDecl>(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<RecordType>();
if (!FieldType) {
auto *FieldRecDecl =
getASTContext().getBaseElementType(F->getType())->getAsCXXRecordDecl();
if (!FieldRecDecl)
continue;
}
CXXRecordDecl *FieldRecDecl =
cast<CXXRecordDecl>(FieldType->getOriginalDecl())
->getDefinitionOrSelf();
Sema::SpecialMemberOverloadResult SMOR =
SemaRef.LookupSpecialMember(FieldRecDecl, CSM,
/* ConstArg */ ConstRHS && !F->isMutable(),

View File

@ -595,13 +595,11 @@ static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType,
DifferentPtrness--;
}
if (!DifferentPtrness) {
auto RecFrom = From->getAs<RecordType>();
auto RecTo = To->getAs<RecordType>();
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<EnumType>()) {
if (const EnumType *Enum = dyn_cast<EnumType>(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<PointerType>())
if (auto DestPointer = DestType->getAs<PointerType>())
if (SrcPointer->getPointeeType()->getAs<RecordType>() &&
DestPointer->getPointeeType()->getAs<RecordType>())
msg = diag::err_bad_cxx_cast_unrelated_class;
if (const auto *SrcPointer = SrcType->getAs<PointerType>())
if (const auto *DestPointer = DestType->getAs<PointerType>())
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)) {

View File

@ -7891,16 +7891,10 @@ bool DecomposePrintfHandler::HandlePrintfSpecifier(
template<typename MemberKind>
static llvm::SmallPtrSet<MemberKind*, 1>
CXXRecordMembersNamed(StringRef Name, Sema &S, QualType Ty) {
const RecordType *RT = Ty->getAs<RecordType>();
auto *RD = Ty->getAsCXXRecordDecl();
llvm::SmallPtrSet<MemberKind*, 1> Results;
if (!RT)
return Results;
CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(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<RecordType>()) {
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,

View File

@ -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<RecordDecl>(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<RecordDecl>(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<RecordType>()) {
CXXRecordDecl *CXXRecord =
cast<CXXRecordDecl>(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<RecordType>())
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<RecordType>()) {
CXXRecordDecl *RDecl = cast<CXXRecordDecl>(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<RecordType>()) {
CXXRecordDecl *RDecl =
cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
if (RDecl->getDefinition()) {
// We check for copy constructors before constructors
// because otherwise we'll never get complaints about
// copy constructors.
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;
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<UnavailableAttr>())
FD->addAttr(UnavailableAttr::CreateImplicit(Context, "",
UnavailableAttr::IR_ARCFieldWithOwnership, Loc));
return false;
}
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<UnavailableAttr>())
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<RecordType>()) {
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<RecordType>()) {
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<RecordType>()
->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<RecordType>()) {
if (RT->getOriginalDecl()
->getDefinitionOrSelf()
->getArgPassingRestrictions() ==
if (const auto *RD = FT->getAsRecordDecl()) {
if (RD->getArgPassingRestrictions() ==
RecordArgPassingKind::CanNeverPassInRegs)
Record->setArgPassingRestrictions(
RecordArgPassingKind::CanNeverPassInRegs);

View File

@ -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<RecordType>()) {
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<RecordType>())
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<PointerType>())
return PT->getPointeeType()->getAs<RecordType>();
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<CapabilityAttr>(
RT->getOriginalDecl()->getDefinitionOrSelf());
return checkRecordDeclForAttr<CapabilityAttr>(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<ScopedLockableAttr>(
RT->getOriginalDecl()->getDefinitionOrSelf());
return checkRecordDeclForAttr<ScopedLockableAttr>(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<FunctionDecl>(D);
const auto *IL = dyn_cast<IntegerLiteral>(ArgExp);
if(FD && IL) {
@ -3639,7 +3636,7 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
QualType T = cast<VarDecl>(D)->getType();
if (S.Context.getAsArrayType(T))
T = S.Context.getBaseElementType(T);
if (!T->getAs<RecordType>()) {
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<TypedefNameDecl>(D);
if (TD && TD->getUnderlyingType()->isUnionType())
RD = TD->getUnderlyingType()
->getAsUnionType()
->getOriginalDecl()
->getDefinitionOrSelf();
RD = TD->getUnderlyingType()->getAsRecordDecl();
else
RD = dyn_cast<RecordDecl>(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<EnumDecl>(D) || OldElemTy->getAs<EnumType>()) &&
if ((isa<EnumDecl>(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<EnumType>();
OldElemTy->isEnumeralType();
if (!OldElemTy->getAs<BuiltinType>() && !OldElemTy->isComplexType() &&
!IntegralOrAnyEnumType)

View File

@ -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<RecordType>()) {
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<RecordType>()) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(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<RecordType>();
if (!BaseType)
auto *BaseClassDecl = B.getType()->getAsCXXRecordDecl();
if (!BaseClassDecl)
continue;
CXXRecordDecl *BaseClassDecl =
cast<CXXRecordDecl>(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<RecordType>();
if (!RT)
auto *BaseClass = Base->getType()->getAsCXXRecordDecl();
if (!BaseClass)
return false;
auto *BaseClass =
cast<CXXRecordDecl>(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<RecordType>()) {
visitClassSubobject(
cast<CXXRecordDecl>(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<RecordType>()
->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<RecordType>()) {
CXXRecordDecl *ClassDecl =
cast<CXXRecordDecl>(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<RecordType>() && 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<RecordType>() && 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<CXXRecordDecl>(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<RecordType>()) {
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<RecordType>()) {
if (!RT->getOriginalDecl()->isEntityBeingDefined() &&
if (const auto *RD = NewClassTy->getAsCXXRecordDecl()) {
if (!RD->isBeingDefined() &&
RequireCompleteType(New->getLocation(), NewClassTy,
diag::err_covariant_return_incomplete,
New->getDeclName()))

View File

@ -3848,10 +3848,8 @@ SemaObjC::ObjCContainerKind SemaObjC::getObjCContainerKind() const {
static bool IsVariableSizedType(QualType T) {
if (T->isIncompleteArrayType())
return true;
const auto *RecordTy = T->getAs<RecordType>();
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<RecordType>()) {
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<RecordType>()) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getOriginalDecl())
->getDefinitionOrSelf();
if (auto *RD = Context.getBaseElementType(Field->getType())
->getAsCXXRecordDecl()) {
if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(RD)) {
SemaRef.MarkFunctionReferenced(Field->getLocation(), Destructor);
SemaRef.CheckDestructorAccess(

View File

@ -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<RecordType>()
->getOriginalDecl()
->isEntityBeingDefined()) &&
if (auto *RD = PointeeT->getAsRecordDecl();
!(RD && RD->isBeingDefined()) &&
RequireCompleteType(Range.getBegin(), PointeeT, DiagID, Kind, Range))
return ReturnValueOnError;

View File

@ -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<RecordType>()) { // C99 6.5.15p3
if (const RecordType *RHSRT = RHSTy->getAs<RecordType>())
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<RecordType>();
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<VarDecl>(Cap.getVariable());
Expr *CopyExpr = nullptr;
if (getLangOpts().CPlusPlus && Cap.isCopyCapture()) {
if (const RecordType *Record =
Cap.getCaptureType()->getAs<RecordType>()) {
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<RecordType>()) {
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<BlocksAttr>();
// 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<RecordType>())
if (E->getType().isVolatileQualified() || E->getType()->isRecordType())
return E;
ExprResult Result =

View File

@ -543,7 +543,7 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
QualType T
= Context.getUnqualifiedArrayType(Operand->getType().getNonReferenceType(),
Quals);
if (T->getAs<RecordType>() &&
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<RecordType>()) {
CXXRecordDecl *RecordD = cast<CXXRecordDecl>(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<RecordType>())
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<RecordType>())
PointeeRD =
cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
PointeeRD = PointeeElem->getAsCXXRecordDecl();
}
}

View File

@ -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<RecordType>()) {
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<ConstantArrayType>(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)
@ -3211,10 +3209,7 @@ static void BuildFlattenedTypeList(QualType BaseTy,
List.insert(List.end(), VT->getNumElements(), VT->getElementType());
continue;
}
if (const auto *RT = dyn_cast<RecordType>(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();

View File

@ -921,8 +921,7 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
if (ILE->isTransparent())
return;
if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
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<RecordType>()) {
if (CXXRecordDecl *ClassDecl =
dyn_cast<CXXRecordDecl>(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 (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());
// -- 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;
// 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<RecordType>()) {
bool IsUnion = RT->isUnionType();
const auto *RD =
cast<CXXRecordDecl>(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<RecordType>()) {
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<RecordType>())
Class =
cast<CXXRecordDecl>(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<RecordType>();
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<CXXRecordDecl>(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<RecordType>()
<< 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<RecordType>())
if (const auto *Record = Entity.getType()->getAs<RecordType>())
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<RecordType>();
<< DestType << DestType->isRecordType();
}
break;
@ -10021,7 +10009,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
// dependent. e.g.
// using AliasFoo = Foo<bool>;
if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(
RT->getAsCXXRecordDecl()))
RT->getOriginalDecl()))
Template = CTSD->getSpecializedTemplate();
}
}

View File

@ -3114,17 +3114,15 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
// Visit the base classes.
for (const auto &Base : Class->bases()) {
const RecordType *BaseType = Base.getType()->getAs<RecordType>();
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<CXXRecordDecl>(BaseType->getOriginalDecl())
->getDefinitionOrSelf();
if (Result.addClassTransitive(BaseDecl)) {
// Find the associated namespace for this base class.
DeclContext *BaseCtx = BaseDecl->getDeclContext();
@ -4262,10 +4260,9 @@ private:
continue;
RD = TD->getTemplatedDecl();
} else {
const auto *Record = BaseType->getAs<RecordType>();
if (!Record)
RD = BaseType->getAsCXXRecordDecl();
if (!RD)
continue;
RD = Record->getOriginalDecl()->getDefinitionOrSelf();
}
// FIXME: It would be nice to be able to determine whether referencing

View File

@ -1320,10 +1320,8 @@ Decl *SemaObjC::ActOnPropertyImplDecl(
CompleteTypeErr = true;
}
if (!CompleteTypeErr) {
const RecordType *RecordTy = PropertyIvarType->getAs<RecordType>();
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

View File

@ -1058,13 +1058,12 @@ static bool shouldAddReversedEqEq(Sema &S, SourceLocation OpLoc,
if (isa<CXXMethodDecl>(EqFD)) {
// If F is a class member, search scope is class type of first operand.
QualType RHS = FirstOperand->getType();
auto *RHSRec = RHS->getAs<RecordType>();
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<RecordType>() && FromType->getAs<RecordType>() &&
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<RecordType>() &&
(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<RecordType>()) {
if (T1->isRecordType()) {
bool IsComplete = isCompleteType(OpLoc, T1);
CXXRecordDecl *T1RD =
cast<CXXRecordDecl>(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<RecordType>();
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<CXXRecordDecl>(TyRec->getOriginalDecl())->getDefinitionOrSelf();
cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getOriginalDecl())
->getDefinitionOrSelf();
for (NamedDecl *D : ClassDecl->getVisibleConversionFunctions()) {
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();

View File

@ -944,16 +944,15 @@ Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member,
/*FirstQualifierFoundInScope=*/nullptr, NameInfo, /*TemplateArgs=*/nullptr);
}
const RecordType *RT = T->getAs<RecordType>();
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.

View File

@ -129,9 +129,9 @@ static bool isErrorParameter(Sema &S, QualType QT) {
// Check for CFError**.
if (const auto *PT = Pointee->getAs<PointerType>())
if (const auto *RT = PT->getPointeeType()->getAs<RecordType>())
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<PointerType>()) {
if (const auto *RT = PtrTy->getPointeeType()->getAs<RecordType>()) {
if (S.ObjC().isCFError(
RT->getOriginalDecl()->getDefinitionOrSelf())) {
AnyErrorParams = true;
break;
}
if (auto *RD = PtrTy->getPointeeType()->getAsRecordDecl();
RD && S.ObjC().isCFError(RD)) {
AnyErrorParams = true;
break;
}
}
}

View File

@ -4087,7 +4087,7 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
// Check the tag kind
if (const RecordType *RT = Result->getAs<RecordType>()) {
RecordDecl *D = RT->getOriginalDecl()->getDefinitionOrSelf();
RecordDecl *D = RT->getOriginalDecl();
IdentifierInfo *Id = D->getIdentifier();
assert(Id && "templated class must have an identifier");

View File

@ -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<InjectedClassNameType>())
if (isa<InjectedClassNameType>(T.getCanonicalType()))
return true;
return false;

View File

@ -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<bool>;
if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(
RT->getAsCXXRecordDecl())) {
if (const auto *CTSD =
dyn_cast<ClassTemplateSpecializationDecl>(RT->getOriginalDecl())) {
Template = CTSD->getSpecializedTemplate();
AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();
}

View File

@ -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<CXXRecordDecl>(ParentDC)) {
if (auto *Spec = dyn_cast<CXXRecordDecl>(ParentDC)) {
if (!Spec->isDependentContext()) {
CanQualType T = Context.getCanonicalTagType(Spec);
const RecordType *Tag = T->getAs<RecordType>();
assert(Tag && "type of non-dependent record is not a RecordType");
auto *TagDecl =
cast<CXXRecordDecl>(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();
}
}

View File

@ -2115,12 +2115,10 @@ QualType Sema::BuildArrayType(QualType T, ArraySizeModifier ASM,
return QualType();
}
if (const RecordType *EltTy = T->getAs<RecordType>()) {
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<RecordType>()) {
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)) {

View File

@ -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<CXXRecordDecl>(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<RecordType>())
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<RecordType>())
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);

View File

@ -14369,9 +14369,9 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) {
Expr *Op = E->getExprOperand();
auto EvalCtx = Sema::ExpressionEvaluationContext::Unevaluated;
if (E->isGLValue())
if (auto *RecordT = Op->getType()->getAs<RecordType>())
if (cast<CXXRecordDecl>(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<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
if (E->isArray() && !E->getAllocatedType()->isDependentType()) {
QualType ElementType
= SemaRef.Context.getBaseElementType(E->getAllocatedType());
if (const RecordType *RecordT = ElementType->getAs<RecordType>()) {
CXXRecordDecl *Record = cast<CXXRecordDecl>(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<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) {
if (!E->getArgument()->isTypeDependent()) {
QualType Destroyed = SemaRef.Context.getBaseElementType(
E->getDestroyedType());
if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
CXXRecordDecl *Record =
cast<CXXRecordDecl>(DestroyedRec->getOriginalDecl())
->getDefinitionOrSelf();
if (auto *Record = Destroyed->getAsCXXRecordDecl())
SemaRef.MarkFunctionReferenced(E->getBeginLoc(),
SemaRef.LookupDestructor(Record));
}
}
return E;
@ -17671,13 +17664,11 @@ TreeTransform<Derived>::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<typename Derived>

View File

@ -70,12 +70,10 @@ public:
QualType DestroyedOrNull = E->getDestroyedType();
if (!DestroyedOrNull.isNull()) {
QualType Destroyed = S.Context.getBaseElementType(DestroyedOrNull);
if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
CXXRecordDecl *Record =
cast<CXXRecordDecl>(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);

View File

@ -258,7 +258,7 @@ public:
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 {

View File

@ -49,11 +49,10 @@ public:
/// of struct bar.
static bool evenFlexibleArraySize(ASTContext &Ctx, CharUnits RegionSize,
CharUnits TypeSize, QualType ToPointeeTy) {
const RecordType *RT = ToPointeeTy->getAs<RecordType>();
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;

View File

@ -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<RecordType>()) {
CXXRecordDecl *baseD = cast<CXXRecordDecl>(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<RecordType>()) {
const RecordDecl *RD = RT->getOriginalDecl()->getDefinition();
if (const auto *RD = T->getAsRecordDecl())
for (auto *I : RD->fields())
Visit(I);
}
FieldChain.pop_back();
}

View File

@ -118,12 +118,12 @@ public:
Elts = CArrTy->getZExtSize();
if (Elts == 0)
return;
const RecordType *RT = ArrTy->getElementType()->getAs<RecordType>();
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 {

View File

@ -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<EnumType>()) {
if (CondExpr->getType()->isEnumeralType()) {
if (SS->isAllEnumCasesCovered())
return;
}

View File

@ -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));
}

View File

@ -9189,7 +9189,7 @@ protected:
.getTypePtr();
ASSERT_TRUE(Ty);
EXPECT_FALSE(Ty->isCanonicalUnqualified());
const auto *InjTy = Ty->castAs<InjectedClassNameType>();
const auto *InjTy = dyn_cast<InjectedClassNameType>(Ty);
EXPECT_TRUE(InjTy);
for (const Decl *ReD : D->redecls()) {
if (ReD == D)
@ -9204,8 +9204,6 @@ protected:
EXPECT_FALSE(ReTy->isCanonicalUnqualified());
EXPECT_NE(ReTy, Ty);
EXPECT_TRUE(Ctx.hasSameType(ReTy, Ty));
const auto *ReInjTy = Ty->castAs<InjectedClassNameType>();
EXPECT_TRUE(ReInjTy);
}
}

View File

@ -531,8 +531,7 @@ TEST(RANDSTRUCT_TEST, AnonymousStructsAndUnionsRetainFieldOrder) {
for (const Decl *D : RD->decls())
if (const FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
if (const auto *Record = FD->getType()->getAs<RecordType>()) {
RD = Record->getOriginalDecl()->getDefinitionOrSelf();
if (const auto *RD = FD->getType()->getAsRecordDecl()) {
if (RD->isAnonymousStructOrUnion()) {
// These field orders shouldn't change.
if (RD->isUnion()) {