aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2018-03-23 01:19:14 +0000
committerAlexandre Oliva <aoliva@gcc.gnu.org>2018-03-23 01:19:14 +0000
commit5904d9d923bd86849209e55550b7876e513f4896 (patch)
treea8f986c5da0ff2a8e3e7afaf7e13d4dadd64afdc /gcc
parent3ec16e36107214035fe9d1177e0acc6ebe037112 (diff)
downloadgcc-5904d9d923bd86849209e55550b7876e513f4896.zip
gcc-5904d9d923bd86849209e55550b7876e513f4896.tar.gz
gcc-5904d9d923bd86849209e55550b7876e513f4896.tar.bz2
[PR c++/84789] do not fail to resolve typename into template-independent
Although resolve_typename_type always takes a template-dependent type-id, and it usually resolves it to another template-dependent type-id, it is not correct to require the latter: in declarators, template-dependent scopes may turn out to name template-independent types, as in the pr84789-2.C and pr84789-3.C testcases. The ill-formed testcase pr84789.C trips the same too-strict assert, and also gets fixed by removing the assertion on the simplified scope. However, whereas when the dependent type cannot be resolved, we get an error that suggests 'typename' is missing: pr84789.C:12:3: error: need ‘typename’ before ‘typename B<T>::A::I::I’ because ‘typename B<T>::A::I’ is a dependent scope B<T>::A::I::I i; ^~~~ when it can, we got errors that did not point at that possibility, which may be confusing: pr84789.C:9:15: error: ‘A::I’ {aka ‘int’} is not a class type B<T>::A::I::I i; // { dg-error "typename" } ^ pr84789.C:9:15: error: ‘I’ in ‘A::I’ {aka ‘int’} does not name a type Changing the parser diagnostic code that reports an invalid type name so that it does not attempt to reparse the name as a declarator gets us the superior diagnostic of a missing 'typename' keyword. for gcc/cp/ChangeLog PR c++/84789 * pt.c (resolve_typename_type): Drop assert that stopped simplification to template-independent types. Add assert to verify the initial scope is template dependent. * parser.c (cp_parser_parse_and_diagnose_invalid_type_name): Reparse the id expression as a type-name, not a declarator. for gcc/testsuite/ChangeLog PR c++/84789 * g++.dg/template/pr84789.C: New. * g++.dg/template/pr84789-2.C: New. * g++.dg/template/pr84789-3.C: New. * g++.dg/parse/dtor11.C: Accept alternate error message. From-SVN: r258792
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/parser.c2
-rw-r--r--gcc/cp/pt.c5
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/parse/dtor11.C2
-rw-r--r--gcc/testsuite/g++.dg/template/pr84789-2.C26
-rw-r--r--gcc/testsuite/g++.dg/template/pr84789-3.C31
-rw-r--r--gcc/testsuite/g++.dg/template/pr84789.C13
8 files changed, 88 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 33add69..08ecf21 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,12 @@
2018-03-22 Alexandre Oliva <aoliva@redhat.com>
+ PR c++/84789
+ * pt.c (resolve_typename_type): Drop assert that stopped
+ simplification to template-independent types. Add assert to
+ verify the initial scope is template dependent.
+ * parser.c (cp_parser_parse_and_diagnose_invalid_type_name):
+ Reparse the id expression as a type-name, not a declarator.
+
PR c++/84729
* init.c (build_vec_init): Error at parenthesized array init.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 3461929..fd81702 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -3455,7 +3455,7 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
/*template_p=*/NULL,
- /*declarator_p=*/true,
+ /*declarator_p=*/false,
/*optional_p=*/false);
/* If the next token is a (, this is a function with no explicit return
type, i.e. constructor, destructor or conversion op. */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index d7c0c7b..5293c2b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -25249,6 +25249,9 @@ resolve_typename_type (tree type, bool only_current_p)
gcc_assert (TREE_CODE (type) == TYPENAME_TYPE);
scope = TYPE_CONTEXT (type);
+ /* We shouldn't have built a TYPENAME_TYPE with a non-dependent scope. */
+ gcc_checking_assert (uses_template_parms (scope));
+
/* Usually the non-qualified identifier of a TYPENAME_TYPE is
TYPE_IDENTIFIER (type). But when 'type' is a typedef variant of
a TYPENAME_TYPE node, then TYPE_NAME (type) is set to the TYPE_DECL representing
@@ -25285,8 +25288,6 @@ resolve_typename_type (tree type, bool only_current_p)
/* scope is either the template itself or a compatible instantiation
like X<T>, so look up the name in the original template. */
scope = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope);
- /* We shouldn't have built a TYPENAME_TYPE with a non-dependent scope. */
- gcc_checking_assert (uses_template_parms (scope));
/* If scope has no fields, it can't be a current instantiation. Check this
before currently_open_class to avoid infinite recursion (71515). */
if (!TYPE_FIELDS (scope))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 07951d9..4875ce4 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,11 @@
2018-03-22 Alexandre Oliva <aoliva@redhat.com>
+ PR c++/84789
+ * g++.dg/template/pr84789.C: New.
+ * g++.dg/template/pr84789-2.C: New.
+ * g++.dg/template/pr84789-3.C: New.
+ * g++.dg/parse/dtor11.C: Accept alternate error message.
+
PR c++/84729
* g++.dg/pr84729.C: New.
* g++.old-deja/g++.ext/arrnew2.C: Require error.
diff --git a/gcc/testsuite/g++.dg/parse/dtor11.C b/gcc/testsuite/g++.dg/parse/dtor11.C
index 63ffb60..83fd934 100644
--- a/gcc/testsuite/g++.dg/parse/dtor11.C
+++ b/gcc/testsuite/g++.dg/parse/dtor11.C
@@ -8,5 +8,5 @@ struct A
struct B
{
- A::~B B(); // { dg-error "as member of" }
+ A::~B B(); // { dg-error "as member of|as a type" }
};
diff --git a/gcc/testsuite/g++.dg/template/pr84789-2.C b/gcc/testsuite/g++.dg/template/pr84789-2.C
new file mode 100644
index 0000000..0b42148
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr84789-2.C
@@ -0,0 +1,26 @@
+// { dg-do compile }
+
+struct K {
+ struct L {
+ static double j;
+ };
+};
+
+template <typename T>
+struct M {
+ struct N {
+ static int i;
+ };
+};
+
+template <typename T>
+struct O {
+ typedef M<T> P;
+ typedef K Q;
+};
+
+template <typename T>
+int O<T>::P::N::i = 42; // This is obfuscated, but apparently ok.
+
+template <typename T>
+double O<T>::Q::L::j = 42.0; // { dg-error "non-template" }
diff --git a/gcc/testsuite/g++.dg/template/pr84789-3.C b/gcc/testsuite/g++.dg/template/pr84789-3.C
new file mode 100644
index 0000000..bc38c15
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr84789-3.C
@@ -0,0 +1,31 @@
+// { dg-do compile }
+
+struct A
+{
+ static int i;
+};
+struct B
+{
+ typedef ::A A;
+};
+int B::A::i = 0;
+
+struct K
+{
+ struct L
+ {
+ template <typename T>
+ static void f(T);
+ };
+};
+
+template <typename T>
+struct O
+{
+ typedef K Q;
+};
+
+template <typename T>
+void O<T>::Q::L::f(T)
+{
+}
diff --git a/gcc/testsuite/g++.dg/template/pr84789.C b/gcc/testsuite/g++.dg/template/pr84789.C
new file mode 100644
index 0000000..bc1567f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr84789.C
@@ -0,0 +1,13 @@
+// { dg-do compile }
+
+struct A
+{
+ typedef int I;
+};
+
+template<typename> struct B : A {};
+
+template<typename T> struct C : B<T>
+{
+ B<T>::A::I::I i; // { dg-error "typename" }
+};