mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-04 11:11:09 +08:00
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
This commit is contained in:
parent
152315665e
commit
56d0c6e3f5
@ -1,3 +1,16 @@
|
||||
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>
|
||||
|
||||
PR c++/33459
|
||||
|
@ -5645,21 +5645,13 @@ currently_open_derived_class (tree t)
|
||||
void
|
||||
push_nested_class (tree type)
|
||||
{
|
||||
tree context;
|
||||
|
||||
/* A namespace might be passed in error cases, like A::B:C. */
|
||||
if (type == NULL_TREE
|
||||
|| type == error_mark_node
|
||||
|| TREE_CODE (type) == NAMESPACE_DECL
|
||||
|| ! IS_AGGR_TYPE (type)
|
||||
|| TREE_CODE (type) == TEMPLATE_TYPE_PARM
|
||||
|| TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
|
||||
|| !CLASS_TYPE_P (type))
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -988,6 +988,10 @@ enum languages { lang_c, lang_cplusplus, lang_java };
|
||||
((T) == RECORD_TYPE || (T) == UNION_TYPE)
|
||||
#define TAGGED_TYPE_P(T) \
|
||||
(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)
|
||||
|
||||
/* True if this a "Java" type, defined in 'extern "Java"'. */
|
||||
|
@ -1281,9 +1281,7 @@ is_aggr_type (tree type, int or_else)
|
||||
if (type == error_mark_node)
|
||||
return 0;
|
||||
|
||||
if (! IS_AGGR_TYPE (type)
|
||||
&& TREE_CODE (type) != TEMPLATE_TYPE_PARM
|
||||
&& TREE_CODE (type) != BOUND_TEMPLATE_TEMPLATE_PARM)
|
||||
if (! IS_AGGR_TYPE (type))
|
||||
{
|
||||
if (or_else)
|
||||
error ("%qT is not an aggregate type", type);
|
||||
|
72
gcc/cp/pt.c
72
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
|
||||
|
@ -14,8 +14,29 @@ struct Y {
|
||||
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<> struct StaticAssert<true> {};
|
||||
|
||||
StaticAssert<__alignof(X<double>) == __alignof(double)> d1;
|
||||
StaticAssert<__alignof(Y<double>) == __alignof(double)> d2;
|
||||
StaticAssert<__alignof(Z<double>) == __alignof(double)> d3;
|
||||
StaticAssert<__alignof(A<double*>) == __alignof(double)> d4;
|
||||
|
19
gcc/testsuite/g++.dg/ext/tmplattr4.C
Normal file
19
gcc/testsuite/g++.dg/ext/tmplattr4.C
Normal file
@ -0,0 +1,19 @@
|
||||
// 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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user