📄 cp-decl2.c
字号:
else if (!strcmp (p, "traditional")) warn_traditional = setting; else if (!strcmp (p, "char-subscripts")) warn_char_subscripts = setting; else if (!strcmp (p, "pointer-arith")) warn_pointer_arith = setting; else if (!strcmp (p, "strict-prototypes")) warn_strict_prototypes = setting; else if (!strcmp (p, "missing-prototypes")) warn_missing_prototypes = setting; else if (!strcmp (p, "redundant-decls")) warn_redundant_decls = setting; else if (!strcmp (p, "format")) warn_format = setting; else if (!strcmp (p, "conversion")) warn_conversion = setting; else if (!strcmp (p, "parentheses")) warn_parentheses = setting; else if (!strcmp (p, "comment")) ; /* cpp handles this one. */ else if (!strcmp (p, "comments")) ; /* cpp handles this one. */ else if (!strcmp (p, "trigraphs")) ; /* cpp handles this one. */ else if (!strcmp (p, "import")) ; /* cpp handles this one. */ else if (!strcmp (p, "all")) { extra_warnings = setting; explicit_warn_return_type = setting; warn_unused = setting; warn_implicit = setting; warn_switch = setting; warn_uninitialized = setting;#if 0 warn_enum_clash = setting;#endif } else if (!strcmp (p, "overloaded-virtual")) warn_overloaded_virtual = setting; else if (!strcmp (p, "enum-clash")) warn_enum_clash = setting; else return 0; } else if (!strcmp (p, "-ansi")) flag_no_asm = 1, dollars_in_ident = 0, flag_ansi = 1;#ifdef SPEW_DEBUG /* Undocumented, only ever used when you're invoking cc1plus by hand, since it's probably safe to assume no sane person would ever want to use this under normal circumstances. */ else if (!strcmp (p, "-spew-debug")) spew_debug = 1;#endif else return 0; return 1;}/* Incorporate `const' and `volatile' qualifiers for member functions. FUNCTION is a TYPE_DECL or a FUNCTION_DECL. QUALS is a list of qualifiers. */treegrok_method_quals (ctype, function, quals) tree ctype, function, quals;{ tree fntype = TREE_TYPE (function); tree raises = TYPE_RAISES_EXCEPTIONS (fntype); do { extern tree ridpointers[]; if (TREE_VALUE (quals) == ridpointers[(int)RID_CONST]) { if (TYPE_READONLY (ctype)) error ("duplicate `%s' %s", IDENTIFIER_POINTER (TREE_VALUE (quals)), (TREE_CODE (function) == FUNCTION_DECL ? "for member function" : "in type declaration")); ctype = build_type_variant (ctype, 1, TYPE_VOLATILE (ctype)); build_pointer_type (ctype); } else if (TREE_VALUE (quals) == ridpointers[(int)RID_VOLATILE]) { if (TYPE_VOLATILE (ctype)) error ("duplicate `%s' %s", IDENTIFIER_POINTER (TREE_VALUE (quals)), (TREE_CODE (function) == FUNCTION_DECL ? "for member function" : "in type declaration")); ctype = build_type_variant (ctype, TYPE_READONLY (ctype), 1); build_pointer_type (ctype); } else my_friendly_abort (20); quals = TREE_CHAIN (quals); } while (quals); fntype = build_cplus_method_type (ctype, TREE_TYPE (fntype), (TREE_CODE (fntype) == METHOD_TYPE ? TREE_CHAIN (TYPE_ARG_TYPES (fntype)) : TYPE_ARG_TYPES (fntype))); if (raises) fntype = build_exception_variant (ctype, fntype, raises); TREE_TYPE (function) = fntype; return ctype;}/* This routine replaces cryptic DECL_NAMEs with readable DECL_NAMEs. It leaves DECL_ASSEMBLER_NAMEs with the correct value. *//* This does not yet work with user defined conversion operators It should. */static voidsubstitute_nice_name (decl) tree decl;{ if (DECL_NAME (decl) && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE) { extern char *decl_as_string (); char *n = decl_as_string (DECL_NAME (decl)); if (n[strlen (n) - 1] == ' ') n[strlen (n) - 1] = 0; DECL_NAME (decl) = get_identifier (n); }}/* Classes overload their constituent function names automatically. When a function name is declared in a record structure, its name is changed to it overloaded name. Since names for constructors and destructors can conflict, we place a leading '$' for destructors. CNAME is the name of the class we are grokking for. FUNCTION is a FUNCTION_DECL. It was created by `grokdeclarator'. FLAGS contains bits saying what's special about today's arguments. 1 == DESTRUCTOR. 2 == OPERATOR. If FUNCTION is a destructor, then we must add the `auto-delete' field as a second parameter. There is some hair associated with the fact that we must "declare" this variable in the manner consistent with the way the rest of the arguments were declared. If FUNCTION is a constructor, and we are doing SOS hacks for dynamic classes, then the second hidden argument is the virtual function table pointer with which to initialize the object. QUALS are the qualifiers for the this pointer. */voidgrokclassfn (ctype, cname, function, flags, quals) tree ctype, cname, function; enum overload_flags flags; tree quals;{ tree fn_name = DECL_NAME (function); tree arg_types; tree parm; char *name; if (fn_name == NULL_TREE) { error ("name missing for member function"); fn_name = get_identifier ("<anonymous>"); DECL_NAME (function) = fn_name; } if (quals) ctype = grok_method_quals (ctype, function, quals); arg_types = TYPE_ARG_TYPES (TREE_TYPE (function)); if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE) { /* Must add the class instance variable up front. */ /* Right now we just make this a pointer. But later we may wish to make it special. */ tree type = TREE_VALUE (arg_types); if (flags == DTOR_FLAG) type = TYPE_MAIN_VARIANT (type); else if (DECL_CONSTRUCTOR_P (function)) { if (TYPE_DYNAMIC (ctype)) { parm = build_decl (PARM_DECL, get_identifier (AUTO_VTABLE_NAME), TYPE_POINTER_TO (ptr_type_node)); TREE_USED (parm) = 1; TREE_READONLY (parm) = 1; DECL_ARG_TYPE (parm) = TYPE_POINTER_TO (ptr_type_node); TREE_CHAIN (parm) = last_function_parms; last_function_parms = parm; } if (TYPE_USES_VIRTUAL_BASECLASSES (ctype)) { DECL_CONSTRUCTOR_FOR_VBASE_P (function) = 1; /* In this case we need "in-charge" flag saying whether this constructor is responsible for initialization of virtual baseclasses or not. */ parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node); DECL_ARG_TYPE (parm) = integer_type_node; DECL_REGISTER (parm) = 1; TREE_CHAIN (parm) = last_function_parms; last_function_parms = parm; } } parm = build_decl (PARM_DECL, this_identifier, type); /* Mark the artificial `this' parameter as "artificial". */ DECL_SOURCE_LINE (parm) = 0; DECL_ARG_TYPE (parm) = type; /* We can make this a register, so long as we don't accidentally complain if someone tries to take its address. */ DECL_REGISTER (parm) = 1;#if 0 /* it is wrong to flag the object as readonly, when flag_this_is_variable is 0. */ if (flags != DTOR_FLAG && (flag_this_is_variable <= 0 || TYPE_READONLY (type)))#else if (flags != DTOR_FLAG && TYPE_READONLY (type))#endif TREE_READONLY (parm) = 1; TREE_CHAIN (parm) = last_function_parms; last_function_parms = parm; } if (flags == DTOR_FLAG) { char *buf, *dbuf; tree const_integer_type = build_type_variant (integer_type_node, 1, 0); int len = sizeof (DESTRUCTOR_DECL_PREFIX)-1; arg_types = hash_tree_chain (const_integer_type, void_list_node); /* Build the overload name. It will look like e.g. 7Example. */ if (IDENTIFIER_TYPE_VALUE (cname)) dbuf = build_overload_name (IDENTIFIER_TYPE_VALUE (cname), 1, 1); else if (IDENTIFIER_LOCAL_VALUE (cname)) dbuf = build_overload_name (TREE_TYPE (IDENTIFIER_LOCAL_VALUE (cname)), 1, 1); else my_friendly_abort (346); buf = (char *)alloca (strlen (dbuf) + sizeof (DESTRUCTOR_DECL_PREFIX)); bcopy (DESTRUCTOR_DECL_PREFIX, buf, len); buf[len] = '\0'; strcat (buf, dbuf); DECL_ASSEMBLER_NAME (function) = get_identifier (buf); parm = build_decl (PARM_DECL, in_charge_identifier, const_integer_type); TREE_USED (parm) = 1; TREE_READONLY (parm) = 1; DECL_ARG_TYPE (parm) = const_integer_type; /* This is the same chain as DECL_ARGUMENTS (...). */ TREE_CHAIN (last_function_parms) = parm; TREE_TYPE (function) = build_cplus_method_type (ctype, void_type_node, arg_types); TYPE_HAS_DESTRUCTOR (ctype) = 1; } else { tree these_arg_types; if (TYPE_DYNAMIC (ctype) && DECL_CONSTRUCTOR_P (function)) { arg_types = hash_tree_chain (build_pointer_type (ptr_type_node), TREE_CHAIN (arg_types)); TREE_TYPE (function) = build_cplus_method_type (ctype, TREE_TYPE (TREE_TYPE (function)), arg_types); arg_types = TYPE_ARG_TYPES (TREE_TYPE (function)); } if (DECL_CONSTRUCTOR_FOR_VBASE_P (function)) { arg_types = hash_tree_chain (integer_type_node, TREE_CHAIN (arg_types)); TREE_TYPE (function) = build_cplus_method_type (ctype, TREE_TYPE (TREE_TYPE (function)), arg_types); arg_types = TYPE_ARG_TYPES (TREE_TYPE (function)); } these_arg_types = arg_types; if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE) /* Only true for static member functions. */ these_arg_types = hash_tree_chain (TYPE_POINTER_TO (ctype), arg_types); DECL_ASSEMBLER_NAME (function) = build_decl_overload (fn_name, these_arg_types, 1 + DECL_CONSTRUCTOR_P (function));#if 0 /* This code is going into the compiler, but currently, it makes libg++/src/Interger.cc not compile. The problem is that the nice name winds up going into the symbol table, and conversion operations look for the manged name. */ substitute_nice_name (function);#endif#if 0 if (flags == TYPENAME_FLAG) /* Not exactly an IDENTIFIER_TYPE_VALUE. */ TREE_TYPE (DECL_ASSEMBLER_NAME (function)) = TREE_TYPE (fn_name);#endif } DECL_ARGUMENTS (function) = last_function_parms; /* First approximations. */ DECL_CONTEXT (function) = ctype; DECL_CLASS_CONTEXT (function) = ctype;}/* Sanity check: report error if this function FUNCTION is not really a member of the class (CTYPE) it is supposed to belong to. CNAME and FLAGS are the same here as they are for grokclassfn above. */voidcheck_classfn (ctype, cname, function, flags) tree ctype, cname, function; int flags;{ tree fn_name = DECL_NAME (function); tree fndecl; int need_quotes = 0; char *err_name; tree method_vec = CLASSTYPE_METHOD_VEC (ctype); tree *methods = 0; tree *end = 0; if (method_vec != 0) { methods = &TREE_VEC_ELT (method_vec, 0); end = TREE_VEC_END (method_vec); /* First suss out ctors and dtors. */ if (*methods && fn_name == cname) goto got_it; while (++methods != end) { if (fn_name == DECL_NAME (*methods)) { got_it: fndecl = *methods; while (fndecl) { if (DECL_ASSEMBLER_NAME (function) == DECL_ASSEMBLER_NAME (fndecl)) return; fndecl = DECL_CHAIN (fndecl); } break; /* loser */ } } } if (fn_name == ansi_opname[(int) TYPE_EXPR]) { if (TYPE_HAS_CONVERSION (ctype)) err_name = "such type conversion operator"; } else if (IDENTIFIER_OPNAME_P (fn_name)) { err_name = (char *)alloca (1024); sprintf (err_name, "`operator %s'", operator_name_string (fn_name)); } else { err_name = IDENTIFIER_POINTER (fn_name); need_quotes = 1; } if (methods != end) if (need_quotes) error ("argument list for `%s' does not match any in class", err_name); else error ("argument list for %s does not match any in class", err_name); else { methods = 0; if (need_quotes) error ("no `%s' member function declared in class", err_name); else error ("no %s declared in class", err_name); } /* If we did not find the method in the class, add it to avoid spurious errors. */ add_method (ctype, methods, function);}/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted) of a structure component, returning a FIELD_DECL node. QUALS is a list of type qualifiers for this decl (such as for declaring const member functions). This is done during the parsing of the struct declaration. The FIELD_DECL nodes are chained together and the lot of them are ultimately passed to `build_struct' to make the RECORD_TYPE node. C++: If class A defines that certain functions in class B are friends, then the way I have set things up, it is B who is interested in permission granted by A. However, it is in A's context that these declarations are parsed. By returning a void_type_node, class A does not attempt to incorporate the declarations of the friends within its structure. DO NOT MAKE ANY CHANGES TO THIS CODE WITHOUT MAKING CORRESPONDING CHANGES TO CODE IN `start_method'. */treegrokfield (declarator, declspecs, raises, init, asmspec_tree) tree declarator, declspecs, raises, init; tree asmspec_tree;{ register tree value; char *asmspec = 0; /* Convert () initializers to = initializers. */ if (init == NULL_TREE && declarator != NULL_TREE && TREE_CODE (declarator) == CALL_EXPR && TREE_OPERAND (declarator, 0) && (TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE || TREE_CODE (TREE_OPERAND (declarator, 0)) == SCOPE_REF) && parmlist_is_exprlist (TREE_OPERAND (declarator, 1))) { init = TREE_OPERAND (declarator, 1); declarator = TREE_OPERAND (declarator, 0); } if (init && TREE_CODE (init) == TREE_LIST && TREE_VALUE (init) == error_mark_node && TREE_CHAIN (init) == NULL_TREE) init = NULL_TREE; value = grokdeclarator (declarator, declspecs, FIELD, init != 0, raises); if (! value) return NULL_TREE; /* friends went bad. */ /* Pass friendly classes back. */ if (TREE_CODE (value) == VOID_TYPE) return void_type_node; if (DECL_NAME (value) != NULL_TREE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -