[cfe-commits] r150790 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Parse/ParseInit.cpp test/Parser/cxx0x-lambda-expressions.cpp

Sebastian Redl sebastian.redl at getdesigned.at
Fri Feb 17 00:05:57 PST 2012


On 17.02.2012, at 04:49, Douglas Gregor wrote:

> Author: dgregor
> Date: Thu Feb 16 21:49:44 2012
> New Revision: 150790
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=150790&view=rev
> Log:
> Disambiguate between C++11 lambda expressions and C99 array
> designators in the parser. In the worst case, this disambiguation
> requires tentative parsing just past the closing ']', but for most
> cases we'll be able to tell by looking ahead just one token (without
> going into the heavyweight tentative parsing machinery).
> 
> Modified:
>    cfe/trunk/include/clang/Parse/Parser.h
>    cfe/trunk/lib/Parse/ParseInit.cpp
>    cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp
> 
> Modified: cfe/trunk/lib/Parse/ParseInit.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseInit.cpp?rev=150790&r1=150789&r2=150790&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseInit.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseInit.cpp Thu Feb 16 21:49:44 2012
> @@ -21,15 +21,86 @@
> using namespace clang;
> 
> 
> -/// MayBeDesignationStart - Return true if this token might be the start of a
> -/// designator.  If we can tell it is impossible that it is a designator, return
> -/// false.
> -static bool MayBeDesignationStart(tok::TokenKind K, Preprocessor &PP) {
> -  switch (K) {
> -  default: return false;
> +/// MayBeDesignationStart - Return true if the current token might be the start 
> +/// of a designator.  If we can tell it is impossible that it is a designator, 
> +/// return false.
> +bool Parser::MayBeDesignationStart() {
> +  switch (Tok.getKind()) {
> +  default: 
> +    return false;
> +      
>   case tok::period:      // designator: '.' identifier
> -  case tok::l_square:    // designator: array-designator
> +    return true;
> +      
> +  case tok::l_square: {  // designator: array-designator
> +    if (!PP.getLangOptions().CPlusPlus0x)
>       return true;
> +    

Maybe reduce nesting by breaking out of the switch here?

> +    // C++11 lambda expressions and C99 designators can be ambiguous all the
> +    // way through the closing ']' and to the next character. Handle the easy
> +    // cases here, and fall back to tentative parsing if those fail.
> +    switch (PP.LookAhead(0).getKind()) {
> +    case tok::equal:
> +    case tok::r_square:
> +      // Definitely starts a lambda expression.
> +      return false;
> +      
> +    case tok::amp:
> +    case tok::kw_this:
> +    case tok::identifier:
> +      // We have to do additional analysis, because these could be the
> +      // start of a constant expression or a lambda capture list.
> +      break;
> +        
> +    default:
> +      // Anything not mentioned above cannot occur following a '[' in a 
> +      // lambda expression.
> +      return true;        
> +    }
> +    
> +    // Parse up to (at most) the token after the closing ']' to determine 
> +    // whether this is a C99 designator or a lambda.
> +    TentativeParsingAction Tentative(*this);
> +    ConsumeBracket();
> +    while (true) {
> +      switch (Tok.getKind()) {
> +      case tok::equal:
> +      case tok::amp:
> +      case tok::identifier:
> +      case tok::kw_this:
> +        // These tokens can occur in a capture list or a constant-expression.
> +        // Keep looking.
> +        ConsumeToken();
> +        continue;
> +          
> +      case tok::comma:
> +        // Since a comma cannot occur in a constant-expression, this must
> +        // be a lambda.
> +        Tentative.Revert();
> +        return false;
> +          
> +      case tok::r_square: {
> +        // Once we hit the closing square bracket, we look at the next
> +        // token. If it's an '=', this is a designator. Otherwise, it's a
> +        // lambda expression. This decision favors lambdas over the older
> +        // GNU designator syntax, which allows one to omit the '=', but is
> +        // consistent with GCC.
> +        ConsumeBracket();
> +        tok::TokenKind Kind = Tok.getKind();
> +        Tentative.Revert();
> +        return Kind == tok::equal;
> +      }
> +          
> +      default:
> +        // Anything else cannot occur in a lambda capture list, so it
> +        // must be a designator.
> +        Tentative.Revert();
> +        return true;
> +      }
> +    }
> +    
> +    return true;
> +  }
>   case tok::identifier:  // designation: identifier ':'
>     return PP.LookAhead(0).is(tok::colon);
>   }

Sebastian





More information about the cfe-commits mailing list