@@ -1916,9 +1916,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context,
1916
1916
case tok::kw_export:
1917
1917
ProhibitAttributes (DeclAttrs);
1918
1918
ProhibitAttributes (DeclSpecAttrs);
1919
- SingleDecl =
1920
- ParseDeclarationStartingWithTemplate (Context, DeclEnd, DeclAttrs);
1921
- break ;
1919
+ return ParseDeclarationStartingWithTemplate (Context, DeclEnd, DeclAttrs);
1922
1920
case tok::kw_inline:
1923
1921
// Could be the start of an inline namespace. Allowed as an ext in C++03.
1924
1922
if (getLangOpts ().CPlusPlus && NextToken ().is (tok::kw_namespace)) {
@@ -1994,8 +1992,9 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(
1994
1992
ParsingDeclSpec DS (*this );
1995
1993
DS.takeAttributesFrom (DeclSpecAttrs);
1996
1994
1995
+ ParsedTemplateInfo TemplateInfo;
1997
1996
DeclSpecContext DSContext = getDeclSpecContextFromDeclaratorContext (Context);
1998
- ParseDeclarationSpecifiers (DS, ParsedTemplateInfo () , AS_none, DSContext);
1997
+ ParseDeclarationSpecifiers (DS, TemplateInfo , AS_none, DSContext);
1999
1998
2000
1999
// If we had a free-standing type definition with a missing semicolon, we
2001
2000
// may get this far before the problem becomes obvious.
@@ -2027,7 +2026,7 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(
2027
2026
if (DeclSpecStart)
2028
2027
DS.SetRangeStart (*DeclSpecStart);
2029
2028
2030
- return ParseDeclGroup (DS, Context, DeclAttrs, &DeclEnd, FRI);
2029
+ return ParseDeclGroup (DS, Context, DeclAttrs, TemplateInfo, &DeclEnd, FRI);
2031
2030
}
2032
2031
2033
2032
// / Returns true if this might be the start of a declarator, or a common typo
@@ -2184,6 +2183,7 @@ void Parser::SkipMalformedDecl() {
2184
2183
Parser::DeclGroupPtrTy Parser::ParseDeclGroup (ParsingDeclSpec &DS,
2185
2184
DeclaratorContext Context,
2186
2185
ParsedAttributes &Attrs,
2186
+ ParsedTemplateInfo &TemplateInfo,
2187
2187
SourceLocation *DeclEnd,
2188
2188
ForRangeInit *FRI) {
2189
2189
// Parse the first declarator.
@@ -2193,8 +2193,19 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
2193
2193
ParsedAttributes LocalAttrs (AttrFactory);
2194
2194
LocalAttrs.takeAllFrom (Attrs);
2195
2195
ParsingDeclarator D (*this , DS, LocalAttrs, Context);
2196
+ if (TemplateInfo.TemplateParams )
2197
+ D.setTemplateParameterLists (*TemplateInfo.TemplateParams );
2198
+
2199
+ bool IsTemplateSpecOrInst =
2200
+ (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||
2201
+ TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);
2202
+ SuppressAccessChecks SAC (*this , IsTemplateSpecOrInst);
2203
+
2196
2204
ParseDeclarator (D);
2197
2205
2206
+ if (IsTemplateSpecOrInst)
2207
+ SAC.done ();
2208
+
2198
2209
// Bail out if the first declarator didn't seem well-formed.
2199
2210
if (!D.hasName () && !D.mayOmitIdentifier ()) {
2200
2211
SkipMalformedDecl ();
@@ -2262,15 +2273,54 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
2262
2273
// need to handle the file scope definition case.
2263
2274
if (Context == DeclaratorContext::File) {
2264
2275
if (isStartOfFunctionDefinition (D)) {
2276
+ // C++23 [dcl.typedef] p1:
2277
+ // The typedef specifier shall not be [...], and it shall not be
2278
+ // used in the decl-specifier-seq of a parameter-declaration nor in
2279
+ // the decl-specifier-seq of a function-definition.
2265
2280
if (DS.getStorageClassSpec () == DeclSpec::SCS_typedef) {
2266
- Diag (Tok, diag::err_function_declared_typedef);
2267
-
2268
- // Recover by treating the 'typedef' as spurious.
2281
+ // If the user intended to write 'typename', we should have already
2282
+ // suggested adding it elsewhere. In any case, recover by ignoring
2283
+ // 'typedef' and suggest removing it.
2284
+ Diag (DS.getStorageClassSpecLoc (),
2285
+ diag::err_function_declared_typedef)
2286
+ << FixItHint::CreateRemoval (DS.getStorageClassSpecLoc ());
2269
2287
DS.ClearStorageClassSpecs ();
2270
2288
}
2289
+ Decl *TheDecl = nullptr ;
2290
+
2291
+ if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
2292
+ if (D.getName ().getKind () != UnqualifiedIdKind::IK_TemplateId) {
2293
+ // If the declarator-id is not a template-id, issue a diagnostic
2294
+ // and recover by ignoring the 'template' keyword.
2295
+ Diag (Tok, diag::err_template_defn_explicit_instantiation) << 0 ;
2296
+ TheDecl = ParseFunctionDefinition (D, ParsedTemplateInfo (),
2297
+ &LateParsedAttrs);
2298
+ } else {
2299
+ SourceLocation LAngleLoc =
2300
+ PP.getLocForEndOfToken (TemplateInfo.TemplateLoc );
2301
+ Diag (D.getIdentifierLoc (),
2302
+ diag::err_explicit_instantiation_with_definition)
2303
+ << SourceRange (TemplateInfo.TemplateLoc )
2304
+ << FixItHint::CreateInsertion (LAngleLoc, " <>" );
2305
+
2306
+ // Recover as if it were an explicit specialization.
2307
+ TemplateParameterLists FakedParamLists;
2308
+ FakedParamLists.push_back (Actions.ActOnTemplateParameterList (
2309
+ 0 , SourceLocation (), TemplateInfo.TemplateLoc , LAngleLoc,
2310
+ std::nullopt, LAngleLoc, nullptr ));
2311
+
2312
+ TheDecl = ParseFunctionDefinition (
2313
+ D,
2314
+ ParsedTemplateInfo (&FakedParamLists,
2315
+ /* isSpecialization=*/ true ,
2316
+ /* lastParameterListWasEmpty=*/ true ),
2317
+ &LateParsedAttrs);
2318
+ }
2319
+ } else {
2320
+ TheDecl =
2321
+ ParseFunctionDefinition (D, TemplateInfo, &LateParsedAttrs);
2322
+ }
2271
2323
2272
- Decl *TheDecl = ParseFunctionDefinition (D, ParsedTemplateInfo (),
2273
- &LateParsedAttrs);
2274
2324
return Actions.ConvertDeclToDeclGroup (TheDecl);
2275
2325
}
2276
2326
@@ -2360,8 +2410,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
2360
2410
}
2361
2411
2362
2412
SmallVector<Decl *, 8 > DeclsInGroup;
2363
- Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes (
2364
- D, ParsedTemplateInfo () , FRI);
2413
+ Decl *FirstDecl =
2414
+ ParseDeclarationAfterDeclaratorAndAttributes ( D, TemplateInfo , FRI);
2365
2415
if (LateParsedAttrs.size () > 0 )
2366
2416
ParseLexedAttributeList (LateParsedAttrs, FirstDecl, true , false );
2367
2417
D.complete (FirstDecl);
@@ -2384,6 +2434,16 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
2384
2434
break ;
2385
2435
}
2386
2436
2437
+ // C++23 [temp.pre]p5:
2438
+ // In a template-declaration, explicit specialization, or explicit
2439
+ // instantiation the init-declarator-list in the declaration shall
2440
+ // contain at most one declarator.
2441
+ if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
2442
+ D.isFirstDeclarator ()) {
2443
+ Diag (CommaLoc, diag::err_multiple_template_declarators)
2444
+ << TemplateInfo.Kind ;
2445
+ }
2446
+
2387
2447
// Parse the next declarator.
2388
2448
D.clear ();
2389
2449
D.setCommaLoc (CommaLoc);
@@ -2413,7 +2473,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
2413
2473
// declarator requires-clause
2414
2474
if (Tok.is (tok::kw_requires))
2415
2475
ParseTrailingRequiresClause (D);
2416
- Decl *ThisDecl = ParseDeclarationAfterDeclarator (D);
2476
+ Decl *ThisDecl = ParseDeclarationAfterDeclarator (D, TemplateInfo );
2417
2477
D.complete (ThisDecl);
2418
2478
if (ThisDecl)
2419
2479
DeclsInGroup.push_back (ThisDecl);
@@ -6526,6 +6586,17 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
6526
6586
/* ObjectHasErrors=*/ false , EnteringContext);
6527
6587
}
6528
6588
6589
+ // C++23 [basic.scope.namespace]p1:
6590
+ // For each non-friend redeclaration or specialization whose target scope
6591
+ // is or is contained by the scope, the portion after the declarator-id,
6592
+ // class-head-name, or enum-head-name is also included in the scope.
6593
+ // C++23 [basic.scope.class]p1:
6594
+ // For each non-friend redeclaration or specialization whose target scope
6595
+ // is or is contained by the scope, the portion after the declarator-id,
6596
+ // class-head-name, or enum-head-name is also included in the scope.
6597
+ //
6598
+ // FIXME: We should not be doing this for friend declarations; they have
6599
+ // their own special lookup semantics specified by [basic.lookup.unqual]p6.
6529
6600
if (D.getCXXScopeSpec ().isValid ()) {
6530
6601
if (Actions.ShouldEnterDeclaratorScope (getCurScope (),
6531
6602
D.getCXXScopeSpec ()))
0 commit comments