Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1731,6 +1731,8 @@ // C++ name lookup def err_incomplete_nested_name_spec : Error< "incomplete type %0 named in nested name specifier">; +def err_incomplete_enum : Error< + "enumeration %0 is incomplete">; def err_dependent_nested_name_spec : Error< "nested name specifier for a declaration cannot depend on a template " "parameter">; Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -6366,6 +6366,9 @@ // Marks SS invalid if it represents an incomplete type. bool RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC); + // Complete an enum decl, maybe without a scope spec. + bool RequireCompleteEnumDecl(EnumDecl *D, SourceLocation L, + CXXScopeSpec *SS = nullptr); DeclContext *computeDeclContext(QualType T); DeclContext *computeDeclContext(const CXXScopeSpec &SS, Index: clang/lib/Sema/SemaCXXScopeSpec.cpp =================================================================== --- clang/lib/Sema/SemaCXXScopeSpec.cpp +++ clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -227,12 +227,19 @@ 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(tag); - if (!EnumD) - return false; + if (auto *EnumD = dyn_cast(tag)) + // Fixed enum types and scoped enum instantiations are complete, but they + // aren't valid as scopes until we see or instantiate their definition. + return RequireCompleteEnumDecl(EnumD, loc, &SS); + + return false; +} + +/// Require that the EnumDecl is completed with its enumerators defined or +/// instantiated. SS, if provided, is the ScopeRef parsed. +/// +bool Sema::RequireCompleteEnumDecl(EnumDecl *EnumD, SourceLocation L, + CXXScopeSpec *SS) { if (EnumD->isCompleteDefinition()) { // If we know about the definition but it is not visible, complain. NamedDecl *SuggestedDef = nullptr; @@ -241,8 +248,8 @@ // 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); + diagnoseMissingImport(L, SuggestedDef, MissingImportKind::Definition, + /*Recover*/ TreatAsComplete); return !TreatAsComplete; } return false; @@ -253,19 +260,26 @@ if (EnumDecl *Pattern = EnumD->getInstantiatedFromMemberEnum()) { MemberSpecializationInfo *MSI = EnumD->getMemberSpecializationInfo(); if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) { - if (InstantiateEnum(loc, EnumD, Pattern, + if (InstantiateEnum(L, EnumD, Pattern, getTemplateInstantiationArgs(EnumD), TSK_ImplicitInstantiation)) { - SS.SetInvalid(SS.getRange()); + if (SS) + SS->SetInvalid(SS->getRange()); return true; } return false; } } - Diag(loc, diag::err_incomplete_nested_name_spec) - << type << SS.getRange(); - SS.SetInvalid(SS.getRange()); + if (SS) { + Diag(L, diag::err_incomplete_nested_name_spec) + << QualType(EnumD->getTypeForDecl(), 0) << SS->getRange(); + SS->SetInvalid(SS->getRange()); + } else { + Diag(L, diag::err_incomplete_enum) << QualType(EnumD->getTypeForDecl(), 0); + Diag(EnumD->getLocation(), diag::note_declared_at); + } + return true; }