[cfe-dev] r372437 - Fix assertion failure when constant evaluation of a switch jumps over an

Richard Smith via cfe-dev cfe-dev at lists.llvm.org
Mon Sep 23 17:29:19 PDT 2019


On Mon, 23 Sep 2019 at 14:52, Eli Friedman via cfe-dev <
cfe-dev at lists.llvm.org> wrote:

> It looks like there's a similar crash with while loops, e.g. "while (int
> m)".  That isn't valid, of course, but we try to perform constexpr
> evaluation anyway.
>

Yes. That's at least not really a regression; we've crashed for a long time
on things like

constexpr int f() {
    switch (1) {
        while (int m = 1) {
            case 1:
            return m;
        }
    }
}

constexpr int k = f();

I guess it'd make sense to just treat this case as non-constant rather than
asserting. (Though it does raise a question of what AST invariants it's
safe to rely on from the constant evaluator.)


> -Eli
>
> -----Original Message-----
> From: cfe-commits <cfe-commits-bounces at lists.llvm.org> On Behalf Of
> Richard Smith via cfe-commits
> Sent: Friday, September 20, 2019 4:09 PM
> To: cfe-commits at lists.llvm.org
> Subject: [EXT] r372437 - Fix assertion failure when constant evaluation of
> a switch jumps over an
>
> Author: rsmith
> Date: Fri Sep 20 16:08:59 2019
> New Revision: 372437
>
> URL: http://llvm.org/viewvc/llvm-project?rev=372437&view=rev
> Log:
> Fix assertion failure when constant evaluation of a switch jumps over an
> uninitialized variable in an init-statement of a 'for' or 'if'.
>
> Modified:
>     cfe/trunk/lib/AST/ExprConstant.cpp
>     cfe/trunk/test/SemaCXX/constant-expression-cxx2a.cpp
>
> Modified: cfe/trunk/lib/AST/ExprConstant.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=372437&r1=372436&r2=372437&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
> +++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Sep 20 16:08:59 2019
> @@ -4131,6 +4131,21 @@ static EvalStmtResult EvaluateStmt(StmtR
>        // preceded by our switch label.
>        BlockScopeRAII Scope(Info);
>
> +      // Step into the init statement in case it brings an (uninitialized)
> +      // variable into scope.
> +      if (const Stmt *Init = IS->getInit()) {
> +        EvalStmtResult ESR = EvaluateStmt(Result, Info, Init, Case);
> +        if (ESR != ESR_CaseNotFound) {
> +          assert(ESR != ESR_Succeeded);
> +          return ESR;
> +        }
> +      }
> +
> +      // Condition variable must be initialized if it exists.
> +      // FIXME: We can skip evaluating the body if there's a condition
> +      // variable, as there can't be any case labels within it.
> +      // (The same is true for 'for' statements.)
> +
>        EvalStmtResult ESR = EvaluateStmt(Result, Info, IS->getThen(),
> Case);
>        if (ESR != ESR_CaseNotFound || !IS->getElse())
>          return ESR;
> @@ -4147,6 +4162,18 @@ static EvalStmtResult EvaluateStmt(StmtR
>
>      case Stmt::ForStmtClass: {
>        const ForStmt *FS = cast<ForStmt>(S);
> +      BlockScopeRAII Scope(Info);
> +
> +      // Step into the init statement in case it brings an (uninitialized)
> +      // variable into scope.
> +      if (const Stmt *Init = FS->getInit()) {
> +        EvalStmtResult ESR = EvaluateStmt(Result, Info, Init, Case);
> +        if (ESR != ESR_CaseNotFound) {
> +          assert(ESR != ESR_Succeeded);
> +          return ESR;
> +        }
> +      }
> +
>        EvalStmtResult ESR =
>            EvaluateLoopBody(Result, Info, FS->getBody(), Case);
>        if (ESR != ESR_Continue)
>
> Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx2a.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx2a.cpp?rev=372437&r1=372436&r2=372437&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/constant-expression-cxx2a.cpp (original)
> +++ cfe/trunk/test/SemaCXX/constant-expression-cxx2a.cpp Fri Sep 20
> 16:08:59 2019
> @@ -620,4 +620,17 @@ namespace Uninit {
>    constexpr int s1 = switch_var(1);
>    constexpr int s2 = switch_var(2);
>    static_assert(s1 == 1 && s2 == 2);
> +
> +  constexpr bool switch_into_init_stmt() {
> +    switch (1) {
> +      if (int n; false) {
> +        for (int m; false;) {
> +        case 1:
> +          n = m = 1;
> +          return n == 1 && m == 1;
> +        }
> +      }
> +    }
> +  }
> +  static_assert(switch_into_init_stmt());
>  }
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20190923/bfd4c59f/attachment.html>


More information about the cfe-dev mailing list