This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix PR13092 (semantic checking of non-dependent SCOPE_REF)
- From: Kriang Lerdsuwanakij <lerdsuwa at users dot sourceforge dot net>
- To: <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 27 Feb 2004 23:41:19 +0700 (ICT)
- Subject: [C++ PATCH] Fix PR13092 (semantic checking of non-dependent SCOPE_REF)
- Reply-to: <lerdsuwa at users dot sourceforge dot net>
Hi
This is the revised version of my earlier patch to fix PR13092.
http://gcc.gnu.org/ml/gcc-patches/2004-01/msg01785.html
The original version dealt with two-phase lookup of SCOPE_REF (reject-legal)
and access checking (accept-illegal) issues but only two-phase problem is
addressed in this patch. Here is the summary of the changes:
- In init.c: This is straightforward, building SCOPE_REF with non-null
TREE_TYPE when the name is non-dependent.
- Diagnostic fix when the operand 1 of SCOPE_REF is not IDENTIFIER_NODE
(such as a FIELD_DECL). Previously the scope is incorrectly displayed twice,
like 'A::A::B' since dump_* first outputs the scope (like 'A') and then
the name. But when the name is a *_DECL node, its context is also outputed
again (producing qualified ID for the name like 'A::B'). The result is
duplicate scope.
- The change to type_dependent_expression_p to take into account SCOPE_REF
may contain BASELINK as operand 1. Its TREE_TYPE is unknown_type_node
for this case.
For access checking problem, this is nasty (as can be seen from the original
patch). We need to resolve name early to perform semantic check while still
preserve the SCOPE_REF until the instantiation time. TYPENAME_TYPE and
UNBOUND_CLASS_TEMPLATE that are non-dependent also have this problem.
This needs some major restructure and I'd rather consider this work for 3.5.
Tested on i686-pc-linux-gnu with no regressions. OK for 3.4 branch and
mainline?
--Kriang
2004-02-27 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/13092
* init.c (build_offset_ref): Build SCOPE_REF with non-null
TREE_TYPE for non-dependent names.
* pt.c (type_dependent_expression_p): Handle SCOPE_REF with
unknown_type_node as its TREE_TYPE.
* cxx-pretty_print.c (pp_cxx_unqualified_id): Handle BASELINK.
* error.c (dump_decl) <SCOPE_REF case>: Use pp_expression.
(dump_expr) <SCOPE_REF case>: Likewise.
2004-02-27 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/13092
* g++.dg/template/non-dependent5.C: New test.
* g++.dg/template/non-dependent6.C: Likewise.
* g++.dg/template/non-dependent7.C: Likewise.
* g++.dg/template/non-dependent8.C: Likewise.
diff -cprN gcc-34-save/gcc/cp/cxx-pretty-print.c gcc-34-new/gcc/cp/cxx-pretty-print.c
*** gcc-34-save/gcc/cp/cxx-pretty-print.c Tue Dec 23 22:15:38 2003
--- gcc-34-new/gcc/cp/cxx-pretty-print.c Tue Feb 24 21:21:56 2004
*************** pp_cxx_unqualified_id (cxx_pretty_printe
*** 177,182 ****
--- 177,186 ----
pp_cxx_template_id (pp, t);
break;
+ case BASELINK:
+ pp_cxx_unqualified_id (pp, BASELINK_FUNCTIONS (t));
+ break;
+
case RECORD_TYPE:
case UNION_TYPE:
case ENUMERAL_TYPE:
diff -cprN gcc-34-save/gcc/cp/error.c gcc-34-new/gcc/cp/error.c
*** gcc-34-save/gcc/cp/error.c Sat Feb 14 18:46:10 2004
--- gcc-34-new/gcc/cp/error.c Tue Feb 24 21:21:56 2004
*************** dump_decl (tree t, int flags)
*** 814,822 ****
break;
case SCOPE_REF:
! dump_decl (TREE_OPERAND (t, 0), flags & ~TFF_DECL_SPECIFIERS);
! pp_colon_colon (cxx_pp);
! dump_decl (TREE_OPERAND (t, 1), flags);
break;
case ARRAY_REF:
--- 814,820 ----
break;
case SCOPE_REF:
! pp_expression (cxx_pp, t);
break;
case ARRAY_REF:
*************** dump_expr (tree t, int flags)
*** 1723,1731 ****
break;
case SCOPE_REF:
! dump_type (TREE_OPERAND (t, 0), flags);
! pp_colon_colon (cxx_pp);
! dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
break;
case CAST_EXPR:
--- 1721,1727 ----
break;
case SCOPE_REF:
! pp_expression (cxx_pp, t);
break;
case CAST_EXPR:
diff -cprN gcc-34-save/gcc/cp/init.c gcc-34-new/gcc/cp/init.c
*** gcc-34-save/gcc/cp/init.c Thu Feb 5 18:03:57 2004
--- gcc-34-new/gcc/cp/init.c Tue Feb 24 21:21:56 2004
*************** build_offset_ref (tree type, tree name,
*** 1371,1377 ****
if (TREE_CODE (name) == TEMPLATE_DECL)
return name;
! if (processing_template_decl || uses_template_parms (type))
return build_min_nt (SCOPE_REF, type, name);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
--- 1371,1377 ----
if (TREE_CODE (name) == TEMPLATE_DECL)
return name;
! if (dependent_type_p (type) || type_dependent_expression_p (name))
return build_min_nt (SCOPE_REF, type, name);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
*************** build_offset_ref (tree type, tree name,
*** 1453,1458 ****
--- 1453,1466 ----
return error_mark_node;
}
+ if (processing_template_decl)
+ {
+ if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
+ return build_min (SCOPE_REF, TREE_TYPE (member), type, orig_name);
+ else
+ return build_min (SCOPE_REF, TREE_TYPE (member), type, name);
+ }
+
if (TREE_CODE (member) == TYPE_DECL)
{
TREE_USED (member) = 1;
diff -cprN gcc-34-save/gcc/cp/pt.c gcc-34-new/gcc/cp/pt.c
*** gcc-34-save/gcc/cp/pt.c Sat Feb 14 18:49:59 2004
--- gcc-34-new/gcc/cp/pt.c Tue Feb 24 21:21:56 2004
*************** convert_nontype_argument (tree type, tre
*** 3183,3189 ****
--a pointer to member expressed as described in _expr.unary.op_. */
/* An integral constant-expression can include const variables or
! . enumerators. Simplify things by folding them to their values,
unless we're about to bind the declaration to a reference
parameter. */
if (INTEGRAL_TYPE_P (expr_type) && TREE_CODE (type) != REFERENCE_TYPE)
--- 3183,3189 ----
--a pointer to member expressed as described in _expr.unary.op_. */
/* An integral constant-expression can include const variables or
! enumerators. Simplify things by folding them to their values,
unless we're about to bind the declaration to a reference
parameter. */
if (INTEGRAL_TYPE_P (expr_type) && TREE_CODE (type) != REFERENCE_TYPE)
*************** type_dependent_expression_p (tree expres
*** 11849,11858 ****
return dependent_type_p (type);
}
! if (TREE_CODE (expression) == SCOPE_REF
! && dependent_scope_ref_p (expression,
! type_dependent_expression_p))
! return true;
if (TREE_CODE (expression) == FUNCTION_DECL
&& DECL_LANG_SPECIFIC (expression)
--- 11849,11858 ----
return dependent_type_p (type);
}
! if (TREE_CODE (expression) == SCOPE_REF)
! return dependent_scope_ref_p (expression,
! type_dependent_expression_p)
! || dependent_type_p (TREE_TYPE (expression));
if (TREE_CODE (expression) == FUNCTION_DECL
&& DECL_LANG_SPECIFIC (expression)
diff -cprN gcc-34-save/gcc/testsuite/g++.dg/template/non-dependent5.C gcc-34-new/gcc/testsuite/g++.dg/template/non-dependent5.C
*** gcc-34-save/gcc/testsuite/g++.dg/template/non-dependent5.C Thu Jan 1 07:00:00 1970
--- gcc-34-new/gcc/testsuite/g++.dg/template/non-dependent5.C Tue Feb 24 21:21:56 2004
***************
*** 0 ****
--- 1,22 ----
+ // { dg-do compile }
+
+ // Origin: Giovanni Bajo <giovannibajo@libero.it>
+
+ // PR c++/13092: ICE taking address of member which is non-dependent
+
+ struct S
+ {
+ int i;
+ };
+
+ template<int S::*p>
+ struct X
+ {};
+
+ template <class T>
+ struct Foo
+ {
+ X<&S::i> x;
+ };
+
+ template struct Foo<void>;
diff -cprN gcc-34-save/gcc/testsuite/g++.dg/template/non-dependent6.C gcc-34-new/gcc/testsuite/g++.dg/template/non-dependent6.C
*** gcc-34-save/gcc/testsuite/g++.dg/template/non-dependent6.C Thu Jan 1 07:00:00 1970
--- gcc-34-new/gcc/testsuite/g++.dg/template/non-dependent6.C Tue Feb 24 21:21:56 2004
***************
*** 0 ****
--- 1,21 ----
+ // { dg-do compile }
+
+ // Origin: Giovanni Bajo <giovannibajo@libero.it>
+
+ // Two-phase name lookup for address of member:
+ // Detecting error during parsing
+
+ struct S
+ {
+ char i;
+ };
+
+ template<int S::*p>
+ struct X
+ {};
+
+ template <class T>
+ struct Foo
+ {
+ X<&S::i> x; // { dg-error "convert|no type" }
+ };
diff -cprN gcc-34-save/gcc/testsuite/g++.dg/template/non-dependent7.C gcc-34-new/gcc/testsuite/g++.dg/template/non-dependent7.C
*** gcc-34-save/gcc/testsuite/g++.dg/template/non-dependent7.C Thu Jan 1 07:00:00 1970
--- gcc-34-new/gcc/testsuite/g++.dg/template/non-dependent7.C Tue Feb 24 21:21:56 2004
***************
*** 0 ****
--- 1,22 ----
+ // { dg-do compile }
+
+ // Origin: Giovanni Bajo <giovannibajo@libero.it>
+
+ // Two-phase name lookup for address of member:
+ // Overloading function
+
+ struct S
+ {
+ int f();
+ int f(int);
+ };
+
+ template<int (S::*p)()>
+ struct X
+ {};
+
+ template <class T>
+ struct Foo
+ {
+ X<&S::f> x;
+ };
diff -cprN gcc-34-save/gcc/testsuite/g++.dg/template/non-dependent8.C gcc-34-new/gcc/testsuite/g++.dg/template/non-dependent8.C
*** gcc-34-save/gcc/testsuite/g++.dg/template/non-dependent8.C Thu Jan 1 07:00:00 1970
--- gcc-34-new/gcc/testsuite/g++.dg/template/non-dependent8.C Tue Feb 24 21:21:56 2004
***************
*** 0 ****
--- 1,22 ----
+ // { dg-do compile }
+
+ // Origin: Giovanni Bajo <giovannibajo@libero.it>
+
+ // Two-phase name lookup for address of member:
+ // Detecting overloading function error during parsing
+
+ struct S
+ {
+ int f(char);
+ int f(int);
+ };
+
+ template<int (S::*p)()>
+ struct X
+ {};
+
+ template <class T>
+ struct Foo
+ {
+ X<&S::f> x; // { dg-error "convert|no type" }
+ };