diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index c4bef4729fd36..90f17465bce7d 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -8909,6 +8909,8 @@ class Parser : public CodeCompletionHandler { bool OuterMightBeMessageSend = false); ///@} + + TemplateParameterLists *TemplateParamsFromAlias = nullptr; }; } // end namespace clang diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 2cf33a856c4f4..4069d257b0150 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -886,11 +886,17 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator( << FixItHint::CreateRemoval(SourceRange(D.EllipsisLoc)); Decl *DeclFromDeclSpec = nullptr; + + this->TemplateParamsFromAlias = TemplateInfo.TemplateParams; + TypeResult TypeAlias = ParseTypeName(nullptr, TemplateInfo.Kind != ParsedTemplateKind::NonTemplate ? DeclaratorContext::AliasTemplate : DeclaratorContext::AliasDecl, AS, &DeclFromDeclSpec, &Attrs); + + this->TemplateParamsFromAlias = nullptr; + if (OwnedType) *OwnedType = DeclFromDeclSpec; @@ -2173,6 +2179,17 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, assert(Tok.is(tok::l_brace) || (getLangOpts().CPlusPlus && Tok.is(tok::colon)) || isClassCompatibleKeyword()); + + if (TemplateParamsFromAlias) { + for (const TemplateParameterList *TPL : *TemplateParamsFromAlias) { + for (NamedDecl *D : *TPL) { + D->setInvalidDecl(true); + auto *TTPD = dyn_cast(D); + TTPD->setTypeForDecl(Actions.Context.IntTy.getTypePtr()); + } + } + } + if (SkipBody.ShouldSkip) SkipCXXMemberSpecification(StartLoc, AttrFixitLoc, TagType, TagOrTempResult.get()); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 86b871396ec90..50c09bd3cdea7 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -288,8 +288,8 @@ static ParsedType buildNamedType(Sema &S, const CXXScopeSpec *SS, QualType T, case Type::ObjCTypeParam: case Type::TemplateTypeParm: return ParsedType::make(T); - default: - llvm_unreachable("Unexpected Type Class"); + //default: + //llvm_unreachable("Unexpected Type Class"); } if (!SS || SS->isEmpty()) diff --git a/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp b/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp index 1efed72522fef..fa3eb1372bd3f 100644 --- a/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp +++ b/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp @@ -60,3 +60,16 @@ concept atomicish = requires() { }; atomicish f(); // expected-error {{expected 'auto' or 'decltype(auto)' after concept name}} } // namespace GH138820 + +namespace GH91564 { +template using A = struct B { // expected-error {{'GH91564::B' cannot be defined in a type alias template}} + template void f() requires (T()); // expected-error {{atomic constraint must be of type 'bool' (found 'int')}} expected-note {{explicit instantiation refers here}} +}; +template void B::f(); // expected-error {{explicit instantiation of undefined function template 'f'}} + +template using C = struct D { // expected-error {{'GH91564::D' cannot be defined in a type alias template}} + using E = T; +}; +template void g() requires (D::E()); // expected-error {{atomic constraint must be of type 'bool' (found 'D::E' (aka 'int'))}} expected-note {{explicit instantiation refers here}} +template void g(); // expected-error {{explicit instantiation of undefined function template 'g'}} +} \ No newline at end of file