Skip to content

Commit c08f489

Browse files
committed
In Parser::ParseClassSpecifier, don't conflate a NULL declaration with
failure to perform a declaration. Instead, explicitly note semantic failures that occur during template parsing with a DeclResult. Fixes PR3872. llvm-svn: 67659
1 parent 1e7602a commit c08f489

File tree

4 files changed

+35
-36
lines changed

4 files changed

+35
-36
lines changed

clang/include/clang/Parse/Action.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class Action : public ActionBase {
8585
typedef ActionResult<2> TypeResult;
8686
typedef ActionResult<3> BaseResult;
8787
typedef ActionResult<4> MemInitResult;
88+
typedef ActionResult<5> DeclResult;
8889

8990
/// Same, but with ownership.
9091
typedef ASTOwningResult<&ActionBase::DeleteExpr> OwningExprResult;
@@ -1169,7 +1170,7 @@ class Action : public ActionBase {
11691170

11701171
/// \brief Process the declaration or definition of a class template
11711172
/// with the given template parameter lists.
1172-
virtual DeclTy *
1173+
virtual DeclResult
11731174
ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
11741175
SourceLocation KWLoc, const CXXScopeSpec &SS,
11751176
IdentifierInfo *Name, SourceLocation NameLoc,
@@ -1247,7 +1248,7 @@ class Action : public ActionBase {
12471248
/// common for users to provide the wrong number of template
12481249
/// parameter lists (such as a missing \c template<> prior to a
12491250
/// specialization); the parser does not check this condition.
1250-
virtual DeclTy *
1251+
virtual DeclResult
12511252
ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
12521253
SourceLocation KWLoc,
12531254
const CXXScopeSpec &SS,

clang/lib/Parse/ParseDeclCXX.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -431,15 +431,15 @@ void Parser::ParseClassSpecifier(DeclSpec &DS,
431431
}
432432

433433
// Create the tag portion of the class or class template.
434-
DeclTy *TagOrTempDecl;
434+
Action::DeclResult TagOrTempResult;
435435
if (TemplateId && TK != Action::TK_Reference) {
436436
// Explicit specialization or class template partial
437437
// specialization. Let semantic analysis decide.
438438
ASTTemplateArgsPtr TemplateArgsPtr(Actions,
439439
TemplateId->getTemplateArgs(),
440440
TemplateId->getTemplateArgIsType(),
441441
TemplateId->NumArgs);
442-
TagOrTempDecl
442+
TagOrTempResult
443443
= Actions.ActOnClassTemplateSpecialization(CurScope, TagType, TK,
444444
StartLoc, SS,
445445
TemplateId->Template,
@@ -454,35 +454,37 @@ void Parser::ParseClassSpecifier(DeclSpec &DS,
454454
TemplateParams? TemplateParams->size() : 0));
455455
TemplateId->Destroy();
456456
} else if (TemplateParams && TK != Action::TK_Reference)
457-
TagOrTempDecl = Actions.ActOnClassTemplate(CurScope, TagType, TK, StartLoc,
458-
SS, Name, NameLoc, Attr,
457+
TagOrTempResult = Actions.ActOnClassTemplate(CurScope, TagType, TK,
458+
StartLoc, SS, Name, NameLoc,
459+
Attr,
459460
Action::MultiTemplateParamsArg(Actions,
460461
&(*TemplateParams)[0],
461462
TemplateParams->size()));
462463
else
463-
TagOrTempDecl = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, SS, Name,
464+
TagOrTempResult = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, SS, Name,
464465
NameLoc, Attr);
465466

466467
// Parse the optional base clause (C++ only).
467468
if (getLang().CPlusPlus && Tok.is(tok::colon))
468-
ParseBaseClause(TagOrTempDecl);
469+
ParseBaseClause(TagOrTempResult.get());
469470

470471
// If there is a body, parse it and inform the actions module.
471472
if (Tok.is(tok::l_brace))
472473
if (getLang().CPlusPlus)
473-
ParseCXXMemberSpecification(StartLoc, TagType, TagOrTempDecl);
474+
ParseCXXMemberSpecification(StartLoc, TagType, TagOrTempResult.get());
474475
else
475-
ParseStructUnionBody(StartLoc, TagType, TagOrTempDecl);
476+
ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get());
476477
else if (TK == Action::TK_Definition) {
477478
// FIXME: Complain that we have a base-specifier list but no
478479
// definition.
479480
Diag(Tok, diag::err_expected_lbrace);
480481
}
481482

482483
const char *PrevSpec = 0;
483-
if (!TagOrTempDecl)
484+
if (TagOrTempResult.isInvalid())
484485
DS.SetTypeSpecError();
485-
else if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, TagOrTempDecl))
486+
else if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec,
487+
TagOrTempResult.get()))
486488
Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
487489
}
488490

clang/lib/Sema/Sema.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1704,7 +1704,7 @@ class Sema : public Action {
17041704
bool CheckTemplateParameterList(TemplateParameterList *NewParams,
17051705
TemplateParameterList *OldParams);
17061706

1707-
virtual DeclTy *
1707+
virtual DeclResult
17081708
ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
17091709
SourceLocation KWLoc, const CXXScopeSpec &SS,
17101710
IdentifierInfo *Name, SourceLocation NameLoc,
@@ -1731,7 +1731,7 @@ class Sema : public Action {
17311731
SourceLocation TemplateNameLoc,
17321732
SourceRange ScopeSpecifierRange);
17331733

1734-
virtual DeclTy *
1734+
virtual DeclResult
17351735
ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
17361736
SourceLocation KWLoc,
17371737
const CXXScopeSpec &SS,

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ Sema::ActOnTemplateParameterList(unsigned Depth,
361361
(Decl**)Params, NumParams, RAngleLoc);
362362
}
363363

