<div dir="ltr">This patch causes <a href="http://llvm.org/PR20660">http://llvm.org/PR20660</a>. Can you take a look?<div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Aug 12, 2014 at 1:30 AM, Richard Smith <span dir="ltr"><<a href="mailto:richard-llvm@metafoo.co.uk" target="_blank">richard-llvm@metafoo.co.uk</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Mon Aug 11 18:30:23 2014<br>
New Revision: 215408<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=215408&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=215408&view=rev</a><br>
Log:<br>
Reject varargs '...' in function prototype if there are more parameters after<br>
it. Diagnose with recovery if it appears after a function parameter that was<br>
obviously supposed to be a parameter pack. Otherwise, warn if it immediately<br>
follows a function parameter pack, because the user most likely didn't intend<br>
to write a parameter pack followed by a C-style varargs ellipsis.<br>
<br>
This warning can be syntactically disabled by using ", ..." instead of "...".<br>
<br>
Modified:<br>
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td<br>
cfe/trunk/include/clang/Sema/Sema.h<br>
cfe/trunk/lib/Parse/ParseDecl.cpp<br>
cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp<br>
cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp<br>
cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp<br>
cfe/trunk/test/Parser/cxx-variadic-func.cpp<br>
cfe/trunk/test/Parser/cxx11-templates.cpp<br>
cfe/trunk/test/SemaCXX/issue547.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=215408&r1=215407&r2=215408&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=215408&r1=215407&r2=215408&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Mon Aug 11 18:30:23 2014<br>
@@ -503,6 +503,17 @@ def note_bracket_depth : Note<<br>
def err_misplaced_ellipsis_in_declaration : Error<<br>
"'...' must %select{immediately precede declared identifier|"<br>
"be innermost component of anonymous pack declaration}0">;<br>
+def warn_misplaced_ellipsis_vararg : Warning<<br>
+ "'...' in this location creates a C-style varargs function"<br>
+ "%select{, not a function parameter pack|}0">,<br>
+ InGroup<DiagGroup<"ambiguous-ellipsis">>;<br>
+def note_misplaced_ellipsis_vararg_existing_ellipsis : Note<<br>
+ "preceding '...' declares a function parameter pack">;<br>
+def note_misplaced_ellipsis_vararg_add_ellipsis : Note<<br>
+ "place '...' %select{immediately before declared identifier|here}0 "<br>
+ "to declare a function parameter pack">;<br>
+def note_misplaced_ellipsis_vararg_add_comma : Note<<br>
+ "insert ',' before '...' to silence this warning">;<br>
def ext_abstract_pack_declarator_parens : ExtWarn<<br>
"ISO C++11 requires a parenthesized pack declaration to have a name">,<br>
InGroup<DiagGroup<"anonymous-pack-parens">>;<br>
<br>
Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=215408&r1=215407&r2=215408&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=215408&r1=215407&r2=215408&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Aug 11 18:30:23 2014<br>
@@ -5585,6 +5585,10 @@ public:<br>
// C++ Variadic Templates (C++0x [temp.variadic])<br>
//===--------------------------------------------------------------------===//<br>
<br>
+ /// Determine whether an unexpanded parameter pack might be permitted in this<br>
+ /// location. Useful for error recovery.<br>
+ bool isUnexpandedParameterPackPermitted();<br>
+<br>
/// \brief The context in which an unexpanded parameter pack is<br>
/// being diagnosed.<br>
///<br>
<br>
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=215408&r1=215407&r2=215408&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=215408&r1=215407&r2=215408&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)<br>
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Aug 11 18:30:23 2014<br>
@@ -5426,6 +5426,15 @@ void Parser::ParseParameterDeclarationCl<br>
// Otherwise, we have something. Add it and let semantic analysis try<br>
// to grok it and add the result to the ParamInfo we are building.<br>
<br>
+ // Last chance to recover from a misplaced ellipsis in an attempted<br>
+ // parameter pack declaration.<br>
+ if (Tok.is(tok::ellipsis) &&<br>
+ (NextToken().isNot(tok::r_paren) ||<br>
+ (!ParmDeclarator.getEllipsisLoc().isValid() &&<br>
+ !Actions.isUnexpandedParameterPackPermitted())) &&<br>
+ Actions.containsUnexpandedParameterPacks(ParmDeclarator))<br>
+ DiagnoseMisplacedEllipsisInDeclarator(ConsumeToken(), ParmDeclarator);<br>
+<br>
// Inform the actions module about the parameter declarator, so it gets<br>
// added to the current scope.<br>
Decl *Param = Actions.ActOnParamDeclarator(getCurScope(),<br>
@@ -5492,12 +5501,34 @@ void Parser::ParseParameterDeclarationCl<br>
Param, DefArgToks));<br>
}<br>
<br>
- if (TryConsumeToken(tok::ellipsis, EllipsisLoc) &&<br>
- !getLangOpts().CPlusPlus) {<br>
- // We have ellipsis without a preceding ',', which is ill-formed<br>
- // in C. Complain and provide the fix.<br>
- Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis)<br>
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) {<br>
+ if (!getLangOpts().CPlusPlus) {<br>
+ // We have ellipsis without a preceding ',', which is ill-formed<br>
+ // in C. Complain and provide the fix.<br>
+ Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis)<br>
+ << FixItHint::CreateInsertion(EllipsisLoc, ", ");<br>
+ } else if (ParmDeclarator.getEllipsisLoc().isValid() ||<br>
+ Actions.containsUnexpandedParameterPacks(ParmDeclarator)) {<br>
+ // It looks like this was supposed to be a parameter pack. Warn and<br>
+ // point out where the ellipsis should have gone.<br>
+ SourceLocation ParmEllipsis = ParmDeclarator.getEllipsisLoc();<br>
+ Diag(EllipsisLoc, diag::warn_misplaced_ellipsis_vararg)<br>
+ << ParmEllipsis.isValid() << ParmEllipsis;<br>
+ if (ParmEllipsis.isValid()) {<br>
+ Diag(ParmEllipsis,<br>
+ diag::note_misplaced_ellipsis_vararg_existing_ellipsis);<br>
+ } else {<br>
+ Diag(ParmDeclarator.getIdentifierLoc(),<br>
+ diag::note_misplaced_ellipsis_vararg_add_ellipsis)<br>
+ << FixItHint::CreateInsertion(ParmDeclarator.getIdentifierLoc(),<br>
+ "...")<br>
+ << !ParmDeclarator.hasName();<br>
+ }<br>
+ Diag(EllipsisLoc, diag::note_misplaced_ellipsis_vararg_add_comma)<br>
<< FixItHint::CreateInsertion(EllipsisLoc, ", ");<br>
+ }<br>
+<br>
+ // We can't have any more parameters after an ellipsis.<br>
break;<br>
}<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=215408&r1=215407&r2=215408&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=215408&r1=215407&r2=215408&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Mon Aug 11 18:30:23 2014<br>
@@ -197,6 +197,20 @@ namespace {<br>
};<br>
}<br>
<br>
+/// \brief Determine whether it's possible for an unexpanded parameter pack to<br>
+/// be valid in this location. This only happens when we're in a declaration<br>
+/// that is nested within an expression that could be expanded, such as a<br>
+/// lambda-expression within a function call.<br>
+///<br>
+/// This is conservatively correct, but may claim that some unexpanded packs are<br>
+/// permitted when they are not.<br>
+bool Sema::isUnexpandedParameterPackPermitted() {<br>
+ for (auto *SI : FunctionScopes)<br>
+ if (isa<sema::LambdaScopeInfo>(SI))<br>
+ return true;<br>
+ return false;<br>
+}<br>
+<br>
/// \brief Diagnose all of the unexpanded parameter packs in the given<br>
/// vector.<br>
bool<br>
<br>
Modified: cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp?rev=215408&r1=215407&r2=215408&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp?rev=215408&r1=215407&r2=215408&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp (original)<br>
+++ cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp Mon Aug 11 18:30:23 2014<br>
@@ -1,5 +1,4 @@<br>
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s<br>
-// expected-no-diagnostics<br>
<br>
template<typename T> struct identity;<br>
template<typename ...Types> struct tuple;<br>
@@ -22,7 +21,7 @@ template<typename T> struct is_same<T, T<br>
template<typename T, typename ...Types><br>
struct X0 {<br>
typedef identity<T(Types...)> function_pack_1;<br>
- typedef identity<T(Types......)> variadic_function_pack_1;<br>
+ typedef identity<T(Types......)> variadic_function_pack_1; // expected-warning {{varargs}} expected-note {{pack}} expected-note {{insert ','}}<br>
typedef identity<T(T...)> variadic_1;<br>
typedef tuple<T(Types, ...)...> template_arg_expansion_1;<br>
};<br>
<br>
Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp?rev=215408&r1=215407&r2=215408&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp?rev=215408&r1=215407&r2=215408&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp (original)<br>
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp Mon Aug 11 18:30:23 2014<br>
@@ -243,7 +243,7 @@ namespace FunctionTypes {<br>
};<br>
<br>
template<typename R, typename ...Types><br>
- struct Arity<R(Types......)> {<br>
+ struct Arity<R(Types......)> { // expected-warning {{varargs}} expected-note {{pack}} expected-note {{insert ','}}<br>
static const unsigned value = sizeof...(Types);<br>
};<br>
<br>
<br>
Modified: cfe/trunk/test/Parser/cxx-variadic-func.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-variadic-func.cpp?rev=215408&r1=215407&r2=215408&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-variadic-func.cpp?rev=215408&r1=215407&r2=215408&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Parser/cxx-variadic-func.cpp (original)<br>
+++ cfe/trunk/test/Parser/cxx-variadic-func.cpp Mon Aug 11 18:30:23 2014<br>
@@ -1,5 +1,8 @@<br>
-// RUN: %clang_cc1 -fsyntax-only %s<br>
+// RUN: %clang_cc1 -fsyntax-only -verify %s<br>
<br>
void f(...) {<br>
- int g(int(...));<br>
+ // FIXME: There's no disambiguation here; this is unambiguous.<br>
+ int g(int(...)); // expected-warning {{disambiguated}} expected-note {{paren}}<br>
}<br>
+<br>
+void h(int n..., int m); // expected-error {{expected ')'}} expected-note {{to match}}<br>
<br>
Modified: cfe/trunk/test/Parser/cxx11-templates.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx11-templates.cpp?rev=215408&r1=215407&r2=215408&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx11-templates.cpp?rev=215408&r1=215407&r2=215408&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Parser/cxx11-templates.cpp (original)<br>
+++ cfe/trunk/test/Parser/cxx11-templates.cpp Mon Aug 11 18:30:23 2014<br>
@@ -7,3 +7,40 @@ struct S {<br>
<br>
template <typename Ty = char><br>
static_assert(sizeof(Ty) != 1, "Not a char"); // expected-error {{a static_assert declaration cannot be a template}}<br>
+<br>
+namespace Ellipsis {<br>
+ template<typename ...T> void f(T t..., int n); // expected-error {{must immediately precede declared identifier}}<br>
+ template<typename ...T> void f(int n, T t...); // expected-error {{must immediately precede declared identifier}}<br>
+ template<typename ...T> void f(int n, T t, ...); // expected-error {{unexpanded parameter pack}}<br>
+ template<typename ...T> void f() {<br>
+ f([]{<br>
+ void g(T<br>
+ t // expected-note {{place '...' immediately before declared identifier to declare a function parameter pack}}<br>
+ ... // expected-warning {{'...' in this location creates a C-style varargs function, not a function parameter pack}}<br>
+ // expected-note@-1 {{insert ',' before '...' to silence this warning}}<br>
+ );<br>
+ void h(T (&<br>
+ ) // expected-note {{place '...' here to declare a function parameter pack}}<br>
+ ... // expected-warning {{'...' in this location creates a C-style varargs function, not a function parameter pack}}<br>
+ // expected-note@-1 {{insert ',' before '...' to silence this warning}}<br>
+ );<br>
+ void i(T (&), ...);<br>
+ }...);<br>
+ }<br>
+ template<typename ...T> struct S {<br>
+ void f(T t...); // expected-error {{must immediately precede declared identifier}}<br>
+ void f(T ... // expected-note {{preceding '...' declares a function parameter pack}}<br>
+ t...); // expected-warning-re {{'...' in this location creates a C-style varargs function{{$}}}}<br>
+ // expected-note@-1 {{insert ',' before '...' to silence this warning}}<br>
+ };<br>
+<br>
+ // FIXME: We should just issue a single error in this case pointing out where<br>
+ // the '...' goes. It's tricky to recover correctly in this case, though,<br>
+ // because the parameter is in scope in the default argument, so must be<br>
+ // passed to Sema before we reach the ellipsis.<br>
+ template<typename...T> void f(T n = 1 ...);<br>
+ // expected-warning@-1 {{creates a C-style varargs}}<br>
+ // expected-note@-2 {{place '...' immediately before declared identifier}}<br>
+ // expected-note@-3 {{insert ','}}<br>
+ // expected-error@-4 {{unexpanded parameter pack}}<br>
+}<br>
<br>
Modified: cfe/trunk/test/SemaCXX/issue547.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/issue547.cpp?rev=215408&r1=215407&r2=215408&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/issue547.cpp?rev=215408&r1=215407&r2=215408&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/issue547.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/issue547.cpp Mon Aug 11 18:30:23 2014<br>
@@ -27,32 +27,32 @@ struct classify_function<R(Args...) cons<br>
};<br>
<br>
template<typename R, typename ...Args><br>
-struct classify_function<R(Args......)> {<br>
+struct classify_function<R(Args..., ...)> {<br>
static const unsigned value = 5;<br>
};<br>
<br>
template<typename R, typename ...Args><br>
-struct classify_function<R(Args......) const> {<br>
+struct classify_function<R(Args..., ...) const> {<br>
static const unsigned value = 6;<br>
};<br>
<br>
template<typename R, typename ...Args><br>
-struct classify_function<R(Args......) volatile> {<br>
+struct classify_function<R(Args..., ...) volatile> {<br>
static const unsigned value = 7;<br>
};<br>
<br>
template<typename R, typename ...Args><br>
-struct classify_function<R(Args......) const volatile> {<br>
+struct classify_function<R(Args..., ...) const volatile> {<br>
static const unsigned value = 8;<br>
};<br>
<br>
template<typename R, typename ...Args><br>
-struct classify_function<R(Args......) &&> {<br>
+struct classify_function<R(Args..., ...) &&> {<br>
static const unsigned value = 9;<br>
};<br>
<br>
template<typename R, typename ...Args><br>
-struct classify_function<R(Args......) const &> {<br>
+struct classify_function<R(Args..., ...) const &> {<br>
static const unsigned value = 10;<br>
};<br>
<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><div><br></div>
</div></div>