[PATCH] Parse: Recover better from bad definitions with base specifiers

David Majnemer david.majnemer at gmail.com
Sat Sep 14 00:53:04 PDT 2013


Hi rsmith, doug.gregor,

We would skip until the next comma, hoping good things whould lie there,
however this would fail when we have such things as this:

struct A {};
template <typename>
struct D;
template <>
struct D<C> : B, A::D;

Once this happens, we would believe that D with a nested namespace
specifier of A was a variable that was being declared.  We would go on
to complain that there was an extraneous 'template <>' on their variable
declaration.

Crashes would happen when 'A' gets defined as 'enum class A {}' as
various asserts would fire.

Instead, we should skip up until the semicolon if we see that we are in
the middle of a definition and the current token is a ':'

This fixes PR17084.

http://llvm-reviews.chandlerc.com/D1687

Files:
  lib/Parse/ParseDeclCXX.cpp
  test/Parser/recovery.cpp

Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp
+++ lib/Parse/ParseDeclCXX.cpp
@@ -1419,8 +1419,14 @@
       Diag(StartLoc, diag::err_anon_type_definition)
         << DeclSpec::getSpecifierName(TagType);
     }
-
-    SkipUntil(tok::comma, true);
+    // If we are parsing a definition and stop at a base-clause, continue on until the
+    // semicolon.  Continuing from the comma will just trick us into thinking we
+    // are seeing a variable declaration.
+    if (TUK == Sema::TUK_Definition && getLangOpts().CPlusPlus &&
+        Tok.is(tok::colon))
+      SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
+    else
+      SkipUntil(tok::comma, /*StopAtSemi=*/true);
     return;
   }
 
Index: test/Parser/recovery.cpp
===================================================================
--- test/Parser/recovery.cpp
+++ test/Parser/recovery.cpp
@@ -50,3 +50,9 @@
 struct Redefined { // expected-error {{redefinition}}
   Redefined() {}
 };
+
+namespace PR17084 {
+enum class EnumID {};
+template <typename> struct TempID;
+template <> struct TempID<BadType> : BadType, EnumID::Garbage; // expected-error{{use of undeclared identifier 'BadType'}}
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1687.1.patch
Type: text/x-patch
Size: 1257 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130914/2071fc9b/attachment.bin>


More information about the cfe-commits mailing list