From patchwork Wed Oct 18 20:31:26 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Malcolm X-Patchwork-Id: 827822 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-464470-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="fVnpVMCC"; 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 3yHNx10vJjz9t39 for ; Thu, 19 Oct 2017 07:30:43 +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:from :to:cc:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=gVjCAeLyxFKiFjlfrrfWOlPRGdhOCUMytjB/SgNwW9cSzyZ1tIx5V mOV4CD7dz/JMlUNZRsgrGKupimzN9fZ8Er2j0SjMoqcqpSmWGtRr9X0LbUvO9evM rZJYPPT6AQfGfd5PVyMi9je/SVMK2TtKEK56VIe8IjU4Vyie090eNE= 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:from :to:cc:subject:date:message-id:in-reply-to:references; s= default; bh=Gcnmn+ATVALYNgmOYZ7Zjje3BNQ=; b=fVnpVMCCLXD7IgP2Gav0 pOhgdvy2kU04rsi8KmgjT/LTPBMhHnfIFROriiF1PPJ0oE2uvKksGkmXGyl9UXsN +lvijs46X2AwKCmLYtm8q+BsyemjXkgeeyeWV+L9h4nGLd/SKojymSmHENSWCyOw HkxJvUmI/GNKPsf3uOZQHBI= Received: (qmail 23897 invoked by alias); 18 Oct 2017 20:30:35 -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 23887 invoked by uid 89); 18 Oct 2017 20:30:35 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 18 Oct 2017 20:30:31 +0000 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5C0157EA8D; Wed, 18 Oct 2017 20:30:30 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 5C0157EA8D Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=dmalcolm@redhat.com Received: from c64.redhat.com (ovpn-112-12.phx2.redhat.com [10.3.112.12]) by smtp.corp.redhat.com (Postfix) with ESMTP id E3CED6A50B; Wed, 18 Oct 2017 20:30:27 +0000 (UTC) From: David Malcolm To: Joseph Myers Cc: gcc-patches@gcc.gnu.org, David Malcolm Subject: [PATCH] v2: C/C++: more stdlib header hints (PR c/81404) Date: Wed, 18 Oct 2017 16:31:26 -0400 Message-Id: <1508358686-48265-1-git-send-email-dmalcolm@redhat.com> In-Reply-To: References: X-IsSubscribed: yes On Tue, 2017-10-17 at 20:05 +0000, Joseph Myers wrote: > On Tue, 17 Oct 2017, David Malcolm wrote: > > > It also adds generalizes some of the code for this (and for the > > "std::" > > namespace hints in the C++ frontend), moving it to a new > > c-family/known-headers.cc and .h, and introducing a class > > known_headers. > > This currently just works by scanning a hardcoded array of known > > name/header associations, but perhaps in the future could be turned > > into some kind of symbol database so that the compiler could record > > API > > uses and use that to offer suggestions e.g. > > > > foo.cc: error: 'myapi::foo' was not declared in this scope > > foo.cc: note: 'myapi::foo" was declared in header 'myapi/private.h' > > (included via 'myapi/public.h') when compiling 'bar.cc'; did you > > forget to > > '#include "myapi/public.h"'? > > > > or somesuch. > > > > In any case, moving this to a class gives an easier way to locate > > the > > hardcoded knowledge about the stdlib. > > > > The patch also adds similar code to the C++ frontend covering > > unqualified names in the standard library, so that rather than just > > I'd tend to expect hardcoded standard library knowledge, where it > relates > to symbols present for both C and C++, to be in a common c-family > file > (e.g. listing both C and C++ headers for each symbol, with the > possibility > of some symbols only having a header listed for one C and C++; most > C > symbols would have and listed, but some might be > different, > e.g. wchar_t being a keyword in C++ or clog being completely > different in > the two libraries). That reduces the chance of a symbol being > gratuitously listed for one language only when such hints make sense > for > it in both languages. Here's an updated version of the patch, which moves the data to c-family/known-headers.cc and unifies the C and C++ data into one array. Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. OK for trunk once the prereqs are in place? gcc/ChangeLog: PR c/81404 * Makefile.in (C_COMMON_OBJS): Add c-family/known-headers.o. gcc/c-family/ChangeLog: PR c/81404 * known-headers.cc: New file, based on material from c/c-decl.c. (suggest_missing_header): Copied as-is. (get_stdlib_header_for_name): New, based on get_c_name_hint but heavily edited to add C++ support. Add some knowledge about , , and . * known-headers.h: Likewise. gcc/c/ChangeLog: PR c/81404 * c-decl.c: Include "c-family/known-headers.h". (get_c_name_hint): Rename to get_stdlib_header_for_name and move to known-headers.cc. (class suggest_missing_header): Move to known-header.h. (lookup_name_fuzzy): Call get_c_stdlib_header_for_name rather than get_c_name_hint. gcc/cp/ChangeLog: PR c/81404 * name-lookup.c: Include "c-family/known-headers.h" (lookup_name_fuzzy): Call get_cp_stdlib_header_for_name and potentially return a new suggest_missing_header hint. gcc/testsuite/ChangeLog: PR c/81404 * g++.dg/spellcheck-stdlib.C: New. * gcc.dg/spellcheck-stdlib.c (test_INT_MAX): New. --- gcc/Makefile.in | 2 +- gcc/c-family/known-headers.cc | 167 +++++++++++++++++++++++++++++++ gcc/c-family/known-headers.h | 41 ++++++++ gcc/c/c-decl.c | 82 +-------------- gcc/cp/name-lookup.c | 11 ++ gcc/testsuite/g++.dg/spellcheck-stdlib.C | 84 ++++++++++++++++ gcc/testsuite/gcc.dg/spellcheck-stdlib.c | 9 ++ 7 files changed, 317 insertions(+), 79 deletions(-) create mode 100644 gcc/c-family/known-headers.cc create mode 100644 gcc/c-family/known-headers.h create mode 100644 gcc/testsuite/g++.dg/spellcheck-stdlib.C diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 2809619..9855919 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1190,7 +1190,7 @@ C_COMMON_OBJS = c-family/c-common.o c-family/c-cppbuiltin.o c-family/c-dump.o \ c-family/c-semantics.o c-family/c-ada-spec.o \ c-family/c-cilkplus.o \ c-family/array-notation-common.o c-family/cilk.o c-family/c-ubsan.o \ - c-family/c-attribs.o c-family/c-warn.o + c-family/c-attribs.o c-family/c-warn.o c-family/known-headers.o # Language-independent object files. # We put the *-match.o and insn-*.o files first so that a parallel make diff --git a/gcc/c-family/known-headers.cc b/gcc/c-family/known-headers.cc new file mode 100644 index 0000000..1ac42f1 --- /dev/null +++ b/gcc/c-family/known-headers.cc @@ -0,0 +1,167 @@ +/* Support for suggestions about missing #include directives. + Copyright (C) 2017 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "c-family/c-common.h" +#include "c-family/known-headers.h" +#include "gcc-rich-location.h" + +/* An enum for distinguishing between the C and C++ stdlibs. */ + +enum stdlib +{ + STDLIB_C, + STDLIB_CPLUSPLUS, + + NUM_STDLIBS +}; + +/* A struct for associating names in a standard library with the header + that should be included to locate them, for each of the C and C++ stdlibs + (or NULL, for names that aren't in a header for a particular stdlib). */ + +struct stdlib_hint +{ + const char *name; + const char *header[NUM_STDLIBS]; +}; + +/* Given non-NULL NAME, return the header name defining it within either + the standard library (with '<' and '>'), or NULL. + Only handles a subset of the most common names within the stdlibs. */ + +static const char * +get_stdlib_header_for_name (const char *name, enum stdlib lib) +{ + gcc_assert (name); + gcc_assert (lib < NUM_STDLIBS); + + static const stdlib_hint hints[] = { + /* and . */ + {"errno", {"", ""} }, + + /* and . */ + {"CHAR_BIT", {"", ""} }, + {"CHAR_MAX", {"", ""} }, + {"CHAR_MIN", {"", ""} }, + {"INT_MAX", {"", ""} }, + {"INT_MIN", {"", ""} }, + {"LLONG_MAX", {"", ""} }, + {"LLONG_MIN", {"", ""} }, + {"LONG_MAX", {"", ""} }, + {"LONG_MIN", {"", ""} }, + {"MB_LEN_MAX", {"", ""} }, + {"SCHAR_MAX", {"", ""} }, + {"SCHAR_MIN", {"", ""} }, + {"SHRT_MAX", {"", ""} }, + {"SHRT_MIN", {"", ""} }, + {"UCHAR_MAX", {"", ""} }, + {"UINT_MAX", {"", ""} }, + {"ULLONG_MAX", {"", ""} }, + {"ULONG_MAX", {"", ""} }, + {"USHRT_MAX", {"", ""} }, + + /* and . */ + {"va_list", {"", ""} }, + + /* and . */ + {"NULL", {"", ""} }, + {"nullptr_t", {NULL, ""} }, + {"offsetof", {"", ""} }, + {"ptrdiff_t", {"", ""} }, + {"size_t", {"", ""} }, + {"wchar_t", {"", NULL /* a keyword in C++ */} }, + + /* . */ + {"BUFSIZ", {"", ""} }, + {"EOF", {"", ""} }, + {"FILE", {"", ""} }, + {"FILENAME_MAX", {"", ""} }, + {"fpos_t", {"", ""} }, + {"stderr", {"", ""} }, + {"stdin", {"", ""} }, + {"stdout", {"", ""} }, + + /* . */ + {"PTRDIFF_MAX", {"", ""} }, + {"PTRDIFF_MIN", {"", ""} }, + {"SIG_ATOMIC_MAX", {"", ""} }, + {"SIG_ATOMIC_MIN", {"", ""} }, + {"SIZE_MAX", {"", ""} }, + + /* . */ + {"WCHAR_MAX", {"", ""} }, + {"WCHAR_MIN", {"", ""} }, + {"WINT_MAX", {"", NULL} }, + {"WINT_MIN", {"", NULL} } + }; + const size_t num_hints = sizeof (hints) / sizeof (hints[0]); + for (size_t i = 0; i < num_hints; i++) + if (0 == strcmp (name, hints[i].name)) + return hints[i].header[lib]; + return NULL; +} + +/* Given non-NULL NAME, return the header name defining it within the C + standard library (with '<' and '>'), or NULL. */ + +const char * +get_c_stdlib_header_for_name (const char *name) +{ + return get_stdlib_header_for_name (name, STDLIB_C); +} + +/* Given non-NULL NAME, return the header name defining it within the C++ + standard library (with '<' and '>'), or NULL. */ + +const char * +get_cp_stdlib_header_for_name (const char *name) +{ + return get_stdlib_header_for_name (name, STDLIB_CPLUSPLUS); +} + +/* Implementation of class suggest_missing_header. */ + +/* suggest_missing_header's ctor. */ + +suggest_missing_header::suggest_missing_header (location_t loc, + const char *name, + const char *header_hint) +: deferred_diagnostic (loc), m_name_str (name), m_header_hint (header_hint) +{ + gcc_assert (name); + gcc_assert (header_hint); +} + +/* suggest_missing_header's dtor. */ + +suggest_missing_header::~suggest_missing_header () +{ + if (is_suppressed_p ()) + return; + + gcc_rich_location richloc (get_location ()); + maybe_add_include_fixit (&richloc, m_header_hint); + inform_at_rich_loc (&richloc, + "%qs is defined in header %qs;" + " did you forget to %<#include %s%>?", + m_name_str, m_header_hint, m_header_hint); +} diff --git a/gcc/c-family/known-headers.h b/gcc/c-family/known-headers.h new file mode 100644 index 0000000..328100f --- /dev/null +++ b/gcc/c-family/known-headers.h @@ -0,0 +1,41 @@ +/* Support for suggestions about missing #include directives. + Copyright (C) 2017 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#ifndef GCC_KNOWN_HEADERS_H +#define GCC_KNOWN_HEADERS_H + +extern const char *get_c_stdlib_header_for_name (const char *name); +extern const char *get_cp_stdlib_header_for_name (const char *name); + +/* Subclass of deferred_diagnostic for suggesting to the user + that they have missed a #include. */ + +class suggest_missing_header : public deferred_diagnostic +{ + public: + suggest_missing_header (location_t loc, const char *name, + const char *header_hint); + ~suggest_missing_header (); + + private: + const char *m_name_str; + const char *m_header_hint; +}; + +#endif /* GCC_KNOWN_HEADERS_H */ diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index ce4cb3e..93d8aab 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -54,6 +54,7 @@ along with GCC; see the file COPYING3. If not see #include "spellcheck-tree.h" #include "gcc-rich-location.h" #include "asan.h" +#include "c-family/known-headers.h" /* In grokdeclarator, distinguish syntactic contexts of declarators. */ enum decl_context @@ -3983,83 +3984,6 @@ lookup_name_in_scope (tree name, struct c_scope *scope) return NULL_TREE; } -/* Subroutine of lookup_name_fuzzy for handling unrecognized names - for some of the most common names within the C standard library. - Given non-NULL NAME, return the header name defining it within the C - standard library (with '<' and '>'), or NULL. */ - -static const char * -get_c_name_hint (const char *name) -{ - struct std_name_hint - { - const char *name; - const char *header; - }; - static const std_name_hint hints[] = { - /* . */ - {"errno", ""}, - - /* . */ - {"va_list", ""}, - - /* . */ - {"NULL", ""}, - {"ptrdiff_t", ""}, - {"wchar_t", ""}, - {"size_t", ""}, - - /* . */ - {"BUFSIZ", ""}, - {"EOF", ""}, - {"FILE", ""}, - {"FILENAME_MAX", ""}, - {"fpos_t", ""}, - {"stderr", ""}, - {"stdin", ""}, - {"stdout", ""} - }; - const size_t num_hints = sizeof (hints) / sizeof (hints[0]); - for (size_t i = 0; i < num_hints; i++) - { - if (0 == strcmp (name, hints[i].name)) - return hints[i].header; - } - return NULL; -} - -/* Subclass of deferred_diagnostic for suggesting to the user - that they have missed a #include. */ - -class suggest_missing_header : public deferred_diagnostic -{ - public: - suggest_missing_header (location_t loc, const char *name, - const char *header_hint) - : deferred_diagnostic (loc), m_name_str (name), m_header_hint (header_hint) - { - gcc_assert (name); - gcc_assert (header_hint); - } - - ~suggest_missing_header () - { - if (is_suppressed_p ()) - return; - - gcc_rich_location richloc (get_location ()); - maybe_add_include_fixit (&richloc, m_header_hint); - inform_at_rich_loc (&richloc, - "%qs is defined in header %qs;" - " did you forget to %<#include %s%>?", - m_name_str, m_header_hint, m_header_hint); - } - - private: - const char *m_name_str; - const char *m_header_hint; -}; - /* Look for the closest match for NAME within the currently valid scopes. @@ -4085,7 +4009,9 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t loc) /* First, try some well-known names in the C standard library, in case the user forgot a #include. */ - const char *header_hint = get_c_name_hint (IDENTIFIER_POINTER (name)); + const char *header_hint + = get_c_stdlib_header_for_name (IDENTIFIER_POINTER (name)); + if (header_hint) return name_hint (NULL, new suggest_missing_header (loc, diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index dec93ad..5de320f 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "gcc-rich-location.h" #include "spellcheck-tree.h" #include "parser.h" +#include "c-family/known-headers.h" static cxx_binding *cxx_binding_make (tree value, tree type); static cp_binding_level *innermost_nonclass_level (void); @@ -5672,6 +5673,16 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t loc) { gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); + /* First, try some well-known names in the C++ standard library, in case + the user forgot a #include. */ + const char *header_hint + = get_cp_stdlib_header_for_name (IDENTIFIER_POINTER (name)); + if (header_hint) + return name_hint (NULL, + new suggest_missing_header (loc, + IDENTIFIER_POINTER (name), + header_hint)); + best_match bm (name); cp_binding_level *lvl; diff --git a/gcc/testsuite/g++.dg/spellcheck-stdlib.C b/gcc/testsuite/g++.dg/spellcheck-stdlib.C new file mode 100644 index 0000000..6e6ab1d --- /dev/null +++ b/gcc/testsuite/g++.dg/spellcheck-stdlib.C @@ -0,0 +1,84 @@ +/* Missing . */ + +void *ptr = NULL; // { dg-error "'NULL' was not declared" } +// { dg-message "'NULL' is defined in header ''; did you forget to '#include '?" "" { target *-*-* } .-1 } + +ptrdiff_t pd; // { dg-error "'ptrdiff_t' does not name a type" } +// { dg-message "'ptrdiff_t' is defined in header ''; did you forget to '#include '?" "" { target *-*-* } .-1 } + +size_t sz; // { dg-error "'size_t' does not name a type" } +// { dg-message "'size_t' is defined in header ''; did you forget to '#include '?" "" { target *-*-* } .-1 } + +/* Missing . */ + +void test_cstdio (void) +{ + FILE *f; // { dg-error "'FILE' was not declared in this scope" } + // { dg-message "'FILE' is defined in header ''; did you forget to '#include '?" "" { target *-*-* } .-1 } + // { dg-error "'f' was not declared in this scope" "" { target *-*-* } .-2 } + // { dg-bogus "suggested alternative: 'if'" "PR c++/80567" { xfail *-*-* } .-3 } + + char buf[BUFSIZ]; // { dg-error "'BUFSIZ' was not declared" } + // { dg-message "'BUFSIZ' is defined in header ''; did you forget to '#include '?" "" { target *-*-* } .-1 } + + char buf2[FILENAME_MAX]; // { dg-error "'FILENAME_MAX' was not declared" } + // { dg-message "'FILENAME_MAX' is defined in header ''; did you forget to '#include '?" "" { target *-*-* } .-1 } + + stderr; // { dg-error "'stderr' was not declared" } + // { dg-message "'stderr' is defined in header ''; did you forget to '#include '?" "" { target *-*-* } .-1 } + + stdin; // { dg-error "'stdin' was not declared" } + // { dg-message "'stdin' is defined in header ''; did you forget to '#include '?" "" { target *-*-* } .-1 } + + stdout; // { dg-error "'stdout' was not declared" } + // { dg-message "'stdout' is defined in header ''; did you forget to '#include '?" "" { target *-*-* } .-1 } + + EOF; // { dg-error "'EOF' was not declared" } + // { dg-message "'EOF' is defined in header ''; did you forget to '#include '?" "" { target *-*-* } .-1 } +} + +/* Missing . */ + +int test_cerrno (void) +{ + return errno; // { dg-error "'errno' was not declared" } + // { dg-message "'errno' is defined in header ''; did you forget to '#include '?" "" { target *-*-* } .-1 } +} + +/* Missing . */ + +void test_cstdarg (void) +{ + va_list ap; // { dg-error "'va_list'" } + // { dg-message "'va_list' is defined in header ''; did you forget to '#include '?" "" { target *-*-* } .-1 } +} + +/* Missing . */ +int test_INT_MAX (void) +{ + return INT_MAX; // { dg-line INT_MAX_line } + // { dg-error "'INT_MAX' was not declared" "" { target *-*-* } INT_MAX_line } + // { dg-bogus "__INT_MAX__" "" { target *-*-* } INT_MAX_line } + // { dg-message "'INT_MAX' is defined in header ''; did you forget to '#include '?" "" { target *-*-* } INT_MAX_line } +} + +/* Verify that we don't offer suggestions to stdlib globals names when + there's an explicit namespace. */ + +namespace some_ns {} + +int not_within_namespace (void) +{ + return some_ns::stdout; // { dg-error "'stdout' is not a member of 'some_ns'" } + // { dg-bogus "is defined in header" "" { target *-*-* } .-1 } +} + +/* Similarly for when there's an explicit class scope. */ + +class some_class {}; + +int not_within_class (void) +{ + return some_class::stdout; // { dg-error "'stdout' is not a member of 'some_class'" } + // { dg-bogus "is defined in header" "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/gcc.dg/spellcheck-stdlib.c b/gcc/testsuite/gcc.dg/spellcheck-stdlib.c index 85a21c3..7474c9a 100644 --- a/gcc/testsuite/gcc.dg/spellcheck-stdlib.c +++ b/gcc/testsuite/gcc.dg/spellcheck-stdlib.c @@ -53,3 +53,12 @@ void test_stdarg_h (void) va_list ap; /* { dg-error "unknown type name 'va_list'" } */ /* { dg-message "'va_list' is defined in header ''; did you forget to '#include '?" "" { target *-*-* } .-1 } */ } + +/* Missing . */ +int test_INT_MAX (void) +{ + return INT_MAX; /* { dg-line INT_MAX_line } */ + /* { dg-error "'INT_MAX' undeclared" "" { target *-*-* } INT_MAX_line } */ + /* { dg-bogus "__INT_MAX__" "" { target *-*-* } INT_MAX_line } */ + /* { dg-message "'INT_MAX' is defined in header ''; did you forget to '#include '?" "" { target *-*-* } INT_MAX_line } */ +}