r224906 - Don't crash on surprising tokens in default parameter template lists.
Nico Weber
nicolasweber at gmx.de
Sun Dec 28 15:24:02 PST 2014
Author: nico
Date: Sun Dec 28 17:24:02 2014
New Revision: 224906
URL: http://llvm.org/viewvc/llvm-project?rev=224906&view=rev
Log:
Don't crash on surprising tokens in default parameter template lists.
Fixes this snippet from SLi's afl fuzzer output:
class {
i (x = <, enum
This parsed i as a function, x as a paramter, and the stuff after < as a
template list. This then called TryConsumeDeclarationSpecifier() which
called TryAnnotateCXXScopeToken() without checking the preconditions of
this function. Check them before calling, like all other callers of
TryAnnotateCXXScopeToken() do.
A more readable reproducer that causes the same crash is
class {
void i(int x = MyTemplateClass<int, union int>::foo());
};
The reduced version used an eof token as surprising token, but kw_int works
just as well to repro and is easier to insert into a test file.
Modified:
cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
cfe/trunk/lib/Parse/ParseTentative.cpp
cfe/trunk/test/Parser/cxx-member-initializers.cpp
Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=224906&r1=224905&r2=224906&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Sun Dec 28 17:24:02 2014
@@ -1019,7 +1019,7 @@ bool Parser::ConsumeAndStoreInitializer(
case CIK_DefaultArgument:
bool InvalidAsDeclaration = false;
Result = TryParseParameterDeclarationClause(
- &InvalidAsDeclaration, /*VersusTemplateArgument*/true);
+ &InvalidAsDeclaration, /*VersusTemplateArgument=*/true);
// If this is an expression or a declaration with a missing
// 'typename', assume it's not a declaration.
if (Result == TPResult::Ambiguous && InvalidAsDeclaration)
Modified: cfe/trunk/lib/Parse/ParseTentative.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=224906&r1=224905&r2=224906&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTentative.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTentative.cpp Sun Dec 28 17:24:02 2014
@@ -195,7 +195,9 @@ Parser::TPResult Parser::TryConsumeDecla
}
}
- if (TryAnnotateCXXScopeToken())
+ if ((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
+ Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id)) &&
+ TryAnnotateCXXScopeToken())
return TPResult::Error;
if (Tok.is(tok::annot_cxxscope))
ConsumeToken();
Modified: cfe/trunk/test/Parser/cxx-member-initializers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-member-initializers.cpp?rev=224906&r1=224905&r2=224906&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx-member-initializers.cpp (original)
+++ cfe/trunk/test/Parser/cxx-member-initializers.cpp Sun Dec 28 17:24:02 2014
@@ -79,3 +79,29 @@ namespace PR16480 {
Errs(X<2>) : decltype(X<0> // expected-note {{to match this '('}}
}; // expected-error {{expected ')'}}
}
+
+template <class U, class V> struct C {
+ int f() { return 4; }
+ class C1 {};
+};
+
+class D {};
+namespace N {
+struct E {
+ class F {};
+};
+}
+
+class G {
+ // These are all valid:
+ void f(int x = C<int, D>().f()) {}
+ void g(int x = C<int, ::D>().f()) {}
+ void h(int x = C<int, N::E>().f()) {}
+ void i(int x = C<int, ::N::E>().f()) {}
+ void j(int x = C<int, decltype(N::E())::F>().f()) {}
+ void k(int x = C<int, C<int, int>>().f()) {}
+ void l(int x = C<int, C<int, int>::C1>().f()) {}
+
+ // This isn't, but it shouldn't crash. The diagnostics don't matter much.
+ void m(int x = C<int, union int>().f()) {} // expected-error {{declaration of anonymous union must be a definition}}
+}; // expected-error {{expected a type}}
More information about the cfe-commits
mailing list