[cfe-commits] Patch - Add fix-it hint for missing case keyword within a switch scope

Richard Trieu rtrieu at google.com
Thu Apr 21 14:51:12 PDT 2011


This patch has been submitted as r129943.

On Thu, Apr 21, 2011 at 7:30 AM, Douglas Gregor <dgregor at apple.com> wrote:

>
> On Apr 20, 2011, at 6:21 PM, Richard Trieu wrote:
>
> Another round of changes.  I believe I addressed all the issues raised.
>
>
> Very nice! One last small request
>
> Index: lib/Sema/SemaExpr.cpp
> ===================================================================
> --- lib/Sema/SemaExpr.cpp (revision 129825)
> +++ lib/Sema/SemaExpr.cpp (working copy)
> @@ -10734,3 +10734,8 @@
>    assert(!type->isPlaceholderType());
>    return Owned(E);
>  }
> +
> +bool Sema::CheckCaseExpression(Expr *expr) {
> +  return expr->isTypeDependent() || expr->isValueDependent() ||
> +         expr->isIntegerConstantExpr(Context);
> +}
>
> When the expression is value-dependent or non-dependent, please check
> whether it has integral or enumeration type. We don't want to suggest "case"
> for, say, value-dependent expressions of pointer type.
>
> You can go ahead and commit with that tweak.
>
> - Doug
>
> On Wed, Apr 20, 2011 at 7:35 AM, Douglas Gregor <dgregor at apple.com> wrote:
>
>>
>> On Apr 19, 2011, at 5:19 PM, Richard Trieu wrote:
>>
>> I have reworked the program flow.  Instead of tentative parsing, the
>> already parsed expression is reused within the case statement parsing
>> following colon detection.
>>
>>
>> I like this much better! A few more comments:
>>
>> Index: include/clang/Sema/Scope.h
>> ===================================================================
>> --- include/clang/Sema/Scope.h (revision 129825)
>> +++ include/clang/Sema/Scope.h (working copy)
>> @@ -75,7 +75,10 @@
>>
>>      /// ObjCMethodScope - This scope corresponds to an Objective-C method
>> body.
>>      /// It always has FnScope and DeclScope set as well.
>> -    ObjCMethodScope = 0x400
>> +    ObjCMethodScope = 0x400,
>> +
>> +    /// SwitchScope - This is a scope that corresponds to a switch
>> statement.
>> +    SwitchScope = 0x800
>>    };
>>  private:
>>    /// The parent scope for this scope.  This is null for the
>> translation-unit
>> @@ -260,6 +263,14 @@
>>      return getFlags() & Scope::AtCatchScope;
>>    }
>>
>> +  /// isSwitchScope - Return true if this scope is a switch scope.
>> +  bool isSwitchScope() const {
>> +    for (const Scope *S = this; S; S = S->getParent()) {
>> +      if (S->getFlags() & Scope::SwitchScope)
>> +        return true;
>> +    }
>> +  }
>> +
>>
>> This is going to search all the way up the scope stack for a switch
>> anywhere, which isn't necessarily the same thing as being in a switch
>> statement because there could be inner classes/blocks/etc. For example,
>> we'll incorrectly suggest the 'case' keyword for this example:
>>
>> void f(int x) {
>>   switch (x) {
>>   case 1: {
>>     struct Inner {
>>       void g() {
>>         1: x = 17;
>>       }
>>     };
>>     break;
>>   }
>>   }
>> }
>>
>> I see two solutions:
>>   1) Prevent isSwitchScope() from walking through function
>> declarations/blocks/etc. Or, only jump up one scope level (e.g., from the
>> compound statement out to the switch) when checking for a switch scope,
>> since case statements rarely show up anywhere else.
>>   2) Add a Sema function isInSwitchStatement() and use that in the parser.
>>
>
> Went with solution 1 and changed isSwitchScope() so that it stops walking
> through declaration/block/etc boundaries.  Moved above code sample to test
> case.
>
>
> Looks good!
>
>
>> @@ -251,8 +266,11 @@
>>  ///         'case' constant-expression ':' statement
>>  /// [GNU]   'case' constant-expression '...' constant-expression ':'
>> statement
>>  ///
>> -StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs) {
>> -  assert(Tok.is(tok::kw_case) && "Not a case stmt!");
>> +StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool
>> MissingCase,
>> +                                      ExprResult Expr) {
>> +  if (!MissingCase) {
>> +    assert(Tok.is(tok::kw_case) && "Not a case stmt!");
>> +  }
>>
>> How about:
>>
>> assert((MissingCase || Tok.is(tok::kw_case)) && "Not a case stmt!");
>>
>>
>> @@ -133,6 +136,18 @@
>>          ConsumeToken();
>>        return StmtError();
>>      }
>> +
>> +    if (Tok.is(tok::colon) && getCurScope()->isSwitchScope() &&
>> +        Expr.get()->isIntegerConstantExpr(Actions.Context)) {
>>
>> There are two issues here. The first is that Expr::isIntegerConstantExpr()
>> isn't safe for type- or value-dependent expressions, so we now crash on this
>> ill-formed code:
>>
>> template<typename T>
>> struct X {
>>   enum { E };
>>
>>   void f(int x) {
>>     switch (x) {
>>       E: break;
>>       E+1: break;
>>     }
>>   }
>> };
>>
>> The second issue is that the parser shouldn't probe the AST directly.
>> Instead, please add a function into Sema that performs the semantic analysis
>> and decides whether this expression was meant to be part of a case
>> statement. That function should allow the correction for type-dependent
>> expressions, value-dependent expressions with integral or enumeration type,
>> and non-dependent, integral constant expressions.
>>
>
> Moved AST checks to Sema.  Included checks for type and value dependent
> expressions.  Included above code into test case.
>
>>
>>
> Finally, I had two thoughts for follow-on patches:
>>
>> 1) Given code like this:
>>
>> enum E { A };
>> void f(int e) {
>>   switch (e) {
>>   A: break;
>>   }
>> }
>>
>> Under -Wunused-label, we warn about 'A'. However, it would be very cool to
>> give a warning like:
>>
>>   warning: unused label 'A' also refers to an
>> %select{integeral|enumeration}0 value within a switch statement
>>
>>   note: did you mean to make this a case statement?
>>
>> (with a "case " Fix-It on the note).
>>
>>
>> 2) It occurs to me that, if we're in a non-switch statement context and we
>> we see a ':' after an expression, the ':' is probably a typo for ';'. It may
>> be worth adding that recovery + Fix-It as well.
>>
> I think Clang already suggests a semi-colon when an out of place colon is
> found.  That was what it suggested before this patch.
>
>
> Okay!
>
> - Doug
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20110421/e6d61583/attachment.html>


More information about the cfe-commits mailing list