aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog13
-rw-r--r--gcc/cp/class.c12
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/init.c4
-rw-r--r--gcc/cp/pt.c72
-rw-r--r--gcc/testsuite/g++.dg/ext/tmplattr3.C21
-rw-r--r--gcc/testsuite/g++.dg/ext/tmplattr4.C19
7 files changed, 95 insertions, 50 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ebcd865..efad3f3 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 9e0502f..5c3e054 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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);
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 4f1e88c..1ddf884 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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"'. */
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 247879c..c5c17b1 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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);
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
diff --git a/gcc/testsuite/g++.dg/ext/tmplattr3.C b/gcc/testsuite/g++.dg/ext/tmplattr3.C
index 51f5daf..f8d3c16 100644
--- a/gcc/testsuite/g++.dg/ext/tmplattr3.C
+++ b/gcc/testsuite/g++.dg/ext/tmplattr3.C
@@ -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;
diff --git a/gcc/testsuite/g++.dg/ext/tmplattr4.C b/gcc/testsuite/g++.dg/ext/tmplattr4.C
new file mode 100644
index 0000000..3d5c6b7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/tmplattr4.C
@@ -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;
+}