static tree get_variable_decl (tree exp) { if (TREE_CODE (exp) == VAR_DECL) { if (! TREE_STATIC (exp) || FIELD_FINAL (exp)) return exp; } /* We only care about final parameters. */ else if (TREE_CODE (exp) == PARM_DECL) { if (DECL_FINAL (exp)) return exp; } /* See if exp is this.field. */ else if (TREE_CODE (exp) == COMPONENT_REF) { tree op0 = TREE_OPERAND (exp, 0); tree op1 = TREE_OPERAND (exp, 1); tree mdecl = current_function_decl; if (TREE_CODE (op0) == INDIRECT_REF && TREE_CODE (op1) == FIELD_DECL && ! METHOD_STATIC (mdecl) && FIELD_FINAL (op1)) { op0 = TREE_OPERAND (op0, 0); if (op0 == BLOCK_EXPR_DECLS (DECL_FUNCTION_BODY (mdecl))) return op1; } } return NULL_TREE; }
tree build_java_array_type (tree element_type, HOST_WIDE_INT length) { tree sig, t, fld, atype, arfld; char buf[23]; tree elsig = build_java_signature (element_type); tree el_name = element_type; buf[0] = '['; if (length >= 0) sprintf (buf+1, HOST_WIDE_INT_PRINT_DEC, length); else buf[1] = '\0'; sig = ident_subst (IDENTIFIER_POINTER (elsig), IDENTIFIER_LENGTH (elsig), buf, 0, 0, ""); t = IDENTIFIER_SIGNATURE_TYPE (sig); if (t != NULL_TREE) return TREE_TYPE (t); t = make_class (); IDENTIFIER_SIGNATURE_TYPE (sig) = build_pointer_type (t); TYPE_ARRAY_P (t) = 1; if (TREE_CODE (el_name) == POINTER_TYPE) el_name = TREE_TYPE (el_name); el_name = TYPE_NAME (el_name); if (TREE_CODE (el_name) == TYPE_DECL) el_name = DECL_NAME (el_name); { char suffix[23]; if (length >= 0) sprintf (suffix, "[%d]", (int)length); else strcpy (suffix, "[]"); TYPE_NAME (t) = TYPE_STUB_DECL (t) = build_decl (input_location, TYPE_DECL, identifier_subst (el_name, "", '.', '.', suffix), t); TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (t)) = true; } set_java_signature (t, sig); set_super_info (0, t, object_type_node, 0); if (TREE_CODE (element_type) == RECORD_TYPE) element_type = promote_type (element_type); TYPE_ARRAY_ELEMENT (t) = element_type; /* Add length pseudo-field. */ fld = build_decl (input_location, FIELD_DECL, get_identifier ("length"), int_type_node); TYPE_FIELDS (t) = fld; DECL_CONTEXT (fld) = t; FIELD_PUBLIC (fld) = 1; FIELD_FINAL (fld) = 1; TREE_READONLY (fld) = 1; atype = build_prim_array_type (element_type, length); arfld = build_decl (input_location, FIELD_DECL, get_identifier ("data"), atype); DECL_CONTEXT (arfld) = t; DECL_CHAIN (fld) = arfld; DECL_ALIGN (arfld) = TYPE_ALIGN (element_type); /* We could layout_class, but that loads java.lang.Object prematurely. * This is called by the parser, and it is a bad idea to do load_class * in the middle of parsing, because of possible circularity problems. */ push_super_field (t, object_type_node); layout_type (t); return t; }
void check_for_initialization (tree body, tree mdecl) { tree decl; word buf[2]; words before = buf; tree owner = DECL_CONTEXT (mdecl); int is_static_method = METHOD_STATIC (mdecl); /* We don't need to check final fields of <init> it it calls this(). */ int is_finit_method = DECL_FINIT_P (mdecl) || DECL_INSTINIT_P (mdecl); int is_init_method = (is_finit_method || DECL_CLINIT_P (mdecl) || (DECL_INIT_P (mdecl) && ! DECL_INIT_CALLS_THIS (mdecl))); start_current_locals = num_current_locals = 0; num_current_words = 2; if (is_init_method) { int words_needed, i; for (decl = TYPE_FIELDS (owner); decl != NULL_TREE; decl = TREE_CHAIN (decl)) { if (DECL_FINAL (decl) && FIELD_STATIC (decl) == is_static_method) { if (DECL_FIELD_FINAL_IUD (decl)) DECL_BIT_INDEX (decl) = -1; else DECL_BIT_INDEX (decl) = num_current_locals++; } } words_needed = WORDS_NEEDED (2 * num_current_locals); if (words_needed > 2) { num_current_words = words_needed; before = ALLOC_WORDS(words_needed); } i = 0; for (decl = TYPE_FIELDS (owner); decl != NULL_TREE; decl = TREE_CHAIN (decl)) { if (FIELD_FINAL (decl) && FIELD_STATIC (decl) == is_static_method) { if (! DECL_FIELD_FINAL_IUD (decl)) { CLEAR_ASSIGNED (before, i); SET_UNASSIGNED (before, i); i++; } } } } check_init (body, before); if (is_init_method) { for (decl = TYPE_FIELDS (owner); decl != NULL_TREE; decl = TREE_CHAIN (decl)) { if (FIELD_FINAL (decl) && FIELD_STATIC (decl) == is_static_method) { int index = DECL_BIT_INDEX (decl); if (index >= 0 && ! ASSIGNED_P (before, index)) { if (! is_finit_method) error ("%Jfinal field %qD may not have been initialized", decl, decl); } else if (is_finit_method) DECL_FIELD_FINAL_IUD (decl) = 1; /* Re-set to initial state, since we later may use the same bit for DECL_POINTER_ALIAS_SET. */ DECL_BIT_INDEX (decl) = -1; } } } start_current_locals = num_current_locals = 0; }
static tree get_variable_decl (tree exp) { /* A static field can be wrapped in a COMPOUND_EXPR where the first argument initializes the class. */ if (TREE_CODE (exp) == COMPOUND_EXPR) exp = extract_field_decl (exp); if (TREE_CODE (exp) == VAR_DECL) { if (! TREE_STATIC (exp) || FIELD_FINAL (exp)) return exp; } /* We only care about final parameters. */ else if (TREE_CODE (exp) == PARM_DECL) { if (DECL_FINAL (exp)) return exp; } /* See if exp is this.field. */ else if (TREE_CODE (exp) == COMPONENT_REF) { tree op0 = TREE_OPERAND (exp, 0); tree op1 = TREE_OPERAND (exp, 1); tree mdecl = current_function_decl; if (TREE_CODE (op0) == INDIRECT_REF && TREE_CODE (op1) == FIELD_DECL && ! METHOD_STATIC (mdecl) && FIELD_FINAL (op1)) { op0 = TREE_OPERAND (op0, 0); if (op0 == BLOCK_EXPR_DECLS (DECL_FUNCTION_BODY (mdecl))) return op1; } } else if (TREE_CODE (exp) == INDIRECT_REF) { /* For indirect dispatch, look for an expression of the form (indirect_ref (+ (array_ref otable <N>) this)). FIXME: it would probably be better to generate a JAVA_FIELD_REF expression that gets converted to OTABLE access at gimplification time. */ exp = TREE_OPERAND (exp, 0); if (TREE_CODE (exp) == PLUS_EXPR) { tree op0 = TREE_OPERAND (exp, 0); STRIP_NOPS (op0); if (TREE_CODE (op0) == ARRAY_REF) { tree table = TREE_OPERAND (op0, 0); if (TREE_CODE (table) == VAR_DECL && DECL_LANG_SPECIFIC (table) && DECL_OWNER (table) && TYPE_OTABLE_DECL (DECL_OWNER (table)) == table) { HOST_WIDE_INT index = TREE_INT_CST_LOW (TREE_OPERAND (op0, 1)); tree otable_methods = TYPE_OTABLE_METHODS (DECL_OWNER (table)); tree element; for (element = otable_methods; element; element = TREE_CHAIN (element)) { if (index == 1) { tree purpose = TREE_PURPOSE (element); if (TREE_CODE (purpose) == FIELD_DECL) return purpose; else return NULL_TREE; } --index; } } } } } return NULL_TREE; }