llvm-gcc-4.2-2.9/gcc/cp/parser.c
/* If too many, or too few, template-parameter lists apply to the
   declarator, issue an error message.  Returns TRUE if all went well,
   and FALSE otherwise.  */
If too many, or too few, template-parameter lists apply to the
declarator, issue an error message.  Returns TRUE if all went well,
and FALSE otherwise.
If too many or too few template - parameter lists apply to the declarator issue an error message . Returns TRUE if all went well and FALSE otherwise .
static bool
cp_parser_check_declarator_template_parameters (cp_parser* parser,
						cp_declarator *declarator)
{
  unsigned num_templates;
  num_templates = 0;
  switch (declarator->kind)
    {
    case cdk_id:
      if (declarator->u.id.qualifying_scope)
	{
	  tree scope;
	  tree member;
	  scope = declarator->u.id.qualifying_scope;
	  member = declarator->u.id.unqualified_name;
	  while (scope && CLASS_TYPE_P (scope))
	    {
	      if (!CLASSTYPE_TEMPLATE_INFO (scope))
		break;
	      if (explicit_class_specialization_p (scope))
		break;
	      if (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope)))
		++num_templates;
	      scope = TYPE_CONTEXT (scope);
	    }
	}
      else if (TREE_CODE (declarator->u.id.unqualified_name)
	       == TEMPLATE_ID_EXPR)
	++num_templates;
      return cp_parser_check_template_parameters (parser,
						  num_templates);
    case cdk_function:
    case cdk_array:
    case cdk_pointer:
    case cdk_reference:
    case cdk_ptrmem:
    case cdk_block_pointer:
      return (cp_parser_check_declarator_template_parameters
	      (parser, declarator->declarator));
    case cdk_error:
      return true;
    default:
      gcc_unreachable ();
    }
  return false;
}
static bool cp_parser_check_declarator_template_parameters ( cp_parser * parser , cp_declarator * declarator ) { unsigned num_templates ; num_templates = 0 ; switch ( declarator -> kind ) { case cdk_id : if ( declarator -> u . id . qualifying_scope ) { tree scope ; tree member ; scope = declarator -> u . id . qualifying_scope ; member = declarator -> u . id . unqualified_name ; while ( scope && CLASS_TYPE_P ( scope ) ) { if ( ! CLASSTYPE_TEMPLATE_INFO ( scope ) ) break ; if ( explicit_class_specialization_p ( scope ) ) break ; if ( PRIMARY_TEMPLATE_P ( CLASSTYPE_TI_TEMPLATE ( scope ) ) ) ++ num_templates ; scope = TYPE_CONTEXT ( scope ) ; } } else if ( TREE_CODE ( declarator -> u . id . unqualified_name ) == TEMPLATE_ID_EXPR ) ++ num_templates ; return cp_parser_check_template_parameters ( parser , num_templates ) ; case cdk_function : case cdk_array : case cdk_pointer : case cdk_reference : case cdk_ptrmem : case cdk_block_pointer : return ( cp_parser_check_declarator_template_parameters ( parser , declarator -> declarator ) ) ; case cdk_error : return true ; default : gcc_unreachable ( ) ; } return false ; }
If too many, or too few, template-parameter lists apply to the
declarator, issue an error message.
If too many or too few template - parameter lists apply to the declarator issue an error message .
/* We haven't seen any classes that involve template parameters yet.  */ /* You're supposed to have one `template <...>'
		 for every template class, but you don't need one
		 for a full specialization.  For example:

		 template <class T> struct S{};
		 template <> struct S<int> { void f(); };
		 void S<int>::f () {}

		 is correct; there shouldn't be a `template <>' for
		 the definition of `S<int>::f'.  */ /* If SCOPE does not have template information of any
		   kind, then it is not a template, nor is it nested
		   within a template.  */ /* If the DECLARATOR has the form `X<y>' then it uses one
	   additional level of template parameters.  */ /* APPLE LOCAL blocks 6040305 */