Studying note of GCC-3.4.6 source (115)

5.12.4.1.1.2.  The default argument

Tokens following the template template parameter is ”= ::Loki::SingleThreaded”, it is the default value for the template template parameter. “::Loki::SingleThreaded” is the form of id-expression.

 

cp_parser_type_parameter (continue)

 

7804         /* If the next token is an `=', then there is a

7805            default-argument.  */

7806         if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))

7807         {

7808           bool is_template;

7809  

7810           /* Consume the `='.  */

7811           cp_lexer_consume_token (parser->lexer);

7812           /* Parse the id-expression.  */

7813           default_argument

7814                = cp_parser_id_expression (parser,

7815                                        /*template_keyword_p=*/ false,

7816                                       /*check_dependency_p=*/ true,

7817                                       /*template_p=*/ &is_template,

7818                                       /*declarator_p=*/ false);

7819           if (TREE_CODE (default_argument) == TYPE_DECL)

7820             /* If the id-expression was a template-id that refers to

7821               a template-class, we already have the declaration here,

7822               so no further lookup is needed.  */

7823             ;

7824           else

7825             /* Look up the name.  */

7826             default_argument

7827                 = cp_parser_lookup_name (parser, default_argument,

7828                                         /*is_type=*/ false,

7829                                        /*is_template=*/ is_template,

7830                                        /*is_namespace=*/ false,

7831                                        /*check_dependency=*/ true);

7832           /* See if the default argument is valid.  */

7833           default_argument

7834               = check_template_template_default_arg (default_argument);

7835         }

7836         else

7837           default_argument = NULL_TREE;

7838  

7839         /* Create the combined representation of the parameter and the

7840           default argument.  */

7841         parameter = build_tree_list (default_argument, parameter);

7842       }

7843       break ;

7844  

7845       default :

7846         abort ();

7847         break ;

7848     }

7849    

7850     return parameter;

7851   }

 

For convience, we present cp_parser_id_expression in below. The function will return the associated IDENTIFIER_NODE. For the example, the identifier is “SingleThreaded”.

 

2685   static tree

2686   cp_parser_id_expression (cp_parser *parser,                                               in parser.c

2687                        bool template_keyword_p,

2688                        bool check_dependency_p,

2689                        bool *template_p,

2690                        bool declarator_p)

2691   {

2692     bool global_scope_p;

2693     bool nested_name_specifier_p;

2694  

2695     /* Assume the `template' keyword was not used.  */

2696     if (template_p)

2697       *template_p = false;

2698  

2699     /* Look for the optional `::' operator.  */

2700     global_scope_p

2701       = (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/ false)

2702          != NULL_TREE);

2703     /* Look for the optional nested-name-specifier.  */

2704     nested_name_specifier_p

2705       = (cp_parser_nested_name_specifier_opt (parser,

2706                                         /*typename_keyword_p=*/ false,

2707                                         check_dependency_p,

2708                                         /*type_p=*/ false,

2709                                         declarator_p)

2710          != NULL_TREE);

2711     /* If there is a nested-name-specifier, then we are looking at

2712       the first qualified-id production.  */

2713     if (nested_name_specifier_p)

2714     {

2715       tree saved_scope;

2716       tree saved_object_scope;

2717       tree saved_qualifying_scope;

2718       tree unqualified_id;

2719       bool is_template;

2720  

2721       /* See if the next token is the `template' keyword.  */

2722       if (!template_p)

2723         template_p = &is_template;

2724       *template_p = cp_parser_optional_template_keyword (parser);

2725        /* Name lookup we do during the processing of the

2726          unqualified-id might obliterate SCOPE.  */

2727        saved_scope = parser->scope;

2728        saved_object_scope = parser->object_scope;

2729        saved_qualifying_scope = parser->qualifying_scope;

2730        /* Process the final unqualified-id.  */

2731        unqualified_id = cp_parser_unqualified_id (parser, *template_p,

2732                                             check_dependency_p,

2733                                            declarator_p);

2734        /* Restore the SAVED_SCOPE for our caller.  */

2735        parser->scope = saved_scope;

2736        parser->object_scope = saved_object_scope;

2737        parser->qualifying_scope = saved_qualifying_scope;

2738  

2739        return unqualified_id;

2740     }

2792   }

 

First, cp_parser_global_scope_opt if “::” present, will return global_namespace for the global namespace scope, and at the same time corresponding node of NAMESPACE_DECL is set in scope field of parser. Then tokens “Loki::” form the nested-name-specifier, at line 2705 cp_parser_nested_name_specifier_opt returns the scope of the class or namespace specified by the specifier. For the example, it is the scope of namespace “Loki”. Also scope field of the parser is updated by relevant NAMESPACE_DECL node. At line 2731 cp_parser_unqualified_id will return the IDENTIFIER_NODE node bound within the scope. However, IDNETIFIER_NODE is not what we expect. We needs TEMPLATE_DECL node here. So this name is looked up by cp_parser_lookup_name to return the expected node.

5.12.4.1.1.2.1.          Detail of name lookup

 

Routine cp_parser_lookup_name searches within the intermediate tree for the specified name. However, for dependent type, normal name-lookup can’t be applied, as it is unknown yet.

For the functon the last 4 parameters control the searching procedure:

If is_type is true, bindings that do not refer to types are ignored.

If it_template is true, bindings that do not refer to templates are ignored.

If is_namespace is true, bindings that do not refer to namespaces are ignored.

If check_dependency is true, names are not looked up in dependent types.

Besides may filting out unwanted result, the function needs check duplication too.

 

13692 static tree

13693 cp_parser_lookup_name (cp_parser *parser, tree name,                               in parser.c

13694                       bool is_type, bool is_template, bool is_namespace,

13695                       bool check_dependency)

13696 {

13697    int flags = 0;

13698    tree decl;

13699    tree object_type = parser->context->object_type;

13700

13701    /* Now that we have looked up the name, the OBJECT_TYPE (if any) is

13702      no longer valid. Note that if we are parsing tentatively, and

13703      the parse fails, OBJECT_TYPE will be automatically restored.  */

13704    parser->context->object_type = NULL_TREE;

13705

13706    if (name == error_mark_node)

13707      return error_mark_node;

13708

13709    if (!cp_parser_parsing_tentatively (parser)

13710        || cp_parser_committed_to_tentative_parse (parser))

13711      flags |= LOOKUP_COMPLAIN;

13712

13713    /* A template-id has already been resolved; there is no lookup to

13714      do.  */

13715    if (TREE_CODE (name) == TEMPLATE_ID_EXPR)

13716      return name;

13717    if (BASELINK_P (name))

13718    {

13719      my_friendly_assert ((TREE_CODE (BASELINK_FUNCTIONS (name))

13720                          == TEMPLATE_ID_EXPR),

13721                       20020909);

13722      return name;

13723    }

13724

13725    /* A BIT_NOT_EXPR is used to represent a destructor. By this point,

13726      it should already have been checked to make sure that the name

13727      used matches the type being destroyed.  */

13728    if (TREE_CODE (name) == BIT_NOT_EXPR)

13729    {

13730      tree type;

13731

13732      /* Figure out to which type this destructor applies.  */

13733      if (parser->scope)

13734        type = parser->scope;

13735      else if (object_type)

13736        type = object_type;

13737      else

13738        type = current_class_type ;

13739      /* If that's not a class type, there is no destructor.  */

13740      if (!type || !CLASS_TYPE_P (type))

13741        return error_mark_node;

13742      if (!CLASSTYPE_DESTRUCTORS (type))

13743        return error_mark_node;

13744       /* If it was a class type, return the destructor.  */

13745      return CLASSTYPE_DESTRUCTORS (type);

13746    }

 

Notice the assertion at line 13719, if BASELINK (a reference to a member function or member functions from a base class. BASELINK_FUNCTIONS gives the FUNCTION_DECL, TEMPLATE_DECL, OVERLOAD, or TEMPLATE_ID_EXPR corresponding to the functions) is found, it must refer to a template-id-expr. Why? Consider:

struct A { void f(); };

struct B: public A {};
B b;

b.f();

BASELINK will be built for “b.f()”, as “b.f()” in fact is “a.f()”, which is the result of name lookup. And this BASELINK should not appear during this procedure.

While for destructor, if outside of class, it must either follow nested-name-specifier, or follow the declarator (i.e, “a.~A()” or “A::~A()”). After parsing “a.” or “A::” (usually, it is done by previous invocation of cp_parser_lookup_name ), it should fill scope (for “A::”) or object_type (for “a.”) slot of parser. Otherwise, it should be within the class which is referred by current_class_type . Then at line 13745, CLASSTYPE_DESTRUCTORS returns the method.

5.12.4.1.1.2.1.1.    Lookup in specified scope

The scope slot of parser indicates in which names should be looked up. If it is NULL_TREE, then we look up names in the scope that is currently open in the source program. If non-NULL, it is either a *_TYPE or NAMESPACE_DECL for the scope in which we should look.

 

cp_parser_lookup_name (continue)

 

13754    /* Perform the lookup.  */

13755    if (parser->scope)

13756    {

13757      bool dependent_p;

13758

13759      if (parser->scope == error_mark_node)

13760       return error_mark_node;

13761

13762      /* If the SCOPE is dependent, the lookup must be deferred until

13763        the template is instantiated -- unless we are explicitly

13764        looking up names in uninstantiated templates. Even then, we

13765        cannot look up the name if the scope is not a class type; it

13766        might, for example, be a template type parameter.  */

13767      dependent_p = (TYPE_P (parser->scope)

13768                   && !(parser->in_declarator_p

13769                        && currently_open_class (parser->scope))

13770                   && dependent_type_p (parser->scope));

13771      if ((check_dependency || !CLASS_TYPE_P (parser->scope))

13772         && dependent_p)

13773     {

13774        if (is_type)

13775          /* The resolution to Core Issue 180 says that `struct A::B'

13776            should be considered a type-name, even if `A' is

13777             dependent.  */

13778          decl = TYPE_NAME (make_typename_type (parser->scope,

13779                           name,

13780                            /*complain=*/ 1));

13781        else if (is_template)

13782          decl = make_unbound_class_template (parser->scope,

13783                                         name,

13784                                         /*complain=*/ 1);

13785        else

13786          decl = build_nt (SCOPE_REF, parser->scope, name);

13787     }

 

If the scope slot of parser is dependent, the lookup result depends on the lookup control flag passed in the function, but note that among is_type , is_template , is_namespace , at invocation, at most one flag would be set.

If we are looking for type, here is Core Iusse 180 described in http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#180

180. typename and elaborated types

Section: 14.7  [temp.res]     Status: CD1     Submitter: Mike Miller     Date: 21 Dec 1999

[Moved to DR at 4/02 meeting.]

Mike Miller : A question about typename came up in the discussion of issue 68 that is somewhat relevant to the idea of omitting typename in contexts where it is clear that a type is required: consider something like

        template <class T>

        class X {

            friend class T::nested;

        };

Is typename required here? If so, where would it go? (The grammar doesn't seem to allow it anywhere in an elaborated-type-specifier that has a class-key .)

Bill Gibbons : The class applies to the last identifier in the qualified name, since all the previous names must be classes or namespaces. Since the name is specified to be a class it does not need typename . [However,] it looks like 14.7 [temp.res] paragraph 3 requires typename and the following paragraphs do not exempt this case. This is not what we agreed on.

Proposed resolution (04/01):

In 14.7 [temp.res] paragraph 5, change

The keyword typename is not permitted in a base-specifier or in a mem-initializer ; in these contexts a qualified-name that depends on a template-parameter (14.7.2 [temp.dep]) is implicitly assumed to be a type name.

to

A qualified name used as the name in a mem-initializer-id , a base-specifier , or an elaborated-type-specifier (in the class-key and enum forms) is implicitly assumed to name a type, without the use of the typename keyword. [Note: the typename keyword is not permitted by the syntax of these constructs.]

(The expected resolution for issue 254 will remove the typename forms from the grammar for elaborated-type-specifier . If that resolution is adopted, the parenthetical phrase "(in the class-key and enum forms)" in the preceding wording should be removed because those will be the only forms of elaborated-type-specifier .)

In short, A::B if A is dependent, B will be considered as typename. While if is_template is true, it is expression mentioned by [3], clause 14.2 “Names of template specializations”, terms 4.

When the name of a member template specialization appears after . or -> in a postfix-expression, or after nested-name-specifier in a qualified-id, and the postfix-expression or qualified-id explicitly depends on a template-parameter, the member template name must be prefixed by the keyword template . Otherwise the name is assumed to name a non-template. For example:

 

class X {

public :

template <size_t> X* alloc();

template <size_t> static X* adjust();

};

template <class T> void f(T* p)

{

T* p1 = p->alloc<200>();

// ill-formed: < means less than

T* p2 = p->template alloc<200>();

// OK: < starts template argument list

T::adjust<100>();

// ill-formed: < means less than

T::template adjust<100>();

// OK: < starts template argument list

}

In the example, expression: “T::template adjust<100>();” is the target processed here by make_unbound_class_template .

 

2724 tree

2725 make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)   in decl.c

2726 {

2727    tree t;

2728    tree d;

2729

2730    if (TYPE_P (name))

2731      name = TYPE_IDENTIFIER (name);

2732    else if (DECL_P (name))

2733      name = DECL_NAME (name);

2734    if (TREE_CODE (name) != IDENTIFIER_NODE)

2735      abort ();

2736

2737    if (!dependent_type_p (context)

2738        || currently_open_class (context))

2739    {

2740      tree tmpl = NULL_TREE;

2741

2742      if (IS_AGGR_TYPE (context))

2743        tmpl = lookup_field (context, name, 0, false);

2744

2745      if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))

2746      {

2747        if (complain & tf_error)

2748          error ("no class template named `%#T' in `%#T'", name, context);

2749        return error_mark_node;

2750      }

2751       

2752      if (complain & tf_error)

2753        perform_or_defer_access_check (TYPE_BINFO (context), tmpl);

2754

2755      return tmpl;

2756    }

2757

2758     /* Build the UNBOUND_CLASS_TEMPLATE.  */

2759    t = make_aggr_type (UNBOUND_CLASS_TEMPLATE);

2760    TYPE_CONTEXT (t) = FROB_CONTEXT (context);

2761    TREE_TYPE (t) = NULL_TREE;

2762

2763     /* Build the corresponding TEMPLATE_DECL.  */

2764    d = build_decl (TEMPLATE_DECL, name, t);

2765    TYPE_NAME (TREE_TYPE (d)) = d;

2766    TYPE_STUB_DECL (TREE_TYPE (d)) = d;

2767    DECL_CONTEXT (d) = FROB_CONTEXT (context);

2768    DECL_ARTIFICIAL (d) = 1;

2769

2770    return t;

2771 }

 

At line 2743, lookup_field invokes lookup_member inside, but returns NULL if function instead of member found. See that in above expression, if ‘T’ is not dependent, or it is the class currently opened, the expression is ill-formed, unless “adjust” is a class template.

Otherwise, if T is dependent and not currently opened, UNBOUND_CLASS_TEMPLATE node is built. It is named UNBOUND, because context like ‘T’ is unknown yet.

Then at line 13785 in cp_parser_lookup_name , if neither type or template is being looked forward, just treat it as normal SCOPE_REF.

 

cp_parser_lookup_name (continue)

 

13788      else

13789     {

13790        bool pop_p = false;

13791     

13792         /* If PARSER->SCOPE is a dependent type, then it must be a

13793          class type, and we must not be checking dependencies;

13794          otherwise, we would have processed this lookup above. So

13795          that PARSER->SCOPE is not considered a dependent base by

13796          lookup_member, we must enter the scope here.  */

13797        if (dependent_p)

13798          pop_p = push_scope (parser->scope);

13799        /* If the PARSER->SCOPE is a a template specialization, it

13800          may be instantiated during name lookup. In that case,

13801          errors may be issued. Even if we rollback the current

13802           tentative parse, those errors are valid.  */

13803        decl = lookup_qualified_name (parser->scope, name, is_type,

13804                                 /*complain=*/ true);

13805        if (pop_p)

13806          pop_scope (parser->scope);

13807     }

13808      parser->qualifying_scope = parser->scope;

13809      parser->object_scope = NULL_TREE;

13810    }

 

If scope is not dependent, it forms the qualified name. Routine lookup_qualified_name does the resolution.

 

3775 tree

3776 lookup_qualified_name (tree scope, tree name, bool is_type_p, bool complain)       in name-lookup.c

3777 {

3778    int flags = 0;

3779

3780    if (TREE_CODE (scope) == NAMESPACE_DECL)

3781    {

3782      cxx_binding binding;

3783

3784      cxx_binding_clear (&binding);

3785      flags |= LOOKUP_COMPLAIN;

3786      if (is_type_p)

3787         flags |= LOOKUP_PREFER_TYPES;

3788      if (qualified_lookup_using_namespace (name, scope, &binding, flags))

3789         return select_decl (&binding, flags);

3790    }

3791    else if (is_aggr_type (scope, complain))

3792    {

3793      tree t;

3794      t = lookup_member (scope, name, 0, is_type_p);

3795      if (t)

3796         return t;

3797    }

3798

3799    return error_mark_node;

3800 }

 

According to the kind of scope, the search can be divided into 2 types.

5.12.4.1.1.2.1.1.1.            Lookup in specified namespace

If the specified scope is namespace, the search is done by below function.

 

3835   static bool

3836   qualified_lookup_using_namespace (tree name, tree scope,                    in name-lookup.c

3837                                  cxx_binding *result, int flags)

3838   {

3839     /* Maintain a list of namespaces visited...  */

3840     tree seen = NULL_TREE;

3841     /* ... and a list of namespace yet to see.  */

3842     tree todo = NULL_TREE;

3843     tree todo_maybe = NULL_TREE;

3844     tree usings;

3845     timevar_push (TV_NAME_LOOKUP);

3846     /* Look through namespace aliases.  */

3847     scope = ORIGINAL_NAMESPACE (scope);

3848     while (scope && result->value != error_mark_node)

3849     {

3850       cxx_binding *binding =

3851         cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name);

3852       seen = tree_cons (scope, NULL_TREE, seen);

3853       if (binding)

3854         result = ambiguous_decl (name, result, binding, flags);

3855  

3856       /* Consider strong using directives always, and non-strong ones

3857         if we haven't found a binding yet. ??? Shouldn't we consider

3858         non-strong ones if the initial RESULT is non-NULL, but the

3859          binding in the given namespace is?  */

3860       for (usings = DECL_NAMESPACE_USING (scope); usings;

3861           usings = TREE_CHAIN (usings))

3862         /* If this was a real directive, and we have not seen it.  */

3863         if (!TREE_INDIRECT_USING (usings))

3864         {

3865           /* Try to avoid queuing the same namespace more than once,

3866              the exception being when a namespace was already

3867              enqueued for todo_maybe and then a strong using is

3868              found for it. We could try to remove it from

3869              todo_maybe, but it's probably not worth the effort.  */

3870           if (is_associated_namespace (scope, TREE_PURPOSE (usings))

3871             && !purpose_member (TREE_PURPOSE (usings), seen)

3872             && !purpose_member (TREE_PURPOSE (usings), todo))

3873            todo = tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);

3874           else if ((!result->value && !result->type)

3875                  && !purpose_member (TREE_PURPOSE (usings), seen)

3876                   && !purpose_member (TREE_PURPOSE (usings), todo)

3877                  && !purpose_member (TREE_PURPOSE (usings), todo_maybe))

3878             todo_maybe = tree_cons (TREE_PURPOSE (usings), NULL_TREE,

3879                                  todo_maybe);

3880         }

3881       if (todo)

3882       {

3883         scope = TREE_PURPOSE (todo);

3884         todo = TREE_CHAIN (todo);

3885       }

3886       else if (todo_maybe

3887             && (!result->value && !result->type))

3888       {

3889         scope = TREE_PURPOSE (todo_maybe);

3890         todo = TREE_CHAIN (todo_maybe);

3891         todo_maybe = NULL_TREE;

3892       }

3893       else

3894         scope = NULL_TREE; /* If there never was a todo list.  */

3895     }

3896     POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result->value != error_mark_node);

3897   }

 

If the name can’t be found in this namespace, in FOR loop at line 3860 processess statement of “using namespace xxx”. See at line 3883 and 3889, namespace “xxx” in “using namespace xxx” is put into scope, then loops back the WHILE loop at line 3848, does the search again via cxx_scope_find_binding_for_name .

 

3474 static cxx_binding *

3475 ambiguous_decl (tree name, cxx_binding *old, cxx_binding *new, int flags)   in name-lookup.c

3476 {

3477    tree val, type;

3478    my_friendly_assert (old != NULL, 393);

3479    /* Copy the value.  */

3480    val = new->value;

3481    if (val)

3482      switch (TREE_CODE (val))

3483      {

3484        case TEMPLATE_DECL:

3485          /* If we expect types or namespaces, and not templates,

3486             or this is not a template class.  */

3487          if (LOOKUP_QUALIFIERS_ONLY (flags)

3488              && !DECL_CLASS_TEMPLATE_P (val))

3489            val = NULL_TREE;

3490          break ;

3491        case TYPE_DECL:

3492          if (LOOKUP_NAMESPACES_ONLY (flags))

3493            val = NULL_TREE;

3494          break ;

3495        case NAMESPACE_DECL:

3496          if (LOOKUP_TYPES_ONLY (flags))

3497            val = NULL_TREE;

3498          break ;

3499        case FUNCTION_DECL:

3500          /* Ignore built-in functions that are still anticipated.  */

3501          if (LOOKUP_QUALIFIERS_ONLY (flags) || DECL_ANTICIPATED (val))

3502            val = NULL_TREE;

3503          break ;

3504        default :

3505          if (LOOKUP_QUALIFIERS_ONLY (flags))

3506            val = NULL_TREE;

3507      }

 

In specified namespace, ambiguity happens when there are more than 1 declarations of the same name and same kind. For example, variable can share the name with function without causing ambiguity, as at point of reference the compiler can tell who is who. So function ambiguous_decl first filters out the unexpected result. Marcos used above have below definitions.

 

3366 #define LOOKUP_PREFER_BOTH (LOOKUP_PREFER_TYPES | LOOKUP_PREFER_NAMESPACES)

3369 #define LOOKUP_NAMESPACES_ONLY(F)  /                                        in cp-tree.h

3370    (((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES))

3371 #define LOOKUP_TYPES_ONLY(F)  /

3372    (!((F) & LOOKUP_PREFER_NAMESPACES) && ((F) & LOOKUP_PREFER_TYPES))

3373 #define LOOKUP_QUALIFIERS_ONLY(F)     ((F) & LOOKUP_PREFER_BOTH)

 

ambiguous_decl (continue)

 

3509    if (!old->value)

3510      old->value = val;

3511    else if (val && val != old->value)

3512    {

3513      if (is_overloaded_fn (old->value) && is_overloaded_fn (val))

3514        old->value = merge_functions (old->value, val);

3515      else

3516      {

3517        /* Some declarations are functions, some are not.  */

3518        if (flags & LOOKUP_COMPLAIN)

3519        {

3520          /* If we've already given this error for this lookup,

3521             old->value is error_mark_node, so let's not

3522             repeat ourselves.  */

3523          if (old->value != error_mark_node)

3524          {

3525            error ("use of `%D' is ambiguous", name);

3526            cp_error_at ("  first declared as `%#D' here",

3527                      old->value);

3528          }

3529          cp_error_at ("  also declared as `%#D' here", val);

3530        }

3531        old->value = error_mark_node;

3532      }

3533    }

3534     /* ... and copy the type.  */

3535    type = new->type;

3536    if (LOOKUP_NAMESPACES_ONLY (flags))

3537      type = NULL_TREE;

3538    if (!old->type)

3539      old->type = type;

3540    else if (type && old->type != type)

3541    {

3542      if (flags & LOOKUP_COMPLAIN)

3543      {

3544        error ("`%D' denotes an ambiguous type",name);

3545        error ("%J  first type here", TYPE_MAIN_DECL (old->type));

3546        error ("%J  other type here", TYPE_MAIN_DECL (type));

3547      }

3548    }

3549    return old;

3550 }

 

More than 1 declarations of same kind and same name in specified namespace means ambiguity, as compiler can’t make selection. Unless there is other information can help compiler in the resolution.The typical cases includes overloaded functions and template instantiations, according to the function parameters list and template parameters list at reference point, compiler can select the best among candidates (if no best found, but there are candidates, it causes ambiguity again). For those declarations subject to overload, it must record all these declarations.

 

852  int

853  is_overloaded_fn (tree x)                                                                                   in tree.c

854  {

855    /* A baselink is also considered an overloaded function.  */

856    if (TREE_CODE (x) == OFFSET_REF)

857      x = TREE_OPERAND (x, 1);

858    if (BASELINK_P (x))

859      x = BASELINK_FUNCTIONS (x);

860    return (TREE_CODE (x) == FUNCTION_DECL

861           || TREE_CODE (x) == TEMPLATE_ID_EXPR

862           || DECL_FUNCTION_TEMPLATE_P (x)

863           || TREE_CODE (x) == OVERLOAD);

864  }

 

Routine merge_functions then checks if the definition is duplicate, and if not links them as overloaded.

 

3437 static tree

3438 merge_functions (tree s1, tree s2)                                                  in name-lookup.c

3439 {

3440    for (; s2; s2 = OVL_NEXT (s2))

3441    {

3442      tree fn2 = OVL_CURRENT (s2);

3443      tree fns1;

3444

3445      for (fns1 = s1; fns1; fns1 = OVL_NEXT (fns1))

3446      {

3447        tree fn1 = OVL_CURRENT (fns1);

3448

3449        /* If the function from S2 is already in S1, there is no

3450          need to add it again. For `extern "C"' functions, we

3451          might have two FUNCTION_DECLs for the same function, in

3452          different namespaces; again, we only need one of them.  */

3453        if (fn1 == fn2

3454           || (DECL_EXTERN_C_P (fn1) && DECL_EXTERN_C_P (fn2)

3455             && DECL_NAME (fn1) == DECL_NAME (fn2)))

3456          break ;

3457      }

3458       

3459      /* If we exhausted all of the functions in S1, FN2 is new.  */

3460      if (!fns1)

3461        s1 = build_overload (fn2, s1);

3462    }

3463    return s1;

3464 }

 

Above, notice that for normal function (node of FUNCTION_DECL), OVL_CURRENT returns the node itself, and OVL_NEXT returns null. So see that if s2 is FUNCTION_DECL and not recorded as overload in s1 yet, at line 3461, fn2 is s2 .

 

916  tree

917  build_overload (tree decl, tree chain)                                                                  in tree.c

918  {

919    if (! chain && TREE_CODE (decl) != TEMPLATE_DECL)

920      return decl;

921    if (chain && TREE_CODE (chain) != OVERLOAD)

922      chain = ovl_cons (chain, NULL_TREE);

923    return ovl_cons (decl, chain);

924  }

 

In the function, see that if chain is null and decl is TEMPLATE_DECL, code at line 923 will still be executed and creates the head node for a new list. Overloaded obejcts will be recorded by list of tree_overload .

 

306  struct tree_overload GTY(())                                                                in cp-tree.h

307  {

308    struct tree_common common;

309    tree function;

310  };

 

Then routine ovl_cons creates the tree node and chains them in order.

 

902  tree

903  ovl_cons (tree decl, tree chain)                                                                           in tree.c

904  {

905    tree result = make_node (OVERLOAD);

906    TREE_TYPE (result) = unknown_type_node;

907    OVL_FUNCTION (result) = decl;

908    TREE_CHAIN (result) = chain;

909   

910    return result;

911  }

 

In qualified_lookup_using_namespace , note that declarations in namespaces introduced by statement “using namespace xxx” aren’t considered in ambiguity checking, unless namespace association included by “using namespace xxx __attribute ((strong))”.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
for Policy and Practice, 2018, 17(2): 179-195. In this article, Victor Wang Chen Neo examines the implementation of school-based curriculum development (SBCD) in Singapore. SBCD is a process where schools are given greater autonomy to develop and implement their own curriculum, rather than following a standardized national curriculum. The author begins by providing an overview of the history of curriculum development in Singapore, and how the shift towards SBCD came about. He then presents the findings of a study that he conducted, which involved interviews with school leaders who had implemented SBCD in their schools. The author identifies several factors that influenced the successful implementation of SBCD in these schools. These include strong leadership, a clear vision and direction for the school, and a focus on student learning and development. The author also highlights the importance of teacher training and support, as well as collaboration and communication among all stakeholders involved in the curriculum development process. However, the author also notes some challenges that schools face when implementing SBCD. These include a lack of resources, such as time and funding, as well as the need to balance autonomy with accountability to ensure that the curriculum developed meets national standards. Overall, the author suggests that SBCD has the potential to improve the quality of education in Singapore by allowing schools to tailor their curriculum to the needs and interests of their students. However, he also calls for continued support and guidance from the government to ensure that schools are able to implement SBCD effectively.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值