<div class="gmail_quote">On Wed, Feb 29, 2012 at 7:24 PM, Eli Friedman <span dir="ltr"><<a href="mailto:eli.friedman@gmail.com">eli.friedman@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="HOEnZb"><div class="h5">On Wed, Feb 29, 2012 at 6:59 PM, Richard Smith<br>
<<a href="mailto:richard-llvm@metafoo.co.uk">richard-llvm@metafoo.co.uk</a>> wrote:<br>
> Author: rsmith<br>
> Date: Wed Feb 29 20:59:17 2012<br>
> New Revision: 151794<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=151794&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=151794&view=rev</a><br>
> Log:<br>
> Reject 'a = {0} = {0}' rather than parsing it as '(a = {0}) = {0}'. Also<br>
> improve the diagnostics for some attempts to use initializer lists in<br>
> expressions.<br>
><br>
> Modified:<br>
>    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td<br>
>    cfe/trunk/lib/Parse/ParseExpr.cpp<br>
>    cfe/trunk/test/CXX/expr/expr.ass/p9-cxx11.cpp<br>
><br>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=151794&r1=151793&r2=151794&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=151794&r1=151793&r2=151794&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)<br>
> +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Wed Feb 29 20:59:17 2012<br>
> @@ -229,6 +229,8 @@<br>
>  def warn_cxx98_compat_generalized_initializer_lists : Warning<<br>
>   "generalized initializer lists are incompatible with C++98">,<br>
>   InGroup<CXX98Compat>, DefaultIgnore;<br>
> +def err_init_list_bin_op : Error<"initializer list cannot be used on the "<br>
> +  "%select{left|right}0 hand side of operator '%1'">;<br>
>  def warn_cxx98_compat_trailing_return_type : Warning<<br>
>   "trailing return types are incompatible with C++98">,<br>
>   InGroup<CXX98Compat>, DefaultIgnore;<br>
><br>
> Modified: cfe/trunk/lib/Parse/ParseExpr.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=151794&r1=151793&r2=151794&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=151794&r1=151793&r2=151794&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Parse/ParseExpr.cpp (original)<br>
> +++ cfe/trunk/lib/Parse/ParseExpr.cpp Wed Feb 29 20:59:17 2012<br>
> @@ -282,6 +282,12 @@<br>
>     Token OpToken = Tok;<br>
>     ConsumeToken();<br>
><br>
> +    if (!LHS.isInvalid() && isa<InitListExpr>(LHS.get())) {<br>
> +      Diag(OpToken, diag::err_init_list_bin_op)<br>
> +        << /*LHS*/0 << PP.getSpelling(OpToken) << LHS.get()->getSourceRange();<br>
> +      LHS = ExprError();<br>
> +    }<br>
> +<br>
>     // Special case handling for the ternary operator.<br>
>     ExprResult TernaryMiddle(true);<br>
>     if (NextTokPrec == prec::Conditional) {<br>
> @@ -353,22 +359,16 @@<br>
>     // Therefore we need some special-casing here.<br>
>     // Also note that the third operand of the conditional operator is<br>
>     // an assignment-expression in C++, and in C++11, we can have a<br>
> -    // braced-init-list on the RHS of an assignment.<br>
> +    // braced-init-list on the RHS of an assignment. For better diagnostics,<br>
> +    // parse as if we were allowed braced-init-lists everywhere, and check that<br>
> +    // they only appear on the RHS of assignments later.<br>
>     ExprResult RHS;<br>
> -    if (getLang().CPlusPlus0x && MinPrec == prec::Assignment &&<br>
> -        Tok.is(tok::l_brace)) {<br>
> -      Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);<br>
> +    if (getLang().CPlusPlus0x && Tok.is(tok::l_brace))<br>
>       RHS = ParseBraceInitializer();<br>
> -      if (LHS.isInvalid() || RHS.isInvalid())<br>
> -        return ExprError();<br>
> -      // A braced-init-list can never be followed by more operators.<br>
> -      return Actions.ActOnBinOp(getCurScope(), OpToken.getLocation(),<br>
> -                                OpToken.getKind(), LHS.take(), RHS.take());<br>
> -    } else if (getLang().CPlusPlus && NextTokPrec <= prec::Conditional) {<br>
> +    else if (getLang().CPlusPlus && NextTokPrec <= prec::Conditional)<br>
>       RHS = ParseAssignmentExpression();<br>
> -    } else {<br>
> +    else<br>
>       RHS = ParseCastExpression(false);<br>
> -    }<br>
><br>
>     if (RHS.isInvalid())<br>
>       LHS = ExprError();<br>
> @@ -387,6 +387,11 @@<br>
>     // more tightly with RHS than we do, evaluate it completely first.<br>
>     if (ThisPrec < NextTokPrec ||<br>
>         (ThisPrec == NextTokPrec && isRightAssoc)) {<br>
> +      if (!LHS.isInvalid() && isa<InitListExpr>(LHS.get())) {<br>
> +        Diag(OpToken, diag::err_init_list_bin_op)<br>
> +          << /*LHS*/0 << PP.getSpelling(OpToken) << LHS.get()->getSourceRange();<br>
> +        LHS = ExprError();<br>
> +      }<br>
<br>
</div></div>We normally try to avoid the Parser using AST methods directly...<br>
granted, the distinction between Parser and Sema has started to blur a<br>
bit, but I think it's still useful to try to maintain.</blockquote><div><br></div><div>Yea, we should keep that layering invariant.</div><div><br></div><div>I'll check to make sure oure layering-enforcement actually checks this case... </div>
</div>