[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:
parent
1ba8b36fef
commit
dc8596d548
@ -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(
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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++;
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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)) {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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() &&
|
||||
|
||||
@ -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())) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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())
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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()) {
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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!");
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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>())
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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()))
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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)));
|
||||
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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");
|
||||
|
||||
|
||||
@ -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())
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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 =
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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())
|
||||
|
||||
@ -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(),
|
||||
|
||||
@ -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)) {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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()))
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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 =
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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)) {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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()) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user