forked from OSchip/llvm-project
Clean up and simplify RequireCompleteType.
No functional change intended, except that we will now produce more "declared here" notes. llvm-svn: 339187
This commit is contained in:
parent
51ed131ed2
commit
96cb356911
|
@ -209,11 +209,13 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
|
|||
if (!tag || tag->isDependentContext())
|
||||
return false;
|
||||
|
||||
// Grab the tag definition, if there is one.
|
||||
QualType type = Context.getTypeDeclType(tag);
|
||||
tag = type->getAsTagDecl();
|
||||
|
||||
// If we're currently defining this type, then lookup into the
|
||||
// type is okay: don't complain that it isn't complete yet.
|
||||
QualType type = Context.getTypeDeclType(tag);
|
||||
const TagType *tagType = type->getAs<TagType>();
|
||||
if (tagType && tagType->isBeingDefined())
|
||||
if (tag->isBeingDefined())
|
||||
return false;
|
||||
|
||||
SourceLocation loc = SS.getLastQualifierNameLoc();
|
||||
|
@ -229,13 +231,13 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
|
|||
// Fixed enum types are complete, but they aren't valid as scopes
|
||||
// until we see a definition, so awkwardly pull out this special
|
||||
// case.
|
||||
const EnumType *enumType = dyn_cast_or_null<EnumType>(tagType);
|
||||
if (!enumType)
|
||||
auto *EnumD = dyn_cast<EnumDecl>(tag);
|
||||
if (!EnumD)
|
||||
return false;
|
||||
if (enumType->getDecl()->isCompleteDefinition()) {
|
||||
if (EnumD->isCompleteDefinition()) {
|
||||
// If we know about the definition but it is not visible, complain.
|
||||
NamedDecl *SuggestedDef = nullptr;
|
||||
if (!hasVisibleDefinition(enumType->getDecl(), &SuggestedDef,
|
||||
if (!hasVisibleDefinition(EnumD, &SuggestedDef,
|
||||
/*OnlyNeedComplete*/false)) {
|
||||
// If the user is going to see an error here, recover by making the
|
||||
// definition visible.
|
||||
|
@ -249,11 +251,11 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
|
|||
|
||||
// Try to instantiate the definition, if this is a specialization of an
|
||||
// enumeration temploid.
|
||||
EnumDecl *ED = enumType->getDecl();
|
||||
if (EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) {
|
||||
MemberSpecializationInfo *MSI = ED->getMemberSpecializationInfo();
|
||||
if (EnumDecl *Pattern = EnumD->getInstantiatedFromMemberEnum()) {
|
||||
MemberSpecializationInfo *MSI = EnumD->getMemberSpecializationInfo();
|
||||
if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
|
||||
if (InstantiateEnum(loc, ED, Pattern, getTemplateInstantiationArgs(ED),
|
||||
if (InstantiateEnum(loc, EnumD, Pattern,
|
||||
getTemplateInstantiationArgs(EnumD),
|
||||
TSK_ImplicitInstantiation)) {
|
||||
SS.SetInvalid(SS.getRange());
|
||||
return true;
|
||||
|
|
|
@ -7684,39 +7684,24 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
|
|||
return false;
|
||||
}
|
||||
|
||||
const TagType *Tag = T->getAs<TagType>();
|
||||
const ObjCInterfaceType *IFace = T->getAs<ObjCInterfaceType>();
|
||||
TagDecl *Tag = dyn_cast_or_null<TagDecl>(Def);
|
||||
ObjCInterfaceDecl *IFace = dyn_cast_or_null<ObjCInterfaceDecl>(Def);
|
||||
|
||||
// If there's an unimported definition of this type in a module (for
|
||||
// instance, because we forward declared it, then imported the definition),
|
||||
// import that definition now.
|
||||
//
|
||||
// FIXME: What about other cases where an import extends a redeclaration
|
||||
// chain for a declaration that can be accessed through a mechanism other
|
||||
// than name lookup (eg, referenced in a template, or a variable whose type
|
||||
// could be completed by the module)?
|
||||
//
|
||||
// FIXME: Should we map through to the base array element type before
|
||||
// checking for a tag type?
|
||||
// Give the external source a chance to provide a definition of the type.
|
||||
// This is kept separate from completing the redeclaration chain so that
|
||||
// external sources such as LLDB can avoid synthesizing a type definition
|
||||
// unless it's actually needed.
|
||||
if (Tag || IFace) {
|
||||
NamedDecl *D =
|
||||
Tag ? static_cast<NamedDecl *>(Tag->getDecl()) : IFace->getDecl();
|
||||
|
||||
// Avoid diagnosing invalid decls as incomplete.
|
||||
if (D->isInvalidDecl())
|
||||
if (Def->isInvalidDecl())
|
||||
return true;
|
||||
|
||||
// Give the external AST source a chance to complete the type.
|
||||
if (auto *Source = Context.getExternalSource()) {
|
||||
if (Tag) {
|
||||
TagDecl *TagD = Tag->getDecl();
|
||||
if (TagD->hasExternalLexicalStorage())
|
||||
Source->CompleteType(TagD);
|
||||
} else {
|
||||
ObjCInterfaceDecl *IFaceD = IFace->getDecl();
|
||||
if (IFaceD->hasExternalLexicalStorage())
|
||||
Source->CompleteType(IFace->getDecl());
|
||||
}
|
||||
if (Tag && Tag->hasExternalLexicalStorage())
|
||||
Source->CompleteType(Tag);
|
||||
if (IFace && IFace->hasExternalLexicalStorage())
|
||||
Source->CompleteType(IFace);
|
||||
// If the external source completed the type, go through the motions
|
||||
// again to ensure we're allowed to use the completed type.
|
||||
if (!T->isIncompleteType())
|
||||
|
@ -7727,32 +7712,31 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
|
|||
// If we have a class template specialization or a class member of a
|
||||
// class template specialization, or an array with known size of such,
|
||||
// try to instantiate it.
|
||||
QualType MaybeTemplate = T;
|
||||
while (const ConstantArrayType *Array
|
||||
= Context.getAsConstantArrayType(MaybeTemplate))
|
||||
MaybeTemplate = Array->getElementType();
|
||||
if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) {
|
||||
if (auto *RD = dyn_cast_or_null<CXXRecordDecl>(Tag)) {
|
||||
bool Instantiated = false;
|
||||
bool Diagnosed = false;
|
||||
if (ClassTemplateSpecializationDecl *ClassTemplateSpec
|
||||
= dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
|
||||
if (RD->isDependentContext()) {
|
||||
// Don't try to instantiate a dependent class (eg, a member template of
|
||||
// an instantiated class template specialization).
|
||||
// FIXME: Can this ever happen?
|
||||
} else if (auto *ClassTemplateSpec =
|
||||
dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
|
||||
if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) {
|
||||
Diagnosed = InstantiateClassTemplateSpecialization(
|
||||
Loc, ClassTemplateSpec, TSK_ImplicitInstantiation,
|
||||
/*Complain=*/Diagnoser);
|
||||
Instantiated = true;
|
||||
}
|
||||
} else if (CXXRecordDecl *Rec
|
||||
= dyn_cast<CXXRecordDecl>(Record->getDecl())) {
|
||||
CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass();
|
||||
if (!Rec->isBeingDefined() && Pattern) {
|
||||
MemberSpecializationInfo *MSI = Rec->getMemberSpecializationInfo();
|
||||
} else {
|
||||
CXXRecordDecl *Pattern = RD->getInstantiatedFromMemberClass();
|
||||
if (!RD->isBeingDefined() && Pattern) {
|
||||
MemberSpecializationInfo *MSI = RD->getMemberSpecializationInfo();
|
||||
assert(MSI && "Missing member specialization information?");
|
||||
// This record was instantiated from a class within a template.
|
||||
if (MSI->getTemplateSpecializationKind() !=
|
||||
TSK_ExplicitSpecialization) {
|
||||
Diagnosed = InstantiateClass(Loc, Rec, Pattern,
|
||||
getTemplateInstantiationArgs(Rec),
|
||||
Diagnosed = InstantiateClass(Loc, RD, Pattern,
|
||||
getTemplateInstantiationArgs(RD),
|
||||
TSK_ImplicitInstantiation,
|
||||
/*Complain=*/Diagnoser);
|
||||
Instantiated = true;
|
||||
|
@ -7783,15 +7767,15 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
|
|||
|
||||
// If the type was a forward declaration of a class/struct/union
|
||||
// type, produce a note.
|
||||
if (Tag && !Tag->getDecl()->isInvalidDecl())
|
||||
Diag(Tag->getDecl()->getLocation(),
|
||||
if (Tag && !Tag->isInvalidDecl())
|
||||
Diag(Tag->getLocation(),
|
||||
Tag->isBeingDefined() ? diag::note_type_being_defined
|
||||
: diag::note_forward_declaration)
|
||||
<< QualType(Tag, 0);
|
||||
<< Context.getTagDeclType(Tag);
|
||||
|
||||
// If the Objective-C class was a forward declaration, produce a note.
|
||||
if (IFace && !IFace->getDecl()->isInvalidDecl())
|
||||
Diag(IFace->getDecl()->getLocation(), diag::note_forward_class);
|
||||
if (IFace && !IFace->isInvalidDecl())
|
||||
Diag(IFace->getLocation(), diag::note_forward_class);
|
||||
|
||||
// If we have external information that we can use to suggest a fix,
|
||||
// produce a note.
|
||||
|
|
|
@ -108,7 +108,7 @@ void g() {
|
|||
extern int incomplete[];
|
||||
for (auto a : incomplete) // expected-error {{cannot use incomplete type 'int []' as a range}}
|
||||
;
|
||||
extern struct Incomplete also_incomplete[2]; // expected-note {{forward declaration}}
|
||||
extern struct Incomplete also_incomplete[2]; // expected-note 2{{forward declaration}}
|
||||
for (auto &a : also_incomplete) // expected-error {{cannot use incomplete type 'struct Incomplete [2]' as a range}}
|
||||
;
|
||||
|
||||
|
|
|
@ -410,7 +410,7 @@ void test16(void) {
|
|||
[v test16_6: 0];
|
||||
}
|
||||
|
||||
@class Test17; // expected-note 2{{forward declaration of class here}}
|
||||
@class Test17; // expected-note 3{{forward declaration of class here}}
|
||||
@protocol Test17p
|
||||
- (void) test17;
|
||||
+ (void) test17;
|
||||
|
|
Loading…
Reference in New Issue