From patchwork Mon Jul 25 18:29:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 652379 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3ryqYQ0w6Gz9sCZ for ; Tue, 26 Jul 2016 04:30:01 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=laRty8eA; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=QDIuUHXOsc7cj6qHM7Wx5Oeeew573NIjjg9ZvZnXd64B5i mMc/gYP1cYS26ZMKwahENPkyg2i0ILSUZ9yomtScN/B3OiyUsmreKYvKMk8DHm5+ glo6tNsWflK49fLG7eyIa6m2h6OHRKCkUfEuSrU8qGhrbXrY4dDFx4Lhd8b9A= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=66FIhkfIk78PvCUtcO82z035SpI=; b=laRty8eA3YW9LqVVSNcD sXhvruKfB/ofaD1FzOlR2UTCYxKqyppMM+9/F2PwJ0KjgC1XW7dfKDduSZlOd2eY +U3mSLDeIjOTEzcuoPy+7xqVhg+GzWODNiNCkoomUxQBulN/xl3Kng43ppsMHg4l PwFVb/a66DIkxrOPYXTrTr0= Received: (qmail 127199 invoked by alias); 25 Jul 2016 18:29:53 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 127177 invoked by uid 89); 25 Jul 2016 18:29:52 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.2 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 spammy=Controlling, !cond, input_location, 1918 X-HELO: mail-oi0-f41.google.com Received: from mail-oi0-f41.google.com (HELO mail-oi0-f41.google.com) (209.85.218.41) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Mon, 25 Jul 2016 18:29:51 +0000 Received: by mail-oi0-f41.google.com with SMTP id j185so264250637oih.0 for ; Mon, 25 Jul 2016 11:29:51 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=zvxBwsjS9Jtu5j1g0SKShni94Gw94h3ZULlx4PfKruU=; b=invN6iC2E3pn84FRijilyg7xpSbSzeQbZlAzHPHlUqJRLyrmThr+Zjwro7OsxADvfb AScT/VlbDd+PjiFmbDnWKrJjUr7gX150Jv92VRD5YerxPWUMzeQg+wg/dtKTwlEcy+zm OuviSLHp+/4kyWBpCypPhwiHnSGWJtuDqpMS+jTbYjWf3/HNMdujGhtL+xUujoZVsHuq gH5e5kS4lx7fdnRO1I1mGdmpr3W1PAhX/id7hVhi1stvkCHXMhmR9MWamq6ByWv00THC f9cgEf5jJZad3ez4eVyr3CZMOnqFRJVsnJsgXOkeJE3q6o1Ddi/GByfisKb/Xg4aMp+k n5YA== X-Gm-Message-State: AEkoouuCr4m+4uTJ676nT4XMBID34B3mdbklcAA24X8UFs/baj6leANDMJYv1TUYKGEpUzJnq8LoBbsKFAZs+eFM X-Received: by 10.157.10.76 with SMTP id 70mr9871446otg.13.1469471389122; Mon, 25 Jul 2016 11:29:49 -0700 (PDT) MIME-Version: 1.0 Received: by 10.182.105.169 with HTTP; Mon, 25 Jul 2016 11:29:29 -0700 (PDT) From: Jason Merrill Date: Mon, 25 Jul 2016 14:29:29 -0400 Message-ID: Subject: C++ PATCH for c++/65970 (constexpr infinite loop) To: gcc-patches List X-IsSubscribed: yes An infinite loop in a constexpr function led to a compiler hang. Fixed by putting an upper bound on loop iterations in constexpr evaluation. Tested x86_64-pc-linux-gnu, applying to trunk. commit 6c93c22a799e5ea5e1cdfe661476cf123ed1a4e8 Author: Jason Merrill Date: Mon Jul 25 10:31:10 2016 -0400 PR c++/65970 - constexpr infinite loop gcc/c-family/ * c.opt (fconstexpr-loop-limit): New. gcc/cp/ * constexpr.c (cxx_eval_loop_expr): Count iterations. * cp-gimplify.c (genericize_cp_loop): Use start_locus even for infinite loops. diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 8c70152..a5358ed 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -1174,6 +1174,10 @@ fconstexpr-depth= C++ ObjC++ Joined RejectNegative UInteger Var(max_constexpr_depth) Init(512) -fconstexpr-depth= Specify maximum constexpr recursion depth. +fconstexpr-loop-limit= +C++ ObjC++ Joined RejectNegative UInteger Var(constexpr_loop_limit) Init(262144) +-fconstexpr-loop-limit= Specify maximum constexpr loop iteration count. + fdebug-cpp C ObjC C++ ObjC++ Emit debug annotations during preprocessing. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 47fb39b..6bcb41a 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -3468,6 +3468,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, constexpr_ctx new_ctx = *ctx; tree body = TREE_OPERAND (t, 0); + int count = 0; do { hash_set save_exprs; @@ -3480,6 +3481,16 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, for (hash_set::iterator iter = save_exprs.begin(); iter != save_exprs.end(); ++iter) new_ctx.values->remove (*iter); + if (++count >= constexpr_loop_limit) + { + if (!ctx->quiet) + error_at (EXPR_LOC_OR_LOC (t, input_location), + "constexpr loop iteration count exceeds limit of %d " + "(use -fconstexpr-loop-limit= to increase the limit)", + constexpr_loop_limit); + *non_constant_p = true; + break; + } } while (!returns (jump_target) && !breaks (jump_target) && !*non_constant_p); diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 59953a6..d9f7cea 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -264,14 +264,7 @@ genericize_cp_loop (tree *stmt_p, location_t start_locus, tree cond, tree body, loop = stmt_list; } else - { - location_t loc = start_locus; - if (!cond || integer_nonzerop (cond)) - loc = EXPR_LOCATION (expr_first (body)); - if (loc == UNKNOWN_LOCATION) - loc = start_locus; - loop = build1_loc (loc, LOOP_EXPR, void_type_node, stmt_list); - } + loop = build1_loc (start_locus, LOOP_EXPR, void_type_node, stmt_list); stmt_list = NULL; append_to_statement_list (loop, &stmt_list); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 9e0f07e..79c842d 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -191,7 +191,8 @@ in the following sections. @xref{C++ Dialect Options,,Options Controlling C++ Dialect}. @gccoptlist{-fabi-version=@var{n} -fno-access-control @gol -fargs-in-order=@var{n} -fcheck-new @gol --fconstexpr-depth=@var{n} -ffriend-injection @gol +-fconstexpr-depth=@var{n} -fconstexpr-loop-limit=@var{n} @gol +-ffriend-injection @gol -fno-elide-constructors @gol -fno-enforce-eh-specs @gol -ffor-scope -fno-for-scope -fno-gnu-keywords @gol @@ -2265,6 +2266,12 @@ to @var{n}. A limit is needed to detect endless recursion during constant expression evaluation. The minimum specified by the standard is 512. +@item -fconstexpr-loop-limit=@var{n} +@opindex fconstexpr-loop-limit +Set the maximum number of iterations for a loop in C++14 constexpr functions +to @var{n}. A limit is needed to detect infinite loops during +constant expression evaluation. The default is 262144 (1<<18). + @item -fdeduce-init-list @opindex fdeduce-init-list Enable deduction of a template type parameter as diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-loop6.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-loop6.C new file mode 100644 index 0000000..e49e531 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-loop6.C @@ -0,0 +1,11 @@ +// PR c++/65970 +// { dg-do compile { target c++14 } } +// { dg-options -fconstexpr-loop-limit=5 } + +constexpr int foo() { + while (true) // { dg-error "-fconstexpr-loop-limit" } + ; + return 0; +} + +constexpr int i = foo(); // { dg-message "" }