aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp46
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;