📄 cp-call.c
字号:
return NULL_TREE;}/* Resolve an expression NAME1::NAME2::...::NAMEn to the name that names the above nested type. INNER_TYPES is a chain of nested type names (held together by SCOPE_REFs); OUTER_TYPE is the type we know to enclose INNER_TYPES. Returns NULL_TREE if there is an error. */treeresolve_scope_to_name (outer_type, inner_types) tree outer_type, inner_types;{ register tree tmp; tree tags, inner_name; if (outer_type == NULL_TREE && current_class_type != NULL_TREE) { /* We first try to look for a nesting in our current class context. */ tree rval = resolve_scope_to_name (current_class_type, inner_types); if (rval != NULL_TREE) return rval; } if (TREE_CODE (inner_types) == SCOPE_REF) { inner_name = TREE_OPERAND (inner_types, 0); inner_types = TREE_OPERAND (inner_types, 1); } else { inner_name = inner_types; inner_types = 0; } if (outer_type == NULL_TREE) { /* If we have something that's already a type by itself, use that. */ if (IDENTIFIER_HAS_TYPE_VALUE (inner_name)) { if (inner_types) return resolve_scope_to_name (IDENTIFIER_TYPE_VALUE (inner_name), inner_types); return inner_name; } return NULL_TREE; } if (! IS_AGGR_TYPE (outer_type)) return NULL_TREE; /* Look for member classes or enums. */ tmp = find_scoped_type (outer_type, inner_name, inner_types); /* If it's not a type in this class, then go down into the base classes and search there. */ if (! tmp && TYPE_BINFO (outer_type)) { tree binfos = TYPE_BINFO_BASETYPES (outer_type); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; for (i = 0; i < n_baselinks; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); tmp = find_scoped_type (BINFO_TYPE (base_binfo), inner_name, inner_types); if (tmp) return tmp; } tmp = NULL_TREE; } return tmp;}/* Build a method call of the form `EXP->SCOPES::NAME (PARMS)'. This is how virtual function calls are avoided. */treebuild_scoped_method_call (exp, scopes, name, parms) tree exp; tree scopes; tree name; tree parms;{ /* Because this syntactic form does not allow a pointer to a base class to be `stolen', we need not protect the derived->base conversion that happens here. @@ But we do have to check visibility privileges later. */ tree basename = resolve_scope_to_name (NULL_TREE, scopes); tree basetype, binfo, decl; tree type = TREE_TYPE (exp); if (type == error_mark_node || basename == NULL_TREE || ! is_aggr_typedef (basename, 1)) return error_mark_node; if (! IS_AGGR_TYPE (type)) { error ("base object of scoped method call is not of aggregate type"); return error_mark_node; } basetype = IDENTIFIER_TYPE_VALUE (basename); if (binfo = binfo_or_else (basetype, type)) { if (binfo == error_mark_node) return error_mark_node; if (TREE_CODE (exp) == INDIRECT_REF) decl = build_indirect_ref (convert_pointer_to (binfo, build_unary_op (ADDR_EXPR, exp, 0)), 0); else decl = build_scoped_ref (exp, scopes); /* Call to a destructor. */ if (TREE_CODE (name) == BIT_NOT_EXPR) { /* Explicit call to destructor. */ name = TREE_OPERAND (name, 0); if (! is_aggr_typedef (name, 1)) return error_mark_node; if (TREE_TYPE (decl) != IDENTIFIER_TYPE_VALUE (name)) { error_with_aggr_type (TREE_TYPE (decl), "qualified type `%s' does not match destructor type `%s'", IDENTIFIER_POINTER (name)); return error_mark_node; } if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl))) error_with_aggr_type (TREE_TYPE (decl), "type `%s' has no destructor"); return build_delete (TREE_TYPE (decl), decl, integer_two_node, LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0, 0); } /* Call to a method. */ return build_method_call (decl, name, parms, NULL_TREE, LOOKUP_NORMAL|LOOKUP_NONVIRTUAL); } return error_mark_node;}/* Build something of the form ptr->method (args) or object.method (args). This can also build calls to constructors, and find friends. Member functions always take their class variable as a pointer. INSTANCE is a class instance. NAME is the NAME field of the struct, union, or class whose type is that of INSTANCE. PARMS help to figure out what that NAME really refers to. BASETYPE_PATH, if non-NULL, tells which basetypes of INSTANCE we should be traversed before starting our search. We need this information to get protected accesses correct. FLAGS is the logical disjunction of zero or more LOOKUP_ flags. See cp-tree.h for more info. If this is all OK, calls build_function_call with the resolved member function. This function must also handle being called to perform initialization, promotion/coercion of arguments, and instantiation of default parameters. Note that NAME may refer to an instance variable name. If `operator()()' is defined for the type of that field, then we return that result. */treebuild_method_call (instance, name, parms, basetype_path, flags) tree instance, name, parms, basetype_path; int flags;{ register tree function, fntype, value_type; register tree basetype, save_basetype; register tree baselink, result, method_name, parmtypes, parm; tree last; int pass; enum visibility_type visibility; int rank_for_overload (); /* Range of cases for vtable optimization. */ enum vtable_needs { not_needed, maybe_needed, unneeded, needed, }; enum vtable_needs need_vtbl = not_needed; char *err_name; char *name_kind; int ever_seen = 0; tree instance_ptr = NULL_TREE; int all_virtual = flag_all_virtual; int static_call_context = 0; tree saw_private = 0; tree saw_protected = 0;#ifdef SOS /* If call is a call to a constructor, then `dtbl' will first be initialized with the function table pointer of the appropriate type (calling "sosFindCode" as a last resort), the the call to the constructor will go through there. */ tree dtbl = (flags & LOOKUP_DYNAMIC) ? TREE_VALUE (parms) : NULL_TREE; /* Flag saying whether or not `dtbl' has been inserted into the parameter list. This is needed because we cannot tell (until we have a match) whether this parameter should go in or not. If 1, then `dtbl' is living naturally. If 0, then `dtbl' is not among the parms that we know about. If -1, the `dtbl' was place into the parms unnaturally. Note that we may side-effect the parameter list, but in such a way that the caller of this function would never know. */ int dtbl_inserted = (flags & LOOKUP_DYNAMIC);#endif /* Keep track of `const' and `volatile' objects. */ int constp, volatilep;#ifdef GATHER_STATISTICS n_build_method_call++;#endif if (instance == error_mark_node || name == error_mark_node || parms == error_mark_node || (instance != 0 && TREE_TYPE (instance) == error_mark_node)) return error_mark_node; /* This is the logic that magically deletes the second argument to operator delete, if it is not needed. */ if (name == ansi_opname[(int) DELETE_EXPR] && list_length (parms)==2) { tree save_last = TREE_CHAIN (parms); tree result; /* get rid of unneeded argument */ TREE_CHAIN (parms) = NULL_TREE; result = build_method_call (instance, name, parms, basetype_path, (LOOKUP_SPECULATIVELY|flags) &~LOOKUP_COMPLAIN); /* If it works, return it. */ if (result && result != error_mark_node) return build_method_call (instance, name, parms, basetype_path, flags); /* If it doesn't work, two argument delete must work */ TREE_CHAIN (parms) = save_last; }#if 0 /* C++ 2.1 does not allow this, but ANSI probably will. */ if (TREE_CODE (name) == BIT_NOT_EXPR) { error ("invalid call to destructor, use qualified name `%s::~%s'", IDENTIFIER_POINTER (name), IDENTIFIER_POINTER (name)); return error_mark_node; }#else if (TREE_CODE (name) == BIT_NOT_EXPR) { flags |= LOOKUP_DESTRUCTOR; name = TREE_OPERAND (name, 0); if (! is_aggr_typedef (name, 1)) return error_mark_node; if (parms) error ("destructors take no parameters"); basetype = IDENTIFIER_TYPE_VALUE (name); if (! TYPE_HAS_DESTRUCTOR (basetype)) {#if 0 /* ARM says tp->~T() without T::~T() is valid. */ error_with_aggr_type (basetype, "type `%s' has no destructor");#endif /* A destructive destructor wouldn't be a bad idea, but let's not bother for now. */ return build_c_cast (void_type_node, instance); } instance = default_conversion (instance); if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE) instance_ptr = instance; else instance_ptr = build_unary_op (ADDR_EXPR, instance, 0); return build_delete (basetype, instance_ptr, integer_two_node, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0, 0); }#endif /* Initialize name for error reporting. */ if (IDENTIFIER_TYPENAME_P (name)) err_name = "type conversion operator"; else if (IDENTIFIER_OPNAME_P (name)) { char *p = operator_name_string (name); err_name = (char *)alloca (strlen (p) + 10); sprintf (err_name, "operator %s", p); } else if (TREE_CODE (name) == SCOPE_REF) err_name = IDENTIFIER_POINTER (TREE_OPERAND (name, 1)); else err_name = IDENTIFIER_POINTER (name); if (IDENTIFIER_OPNAME_P (name)) GNU_xref_call (current_function_decl, IDENTIFIER_POINTER (name)); else GNU_xref_call (current_function_decl, err_name); if (instance == NULL_TREE) { basetype = NULL_TREE; /* Check cases where this is really a call to raise an exception. */ if (current_class_type && TREE_CODE (name) == IDENTIFIER_NODE) { basetype = purpose_member (name, CLASSTYPE_TAGS (current_class_type)); if (basetype) basetype = TREE_VALUE (basetype); } else if (TREE_CODE (name) == SCOPE_REF && TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE) { if (! is_aggr_typedef (TREE_OPERAND (name, 0), 1)) return error_mark_node; basetype = purpose_member (TREE_OPERAND (name, 1), CLASSTYPE_TAGS (IDENTIFIER_TYPE_VALUE (TREE_OPERAND (name, 0)))); if (basetype) basetype = TREE_VALUE (basetype); } if (basetype != NULL_TREE) ; /* call to a constructor... */ else if (IDENTIFIER_HAS_TYPE_VALUE (name)) { basetype = IDENTIFIER_TYPE_VALUE (name); name = constructor_name (basetype); } else { tree typedef_name = lookup_name (name, 1); if (typedef_name && TREE_CODE (typedef_name) == TYPE_DECL) { /* Canonicalize the typedef name. */ basetype = TREE_TYPE (typedef_name); name = TYPE_IDENTIFIER (basetype); } else { error ("no constructor named `%s' in visible scope", IDENTIFIER_POINTER (name)); return error_mark_node; } } if (! IS_AGGR_TYPE (basetype)) { non_aggr_error: if ((flags & LOOKUP_COMPLAIN) && TREE_CODE (basetype) != ERROR_MARK) error ("request for member `%s' in something not a structure or union", err_name); return error_mark_node; } } else if (instance == C_C_D || instance == current_class_decl) { /* When doing initialization, we side-effect the TREE_TYPE of C_C_D, hence we cannot set up BASETYPE from CURRENT_CLASS_TYPE. */ basetype = TREE_TYPE (C_C_D); /* Anything manifestly `this' in constructors and destructors has a known type, so virtual function tables are not needed. */ if (TYPE_VIRTUAL_P (basetype) && !(flags & LOOKUP_NONVIRTUAL)) need_vtbl = (dtor_label || ctor_label) ? unneeded : maybe_needed; instance = C_C_D; instance_ptr = current_class_decl; result = build_field_call (TYPE_BINFO (current_class_type), instance_ptr, name, parms, err_name); if (result) return result; } else if (TREE_CODE (instance) == RESULT_DECL) { basetype = TREE_TYPE (instance); /* Should we ever have to make a virtual function reference from a RESULT_DECL, know that it must be of fixed type within the scope of this function. */ if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype)) need_vtbl = maybe_needed; instance_ptr = build1 (ADDR_EXPR, TYPE_POINTER_TO (basetype), instance); } else if (instance == current_exception_object) { instance_ptr = build1 (ADDR_EXPR, TYPE_POINTER_TO (current_exception_type), TREE_OPERAND (current_exception_object, 0)); mark_addressable (TREE_OPERAND (current_exception_object, 0)); result = build_field_call (TYPE_BINFO (current_exception_type), instance_ptr, name, parms, err_name); if (result) return result; error ("exception member `%s' cannot be invoked", err_name); return error_mark_node; } else { /* The MAIN_VARIANT of the type that `instance_ptr' winds up being. */ tree inst_ptr_basetype; static_call_context = (TREE_CODE (instance) == NOP_EXPR && TREE_OPERAND (instance, 0) == error_mark_node); /* the base type of an instance variable is pointer to class */ basetype = TREE_TYPE (instance); if (TREE_CODE (basetype) == REFERENCE_TYPE) { basetype = TYPE_MAIN_VARIANT (TREE_TYPE (basetype)); if (! IS_AGGR_TYPE (basetype)) goto non_aggr_error; /* Call to convert not needed because we are remaining within the same type. */ instance_ptr = build1 (NOP_EXPR, TYPE_POINTER_TO (basetype), instance); inst_ptr_basetype = basetype; } else { if (TREE_CODE (basetype) == POINTER_TYPE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -