[PATCH] Recover from errors in enum definition.

Alp Toker alp at nuanti.com
Mon Dec 30 16:35:51 PST 2013


On 30/12/2013 18:13, Serge Pavlov wrote:
>    Updated patch according to Alp Toker's notes.
>
> http://llvm-reviews.chandlerc.com/D2116
>
> CHANGE SINCE LAST DIFF
>    http://llvm-reviews.chandlerc.com/D2116?vs=6309&id=6316#toc
>
> Files:
>    include/clang/Basic/DiagnosticParseKinds.td
>    lib/Parse/ParseDecl.cpp
>    test/Parser/cxx0x-ambig.cpp
>    test/Parser/declarators.c
>
> Index: include/clang/Basic/DiagnosticParseKinds.td
> ===================================================================
> --- include/clang/Basic/DiagnosticParseKinds.td
> +++ include/clang/Basic/DiagnosticParseKinds.td
> @@ -354,6 +354,8 @@
>     "unexpected parenthesis after '::'">;
>   def err_function_definition_not_allowed : Error<
>     "function definition is not allowed here">;
> +def err_expected_end_of_enumerator : Error<
> +  "expected '=constant expression' or end of enumerator definition">;

Make this '= constant-expression' with a space and a hyphen.

LGTM with that change!

Alp.


>   
>   /// Objective-C parser diagnostics
>   def err_expected_minus_or_plus : Error<
> Index: lib/Parse/ParseDecl.cpp
> ===================================================================
> --- lib/Parse/ParseDecl.cpp
> +++ lib/Parse/ParseDecl.cpp
> @@ -3888,7 +3888,16 @@
>     Decl *LastEnumConstDecl = 0;
>   
>     // Parse the enumerator-list.
> -  while (Tok.is(tok::identifier)) {
> +  while (Tok.isNot(tok::r_brace)) {
> +    // Parse enumerator. If failed, try skipping till the start of the next
> +    // enumerator definition.
> +    if (Tok.isNot(tok::identifier)) {
> +      Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
> +      if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch) &&
> +          TryConsumeToken(tok::comma))
> +        continue;
> +      break;
> +    }
>       IdentifierInfo *Ident = Tok.getIdentifierInfo();
>       SourceLocation IdentLoc = ConsumeToken();
>   
> @@ -3905,7 +3914,7 @@
>       if (TryConsumeToken(tok::equal, EqualLoc)) {
>         AssignedVal = ParseConstantExpression();
>         if (AssignedVal.isInvalid())
> -        SkipUntil(tok::comma, tok::r_brace, StopAtSemi | StopBeforeMatch);
> +        SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch);
>       }
>   
>       // Install the enumerator constant into EnumDecl.
> @@ -3927,19 +3936,34 @@
>         continue;
>       }
>   
> +    // Emumerator definition must be finished, only comma or r_brace are
> +    // allowed here.
>       SourceLocation CommaLoc;
> -    if (!TryConsumeToken(tok::comma, CommaLoc))
> -      break;
> +    if (Tok.isNot(tok::r_brace) && !TryConsumeToken(tok::comma, CommaLoc)) {
> +      if (EqualLoc.isValid())
> +        Diag(Tok.getLocation(), diag::err_expected_either) << tok::r_brace
> +                                                           << tok::comma;
> +      else
> +        Diag(Tok.getLocation(), diag::err_expected_end_of_enumerator);
> +      if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch)) {
> +        if (TryConsumeToken(tok::comma, CommaLoc))
> +          continue;
> +      } else {
> +        break;
> +      }
> +    }
>   
> -    if (Tok.isNot(tok::identifier)) {
> +    // If comma is followed by r_brace, emit appropriate warning.
> +    if (Tok.is(tok::r_brace) && CommaLoc.isValid()) {
>         if (!getLangOpts().C99 && !getLangOpts().CPlusPlus11)
>           Diag(CommaLoc, getLangOpts().CPlusPlus ?
>                  diag::ext_enumerator_list_comma_cxx :
>                  diag::ext_enumerator_list_comma_c)
>             << FixItHint::CreateRemoval(CommaLoc);
>         else if (getLangOpts().CPlusPlus11)
>           Diag(CommaLoc, diag::warn_cxx98_compat_enumerator_list_comma)
>             << FixItHint::CreateRemoval(CommaLoc);
> +      break;
>       }
>     }
>   
> Index: test/Parser/cxx0x-ambig.cpp
> ===================================================================
> --- test/Parser/cxx0x-ambig.cpp
> +++ test/Parser/cxx0x-ambig.cpp
> @@ -48,7 +48,7 @@
>     };
>     // This could be a bit-field.
>     struct S2 {
> -    enum E : T { a = 1, b = 2, c = 3, 4 }; // expected-error {{non-integral type}} expected-error {{expected '}'}} expected-note {{to match}}
> +    enum E : T { a = 1, b = 2, c = 3, 4 }; // expected-error {{non-integral type}} expected-error {{expected identifier}}
>     };
>     struct S3 {
>       enum E : int { a = 1, b = 2, c = 3, d }; // ok, defines an enum
> @@ -64,7 +64,7 @@
>     };
>     // This could be a bit-field.
>     struct S6 {
> -    enum E : int { 1 }; // expected-error {{expected '}'}} expected-note {{to match}}
> +    enum E : int { 1 }; // expected-error {{expected identifier}}
>     };
>   
>     struct U {
> Index: test/Parser/declarators.c
> ===================================================================
> --- test/Parser/declarators.c
> +++ test/Parser/declarators.c
> @@ -113,3 +113,37 @@
>     struct S { int n; }: // expected-error {{expected ';'}}
>   
>   };
> +
> +// PR10982
> +enum E11 {
> +  A1 = 1,
> +};
> +
> +enum E12 {
> +  ,  // expected-error{{expected identifier}}
> +  A2
> +};
> +void func_E12(enum E12 *p) { *p = A2; }
> +
> +enum E13 {
> +  1D,  // expected-error{{expected identifier}}
> +  A3
> +};
> +void func_E13(enum E13 *p) { *p = A3; }
> +
> +enum E14 {
> +  A4 12,  // expected-error{{expected '=constant expression' or end of enumerator definition}}
> +  A4a
> +};
> +void func_E14(enum E14 *p) { *p = A4a; }
> +
> +enum E15 {
> +  A5=12 4,  // expected-error{{expected '}' or ','}}
> +  A5a
> +};
> +void func_E15(enum E15 *p) { *p = A5a; }
> +
> +enum E16 {
> +  A6;  // expected-error{{expected '=constant expression' or end of enumerator definition}}
> +  A6a
> +};
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

-- 
http://www.nuanti.com
the browser experts




More information about the cfe-commits mailing list