Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 74bda9c

Browse files
committed
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
1 parent cb48eba commit 74bda9c

File tree

3 files changed

+86
-7
lines changed

3 files changed

+86
-7
lines changed

lib/Parse/ParseDeclCXX.cpp

+36-6
Original file line numberDiff line numberDiff line change
@@ -2670,13 +2670,43 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
26702670

26712671
if (Tok.is(tok::colon)) {
26722672
ParseBaseClause(TagDecl);
2673-
26742673
if (!Tok.is(tok::l_brace)) {
2675-
Diag(Tok, diag::err_expected_lbrace_after_base_specifiers);
2676-
2677-
if (TagDecl)
2678-
Actions.ActOnTagDefinitionError(getCurScope(), TagDecl);
2679-
return;
2674+
bool SuggestFixIt = false;
2675+
SourceLocation BraceLoc = PP.getLocForEndOfToken(PrevTokLocation);
2676+
if (Tok.isAtStartOfLine()) {
2677+
switch (Tok.getKind()) {
2678+
case tok::kw_private:
2679+
case tok::kw_protected:
2680+
case tok::kw_public:
2681+
SuggestFixIt = NextToken().getKind() == tok::colon;
2682+
break;
2683+
case tok::kw_static_assert:
2684+
case tok::r_brace:
2685+
case tok::kw_using:
2686+
// base-clause can have simple-template-id; 'template' can't be there
2687+
case tok::kw_template:
2688+
SuggestFixIt = true;
2689+
break;
2690+
case tok::identifier:
2691+
SuggestFixIt = isConstructorDeclarator(true);
2692+
break;
2693+
default:
2694+
SuggestFixIt = isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false);
2695+
break;
2696+
}
2697+
}
2698+
DiagnosticBuilder LBraceDiag =
2699+
Diag(BraceLoc, diag::err_expected_lbrace_after_base_specifiers);
2700+
if (SuggestFixIt) {
2701+
LBraceDiag << FixItHint::CreateInsertion(BraceLoc, " {");
2702+
// Try recovering from missing { after base-clause.
2703+
PP.EnterToken(Tok);
2704+
Tok.setKind(tok::l_brace);
2705+
} else {
2706+
if (TagDecl)
2707+
Actions.ActOnTagDefinitionError(getCurScope(), TagDecl);
2708+
return;
2709+
}
26802710
}
26812711
}
26822712

test/FixIt/fixit.cpp

+35-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %clang_cc1 -pedantic -Wall -Wno-comment -verify -fcxx-exceptions -x c++ %s
2-
// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -x c++ %s 2>&1 | FileCheck %s
2+
// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -x c++ -std=c++11 %s 2>&1 | FileCheck %s
33
// RUN: cp %s %t
44
// RUN: not %clang_cc1 -pedantic -Wall -Wno-comment -fcxx-exceptions -fixit -x c++ %t
55
// RUN: %clang_cc1 -fsyntax-only -pedantic -Wall -Werror -Wno-comment -fcxx-exceptions -x c++ %t
@@ -347,3 +347,37 @@ namespace PR15045 {
347347
return c->a; // expected-error {{member reference type 'PR15045::Cl0' is not a pointer; maybe you meant to use '.'?}}
348348
}
349349
}
350+
351+
namespace curly_after_base_clause {
352+
struct A { void f(); };
353+
struct B : A // expected-error{{expected '{' after base class list}}
354+
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:" {"
355+
int i;
356+
};
357+
struct C : A // expected-error{{expected '{' after base class list}}
358+
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:" {"
359+
using A::f;
360+
};
361+
struct D : A // expected-error{{expected '{' after base class list}}
362+
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:" {"
363+
protected:
364+
};
365+
struct E : A // expected-error{{expected '{' after base class list}}
366+
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:" {"
367+
template<typename T> struct inner { };
368+
};
369+
struct F : A // expected-error{{expected '{' after base class list}}
370+
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:" {"
371+
F() { }
372+
};
373+
#if __cplusplus >= 201103L
374+
struct G : A // expected-error{{expected '{' after base class list}}
375+
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:" {"
376+
constexpr G(int) { }
377+
};
378+
struct H : A // expected-error{{expected '{' after base class list}}
379+
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:" {"
380+
static_assert(true, "");
381+
};
382+
#endif
383+
}

test/Parser/cxx-template-decl.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -210,3 +210,18 @@ void Instantiate() {
210210
}
211211

212212
}
213+
214+
namespace broken_baseclause {
215+
template<typename T>
216+
struct base { };
217+
218+
struct t1 : base<int,
219+
public: // expected-error {{expected expression}}
220+
}; // expected-error {{expected class name}}
221+
// expected-error@-1 {{expected '{' after base class list}}
222+
struct t2 : base<int,
223+
public // expected-error {{expected expression}}
224+
}; // expected-error {{expected class name}}
225+
// expected-error@-1 {{expected '{' after base class list}}
226+
227+
}

0 commit comments

Comments
 (0)