diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1256,25 +1256,6 @@ return OpenCLAccessAttr::Keyword_read_only; } -static QualType ConvertConstrainedAutoDeclSpecToType(Sema &S, DeclSpec &DS, - AutoTypeKeyword AutoKW) { - assert(DS.isConstrainedAuto()); - TemplateIdAnnotation *TemplateId = DS.getRepAsTemplateId(); - TemplateArgumentListInfo TemplateArgsInfo; - TemplateArgsInfo.setLAngleLoc(TemplateId->LAngleLoc); - TemplateArgsInfo.setRAngleLoc(TemplateId->RAngleLoc); - ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), - TemplateId->NumArgs); - S.translateTemplateArguments(TemplateArgsPtr, TemplateArgsInfo); - llvm::SmallVector TemplateArgs; - for (auto &ArgLoc : TemplateArgsInfo.arguments()) - TemplateArgs.push_back(ArgLoc.getArgument()); - return S.Context.getAutoType( - QualType(), AutoKW, false, /*IsPack=*/false, - cast(TemplateId->Template.get().getAsTemplateDecl()), - TemplateArgs); -} - /// Convert the specified declspec to the appropriate type /// object. /// \param state Specifies the declarator containing the declaration specifier @@ -1655,29 +1636,39 @@ break; case DeclSpec::TST_auto: + case DeclSpec::TST_decltype_auto: { + auto AutoKW = DS.getTypeSpecType() == DeclSpec::TST_decltype_auto + ? AutoTypeKeyword::DecltypeAuto + : AutoTypeKeyword::Auto; + + ConceptDecl *TypeConstraintConcept = nullptr; + llvm::SmallVector TemplateArgs; if (DS.isConstrainedAuto()) { - Result = ConvertConstrainedAutoDeclSpecToType(S, DS, - AutoTypeKeyword::Auto); - break; + if (TemplateIdAnnotation *TemplateId = DS.getRepAsTemplateId()) { + TypeConstraintConcept = + cast(TemplateId->Template.get().getAsTemplateDecl()); + TemplateArgumentListInfo TemplateArgsInfo; + TemplateArgsInfo.setLAngleLoc(TemplateId->LAngleLoc); + TemplateArgsInfo.setRAngleLoc(TemplateId->RAngleLoc); + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + S.translateTemplateArguments(TemplateArgsPtr, TemplateArgsInfo); + for (const auto &ArgLoc : TemplateArgsInfo.arguments()) + TemplateArgs.push_back(ArgLoc.getArgument()); + } else { + declarator.setInvalidType(true); + } } - Result = Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false); + Result = S.Context.getAutoType(QualType(), AutoKW, + /*IsDependent*/ false, /*IsPack=*/false, + TypeConstraintConcept, TemplateArgs); break; + } case DeclSpec::TST_auto_type: Result = Context.getAutoType(QualType(), AutoTypeKeyword::GNUAutoType, false); break; - case DeclSpec::TST_decltype_auto: - if (DS.isConstrainedAuto()) { - Result = - ConvertConstrainedAutoDeclSpecToType(S, DS, - AutoTypeKeyword::DecltypeAuto); - break; - } - Result = Context.getAutoType(QualType(), AutoTypeKeyword::DecltypeAuto, - /*IsDependent*/ false); - break; - case DeclSpec::TST_unknown_anytype: Result = Context.UnknownAnyTy; break; @@ -5962,6 +5953,8 @@ if (!DS.isConstrainedAuto()) return; TemplateIdAnnotation *TemplateId = DS.getRepAsTemplateId(); + if (!TemplateId) + return; if (DS.getTypeSpecScope().isNotEmpty()) TL.setNestedNameSpecifierLoc( DS.getTypeSpecScope().getWithLocInContext(Context)); diff --git a/clang/test/CXX/dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp b/clang/test/CXX/dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp --- a/clang/test/CXX/dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp +++ b/clang/test/CXX/dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp @@ -68,3 +68,11 @@ True decltype(auto) h = (b); static_assert(is_same_v); } + +namespace PR48593 { + template concept a = true; + a auto c = 0; // expected-error{{use of undeclared identifier 'B'}} + + template concept d = true; + d<,> auto e = 0; // expected-error{{expected expression}} +}