[cfe-commits] r151794 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td lib/Parse/ParseExpr.cpp test/CXX/expr/expr.ass/p9-cxx11.cpp

Eli Friedman eli.friedman at gmail.com
Wed Feb 29 19:24:42 PST 2012


On Wed, Feb 29, 2012 at 6:59 PM, Richard Smith
<richard-llvm at metafoo.co.uk> wrote:
> Author: rsmith
> Date: Wed Feb 29 20:59:17 2012
> New Revision: 151794
>
> URL: http://llvm.org/viewvc/llvm-project?rev=151794&view=rev
> Log:
> Reject 'a = {0} = {0}' rather than parsing it as '(a = {0}) = {0}'. Also
> improve the diagnostics for some attempts to use initializer lists in
> expressions.
>
> Modified:
>    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
>    cfe/trunk/lib/Parse/ParseExpr.cpp
>    cfe/trunk/test/CXX/expr/expr.ass/p9-cxx11.cpp
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=151794&r1=151793&r2=151794&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Wed Feb 29 20:59:17 2012
> @@ -229,6 +229,8 @@
>  def warn_cxx98_compat_generalized_initializer_lists : Warning<
>   "generalized initializer lists are incompatible with C++98">,
>   InGroup<CXX98Compat>, DefaultIgnore;
> +def err_init_list_bin_op : Error<"initializer list cannot be used on the "
> +  "%select{left|right}0 hand side of operator '%1'">;
>  def warn_cxx98_compat_trailing_return_type : Warning<
>   "trailing return types are incompatible with C++98">,
>   InGroup<CXX98Compat>, DefaultIgnore;
>
> Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=151794&r1=151793&r2=151794&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseExpr.cpp Wed Feb 29 20:59:17 2012
> @@ -282,6 +282,12 @@
>     Token OpToken = Tok;
>     ConsumeToken();
>
> +    if (!LHS.isInvalid() && isa<InitListExpr>(LHS.get())) {
> +      Diag(OpToken, diag::err_init_list_bin_op)
> +        << /*LHS*/0 << PP.getSpelling(OpToken) << LHS.get()->getSourceRange();
> +      LHS = ExprError();
> +    }
> +
>     // Special case handling for the ternary operator.
>     ExprResult TernaryMiddle(true);
>     if (NextTokPrec == prec::Conditional) {
> @@ -353,22 +359,16 @@
>     // Therefore we need some special-casing here.
>     // Also note that the third operand of the conditional operator is
>     // an assignment-expression in C++, and in C++11, we can have a
> -    // braced-init-list on the RHS of an assignment.
> +    // braced-init-list on the RHS of an assignment. For better diagnostics,
> +    // parse as if we were allowed braced-init-lists everywhere, and check that
> +    // they only appear on the RHS of assignments later.
>     ExprResult RHS;
> -    if (getLang().CPlusPlus0x && MinPrec == prec::Assignment &&
> -        Tok.is(tok::l_brace)) {
> -      Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
> +    if (getLang().CPlusPlus0x && Tok.is(tok::l_brace))
>       RHS = ParseBraceInitializer();
> -      if (LHS.isInvalid() || RHS.isInvalid())
> -        return ExprError();
> -      // A braced-init-list can never be followed by more operators.
> -      return Actions.ActOnBinOp(getCurScope(), OpToken.getLocation(),
> -                                OpToken.getKind(), LHS.take(), RHS.take());
> -    } else if (getLang().CPlusPlus && NextTokPrec <= prec::Conditional) {
> +    else if (getLang().CPlusPlus && NextTokPrec <= prec::Conditional)
>       RHS = ParseAssignmentExpression();
> -    } else {
> +    else
>       RHS = ParseCastExpression(false);
> -    }
>
>     if (RHS.isInvalid())
>       LHS = ExprError();
> @@ -387,6 +387,11 @@
>     // more tightly with RHS than we do, evaluate it completely first.
>     if (ThisPrec < NextTokPrec ||
>         (ThisPrec == NextTokPrec && isRightAssoc)) {
> +      if (!LHS.isInvalid() && isa<InitListExpr>(LHS.get())) {
> +        Diag(OpToken, diag::err_init_list_bin_op)
> +          << /*LHS*/0 << PP.getSpelling(OpToken) << LHS.get()->getSourceRange();
> +        LHS = ExprError();
> +      }

We normally try to avoid the Parser using AST methods directly...
granted, the distinction between Parser and Sema has started to blur a
bit, but I think it's still useful to try to maintain.

-Eli




More information about the cfe-commits mailing list