364-
Sema::DeclTy *
364+
Sema::DeclResult
365365
Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
366366
SourceLocation KWLoc, const CXXScopeSpec &SS,
367367
IdentifierInfo *Name, SourceLocation NameLoc,
@@ -373,7 +373,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
373373

374374
// Check that we can declare a template here.
375375
if (CheckTemplateDeclScope(S, TemplateParameterLists))
376-
return 0;
376+
return true;
377377

378378
TagDecl::TagKind Kind;
379379
switch (TagSpec) {
@@ -386,7 +386,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
386386
// There is no such thing as an unnamed class template.
387387
if (!Name) {
388388
Diag(KWLoc, diag::err_template_unnamed_class);
389-
return 0;
389+
return true;
390390
}
391391

392392
// Find any previous declaration with this name.
@@ -418,7 +418,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
418418
if (!TemplateParameterListsAreEqual(TemplateParams,
419419
PrevClassTemplate->getTemplateParameters(),
420420
/*Complain=*/true))
421-
return 0;
421+
return true;
422422

423423
// C++ [temp.class]p4:
424424
// In a redeclaration, partial specialization, explicit
@@ -429,7 +429,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
429429
if (PrevRecordDecl->getTagKind() != Kind) {
430430
Diag(KWLoc, diag::err_use_with_wrong_tag) << Name;
431431
Diag(PrevRecordDecl->getLocation(), diag::note_previous_use);
432-
return 0;
432+
return true;
433433
}
434434

435435

@@ -440,7 +440,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
440440
Diag(Def->getLocation(), diag::note_previous_definition);
441441
// FIXME: Would it make sense to try to "forget" the previous
442442
// definition, as part of error recovery?
443-
return 0;
443+
return true;
444444
}
445445
}
446446
} else if (PrevDecl && PrevDecl->isTemplateParameter()) {
@@ -456,7 +456,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
456456
// in (14.5.4).
457457
Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
458458
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
459-
return 0;
459+
return true;
460460
}
461461

462462
// Check the template parameter list of this declaration, possibly
@@ -1767,7 +1767,7 @@ Sema::CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate,
17671767
return false;
17681768
}
17691769

1770-
Sema::DeclTy *
1770+
Sema::DeclResult
17711771
Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
17721772
SourceLocation KWLoc,
17731773
const CXXScopeSpec &SS,
@@ -1783,7 +1783,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
17831783
ClassTemplateDecl *ClassTemplate
17841784
= dyn_cast_or_null<ClassTemplateDecl>(static_cast<Decl *>(TemplateD));
17851785
if (!ClassTemplate)
1786-
return 0;
1786+
return true;
17871787

17881788
// Check the validity of the template headers that introduce this
17891789
// template.
@@ -1796,18 +1796,14 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
17961796
else {
17971797
TemplateParameterList *TemplateParams
17981798
= static_cast<TemplateParameterList*>(*TemplateParameterLists.get());
1799-
if (TemplateParameterLists.size() > 1) {
1800-
Diag(TemplateParams->getTemplateLoc(),
1801-
diag::err_template_spec_extra_headers);
1802-
return 0;
1803-
}
1799+
if (TemplateParameterLists.size() > 1)
1800+
return Diag(TemplateParams->getTemplateLoc(),
1801+
diag::err_template_spec_extra_headers);
18041802

1805-
if (TemplateParams->size() > 0) {
1803+
if (TemplateParams->size() > 0)
18061804
// FIXME: No support for class template partial specialization.
1807-
Diag(TemplateParams->getTemplateLoc(),
1808-
diag::unsup_template_partial_spec);
1809-
return 0;
1810-
}
1805+
return Diag(TemplateParams->getTemplateLoc(),
1806+
diag::unsup_template_partial_spec);
18111807
}
18121808

18131809
// Check that the specialization uses the same tag kind as the
@@ -1836,7 +1832,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
18361832
if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc,
18371833
&TemplateArgs[0], TemplateArgs.size(),
18381834
RAngleLoc, ConvertedTemplateArgs))
1839-
return 0;
1835+
return true;
18401836

18411837
assert((ConvertedTemplateArgs.size() ==
18421838
ClassTemplate->getTemplateParameters()->size()) &&
@@ -1858,7 +1854,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
18581854
if (CheckClassTemplateSpecializationScope(ClassTemplate, PrevDecl,
18591855
TemplateNameLoc,
18601856
SS.getRange()))
1861-
return 0;
1857+
return true;
18621858

18631859
if (PrevDecl && PrevDecl->getSpecializationKind() == TSK_Undeclared) {
18641860
// Since the only prior class template specialization with these
@@ -1902,7 +1898,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
19021898
<< Specialization << Range;
19031899
Diag(Def->getLocation(), diag::note_previous_definition);
19041900
Specialization->setInvalidDecl();
1905-
return 0;
1901+
return true;
19061902
}
19071903
}
19081904

0 commit comments

Comments
 (0)