I'm not too happy with DiagnoseMisplacedEllipsis but it's still better than
having it in two places. The rest should be good.
http://reviews.llvm.org/D3604
Files:
include/clang/Parse/Parser.h
include/clang/Sema/Sema.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseTemplate.cpp
lib/Sema/SemaTemplate.cpp
test/FixIt/fixit-cxx0x.cpp
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -2371,6 +2371,8 @@
Decl *ParseTypeParameter(unsigned Depth, unsigned Position);
Decl *ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
Decl *ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
+ void DiagnoseMisplacedEllipsis(SourceLocation EllipsisLoc,
+ SourceLocation CorrectLoc, Declarator *D);
// C++ 14.3: Template arguments [temp.arg]
typedef SmallVector<ParsedTemplateArgument, 16> TemplateArgList;
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -5174,7 +5174,7 @@
void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl);
- Decl *ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
+ Decl *ActOnTypeParameter(Scope *S, bool Typename,
SourceLocation EllipsisLoc,
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp
+++ lib/Parse/ParseDecl.cpp
@@ -4661,19 +4661,6 @@
}
}
-static void diagnoseMisplacedEllipsis(Parser &P, Declarator &D,
- SourceLocation EllipsisLoc) {
- if (EllipsisLoc.isValid()) {
- FixItHint Insertion;
- if (!D.getEllipsisLoc().isValid()) {
- Insertion = FixItHint::CreateInsertion(D.getIdentifierLoc(), "...");
- D.setEllipsisLoc(EllipsisLoc);
- }
- P.Diag(EllipsisLoc, diag::err_misplaced_ellipsis_in_declaration)
- << FixItHint::CreateRemoval(EllipsisLoc) << Insertion << !D.hasName();
- }
-}
-
/// ParseDirectDeclarator
/// direct-declarator: [C99 6.7.5]
/// [C99] identifier
@@ -4753,7 +4740,7 @@
// The ellipsis was put in the wrong place. Recover, and explain to
// the user what they should have done.
ParseDeclarator(D);
- diagnoseMisplacedEllipsis(*this, D, EllipsisLoc);
+ DiagnoseMisplacedEllipsis(EllipsisLoc, D.getIdentifierLoc(), &D);
return;
} else
D.setEllipsisLoc(EllipsisLoc);
@@ -5003,8 +4990,7 @@
D.setGroupingParens(hadGroupingParens);
// An ellipsis cannot be placed outside parentheses.
- if (EllipsisLoc.isValid())
- diagnoseMisplacedEllipsis(*this, D, EllipsisLoc);
+ DiagnoseMisplacedEllipsis(EllipsisLoc, D.getIdentifierLoc(), &D);
return;
}
Index: lib/Parse/ParseTemplate.cpp
===================================================================
--- lib/Parse/ParseTemplate.cpp
+++ lib/Parse/ParseTemplate.cpp
@@ -498,6 +498,10 @@
return nullptr;
}
+ // Recover from misplaced ellipsis.
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
+ DiagnoseMisplacedEllipsis(EllipsisLoc, NameLoc, nullptr);
+
// Grab a default argument (if available).
// Per C++0x [basic.scope.pdecl]p9, we parse the default argument before
// we introduce the type parameter into the local scope.
@@ -507,9 +511,9 @@
DefaultArg = ParseTypeName(/*Range=*/nullptr,
Declarator::TemplateTypeArgContext).get();
- return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, Ellipsis,
- EllipsisLoc, KeyLoc, ParamName, NameLoc,
- Depth, Position, EqualLoc, DefaultArg);
+ return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, EllipsisLoc,
+ KeyLoc, ParamName, NameLoc, Depth, Position,
+ EqualLoc, DefaultArg);
}
/// ParseTemplateTemplateParameter - Handle the parsing of template
@@ -579,6 +583,10 @@
return nullptr;
}
+ // Recover from misplaced ellipsis.
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
+ DiagnoseMisplacedEllipsis(EllipsisLoc, NameLoc, nullptr);
+
TemplateParameterList *ParamList =
Actions.ActOnTemplateParameterList(Depth, SourceLocation(),
TemplateLoc, LAngleLoc,
@@ -629,6 +637,12 @@
return nullptr;
}
+ // Recover from misplaced ellipsis.
+ SourceLocation EllipsisLoc;
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
+ DiagnoseMisplacedEllipsis(EllipsisLoc, ParamDecl.getIdentifierLoc(),
+ &ParamDecl);
+
// If there is a default value, parse it.
// Per C++0x [basic.scope.pdecl]p9, we parse the default argument before
// we introduce the template parameter into the local scope.
@@ -654,6 +668,23 @@
DefaultArg.get());
}
+void Parser::DiagnoseMisplacedEllipsis(SourceLocation EllipsisLoc,
+ SourceLocation CorrectLoc,
+ Declarator *D) {
+ if (EllipsisLoc.isValid()) {
+ FixItHint Insertion;
+ if (D && D->getEllipsisLoc().isInvalid()) {
+ Insertion = FixItHint::CreateInsertion(CorrectLoc, "...");
+ D->setEllipsisLoc(EllipsisLoc);
+ }
+ else if (!D && CorrectLoc.isValid())
+ Insertion = FixItHint::CreateInsertion(CorrectLoc, "...");
+ Diag(EllipsisLoc, diag::err_misplaced_ellipsis_in_declaration)
+ << FixItHint::CreateRemoval(EllipsisLoc) << Insertion
+ << (D && !D->hasName());
+ }
+}
+
/// \brief Parses a '>' at the end of a template list.
///
/// If this function encounters '>>', '>>>', '>=', or '>>=', it tries
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -544,7 +544,7 @@
/// ParamNameLoc is the location of the parameter name (if any).
/// If the type parameter has a default argument, it will be added
/// later via ActOnTypeParameterDefault.
-Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
+Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename,
SourceLocation EllipsisLoc,
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
@@ -560,10 +560,11 @@
if (!ParamName)
Loc = KeyLoc;
+ bool IsParameterPack = EllipsisLoc.isValid();
TemplateTypeParmDecl *Param
= TemplateTypeParmDecl::Create(Context, Context.getTranslationUnitDecl(),
KeyLoc, Loc, Depth, Position, ParamName,
- Typename, Ellipsis);
+ Typename, IsParameterPack);
Param->setAccess(AS_public);
if (Invalid)
Param->setInvalidDecl();
@@ -579,7 +580,7 @@
// C++0x [temp.param]p9:
// A default template-argument may be specified for any kind of
// template-parameter that is not a template parameter pack.
- if (DefaultArg && Ellipsis) {
+ if (DefaultArg && IsParameterPack) {
Diag(EqualLoc, diag::err_template_param_pack_default_arg);
DefaultArg = ParsedType();
}
Index: test/FixIt/fixit-cxx0x.cpp
===================================================================
--- test/FixIt/fixit-cxx0x.cpp
+++ test/FixIt/fixit-cxx0x.cpp
@@ -138,3 +138,14 @@
register int n; // expected-warning {{'register' storage class specifier is deprecated}}
return n;
}
+
+namespace MissplacedParameterPack {
+ template <typename Args...> // expected-error {{'...' must immediately precede declared identifier}}
+ void typeParameter(Args...);
+
+ template <template <typename> class Args...> // expected-error {{'...' must immediately precede declared identifier}}
+ void templateTypeParameter(Args<int>...);
+
+ template <int N...> // expected-error {{'...' must immediately precede declared identifier}}
+ void nonTypeTemplateParameter();
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits