From 74bda9c15a6e729ed192d40692ac509e54a8a3f5 Mon Sep 17 00:00:00 2001 From: Ismail Pazarbasi Date: Thu, 25 Sep 2014 21:13:02 +0000 Subject: [PATCH] Suggest fix-it for missing '{' after base-clause git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@218468 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Parse/ParseDeclCXX.cpp | 42 ++++++++++++++++++++++++++----- test/FixIt/fixit.cpp | 36 +++++++++++++++++++++++++- test/Parser/cxx-template-decl.cpp | 15 +++++++++++ 3 files changed, 86 insertions(+), 7 deletions(-) diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 08f73d4d09..362b2c0442 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -2670,13 +2670,43 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, if (Tok.is(tok::colon)) { ParseBaseClause(TagDecl); - if (!Tok.is(tok::l_brace)) { - Diag(Tok, diag::err_expected_lbrace_after_base_specifiers); - - if (TagDecl) - Actions.ActOnTagDefinitionError(getCurScope(), TagDecl); - return; + bool SuggestFixIt = false; + SourceLocation BraceLoc = PP.getLocForEndOfToken(PrevTokLocation); + if (Tok.isAtStartOfLine()) { + switch (Tok.getKind()) { + case tok::kw_private: + case tok::kw_protected: + case tok::kw_public: + SuggestFixIt = NextToken().getKind() == tok::colon; + break; + case tok::kw_static_assert: + case tok::r_brace: + case tok::kw_using: + // base-clause can have simple-template-id; 'template' can't be there + case tok::kw_template: + SuggestFixIt = true; + break; + case tok::identifier: + SuggestFixIt = isConstructorDeclarator(true); + break; + default: + SuggestFixIt = isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false); + break; + } + } + DiagnosticBuilder LBraceDiag = + Diag(BraceLoc, diag::err_expected_lbrace_after_base_specifiers); + if (SuggestFixIt) { + LBraceDiag << FixItHint::CreateInsertion(BraceLoc, " {"); + // Try recovering from missing { after base-clause. + PP.EnterToken(Tok); + Tok.setKind(tok::l_brace); + } else { + if (TagDecl) + Actions.ActOnTagDefinitionError(getCurScope(), TagDecl); + return; + } } } diff --git a/test/FixIt/fixit.cpp b/test/FixIt/fixit.cpp index 6c328c5218..20b5b52c11 100644 --- a/test/FixIt/fixit.cpp +++ b/test/FixIt/fixit.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -pedantic -Wall -Wno-comment -verify -fcxx-exceptions -x c++ %s -// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -x c++ %s 2>&1 | FileCheck %s +// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -x c++ -std=c++11 %s 2>&1 | FileCheck %s // RUN: cp %s %t // RUN: not %clang_cc1 -pedantic -Wall -Wno-comment -fcxx-exceptions -fixit -x c++ %t // RUN: %clang_cc1 -fsyntax-only -pedantic -Wall -Werror -Wno-comment -fcxx-exceptions -x c++ %t @@ -347,3 +347,37 @@ namespace PR15045 { return c->a; // expected-error {{member reference type 'PR15045::Cl0' is not a pointer; maybe you meant to use '.'?}} } } + +namespace curly_after_base_clause { +struct A { void f(); }; +struct B : A // expected-error{{expected '{' after base class list}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:" {" + int i; +}; +struct C : A // expected-error{{expected '{' after base class list}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:" {" + using A::f; +}; +struct D : A // expected-error{{expected '{' after base class list}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:" {" + protected: +}; +struct E : A // expected-error{{expected '{' after base class list}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:" {" + template struct inner { }; +}; +struct F : A // expected-error{{expected '{' after base class list}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:" {" + F() { } +}; +#if __cplusplus >= 201103L +struct G : A // expected-error{{expected '{' after base class list}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:" {" + constexpr G(int) { } +}; +struct H : A // expected-error{{expected '{' after base class list}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:" {" + static_assert(true, ""); +}; +#endif +} diff --git a/test/Parser/cxx-template-decl.cpp b/test/Parser/cxx-template-decl.cpp index 8b2b12037b..bce1b7cbde 100644 --- a/test/Parser/cxx-template-decl.cpp +++ b/test/Parser/cxx-template-decl.cpp @@ -210,3 +210,18 @@ void Instantiate() { } } + +namespace broken_baseclause { +template +struct base { }; + +struct t1 : base