[PATCH] Improve diagnostic message for misplaced square brackets

Richard Trieu rtrieu at google.com
Thu Jun 12 21:31:45 PDT 2014


>>! In D2712#21, @rsmith wrote:
> +    if (Tok.is(tok::l_square)) {
> +      //if (ParseMisplacedBracketDeclarator(D)) {
> +      ParseMisplacedBracketDeclarator(D);
> +      //  goto PastIdentifier;
> +      return;
> 
> Remove comments here; maybe just
> 
Removed comments.

>   if (Tok.is(tok::l_square))
>     return ParseMisplacedBracketDeclarator(D);
> 
> 
> +  // Sometimes, parentheses are needed.  Determine if they are needed by
> +  // looking at the current token.  If they are needed, store the location
> +  // of the left parentheses in SuggestParenLoc.
> +  SourceLocation SuggestParenLoc;
> +  if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_paren) &&
> +      Tok.isNot(tok::semi)) {
> +    SuggestParenLoc = Tok.getLocation();
> +    D.getName().EndLocation = SourceLocation();
> +  }
> +
> +  // Now that the brackets are removed, try parsing the declarator again.
> +  ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
> 
> This logic for determining whether parens are needed doesn't seem to cover
> all cases. In particular:
> 
>   int [3] T::*p;
> 
> needs parens but starts with an identifier. Conversely,
> 
>   int [3] ::n;
> 
> doesn't need parens, but gets them. Instead, how about something like:
> 
>   SourceLocation LocBeforeDeclarator = Tok.getLocation();
>   ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
> 
>   bool NeedParens = false;
>   if (D.getNumTypeObjects()) {
>     switch (D.getTypeObject(D.getNumTypeObjects())) {
>       case DeclaratorChunk::Pointer:
>       case DeclaratorChunk::Reference:
>       case DeclaratorChunk::BlockPointer:
>       case DeclaratorChunk::MemberPointer:
>         NeedParens = true;
>         break;
>       case /* all the rest */
>         break;
>     }
>   }
> 
Paren adding updated.
> 
> 
> +  // Adding back the bracket info to the end of the Declarator.
> 
> If you've detected that you need parens, it'd be nice to fabricate a
> DeclaratorChunk for the parens, just in case something downstream is making
> assumptions about what DeclaratorChunks can exist based on how types can be
> written.
> 
Done.  New paren DeclaratorChuck added right after figuring out they are needed.
> 
> +  // The missing identifier would have been diagnosed in
> ParseDirectDeclarator.
> +  // If parentheses are required, always suggest them.
> +  if (!D.getIdentifier() && !SuggestParenLoc.isValid())
> +    return;
> 
> It would be nice to assert !D.mayOmitIdentifier() somewhere in this
> function, maybe right next to this check, since you're relying on that
> here. (I could certainly imagine this code getting reused for parsing
> abstract declarators at some point.)
> 
!D.mayOmitIdentifier() asserted at the beginning of the function since this function assumed the existence of an identifier.
> 
> +  SourceLocation EndBracketLoc =
> +      TempDeclarator.getTypeObject(TempDeclarator.getNumTypeObjects() - 1)
> +          .EndLoc;
> 
> Is this just 'TempDeclarator.getLocEnd()'?
> 
Yes.  Changed.
> 
> +  // When suggesting parentheses, the closing paren should not be before the
> +  // opening paren.
> +  if (SuggestParenLoc.isValid() && EndLoc < SuggestParenLoc)
> 
> This kind of SourceLocation comparison won't work in general (for instance,
> it will do weird things if the two locations have different FileIDs). Does
> this error case really happen?
> 
Changed it to detect that the Declarator end location changes after the call to ParseDeclaratorInternal.  Something like "int [];" will trigger this case.
> Also, you still need to produce some kind of diagnostic on this code path.
The ParseDeclaratorInternal should provide the error here.

http://reviews.llvm.org/D2712






More information about the cfe-commits mailing list