From a813e2bd4bd98db0c7067b6e51dff2042a5bba5c Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Thu, 5 Dec 2013 01:36:53 +0000 Subject: [PATCH] Parse: Recover better from bad definitions with base specifiers 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 struct D; template <> struct D : 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@196453 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Parse/ParseDeclCXX.cpp | 8 +++++++- test/Parser/recovery.cpp | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 9c56022941..b34b1119af 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1429,7 +1429,13 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, << DeclSpec::getSpecifierName(TagType); } - SkipUntil(tok::comma, StopAtSemi); + // 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 && Tok.is(tok::colon)) + SkipUntil(tok::semi, StopBeforeMatch); + else + SkipUntil(tok::comma, StopAtSemi); return; } diff --git a/test/Parser/recovery.cpp b/test/Parser/recovery.cpp index 60b4b5a336..cb1979f9ff 100644 --- a/test/Parser/recovery.cpp +++ b/test/Parser/recovery.cpp @@ -129,3 +129,9 @@ NS::Foo missingSemiBeforeFunctionReturningTemplateId1(); using NS::Foo; struct MissingSemiThenTemplate2 {} // expected-error {{expected ';' after struct}} Foo missingSemiBeforeFunctionReturningTemplateId2(); + +namespace PR17084 { +enum class EnumID {}; +template struct TempID; +template <> struct TempID : BadType, EnumID::Garbage; // expected-error{{use of undeclared identifier 'BadType'}} +} -- 2.50.1