From 96cb3569111024bd28a100f5bf0cbe718a96cf2d Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 7 Aug 2018 21:35:41 +0000 Subject: [PATCH] Clean up and simplify RequireCompleteType. No functional change intended, except that we will now produce more "declared here" notes. llvm-svn: 339187 --- clang/lib/Sema/SemaCXXScopeSpec.cpp | 24 +++--- clang/lib/Sema/SemaType.cpp | 74 ++++++++----------- .../stmt.stmt/stmt.iter/stmt.ranged/p1.cpp | 2 +- clang/test/SemaObjC/arc.m | 2 +- 4 files changed, 44 insertions(+), 58 deletions(-) diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 4e39d0675471..2354ffe7fbcc 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -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(); - 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(tagType); - if (!enumType) + auto *EnumD = dyn_cast(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; diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 7bd9c8f315b6..8c2209d179d2 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -7684,39 +7684,24 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, return false; } - const TagType *Tag = T->getAs(); - const ObjCInterfaceType *IFace = T->getAs(); + TagDecl *Tag = dyn_cast_or_null(Def); + ObjCInterfaceDecl *IFace = dyn_cast_or_null(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(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()) { + if (auto *RD = dyn_cast_or_null(Tag)) { bool Instantiated = false; bool Diagnosed = false; - if (ClassTemplateSpecializationDecl *ClassTemplateSpec - = dyn_cast(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(RD)) { if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) { Diagnosed = InstantiateClassTemplateSpecialization( Loc, ClassTemplateSpec, TSK_ImplicitInstantiation, /*Complain=*/Diagnoser); Instantiated = true; } - } else if (CXXRecordDecl *Rec - = dyn_cast(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. diff --git a/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp b/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp index 34202494c0d8..473c8b62bad0 100644 --- a/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp +++ b/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp @@ -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}} ; diff --git a/clang/test/SemaObjC/arc.m b/clang/test/SemaObjC/arc.m index fcac798ff2d1..b87f294eef53 100644 --- a/clang/test/SemaObjC/arc.m +++ b/clang/test/SemaObjC/arc.m @@ -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;