diff options
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 46 |
1 files changed, 23 insertions, 23 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 9bf1e9d..c89c3c4 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5207,25 +5207,6 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, return ActOnFriendTypeDecl(S, DS, TemplateParams); } - const CXXScopeSpec &SS = DS.getTypeSpecScope(); - bool IsExplicitSpecialization = - !TemplateParams.empty() && TemplateParams.back()->size() == 0; - if (Tag && SS.isNotEmpty() && !Tag->isCompleteDefinition() && - !IsExplicitInstantiation && !IsExplicitSpecialization && - !isa<ClassTemplatePartialSpecializationDecl>(Tag)) { - // Per C++ [dcl.type.elab]p1, a class declaration cannot have a - // nested-name-specifier unless it is an explicit instantiation - // or an explicit specialization. - // - // FIXME: We allow class template partial specializations here too, per the - // obvious intent of DR1819. - // - // Per C++ [dcl.enum]p1, an opaque-enum-declaration can't either. - Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier) - << GetDiagnosticTypeSpecifierID(DS) << SS.getRange(); - return nullptr; - } - // Track whether this decl-specifier declares anything. bool DeclaresAnything = true; @@ -17222,10 +17203,29 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // for non-C++ cases. if (TemplateParameterLists.size() > 0 || (SS.isNotEmpty() && TUK != TUK_Reference)) { - if (TemplateParameterList *TemplateParams = - MatchTemplateParametersToScopeSpecifier( - KWLoc, NameLoc, SS, nullptr, TemplateParameterLists, - TUK == TUK_Friend, isMemberSpecialization, Invalid)) { + TemplateParameterList *TemplateParams = + MatchTemplateParametersToScopeSpecifier( + KWLoc, NameLoc, SS, nullptr, TemplateParameterLists, + TUK == TUK_Friend, isMemberSpecialization, Invalid); + + // C++23 [dcl.type.elab] p2: + // If an elaborated-type-specifier is the sole constituent of a + // declaration, the declaration is ill-formed unless it is an explicit + // specialization, an explicit instantiation or it has one of the + // following forms: [...] + // C++23 [dcl.enum] p1: + // If the enum-head-name of an opaque-enum-declaration contains a + // nested-name-specifier, the declaration shall be an explicit + // specialization. + // + // FIXME: Class template partial specializations can be forward declared + // per CWG2213, but the resolution failed to allow qualified forward + // declarations. This is almost certainly unintentional, so we allow them. + if (TUK == TUK_Declaration && SS.isNotEmpty() && !isMemberSpecialization) + Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier) + << TypeWithKeyword::getTagTypeKindName(Kind) << SS.getRange(); + + if (TemplateParams) { if (Kind == TagTypeKind::Enum) { Diag(KWLoc, diag::err_enum_template); return true; |