@@ -768,58 +768,44 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
768768 // C++23 [dcl.pre]/6:
769769 // Each decl-specifier in the decl-specifier-seq shall be static,
770770 // thread_local, auto (9.2.9.6 [dcl.spec.auto]), or a cv-qualifier.
771+ // C++23 [dcl.pre]/7:
772+ // Each decl-specifier in the decl-specifier-seq shall be constexpr,
773+ // constinit, static, thread_local, auto, or a cv-qualifier
771774 auto &DS = D.getDeclSpec();
772- {
773- // Note: While constrained-auto needs to be checked, we do so separately so
774- // we can emit a better diagnostic.
775- SmallVector<StringRef, 8> BadSpecifiers;
776- SmallVector<SourceLocation, 8> BadSpecifierLocs;
777- SmallVector<StringRef, 8> CPlusPlus20Specifiers;
778- SmallVector<SourceLocation, 8> CPlusPlus20SpecifierLocs;
779- if (auto SCS = DS.getStorageClassSpec()) {
780- if (SCS == DeclSpec::SCS_static) {
781- CPlusPlus20Specifiers.push_back(DeclSpec::getSpecifierName(SCS));
782- CPlusPlus20SpecifierLocs.push_back(DS.getStorageClassSpecLoc());
783- } else {
784- BadSpecifiers.push_back(DeclSpec::getSpecifierName(SCS));
785- BadSpecifierLocs.push_back(DS.getStorageClassSpecLoc());
786- }
787- }
788- if (auto TSCS = DS.getThreadStorageClassSpec()) {
789- CPlusPlus20Specifiers.push_back(DeclSpec::getSpecifierName(TSCS));
790- CPlusPlus20SpecifierLocs.push_back(DS.getThreadStorageClassSpecLoc());
791- }
792- if (DS.hasConstexprSpecifier()) {
793- BadSpecifiers.push_back(
794- DeclSpec::getSpecifierName(DS.getConstexprSpecifier()));
795- BadSpecifierLocs.push_back(DS.getConstexprSpecLoc());
796- }
797- if (DS.isInlineSpecified()) {
798- BadSpecifiers.push_back("inline");
799- BadSpecifierLocs.push_back(DS.getInlineSpecLoc());
800- }
801-
802- if (!BadSpecifiers.empty()) {
803- auto &&Err = Diag(BadSpecifierLocs.front(), diag::err_decomp_decl_spec);
804- Err << (int)BadSpecifiers.size()
805- << llvm::join(BadSpecifiers.begin(), BadSpecifiers.end(), " ");
806- // Don't add FixItHints to remove the specifiers; we do still respect
807- // them when building the underlying variable.
808- for (auto Loc : BadSpecifierLocs)
809- Err << SourceRange(Loc, Loc);
810- } else if (!CPlusPlus20Specifiers.empty()) {
811- auto &&Warn = DiagCompat(CPlusPlus20SpecifierLocs.front(),
812- diag_compat::decomp_decl_spec);
813- Warn << (int)CPlusPlus20Specifiers.size()
814- << llvm::join(CPlusPlus20Specifiers.begin(),
815- CPlusPlus20Specifiers.end(), " ");
816- for (auto Loc : CPlusPlus20SpecifierLocs)
817- Warn << SourceRange(Loc, Loc);
818- }
819- // We can't recover from it being declared as a typedef.
820- if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef)
821- return nullptr;
775+ auto DiagBadSpecifier = [&](StringRef Name, SourceLocation Loc) {
776+ Diag(Loc, diag::err_decomp_decl_spec) << Name;
777+ };
778+
779+ auto DiagCpp20Specifier = [&](StringRef Name, SourceLocation Loc) {
780+ DiagCompat(Loc, diag_compat::decomp_decl_spec) << Name;
781+ };
782+
783+ if (auto SCS = DS.getStorageClassSpec()) {
784+ if (SCS == DeclSpec::SCS_static)
785+ DiagCpp20Specifier(DeclSpec::getSpecifierName(SCS),
786+ DS.getStorageClassSpecLoc());
787+ else
788+ DiagBadSpecifier(DeclSpec::getSpecifierName(SCS),
789+ DS.getStorageClassSpecLoc());
822790 }
791+ if (auto TSCS = DS.getThreadStorageClassSpec())
792+ DiagCpp20Specifier(DeclSpec::getSpecifierName(TSCS),
793+ DS.getThreadStorageClassSpecLoc());
794+
795+ if (DS.isInlineSpecified())
796+ DiagBadSpecifier("inline", DS.getInlineSpecLoc());
797+
798+ if (ConstexprSpecKind ConstexprSpec = DS.getConstexprSpecifier();
799+ ConstexprSpec != ConstexprSpecKind::Unspecified) {
800+ if (ConstexprSpec == ConstexprSpecKind::Consteval ||
801+ !getLangOpts().CPlusPlus26)
802+ DiagBadSpecifier(DeclSpec::getSpecifierName(ConstexprSpec),
803+ DS.getConstexprSpecLoc());
804+ }
805+
806+ // We can't recover from it being declared as a typedef.
807+ if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef)
808+ return nullptr;
823809
824810 // C++2a [dcl.struct.bind]p1:
825811 // A cv that includes volatile is deprecated
0 commit comments