aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/pt.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2007-09-20 10:13:00 -0400
committerJason Merrill <jason@gcc.gnu.org>2007-09-20 10:13:00 -0400
commit56d0c6e3f540686a9d7e240c536b7c2fe361bbe2 (patch)
tree497200eb12dfd940a8293d497ecc5a24595fb6ef /gcc/cp/pt.c
parent152315665ec17e11bad055588958922ae831def8 (diff)
downloadgcc-56d0c6e3f540686a9d7e240c536b7c2fe361bbe2.zip
gcc-56d0c6e3f540686a9d7e240c536b7c2fe361bbe2.tar.gz
gcc-56d0c6e3f540686a9d7e240c536b7c2fe361bbe2.tar.bz2
re PR c++/7586 (Incorrect handling of attributes in template codes)
PR c++/7586 * pt.c (tsubst): Handle typedefs by looking for the specialization. (retrieve_specialization): Only tagged types use DECL_TEMPLATE_INSTANTIATIONS. (instantiate_class_template): Push nested classes too. (tsubst_decl) [TYPE_DECL]: Only check for canonical decl for tagged types. * cp-tree.h (MAYBE_TAGGED_TYPE_P): New macro. * init.c (is_aggr_type): Remove redundant tests. * class.c (push_nested_class): Use CLASS_TYPE_P. From-SVN: r128621
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r--gcc/cp/pt.c72
1 files changed, 35 insertions, 37 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e54bc5f..17acbaf 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -930,7 +930,8 @@ retrieve_specialization (tree tmpl, tree args,
DECL_TEMPLATE_INSTANTIATIONS list; other templates use the
DECL_TEMPLATE_SPECIALIZATIONS list. */
if (!class_specializations_p
- && TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) == TYPE_DECL)
+ && TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) == TYPE_DECL
+ && TAGGED_TYPE_P (TREE_TYPE (tmpl)))
sp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
else
sp = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
@@ -6688,8 +6689,8 @@ instantiate_class_template (tree type)
class, so that name lookups into base classes, etc. will work
correctly. This is precisely analogous to what we do in
begin_class_definition when defining an ordinary non-template
- class. */
- pushclass (type);
+ class, except we also need to push the enclosing classes. */
+ push_nested_class (type);
/* Now members are processed in the order of declaration. */
for (member = CLASSTYPE_DECL_LIST (pattern);
@@ -6986,7 +6987,7 @@ instantiate_class_template (tree type)
&& DECL_TEMPLATE_INFO (t))
tsubst_default_arguments (t);
- popclass ();
+ pop_nested_class ();
pop_from_top_level ();
pop_deferring_access_checks ();
pop_tinst_level ();
@@ -8083,7 +8084,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
tree type = NULL_TREE;
bool local_p;
- if (TREE_CODE (t) == TYPE_DECL)
+ if (TREE_CODE (t) == TYPE_DECL
+ && MAYBE_TAGGED_TYPE_P (TREE_TYPE (t)))
{
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
@@ -8158,6 +8160,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
/* Create a new node for the specialization we need. */
r = copy_decl (t);
+ if (type == NULL_TREE)
+ type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (TREE_CODE (r) == VAR_DECL)
{
/* Even if the original location is out of scope, the
@@ -8165,7 +8169,6 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
DECL_DEAD_FOR_LOCAL (r) = 0;
DECL_INITIALIZED_P (r) = 0;
DECL_TEMPLATE_INSTANTIATED (r) = 0;
- type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node)
return error_mark_node;
if (TREE_CODE (type) == FUNCTION_TYPE)
@@ -8551,41 +8554,36 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
gcc_assert (type != unknown_type_node);
- /* Reuse typedefs. This is a rather complicated way to check whether the
- type is a typedef from the same class template as the current scope,
- but I can't think of a better one.
-
- We need to do this to handle dependent attributes, specifically
- attribute aligned. */
+ /* Reuse typedefs. We need to do this to handle dependent attributes,
+ specifically attribute aligned. */
if (TYPE_P (t)
&& TYPE_NAME (t)
- && !IS_AGGR_TYPE (t)
- && current_class_type
- && CLASSTYPE_TEMPLATE_INFO (current_class_type))
+ && !MAYBE_TAGGED_TYPE_P (t)
+ && TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM
+ && TREE_CODE (t) != UNBOUND_CLASS_TEMPLATE)
{
tree decl = TYPE_NAME (t);
- tree context = DECL_CONTEXT (decl);
- if (context
- && CLASS_TYPE_P (context)
- && CLASSTYPE_TEMPLATE_INFO (context)
- && (CLASSTYPE_TI_TEMPLATE (context)
- == CLASSTYPE_TI_TEMPLATE (current_class_type))
- && (tsubst_aggr_type (context, args, complain, in_decl,
- /*entering_scope=*/0)
- == current_class_type))
- {
- r = lookup_name (DECL_NAME (decl));
- if (r && TREE_CODE (r) == TYPE_DECL
- && DECL_CONTEXT (r) == current_class_type)
- {
- r = TREE_TYPE (r);
- r = cp_build_qualified_type_real
- (r, cp_type_quals (t) | cp_type_quals (r),
- complain | tf_ignore_bad_quals);
- return r;
- /* Else we're instantiating the typedef, so fall through. */
- }
- }
+
+ if (DECL_CLASS_SCOPE_P (decl))
+ {
+ tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
+ tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
+ r = retrieve_specialization (tmpl, gen_args, false);
+ }
+ else if (DECL_FUNCTION_SCOPE_P (decl))
+ r = retrieve_local_specialization (decl);
+ else
+ r = NULL_TREE;
+
+ if (r)
+ {
+ r = TREE_TYPE (r);
+ r = cp_build_qualified_type_real
+ (r, cp_type_quals (t) | cp_type_quals (r),
+ complain | tf_ignore_bad_quals);
+ return r;
+ }
+ /* Else we must be instantiating the typedef, so fall through. */
}
if (type