[cfe-commits] r153622 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td lib/Parse/ParseDecl.cpp test/FixIt/fixit-cxx0x.cpp
Richard Smith
richard-llvm at metafoo.co.uk
Wed Mar 28 18:16:42 PDT 2012
Author: rsmith
Date: Wed Mar 28 20:16:42 2012
New Revision: 153622
URL: http://llvm.org/viewvc/llvm-project?rev=153622&view=rev
Log:
Reject 'template<typename...Ts> void f(Ts ...(x));'. Add a special-case
diagnostic and a fix-it to explain to the user where the ellipsis is
supposed to go.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/test/FixIt/fixit-cxx0x.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=153622&r1=153621&r2=153622&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Wed Mar 28 20:16:42 2012
@@ -428,6 +428,9 @@
"unexpected end of default argument expression">;
def err_parser_impl_limit_overflow : Error<
"parser recursion limit reached, program too complex">, DefaultFatal;
+def err_misplaced_ellipsis_in_declaration : Error<
+ "'...' must %select{immediately precede declared identifier|"
+ "be innermost component of anonymous pack declaration}0">;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=153622&r1=153621&r2=153622&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed Mar 28 20:16:42 2012
@@ -3540,6 +3540,17 @@
ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
}
+static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang) {
+ if (Kind == tok::star || Kind == tok::caret)
+ return true;
+
+ // We parse rvalue refs in C++03, because otherwise the errors are scary.
+ if (!Lang.CPlusPlus)
+ return false;
+
+ return Kind == tok::amp || Kind == tok::ampamp;
+}
+
/// ParseDeclaratorInternal - Parse a C or C++ declarator. The direct-declarator
/// is parsed by the function passed to it. Pass null, and the direct-declarator
/// isn't parsed at all, making this function effectively parse the C++
@@ -3611,10 +3622,7 @@
tok::TokenKind Kind = Tok.getKind();
// Not a pointer, C++ reference, or block.
- if (Kind != tok::star && Kind != tok::caret &&
- (Kind != tok::amp || !getLangOpts().CPlusPlus) &&
- // We parse rvalue refs in C++03, because otherwise the errors are scary.
- (Kind != tok::ampamp || !getLangOpts().CPlusPlus)) {
+ if (!isPtrOperatorToken(Kind, getLangOpts())) {
if (DirectDeclParser)
(this->*DirectDeclParser)(D);
return;
@@ -3706,6 +3714,19 @@
}
}
+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
@@ -3767,13 +3788,26 @@
// abstract-declarator if the type of the parameter names a template
// parameter pack that has not been expanded; otherwise, it is parsed
// as part of the parameter-declaration-clause.
- if (Tok.is(tok::ellipsis) &&
+ if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() &&
!((D.getContext() == Declarator::PrototypeContext ||
D.getContext() == Declarator::BlockLiteralContext) &&
NextToken().is(tok::r_paren) &&
- !Actions.containsUnexpandedParameterPacks(D)))
- D.setEllipsisLoc(ConsumeToken());
-
+ !Actions.containsUnexpandedParameterPacks(D))) {
+ SourceLocation EllipsisLoc = ConsumeToken();
+ if (isPtrOperatorToken(Tok.getKind(), getLangOpts())) {
+ // 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);
+ return;
+ } else
+ D.setEllipsisLoc(EllipsisLoc);
+
+ // The ellipsis can't be followed by a parenthesized declarator. We
+ // check for that in ParseParenDeclarator, after we have disambiguated
+ // the l_paren token.
+ }
+
if (Tok.is(tok::identifier) || Tok.is(tok::kw_operator) ||
Tok.is(tok::annot_template_id) || Tok.is(tok::tilde)) {
// We found something that indicates the start of an unqualified-id.
@@ -3818,7 +3852,7 @@
ConsumeToken();
goto PastIdentifier;
}
-
+
if (Tok.is(tok::l_paren)) {
// direct-declarator: '(' declarator ')'
// direct-declarator: '(' attributes declarator ')'
@@ -3830,7 +3864,7 @@
// the scope already. Re-enter the scope, if we need to.
if (D.getCXXScopeSpec().isSet()) {
// If there was an error parsing parenthesized declarator, declarator
- // scope may have been enterred before. Don't do it again.
+ // scope may have been entered before. Don't do it again.
if (!D.isInvalidType() &&
Actions.ShouldEnterDeclaratorScope(getCurScope(), D.getCXXScopeSpec()))
// Change the declaration context for name lookup, until this function
@@ -3965,9 +3999,11 @@
// direct-declarator: '(' declarator ')'
// direct-declarator: '(' attributes declarator ')'
if (isGrouping) {
+ SourceLocation EllipsisLoc = D.getEllipsisLoc();
+ D.setEllipsisLoc(SourceLocation());
+
bool hadGroupingParens = D.hasGroupingParens();
D.setGroupingParens(true);
-
ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
// Match the ')'.
T.consumeClose();
@@ -3976,6 +4012,11 @@
attrs, T.getCloseLocation());
D.setGroupingParens(hadGroupingParens);
+
+ // An ellipsis cannot be placed outside parentheses.
+ if (EllipsisLoc.isValid())
+ diagnoseMisplacedEllipsis(*this, D, EllipsisLoc);
+
return;
}
Modified: cfe/trunk/test/FixIt/fixit-cxx0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-cxx0x.cpp?rev=153622&r1=153621&r2=153622&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/fixit-cxx0x.cpp (original)
+++ cfe/trunk/test/FixIt/fixit-cxx0x.cpp Wed Mar 28 20:16:42 2012
@@ -77,3 +77,26 @@
'c'_z;
'd'_whoops;
}
+
+template<typename ...Ts> struct MisplacedEllipsis {
+ int a(Ts ...(x)); // expected-error {{'...' must immediately precede declared identifier}}
+ int b(Ts ...&x); // expected-error {{'...' must immediately precede declared identifier}}
+ int c(Ts ...&); // expected-error {{'...' must be innermost component of anonymous pack declaration}}
+ int d(Ts ...(...&...)); // expected-error 2{{'...' must be innermost component of anonymous pack declaration}}
+ int e(Ts ...*[]); // expected-error {{'...' must be innermost component of anonymous pack declaration}}
+ int f(Ts ...(...*)()); // expected-error 2{{'...' must be innermost component of anonymous pack declaration}}
+ int g(Ts ...()); // ok
+};
+namespace TestMisplacedEllipsisRecovery {
+ MisplacedEllipsis<int, char> me;
+ int i; char k;
+ int *ip; char *kp;
+ int ifn(); char kfn();
+ int a = me.a(i, k);
+ int b = me.b(i, k);
+ int c = me.c(i, k);
+ int d = me.d(i, k);
+ int e = me.e(&ip, &kp);
+ int f = me.f(ifn, kfn);
+ int g = me.g(ifn, kfn);
+}
More information about the cfe-commits
mailing list