diff mbox

RFC [ABI]: C++ PATCH for c++/44540 - avoid mangling attribute noreturn

Message ID 4C4469AB.4000700@redhat.com
State New
Headers show

Commit Message

Jason Merrill July 19, 2010, 3:05 p.m. UTC
On 07/13/2010 06:37 PM, Jason Merrill wrote:
> On 07/07/2010 11:14 AM, Mark Mitchell wrote:
>> I agree that an orthogonal improvement would be to stop abusing
>> TYPE_CONST and TYPE_VOLATILE for these attributes and record them on
>> TYPE_ATTRIBUTES. But, that would be much bigger than Jason's patch.
>
> I've done a lot of the work toward this, but decided to put it aside
> because it was taking up too much time for a minor internal cleanup.
> Perhaps I'll pick it up again after the August C++ meeting.

Here's the current state, on the off chance that anyone is interested in 
picking it up.

Jason
diff mbox

Patch

commit 4d5074bd48669bf1215e231cd1ae4b39b36009a8
Author: Jason Merrill <jason@redhat.com>
Date:   Wed May 19 16:59:19 2010 -0400

    type_main_variant cleanup

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 64e2e50..cbe9914 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -240,7 +240,7 @@  check_dtor_name (tree basetype, tree name)
 
   if (!name || name == error_mark_node)
     return false;
-  return same_type_p (TYPE_MAIN_VARIANT (basetype), TYPE_MAIN_VARIANT (name));
+  return same_type_ignoring_top_level_qualifiers_p (basetype, name);
 }
 
 /* We want the address of a function or method.  We avoid creating a
@@ -2361,7 +2361,7 @@  add_builtin_candidates (struct z_candidate **candidates, enum tree_code code,
 		  (NULL_TREE, build_reference_type (argtypes[i]), types[i]);
 
 	      types[i] = tree_cons
-		(NULL_TREE, TYPE_MAIN_VARIANT (argtypes[i]), types[i]);
+		(NULL_TREE, cv_unqualified (argtypes[i]), types[i]);
 	    }
 
 	  else if (! convs)
@@ -2382,7 +2382,7 @@  add_builtin_candidates (struct z_candidate **candidates, enum tree_code code,
 	      type = non_reference (type);
 	      if (i != 0 || ! ref1)
 		{
-		  type = TYPE_MAIN_VARIANT (type_decays_to (type));
+		  type = type_decays_to (type);
 		  if (enum_p && TREE_CODE (type) == ENUMERAL_TYPE)
 		    types[i] = tree_cons (NULL_TREE, type, types[i]);
 		  if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
@@ -2401,7 +2401,7 @@  add_builtin_candidates (struct z_candidate **candidates, enum tree_code code,
 	  type = non_reference (argtypes[i]);
 	  if (i != 0 || ! ref1)
 	    {
-	      type = TYPE_MAIN_VARIANT (type_decays_to (type));
+	      type = type_decays_to (type);
 	      if (enum_p && UNSCOPED_ENUM_P (type))
 		types[i] = tree_cons (NULL_TREE, type, types[i]);
 	      if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
@@ -2537,8 +2537,8 @@  add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
   if (DECL_CONSTRUCTOR_P (fn) && nargs == 2)
     {
       tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn);
-      if (arg_types && same_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (arg_types)),
-				    ctype))
+      if (arg_types && (same_type_ignoring_top_level_qualifiers_p
+			(TREE_VALUE (arg_types), ctype)))
 	goto fail;
     }
 
@@ -3552,8 +3552,7 @@  conditional_conversion (tree e1, tree e2)
       if (good_base && at_least_as_qualified_p (t2, t1))
 	{
 	  conv = build_identity_conv (t1, e1);
-	  if (!same_type_p (TYPE_MAIN_VARIANT (t1),
-			    TYPE_MAIN_VARIANT (t2)))
+	  if (!same_type_ignoring_top_level_qualifiers_p (t1, t2))
 	    conv = build_conv (ck_base, t2, conv);
 	  else
 	    conv = build_conv (ck_rvalue, t2, conv);
@@ -4408,8 +4407,8 @@  build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
 	    case NE_EXPR:
 	      if (TREE_CODE (TREE_TYPE (arg1)) == ENUMERAL_TYPE
 		  && TREE_CODE (TREE_TYPE (arg2)) == ENUMERAL_TYPE
-		  && (TYPE_MAIN_VARIANT (TREE_TYPE (arg1))
-		      != TYPE_MAIN_VARIANT (TREE_TYPE (arg2)))
+		  && !(same_type_ignoring_top_level_qualifiers_p
+		       (TREE_TYPE (arg1), TREE_TYPE (arg2)))
 		  && (complain & tf_warning))
 		{
 		  warning (OPT_Wenum_compare,
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index c2831c1..9296080 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -5422,7 +5422,7 @@  finish_struct_1 (tree t)
   for (x = TYPE_FIELDS (t); x; x = TREE_CHAIN (x))
     if (TREE_CODE (x) == VAR_DECL && TREE_STATIC (x)
         && TREE_TYPE (x) != error_mark_node
-	&& same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (x)), t))
+	&& same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (x), t))
       DECL_MODE (x) = TYPE_MODE (t);
 
   /* Done with FIELDS...now decide whether to sort these for
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 2e3f11d..0a78074 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1180,8 +1180,8 @@  cxx_omp_predetermined_sharing (tree decl)
 	  if (outer)
 	    for (var = BLOCK_VARS (outer); var; var = TREE_CHAIN (var))
 	      if (DECL_NAME (decl) == DECL_NAME (var)
-		  && (TYPE_MAIN_VARIANT (type)
-		      == TYPE_MAIN_VARIANT (TREE_TYPE (var))))
+		  && (same_type_ignoring_top_level_qualifiers_p
+		      (type, TREE_TYPE (var))))
 		{
 		  if (TYPE_READONLY (TREE_TYPE (var)))
 		    type = TREE_TYPE (var);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 37a0f1e..753fe36 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -293,7 +293,7 @@  typedef struct ptrmem_cst * ptrmem_cst_t;
 /* Returns nonzero iff TYPE1 and TYPE2 are the same type, ignoring
    top-level qualifiers.  */
 #define same_type_ignoring_top_level_qualifiers_p(TYPE1, TYPE2) \
-  same_type_p (TYPE_MAIN_VARIANT (TYPE1), TYPE_MAIN_VARIANT (TYPE2))
+  same_type_p (cv_unqualified (TYPE1), cv_unqualified (TYPE2))
 
 /* Nonzero if we are presently building a statement tree, rather
    than expanding each statement as we encounter it.  */
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 646610a..10f301d 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -123,9 +123,7 @@  cp_convert_to_pointer (tree type, tree expr)
 
   if (POINTER_TYPE_P (intype))
     {
-      intype = TYPE_MAIN_VARIANT (intype);
-
-      if (TYPE_MAIN_VARIANT (type) != intype
+      if (!same_type_ignoring_top_level_qualifiers_p (type, intype)
 	  && TREE_CODE (type) == POINTER_TYPE
 	  && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
 	  && MAYBE_CLASS_TYPE_P (TREE_TYPE (type))
@@ -141,8 +139,9 @@  cp_convert_to_pointer (tree type, tree expr)
 	  intype_class = TREE_TYPE (intype);
 	  type_class = TREE_TYPE (type);
 
-	  same_p = same_type_p (TYPE_MAIN_VARIANT (intype_class),
-				TYPE_MAIN_VARIANT (type_class));
+	  same_p = (same_type_ignoring_top_level_qualifiers_p
+		    (intype_class, type_class));
+
 	  binfo = NULL_TREE;
 	  /* Try derived to base conversion.  */
 	  if (!same_p)
@@ -253,9 +252,7 @@  convert_to_pointer_force (tree type, tree expr)
 
   if (form == POINTER_TYPE)
     {
-      intype = TYPE_MAIN_VARIANT (intype);
-
-      if (TYPE_MAIN_VARIANT (type) != intype
+      if (!same_type_ignoring_top_level_qualifiers_p (type, intype)
 	  && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
 	  && MAYBE_CLASS_TYPE_P (TREE_TYPE (type))
 	  && MAYBE_CLASS_TYPE_P (TREE_TYPE (intype))
@@ -332,7 +329,7 @@  build_up_reference (tree type, tree arg, int flags, tree decl)
     return error_mark_node;
 
   if ((flags & LOOKUP_PROTECT)
-      && TYPE_MAIN_VARIANT (argtype) != TYPE_MAIN_VARIANT (target_type)
+      && !same_type_ignoring_top_level_qualifiers_p (argtype, target_type)
       && MAYBE_CLASS_TYPE_P (argtype)
       && MAYBE_CLASS_TYPE_P (target_type))
     {
@@ -395,7 +392,7 @@  tree
 convert_to_reference (tree reftype, tree expr, int convtype,
 		      int flags, tree decl)
 {
-  tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype));
+  tree type = cv_unqualified (TREE_TYPE (reftype));
   tree intype;
   tree rval = NULL_TREE;
   tree rval_as_conversion = NULL_TREE;
@@ -415,7 +412,7 @@  convert_to_reference (tree reftype, tree expr, int convtype,
   gcc_assert (TREE_CODE (intype) != REFERENCE_TYPE);
   gcc_assert (TREE_CODE (reftype) == REFERENCE_TYPE);
 
-  intype = TYPE_MAIN_VARIANT (intype);
+  intype = cv_unqualified (intype);
 
   can_convert_intype_to_type = can_convert (type, intype);
   if (!can_convert_intype_to_type
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index d5ccd65..dae6bfa 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -926,19 +926,12 @@  cp_build_qualified_type_real (tree type,
   return result;
 }
 
-/* Return TYPE with const and volatile removed.  */
+/* Return TYPE with const, volatile and restrict removed.  */
 
 tree
 cv_unqualified (tree type)
 {
-  int quals;
-
-  if (type == error_mark_node)
-    return type;
-
-  quals = cp_type_quals (type);
-  quals &= ~(TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE);
-  return cp_build_qualified_type (type, quals);
+  return cp_build_qualified_type (type, TYPE_UNQUALIFIED);
 }
 
 /* Builds a qualified variant of T that is not a typedef variant.

commit 1514f0d2849c03c7c10dbe42e5a9daac6a19008d
Author: Jason Merrill <jason@redhat.com>
Date:   Fri May 28 11:05:32 2010 -0400

    more type_main_variant

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 753fe36..6fbd30c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1110,6 +1110,7 @@  enum languages { lang_c, lang_cplusplus, lang_java };
 
 /* The _DECL for this _TYPE.  */
 #define TYPE_MAIN_DECL(NODE) (TYPE_STUB_DECL (TYPE_MAIN_VARIANT (NODE)))
+#define TYPE_MAIN_NAME(NODE) (TYPE_NAME (TYPE_MAIN_VARIANT (NODE)))
 
 /* Nonzero if T is a class (or struct or union) type.  Also nonzero
    for template type parameters, typename types, and instantiated
@@ -5256,6 +5257,7 @@  extern bool type_has_nontrivial_copy_init	(const_tree);
 extern bool class_tmpl_impl_spec_p		(const_tree);
 extern int zero_init_p				(const_tree);
 extern tree strip_typedefs			(tree);
+extern tree strip_top_typedef			(tree);
 extern bool typedef_variant_p			(tree);
 extern void cp_set_underlying_type		(tree);
 extern tree copy_binfo				(tree, tree, tree,
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 10f301d..55f4b8b 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -1303,7 +1303,7 @@  type_promotes_to (tree type)
   if (type == error_mark_node)
     return error_mark_node;
 
-  type = TYPE_MAIN_VARIANT (type);
+  type = cv_unqualified (type);
 
   /* Check for promotions of target-defined types first.  */
   promoted_type = targetm.promoted_type (type);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 0d30340..18e6346 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5028,7 +5028,7 @@  reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p)
       braces); a wchar_t array can be initialized by a wide
       string-literal (optionally enclosed in braces).  */
   if (TREE_CODE (type) == ARRAY_TYPE
-      && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type))))
+      && char_type_p (cv_unqualified (TREE_TYPE (type))))
     {
       tree str_init = init;
 
@@ -6506,7 +6506,7 @@  cp_complete_array_type (tree *ptype, tree initial_value, bool do_default)
 
 	 FIXME: this code is duplicated from reshape_init. Probably
 	 we should just call reshape_init here?  */
-      if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (*ptype)))
+      if (char_type_p (cv_unqualified (TREE_TYPE (*ptype)))
 	  && TREE_CODE (initial_value) == CONSTRUCTOR
 	  && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (initial_value)))
 	{
@@ -7203,7 +7203,7 @@  build_ptrmemfunc_type (tree type)
      type first.  */
   if (cp_type_quals (type) != TYPE_UNQUALIFIED)
     unqualified_variant
-      = build_ptrmemfunc_type (TYPE_MAIN_VARIANT (type));
+      = build_ptrmemfunc_type (cv_unqualified (type));
 
   t = make_class_type (RECORD_TYPE);
   xref_basetypes (t, NULL_TREE);
@@ -8175,7 +8175,7 @@  grokdeclarator (const cp_declarator *declarator,
 	  && !(typedef_decl
 	       && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))
 	  && TREE_CODE (type) == INTEGER_TYPE
-	  && !same_type_p (TYPE_MAIN_VARIANT (type), wchar_type_node)))
+	  && !same_type_p (cv_unqualified (type), wchar_type_node)))
     {
       if (explicit_int128)
 	type = int128_unsigned_type_node;
@@ -9158,7 +9158,7 @@  grokdeclarator (const cp_declarator *declarator,
                           "declare static member functions")
                      : G_("qualified function types cannot be used to "
                           "declare free functions"));
-	      type = TYPE_MAIN_VARIANT (type);
+	      type = apply_memfn_quals (type, TYPE_UNQUALIFIED);
 	    }
 
 	  /* The qualifiers on the function type become the qualifiers on
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 592f360..a24f659 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -547,17 +547,14 @@  dump_aggr_type (tree t, int flags)
 
   if (name)
     {
-      typdef = !DECL_ARTIFICIAL (name);
-
-      if ((typdef
-	   && ((flags & TFF_CHASE_TYPEDEF)
-	       || (!flag_pretty_templates && DECL_LANG_SPECIFIC (name)
-		   && DECL_TEMPLATE_INFO (name))))
-	  || DECL_SELF_REFERENCE_P (name))
+      while (((typdef = !DECL_ARTIFICIAL (name))
+	      && ((flags & TFF_CHASE_TYPEDEF)
+		  || (!flag_pretty_templates && DECL_LANG_SPECIFIC (name)
+		      && DECL_TEMPLATE_INFO (name))))
+	     || DECL_SELF_REFERENCE_P (name))
 	{
-	  t = TYPE_MAIN_VARIANT (t);
+	  t = DECL_ORIGINAL_TYPE (name);
 	  name = TYPE_NAME (t);
-	  typdef = 0;
 	}
 
       tmplate = !typdef && TREE_CODE (t) != ENUMERAL_TYPE
@@ -1183,7 +1180,7 @@  find_typenames_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
   else if (TREE_CODE (*tp) == TYPENAME_TYPE
 	   || TREE_CODE (*tp) == DECLTYPE_TYPE)
     /* Add the typename without any cv-qualifiers.  */
-    mv = TYPE_MAIN_VARIANT (*tp);
+    mv = cv_unqualified (*tp);
 
   if (mv && (mv == *tp || !pointer_set_insert (d->p_set, mv)))
     VEC_safe_push (tree, gc, d->typenames, mv);
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index de49095..974c6f6 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -102,7 +102,7 @@  prepare_eh_type (tree type)
   type = non_reference (type);
 
   /* Peel off cv qualifiers.  */
-  type = TYPE_MAIN_VARIANT (type);
+  type = cv_unqualified (type);
 
   /* Functions and arrays decay to pointers.  */
   type = type_decays_to (type);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 3e56417..7734dff 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -3130,7 +3130,7 @@  build_delete (tree type, tree addr, special_function_kind auto_delete,
   if (type == error_mark_node)
     return error_mark_node;
 
-  type = TYPE_MAIN_VARIANT (type);
+  type = cv_unqualified (type);
 
   addr = mark_rvalue_use (addr);
 
@@ -3138,7 +3138,7 @@  build_delete (tree type, tree addr, special_function_kind auto_delete,
     {
       bool complete_p = true;
 
-      type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
+      type = cv_unqualified (TREE_TYPE (type));
       if (TREE_CODE (type) == ARRAY_TYPE)
 	goto handle_array;
 
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index e825952..7a2ac01 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -157,7 +157,6 @@  static int decl_is_template_id (const tree, tree* const);
 
 /* Functions for handling substitutions.  */
 
-static inline tree canonicalize_for_substitution (tree);
 static void add_substitution (tree);
 static inline int is_std_substitution (const tree,
 				       const substitution_identifier_index_t);
@@ -330,49 +329,16 @@  dump_substitution_candidates (void)
     }
 }
 
-/* Both decls and types can be substitution candidates, but sometimes
-   they refer to the same thing.  For instance, a TYPE_DECL and
-   RECORD_TYPE for the same class refer to the same thing, and should
-   be treated accordingly in substitutions.  This function returns a
-   canonicalized tree node representing NODE that is used when adding
-   and substitution candidates and finding matches.  */
-
-static inline tree
-canonicalize_for_substitution (tree node)
-{
-  /* For a TYPE_DECL, use the type instead.  */
-  if (TREE_CODE (node) == TYPE_DECL)
-    node = TREE_TYPE (node);
-  if (TYPE_P (node)
-      && TYPE_CANONICAL (node) != node
-      && TYPE_MAIN_VARIANT (node) != node)
-      /* Here we want to strip the topmost typedef only.
-         We need to do that so is_std_substitution can do proper
-         name matching.  */
-    node = cp_build_qualified_type (TYPE_MAIN_VARIANT (node),
-                                    cp_type_quals (node));
-  return node;
-}
-
 /* Add NODE as a substitution candidate.  NODE must not already be on
    the list of candidates.  */
 
 static void
 add_substitution (tree node)
 {
-  tree c;
-
   if (DEBUG_MANGLE)
     fprintf (stderr, "  ++ add_substitution (%s at %10p)\n",
 	     tree_code_name[TREE_CODE (node)], (void *) node);
 
-  /* Get the canonicalized substitution candidate for NODE.  */
-  c = canonicalize_for_substitution (node);
-  if (DEBUG_MANGLE && c != node)
-    fprintf (stderr, "  ++ using candidate (%s at %10p)\n",
-	     tree_code_name[TREE_CODE (node)], (void *) node);
-  node = c;
-
 #if ENABLE_CHECKING
   /* Make sure NODE isn't already a candidate.  */
   {
@@ -414,7 +380,7 @@  is_std_substitution (const tree node,
   else if (CLASS_TYPE_P (node))
     {
       type = node;
-      decl = TYPE_NAME (node);
+      decl = TYPE_MAIN_NAME (node);
     }
   else
     /* These are not the droids you're looking for.  */
@@ -500,13 +466,9 @@  find_substitution (tree node)
     fprintf (stderr, "  ++ find_substitution (%s at %p)\n",
 	     tree_code_name[TREE_CODE (node)], (void *) node);
 
-  /* Obtain the canonicalized substitution representation for NODE.
-     This is what we'll compare against.  */
-  node = canonicalize_for_substitution (node);
-
   /* Check for builtin substitutions.  */
 
-  decl = TYPE_P (node) ? TYPE_NAME (node) : node;
+  decl = TYPE_P (node) ? TYPE_MAIN_NAME (node) : node;
   type = TYPE_P (node) ? node : TREE_TYPE (node);
 
   /* Check for std::allocator.  */
@@ -773,7 +735,7 @@  write_name (tree decl, const int ignore_local_scope)
     {
       /* In case this is a typedef, fish out the corresponding
 	 TYPE_DECL for the main variant.  */
-      decl = TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
+      decl = TYPE_MAIN_NAME (TREE_TYPE (decl));
     }
 
   context = decl_mangling_context (decl);
@@ -1790,9 +1752,9 @@  write_type (tree type)
        mangle the unqualified type.  The recursive call is needed here
        since both the qualified and unqualified types are substitution
        candidates.  */
-    write_type (TYPE_MAIN_VARIANT (type));
+    write_type (cv_unqualified (type));
   else if (TREE_CODE (type) == ARRAY_TYPE)
-    /* It is important not to use the TYPE_MAIN_VARIANT of TYPE here
+    /* It is important not to use the cv_unqualified of TYPE here
        so that the cv-qualification of the element type is available
        in write_array_type.  */
     write_array_type (type);
@@ -1800,9 +1762,6 @@  write_type (tree type)
     {
       tree type_orig = type;
 
-      /* See through any typedefs.  */
-      type = TYPE_MAIN_VARIANT (type);
-
       if (TYPE_PTRMEM_P (type))
 	write_pointer_to_member_type (type);
       else
@@ -1831,13 +1790,8 @@  write_type (tree type)
 	    case INTEGER_TYPE:  /* Includes wchar_t.  */
 	    case REAL_TYPE:
 	    case FIXED_POINT_TYPE:
-	      {
-		/* If this is a typedef, TYPE may not be one of
-		   the standard builtin type nodes, but an alias of one.  Use
-		   TYPE_MAIN_VARIANT to get to the underlying builtin type.  */
-		write_builtin_type (TYPE_MAIN_VARIANT (type));
-		++is_builtin_type;
-	      }
+	      write_builtin_type (type);
+	      ++is_builtin_type;
 	      break;
 
 	    case COMPLEX_TYPE:
@@ -1865,7 +1819,7 @@  write_type (tree type)
 	    case UNBOUND_CLASS_TEMPLATE:
 	      /* We handle TYPENAME_TYPEs and UNBOUND_CLASS_TEMPLATEs like
 		 ordinary nested names.  */
-	      write_nested_name (TYPE_STUB_DECL (type));
+	      write_nested_name (TYPE_MAIN_NAME (type));
 	      break;
 
 	    case POINTER_TYPE:
@@ -2329,7 +2283,7 @@  write_method_parms (tree parm_types, const int method_p, const tree decl)
 static void
 write_class_enum_type (const tree type)
 {
-  write_name (TYPE_NAME (type), /*ignore_local_scope=*/0);
+  write_name (TYPE_MAIN_NAME (type), /*ignore_local_scope=*/0);
 }
 
 /* Non-terminal <template-args>.  ARGS is a TREE_VEC of template
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9eeba8a..ef482f3 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -3481,7 +3481,7 @@  process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
 
 	   The top-level cv-qualifiers on the template-parameter are
 	   ignored when determining its type.  */
-	TREE_TYPE (parm) = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
+	TREE_TYPE (parm) = cv_unqualified (TREE_TYPE (parm));
 	if (invalid_nontype_parm_type_p (TREE_TYPE (parm), 1))
           {
             err_parm_list = build_tree_list (defval, parm);
@@ -9708,7 +9708,7 @@  tsubst_arg_types (tree arg_types,
     
     /* Do array-to-pointer, function-to-pointer conversion, and ignore
        top-level qualifiers as required.  */
-    type = TYPE_MAIN_VARIANT (type_decays_to (type));
+    type = cv_unqualified (type_decays_to (type));
 
     /* We do not substitute into default arguments here.  The standard
        mandates that they be instantiated only when needed, which is
@@ -10166,7 +10166,7 @@  tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	  case BOUND_TEMPLATE_TEMPLATE_PARM:
 	    if (cp_type_quals (t))
 	      {
-		r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
+		r = tsubst (cv_unqualified (t), args, complain, in_decl);
 		r = cp_build_qualified_type_real
 		  (r, cp_type_quals (t),
 		   complain | (TREE_CODE (t) == TEMPLATE_TYPE_PARM
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 62aa921..ae66d3a 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -252,7 +252,7 @@  get_tinfo_decl_dynamic (tree exp)
   type = non_reference (TREE_TYPE (exp));
 
   /* Peel off cv qualifiers.  */
-  type = TYPE_MAIN_VARIANT (type);
+  type = cv_unqualified (type);
 
   /* For UNKNOWN_TYPEs call complete_type_or_else to get diagnostics.  */
   if (CLASS_TYPE_P (type) || type == unknown_type_node
@@ -276,7 +276,7 @@  get_tinfo_decl_dynamic (tree exp)
     }
   else
     /* Otherwise return the type_info for the static type of the expr.  */
-    t = get_tinfo_ptr (TYPE_MAIN_VARIANT (type));
+    t = get_tinfo_ptr (type);
 
   return cp_build_indirect_ref (t, RO_NULL, tf_warning_or_error);
 }
@@ -300,7 +300,7 @@  typeid_ok_p (void)
 
   pseudo_type_info
     = VEC_index (tinfo_s, tinfo_descs, TK_TYPE_INFO_TYPE)->type;
-  type_info_type = TYPE_MAIN_VARIANT (const_type_info_type_node);
+  type_info_type = cv_unqualified (const_type_info_type_node);
 
   /* Make sure abi::__type_info_pseudo has the same alias set
      as std::type_info.  */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index bf016f1..3af9e2e 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -4967,7 +4967,7 @@  finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
               else if (expr == current_class_ptr)
                 /* If the expression is just "this", we want the
                    cv-unqualified pointer for the "this" type.  */
-                type = TYPE_MAIN_VARIANT (type);
+                type = cv_unqualified (type);
               else if (real_lvalue_p (expr))
                 {
                   if (TREE_CODE (type) != REFERENCE_TYPE)
@@ -5568,7 +5568,7 @@  apply_lambda_return_type (tree lambda, tree return_type)
      Now we need to redo the work it and allocate_struct_function
      did to reflect the new type.  */
   result = build_decl (input_location, RESULT_DECL, NULL_TREE,
-		       TYPE_MAIN_VARIANT (return_type));
+		       cv_unqualified (return_type));
   DECL_ARTIFICIAL (result) = 1;
   DECL_IGNORED_P (result) = 1;
   cp_apply_type_quals_to_decl (cp_type_quals (return_type),
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index dae6bfa..41404cc 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -531,7 +531,7 @@  convert_bitfield_to_declared_type (tree expr)
 
   bitfield_type = is_bitfield_expr_with_lowered_type (expr);
   if (bitfield_type)
-    expr = convert_to_integer (TYPE_MAIN_VARIANT (bitfield_type),
+    expr = convert_to_integer (cv_unqualified (bitfield_type),
 			       expr);
   return expr;
 }
@@ -662,6 +662,7 @@  build_cplus_array_type (tree elt_type, tree index_type)
   else
     t = build_array_type (elt_type, index_type);
 
+  /* FIXME do we still need this?  */
   /* We want TYPE_MAIN_VARIANT of an array to strip cv-quals from the
      element type as well, so fix it up if needed.  */
   if (elt_type != TYPE_MAIN_VARIANT (elt_type))
@@ -952,7 +953,7 @@  cv_unqualified (tree type)
     * If T is a type that needs structural equality
       its TYPE_CANONICAL (T) will be NULL.
     * TYPE_CANONICAL (T) desn't carry type attributes
-      and looses template parameter names.   */
+      and loses template parameter names.   */
 
 tree
 strip_typedefs (tree t)
@@ -1042,12 +1043,27 @@  strip_typedefs (tree t)
     }
 
   if (!result)
-      result = TYPE_MAIN_VARIANT (t);
+    return strip_top_typedef (t);
   if (TYPE_ATTRIBUTES (t))
     result = cp_build_type_attribute_variant (result, TYPE_ATTRIBUTES (t));
   return cp_build_qualified_type (result, cp_type_quals (t));
 }
 
+/* Strip just the topmost typedef from TYPE, don't recurse.  */
+
+tree
+strip_top_typedef (tree type)
+{
+  tree t = type;
+  if (!t || t == error_mark_node || t == TYPE_CANONICAL (t))
+    return t;
+  while (typedef_variant_p (t))
+    t = DECL_ORIGINAL_TYPE (TYPE_NAME (t));
+  t = cp_build_type_attribute_variant (t, TYPE_ATTRIBUTES (type));
+  t = cp_build_qualified_type (t, cp_type_quals (type));
+  return type;
+}
+
 /* Returns true iff TYPE is a type variant created for a typedef. */
 
 bool
@@ -2311,7 +2327,7 @@  maybe_dummy_object (tree type, tree* binfop)
       /* Kludge: Make sure that current_class_type is actually
 	 correct.  It might not be if we're in the middle of
 	 tsubst_default_argument.  */
-      && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)),
+      && same_type_p (cv_unqualified (TREE_TYPE (current_class_ref)),
 		      current_class_type))
     decl = current_class_ref;
   else if (current != current_class_type
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 4ad9349..1128dd0 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2037,7 +2037,7 @@  string_conv_p (const_tree totype, const_tree exp, int warn)
   if (TREE_CODE (exp) == STRING_CST)
     {
       /* Make sure that we don't try to convert between char and wide chars.  */
-      if (!same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (exp))), t))
+      if (!same_type_p (cv_unqualified (TREE_TYPE (TREE_TYPE (exp))), t))
 	return 0;
     }
   else
@@ -2430,7 +2430,7 @@  lookup_destructor (tree object, tree scope, tree dtor_name)
   else if (!DERIVED_FROM_P (dtor_type, TYPE_MAIN_VARIANT (object_type)))
     {
       error ("the type being destroyed is %qT, but the destructor refers to %qT",
-	     TYPE_MAIN_VARIANT (object_type), dtor_type);
+	     cv_unqualified (object_type), dtor_type);
       return error_mark_node;
     }
   expr = lookup_member (dtor_type, complete_dtor_identifier,
@@ -5868,10 +5868,10 @@  build_static_cast_1 (tree type, tree expr, bool c_cast_p,
 	{
 	  t1 = (build_ptrmem_type
 		(c1,
-		 TYPE_MAIN_VARIANT (TYPE_PTRMEM_POINTED_TO_TYPE (intype))));
+		 cv_unqualified (TYPE_PTRMEM_POINTED_TO_TYPE (intype))));
 	  t2 = (build_ptrmem_type
 		(c2,
-		 TYPE_MAIN_VARIANT (TYPE_PTRMEM_POINTED_TO_TYPE (type))));
+		 cv_unqualified (TYPE_PTRMEM_POINTED_TO_TYPE (type))));
 	}
       else
 	{
@@ -6414,10 +6414,10 @@  cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain)
 
       /* Non-class rvalues always have cv-unqualified type.  */
       if (!CLASS_TYPE_P (type))
-	type = TYPE_MAIN_VARIANT (type);
+	type = cv_unqualified (type);
       result_type = TREE_TYPE (result);
       if (!CLASS_TYPE_P (result_type))
-	result_type = TYPE_MAIN_VARIANT (result_type);
+	result_type = cv_unqualified (result_type);
       /* If the type of RESULT does not match TYPE, perform a
 	 const_cast to make it match.  If the static_cast or
 	 reinterpret_cast succeeded, we will differ by at most
@@ -6692,8 +6692,8 @@  cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
 	  newrhs = digest_init (lhstype, newrhs);
 	}
 
-      else if (!same_or_base_type_p (TYPE_MAIN_VARIANT (lhstype),
-				     TYPE_MAIN_VARIANT (TREE_TYPE (newrhs))))
+      else if (!same_or_base_type_p (cv_unqualified (lhstype),
+				     cv_unqualified (TREE_TYPE (newrhs))))
 	{
 	  if (complain & tf_error)
 	    error ("incompatible types in assignment of %qT to %qT",
@@ -7625,8 +7625,8 @@  check_return_expr (tree retval, bool *no_warning)
      /* The cv-unqualified type of the returned value must be the
         same as the cv-unqualified return type of the
         function.  */
-     && same_type_p ((TYPE_MAIN_VARIANT (TREE_TYPE (retval))),
-                     (TYPE_MAIN_VARIANT
+     && same_type_p ((cv_unqualified (TREE_TYPE (retval))),
+                     (cv_unqualified
                       (TREE_TYPE (TREE_TYPE (current_function_decl)))))
      /* And the returned value must be non-volatile.  */
      && ! TYPE_VOLATILE (TREE_TYPE (retval)));
@@ -7842,7 +7842,7 @@  ptr_reasonably_similar (const_tree to, const_tree from)
 
       if (TREE_CODE (to) != POINTER_TYPE)
 	return comptypes
-	  (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from),
+	  (cv_unqualified (to), cv_unqualified (from),
 	   COMPARE_BASE | COMPARE_DERIVED);
     }
 }
@@ -8094,8 +8094,8 @@  casts_away_constness (tree t1, tree t2)
     return false;
 
   /* Top-level qualifiers don't matter.  */
-  t1 = TYPE_MAIN_VARIANT (t1);
-  t2 = TYPE_MAIN_VARIANT (t2);
+  t1 = cv_unqualified (t1);
+  t2 = cv_unqualified (t2);
   casts_away_constness_r (&t1, &t2);
   if (!can_convert (t2, t1))
     return true;

commit 324274d188ce37bd894619d2b4a27046f8d4ab78
Author: Jason Merrill <jason@redhat.com>
Date:   Fri May 28 12:08:37 2010 -0400

    still more

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index cbe9914..eeb5288 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -981,8 +981,8 @@  standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
 bool
 reference_related_p (tree t1, tree t2)
 {
-  t1 = TYPE_MAIN_VARIANT (t1);
-  t2 = TYPE_MAIN_VARIANT (t2);
+  t1 = cv_unqualified (t1);
+  t2 = cv_unqualified (t2);
 
   /* [dcl.init.ref]
 
@@ -4002,12 +4002,7 @@  static tree
 prep_operand (tree operand)
 {
   if (operand)
-    {
-      if (CLASS_TYPE_P (TREE_TYPE (operand))
-	  && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (operand)))
-	/* Make sure the template type is instantiated now.  */
-	instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (operand)));
-    }
+    complete_type (TREE_TYPE (operand));
 
   return operand;
 }
@@ -4056,7 +4051,7 @@  add_candidates (tree fns, tree first_arg, const VEC(tree,gc) *args,
 	 is considered to be a member of the class of the implicit
 	 object argument for the purpose of defining the type of
 	 the implicit object parameter.  */
-      ctype = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (first_arg)));
+      ctype = TREE_TYPE (TREE_TYPE (first_arg));
     }
   else
     {
@@ -5410,7 +5405,7 @@  convert_for_arg_passing (tree type, tree val)
   bitfield_type = is_bitfield_expr_with_lowered_type (val);
   if (bitfield_type 
       && TYPE_PRECISION (TREE_TYPE (val)) < TYPE_PRECISION (type))
-    val = convert_to_integer (TYPE_MAIN_VARIANT (bitfield_type), val);
+    val = convert_to_integer (cv_unqualified (bitfield_type), val);
 
   if (val == error_mark_node)
     ;
@@ -6267,7 +6262,7 @@  build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args,
   fn = get_first_fn (fns);
   name = DECL_NAME (fn);
 
-  basetype = TYPE_MAIN_VARIANT (TREE_TYPE (instance));
+  basetype = TREE_TYPE (instance);
   gcc_assert (CLASS_TYPE_P (basetype));
 
   if (processing_template_decl)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 6fbd30c..325042b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1111,6 +1111,7 @@  enum languages { lang_c, lang_cplusplus, lang_java };
 /* The _DECL for this _TYPE.  */
 #define TYPE_MAIN_DECL(NODE) (TYPE_STUB_DECL (TYPE_MAIN_VARIANT (NODE)))
 #define TYPE_MAIN_NAME(NODE) (TYPE_NAME (TYPE_MAIN_VARIANT (NODE)))
+#define TYPE_MAIN_IDENTIFIER(NODE) (TYPE_IDENTIFIER (TYPE_MAIN_VARIANT (NODE)))
 
 /* Nonzero if T is a class (or struct or union) type.  Also nonzero
    for template type parameters, typename types, and instantiated
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 55f4b8b..7f6fa8c 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -747,8 +747,6 @@  ocp_convert (tree type, tree expr, int convtype, int flags)
       tree dtype = TREE_TYPE (e);
       tree ctor = NULL_TREE;
 
-      dtype = TYPE_MAIN_VARIANT (dtype);
-
       /* Conversion between aggregate types.  New C++ semantics allow
 	 objects of derived type to be cast to objects of base type.
 	 Old semantics only allowed this between pointers.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 18e6346..2b8b705 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4185,7 +4185,7 @@  start_decl (const cp_declarator *declarator,
      (7.1.3p8), apply any attributes directly to the type.  */
   if (TREE_CODE (decl) == TYPE_DECL
       && TAGGED_TYPE_P (TREE_TYPE (decl))
-      && decl == TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl))))
+      && decl == TYPE_MAIN_NAME (TREE_TYPE (decl)))
     flags = ATTR_FLAG_TYPE_IN_PLACE;
   else
     flags = 0;
@@ -8829,7 +8829,6 @@  grokdeclarator (const cp_declarator *declarator,
       tree t;
 
       ctype = declarator->u.id.qualifying_scope;
-      ctype = TYPE_MAIN_VARIANT (ctype);
       t = ctype;
       while (t != NULL_TREE && CLASS_TYPE_P (t))
 	{
@@ -9212,7 +9211,7 @@  grokdeclarator (const cp_declarator *declarator,
 	    {
 	      /* A friendly class?  */
 	      if (current_class_type)
-		make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type),
+		make_friend_class (current_class_type, type,
 				   /*complain=*/true);
 	      else
 		error ("trying to make class %qT a friend of global scope",
@@ -10162,7 +10161,7 @@  move_fn_p (const_tree d)
 
   if (TREE_CODE (arg_type) == REFERENCE_TYPE
       && TYPE_REF_IS_RVALUE (arg_type)
-      && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)),
+      && same_type_p (cv_unqualified (TREE_TYPE (arg_type)),
                       DECL_CONTEXT (d)))
     result = true;
 
@@ -10471,9 +10470,9 @@  grok_op_properties (tree decl, bool complain)
 	  int ref = (TREE_CODE (t) == REFERENCE_TYPE);
 
 	  if (ref)
-	    t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
+	    t = TREE_TYPE (t);
 
-	  if (TREE_CODE (t) == VOID_TYPE)
+	  if (VOID_TYPE_P (t))
             warning (OPT_Wconversion,
                      ref
                      ? G_("conversion to a reference to void "
@@ -10482,7 +10481,7 @@  grok_op_properties (tree decl, bool complain)
                           "will never use a type conversion operator"));
 	  else if (class_type)
 	    {
-	      if (t == class_type)
+	      if (same_type_p (t, class_type))
                 warning (OPT_Wconversion,
                      ref
                      ? G_("conversion to a reference to the same type "
@@ -10590,19 +10589,17 @@  grok_op_properties (tree decl, bool complain)
 	      tree ret = TREE_TYPE (TREE_TYPE (decl));
 	      if (methodp || TREE_CODE (arg) == REFERENCE_TYPE)
 		arg = TREE_TYPE (arg);
-	      arg = TYPE_MAIN_VARIANT (arg);
 	      if (operator_code == PREINCREMENT_EXPR
 		  || operator_code == PREDECREMENT_EXPR)
 		{
 		  if (TREE_CODE (ret) != REFERENCE_TYPE
-		      || !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
-				       arg))
+		      || !same_type_p (TREE_TYPE (ret), arg))
 		    warning (OPT_Weffc__, "prefix %qD should return %qT", decl,
 			     build_reference_type (arg));
 		}
 	      else
 		{
-		  if (!same_type_p (TYPE_MAIN_VARIANT (ret), arg))
+		  if (!same_type_p (ret, arg))
 		    warning (OPT_Weffc__, "postfix %qD should return %qT", decl, arg);
 		}
 	    }
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 0313101..93c1c51 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -869,7 +869,7 @@  grokfield (const cp_declarator *declarator,
 	  /* If this is a typedef that names the class for linkage purposes
 	     (7.1.3p8), apply any attributes directly to the type.  */
 	  if (TAGGED_TYPE_P (TREE_TYPE (value))
-	      && value == TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))))
+	      && value == TYPE_MAIN_NAME (TREE_TYPE (value)))
 	    attrflags = ATTR_FLAG_TYPE_IN_PLACE;
 
 	  cplus_decl_attributes (&value, attrlist, attrflags);
@@ -877,7 +877,7 @@  grokfield (const cp_declarator *declarator,
 
       if (declspecs->specs[(int)ds_typedef]
           && TREE_TYPE (value) != error_mark_node
-          && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
+          && TYPE_MAIN_NAME (TREE_TYPE (value)) != value)
 	cp_set_underlying_type (value);
 
       return value;
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index 7bc11c7..c316bcb 100644
--- a/gcc/cp/friend.c
+++ b/gcc/cp/friend.c
@@ -256,6 +256,8 @@  make_friend_class (tree type, tree friend_type, bool complain)
       return;
     }
 
+  friend_type = TYPE_MAIN_VARIANT (friend_type);
+
   /* [temp.friend]
 
      A friend of a class or class template can be a function or
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4a50b55..a8e109f 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1038,8 +1038,6 @@  make_id_declarator (tree qualifying_scope, tree unqualified_name,
      legal; as of 2002-09-15 the committee is considering that
      question.  EDG 3.0 allows that syntax.  Therefore, we do as
      well.  */
-  if (qualifying_scope && TYPE_P (qualifying_scope))
-    qualifying_scope = TYPE_MAIN_VARIANT (qualifying_scope);
 
   gcc_assert (TREE_CODE (unqualified_name) == IDENTIFIER_NODE
 	      || TREE_CODE (unqualified_name) == BIT_NOT_EXPR
@@ -4577,15 +4575,7 @@  cp_parser_nested_name_specifier_opt (cp_parser *parser,
 	  && !COMPLETE_TYPE_P (new_scope)
 	  /* Do not try to complete dependent types.  */
 	  && !dependent_type_p (new_scope))
-	{
-	  new_scope = complete_type (new_scope);
-	  /* If it is a typedef to current class, use the current
-	     class instead, as the typedef won't have any names inside
-	     it yet.  */
-	  if (!COMPLETE_TYPE_P (new_scope)
-	      && currently_open_class (new_scope))
-	    new_scope = TYPE_MAIN_VARIANT (new_scope);
-	}
+	new_scope = complete_type (new_scope);
       /* Make sure we look in the right scope the next time through
 	 the loop.  */
       parser->scope = new_scope;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index ef482f3..4c149a8 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -7699,6 +7699,8 @@  instantiate_class_template (tree type)
   if (type == error_mark_node)
     return error_mark_node;
 
+  type = TYPE_MAIN_VARIANT (type);
+
   if (TYPE_BEING_DEFINED (type)
       || COMPLETE_TYPE_P (type)
       || uses_template_parms (type))
@@ -13391,7 +13393,7 @@  maybe_adjust_types_for_deduction (unification_kind_t strict,
       else if (TREE_CODE (*arg) == FUNCTION_TYPE)
 	*arg = build_pointer_type (*arg);
       else
-	*arg = TYPE_MAIN_VARIANT (*arg);
+	*arg = cv_unqualified (*arg);
     }
 
   /* From C++0x [14.8.2.1/3 temp.deduct.call] (after DR606), "If P is
@@ -13410,7 +13412,7 @@  maybe_adjust_types_for_deduction (unification_kind_t strict,
      of P's type are ignored for type deduction.  If P is a
      reference type, the type referred to by P is used for
      type deduction.  */
-  *parm = TYPE_MAIN_VARIANT (*parm);
+  *parm = cv_unqualified (*parm);
   if (TREE_CODE (*parm) == REFERENCE_TYPE)
     {
       *parm = TREE_TYPE (*parm);
@@ -15424,8 +15426,8 @@  more_specialized_fn (tree pat1, tree pat2, int len)
 	    }
 	}
 
-      arg1 = TYPE_MAIN_VARIANT (arg1);
-      arg2 = TYPE_MAIN_VARIANT (arg2);
+      arg1 = cv_unqualified (arg1);
+      arg2 = cv_unqualified (arg2);
 
       if (TREE_CODE (arg1) == TYPE_PACK_EXPANSION)
         {
@@ -17318,7 +17320,7 @@  dependent_type_p_r (tree type)
     return true;
   /* -- a cv-qualified type where the cv-unqualified type is
 	dependent.  */
-  type = TYPE_MAIN_VARIANT (type);
+  type = cv_unqualified (type);
   /* -- a compound type constructed from any dependent type.  */
   if (TYPE_PTR_TO_MEMBER_P (type))
     return (dependent_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
@@ -18074,7 +18076,7 @@  resolve_typename_type (tree type, bool only_current_p)
      So by getting the TYPE_IDENTIFIER of the _main declaration_ of the
      TYPENAME_TYPE instead, we avoid messing up with a possible
      typedef variant case.  */
-  name = TYPE_IDENTIFIER (TYPE_MAIN_VARIANT (type));
+  name = TYPE_MAIN_IDENTIFIER (type);
 
   /* If the SCOPE is itself a TYPENAME_TYPE, then we need to resolve
      it first before we can figure out what NAME refers to.  */
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index ae66d3a..6def6d2 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -394,6 +394,8 @@  get_tinfo_decl (tree type)
   tree name;
   tree d;
 
+  type = TYPE_MAIN_VARIANT (type);
+
   if (variably_modified_type_p (type, /*fn=*/NULL_TREE))
     {
       error ("cannot create type information for type %qT because "
@@ -410,7 +412,7 @@  get_tinfo_decl (tree type)
      itself.  */
   if (CLASS_TYPE_P (type))
     {
-      d = CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type));
+      d = CLASSTYPE_TYPEINFO_VAR (type);
       if (d)
 	return d;
     }
@@ -440,7 +442,7 @@  get_tinfo_decl (tree type)
 
       d = pushdecl_top_level_and_finish (d, NULL_TREE);
       if (CLASS_TYPE_P (type))
-	CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d;
+	CLASSTYPE_TYPEINFO_VAR (type) = d;
 
       /* Add decl to the global array of tinfo decls.  */
       VEC_safe_push (tree, gc, unemitted_tinfo_decls, d);
@@ -480,7 +482,7 @@  get_typeid (tree type)
 
   /* The top-level cv-qualifiers of the lvalue expression or the type-id
      that is the operand of typeid are always ignored.  */
-  type = TYPE_MAIN_VARIANT (type);
+  type = cv_unqualified (type);
 
   /* For UNKNOWN_TYPEs call complete_type_or_else to get diagnostics.  */
   if (CLASS_TYPE_P (type) || type == unknown_type_node
@@ -689,8 +691,8 @@  build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
 	      return error_mark_node;
 	    }
 
-	  target_type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
-	  static_type = TYPE_MAIN_VARIANT (TREE_TYPE (exprtype));
+	  target_type = TREE_TYPE (type);
+	  static_type = TREE_TYPE (exprtype);
 	  td2 = get_tinfo_decl (target_type);
 	  mark_used (td2);
 	  td2 = cp_build_unary_op (ADDR_EXPR, td2, 0, complain);
@@ -971,8 +973,7 @@  ptr_initializer (tinfo_s *ti, tree target)
     flags |= 8;
   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init);
   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, flags));
-  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
-                          get_tinfo_ptr (TYPE_MAIN_VARIANT (to)));
+  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, get_tinfo_ptr (to));
 
   init = build_constructor (init_list_type_node, v);
   TREE_CONSTANT (init) = 1;
@@ -1001,8 +1002,7 @@  ptm_initializer (tinfo_s *ti, tree target)
     flags |= 0x10;
   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init);
   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, flags));
-  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
-                          get_tinfo_ptr (TYPE_MAIN_VARIANT (to)));
+  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, get_tinfo_ptr (to));
   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, get_tinfo_ptr (klass));
 
   init = build_constructor (init_list_type_node, v);
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 4843855..052a925 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -360,7 +360,9 @@  dcast_base_hint (tree subtype, tree target)
 {
   struct dcast_data_s data;
 
-  data.subtype = subtype;
+  target = TYPE_MAIN_VARIANT (target);
+
+  data.subtype = TYPE_MAIN_VARIANT (subtype);
   data.virt_depth = 0;
   data.offset = NULL_TREE;
   data.repeated_base = CLASSTYPE_REPEATED_BASE_P (target);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 1128dd0..932ab72 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -125,7 +125,7 @@  complete_type (tree type)
 	}
     }
   else if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
-    instantiate_class_template (TYPE_MAIN_VARIANT (type));
+    instantiate_class_template (type);
 
   return type;
 }
@@ -2124,7 +2124,7 @@  lookup_anon_field (tree t, tree type)
 
       /* If we find it directly, return the field.  */
       if (DECL_NAME (field) == NULL_TREE
-	  && type == TYPE_MAIN_VARIANT (TREE_TYPE (field)))
+	  && type == TREE_TYPE (field))
 	{
 	  return field;
 	}
@@ -2244,8 +2244,8 @@  build_class_member_access_expr (tree object, tree member,
 		       && integer_zerop (TREE_OPERAND (object, 0)));
 
       /* Convert OBJECT to the type of MEMBER.  */
-      if (!same_type_p (TYPE_MAIN_VARIANT (object_type),
-			TYPE_MAIN_VARIANT (member_scope)))
+      if (!same_type_ignoring_top_level_qualifiers_p (object_type,
+						      member_scope))
 	{
 	  tree binfo;
 	  base_kind kind;
@@ -2427,7 +2427,7 @@  lookup_destructor (tree object, tree scope, tree dtor_name)
 	}
       
     }
-  else if (!DERIVED_FROM_P (dtor_type, TYPE_MAIN_VARIANT (object_type)))
+  else if (!DERIVED_FROM_P (dtor_type, object_type))
     {
       error ("the type being destroyed is %qT, but the destructor refers to %qT",
 	     cv_unqualified (object_type), dtor_type);
@@ -5070,7 +5070,7 @@  cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
 	     contains an extra const qualifier.  TYPE_MAIN_VARIANT
 	     is used here to remove this const from the diagnostics
 	     and the created OFFSET_REF.  */
-	  tree base = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg, 0)));
+	  tree base = cv_unqualified (TREE_TYPE (TREE_OPERAND (arg, 0)));
 	  tree fn = get_first_fn (TREE_OPERAND (arg, 1));
 	  mark_used (fn);
 
