From patchwork Thu Feb 27 22:40:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 1246152 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-520276-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha1 header.s=default header.b=Ng/ygY4/; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=pBi6eu2z; dkim-atps=neutral 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 48T71S66c6z9sPk for ; Fri, 28 Feb 2020 09:40:58 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=OmfLkrtaYNBe0pA1ZhKaLyz6on9HznOhLx/r5mPSMSXFAhndkK eP6DnLy31s5g5Shead01airmwFDO2y6aAlxIiefxi+D8WcDxtIYZTtt18WMSkrNj A9wvvArluUFA3zi90Mcl6PrKSLF7iqcJMwm8p99e/cMvDMbLxFddeB7fk= 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:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=acKJOXGD6LR9ov7ZogmsYY2Zwlg=; b=Ng/ygY4/QNgqlJDbOnhj P/ciP06KP9dYr2MaVZgWLlzKNRXdDA5/CHj+NPcd1slUqq4snKJjZo/9sZL8uCVj 0BAZMvlRtsEVxLEpFAPaj9hCv+MhI4Bt6bx0FdQdJ0dsoqry6Wu8I3h+c2QxCE++ Po7LVErvINnT0/KxY1blTlk= Received: (qmail 25817 invoked by alias); 27 Feb 2020 22:40:51 -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 25809 invoked by uid 89); 27 Feb 2020 22:40:50 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-20.1 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=notion, tighten, strdup X-HELO: mail-qk1-f172.google.com Received: from mail-qk1-f172.google.com (HELO mail-qk1-f172.google.com) (209.85.222.172) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 27 Feb 2020 22:40:41 +0000 Received: by mail-qk1-f172.google.com with SMTP id 145so1203663qkl.2 for ; Thu, 27 Feb 2020 14:40:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=to:from:subject:message-id:date:user-agent:mime-version :content-language; bh=z8GvD1CHCDuV0IHoGC2W5Qv0o7xCsH7Ml8nvsFVG7ew=; b=pBi6eu2zCLnV4IQQwn1Gc8VEL4u/2MGoz3uNTfB+xZCnakUYslne4b6eDHhSPGBcqZ XZ+9GouUkjw+zIyFXqQscr1xR/N/reMfV9zqAL0R/6SnQ4+NFdrEiBtC7yYBzgNCiS0a dcvYDLHfbkDVrBnFPCMdexsSmULkkpDfVymmKwrQrB18RnK8KLUZ9RkTPo40bJG23o3K tFbXPB367anT3it3OW5iIRuQXJZloBcagUy5reTqBJQHHvNQw82N9yKM9Qa+rPt0Obc7 +zN80u9HjY0aPlC2dXxgc2MyeF0zvnZEqariXiEW/VoeMhCs1R8jid3UaJoAzvAusqgg wfdA== Received: from [192.168.0.41] (174-16-106-242.hlrn.qwest.net. [174.16.106.242]) by smtp.gmail.com with ESMTPSA id h34sm4093994qtc.62.2020.02.27.14.40.38 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 27 Feb 2020 14:40:39 -0800 (PST) To: gcc-patches From: Martin Sebor Subject: [PATCH] tighten up validation of built-in redeclarations (PR 93926) Message-ID: <062e3164-0f7f-8352-f105-3250c380833a@gmail.com> Date: Thu, 27 Feb 2020 15:40:37 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.6.1 MIME-Version: 1.0 X-IsSubscribed: yes GCC considers valid explicit declarations of built-ins whose return types match in their modes, even if the types themselves are incompatible (say integer and pointer of the same size). This is more permissive than for argument types where a pointer/integer mismatch disqualifies the redeclaration. With -Wextra enabled although -Wbuiltin-declaration-mismatch diagnoses these "benign" mismatches in return types the C front-end still considers the mismatched declaration one of the built-in. That can lead to problems down the line when the middle attempts to do its own sanity checking based on some simple and reasonable notion of type compatibility (like a malloc kind of function returning a pointer). The attached patch tightens up the requirements a declaration has to meet in order to match a built-in to apply the same matching to their return types as to their arguments. Tested on x86_64-linux. Martin PR middle-end/93926 - ICE on a built-in redeclaration returning an integer instead of a pointer gcc/c/ChangeLog: PR middle-end/93926 * c-decl.c (types_close_enough_to_match): New function. (match_builtin_function_types): (diagnose_mismatched_decls): Add missing inform call to a warning. gcc/testsuite/ChangeLog: PR middle-end/93926 * gcc.dg/Wbuiltin-declaration-mismatch-13.c: New test. diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 1aa410db6e4..da276e981fa 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -1649,6 +1649,18 @@ c_bind (location_t loc, tree decl, bool is_global) static GTY(()) tree last_structptr_types[6]; +/* Returns true if types T1 and T2 representing return types or types + of function arguments are close enough to be considered interchangeable + in redeclarations of built-in functions. */ + +static bool +types_close_enough_to_match (tree t1, tree t2) +{ + return (TYPE_MODE (t1) == TYPE_MODE (t2) + && POINTER_TYPE_P (t1) == POINTER_TYPE_P (t2) + && FUNCTION_POINTER_TYPE_P (t1) == FUNCTION_POINTER_TYPE_P (t2)); +} + /* Subroutine of compare_decls. Allow harmless mismatches in return and argument types provided that the type modes match. Set *STRICT and *ARGNO to the expected argument type and number in case of @@ -1659,16 +1671,19 @@ static tree match_builtin_function_types (tree newtype, tree oldtype, tree *strict, unsigned *argno) { - /* Accept the return type of the new declaration if same modes. */ - tree oldrettype = TREE_TYPE (oldtype); - tree newrettype = TREE_TYPE (newtype); - *argno = 0; *strict = NULL_TREE; - if (TYPE_MODE (oldrettype) != TYPE_MODE (newrettype)) + /* Accept the return type of the new declaration if it has the same + mode and if they're both pointers or if neither is. */ + tree oldrettype = TREE_TYPE (oldtype); + tree newrettype = TREE_TYPE (newtype); + + if (!types_close_enough_to_match (oldrettype, newrettype)) return NULL_TREE; + /* Check that the return types are compatible but don't fail if they + are not (e.g., int vs long in ILP32) and just let the caller know. */ if (!comptypes (TYPE_MAIN_VARIANT (oldrettype), TYPE_MAIN_VARIANT (newrettype))) *strict = oldrettype; @@ -1692,15 +1707,7 @@ match_builtin_function_types (tree newtype, tree oldtype, tree oldtype = TYPE_MAIN_VARIANT (TREE_VALUE (oldargs)); tree newtype = TYPE_MAIN_VARIANT (TREE_VALUE (newargs)); - /* Fail for types with incompatible modes/sizes. */ - if (TYPE_MODE (TREE_VALUE (oldargs)) - != TYPE_MODE (TREE_VALUE (newargs))) - return NULL_TREE; - - /* Fail for function and object pointer mismatches. */ - if ((FUNCTION_POINTER_TYPE_P (oldtype) - != FUNCTION_POINTER_TYPE_P (newtype)) - || POINTER_TYPE_P (oldtype) != POINTER_TYPE_P (newtype)) + if (!types_close_enough_to_match (oldtype, newtype)) return NULL_TREE; unsigned j = (sizeof (builtin_structptr_types) @@ -1957,11 +1964,10 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, && !C_DECL_DECLARED_BUILTIN (olddecl)) { /* Accept "harmless" mismatches in function types such - as missing qualifiers or pointer vs same size integer - mismatches. This is for the ffs and fprintf builtins. - However, with -Wextra in effect, diagnose return and - argument types that are incompatible according to - language rules. */ + as missing qualifiers or int vs long when they're the same + size. However, with -Wextra in effect, diagnose return and + argument types that are incompatible according to language + rules. */ tree mismatch_expect; unsigned mismatch_argno; @@ -1999,16 +2005,25 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, /* If types match only loosely, print a warning but accept the redeclaration. */ location_t newloc = DECL_SOURCE_LOCATION (newdecl); + bool warned = false; if (mismatch_argno) - warning_at (newloc, OPT_Wbuiltin_declaration_mismatch, - "mismatch in argument %u type of built-in " - "function %qD; expected %qT", - mismatch_argno, newdecl, mismatch_expect); + warned = warning_at (newloc, OPT_Wbuiltin_declaration_mismatch, + "mismatch in argument %u type of built-in " + "function %qD; expected %qT", + mismatch_argno, newdecl, mismatch_expect); else - warning_at (newloc, OPT_Wbuiltin_declaration_mismatch, - "mismatch in return type of built-in " - "function %qD; expected %qT", - newdecl, mismatch_expect); + warned = warning_at (newloc, OPT_Wbuiltin_declaration_mismatch, + "mismatch in return type of built-in " + "function %qD; expected %qT", + newdecl, mismatch_expect); + const char *header = header_for_builtin_fn (olddecl); + if (warned && header) + { + rich_location richloc (line_table, newloc); + maybe_add_include_fixit (&richloc, header, true); + inform (&richloc, + "%qD is declared in header %qs", olddecl, header); + } } } else if (TREE_CODE (olddecl) == FUNCTION_DECL diff --git a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-13.c b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-13.c new file mode 100644 index 00000000000..f21f407e181 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-13.c @@ -0,0 +1,78 @@ +/* PR middle-end/93926 - ICE on a built-in redeclaration returning an integer + instead of a pointer + { dg-do compile } + { dg-options "-Wall" } */ + +typedef __SIZE_TYPE__ size_t; + +void* ret_calloc (size_t n1, size_t n2) +{ + extern size_t calloc (size_t, size_t); // { dg-warning "\\\[-Wbuiltin-declaration-mismatch" } + + return (void *) calloc (n1, n2); +} + +void* ret_malloc (size_t n) +{ + extern size_t malloc (size_t); // { dg-warning "\\\[-Wbuiltin-declaration-mismatch" } + + return (void *) malloc (n); +} + +void* ret_realloc (void *p, size_t n) +{ + extern size_t realloc (void *p, size_t); // { dg-warning "\\\[-Wbuiltin-declaration-mismatch" } + + return (void *) realloc (p, n); +} + +void* ret_strdup (const char *s) +{ + extern size_t strdup (const char*); // { dg-warning "\\\[-Wbuiltin-declaration-mismatch" } + + return (void *) strdup (s); +} + +void* ret_strndup (const char *s, size_t n) +{ + extern size_t + strndup (const char*, size_t); // { dg-warning "\\\[-Wbuiltin-declaration-mismatch" } + + return (void *) strndup (s, n); +} + +// For good measure also exerise strcmp return type (not part of the bug). + +char* ret_strcmp (const char *s, const char *t) +{ + extern char* + strcmp (const char*, const char*); // { dg-warning "\\\[-Wbuiltin-declaration-mismatch" } + + return strcmp (s, t); +} + +// Exercise warnings for pointer/integer mismatches in argument types +// (also not part of the bug). + +char* ret_strcat (size_t s, const char *t) +{ + extern char* + strcat (size_t, const char*); // { dg-warning "\\\[-Wbuiltin-declaration-mismatch" } + + return strcat (s, t); +} + +char* ret_strcpy (char *s, size_t t) +{ + extern char* strcpy (char*, size_t); // { dg-warning "\\\[-Wbuiltin-declaration-mismatch" } + + return strcpy (s, t); +} + +char* ret_strncpy (char *s, const char *t, size_t n) +{ + extern char* + strncpy (char*, size_t, const char*); // { dg-warning "\\\[-Wbuiltin-declaration-mismatch" } + + return strncpy (s, n, t); +}