aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2017-04-25 13:54:35 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2017-04-25 13:54:35 +0000
commit5ca28c1d5f5f8c435d534ed6142e8215b0babb65 (patch)
tree4af24850da8afcbe9bf1a162913989aa86eeac0b /gcc
parent2ec07fa616d283c60844031818c239f1714d31c9 (diff)
downloadgcc-5ca28c1d5f5f8c435d534ed6142e8215b0babb65.zip
gcc-5ca28c1d5f5f8c435d534ed6142e8215b0babb65.tar.gz
gcc-5ca28c1d5f5f8c435d534ed6142e8215b0babb65.tar.bz2
C++: hints for missing std:: headers
gcc/cp/ChangeLog: * name-lookup.c (get_std_name_hint): New function. (maybe_suggest_missing_header): New function. (suggest_alternative_in_explicit_scope): Call maybe_suggest_missing_header. gcc/testsuite/ChangeLog: * g++.dg/lookup/missing-std-include.C: New test file. From-SVN: r247240
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/name-lookup.c109
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/lookup/missing-std-include.C29
4 files changed, 149 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b04894d..ff80b33 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,12 @@
2017-04-25 David Malcolm <dmalcolm@redhat.com>
+ * name-lookup.c (get_std_name_hint): New function.
+ (maybe_suggest_missing_header): New function.
+ (suggest_alternative_in_explicit_scope): Call
+ maybe_suggest_missing_header.
+
+2017-04-25 David Malcolm <dmalcolm@redhat.com>
+
PR c++/80177
* name-lookup.c (suggest_alternative_in_explicit_scope): Convert
candidate type of bm from tree to const char *.
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index eda6db2..0c5df93 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -4537,6 +4537,113 @@ suggest_alternatives_for (location_t location, tree name,
candidates.release ();
}
+/* Subroutine of maybe_suggest_missing_header for handling unrecognized names
+ for some of the most common names within "std::".
+ Given non-NULL NAME, a name for lookup within "std::", return the header
+ name defining it within the C++ Standard Library (without '<' and '>'),
+ or NULL. */
+
+static const char *
+get_std_name_hint (const char *name)
+{
+ struct std_name_hint
+ {
+ const char *name;
+ const char *header;
+ };
+ static const std_name_hint hints[] = {
+ /* <array>. */
+ {"array", "array"}, // C++11
+ /* <deque>. */
+ {"deque", "deque"},
+ /* <forward_list>. */
+ {"forward_list", "forward_list"}, // C++11
+ /* <fstream>. */
+ {"basic_filebuf", "fstream"},
+ {"basic_ifstream", "fstream"},
+ {"basic_ofstream", "fstream"},
+ {"basic_fstream", "fstream"},
+ /* <iostream>. */
+ {"cin", "iostream"},
+ {"cout", "iostream"},
+ {"cerr", "iostream"},
+ {"clog", "iostream"},
+ {"wcin", "iostream"},
+ {"wcout", "iostream"},
+ {"wclog", "iostream"},
+ /* <list>. */
+ {"list", "list"},
+ /* <map>. */
+ {"map", "map"},
+ {"multimap", "map"},
+ /* <queue>. */
+ {"queue", "queue"},
+ {"priority_queue", "queue"},
+ /* <ostream>. */
+ {"ostream", "ostream"},
+ {"wostream", "ostream"},
+ {"ends", "ostream"},
+ {"flush", "ostream"},
+ {"endl", "ostream"},
+ /* <set>. */
+ {"set", "set"},
+ {"multiset", "set"},
+ /* <sstream>. */
+ {"basic_stringbuf", "sstream"},
+ {"basic_istringstream", "sstream"},
+ {"basic_ostringstream", "sstream"},
+ {"basic_stringstream", "sstream"},
+ /* <stack>. */
+ {"stack", "stack"},
+ /* <string>. */
+ {"string", "string"},
+ {"wstring", "string"},
+ {"u16string", "string"},
+ {"u32string", "string"},
+ /* <unordered_map>. */
+ {"unordered_map", "unordered_map"}, // C++11
+ {"unordered_multimap", "unordered_map"}, // C++11
+ /* <unordered_set>. */
+ {"unordered_set", "unordered_set"}, // C++11
+ {"unordered_multiset", "unordered_set"}, // C++11
+ /* <vector>. */
+ {"vector", "vector"},
+ };
+ 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;
+}
+
+/* Subroutine of suggest_alternative_in_explicit_scope, for use when we have no
+ suggestions to offer.
+ If SCOPE is the "std" namespace, then suggest pertinent header
+ files for NAME. */
+
+static void
+maybe_suggest_missing_header (location_t location, tree name, tree scope)
+{
+ if (scope == NULL_TREE)
+ return;
+ if (TREE_CODE (scope) != NAMESPACE_DECL)
+ return;
+ /* We only offer suggestions for the "std" namespace. */
+ if (scope != std_node)
+ return;
+ gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
+
+ const char *name_str = IDENTIFIER_POINTER (name);
+ const char *header_hint = get_std_name_hint (name_str);
+ if (header_hint)
+ inform (location,
+ "%<std::%s%> is defined in header %<<%s>%>;"
+ " did you forget to %<#include <%s>%>?",
+ name_str, header_hint, header_hint);
+}
+
/* Look for alternatives for NAME, an IDENTIFIER_NODE for which name
lookup failed within the explicitly provided SCOPE. Suggest the
the best meaningful candidates (if any) as a fix-it hint.
@@ -4564,6 +4671,8 @@ suggest_alternative_in_explicit_scope (location_t location, tree name,
fuzzy_name);
return true;
}
+ else
+ maybe_suggest_missing_header (location, name, scope);
return false;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c60d9a2..a8e24e9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2017-04-25 David Malcolm <dmalcolm@redhat.com>
+
+ * g++.dg/lookup/missing-std-include.C: New test file.
+
2017-04-25 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
Jakub Jelinek <jakub@redhat.com>
diff --git a/gcc/testsuite/g++.dg/lookup/missing-std-include.C b/gcc/testsuite/g++.dg/lookup/missing-std-include.C
new file mode 100644
index 0000000..82f994f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/missing-std-include.C
@@ -0,0 +1,29 @@
+void test (void)
+{
+ std::string s ("hello world"); // { dg-error ".string. is not a member of .std." }
+ // { dg-message ".std::string. is defined in header .<string>.; did you forget to .#include <string>.?" "" { target *-*-* } .-1 }
+
+ std::wstring ws ("hello world"); // { dg-error ".wstring. is not a member of .std." }
+ // { dg-message ".std::wstring. is defined in header .<string>.; did you forget to .#include <string>.?" "" { target *-*-* } .-1 }
+
+ std::cout << 10; // { dg-error ".cout. is not a member of .std." }
+ // { dg-message ".std::cout. is defined in header .<iostream>.; did you forget to .#include <iostream>.?" "" { target *-*-* } .-1 }
+
+ int i;
+ std::cin >> i; // { dg-error ".cin. is not a member of .std." }
+ // { dg-message ".std::cin. is defined in header .<iostream>.; did you forget to .#include <iostream>.?" "" { target *-*-* } .-1 }
+
+ std::array a; // { dg-error ".array. is not a member of .std." }
+ // { dg-message ".std::array. is defined in header .<array>.; did you forget to .#include <array>.?" "" { target *-*-* } .-1 }
+
+ std::deque a; // { dg-error ".deque. is not a member of .std." }
+ // { dg-message ".std::deque. is defined in header .<deque>.; did you forget to .#include <deque>.?" "" { target *-*-* } .-1 }
+
+ std::vector<int> v; // { dg-error ".vector. is not a member of .std." }
+ // { dg-message ".std::vector. is defined in header .<vector>.; did you forget to .#include <vector>.?" "" { target *-*-* } .-1 }
+ // { dg-error "expected primary-expression before .int." "" { target *-*-* } .-2 }
+
+ 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 }
+}