From patchwork Wed Jun 24 18:36:45 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?TWFudWVsIEzDs3Blei1JYsOhw7Fleg==?= X-Patchwork-Id: 488166 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 240721402DE for ; Thu, 25 Jun 2015 04:37:41 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=XmuY6hTU; 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=BuOSxKe51q1PQzoScNFAUuGoBsHr+GnBXX1lLqK2qJ9p69 e2+XN2NYinU9YBYRTAxVu4k/nLXy6AoZCH3uQ8cPbyWiz8dXTnkyblN5GzIdnlep 0psX0gk7LcGqAvOXD2TYHqOXoYx2HB//lJAJOa9Wla9OFE0LFmZWRVX21jiJs= 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=c6RozWNRciZKP2/J0hgygywjtoQ=; b=XmuY6hTUvhFZhhuKl3x6 bhg6QFKDkNawtDhtzOn33VJ17WquW1VECm0B+od7YR/VdFKUmusy85m9xg7oCTsA wuLe6NQJ/efGDWTT/kIjiD9Ds+8f9eeL61K65uNJegbTkp/GCmFQXUWFx7/1JApU XvLqDhFE3Wq0T7oBtdztkDQ= Received: (qmail 107050 invoked by alias); 24 Jun 2015 18:37:34 -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 107033 invoked by uid 89); 24 Jun 2015 18:37:33 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.2 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=no version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mail-wi0-f170.google.com Received: from mail-wi0-f170.google.com (HELO mail-wi0-f170.google.com) (209.85.212.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Wed, 24 Jun 2015 18:37:28 +0000 Received: by wicnd19 with SMTP id nd19so143345784wic.1; Wed, 24 Jun 2015 11:37:25 -0700 (PDT) X-Received: by 10.194.192.166 with SMTP id hh6mr71345049wjc.127.1435171045344; Wed, 24 Jun 2015 11:37:25 -0700 (PDT) MIME-Version: 1.0 Received: by 10.28.180.133 with HTTP; Wed, 24 Jun 2015 11:36:45 -0700 (PDT) From: =?UTF-8?B?TWFudWVsIEzDs3Blei1JYsOhw7Fleg==?= Date: Wed, 24 Jun 2015 20:36:45 +0200 Message-ID: Subject: [PR fortran/66528] unbalanced IF/ENDIF with -fmax-errors=1 causes invalid free To: "fortran@gcc.gnu.org List" , Gcc Patch List The problem is that diagnostic_action_after_output tries to delete the active pretty-printer which tries to delete its output_buffer, which is normally dynamically allocated via placement-new, but the output_buffer used by the error_buffer of Fortran is statically allocated. Being statically allocated simplifies a lot pushing/poping several instances of error_buffer. The solution I found is to reset the active output_buffer back to the default one before calling diagnostic_action_after_output. This is a bit ugly, because this function does use the output_buffer, however, at the point that Fortran calls it, both are in an equivalent state, thus there is no visible difference. Bootstrapped and regression tested on x86_64-linux-gnu. 2015-06-24 Manuel López-Ibáñez PR fortran/66528 * gfortran.dg/maxerrors.f90: New test. gcc/fortran/ChangeLog: 2015-06-24 Manuel López-Ibáñez PR fortran/66528 * error.c (gfc_warning_check): Restore the default output_buffer before calling diagnostic_action_after_output. (gfc_error_check): Likewise. (gfc_diagnostics_init): Add comment. Index: gcc/testsuite/gfortran.dg/maxerrors.f90 =================================================================== --- gcc/testsuite/gfortran.dg/maxerrors.f90 (revision 0) +++ gcc/testsuite/gfortran.dg/maxerrors.f90 (revision 0) @@ -0,0 +1,12 @@ +! { dg-do compile } +! { dg-options "-fmax-errors=1" } +! PR66528 +! { dg-prune-output "compilation terminated" } +program main + read (*,*) n + if (n<0) then + print *,foo + end ! { dg-error "END IF statement expected" } + print *,bar +end program main + Index: gcc/fortran/error.c =================================================================== --- gcc/fortran/error.c (revision 224844) +++ gcc/fortran/error.c (working copy) @@ -1247,24 +1247,23 @@ gfc_clear_warning (void) If so, print the warning. */ void gfc_warning_check (void) { - /* This is for the new diagnostics machinery. */ if (! gfc_output_buffer_empty_p (pp_warning_buffer)) { pretty_printer *pp = global_dc->printer; output_buffer *tmp_buffer = pp->buffer; pp->buffer = pp_warning_buffer; pp_really_flush (pp); warningcount += warningcount_buffered; werrorcount += werrorcount_buffered; gcc_assert (warningcount_buffered + werrorcount_buffered == 1); + pp->buffer = tmp_buffer; diagnostic_action_after_output (global_dc, warningcount_buffered ? DK_WARNING : DK_ERROR); - pp->buffer = tmp_buffer; } } /* Issue an error. */ @@ -1379,12 +1378,12 @@ gfc_error_check (void) output_buffer *tmp_buffer = pp->buffer; pp->buffer = pp_error_buffer; pp_really_flush (pp); ++errorcount; gcc_assert (gfc_output_buffer_empty_p (pp_error_buffer)); - diagnostic_action_after_output (global_dc, DK_ERROR); pp->buffer = tmp_buffer; + diagnostic_action_after_output (global_dc, DK_ERROR); return true; } return false; } @@ -1470,10 +1469,12 @@ gfc_diagnostics_init (void) diagnostic_format_decoder (global_dc) = gfc_format_decoder; global_dc->caret_chars[0] = '1'; global_dc->caret_chars[1] = '2'; pp_warning_buffer = new (XNEW (output_buffer)) output_buffer (); pp_warning_buffer->flush_p = false; + /* pp_error_buffer is statically allocated. This simplifies memory + management when using gfc_push/pop_error. */ pp_error_buffer = &(error_buffer.buffer); pp_error_buffer->flush_p = false; } void