/// \brief Require that the context specified by SS be complete. /// /// If SS refers to a type, this routine checks whether the type is /// complete enough (or can be made complete enough) for name lookup /// into the DeclContext. A type that is not yet completed can be /// considered "complete enough" if it is a class/struct/union/enum /// that is currently being defined. Or, if we have a type that names /// a class template specialization that is not a complete type, we /// will attempt to instantiate that class template. bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC) { assert(DC && "given null context"); TagDecl *tag = dyn_cast<TagDecl>(DC); // If this is a dependent type, then we consider it complete. if (!tag || tag->isDependentContext()) return false; // 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()) return false; SourceLocation loc = SS.getLastQualifierNameLoc(); if (loc.isInvalid()) loc = SS.getRange().getBegin(); // The type must be complete. if (RequireCompleteType(loc, type, diag::err_incomplete_nested_name_spec, SS.getRange())) { SS.SetInvalid(SS.getRange()); return true; } // Fixed enum types are complete, but they aren't valid as scopes // until we see a definition, so awkwardly pull out this special // case. // FIXME: The definition might not be visible; complain if it is not. const EnumType *enumType = dyn_cast_or_null<EnumType>(tagType); if (!enumType || enumType->getDecl()->isCompleteDefinition()) return false; // 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 (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) { if (InstantiateEnum(loc, ED, Pattern, getTemplateInstantiationArgs(ED), TSK_ImplicitInstantiation)) { SS.SetInvalid(SS.getRange()); return true; } return false; } } Diag(loc, diag::err_incomplete_nested_name_spec) << type << SS.getRange(); SS.SetInvalid(SS.getRange()); return true; }
/// Require that the context specified by SS be complete. /// /// If SS refers to a type, this routine checks whether the type is /// complete enough (or can be made complete enough) for name lookup /// into the DeclContext. A type that is not yet completed can be /// considered "complete enough" if it is a class/struct/union/enum /// that is currently being defined. Or, if we have a type that names /// a class template specialization that is not a complete type, we /// will attempt to instantiate that class template. bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC) { assert(DC && "given null context"); TagDecl *tag = dyn_cast<TagDecl>(DC); // If this is a dependent type, then we consider it complete. // FIXME: This is wrong; we should require a (visible) definition to // exist in this case too. 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. if (tag->isBeingDefined()) return false; SourceLocation loc = SS.getLastQualifierNameLoc(); if (loc.isInvalid()) loc = SS.getRange().getBegin(); // The type must be complete. if (RequireCompleteType(loc, type, diag::err_incomplete_nested_name_spec, SS.getRange())) { SS.SetInvalid(SS.getRange()); return true; } // Fixed enum types are complete, but they aren't valid as scopes // until we see a definition, so awkwardly pull out this special // case. auto *EnumD = dyn_cast<EnumDecl>(tag); if (!EnumD) return false; if (EnumD->isCompleteDefinition()) { // If we know about the definition but it is not visible, complain. NamedDecl *SuggestedDef = nullptr; if (!hasVisibleDefinition(EnumD, &SuggestedDef, /*OnlyNeedComplete*/false)) { // If the user is going to see an error here, recover by making the // definition visible. bool TreatAsComplete = !isSFINAEContext(); diagnoseMissingImport(loc, SuggestedDef, MissingImportKind::Definition, /*Recover*/TreatAsComplete); return !TreatAsComplete; } return false; } // Try to instantiate the definition, if this is a specialization of an // enumeration temploid. if (EnumDecl *Pattern = EnumD->getInstantiatedFromMemberEnum()) { MemberSpecializationInfo *MSI = EnumD->getMemberSpecializationInfo(); if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) { if (InstantiateEnum(loc, EnumD, Pattern, getTemplateInstantiationArgs(EnumD), TSK_ImplicitInstantiation)) { SS.SetInvalid(SS.getRange()); return true; } return false; } } Diag(loc, diag::err_incomplete_nested_name_spec) << type << SS.getRange(); SS.SetInvalid(SS.getRange()); return true; }
/// \brief Require that the context specified by SS be complete. /// /// If SS refers to a type, this routine checks whether the type is /// complete enough (or can be made complete enough) for name lookup /// into the DeclContext. A type that is not yet completed can be /// considered "complete enough" if it is a class/struct/union/enum /// that is currently being defined. Or, if we have a type that names /// a class template specialization that is not a complete type, we /// will attempt to instantiate that class template. bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *&DC) { assert(DC && "given null context"); TagDecl *tag = dyn_cast<TagDecl>(DC); // If this is a dependent type, then we consider it complete. // FIXME: This is wrong; we should require a (visible) definition to // exist in this case too. if (!tag || tag->isDependentContext()) return false; // 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()) return false; SourceLocation loc = SS.getLastQualifierNameLoc(); if (loc.isInvalid()) loc = SS.getRange().getBegin(); // The type must be complete. if (RequireCompleteType(loc, type, diag::err_incomplete_nested_name_spec, SS.getRange())) { // The actual information about the decl may have been loaded via an // external source that created a new AST node/decl for the definition // rather than reusing the one we had (DC) like the ASTReader does. // To avoid the caller to continue using the still incomplete decl, let's // set it to the definition. DC = tag->getDefinition(); SS.SetInvalid(SS.getRange()); return true; } // 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) return false; if (enumType->getDecl()->isCompleteDefinition()) { // If we know about the definition but it is not visible, complain. NamedDecl *SuggestedDef = nullptr; if (!hasVisibleDefinition(enumType->getDecl(), &SuggestedDef, /*OnlyNeedComplete*/false)) { // If the user is going to see an error here, recover by making the // definition visible. bool TreatAsComplete = !isSFINAEContext(); diagnoseMissingImport(loc, SuggestedDef, MissingImportKind::Definition, /*Recover*/TreatAsComplete); return !TreatAsComplete; } return false; } // 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 (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) { if (InstantiateEnum(loc, ED, Pattern, getTemplateInstantiationArgs(ED), TSK_ImplicitInstantiation)) { SS.SetInvalid(SS.getRange()); return true; } return false; } } Diag(loc, diag::err_incomplete_nested_name_spec) << type << SS.getRange(); SS.SetInvalid(SS.getRange()); return true; }