OK.
On Thu, Mar 22, 2018 at 7:44 PM, David Malcolm <dmalc...@redhat.com> wrote: > PR c++/84269 reports a number of names in the C and C++ standard > libraries for which we don't yet offer #include fix-it hints. > > This patch adds them (up to comment #9). > > Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. > > OK for trunk? > > gcc/c-family/ChangeLog: > PR c++/84269 > * known-headers.cc (get_stdlib_header_for_name): Add various names > from <assert.h>, <string.h>, and <memory.h>; add more names from > <stdio.h>. > > gcc/cp/ChangeLog: > PR c++/84269 > * name-lookup.c (get_std_name_hint): Add names from <memory>, > <tuple>, and <utility>. > > gcc/testsuite/ChangeLog: > PR c++/84269 > * g++.dg/lookup/missing-std-include-6.C: New test. > * g++.dg/lookup/missing-std-include.C: Add std::pair and > std::tuple tests. > * g++.dg/spellcheck-reswords.C: Expect a hint about <cstring>. > * g++.dg/spellcheck-stdlib.C: Add tests for names in <cstdio>, > <cstring>, <cassert>, and <cstdlib>. > --- > gcc/c-family/known-headers.cc | 33 +++++++++- > gcc/cp/name-lookup.c | 14 +++++ > .../g++.dg/lookup/missing-std-include-6.C | 62 ++++++++++++++++++ > gcc/testsuite/g++.dg/lookup/missing-std-include.C | 8 +++ > gcc/testsuite/g++.dg/spellcheck-reswords.C | 1 + > gcc/testsuite/g++.dg/spellcheck-stdlib.C | 73 > ++++++++++++++++++++++ > 6 files changed, 190 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/g++.dg/lookup/missing-std-include-6.C > > diff --git a/gcc/c-family/known-headers.cc b/gcc/c-family/known-headers.cc > index ef23cbe..5524d21 100644 > --- a/gcc/c-family/known-headers.cc > +++ b/gcc/c-family/known-headers.cc > @@ -57,6 +57,9 @@ get_stdlib_header_for_name (const char *name, enum stdlib > lib) > gcc_assert (lib < NUM_STDLIBS); > > static const stdlib_hint hints[] = { > + /* <assert.h> and <cassert>. */ > + {"assert", {"<assert.h>", "<cassert>"} }, > + > /* <errno.h> and <cerrno>. */ > {"errno", {"<errno.h>", "<cerrno>"} }, > > @@ -92,16 +95,44 @@ get_stdlib_header_for_name (const char *name, enum stdlib > lib) > {"size_t", {"<stddef.h>", "<cstddef>"} }, > {"wchar_t", {"<stddef.h>", NULL /* a keyword in C++ */} }, > > - /* <stdio.h>. */ > + /* <stdio.h> and <cstdio>. */ > {"BUFSIZ", {"<stdio.h>", "<cstdio>"} }, > {"EOF", {"<stdio.h>", "<cstdio>"} }, > {"FILE", {"<stdio.h>", "<cstdio>"} }, > {"FILENAME_MAX", {"<stdio.h>", "<cstdio>"} }, > + {"fopen", {"<stdio.h>", "<cstdio>"} }, > {"fpos_t", {"<stdio.h>", "<cstdio>"} }, > + {"getchar", {"<stdio.h>", "<cstdio>"} }, > + {"printf", {"<stdio.h>", "<cstdio>"} }, > + {"snprintf", {"<stdio.h>", "<cstdio>"} }, > + {"sprintf", {"<stdio.h>", "<cstdio>"} }, > {"stderr", {"<stdio.h>", "<cstdio>"} }, > {"stdin", {"<stdio.h>", "<cstdio>"} }, > {"stdout", {"<stdio.h>", "<cstdio>"} }, > > + /* <stdlib.h> and <cstdlib>. */ > + {"free", {"<stdlib.h>", "<cstdlib>"} }, > + {"malloc", {"<stdlib.h>", "<cstdlib>"} }, > + {"realloc", {"<stdlib.h>", "<cstdlib>"} }, > + > + /* <string.h> and <cstring>. */ > + {"memchr", {"<string.h>", "<cstring>"} }, > + {"memcmp", {"<string.h>", "<cstring>"} }, > + {"memcpy", {"<string.h>", "<cstring>"} }, > + {"memmove", {"<string.h>", "<cstring>"} }, > + {"memset", {"<string.h>", "<cstring>"} }, > + {"strcat", {"<string.h>", "<cstring>"} }, > + {"strchr", {"<string.h>", "<cstring>"} }, > + {"strcmp", {"<string.h>", "<cstring>"} }, > + {"strcpy", {"<string.h>", "<cstring>"} }, > + {"strlen", {"<string.h>", "<cstring>"} }, > + {"strncat", {"<string.h>", "<cstring>"} }, > + {"strncmp", {"<string.h>", "<cstring>"} }, > + {"strncpy", {"<string.h>", "<cstring>"} }, > + {"strrchr", {"<string.h>", "<cstring>"} }, > + {"strspn", {"<string.h>", "<cstring>"} }, > + {"strstr", {"<string.h>", "<cstring>"} }, > + > /* <stdint.h>. */ > {"PTRDIFF_MAX", {"<stdint.h>", "<cstdint>"} }, > {"PTRDIFF_MIN", {"<stdint.h>", "<cstdint>"} }, > diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c > index e193b3b..061729a 100644 > --- a/gcc/cp/name-lookup.c > +++ b/gcc/cp/name-lookup.c > @@ -5453,6 +5453,12 @@ get_std_name_hint (const char *name) > /* <map>. */ > {"map", "<map>"}, > {"multimap", "<map>"}, > + /* <memory>. */ > + {"make_shared", "<memory>"}, > + {"make_unique", "<memory>"}, > + {"shared_ptr", "<memory>"}, > + {"unique_ptr", "<memory>"}, > + {"weak_ptr", "<memory>"}, > /* <queue>. */ > {"queue", "<queue>"}, > {"priority_queue", "<queue>"}, > @@ -5472,6 +5478,9 @@ get_std_name_hint (const char *name) > {"basic_stringstream", "<sstream>"}, > /* <stack>. */ > {"stack", "<stack>"}, > + /* <tuple>. */ > + {"make_tuple", "<tuple>"}, > + {"tuple", "<tuple>"}, > /* <string>. */ > {"string", "<string>"}, > {"wstring", "<string>"}, > @@ -5483,6 +5492,11 @@ get_std_name_hint (const char *name) > /* <unordered_set>. */ > {"unordered_set", "<unordered_set>"}, // C++11 > {"unordered_multiset", "<unordered_set>"}, // C++11 > + /* <utility>. */ > + {"forward", "<utility>"}, > + {"make_pair", "<utility>"}, > + {"move", "<utility>"}, > + {"pair", "<utility>"}, > /* <vector>. */ > {"vector", "<vector>"}, > }; > diff --git a/gcc/testsuite/g++.dg/lookup/missing-std-include-6.C > b/gcc/testsuite/g++.dg/lookup/missing-std-include-6.C > new file mode 100644 > index 0000000..100bcc0 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/lookup/missing-std-include-6.C > @@ -0,0 +1,62 @@ > +// { dg-do compile { target c++11 } } > + > +/* <memory>. */ > + > +template<class T> > +void test_make_shared () > +{ > + auto p = std::make_shared<T>(); // { dg-error "'make_shared' is not a > member of 'std'" } > + // { dg-message "'#include <memory>'" "" { target *-*-* } .-1 } > + // { dg-error "expected primary-expression before '>' token" "" { target > *-*-* } .-2 } > + // { dg-error "expected primary-expression before '\\)' token" "" { target > *-*-* } .-3 } > +} > + > +template<class T> > +void test_make_unique () > +{ > + auto p = std::make_unique<T>(); // { dg-error "'make_unique' is not a > member of 'std'" } > + // { dg-message "'#include <memory>'" "" { target *-*-* } .-1 } > + // { dg-error "expected primary-expression before '>' token" "" { target > *-*-* } .-2 } > + // { dg-error "expected primary-expression before '\\)' token" "" { target > *-*-* } .-3 } > +} > + > +std::shared_ptr<int> test_shared_ptr; // { dg-error "'shared_ptr' in > namespace 'std' does not name a template type" } > +// { dg-message "'#include <memory>'" "" { target *-*-* } .-1 } > + > +std::unique_ptr<int> test_unique_ptr; // { dg-error "'unique_ptr' in > namespace 'std' does not name a template type" } > +// { dg-message "'#include <memory>'" "" { target *-*-* } .-1 } > + > +std::weak_ptr<int> test_weak_ptr; // { dg-error "'weak_ptr' in namespace > 'std' does not name a template type" } > +// { dg-message "'#include <memory>'" "" { target *-*-* } .-1 } > + > +/* <tuple>. */ > + > +void test_make_tuple (int i, int j, int k) > +{ > + auto t = std::make_tuple (i, j, k); // { dg-error "'make_tuple' is not a > member of 'std'" } > + // { dg-message "'#include <tuple>'" "" { target *-*-* } .-1 } > +} > + > +/* <utility>. */ > + > +template<class T> > +void test_forward(T&& arg) > +{ > + std::forward<T>(arg); // { dg-error "'forward' is not a member of 'std'" } > + // { dg-message "'#include <utility>'" "" { target *-*-* } .-1 } > + // { dg-error "expected primary-expression before '>' token" "" { target > *-*-* } .-2 } > +} > + > +void test_make_pair (int i, int j) > +{ > + auto p = std::make_pair (i, j); // { dg-error "'make_pair' is not a member > of 'std'" } > + // { dg-message "'#include <utility>'" "" { target *-*-* } .-1 } > +} > + > +template<class T> > +void test_move(T&& arg) > +{ > + std::move<T>(arg); // { dg-error "'move' is not a member of 'std'" } > + // { dg-message "'#include <utility>'" "" { target *-*-* } .-1 } > + // { dg-error "expected primary-expression before '>' token" "" { target > *-*-* } .-2 } > +} > diff --git a/gcc/testsuite/g++.dg/lookup/missing-std-include.C > b/gcc/testsuite/g++.dg/lookup/missing-std-include.C > index 82f994f..5452760 100644 > --- a/gcc/testsuite/g++.dg/lookup/missing-std-include.C > +++ b/gcc/testsuite/g++.dg/lookup/missing-std-include.C > @@ -26,4 +26,12 @@ void test (void) > std::list<int> lst; // { dg-error ".list. is not a member of .std." } > // { dg-message ".std::list. is defined in header .<list>.; did you forget > to .#include <list>.?" "" { target *-*-* } .-1 } > // { dg-error "expected primary-expression before .int." "" { target *-*-* > } .-2 } > + > + std::pair<int,float> p; // { dg-error ".pair. is not a member of .std." } > + // { dg-message ".std::pair. is defined in header .<utility>.; did you > forget to .#include <utility>.?" "" { target *-*-* } .-1 } > + // { dg-error "expected primary-expression before .int." "" { target *-*-* > } .-2 } > + > + std::tuple<int,float> p; // { dg-error ".tuple. is not a member of .std." } > + // { dg-message ".std::tuple. is defined in header .<tuple>.; did you > forget to .#include <tuple>.?" "" { target *-*-* } .-1 } > + // { dg-error "expected primary-expression before .int." "" { target *-*-* > } .-2 } > } > diff --git a/gcc/testsuite/g++.dg/spellcheck-reswords.C > b/gcc/testsuite/g++.dg/spellcheck-reswords.C > index db6104b..0687666 100644 > --- a/gcc/testsuite/g++.dg/spellcheck-reswords.C > +++ b/gcc/testsuite/g++.dg/spellcheck-reswords.C > @@ -8,4 +8,5 @@ void pr80567 (void *p) > { > memset (p, 0, 4); // { dg-error "not declared" } > // { dg-bogus "'else'" "" { target *-*-*} .-1 } > + // { dg-message "'#include <cstring>'" "" { target *-*-*} .-2 } > } > diff --git a/gcc/testsuite/g++.dg/spellcheck-stdlib.C > b/gcc/testsuite/g++.dg/spellcheck-stdlib.C > index c7a6626..11a4e3e 100644 > --- a/gcc/testsuite/g++.dg/spellcheck-stdlib.C > +++ b/gcc/testsuite/g++.dg/spellcheck-stdlib.C > @@ -35,6 +35,21 @@ void test_cstdio (void) > > EOF; // { dg-error "'EOF' was not declared" } > // { dg-message "'EOF' is defined in header '<cstdio>'; did you forget to > '#include <cstdio>'?" "" { target *-*-* } .-1 } > + > + fopen ("test.txt"); // { dg-error "'fopen' was not declared" } > + // { dg-message "'#include <cstdio>'" "" { target *-*-* } .-1 } > + > + printf ("test\n"); // { dg-error "'printf' was not declared" } > + // { dg-message "'#include <cstdio>'" "" { target *-*-* } .-1 } > + > + char tmp[16]; > + sprintf (tmp, "test\n"); // { dg-error "'sprintf' was not declared" } > + // { dg-message "'#include <cstdio>'" "" { target *-*-* } .-1 } > + snprintf (tmp, 16, "test\n"); // { dg-error "'snprintf' was not declared" > } > + // { dg-message "'#include <cstdio>'" "" { target *-*-* } .-1 } > + > + getchar (); // { dg-error "'getchar' was not declared" } > + // { dg-message "'#include <cstdio>'" "" { target *-*-* } .-1 } > } > > /* Missing <cerrno>. */ > @@ -62,6 +77,64 @@ int test_INT_MAX (void) > // { dg-message "'INT_MAX' is defined in header '<climits>'; did you > forget to '#include <climits>'?" "" { target *-*-* } INT_MAX_line } > } > > +/* Missing <cstring>. */ > + > +void test_cstring (char *dest, char *src) > +{ > + memchr(dest, 'a', 4); // { dg-error "was not declared" } > + // { dg-message "'#include <cstring>'" "" { target *-*-* } .-1 } > + memcmp(dest, src, 4); // { dg-error "was not declared" } > + // { dg-message "'#include <cstring>'" "" { target *-*-* } .-1 } > + memcpy(dest, src, 4); // { dg-error "was not declared" } > + // { dg-message "'#include <cstring>'" "" { target *-*-* } .-1 } > + memmove(dest, src, 4); // { dg-error "was not declared" } > + // { dg-message "'#include <cstring>'" "" { target *-*-* } .-1 } > + memset(dest, 'a', 4); // { dg-error "was not declared" } > + // { dg-message "'#include <cstring>'" "" { target *-*-* } .-1 } > + strcat(dest, "test"); // { dg-error "was not declared" } > + // { dg-message "'#include <cstring>'" "" { target *-*-* } .-1 } > + strchr("test", 'e'); // { dg-error "was not declared" } > + // { dg-message "'#include <cstring>'" "" { target *-*-* } .-1 } > + strcmp(dest, "test"); // { dg-error "was not declared" } > + // { dg-message "'#include <cstring>'" "" { target *-*-* } .-1 } > + strcpy(dest, "test"); // { dg-error "was not declared" } > + // { dg-message "'#include <cstring>'" "" { target *-*-* } .-1 } > + strlen("test"); // { dg-error "was not declared" } > + // { dg-message "'#include <cstring>'" "" { target *-*-* } .-1 } > + strncat(dest, "test", 3); // { dg-error "was not declared" } > + // { dg-message "'#include <cstring>'" "" { target *-*-* } .-1 } > + strncmp(dest, "test", 3); // { dg-error "was not declared" } > + // { dg-message "'#include <cstring>'" "" { target *-*-* } .-1 } > + strncpy(dest, "test", 3); // { dg-error "was not declared" } > + // { dg-message "'#include <cstring>'" "" { target *-*-* } .-1 } > + strrchr("test", 'e'); // { dg-error "was not declared" } > + // { dg-message "'#include <cstring>'" "" { target *-*-* } .-1 } > + strspn(dest, "test"); // { dg-error "was not declared" } > + // { dg-message "'#include <cstring>'" "" { target *-*-* } .-1 } > + strstr(dest, "test"); // { dg-error "was not declared" } > + // { dg-message "'#include <cstring>'" "" { target *-*-* } .-1 } > +} > + > +/* Missing <cassert>. */ > + > +void test_cassert (int a, int b) > +{ > + assert (a == b); // { dg-error "was not declared" } > + // { dg-message "'#include <cassert>'" "" { target *-*-* } .-1 } > +} > + > +/* Missing <cstdlib>. */ > + > +void test_cstdlib (void *q) > +{ > + void *ptr = malloc (64); // { dg-error "was not declared" } > + // { dg-message "'#include <cstdlib>'" "" { target *-*-* } .-1 } > + free (ptr); // { dg-error "was not declared" } > + // { dg-message "'#include <cstdlib>'" "" { target *-*-* } .-1 } > + q = realloc (q, 1024); // { dg-error "was not declared" } > + // { dg-message "'#include <cstdlib>'" "" { target *-*-* } .-1 } > +} > + > /* Verify that we don't offer suggestions to stdlib globals names when > there's an explicit namespace. */ > > -- > 1.8.5.3 >