@@ -5724,8 +5724,8 @@  build_static_cast_1 (tree type, tree expr, bool c_cast_p,
       && CLASS_TYPE_P (intype)
       && (TYPE_REF_IS_RVALUE (type) || real_lvalue_p (expr))
       && DERIVED_FROM_P (intype, TREE_TYPE (type))
-      && can_convert (build_pointer_type (TYPE_MAIN_VARIANT (intype)),
-		      build_pointer_type (TYPE_MAIN_VARIANT
+      && can_convert (build_pointer_type (cv_unqualified (intype)),
+		      build_pointer_type (cv_unqualified
 					  (TREE_TYPE (type))))
       && (c_cast_p
 	  || at_least_as_qualified_p (TREE_TYPE (type), intype)))
@@ -5838,9 +5838,9 @@  build_static_cast_1 (tree type, tree expr, bool c_cast_p,
   if (TYPE_PTR_P (type) && TYPE_PTR_P (intype)
       && CLASS_TYPE_P (TREE_TYPE (type))
       && CLASS_TYPE_P (TREE_TYPE (intype))
-      && can_convert (build_pointer_type (TYPE_MAIN_VARIANT
+      && can_convert (build_pointer_type (cv_unqualified
 					  (TREE_TYPE (intype))),
-		      build_pointer_type (TYPE_MAIN_VARIANT
+		      build_pointer_type (cv_unqualified
 					  (TREE_TYPE (type)))))
     {
       tree base;
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index e512272..33086ae 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1493,7 +1493,7 @@  build_m_component_ref (tree datum, tree component)
       return error_mark_node;
     }
 
-  objtype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
+  objtype = cv_unqualified (TREE_TYPE (datum));
   if (! MAYBE_CLASS_TYPE_P (objtype))
     {
       error ("cannot apply member pointer %qE to %qE, which is of "

commit 123ca011e01b56ff3608d101fdb19100ced35d41
Author: Jason Merrill <jason@redhat.com>
Date:   Fri May 28 15:59:39 2010 -0400

    more yet

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 325042b..4f6ea24 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -294,7 +294,6 @@  typedef struct ptrmem_cst * ptrmem_cst_t;
    top-level qualifiers.  */
 #define same_type_ignoring_top_level_qualifiers_p(TYPE1, TYPE2) \
   same_type_p (cv_unqualified (TYPE1), cv_unqualified (TYPE2))
-
 /* Nonzero if we are presently building a statement tree, rather
    than expanding each statement as we encounter it.  */
 #define building_stmt_tree()  (cur_stmt_list != NULL_TREE)
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 2b8b705..29e07ee 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -8075,7 +8075,8 @@  grokdeclarator (const cp_declarator *declarator,
      and check for invalid combinations.  */
 
   /* Long double is a special combination.  */
-  if (long_p && !longlong && TYPE_MAIN_VARIANT (type) == double_type_node)
+  if (long_p && !longlong
+      && same_type_ignoring_top_level_qualifiers_p (type, double_type_node))
     {
       long_p = false;
       type = cp_build_qualified_type (long_double_type_node,
@@ -9120,9 +9121,8 @@  grokdeclarator (const cp_declarator *declarator,
      We must copy the type, so that the array's domain can be
      individually set by the object's initializer.  */
 
-  if (type && typedef_type
-      && TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
-      && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type))
+  if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
+      && typedef_variant_p (type))
     type = build_cplus_array_type (TREE_TYPE (type), NULL_TREE);
 
   /* Detect where we're using a typedef of function type to declare a
@@ -10099,14 +10099,15 @@  copy_fn_p (const_tree d)
   if (arg_type == error_mark_node)
     return 0;
 
-  if (TYPE_MAIN_VARIANT (arg_type) == DECL_CONTEXT (d))
+  if (same_type_ignoring_top_level_qualifiers_p (arg_type, DECL_CONTEXT (d)))
     {
       /* Pass by value copy assignment operator.  */
       result = -1;
     }
   else if (TREE_CODE (arg_type) == REFERENCE_TYPE
 	   && !TYPE_REF_IS_RVALUE (arg_type)
-	   && TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)) == DECL_CONTEXT (d))
+	   && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (arg_type),
+							 DECL_CONTEXT (d)))
     {
       if (CP_TYPE_CONST_P (TREE_TYPE (arg_type)))
 	result = 2;
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index c316bcb..ffad18b 100644
--- a/gcc/cp/friend.c
+++ b/gcc/cp/friend.c
@@ -256,8 +256,6 @@  make_friend_class (tree type, tree friend_type, bool complain)
       return;
     }
 
-  friend_type = TYPE_MAIN_VARIANT (friend_type);
-
   /* [temp.friend]
 
      A friend of a class or class template can be a function or
@@ -353,6 +351,8 @@  make_friend_class (tree type, tree friend_type, bool complain)
   if (friend_type == error_mark_node)
     return;
 
+  friend_type = TYPE_MAIN_VARIANT (friend_type);
+
   /* See if it is already a friend.  */
   for (classes = CLASSTYPE_FRIEND_CLASSES (type);
        classes;
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 051d3c5..0f4ed0c 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -1801,7 +1801,7 @@  set_identifier_type_value (tree id, tree decl)
 static inline tree
 constructor_name_full (tree type)
 {
-  return TYPE_IDENTIFIER (TYPE_MAIN_VARIANT (type));
+  return TYPE_MAIN_IDENTIFIER (type);
 }
 
 /* Return the name for the constructor (or destructor) for the
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 3af9e2e..bb5ea66 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2582,7 +2582,7 @@  finish_base_specifier (tree base, tree access, bool virtual_p)
       if (cp_type_quals (base) != 0)
 	{
 	  error ("base class %qT has cv qualifiers", base);
-	  base = TYPE_MAIN_VARIANT (base);
+	  base = cv_unqualified (base);
 	}
       result = build_tree_list (access, base);
       if (virtual_p)
@@ -5809,8 +5809,9 @@  lambda_expr_this_capture (tree lambda)
     }
   else
     {
-      /* To make sure that current_class_ref is for the lambda.  */
-      gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)) == TREE_TYPE (lambda));
+      /* Make sure that current_class_ref is for the lambda.  */
+      gcc_assert (same_type_ignoring_top_level_qualifiers_p
+		  (TREE_TYPE (current_class_ref), TREE_TYPE (lambda)));
 
       result = finish_non_static_data_member (this_capture,
                                               NULL_TREE,
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 41404cc..1879db5 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2866,6 +2866,7 @@  special_function_p (const_tree decl)
 int
 char_type_p (tree type)
 {
+  type = cv_unqualified (type);
   return (same_type_p (type, char_type_node)
 	  || same_type_p (type, unsigned_char_type_node)
 	  || same_type_p (type, signed_char_type_node)
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 932ab72..5896843 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -263,9 +263,12 @@  cp_common_type (tree t1, tree t2)
      attributes.  */
   attributes = (*targetm.merge_type_attributes) (t1, t2);
 
+  gcc_assert (t1 == cv_unqualified (t1)
+	      && t2 == cv_unqualified (t2));
+
   if (SCOPED_ENUM_P (t1) || SCOPED_ENUM_P (t2))
     {
-      if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
+      if (same_type_p (t1, t2))
 	return build_type_attribute_variant (t1, attributes);
       else
 	return NULL_TREE;
@@ -321,15 +324,15 @@  cp_common_type (tree t1, tree t2)
     return build_type_attribute_variant (t2, attributes);
 
   /* The types are the same; no need to do anything fancy.  */
-  if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
+  if (same_type_p (t1, t2))
     return build_type_attribute_variant (t1, attributes);
 
   if (code1 != REAL_TYPE)
     {
       /* If one is unsigned long long, then convert the other to unsigned
 	 long long.  */
-      if (same_type_p (TYPE_MAIN_VARIANT (t1), long_long_unsigned_type_node)
-	  || same_type_p (TYPE_MAIN_VARIANT (t2), long_long_unsigned_type_node))
+      if (same_type_p (t1, long_long_unsigned_type_node)
+	  || same_type_p (t2, long_long_unsigned_type_node))
 	return build_type_attribute_variant (long_long_unsigned_type_node,
 					     attributes);
       /* If one is a long long, and the other is an unsigned long, and
@@ -342,8 +345,8 @@  cp_common_type (tree t1, tree t2)
 	 therefore converting to long long cannot represent all the values
 	 of an unsigned long, so we choose unsigned long long in that
 	 case.  */
-      if (same_type_p (TYPE_MAIN_VARIANT (t1), long_long_integer_type_node)
-	  || same_type_p (TYPE_MAIN_VARIANT (t2), long_long_integer_type_node))
+      if (same_type_p (t1, long_long_integer_type_node)
+	  || same_type_p (t2, long_long_integer_type_node))
 	{
 	  tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
 		    ? long_long_unsigned_type_node
@@ -351,10 +354,8 @@  cp_common_type (tree t1, tree t2)
 	  return build_type_attribute_variant (t, attributes);
 	}
       if (int128_integer_type_node != NULL_TREE
-	  && (same_type_p (TYPE_MAIN_VARIANT (t1),
-			   int128_integer_type_node)
-	      || same_type_p (TYPE_MAIN_VARIANT (t2),
-			      int128_integer_type_node)))
+	  && (same_type_p (t1, int128_integer_type_node)
+	      || same_type_p (t2, int128_integer_type_node)))
 	{
 	  tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
 		    ? int128_unsigned_type_node
@@ -363,12 +364,12 @@  cp_common_type (tree t1, tree t2)
 	}
 
       /* Go through the same procedure, but for longs.  */
-      if (same_type_p (TYPE_MAIN_VARIANT (t1), long_unsigned_type_node)
-	  || same_type_p (TYPE_MAIN_VARIANT (t2), long_unsigned_type_node))
+      if (same_type_p (t1, long_unsigned_type_node)
+	  || same_type_p (t2, long_unsigned_type_node))
 	return build_type_attribute_variant (long_unsigned_type_node,
 					     attributes);
-      if (same_type_p (TYPE_MAIN_VARIANT (t1), long_integer_type_node)
-	  || same_type_p (TYPE_MAIN_VARIANT (t2), long_integer_type_node))
+      if (same_type_p (t1, long_integer_type_node)
+	  || same_type_p (t2, long_integer_type_node))
 	{
 	  tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
 		    ? long_unsigned_type_node : long_integer_type_node);
@@ -382,16 +383,16 @@  cp_common_type (tree t1, tree t2)
     }
   else
     {
-      if (same_type_p (TYPE_MAIN_VARIANT (t1), long_double_type_node)
-	  || same_type_p (TYPE_MAIN_VARIANT (t2), long_double_type_node))
+      if (same_type_p (t1, long_double_type_node)
+	  || same_type_p (t2, long_double_type_node))
 	return build_type_attribute_variant (long_double_type_node,
 					     attributes);
-      if (same_type_p (TYPE_MAIN_VARIANT (t1), double_type_node)
-	  || same_type_p (TYPE_MAIN_VARIANT (t2), double_type_node))
+      if (same_type_p (t1, double_type_node)
+	  || same_type_p (t2, double_type_node))
 	return build_type_attribute_variant (double_type_node,
 					     attributes);
-      if (same_type_p (TYPE_MAIN_VARIANT (t1), float_type_node)
-	  || same_type_p (TYPE_MAIN_VARIANT (t2), float_type_node))
+      if (same_type_p (t1, float_type_node)
+	  || same_type_p (t2, float_type_node))
 	return build_type_attribute_variant (float_type_node,
 					     attributes);
 
@@ -1195,7 +1196,8 @@  incompatible_dependent_types_p (tree t1, tree t2)
        At this point, if the main variant type of T1 and T2 are equal
        it means the two types can't be incompatible, from the perspective
        of this function.  */
-    if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
+    /* FIXME a4d2e70 typedef33.C? */
+    if (0 && TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
       return false;
 
   /* So if we reach this point, it means either T1 or T2 is a typedef variant.
@@ -1825,8 +1827,9 @@  is_bitfield_expr_with_lowered_type (const_tree exp)
       }
 
     CASE_CONVERT:
-      if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (exp, 0)))
-	  == TYPE_MAIN_VARIANT (TREE_TYPE (exp)))
+      if (same_type_ignoring_top_level_qualifiers_p
+	  (TREE_TYPE (TREE_OPERAND (exp, 0)),
+	   TREE_TYPE (exp)))
 	return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0));
       /* Fallthrough.  */
 
@@ -3917,7 +3920,8 @@  cp_build_binary_op (location_t location,
 	    }
 	  /* Convert the shift-count to an integer, regardless of
 	     size of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (op1),
+							  integer_type_node))
 	    op1 = cp_convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;
@@ -3945,7 +3949,8 @@  cp_build_binary_op (location_t location,
 	    }
 	  /* Convert the shift-count to an integer, regardless of
 	     size of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (op1),
+							  integer_type_node))
 	    op1 = cp_convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;
@@ -3976,7 +3981,8 @@  cp_build_binary_op (location_t location,
 	    }
 	  /* Convert the shift-count to an integer, regardless of
 	     size of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (op1),
+							  integer_type_node))
 	    op1 = cp_convert (integer_type_node, op1);
 	}
       break;
@@ -5067,7 +5073,7 @@  cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
 	     a useful error here.  */
 
 	  /* Inside constant member functions, the `this' pointer
-	     contains an extra const qualifier.  TYPE_MAIN_VARIANT
+	     contains an extra const qualifier.  cv_unqualified
 	     is used here to remove this const from the diagnostics
 	     and the created OFFSET_REF.  */
 	  tree base = cv_unqualified (TREE_TYPE (TREE_OPERAND (arg, 0)));
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 33086ae..d98de9b 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -854,16 +854,16 @@  digest_init_r (tree type, tree init, bool nested, int flags)
      them if they were present.  */
   if (code == ARRAY_TYPE)
     {
-      tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
+      tree typ1 = cv_unqualified (TREE_TYPE (type));
       if (char_type_p (typ1)
 	  /*&& init */
 	  && TREE_CODE (init) == STRING_CST)
 	{
-	  tree char_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (init)));
+	  tree char_type = cv_unqualified (TREE_TYPE (TREE_TYPE (init)));
 
 	  if (TYPE_PRECISION (typ1) == BITS_PER_UNIT)
 	    {
-	      if (char_type != char_type_node)
+	      if (!same_type_p (char_type, char_type_node))
 		{
 		  error ("char-array initialized from wide string");
 		  return error_mark_node;
@@ -871,12 +871,12 @@  digest_init_r (tree type, tree init, bool nested, int flags)
 	    }
 	  else
 	    {
-	      if (char_type == char_type_node)
+	      if (same_type_p (char_type, char_type_node))
 		{
 		  error ("int-array initialized from non-wide string");
 		  return error_mark_node;
 		}
-	      else if (char_type != typ1)
+	      else if (!same_type_p (char_type, typ1))
 		{
 		  error ("int-array initialized from incompatible wide string");
 		  return error_mark_node;

commit ba2ae527739acee7399c5caf573443e5a2283027
Author: Jason Merrill <jason@redhat.com>
Date:   Fri May 28 16:06:05 2010 -0400

    same_cv_unqual

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index eeb5288..1b028da 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -240,7 +240,7 @@  check_dtor_name (tree basetype, tree name)
 
   if (!name || name == error_mark_node)
     return false;
-  return same_type_ignoring_top_level_qualifiers_p (basetype, name);
+  return same_cv_unqualified_type_p (basetype, name);
 }
 
 /* We want the address of a function or method.  We avoid creating a
@@ -807,8 +807,7 @@  standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
       tree from_pointee;
 
       if (tcode == POINTER_TYPE
-	  && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (from),
-							TREE_TYPE (to)))
+	  && same_cv_unqualified_type_p (TREE_TYPE (from), TREE_TYPE (to)))
 	;
       else if (VOID_TYPE_P (TREE_TYPE (to))
 	       && !TYPE_PTRMEM_P (from)
@@ -825,7 +824,7 @@  standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
 	  tree tbase = TYPE_PTRMEM_CLASS_TYPE (to);
 
 	  if (DERIVED_FROM_P (fbase, tbase)
-	      && (same_type_ignoring_top_level_qualifiers_p
+	      && (same_cv_unqualified_type_p
 		  (TYPE_PTRMEM_POINTED_TO_TYPE (from),
 		   TYPE_PTRMEM_POINTED_TO_TYPE (to))))
 	    {
@@ -1169,7 +1168,7 @@  direct_reference_binding (tree type, conversion *conv)
      either an identity conversion or, if the conversion function
      returns an entity of a type that is a derived class of the
      parameter type, a derived-to-base conversion.  */
-  if (!same_type_ignoring_top_level_qualifiers_p (t, conv->type))
+  if (!same_cv_unqualified_type_p (t, conv->type))
     {
       /* Represent the derived-to-base conversion.  */
       conv = build_conv (ck_base, t, conv);
@@ -2537,8 +2536,8 @@  add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
   if (DECL_CONSTRUCTOR_P (fn) && nargs == 2)
     {
       tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn);
-      if (arg_types && (same_type_ignoring_top_level_qualifiers_p
-			(TREE_VALUE (arg_types), ctype)))
+      if (arg_types && same_cv_unqualified_type_p (TREE_VALUE (arg_types),
+						   ctype))
 	goto fail;
     }
 
@@ -2838,9 +2837,9 @@  build_user_type_conversion_1 (tree totype, tree expr, int flags)
   if (MAYBE_CLASS_TYPE_P (fromtype))
     {
       tree to_nonref = non_reference (totype);
-      if (same_type_ignoring_top_level_qualifiers_p (to_nonref, fromtype) ||
-	  (CLASS_TYPE_P (to_nonref) && CLASS_TYPE_P (fromtype)
-	   && DERIVED_FROM_P (to_nonref, fromtype)))
+      if (same_cv_unqualified_type_p (to_nonref, fromtype)
+	  || (CLASS_TYPE_P (to_nonref) && CLASS_TYPE_P (fromtype)
+	      && DERIVED_FROM_P (to_nonref, fromtype)))
 	{
 	  /* [class.conv.fct] A conversion function is never used to
 	     convert a (possibly cv-qualified) object to the (possibly
@@ -3552,7 +3551,7 @@  conditional_conversion (tree e1, tree e2)
       if (good_base && at_least_as_qualified_p (t2, t1))
 	{
 	  conv = build_identity_conv (t1, e1);
-	  if (!same_type_ignoring_top_level_qualifiers_p (t1, t2))
+	  if (!same_cv_unqualified_type_p (t1, t2))
 	    conv = build_conv (ck_base, t2, conv);
 	  else
 	    conv = build_conv (ck_rvalue, t2, conv);
@@ -4402,8 +4401,8 @@  build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
 	    case NE_EXPR:
 	      if (TREE_CODE (TREE_TYPE (arg1)) == ENUMERAL_TYPE
 		  && TREE_CODE (TREE_TYPE (arg2)) == ENUMERAL_TYPE
-		  && !(same_type_ignoring_top_level_qualifiers_p
-		       (TREE_TYPE (arg1), TREE_TYPE (arg2)))
+		  && !same_cv_unqualified_type_p (TREE_TYPE (arg1),
+						  TREE_TYPE (arg2))
 		  && (complain & tf_warning))
 		{
 		  warning (OPT_Wenum_compare,
@@ -5752,8 +5751,8 @@  build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
       if (TREE_CODE (targ) == ADDR_EXPR)
 	{
 	  targ = TREE_OPERAND (targ, 0);
-	  if (!same_type_ignoring_top_level_qualifiers_p
-	      (TREE_TYPE (TREE_TYPE (arg)), TREE_TYPE (targ)))
+	  if (!same_cv_unqualified_type_p (TREE_TYPE (TREE_TYPE (arg)),
+					   TREE_TYPE (targ)))
 	    targ = NULL_TREE;
 	}
       else
@@ -6083,8 +6082,8 @@  build_special_member_call (tree instance, tree name, VEC(tree,gc) **args,
 	gcc_assert (args == NULL || VEC_empty (tree, *args));
 
       /* Convert to the base class, if necessary.  */
-      if (!same_type_ignoring_top_level_qualifiers_p
-	  (TREE_TYPE (instance), BINFO_TYPE (binfo)))
+      if (!same_cv_unqualified_type_p (TREE_TYPE (instance),
+				       BINFO_TYPE (binfo)))
 	{
 	  if (name != ansi_assopname (NOP_EXPR))
 	    /* For constructors and destructors, either the base is
@@ -6572,7 +6571,7 @@  is_properly_derived_from (tree derived, tree base)
 
   /* We only allow proper derivation here.  The DERIVED_FROM_P macro
      considers every class derived from itself.  */
-  return (!same_type_ignoring_top_level_qualifiers_p (derived, base)
+  return (!same_cv_unqualified_type_p (derived, base)
 	  && DERIVED_FROM_P (base, derived));
 }
 
@@ -7007,7 +7006,7 @@  compare_ics (conversion *ics1, conversion *ics2)
 	    return -1;
 	}
 
-      if (same_type_ignoring_top_level_qualifiers_p (to_type1, to_type2))
+      if (same_cv_unqualified_type_p (to_type1, to_type2))
 	return comp_cv_qualification (TREE_TYPE (ref_conv2->type),
 				      TREE_TYPE (ref_conv1->type));
     }
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 9296080..ce79044 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -578,7 +578,7 @@  build_vfield_ref (tree datum, tree type)
     return error_mark_node;
 
   /* First, convert to the requested type.  */
-  if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (datum), type))
+  if (!same_cv_unqualified_type_p (TREE_TYPE (datum), type))
     datum = convert_to_base (datum, type, /*check_access=*/false,
 			     /*nonnull=*/true, tf_warning_or_error);
 
@@ -590,7 +590,7 @@  build_vfield_ref (tree datum, tree type)
      one step at a time via primary bases avoids the problem.  */
   vfield = TYPE_VFIELD (type);
   vcontext = DECL_CONTEXT (vfield);
-  while (!same_type_ignoring_top_level_qualifiers_p (vcontext, type))
+  while (!same_cv_unqualified_type_p (vcontext, type))
     {
       datum = build_simple_base_path (datum, CLASSTYPE_PRIMARY_BINFO (type));
       type = TREE_TYPE (datum);
@@ -1327,8 +1327,7 @@  check_bases (tree t,
 	  /* ...has no base classes of the same type as the first non-static
 	     data member...  */
 	  if (field && DECL_CONTEXT (field) == t
-	      && (same_type_ignoring_top_level_qualifiers_p
-		  (TREE_TYPE (field), basetype)))
+	      && (same_cv_unqualified_type_p (TREE_TYPE (field), basetype)))
 	    CLASSTYPE_NON_STD_LAYOUT (t) = 1;
 	  else
 	    /* ...either has no non-static data members in the most-derived
@@ -2124,8 +2123,7 @@  update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
 	   there.  */
 	virtual_offset = binfo_for_vbase (BINFO_TYPE (virtual_offset),
 					  over_return);
-      else if (!same_type_ignoring_top_level_qualifiers_p
-	       (over_return, base_return))
+      else if (!same_cv_unqualified_type_p (over_return, base_return))
 	{
 	  /* There was no existing virtual thunk (which takes
 	     precedence).  So find the binfo of the base function's
@@ -5422,7 +5420,7 @@  finish_struct_1 (tree t)
   for (x = TYPE_FIELDS (t); x; x = TREE_CHAIN (x))
     if (TREE_CODE (x) == VAR_DECL && TREE_STATIC (x)
         && TREE_TYPE (x) != error_mark_node
-	&& same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (x), t))
+	&& same_cv_unqualified_type_p (TREE_TYPE (x), t))
       DECL_MODE (x) = TYPE_MODE (t);
 
   /* Done with FIELDS...now decide whether to sort these for
@@ -5759,7 +5757,7 @@  resolves_to_fixed_type_p (tree instance, int* nonnull)
     return 0;
   if (POINTER_TYPE_P (t))
     t = TREE_TYPE (t);
-  if (!same_type_ignoring_top_level_qualifiers_p (t, fixed))
+  if (!same_cv_unqualified_type_p (t, fixed))
     return 0;
   return cdtorp ? -1 : 1;
 }
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 0a78074..1f2aea5 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1180,8 +1180,7 @@  cxx_omp_predetermined_sharing (tree decl)
 	  if (outer)
 	    for (var = BLOCK_VARS (outer); var; var = TREE_CHAIN (var))
 	      if (DECL_NAME (decl) == DECL_NAME (var)
-		  && (same_type_ignoring_top_level_qualifiers_p
-		      (type, TREE_TYPE (var))))
+		  && same_cv_unqualified_type_p (type, TREE_TYPE (var)))
 		{
 		  if (TYPE_READONLY (TREE_TYPE (var)))
 		    type = TREE_TYPE (var);
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index 460f32f..7e8405d 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -146,7 +146,7 @@  cxx_initialize_diagnostics (diagnostic_context *context)
 int
 cxx_types_compatible_p (tree x, tree y)
 {
-  return same_type_ignoring_top_level_qualifiers_p (x, y);
+  return same_cv_unqualified_type_p (x, y);
 }
 
 /* Return true if DECL is explicit member function.  */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 4f6ea24..8eac0b0 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -292,7 +292,7 @@  typedef struct ptrmem_cst * ptrmem_cst_t;
 
 /* Returns nonzero iff TYPE1 and TYPE2 are the same type, ignoring
    top-level qualifiers.  */
-#define same_type_ignoring_top_level_qualifiers_p(TYPE1, TYPE2) \
+#define same_cv_unqualified_type_p(TYPE1,TYPE2) \
   same_type_p (cv_unqualified (TYPE1), cv_unqualified (TYPE2))
 /* Nonzero if we are presently building a statement tree, rather
    than expanding each statement as we encounter it.  */
@@ -3782,7 +3782,7 @@  more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
 /* True if EXPR expresses direct-initialization of a TYPE.  */
 #define DIRECT_INIT_EXPR_P(TYPE,EXPR)					\
   (TREE_CODE (EXPR) == TARGET_EXPR && TREE_LANG_FLAG_2 (EXPR)		\
-   && same_type_ignoring_top_level_qualifiers_p (TYPE, TREE_TYPE (EXPR)))
+   && same_cv_unqualified_type_p (TYPE, TREE_TYPE (EXPR)))
 
 /* An enumeration of the kind of tags that C++ accepts.  */
 enum tag_types {
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 7f6fa8c..1baf26a 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -123,7 +123,7 @@  cp_convert_to_pointer (tree type, tree expr)
 
   if (POINTER_TYPE_P (intype))
     {
-      if (!same_type_ignoring_top_level_qualifiers_p (type, intype)
+      if (!same_cv_unqualified_type_p (type, intype)
 	  && TREE_CODE (type) == POINTER_TYPE
 	  && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
 	  && MAYBE_CLASS_TYPE_P (TREE_TYPE (type))
@@ -139,8 +139,7 @@  cp_convert_to_pointer (tree type, tree expr)
 	  intype_class = TREE_TYPE (intype);
 	  type_class = TREE_TYPE (type);
 
-	  same_p = (same_type_ignoring_top_level_qualifiers_p
-		    (intype_class, type_class));
+	  same_p = same_cv_unqualified_type_p (intype_class, type_class);
 
 	  binfo = NULL_TREE;
 	  /* Try derived to base conversion.  */
@@ -252,7 +251,7 @@  convert_to_pointer_force (tree type, tree expr)
 
   if (form == POINTER_TYPE)
     {
-      if (!same_type_ignoring_top_level_qualifiers_p (type, intype)
+      if (!same_cv_unqualified_type_p (type, intype)
 	  && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
 	  && MAYBE_CLASS_TYPE_P (TREE_TYPE (type))
 	  && MAYBE_CLASS_TYPE_P (TREE_TYPE (intype))
@@ -329,7 +328,7 @@  build_up_reference (tree type, tree arg, int flags, tree decl)
     return error_mark_node;
 
   if ((flags & LOOKUP_PROTECT)
-      && !same_type_ignoring_top_level_qualifiers_p (argtype, target_type)
+      && !same_cv_unqualified_type_p (argtype, target_type)
       && MAYBE_CLASS_TYPE_P (argtype)
       && MAYBE_CLASS_TYPE_P (target_type))
     {
@@ -612,7 +611,7 @@  ocp_convert (tree type, tree expr, int convtype, int flags)
 
   if (MAYBE_CLASS_TYPE_P (type) && (convtype & CONV_FORCE_TEMP))
     /* We need a new temporary; don't take this shortcut.  */;
-  else if (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (e)))
+  else if (same_cv_unqualified_type_p (type, TREE_TYPE (e)))
     {
       if (same_type_p (type, TREE_TYPE (e)))
 	/* The call to fold will not always remove the NOP_EXPR as
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 29e07ee..3b8e9e9 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5014,7 +5014,7 @@  reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p)
 	 looking through the outermost braces; A a2 = { a1 }; is not a
 	 valid aggregate initialization.  */
       && !first_initializer_p
-      && (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (init))
+      && (same_cv_unqualified_type_p (type, TREE_TYPE (init))
 	  || can_convert_arg (type, TREE_TYPE (init), init, LOOKUP_NORMAL)))
     {
       d->cur++;
@@ -5833,8 +5833,8 @@  cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
 		  || jclass == NULL_TREE
 		  || TREE_CODE (jclass) != TYPE_DECL
 		  || !POINTER_TYPE_P (TREE_TYPE (jclass))
-		  || !same_type_ignoring_top_level_qualifiers_p
-					(type, TREE_TYPE (TREE_TYPE (jclass))))
+		  || !(same_cv_unqualified_type_p
+		       (type, TREE_TYPE (TREE_TYPE (jclass)))))
 		error ("Java object %qD not allocated with %<new%>", decl);
 	      init = NULL_TREE;
 	    }
@@ -8076,7 +8076,7 @@  grokdeclarator (const cp_declarator *declarator,
 
   /* Long double is a special combination.  */
   if (long_p && !longlong
-      && same_type_ignoring_top_level_qualifiers_p (type, double_type_node))
+      && same_cv_unqualified_type_p (type, double_type_node))
     {
       long_p = false;
       type = cp_build_qualified_type (long_double_type_node,
@@ -10099,15 +10099,15 @@  copy_fn_p (const_tree d)
   if (arg_type == error_mark_node)
     return 0;
 
-  if (same_type_ignoring_top_level_qualifiers_p (arg_type, DECL_CONTEXT (d)))
+  if (same_cv_unqualified_type_p (arg_type, DECL_CONTEXT (d)))
     {
       /* Pass by value copy assignment operator.  */
       result = -1;
     }
   else if (TREE_CODE (arg_type) == REFERENCE_TYPE
 	   && !TYPE_REF_IS_RVALUE (arg_type)
-	   && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (arg_type),
-							 DECL_CONTEXT (d)))
+	   && same_cv_unqualified_type_p (TREE_TYPE (arg_type),
+					  DECL_CONTEXT (d)))
     {
       if (CP_TYPE_CONST_P (TREE_TYPE (arg_type)))
 	result = 2;
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 124a83c..44bdcaf 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -834,7 +834,7 @@  locate_copy (tree type, void *client_)
       if (src_type == error_mark_node)
         return NULL_TREE;
 
-      if (!same_type_ignoring_top_level_qualifiers_p (src_type, type))
+      if (!same_cv_unqualified_type_p (src_type, type))
 	continue;
       if (!sufficient_parms_p (TREE_CHAIN (parms)))
 	continue;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 4c149a8..7ce43c1 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1070,7 +1070,7 @@  is_specialization_of (tree decl, tree tmpl)
 	   t != NULL_TREE;
 	   t = CLASSTYPE_USE_TEMPLATE (t)
 	     ? TREE_TYPE (CLASSTYPE_TI_TEMPLATE (t)) : NULL_TREE)
-	if (same_type_ignoring_top_level_qualifiers_p (t, TREE_TYPE (tmpl)))
+	if (same_cv_unqualified_type_p (t, TREE_TYPE (tmpl)))
 	  return 1;
     }
 
@@ -4952,7 +4952,7 @@  convert_nontype_argument (tree type, tree expr)
 	  gcc_assert (TREE_CODE (expr_type) == REFERENCE_TYPE);
 	  gcc_assert (TREE_CODE (addr) == ADDR_EXPR);
 	  gcc_assert (TREE_CODE (TREE_TYPE (addr)) == POINTER_TYPE);
-	  gcc_assert (same_type_ignoring_top_level_qualifiers_p
+	  gcc_assert (same_cv_unqualified_type_p
 		      (TREE_TYPE (expr_type),
 		       TREE_TYPE (TREE_TYPE (addr))));
 
@@ -5085,8 +5085,7 @@  convert_nontype_argument (tree type, tree expr)
      template-argument, which must be an lvalue.  */
   else if (TYPE_REF_OBJ_P (type))
     {
-      if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type),
-						      expr_type))
+      if (!same_cv_unqualified_type_p (TREE_TYPE (type), expr_type))
 	return error_mark_node;
 
       if (!at_least_as_qualified_p (TREE_TYPE (type), expr_type))
@@ -14903,7 +14902,7 @@  unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 
       /* We have already checked cv-qualification at the top of the
 	 function.  */
-      if (!same_type_ignoring_top_level_qualifiers_p (arg, parm))
+      if (!same_cv_unqualified_type_p (arg, parm))
 	return 1;
 
       /* As far as unification is concerned, this wins.	 Later checks
@@ -14991,7 +14990,7 @@  unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	  return unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
 			CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE);
 	}
-      else if (!same_type_ignoring_top_level_qualifiers_p (parm, arg))
+      else if (!same_cv_unqualified_type_p (parm, arg))
 	return 1;
       return 0;
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index bb5ea66..855bbad 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2131,8 +2131,7 @@  finish_pseudo_destructor_expr (tree object, tree scope, tree destructor)
 
 	 We implement the more generous second sentence, since that is
 	 what most other compilers do.  */
-      if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (object),
-						      destructor))
+      if (!same_cv_unqualified_type_p (TREE_TYPE (object), destructor))
 	{
 	  error ("%qE is not of type %qT", object, destructor);
 	  return error_mark_node;
@@ -5234,7 +5233,7 @@  finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
 
     case CPTK_IS_BASE_OF:
       if (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
-	  && !same_type_ignoring_top_level_qualifiers_p (type1, type2)
+	  && !same_cv_unqualified_type_p (type1, type2)
 	  && !COMPLETE_TYPE_P (type2))
 	{
 	  error ("incomplete type %qT not allowed", type2);
@@ -5810,8 +5809,8 @@  lambda_expr_this_capture (tree lambda)
   else
     {
       /* Make sure that current_class_ref is for the lambda.  */
-      gcc_assert (same_type_ignoring_top_level_qualifiers_p
-		  (TREE_TYPE (current_class_ref), TREE_TYPE (lambda)));
+      gcc_assert (same_cv_unqualified_type_p (TREE_TYPE (current_class_ref),
+					      TREE_TYPE (lambda)));
 
       result = finish_non_static_data_member (this_capture,
                                               NULL_TREE,
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 5896843..28f0224 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -462,7 +462,7 @@  composite_pointer_type_r (tree t1, tree t2,
      with a cv-qualification signature (_conv.qual_) that is the
      union of the cv-qualification signatures of the operand
      types.  */
-  if (same_type_ignoring_top_level_qualifiers_p (pointee1, pointee2))
+  if (same_cv_unqualified_type_p (pointee1, pointee2))
     result_type = pointee1;
   else if ((TREE_CODE (pointee1) == POINTER_TYPE
 	    && TREE_CODE (pointee2) == POINTER_TYPE)
@@ -634,8 +634,7 @@  composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2,
   if (TREE_CODE (t1) == POINTER_TYPE && TREE_CODE (t2) == POINTER_TYPE
       && CLASS_TYPE_P (TREE_TYPE (t1))
       && CLASS_TYPE_P (TREE_TYPE (t2))
-      && !same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (t1),
-						     TREE_TYPE (t2)))
+      && !same_cv_unqualified_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
     {
       class1 = TREE_TYPE (t1);
       class2 = TREE_TYPE (t2);
@@ -1820,16 +1819,15 @@  is_bitfield_expr_with_lowered_type (const_tree exp)
 	field = TREE_OPERAND (exp, 1);
 	if (TREE_CODE (field) != FIELD_DECL || !DECL_BIT_FIELD_TYPE (field))
 	  return NULL_TREE;
-	if (same_type_ignoring_top_level_qualifiers_p
-	    (TREE_TYPE (exp), DECL_BIT_FIELD_TYPE (field)))
+	if (same_cv_unqualified_type_p (TREE_TYPE (exp),
+					DECL_BIT_FIELD_TYPE (field)))
 	  return NULL_TREE;
 	return DECL_BIT_FIELD_TYPE (field);
       }
 
     CASE_CONVERT:
-      if (same_type_ignoring_top_level_qualifiers_p
-	  (TREE_TYPE (TREE_OPERAND (exp, 0)),
-	   TREE_TYPE (exp)))
+      if (same_cv_unqualified_type_p (TREE_TYPE (TREE_OPERAND (exp, 0)),
+				      TREE_TYPE (exp)))
 	return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0));
       /* Fallthrough.  */
 
@@ -2202,8 +2200,7 @@  build_class_member_access_expr (tree object, tree member,
      presently be the anonymous union.  Go outwards until we find a
      type related to OBJECT_TYPE.  */
   while (ANON_AGGR_TYPE_P (member_scope)
-	 && !same_type_ignoring_top_level_qualifiers_p (member_scope,
-							object_type))
+	 && !same_cv_unqualified_type_p (member_scope, object_type))
     member_scope = TYPE_CONTEXT (member_scope);
   if (!member_scope || !DERIVED_FROM_P (member_scope, object_type))
     {
@@ -2247,8 +2244,7 @@  build_class_member_access_expr (tree object, tree member,
 		       && integer_zerop (TREE_OPERAND (object, 0)));
 
       /* Convert OBJECT to the type of MEMBER.  */
-      if (!same_type_ignoring_top_level_qualifiers_p (object_type,
-						      member_scope))
+      if (!same_cv_unqualified_type_p (object_type, member_scope))
 	{
 	  tree binfo;
 	  base_kind kind;
@@ -2313,8 +2309,8 @@  build_class_member_access_expr (tree object, tree member,
 	     constructed, and was then disassembled before calling
 	     build_field_call.  After the function-call code is
 	     cleaned up, this waste can be eliminated.  */
-	  && (!same_type_ignoring_top_level_qualifiers_p
-	      (TREE_TYPE (object), DECL_CONTEXT (member))))
+	  && !same_cv_unqualified_type_p (TREE_TYPE (object),
+					  DECL_CONTEXT (member)))
 	{
 	  tree anonymous_union;
 
@@ -3132,8 +3128,8 @@  get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
 	 lookup_base will fail in that case, because incomplete
 	 classes do not have BINFOs.  */
       basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
-      if (!same_type_ignoring_top_level_qualifiers_p
-	  (basetype, TREE_TYPE (TREE_TYPE (instance_ptr))))
+      if (!same_cv_unqualified_type_p (basetype,
+				       TREE_TYPE (TREE_TYPE (instance_ptr))))
 	{
 	  basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)),
 				  basetype, ba_check, NULL);
@@ -3783,8 +3779,7 @@  cp_build_binary_op (location_t location,
       /* Subtraction of two similar pointers.
 	 We must subtract them as integers, then divide by object size.  */
       if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
-	  && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0),
-							TREE_TYPE (type1)))
+	  && same_cv_unqualified_type_p (TREE_TYPE (type0), TREE_TYPE (type1)))
 	return pointer_diff (op0, op1, common_pointer_type (type0, type1));
       /* In all other cases except pointer - int, the usual arithmetic
 	 rules apply.  */
@@ -3920,8 +3915,7 @@  cp_build_binary_op (location_t location,
 	    }
 	  /* Convert the shift-count to an integer, regardless of
 	     size of value being shifted.  */
-	  if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (op1),
-							  integer_type_node))
+	  if (!same_cv_unqualified_type_p (TREE_TYPE (op1), integer_type_node))
 	    op1 = cp_convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;
@@ -3949,8 +3943,7 @@  cp_build_binary_op (location_t location,
 	    }
 	  /* Convert the shift-count to an integer, regardless of
 	     size of value being shifted.  */
-	  if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (op1),
-							  integer_type_node))
+	  if (!same_cv_unqualified_type_p (TREE_TYPE (op1), integer_type_node))
 	    op1 = cp_convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;
@@ -3981,8 +3974,7 @@  cp_build_binary_op (location_t location,
 	    }
 	  /* Convert the shift-count to an integer, regardless of
 	     size of value being shifted.  */
-	  if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (op1),
-							  integer_type_node))
+	  if (!same_cv_unqualified_type_p (TREE_TYPE (op1), integer_type_node))
 	    op1 = cp_convert (integer_type_node, op1);
 	}
       break;
@@ -5209,8 +5201,8 @@  cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
 	{
 	  tree object = TREE_OPERAND (arg, 0);
 	  tree field = TREE_OPERAND (arg, 1);
-	  gcc_assert (same_type_ignoring_top_level_qualifiers_p
-		      (TREE_TYPE (object), decl_type_context (field)));
+	  gcc_assert (same_cv_unqualified_type_p (TREE_TYPE (object),
+						  decl_type_context (field)));
 	  val = build_address (arg);
 	}
 
@@ -6858,7 +6850,7 @@  get_delta_difference (tree from, tree to,
 {
   tree result;
 
-  if (same_type_ignoring_top_level_qualifiers_p (from, to))
+  if (same_cv_unqualified_type_p (from, to))
     /* Pointer to member of incomplete class is permitted*/
     result = size_zero_node;
   else
@@ -6994,8 +6986,8 @@  build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p)
 	}
 
       /* Just adjust the DELTA field.  */
-      gcc_assert  (same_type_ignoring_top_level_qualifiers_p
-		   (TREE_TYPE (delta), ptrdiff_type_node));
+      gcc_assert (same_cv_unqualified_type_p (TREE_TYPE (delta),
+					      ptrdiff_type_node));
       if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta)
 	n = cp_build_binary_op (input_location,
 				LSHIFT_EXPR, n, integer_one_node,
@@ -7583,8 +7575,8 @@  check_return_expr (tree retval, bool *no_warning)
       /* The function return type must be a reference to the current
 	class.  */
       if (TREE_CODE (valtype) == REFERENCE_TYPE
-	  && same_type_ignoring_top_level_qualifiers_p
-	      (TREE_TYPE (valtype), TREE_TYPE (current_class_ref)))
+	  && same_cv_unqualified_type_p (TREE_TYPE (valtype),
+					 TREE_TYPE (current_class_ref)))
 	{
 	  /* Returning '*this' is obviously OK.  */
 	  if (retval == current_class_ref)
@@ -7760,7 +7752,7 @@  comp_ptr_ttypes_real (tree to, tree from, int constp)
       if (TREE_CODE (to) != POINTER_TYPE && !TYPE_PTRMEM_P (to))
 	return ((constp >= 0 || to_more_cv_qualified)
 		&& (is_opaque_pointer
-		    || same_type_ignoring_top_level_qualifiers_p (to, from)));
+		    || same_cv_unqualified_type_p (to, from)));
     }
 }
 
@@ -7877,7 +7869,7 @@  comp_ptr_ttypes_const (tree to, tree from)
 
       if (TREE_CODE (to) != POINTER_TYPE)
 	return (is_opaque_pointer
-		|| same_type_ignoring_top_level_qualifiers_p (to, from));
+		|| same_cv_unqualified_type_p (to, from));
     }
 }
 
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index d98de9b..7537059 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -952,8 +952,7 @@  digest_init_r (tree type, tree init, bool nested, int flags)
 	     build_value_init_noctor.  */
 	  if ((TREE_CODE (init) == TARGET_EXPR
 	       || TREE_CODE (init) == CONSTRUCTOR)
-	      && (same_type_ignoring_top_level_qualifiers_p
-		  (type, TREE_TYPE (init))))
+	      && same_cv_unqualified_type_p (type, TREE_TYPE (init)))
 	    return init;
 
 	  error ("array must be initialized with a brace-enclosed"
@@ -1052,8 +1051,8 @@  process_init_constructor_array (tree type, tree init)
       ce->value = digest_init_r (TREE_TYPE (type), ce->value, true, LOOKUP_IMPLICIT);
 
       if (ce->value != error_mark_node)
-	gcc_assert (same_type_ignoring_top_level_qualifiers_p
-		      (TREE_TYPE (type), TREE_TYPE (ce->value)));
+	gcc_assert (same_cv_unqualified_type_p (TREE_TYPE (type),
+						TREE_TYPE (ce->value)));
 
       flags |= picflag_from_initializer (ce->value);
     }

commit ca9e07ff0aad68ada0e4af1094624222e078f750
Author: Jason Merrill <jason@redhat.com>
Date:   Fri May 28 16:20:47 2010 -0400

    type_linkage_name

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8eac0b0..548e1a2 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1098,19 +1098,18 @@  enum languages { lang_c, lang_cplusplus, lang_java };
 
 /* Macros to make error reporting functions' lives easier.  */
 #define TYPE_IDENTIFIER(NODE) (DECL_NAME (TYPE_NAME (NODE)))
-#define TYPE_LINKAGE_IDENTIFIER(NODE) \
-  (TYPE_IDENTIFIER (TYPE_MAIN_VARIANT (NODE)))
 #define TYPE_NAME_STRING(NODE) (IDENTIFIER_POINTER (TYPE_IDENTIFIER (NODE)))
 #define TYPE_NAME_LENGTH(NODE) (IDENTIFIER_LENGTH (TYPE_IDENTIFIER (NODE)))
 
+#define TYPE_LINKAGE_NAME(NODE) (TYPE_NAME (TYPE_MAIN_VARIANT (NODE)))
+#define TYPE_LINKAGE_IDENTIFIER(NODE) (DECL_NAME (TYPE_LINKAGE_NAME (NODE)))
+
 /* Nonzero if NODE has no name for linkage purposes.  */
 #define TYPE_ANONYMOUS_P(NODE) \
   (TAGGED_TYPE_P (NODE) && ANON_AGGRNAME_P (TYPE_LINKAGE_IDENTIFIER (NODE)))
 
 /* The _DECL for this _TYPE.  */
 #define TYPE_MAIN_DECL(NODE) (TYPE_STUB_DECL (TYPE_MAIN_VARIANT (NODE)))
-#define TYPE_MAIN_NAME(NODE) (TYPE_NAME (TYPE_MAIN_VARIANT (NODE)))
-#define TYPE_MAIN_IDENTIFIER(NODE) (TYPE_IDENTIFIER (TYPE_MAIN_VARIANT (NODE)))
 
 /* Nonzero if T is a class (or struct or union) type.  Also nonzero
    for template type parameters, typename types, and instantiated
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 3b8e9e9..c6a9d6a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4185,7 +4185,7 @@  start_decl (const cp_declarator *declarator,
      (7.1.3p8), apply any attributes directly to the type.  */
   if (TREE_CODE (decl) == TYPE_DECL
       && TAGGED_TYPE_P (TREE_TYPE (decl))
-      && decl == TYPE_MAIN_NAME (TREE_TYPE (decl)))
+      && decl == TYPE_LINKAGE_NAME (TREE_TYPE (decl)))
     flags = ATTR_FLAG_TYPE_IN_PLACE;
   else
     flags = 0;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 93c1c51..c06a0b0 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -869,7 +869,7 @@  grokfield (const cp_declarator *declarator,
 	  /* If this is a typedef that names the class for linkage purposes
 	     (7.1.3p8), apply any attributes directly to the type.  */
 	  if (TAGGED_TYPE_P (TREE_TYPE (value))
-	      && value == TYPE_MAIN_NAME (TREE_TYPE (value)))
+	      && value == TYPE_LINKAGE_NAME (TREE_TYPE (value)))
 	    attrflags = ATTR_FLAG_TYPE_IN_PLACE;
 
 	  cplus_decl_attributes (&value, attrlist, attrflags);
@@ -877,7 +877,7 @@  grokfield (const cp_declarator *declarator,
 
       if (declspecs->specs[(int)ds_typedef]
           && TREE_TYPE (value) != error_mark_node
-          && TYPE_MAIN_NAME (TREE_TYPE (value)) != value)
+          && TYPE_LINKAGE_NAME (TREE_TYPE (value)) != value)
 	cp_set_underlying_type (value);
 
       return value;
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 7a2ac01..d435f65 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -380,7 +380,7 @@  is_std_substitution (const tree node,
   else if (CLASS_TYPE_P (node))
     {
       type = node;
-      decl = TYPE_MAIN_NAME (node);
+      decl = TYPE_LINKAGE_NAME (node);
     }
   else
     /* These are not the droids you're looking for.  */
@@ -468,7 +468,7 @@  find_substitution (tree node)
 
   /* Check for builtin substitutions.  */
 
-  decl = TYPE_P (node) ? TYPE_MAIN_NAME (node) : node;
+  decl = TYPE_P (node) ? TYPE_LINKAGE_NAME (node) : node;
   type = TYPE_P (node) ? node : TREE_TYPE (node);
 
   /* Check for std::allocator.  */
@@ -735,7 +735,7 @@  write_name (tree decl, const int ignore_local_scope)
     {
       /* In case this is a typedef, fish out the corresponding
 	 TYPE_DECL for the main variant.  */
-      decl = TYPE_MAIN_NAME (TREE_TYPE (decl));
+      decl = TYPE_LINKAGE_NAME (TREE_TYPE (decl));
     }
 
   context = decl_mangling_context (decl);
@@ -1819,7 +1819,7 @@  write_type (tree type)
 	    case UNBOUND_CLASS_TEMPLATE:
 	      /* We handle TYPENAME_TYPEs and UNBOUND_CLASS_TEMPLATEs like
 		 ordinary nested names.  */
-	      write_nested_name (TYPE_MAIN_NAME (type));
+	      write_nested_name (TYPE_LINKAGE_NAME (type));
 	      break;
 
 	    case POINTER_TYPE:
@@ -2283,7 +2283,7 @@  write_method_parms (tree parm_types, const int method_p, const tree decl)
 static void
 write_class_enum_type (const tree type)
 {
-  write_name (TYPE_MAIN_NAME (type), /*ignore_local_scope=*/0);
+  write_name (TYPE_LINKAGE_NAME (type), /*ignore_local_scope=*/0);
 }
 
 /* Non-terminal <template-args>.  ARGS is a TREE_VEC of template
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 0f4ed0c..96e0d4b 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -1801,7 +1801,7 @@  set_identifier_type_value (tree id, tree decl)
 static inline tree
 constructor_name_full (tree type)
 {
-  return TYPE_MAIN_IDENTIFIER (type);
+  return DECL_NAME (TYPE_MAIN_DECL (type));
 }
 
 /* Return the name for the constructor (or destructor) for the
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 7ce43c1..cb66fd1 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -18075,7 +18075,7 @@  resolve_typename_type (tree type, bool only_current_p)
      So by getting the TYPE_IDENTIFIER of the _main declaration_ of the
      TYPENAME_TYPE instead, we avoid messing up with a possible
      typedef variant case.  */
-  name = TYPE_MAIN_IDENTIFIER (type);
+  name = TYPE_LINKAGE_IDENTIFIER (type);
 
   /* If the SCOPE is itself a TYPENAME_TYPE, then we need to resolve
      it first before we can figure out what NAME refers to.  */
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 1879db5..e609ef1 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -662,7 +662,6 @@  build_cplus_array_type (tree elt_type, tree index_type)
   else
     t = build_array_type (elt_type, index_type);
 
-  /* FIXME do we still need this?  */
   /* We want TYPE_MAIN_VARIANT of an array to strip cv-quals from the
      element type as well, so fix it up if needed.  */
   if (elt_type != TYPE_MAIN_VARIANT (elt_type))
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 28f0224..f8bdbfb 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -396,7 +396,7 @@  cp_common_type (tree t1, tree t2)
 	return build_type_attribute_variant (float_type_node,
 					     attributes);
 
-      /* Two floating-point types whose TYPE_MAIN_VARIANTs are none of
+      /* Two floating-point types that are not variants of
 	 the standard C++ floating-point types.  Logic earlier in this
 	 function has already eliminated the possibility that
 	 TYPE_PRECISION (t2) != TYPE_PRECISION (t1), so there's no

commit 6fa0787cc5cd7fdbbfa4e28a54f01aa6eed598b1
Author: Jason Merrill <jason@redhat.com>
Date:   Fri May 28 16:23:18 2010 -0400

    const

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 548e1a2..471ed03 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5409,7 +5409,7 @@  extern tree convert_for_initialization		(tree, tree, tree, int,
 extern int comp_ptr_ttypes			(tree, tree);
 extern bool comp_ptr_ttypes_const		(tree, tree);
 extern bool error_type_p			(const_tree);
-extern int ptr_reasonably_similar		(const_tree, const_tree);
+extern int ptr_reasonably_similar		(tree, tree);
 extern tree build_ptrmemfunc			(tree, tree, int, bool);
 extern int cp_type_quals			(const_tree);
 extern int type_memfn_quals			(const_tree);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index f8bdbfb..d7d1d43 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -7808,7 +7808,7 @@  error_type_p (const_tree type)
    type or inheritance-related types, regardless of cv-quals.  */
 
 int
-ptr_reasonably_similar (const_tree to, const_tree from)
+ptr_reasonably_similar (tree to, tree from)
 {
   for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
     {

commit dbd99759dfddb32e499afba32b942586b684fc1f
Author: Jason Merrill <jason@redhat.com>
Date:   Fri May 28 17:33:20 2010 -0400

    fix tests

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 1b028da..3aca132 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6326,7 +6326,7 @@  build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args,
   if (DECL_DESTRUCTOR_P (fn)
       || DECL_CONSTRUCTOR_P (fn))
     {
-      tree type = build_pointer_type (basetype);
+      tree type = build_pointer_type (cv_unqualified (basetype));
       if (!same_type_p (type, TREE_TYPE (instance_ptr)))
 	instance_ptr = build_nop (type, instance_ptr);
     }
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index c6a9d6a..872f825 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -8857,7 +8857,7 @@  grokdeclarator (const cp_declarator *declarator,
 	  t = DECL_CONTEXT (t);
 	}
 
-      if (ctype == current_class_type)
+      if (current_class_type && same_type_p (ctype, current_class_type))
 	{
 	  if (friendp)
 	    {
@@ -9478,7 +9478,7 @@  grokdeclarator (const cp_declarator *declarator,
 	if (friendp)
 	  {
 	    /* Friends are treated specially.  */
-	    if (ctype == current_class_type)
+	    if (ctype && same_type_p (ctype, current_class_type))
 	      ;  /* We already issued a permerror.  */
 	    else if (decl && DECL_NAME (decl))
 	      {
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index ffad18b..2f0929f 100644
--- a/gcc/cp/friend.c
+++ b/gcc/cp/friend.c
@@ -351,7 +351,8 @@  make_friend_class (tree type, tree friend_type, bool complain)
   if (friend_type == error_mark_node)
     return;
 
-  friend_type = TYPE_MAIN_VARIANT (friend_type);
+  if (TYPE_P (friend_type))
+    friend_type = TYPE_MAIN_VARIANT (friend_type);
 
   /* See if it is already a friend.  */
   for (classes = CLASSTYPE_FRIEND_CLASSES (type);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index d7d1d43..38ecb89 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -263,8 +263,8 @@  cp_common_type (tree t1, tree t2)
      attributes.  */
   attributes = (*targetm.merge_type_attributes) (t1, t2);
 
-  gcc_assert (t1 == cv_unqualified (t1)
-	      && t2 == cv_unqualified (t2));
+  t1 = cv_unqualified (t1);
+  t2 = cv_unqualified (t2);
 
   if (SCOPED_ENUM_P (t1) || SCOPED_ENUM_P (t2))
     {

commit b4bf0d44d3b7bf7ae046ac89b7516393f5b06b85
Author: Jason Merrill <jason@redhat.com>
Date:   Sat May 29 17:28:12 2010 -0400

    move comment

diff --git a/gcc/except.c b/gcc/except.c
index 393a801..feaf7af 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -1854,9 +1854,6 @@  set_nothrow_function_flags (void)
 
   crtl->all_throwers_are_sibcalls = 1;
 
-  /* If we don't know that this implementation of the function will
-     actually be used, then we must not set TREE_NOTHROW, since
-     callers must not assume that this function does not throw.  */
   if (TREE_NOTHROW (current_function_decl))
     return 0;
 
@@ -1887,6 +1884,9 @@  set_nothrow_function_flags (void)
 	    return 0;
 	  }
       }
+  /* If we don't know that this implementation of the function will
+     actually be used, then we must not set TREE_NOTHROW, since
+     callers must not assume that this function does not throw.  */
   if (crtl->nothrow
       && (cgraph_function_body_availability (cgraph_node
 					     (current_function_decl))

commit 42c9024793456b2413eecc1f26ba47e8715a738b
Author: Jason Merrill <jason@redhat.com>
Date:   Mon May 31 17:23:30 2010 -0400

    nothrow

diff --git a/gcc/c-common.c b/gcc/c-common.c
index 77026fa..219f195 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -7643,12 +7643,30 @@  get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
    struct attribute_spec.handler.  */
 
 static tree
-handle_nothrow_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+handle_nothrow_attribute (tree *node, tree name, tree args,
 			  int ARG_UNUSED (flags), bool *no_add_attrs)
 {
+  tree type = TREE_TYPE (*node);
+  bool ptr = false;
+
   if (TREE_CODE (*node) == FUNCTION_DECL)
     TREE_NOTHROW (*node) = 1;
-  /* ??? TODO: Support types.  */
+
+  if (TREE_CODE (type) == POINTER_TYPE)
+    {
+      ptr = true;
+      type = TREE_TYPE (type);
+    }
+
+  if (TREE_CODE (type) == FUNCTION_TYPE)
+    {
+      tree attrs = TYPE_ATTRIBUTES (type);
+      attrs = tree_cons (name, args, attrs);
+      type = build_type_attribute_variant (type, attrs);
+      if (ptr)
+	type = build_pointer_type (type);
+      TREE_TYPE (*node) = type;
+    }
   else
     {
       warning (OPT_Wattributes, "%qE attribute ignored", name);
@@ -8978,21 +8996,8 @@  bool
 check_missing_format_attribute (tree ltype, tree rtype)
 {
   tree const ttr = TREE_TYPE (rtype), ttl = TREE_TYPE (ltype);
-  tree ra;
-
-  for (ra = TYPE_ATTRIBUTES (ttr); ra; ra = TREE_CHAIN (ra))
-    if (is_attribute_p ("format", TREE_PURPOSE (ra)))
-      break;
-  if (ra)
-    {
-      tree la;
-      for (la = TYPE_ATTRIBUTES (ttl); la; la = TREE_CHAIN (la))
-	if (is_attribute_p ("format", TREE_PURPOSE (la)))
-	  break;
-      return !la;
-    }
-  else
-    return false;
+  return (lookup_attribute ("format", TYPE_ATTRIBUTES (ttr))
+	  && !lookup_attribute ("format", TYPE_ATTRIBUTES (ttl)));
 }
 
 /* Subscripting with type char is likely to lose on a machine where
diff --git a/gcc/calls.c b/gcc/calls.c
index 9c51f1a..9510810 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -611,13 +611,27 @@  flags_from_decl_or_type (const_tree exp)
       if (TREE_NOTHROW (exp))
 	flags |= ECF_NOTHROW;
 
+      if (TREE_THIS_VOLATILE (exp))
+	flags |= ECF_NORETURN;
+
       flags = special_function_p (exp, flags);
-    }
-  else if (TYPE_P (exp) && TYPE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp))
-    flags |= ECF_CONST;
 
-  if (TREE_THIS_VOLATILE (exp))
-    flags |= ECF_NORETURN;
+      flags |= flags_from_decl_or_type (TREE_TYPE (exp));
+    }
+  else
+    {
+      tree attrs = TYPE_ATTRIBUTES (exp);
+      bool const_p = (TYPE_READONLY (exp)
+		      || lookup_attribute ("const", attrs));
+      bool volatile_p = (TYPE_VOLATILE (exp)
+			 || lookup_attribute ("noreturn", attrs));
+      if (const_p && !volatile_p)
+	flags |= ECF_CONST;
+      if (volatile_p)
+	flags |= ECF_NORETURN;
+      if (lookup_attribute ("nothrow", attrs))
+	flags |= ECF_NOTHROW;
+    }
 
   return flags;
 }
@@ -641,6 +655,9 @@  call_expr_flags (const_tree t)
 	flags = 0;
     }
 
+  if (TREE_NOTHROW (t))
+    flags |= ECF_NOTHROW;
+
   return flags;
 }
 
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 3aca132..ccc241a 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -337,7 +337,8 @@  build_call_a (tree function, int n, tree *argarray)
   /* We check both the decl and the type; a function may be known not to
      throw without being declared throw().  */
   nothrow = ((decl && TREE_NOTHROW (decl))
-	     || TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (function))));
+	     || lookup_attribute ("nothrow", TYPE_ATTRIBUTES (fntype))
+	     || TYPE_NOTHROW_P (fntype));
 
   if (decl && TREE_THIS_VOLATILE (decl) && cfun && cp_function_chain)
     current_function_returns_abnormally = 1;
@@ -5909,13 +5910,13 @@  build_cxx_call (tree fn, int nargs, tree *argarray)
   fn = build_call_a (fn, nargs, argarray);
 
   /* If this call might throw an exception, note that fact.  */
-  fndecl = get_callee_fndecl (fn);
-  if ((!fndecl || !TREE_NOTHROW (fndecl))
+  if (!TREE_NOTHROW (fn)
       && at_function_scope_p ()
       && cfun)
     cp_function_chain->can_throw = 1;
 
   /* Check that arguments to builtin functions match the expectations.  */
+  fndecl = get_callee_fndecl (fn);
   if (fndecl
       && DECL_BUILT_IN (fndecl)
       && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
diff --git a/gcc/tree.c b/gcc/tree.c
index 743293e..e810e53 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -2654,6 +2654,7 @@  process_call_operands (tree t)
 {
   bool side_effects = TREE_SIDE_EFFECTS (t);
   bool read_only = false;
+  bool nothrow = false;
   int i = call_expr_flags (t);
 
   /* Calls have side-effects, except those to const or pure functions.  */
@@ -2662,6 +2663,8 @@  process_call_operands (tree t)
   /* Propagate TREE_READONLY of arguments for const functions.  */
   if (i & ECF_CONST)
     read_only = true;
+  if (i & ECF_NOTHROW)
+    nothrow = true;
 
   if (!side_effects || read_only)
     for (i = 1; i < TREE_OPERAND_LENGTH (t); i++)
@@ -2675,6 +2678,7 @@  process_call_operands (tree t)
 
   TREE_SIDE_EFFECTS (t) = side_effects;
   TREE_READONLY (t) = read_only;
+  TREE_NOTHROW (t) = nothrow;
 }
 
 /* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size

commit 70399b338f583de79bba15e1c0015e3b87aca9a6
Author: Jason Merrill <jason@redhat.com>
Date:   Mon May 31 17:30:15 2010 -0400

    const, noreturn

diff --git a/gcc/c-common.c b/gcc/c-common.c
index 219f195..a7d3bb9 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -5955,20 +5955,30 @@  handle_common_attribute (tree *node, tree name, tree ARG_UNUSED (args),
    struct attribute_spec.handler.  */
 
 static tree
-handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+handle_noreturn_attribute (tree *node, tree name, tree args,
 			   int ARG_UNUSED (flags), bool *no_add_attrs)
 {
   tree type = TREE_TYPE (*node);
+  bool ptr = false;
 
-  /* See FIXME comment in c_common_attribute_table.  */
   if (TREE_CODE (*node) == FUNCTION_DECL)
     TREE_THIS_VOLATILE (*node) = 1;
-  else if (TREE_CODE (type) == POINTER_TYPE
-	   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
-    TREE_TYPE (*node)
-      = build_pointer_type
-	(build_type_variant (TREE_TYPE (type),
-			     TYPE_READONLY (TREE_TYPE (type)), 1));
+
+  if (TREE_CODE (type) == POINTER_TYPE)
+    {
+      ptr = true;
+      type = TREE_TYPE (type);
+    }
+
+  if (TREE_CODE (type) == FUNCTION_TYPE)
+    {
+      tree attrs = TYPE_ATTRIBUTES (type);
+      attrs = tree_cons (get_identifier ("noreturn"), args, attrs);
+      type = build_type_attribute_variant (type, attrs);
+      if (ptr)
+	type = build_pointer_type (type);
+      TREE_TYPE (*node) = type;
+    }
   else
     {
       warning (OPT_Wattributes, "%qE attribute ignored", name);
@@ -6277,20 +6287,29 @@  handle_externally_visible_attribute (tree *pnode, tree name,
    struct attribute_spec.handler.  */
 
 static tree
-handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+handle_const_attribute (tree *node, tree name, tree args,
 			int ARG_UNUSED (flags), bool *no_add_attrs)
 {
   tree type = TREE_TYPE (*node);
+  bool ptr = false;
 
-  /* See FIXME comment on noreturn in c_common_attribute_table.  */
   if (TREE_CODE (*node) == FUNCTION_DECL)
     TREE_READONLY (*node) = 1;
-  else if (TREE_CODE (type) == POINTER_TYPE
-	   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
-    TREE_TYPE (*node)
-      = build_pointer_type
-	(build_type_variant (TREE_TYPE (type), 1,
-			     TREE_THIS_VOLATILE (TREE_TYPE (type))));
+
+  if (TREE_CODE (type) == POINTER_TYPE)
+    {
+      ptr = true;
+      type = TREE_TYPE (type);
+    }
+  if (TREE_CODE (type) == FUNCTION_TYPE)
+    {
+      tree attrs = TYPE_ATTRIBUTES (type);
+      attrs = tree_cons (name, args, attrs);
+      type = build_type_attribute_variant (type, attrs);
+      if (ptr)
+	type = build_pointer_type (type);
+      TREE_TYPE (*node) = type;
+    }
   else
     {
       warning (OPT_Wattributes, "%qE attribute ignored", name);

commit daf769fbb986f16ce5be66ad254331d50c5d7c90
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Jun 1 11:10:05 2010 -0400

    decl_noreturn accessor macros

diff --git a/gcc/tree.h b/gcc/tree.h
index 5acadb4..725fb56 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1244,7 +1244,8 @@  extern void omp_clause_range_check_failed (const_tree, const char *, int,
    because eventually we may make that a different bit.
 
    If this bit is set in an expression, so is TREE_SIDE_EFFECTS.  */
-#define TREE_THIS_VOLATILE(NODE) ((NODE)->base.volatile_flag)
+#define TREE_THIS_VOLATILE(NODE) (NON_TYPE_CHECK (NODE)->base.volatile_flag)
+#define DECL_NORETURN(NODE) (TREE_THIS_VOLATILE (FUNCTION_DECL_CHECK (NODE)))
 
 /* Nonzero means this node will not trap.  In an INDIRECT_REF, means
    accessing the memory pointed to won't generate a trap.  However,
@@ -1263,6 +1264,7 @@  extern void omp_clause_range_check_failed (const_tree, const char *, int,
    Nonzero in a FUNCTION_DECL means this function should be treated
    as "const" function (can only read its arguments).  */
 #define TREE_READONLY(NODE) (NON_TYPE_CHECK (NODE)->base.readonly_flag)
+#define DECL_CONST_FUNCTION(NODE) (TREE_READONLY (FUNCTION_DECL_CHECK (NODE)))
 
 /* Value of expression is constant.  Always on in all ..._CST nodes.  May
    also appear in an expression or decl where the value is constant.  */

commit 30edb13210d23b79f29cbef4ae3ecc0b5e242b34
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Jun 1 11:24:39 2010 -0400

    strip_typedefs

diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index e609ef1..7a7d106 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1043,8 +1043,7 @@  strip_typedefs (tree t)
 
   if (!result)
     return strip_top_typedef (t);
-  if (TYPE_ATTRIBUTES (t))
-    result = cp_build_type_attribute_variant (result, TYPE_ATTRIBUTES (t));
+  result = cp_build_type_attribute_variant (result, TYPE_ATTRIBUTES (t));
   return cp_build_qualified_type (result, cp_type_quals (t));
 }