aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorFabien Chêne <fabien@gcc.gnu.org>2011-12-13 19:46:58 +0100
committerFabien Chêne <fabien@gcc.gnu.org>2011-12-13 19:46:58 +0100
commit0f8fa9b67833f5f15226564b3f6bb782f5493517 (patch)
tree42d417ed9dfb4115cfed8440e8d3927916c549a9 /gcc
parent863ea6cf55e6f8d7469e257d22eb2c69a0cb181c (diff)
downloadgcc-0f8fa9b67833f5f15226564b3f6bb782f5493517.zip
gcc-0f8fa9b67833f5f15226564b3f6bb782f5493517.tar.gz
gcc-0f8fa9b67833f5f15226564b3f6bb782f5493517.tar.bz2
re PR c++/14258 (typename in a using declaration not supported)
gcc/testsuite/ChangeLog 2011-12-11 Fabien Chene <fabien@gcc.gnu.org> PR c++/14258 * g++.dg/template/using16.C: New. * g++.dg/template/using17.C: New. gcc/cp/ChangeLog 2011-12-11 Fabien Chene <fabien@gcc.gnu.org> PR c++/14258 * cp-tree.h (USING_DECL_TYPENAME_P): New macro. * parser.c (cp_parser_nonclass_name): Handle using declarations that refer to a dependent type. (cp_parser_using_declaration): Set USING_DECL_TYPENAME_P to 1 if the using declaration refers to a dependent type. From-SVN: r182292
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/parser.c32
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/template/using16.C42
-rw-r--r--gcc/testsuite/g++.dg/template/using17.C44
6 files changed, 133 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3f04054..3e7abcc 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2011-12-13 Fabien Chêne <fabien@gcc.gnu.org>
+
+ PR c++/14258
+ * cp-tree.h (USING_DECL_TYPENAME_P): New macro.
+ * parser.c (cp_parser_nonclass_name): Handle using declarations
+ that refer to a dependent type.
+ (cp_parser_using_declaration): Set USING_DECL_TYPENAME_P to 1 if
+ the using declaration refers to a dependent type.
+
2011-12-12 Jakub Jelinek <jakub@redhat.com>
PR c++/51496
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f443816..a96adbb 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -130,6 +130,7 @@ c-common.h, not after.
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
DECL_MEMBER_TEMPLATE_P (in TEMPLATE_DECL)
FUNCTION_PARAMETER_PACK_P (in PARM_DECL)
+ USING_DECL_TYPENAME_P (in USING_DECL)
2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL)
3: DECL_IN_AGGR_P.
@@ -2521,6 +2522,9 @@ extern void decl_shadowed_for_var_insert (tree, tree);
/* The decls named by a using decl. */
#define USING_DECL_DECLS(NODE) DECL_INITIAL (USING_DECL_CHECK (NODE))
+/* Non zero if the using decl refers to a dependent type. */
+#define USING_DECL_TYPENAME_P(NODE) DECL_LANG_FLAG_1 (USING_DECL_CHECK (NODE))
+
/* In a VAR_DECL, true if we have a shadowed local variable
in the shadowed var table for this VAR_DECL. */
#define DECL_HAS_SHADOWED_FOR_VAR_P(NODE) \
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 2bd91ec..91280b7 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -13807,9 +13807,26 @@ cp_parser_nonclass_name (cp_parser* parser)
/* Look up the type-name. */
type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location);
- /* If it is a using decl, use its underlying decl. */
- type_decl = strip_using_decl (type_decl);
-
+ if (TREE_CODE (type_decl) == USING_DECL)
+ {
+ if (!DECL_DEPENDENT_P (type_decl))
+ type_decl = strip_using_decl (type_decl);
+ else if (USING_DECL_TYPENAME_P (type_decl))
+ {
+ /* We have found a type introduced by a using
+ declaration at class scope that refers to a dependent
+ type.
+
+ using typename :: [opt] nested-name-specifier unqualified-id ;
+ */
+ type_decl = make_typename_type (TREE_TYPE (type_decl),
+ DECL_NAME (type_decl),
+ typename_type, tf_error);
+ if (type_decl != error_mark_node)
+ type_decl = TYPE_NAME (type_decl);
+ }
+ }
+
if (TREE_CODE (type_decl) != TYPE_DECL
&& (objc_is_id (identifier) || objc_is_class_name (identifier)))
{
@@ -14947,6 +14964,9 @@ cp_parser_using_declaration (cp_parser* parser,
/* Create the USING_DECL. */
decl = do_class_using_decl (parser->scope, identifier);
+ if (typename_p)
+ USING_DECL_TYPENAME_P (decl) = 1;
+
if (check_for_bare_parameter_packs (decl))
return false;
else
@@ -18900,7 +18920,11 @@ cp_parser_member_declaration (cp_parser* parser)
parser->colon_corrects_to_scope_p = false;
if (cp_parser_using_declaration (parser, /*access_declaration=*/true))
- goto out;
+ {
+ warning (OPT_Wdeprecated, "access declarations are deprecated; "
+ "employ using declarations instead");
+ goto out;
+ }
/* Parse the decl-specifier-seq. */
decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e5fa8ba..50595b2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2011-12-11 Fabien Chêne <fabien@gcc.gnu.org>
+
+ PR c++/14258
+ * g++.dg/template/using16.C: New.
+ * g++.dg/template/using17.C: New.
+
2011-12-13 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/51362
diff --git a/gcc/testsuite/g++.dg/template/using16.C b/gcc/testsuite/g++.dg/template/using16.C
new file mode 100644
index 0000000..589f7f1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/using16.C
@@ -0,0 +1,42 @@
+// { dg-do compile }
+
+template <class T>
+struct A
+{
+ typedef T type;
+};
+
+template <class T>
+struct B
+{
+ class type
+ {
+ type(); // { dg-error "private" }
+ };
+};
+
+template <class T>
+struct C : A<T>, B<T>
+{
+ using typename B<T>::type;
+
+ void f()
+ {
+ type j; // { dg-error "context" }
+ }
+};
+
+template class C<int>; // { dg-message "required" }
+
+template <class T>
+struct D
+{
+ typedef T type;
+};
+
+template <class T>
+class E : D<T>
+{
+ using typename D<T>::type; // { dg-message "previous" }
+ using typename D<T>::type; // { dg-error "redeclaration" }
+};
diff --git a/gcc/testsuite/g++.dg/template/using17.C b/gcc/testsuite/g++.dg/template/using17.C
new file mode 100644
index 0000000..1af1dc7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/using17.C
@@ -0,0 +1,44 @@
+// PR c++/14258
+// { dg-do run }
+
+template<typename T>
+struct A
+{
+ typedef T type;
+ typedef A type2;
+};
+
+template<typename T>
+struct B : A<T>
+{
+ using typename A<T>::type;
+ type t;
+
+ using typename A<T>::type2;
+
+ type f()
+ {
+ type i = 1;
+ return i;
+ }
+};
+
+int main()
+{
+ B<int>::type t = 4;
+ if (t != 4)
+ __builtin_abort();
+
+ B<double> b;
+ b.t = 3;
+ if (b.t != 3)
+ __builtin_abort();
+
+ B<long> b2;
+ if (b2.f() != 1)
+ __builtin_abort();
+
+ B<double>::type2::type tt = 12;
+ if (tt != 12)
+ __builtin_abort();
+}