<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Dec 4, 2013 at 5:36 PM, David Majnemer <span dir="ltr"><<a href="mailto:david.majnemer@gmail.com" target="_blank">david.majnemer@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Author: majnemer<br>
Date: Wed Dec  4 19:36:53 2013<br>
New Revision: 196453<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=196453&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=196453&view=rev</a><br>
Log:<br>
Parse: Recover better from bad definitions with base specifiers<br>
<br>
We would skip until the next comma, hoping good things whould lie there,<br>
however this would fail when we have such things as this:<br>
<br>
struct A {};<br>
template <typename><br>
struct D;<br>
template <><br>
struct D<C> : B, A::D;<br>
<br>
Once this happens, we would believe that D with a nested namespace<br>
specifier of A was a variable that was being declared. We would go on<br>
to complain that there was an extraneous 'template <>' on their variable<br>
declaration.<br>
<br>
Crashes would happen when 'A' gets defined as 'enum class A {}' as<br>
various asserts would fire.<br>
<br>
Instead, we should skip up until the semicolon if we see that we are in<br>
the middle of a definition and the current token is a ':'<br>
<br>
This fixes PR17084.<br>
<br>
Modified:<br>
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp<br>
    cfe/trunk/test/Parser/recovery.cpp<br>
<br>
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=196453&r1=196452&r2=196453&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=196453&r1=196452&r2=196453&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Wed Dec  4 19:36:53 2013<br>
@@ -1429,7 +1429,13 @@ void Parser::ParseClassSpecifier(tok::To<br>
         << DeclSpec::getSpecifierName(TagType);<br>
     }<br>
<br>
-    SkipUntil(tok::comma, StopAtSemi);<br>
+    // If we are parsing a definition and stop at a base-clause, continue on<br>
+    // until the semicolon.  Continuing from the comma will just trick us into<br>
+    // thinking we are seeing a variable declaration.<br>
+    if (TUK == Sema::TUK_Definition && Tok.is(tok::colon))<br>
+      SkipUntil(tok::semi, StopBeforeMatch);<br>
+    else<br>
+      SkipUntil(tok::comma, StopAtSemi);<br></blockquote><div><br></div><div>Does it ever make sense to only skip to a comma? Where is this useful? (I realize the tok::comma skipping predates your patch, but since you touched this a short 1.2 years ago, maybe you know :-) Looking at the commit that originally added it wasn't enlightening. I looked at this because of r229288.)</div>







<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
     return;<br>
   }<br>
<br>
<br>
Modified: cfe/trunk/test/Parser/recovery.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/recovery.cpp?rev=196453&r1=196452&r2=196453&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/recovery.cpp?rev=196453&r1=196452&r2=196453&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Parser/recovery.cpp (original)<br>
+++ cfe/trunk/test/Parser/recovery.cpp Wed Dec  4 19:36:53 2013<br>
@@ -129,3 +129,9 @@ NS::Foo<int> missingSemiBeforeFunctionRe<br>
 using NS::Foo;<br>
 struct MissingSemiThenTemplate2 {} // expected-error {{expected ';' after struct}}<br>
 Foo<int> missingSemiBeforeFunctionReturningTemplateId2();<br>
+<br>
+namespace PR17084 {<br>
+enum class EnumID {};<br>
+template <typename> struct TempID;<br>
+template <> struct TempID<BadType> : BadType, EnumID::Garbage; // expected-error{{use of undeclared identifier 'BadType'}}<br>
+}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">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><br></div></div>