c-common.c
来自「GCC编译器源代码」· C语言 代码 · 共 2,225 行 · 第 1/5 页
C
2,225 行
|| TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL) TREE_USED (decl) = 1; else warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); break; case A_CONST: if (TREE_CODE (decl) == FUNCTION_DECL) TREE_READONLY (decl) = 1; else if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) TREE_TYPE (decl) = type = build_pointer_type (build_type_variant (TREE_TYPE (type), 1, TREE_THIS_VOLATILE (TREE_TYPE (type)))); else warning ( "`%s' attribute ignored", IDENTIFIER_POINTER (name)); break; case A_T_UNION: if (is_type && TREE_CODE (type) == UNION_TYPE && (decl == 0 || (TYPE_FIELDS (type) != 0 && TYPE_MODE (type) == DECL_MODE (TYPE_FIELDS (type))))) TYPE_TRANSPARENT_UNION (type) = 1; else if (decl != 0 && TREE_CODE (decl) == PARM_DECL && TREE_CODE (type) == UNION_TYPE && TYPE_MODE (type) == DECL_MODE (TYPE_FIELDS (type))) DECL_TRANSPARENT_UNION (decl) = 1; else warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); break; case A_CONSTRUCTOR: if (TREE_CODE (decl) == FUNCTION_DECL && TREE_CODE (type) == FUNCTION_TYPE && decl_function_context (decl) == 0) { DECL_STATIC_CONSTRUCTOR (decl) = 1; TREE_USED (decl) = 1; } else warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); break; case A_DESTRUCTOR: if (TREE_CODE (decl) == FUNCTION_DECL && TREE_CODE (type) == FUNCTION_TYPE && decl_function_context (decl) == 0) { DECL_STATIC_DESTRUCTOR (decl) = 1; TREE_USED (decl) = 1; } else warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); break; case A_MODE: if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE) warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); else { int j; char *p = IDENTIFIER_POINTER (TREE_VALUE (args)); int len = strlen (p); enum machine_mode mode = VOIDmode; tree typefm; if (len > 4 && p[0] == '_' && p[1] == '_' && p[len - 1] == '_' && p[len - 2] == '_') { char *newp = (char *) alloca (len - 1); strcpy (newp, &p[2]); newp[len - 4] = '\0'; p = newp; } /* Give this decl a type with the specified mode. First check for the special modes. */ if (! strcmp (p, "byte")) mode = byte_mode; else if (!strcmp (p, "word")) mode = word_mode; else if (! strcmp (p, "pointer")) mode = ptr_mode; else for (j = 0; j < NUM_MACHINE_MODES; j++) if (!strcmp (p, GET_MODE_NAME (j))) mode = (enum machine_mode) j; if (mode == VOIDmode) error ("unknown machine mode `%s'", p); else if (0 == (typefm = type_for_mode (mode, TREE_UNSIGNED (type)))) error ("no data type for mode `%s'", p); else { TREE_TYPE (decl) = type = typefm; DECL_SIZE (decl) = 0; layout_decl (decl, 0); } } break; case A_SECTION:#ifdef ASM_OUTPUT_SECTION_NAME if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL) && TREE_CODE (TREE_VALUE (args)) == STRING_CST) { if (TREE_CODE (decl) == VAR_DECL && current_function_decl != NULL_TREE && ! TREE_STATIC (decl)) error_with_decl (decl, "section attribute cannot be specified for local variables"); /* The decl may have already been given a section attribute from a previous declaration. Ensure they match. */ else if (DECL_SECTION_NAME (decl) != NULL_TREE && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)), TREE_STRING_POINTER (TREE_VALUE (args))) != 0) error_with_decl (node, "section of `%s' conflicts with previous declaration"); else DECL_SECTION_NAME (decl) = TREE_VALUE (args); } else error_with_decl (node, "section attribute not allowed for `%s'");#else error_with_decl (node, "section attributes are not supported for this target");#endif break; case A_ALIGNED: { tree align_expr = (args ? TREE_VALUE (args) : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); int align; /* Strip any NOPs of any kind. */ while (TREE_CODE (align_expr) == NOP_EXPR || TREE_CODE (align_expr) == CONVERT_EXPR || TREE_CODE (align_expr) == NON_LVALUE_EXPR) align_expr = TREE_OPERAND (align_expr, 0); if (TREE_CODE (align_expr) != INTEGER_CST) { error ("requested alignment is not a constant"); continue; } align = TREE_INT_CST_LOW (align_expr) * BITS_PER_UNIT; if (exact_log2 (align) == -1) error ("requested alignment is not a power of 2"); else if (is_type) TYPE_ALIGN (type) = align; else if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FIELD_DECL) error_with_decl (decl, "alignment may not be specified for `%s'"); else DECL_ALIGN (decl) = align; } break; case A_FORMAT: { tree format_type = TREE_VALUE (args); tree format_num_expr = TREE_VALUE (TREE_CHAIN (args)); tree first_arg_num_expr = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args))); int format_num; int first_arg_num; int is_scan; tree argument; int arg_num; if (TREE_CODE (decl) != FUNCTION_DECL) { error_with_decl (decl, "argument format specified for non-function `%s'"); continue; } if (TREE_CODE (format_type) == IDENTIFIER_NODE && (!strcmp (IDENTIFIER_POINTER (format_type), "printf") || !strcmp (IDENTIFIER_POINTER (format_type), "__printf__"))) is_scan = 0; else if (TREE_CODE (format_type) == IDENTIFIER_NODE && (!strcmp (IDENTIFIER_POINTER (format_type), "scanf") || !strcmp (IDENTIFIER_POINTER (format_type), "__scanf__"))) is_scan = 1; else if (TREE_CODE (format_type) == IDENTIFIER_NODE) { error ("`%s' is an unrecognized format function type", IDENTIFIER_POINTER (format_type)); continue; } else { error ("unrecognized format specifier"); continue; } /* Strip any conversions from the string index and first arg number and verify they are constants. */ while (TREE_CODE (format_num_expr) == NOP_EXPR || TREE_CODE (format_num_expr) == CONVERT_EXPR || TREE_CODE (format_num_expr) == NON_LVALUE_EXPR) format_num_expr = TREE_OPERAND (format_num_expr, 0); while (TREE_CODE (first_arg_num_expr) == NOP_EXPR || TREE_CODE (first_arg_num_expr) == CONVERT_EXPR || TREE_CODE (first_arg_num_expr) == NON_LVALUE_EXPR) first_arg_num_expr = TREE_OPERAND (first_arg_num_expr, 0); if (TREE_CODE (format_num_expr) != INTEGER_CST || TREE_CODE (first_arg_num_expr) != INTEGER_CST) { error ("format string has non-constant operand number"); continue; } format_num = TREE_INT_CST_LOW (format_num_expr); first_arg_num = TREE_INT_CST_LOW (first_arg_num_expr); if (first_arg_num != 0 && first_arg_num <= format_num) { error ("format string arg follows the args to be formatted"); continue; } /* If a parameter list is specified, verify that the format_num argument is actually a string, in case the format attribute is in error. */ argument = TYPE_ARG_TYPES (type); if (argument) { for (arg_num = 1; ; ++arg_num) { if (argument == 0 || arg_num == format_num) break; argument = TREE_CHAIN (argument); } if (! argument || TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument))) != char_type_node)) { error ("format string arg not a string type"); continue; } if (first_arg_num != 0) { /* Verify that first_arg_num points to the last arg, the ... */ while (argument) arg_num++, argument = TREE_CHAIN (argument); if (arg_num != first_arg_num) { error ("args to be formatted is not ..."); continue; } } } record_function_format (DECL_NAME (decl), DECL_ASSEMBLER_NAME (decl), is_scan, format_num, first_arg_num); break; } case A_FORMAT_ARG: { tree format_num_expr = TREE_VALUE (args); int format_num, arg_num; tree argument; if (TREE_CODE (decl) != FUNCTION_DECL) { error_with_decl (decl, "argument format specified for non-function `%s'"); continue; } /* Strip any conversions from the first arg number and verify it is a constant. */ while (TREE_CODE (format_num_expr) == NOP_EXPR || TREE_CODE (format_num_expr) == CONVERT_EXPR || TREE_CODE (format_num_expr) == NON_LVALUE_EXPR) format_num_expr = TREE_OPERAND (format_num_expr, 0); if (TREE_CODE (format_num_expr) != INTEGER_CST) { error ("format string has non-constant operand number"); continue; } format_num = TREE_INT_CST_LOW (format_num_expr); /* If a parameter list is specified, verify that the format_num argument is actually a string, in case the format attribute is in error. */ argument = TYPE_ARG_TYPES (type); if (argument) { for (arg_num = 1; ; ++arg_num) { if (argument == 0 || arg_num == format_num) break; argument = TREE_CHAIN (argument); } if (! argument || TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument))) != char_type_node)) { error ("format string arg not a string type"); continue; } } if (TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) != POINTER_TYPE || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (TREE_TYPE (decl)))) != char_type_node)) { error ("function does not return string type"); continue; } record_international_format (DECL_NAME (decl), DECL_ASSEMBLER_NAME (decl), format_num); break; } case A_WEAK: declare_weak (decl); break; case A_ALIAS: if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl)) || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl))) error_with_decl (decl, "`%s' defined both normally and as an alias"); else if (decl_function_context (decl) == 0) { tree id = get_identifier (TREE_STRING_POINTER (TREE_VALUE (args))); if (TREE_CODE (decl) == FUNCTION_DECL) DECL_INITIAL (decl) = error_mark_node; else DECL_EXTERNAL (decl) = 0; assemble_alias (decl, id); } else warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); break; } }}/* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two lists. SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE). The head of the declspec list is stored in DECLSPECS. The head of the attribute list is stored in PREFIX_ATTRIBUTES. Note that attributes in SPECS_ATTRS are stored in the TREE_PURPOSE of the list elements. We drop the containing TREE_LIST nodes and link the resulting attributes together the way decl_attributes expects them. */voidsplit_specs_attrs (specs_attrs, declspecs, prefix_attributes) tree specs_attrs; tree *declspecs, *prefix_attributes;{ tree t, s, a, next, specs, attrs; /* This can happen in c++ (eg: decl: typespec initdecls ';'). */ if (specs_attrs != NULL_TREE && TREE_CODE (specs_attrs) != TREE_LIST) { *declspecs = specs_attrs; *prefix_attributes = NULL_TREE; return; } /* Remember to keep the lists in the same order, element-wise. */ specs = s = NULL_TREE; attrs = a = NULL_TREE; for (t = specs_attrs; t; t = next) { next = TREE_CHAIN (t); /* Declspecs have a non-NULL TREE_VALUE. */ if (TREE_VALUE (t) != NULL_TREE) { if (specs == NULL_TREE) specs = s = t; else { TREE_CHAIN (s) = t; s = t; } } else { if (attrs == NULL_TREE) attrs = a = TREE_PURPOSE (t); else { TREE_CHAIN (a) = TREE_PURPOSE (t); a = TREE_PURPOSE (t); } /* More attrs can be linked here, move A to the end. */ while (TREE_CHAIN (a) != NULL_TREE) a = TREE_CHAIN (a); } } /* Terminate the lists. */ if (s != NULL_TREE) TREE_CHAIN (s) = NULL_TREE; if (a != NULL_TREE) TREE_CHAIN (a) = NULL_TREE; /* All done. */ *declspecs = specs; *prefix_attributes = attrs;}/* Check a printf/fprintf/sprintf/scanf/fscanf/sscanf format against a parameter list. */#define T_I &integer_type_node#define T_L &long_integer_type_node#define T_LL &long_long_integer_type_node
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?