Commit 56d0c6e3 by Jason Merrill Committed by Jason Merrill

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
parent 15231566
2007-09-19 Jason Merrill <jason@redhat.com>
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.
2007-09-20 Paolo Carlini <pcarlini@suse.de> 2007-09-20 Paolo Carlini <pcarlini@suse.de>
PR c++/33459 PR c++/33459
......
...@@ -5645,21 +5645,13 @@ currently_open_derived_class (tree t) ...@@ -5645,21 +5645,13 @@ currently_open_derived_class (tree t)
void void
push_nested_class (tree type) push_nested_class (tree type)
{ {
tree context;
/* A namespace might be passed in error cases, like A::B:C. */ /* A namespace might be passed in error cases, like A::B:C. */
if (type == NULL_TREE if (type == NULL_TREE
|| type == error_mark_node || !CLASS_TYPE_P (type))
|| TREE_CODE (type) == NAMESPACE_DECL
|| ! IS_AGGR_TYPE (type)
|| TREE_CODE (type) == TEMPLATE_TYPE_PARM
|| TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
return; return;
context = DECL_CONTEXT (TYPE_MAIN_DECL (type)); push_nested_class (DECL_CONTEXT (TYPE_MAIN_DECL (type)));
if (context && CLASS_TYPE_P (context))
push_nested_class (context);
pushclass (type); pushclass (type);
} }
......
...@@ -988,6 +988,10 @@ enum languages { lang_c, lang_cplusplus, lang_java }; ...@@ -988,6 +988,10 @@ enum languages { lang_c, lang_cplusplus, lang_java };
((T) == RECORD_TYPE || (T) == UNION_TYPE) ((T) == RECORD_TYPE || (T) == UNION_TYPE)
#define TAGGED_TYPE_P(T) \ #define TAGGED_TYPE_P(T) \
(CLASS_TYPE_P (T) || TREE_CODE (T) == ENUMERAL_TYPE) (CLASS_TYPE_P (T) || TREE_CODE (T) == ENUMERAL_TYPE)
/* A tagged type or a dependent type that might be a tagged type when
instantiated. Like IS_AGGR_TYPE, but include enums as well. */
#define MAYBE_TAGGED_TYPE_P(T) \
(IS_AGGR_TYPE(T) || TREE_CODE (T) == ENUMERAL_TYPE)
#define IS_OVERLOAD_TYPE(T) TAGGED_TYPE_P (T) #define IS_OVERLOAD_TYPE(T) TAGGED_TYPE_P (T)
/* True if this a "Java" type, defined in 'extern "Java"'. */ /* True if this a "Java" type, defined in 'extern "Java"'. */
......
...@@ -1281,9 +1281,7 @@ is_aggr_type (tree type, int or_else) ...@@ -1281,9 +1281,7 @@ is_aggr_type (tree type, int or_else)
if (type == error_mark_node) if (type == error_mark_node)
return 0; return 0;
if (! IS_AGGR_TYPE (type) if (! IS_AGGR_TYPE (type))
&& TREE_CODE (type) != TEMPLATE_TYPE_PARM
&& TREE_CODE (type) != BOUND_TEMPLATE_TEMPLATE_PARM)
{ {
if (or_else) if (or_else)
error ("%qT is not an aggregate type", type); error ("%qT is not an aggregate type", type);
......
...@@ -930,7 +930,8 @@ retrieve_specialization (tree tmpl, tree args, ...@@ -930,7 +930,8 @@ retrieve_specialization (tree tmpl, tree args,
DECL_TEMPLATE_INSTANTIATIONS list; other templates use the DECL_TEMPLATE_INSTANTIATIONS list; other templates use the
DECL_TEMPLATE_SPECIALIZATIONS list. */ DECL_TEMPLATE_SPECIALIZATIONS list. */
if (!class_specializations_p 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); sp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
else else
sp = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl); sp = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
...@@ -6688,8 +6689,8 @@ instantiate_class_template (tree type) ...@@ -6688,8 +6689,8 @@ instantiate_class_template (tree type)
class, so that name lookups into base classes, etc. will work class, so that name lookups into base classes, etc. will work
correctly. This is precisely analogous to what we do in correctly. This is precisely analogous to what we do in
begin_class_definition when defining an ordinary non-template begin_class_definition when defining an ordinary non-template
class. */ class, except we also need to push the enclosing classes. */
pushclass (type); push_nested_class (type);
/* Now members are processed in the order of declaration. */ /* Now members are processed in the order of declaration. */
for (member = CLASSTYPE_DECL_LIST (pattern); for (member = CLASSTYPE_DECL_LIST (pattern);
...@@ -6986,7 +6987,7 @@ instantiate_class_template (tree type) ...@@ -6986,7 +6987,7 @@ instantiate_class_template (tree type)
&& DECL_TEMPLATE_INFO (t)) && DECL_TEMPLATE_INFO (t))
tsubst_default_arguments (t); tsubst_default_arguments (t);
popclass (); pop_nested_class ();
pop_from_top_level (); pop_from_top_level ();
pop_deferring_access_checks (); pop_deferring_access_checks ();
pop_tinst_level (); pop_tinst_level ();
...@@ -8083,7 +8084,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -8083,7 +8084,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
tree type = NULL_TREE; tree type = NULL_TREE;
bool local_p; 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); type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
...@@ -8158,6 +8160,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -8158,6 +8160,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
/* Create a new node for the specialization we need. */ /* Create a new node for the specialization we need. */
r = copy_decl (t); r = copy_decl (t);
if (type == NULL_TREE)
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (TREE_CODE (r) == VAR_DECL) if (TREE_CODE (r) == VAR_DECL)
{ {
/* Even if the original location is out of scope, the /* Even if the original location is out of scope, the
...@@ -8165,7 +8169,6 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -8165,7 +8169,6 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
DECL_DEAD_FOR_LOCAL (r) = 0; DECL_DEAD_FOR_LOCAL (r) = 0;
DECL_INITIALIZED_P (r) = 0; DECL_INITIALIZED_P (r) = 0;
DECL_TEMPLATE_INSTANTIATED (r) = 0; DECL_TEMPLATE_INSTANTIATED (r) = 0;
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node) if (type == error_mark_node)
return error_mark_node; return error_mark_node;
if (TREE_CODE (type) == FUNCTION_TYPE) if (TREE_CODE (type) == FUNCTION_TYPE)
...@@ -8551,41 +8554,36 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8551,41 +8554,36 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
gcc_assert (type != unknown_type_node); gcc_assert (type != unknown_type_node);
/* Reuse typedefs. This is a rather complicated way to check whether the /* Reuse typedefs. We need to do this to handle dependent attributes,
type is a typedef from the same class template as the current scope, specifically attribute aligned. */
but I can't think of a better one.
We need to do this to handle dependent attributes, specifically
attribute aligned. */
if (TYPE_P (t) if (TYPE_P (t)
&& TYPE_NAME (t) && TYPE_NAME (t)
&& !IS_AGGR_TYPE (t) && !MAYBE_TAGGED_TYPE_P (t)
&& current_class_type && TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM
&& CLASSTYPE_TEMPLATE_INFO (current_class_type)) && TREE_CODE (t) != UNBOUND_CLASS_TEMPLATE)
{ {
tree decl = TYPE_NAME (t); tree decl = TYPE_NAME (t);
tree context = DECL_CONTEXT (decl);
if (context if (DECL_CLASS_SCOPE_P (decl))
&& CLASS_TYPE_P (context) {
&& CLASSTYPE_TEMPLATE_INFO (context) tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
&& (CLASSTYPE_TI_TEMPLATE (context) tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
== CLASSTYPE_TI_TEMPLATE (current_class_type)) r = retrieve_specialization (tmpl, gen_args, false);
&& (tsubst_aggr_type (context, args, complain, in_decl, }
/*entering_scope=*/0) else if (DECL_FUNCTION_SCOPE_P (decl))
== current_class_type)) r = retrieve_local_specialization (decl);
{ else
r = lookup_name (DECL_NAME (decl)); r = NULL_TREE;
if (r && TREE_CODE (r) == TYPE_DECL
&& DECL_CONTEXT (r) == current_class_type) if (r)
{ {
r = TREE_TYPE (r); r = TREE_TYPE (r);
r = cp_build_qualified_type_real r = cp_build_qualified_type_real
(r, cp_type_quals (t) | cp_type_quals (r), (r, cp_type_quals (t) | cp_type_quals (r),
complain | tf_ignore_bad_quals); complain | tf_ignore_bad_quals);
return r; return r;
/* Else we're instantiating the typedef, so fall through. */ }
} /* Else we must be instantiating the typedef, so fall through. */
}
} }
if (type if (type
......
...@@ -14,8 +14,29 @@ struct Y { ...@@ -14,8 +14,29 @@ struct Y {
layout_type data; layout_type data;
}; };
template<typename T>
struct Z {
typedef char layout_type[sizeof(T)]
__attribute ((aligned(__alignof(T))));
struct Z2 {
layout_type data;
} in;
};
template<typename T>
struct A;
template <typename T>
struct A<T*> {
typedef char layout_type[sizeof(T)]
__attribute ((aligned(__alignof(T))));
layout_type data;
};
template<bool> struct StaticAssert; template<bool> struct StaticAssert;
template<> struct StaticAssert<true> {}; template<> struct StaticAssert<true> {};
StaticAssert<__alignof(X<double>) == __alignof(double)> d1; StaticAssert<__alignof(X<double>) == __alignof(double)> d1;
StaticAssert<__alignof(Y<double>) == __alignof(double)> d2; StaticAssert<__alignof(Y<double>) == __alignof(double)> d2;
StaticAssert<__alignof(Z<double>) == __alignof(double)> d3;
StaticAssert<__alignof(A<double*>) == __alignof(double)> d4;
// PR c++/7586
// { dg-do run }
template<typename T>
int f()
{
typedef unsigned char type[sizeof (T)]
__attribute((aligned(__alignof(T))));
return __alignof (type);
}
int main()
{
if (f<int>() == __alignof (int))
return 0;
else
return 1;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment