📄 cp-decl.c
字号:
|| TYPE_SIZE (current_class_type) != NULL_TREE) { if (current_lang_name == lang_name_cplusplus) d = lookup_nested_type (type, current_class_type ? TYPE_NAME (current_class_type) : NULL_TREE); else d = NULL_TREE; if (d == NULL_TREE) {#if 0 /* not yet, should get fixed properly later */ d = make_type_decl (name, type); DECL_ASSEMBLER_NAME (d) = get_identifier (build_overload_name (type, 1, 1));#else d = build_decl (TYPE_DECL, name, type); DECL_ASSEMBLER_NAME (d) = get_identifier (build_overload_name (type, 1, 1));#endif /* mark the binding layer marker as internal. (mrs) */ DECL_SOURCE_LINE (d) = 0; set_identifier_type_value (name, type); } else d = TYPE_NAME (d); /* If it is anonymous, then we are called from pushdecl, and we don't want to infinitely recurse. Also, if the name is already in scope, we don't want to push it again--pushdecl is only for pushing new decls. */ if (! ANON_AGGRNAME_P (name) && TYPE_NAME (type) && (TREE_CODE (TYPE_NAME (type)) != TYPE_DECL || lookup_name (name, 1) != TYPE_NAME (type))) { if (class_binding_level) d = pushdecl_class_level (d); else d = pushdecl (d); } } else { /* Make nested declarations go into class-level scope. */ d = build_lang_field_decl (TYPE_DECL, name, type); set_identifier_type_value (name, type); d = pushdecl_class_level (d); } if (ANON_AGGRNAME_P (name)) DECL_IGNORED_P (d) = 1; TYPE_NAME (type) = d; if ((current_class_type == NULL_TREE && current_function_decl == NULL_TREE) || current_lang_name != lang_name_cplusplus) /* Non-nested class. */ DECL_NESTED_TYPENAME (d) = name; else if (current_function_decl != NULL_TREE) { /* Function-nested class. */ set_nested_typename (d, DECL_ASSEMBLER_NAME (current_function_decl), name, type); /* This builds the links for classes nested in fn scope. */ DECL_CONTEXT (d) = current_function_decl; } else if (TYPE_SIZE (current_class_type) == NULL_TREE) { /* Class-nested class. */ set_nested_typename (d, DECL_NESTED_TYPENAME (TYPE_NAME (current_class_type)), name, type); /* This builds the links for classes nested in type scope. */ DECL_CONTEXT (d) = current_class_type; DECL_CLASS_CONTEXT (d) = current_class_type; } } if (b->parm_flag == 2) { TREE_NONLOCAL_FLAG (type) = 1; IDENTIFIER_CLASS_VALUE (name) = TYPE_NAME (type); if (TYPE_SIZE (current_class_type) == NULL_TREE) CLASSTYPE_TAGS (current_class_type) = b->tags; } } if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL) /* Use the canonical TYPE_DECL for this node. */ TYPE_STUB_DECL (type) = TYPE_NAME (type); else { /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the tagged type we just added to the current binding level. This fake NULL-named TYPE_DECL node helps dwarfout.c to know when it needs to output a representation of a tagged type, and it also gives us a convenient place to record the "scope start" address for the tagged type. */#if 0 /* not yet, should get fixed properly later */ TYPE_STUB_DECL (type) = pushdecl (make_type_decl (NULL, type));#else TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL, type));#endif }}/* Counter used to create anonymous type names. */static int anon_cnt = 0;/* Return an IDENTIFIER which can be used as a name for anonymous structs and unions. */treemake_anon_name (){ char buf[32]; sprintf (buf, ANON_AGGRNAME_FORMAT, anon_cnt++); return get_identifier (buf);}/* Clear the TREE_PURPOSE slot of tags which have anonymous typenames. This keeps dbxout from getting confused. */voidclear_anon_tags (){ register struct binding_level *b; register tree tags; static int last_cnt = 0; /* Fast out if no new anon names were declared. */ if (last_cnt == anon_cnt) return; b = current_binding_level; while (b->tag_transparent) b = b->level_chain; tags = b->tags; while (tags) { /* A NULL purpose means we have already processed all tags from here to the end of the list. */ if (TREE_PURPOSE (tags) == NULL_TREE) break; if (ANON_AGGRNAME_P (TREE_PURPOSE (tags))) TREE_PURPOSE (tags) = NULL_TREE; tags = TREE_CHAIN (tags); } last_cnt = anon_cnt;}/* Subroutine of duplicate_decls: return truthvalue of whether or not types of these decls match. */static intdecls_match (newdecl, olddecl) tree newdecl, olddecl;{ int types_match; if (TREE_CODE (newdecl) == FUNCTION_DECL && TREE_CODE (olddecl) == FUNCTION_DECL) { tree f1 = TREE_TYPE (newdecl); tree f2 = TREE_TYPE (olddecl); tree p1 = TYPE_ARG_TYPES (f1); tree p2 = TYPE_ARG_TYPES (f2); /* When we parse a static member function definition, we put together a FUNCTION_DECL which thinks its type is METHOD_TYPE. Change that to FUNCTION_TYPE, and proceed. */ if (TREE_CODE (f1) == METHOD_TYPE && DECL_STATIC_FUNCTION_P (olddecl)) revert_static_member_fn (&f1, &newdecl, &p1); else if (TREE_CODE (f2) == METHOD_TYPE && DECL_STATIC_FUNCTION_P (newdecl)) revert_static_member_fn (&f2, &olddecl, &p2); /* Here we must take care of the case where new default parameters are specified. Also, warn if an old declaration becomes ambiguous because default parameters may cause the two to be ambiguous. */ if (TREE_CODE (f1) != TREE_CODE (f2)) { if (TREE_CODE (f1) == OFFSET_TYPE) compiler_error_with_decl (newdecl, "`%s' redeclared as member function"); else compiler_error_with_decl (newdecl, "`%s' redeclared as non-member function"); return 0; } if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (f1)), TYPE_MAIN_VARIANT (TREE_TYPE (f2)), 1)) types_match = compparms (p1, p2, 1); else types_match = 0; } else { if (TREE_TYPE (newdecl) == error_mark_node) types_match = TREE_TYPE (olddecl) == error_mark_node; else if (TREE_TYPE (olddecl) == NULL_TREE) types_match = TREE_TYPE (newdecl) == NULL_TREE; else types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 1); } return types_match;}/* Handle when a new declaration NEWDECL has the same name as an old one OLDDECL in the same binding contour. Prints an error message if appropriate. If safely possible, alter OLDDECL to look like NEWDECL, and return 1. Otherwise, return 0. */static intduplicate_decls (newdecl, olddecl) register tree newdecl, olddecl;{ extern struct obstack permanent_obstack; unsigned olddecl_uid = DECL_UID (olddecl); int olddecl_friend = 0, types_match; int new_defines_function; register unsigned saved_old_decl_uid; register int saved_old_decl_friend_p; if (TREE_CODE (olddecl) == TREE_LIST && TREE_CODE (newdecl) == FUNCTION_DECL) { /* If a new decl finds a list of old decls, then we assume that the new decl has C linkage, and that the old decls have C++ linkage. In this case, we must look through the list to see whether there is an ambiguity or not. */ tree olddecls = olddecl; /* If the overload list is empty, just install the decl. */ if (TREE_VALUE (olddecls) == NULL_TREE) { TREE_VALUE (olddecls) = newdecl; return 1; } while (olddecls) { if (decls_match (newdecl, TREE_VALUE (olddecls))) { if (TREE_CODE (newdecl) == VAR_DECL) ; else if (DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (TREE_VALUE (olddecls))) { error_with_decl (newdecl, "declaration of `%s' with different language linkage"); error_with_decl (TREE_VALUE (olddecls), "previous declaration here"); } types_match = 1; break; } olddecls = TREE_CHAIN (olddecls); } if (olddecls) olddecl = TREE_VALUE (olddecl); else return 1; } else { if (TREE_CODE (olddecl) != TREE_LIST) olddecl_friend = DECL_LANG_SPECIFIC (olddecl) && DECL_FRIEND_P (olddecl); types_match = decls_match (newdecl, olddecl); } if ((TREE_TYPE (newdecl) && TREE_CODE (TREE_TYPE (newdecl)) == ERROR_MARK) || (TREE_TYPE (olddecl) && TREE_CODE (TREE_TYPE (olddecl)) == ERROR_MARK)) types_match = 0; /* If this decl has linkage, and the old one does too, maybe no error. */ if (TREE_CODE (olddecl) != TREE_CODE (newdecl)) { error_with_decl (newdecl, "`%s' redeclared as different kind of symbol"); if (TREE_CODE (olddecl) == TREE_LIST) olddecl = TREE_VALUE (olddecl); error_with_decl (olddecl, "previous declaration of `%s'"); /* New decl is completely inconsistent with the old one => tell caller to replace the old one. */ return 0; } if (TREE_CODE (newdecl) == FUNCTION_DECL) { /* Now that functions must hold information normally held by field decls, there is extra work to do so that declaration information does not get destroyed during definition. */ if (DECL_VINDEX (olddecl)) DECL_VINDEX (newdecl) = DECL_VINDEX (olddecl); if (DECL_CONTEXT (olddecl)) DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl); if (DECL_CLASS_CONTEXT (olddecl)) DECL_CLASS_CONTEXT (newdecl) = DECL_CLASS_CONTEXT (olddecl);#ifdef SOS if (DECL_DINDEX (olddecl)) DECL_DINDEX (newdecl) = DECL_DINDEX (newdecl);#endif if (DECL_CHAIN (newdecl) == 0) DECL_CHAIN (newdecl) = DECL_CHAIN (olddecl); if (DECL_PENDING_INLINE_INFO (newdecl) == 0) DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl); } if (flag_traditional && TREE_CODE (newdecl) == FUNCTION_DECL && IDENTIFIER_IMPLICIT_DECL (DECL_ASSEMBLER_NAME (newdecl)) == olddecl) /* If -traditional, avoid error for redeclaring fcn after implicit decl. */ ; else if (TREE_CODE (olddecl) == FUNCTION_DECL && DECL_BUILT_IN (olddecl)) { if (!types_match) { error_with_decl (newdecl, "declaration of `%s'"); error_with_decl (olddecl, "conflicts with built-in declaration `%s'"); } } else if (!types_match) { tree oldtype = TREE_TYPE (olddecl); tree newtype = TREE_TYPE (newdecl); int give_error = 0; /* Already complained about this, so don't do so again. */ if (current_class_type == NULL_TREE || IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type) { give_error = 1; error_with_decl (newdecl, "conflicting types for `%s'"); } /* Check for function type mismatch involving an empty arglist vs a nonempty one. */ if (TREE_CODE (olddecl) == FUNCTION_DECL && comptypes (TREE_TYPE (oldtype), TREE_TYPE (newtype), 1) && ((TYPE_ARG_TYPES (oldtype) == 0 && DECL_INITIAL (olddecl) == 0) || (TYPE_ARG_TYPES (newtype) == 0 && DECL_INITIAL (newdecl) == 0))) { /* Classify the problem further. */ register tree t = TYPE_ARG_TYPES (oldtype); if (t == 0) t = TYPE_ARG_TYPES (newtype); for (; t; t = TREE_CHAIN (t)) { register tree type = TREE_VALUE (t); if (TREE_CHAIN (t) == 0 && type != void_type_node) { error ("A parameter list with an ellipsis can't match"); error ("an empty parameter name list declaration."); break; } if (TYPE_MAIN_VARIANT (type) == float_type_node || C_PROMOTING_INTEGER_TYPE_P (type)) { error ("An argument type that has a default promotion"); error ("can't match an empty parameter name list declaration."); break; } } } if (give_error) error_with_decl (olddecl, "previous declaration of `%s'"); /* There is one thing GNU C++ cannot tolerate: a constructor which takes the type of object being constructed. Farm that case out here. */ if (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_CONSTRUCTOR_P (newdecl)) { tree tmp = TREE_CHAIN (TYPE_ARG_TYPES (newtype)); if (tmp != NULL_TREE && (TYPE_MAIN_VARIANT (TREE_VALUE (tmp)) == TYPE_METHOD_BASETYPE (newtype))) { tree parm = TREE_CHAIN (DECL_ARGUMENTS (newdecl)); tree argtypes = hash_tree_chain (build_reference_type (TREE_VALUE (tmp)), TREE_CHAIN (tmp)); DECL_ARG_TYPE (parm) = TREE_TYPE (parm) = TYPE_REFERENCE_TO (TREE_VALUE (tmp)); TREE_TYPE (newdecl) = newtype = build_cplus_method_type (TYPE_METHOD_BASETYPE (newtype), TREE_TYPE (newtype), argtypes); error ("constructor cannot take as argument the type being constructed"); SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl), current_class_type); } } } else { char *errmsg = redeclaration_error_message (newdecl, olddecl); if (errmsg) { error_with_decl (newdecl, errmsg); if (DECL_NAME (olddecl) != NULL_TREE) error_with_decl (olddecl, (DECL_INITIAL (olddecl) && current_binding_level == global_binding_level) ? "`%s' previously defined here" : "`%s' previously declared here"); } else if (TREE_CODE (olddecl) == FUNCTION_DECL && DECL_INITIAL (olddecl) != 0 && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) == 0 && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0) { /* Prototype decl follows defn w/o prototype. */ warning_with_decl (newdecl, "prototype for `%s'"); warning_with_decl (olddecl, "follows non-prototype definition here"); } /* These bits are logically part of the type. */ if (pedantic && (TREE_READONLY (newdecl) != TREE_READONLY (olddecl) || TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl))) error_with_decl (newdecl, "type qualifiers for `%s' conflict with previous decl"); } /* Deal with C++: must preserve virtual function table size. */ if (TREE_CODE (olddecl) == TYPE_DECL) { if (TYPE_LANG_SPECIFIC (TREE_TYPE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -