diff options
Diffstat (limited to 'gcc/rust/backend/rust-tree.cc')
-rw-r--r-- | gcc/rust/backend/rust-tree.cc | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/gcc/rust/backend/rust-tree.cc b/gcc/rust/backend/rust-tree.cc index 22e91f4..e1ab7f1 100644 --- a/gcc/rust/backend/rust-tree.cc +++ b/gcc/rust/backend/rust-tree.cc @@ -28,12 +28,17 @@ #include "timevar.h" #include "convert.h" #include "gimple-expr.h" +#include "gimplify.h" +#include "function.h" +#include "gcc-rich-location.h" // forked from gcc/c-family/c-common.cc c_global_trees tree c_global_trees[CTI_MAX]; // forked from gcc/cp/decl.cc cp_global_trees tree cp_global_trees[CPTI_MAX]; +struct saved_scope *scope_chain; + namespace Rust { void @@ -3721,4 +3726,247 @@ resolve_nondeduced_context (tree orig_expr, tsubst_flags_t complain) return orig_expr; } + +// forked from gcc/cp/pt.cc instantiate_non_dependent_or_null + +/* Like instantiate_non_dependent_expr, but return NULL_TREE rather than + an uninstantiated expression. */ + +tree +instantiate_non_dependent_or_null (tree expr) +{ + if (expr == NULL_TREE) + return NULL_TREE; + + return expr; +} + +// forked from gcc/cp/pt.cc resolve_nondeduced_context_or_error + +/* As above, but error out if the expression remains overloaded. */ + +tree +resolve_nondeduced_context_or_error (tree exp, tsubst_flags_t complain) +{ + exp = resolve_nondeduced_context (exp, complain); + if (type_unknown_p (exp)) + { + if (complain & tf_error) + cxx_incomplete_type_error (exp, TREE_TYPE (exp)); + return error_mark_node; + } + return exp; +} + +// forked from gcc/cp/tree.cc really_overloaded_fn + +/* Returns true iff X is an expression for an overloaded function + whose type cannot be known without performing overload + resolution. */ + +bool +really_overloaded_fn (tree x) +{ + return is_overloaded_fn (x) == 2; +} + +// forked from gcc/cp/typeck..cc invalid_nonstatic_memfn_p + +/* EXPR is being used in a context that is not a function call. + Enforce: + + [expr.ref] + + The expression can be used only as the left-hand operand of a + member function call. + + [expr.mptr.operator] + + If the result of .* or ->* is a function, then that result can be + used only as the operand for the function call operator (). + + by issuing an error message if appropriate. Returns true iff EXPR + violates these rules. */ + +bool +invalid_nonstatic_memfn_p (location_t loc, tree expr, tsubst_flags_t complain) +{ + if (expr == NULL_TREE) + return false; + /* Don't enforce this in MS mode. */ + if (flag_ms_extensions) + return false; + if (is_overloaded_fn (expr) && !really_overloaded_fn (expr)) + expr = get_first_fn (expr); + if (DECL_NONSTATIC_MEMBER_FUNCTION_P (expr)) + { + if (complain & tf_error) + { + if (DECL_P (expr)) + { + error_at (loc, "invalid use of non-static member function %qD", + expr); + inform (DECL_SOURCE_LOCATION (expr), "declared here"); + } + else + error_at (loc, + "invalid use of non-static member function of " + "type %qT", + TREE_TYPE (expr)); + } + return true; + } + return false; +} + +// forked from gcc/cp/call.cc strip_top_quals + +tree +strip_top_quals (tree t) +{ + if (TREE_CODE (t) == ARRAY_TYPE) + return t; + return rs_build_qualified_type (t, 0); +} + +// forked from gcc/cp/typeck2.cc cxx_incomplete_type_inform + +/* Print an inform about the declaration of the incomplete type TYPE. */ + +void +cxx_incomplete_type_inform (const_tree type) +{ + if (!TYPE_MAIN_DECL (type)) + return; + + location_t loc = DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)); + tree ptype = strip_top_quals (CONST_CAST_TREE (type)); + + if (current_class_type && TYPE_BEING_DEFINED (current_class_type) + && same_type_p (ptype, current_class_type)) + inform (loc, + "definition of %q#T is not complete until " + "the closing brace", + ptype); + else + inform (loc, "forward declaration of %q#T", ptype); +} + +// forked from gcc/cp/typeck2.cc cxx_incomplete_type_diagnostic + +/* Print an error message for invalid use of an incomplete type. + VALUE is the expression that was used (or 0 if that isn't known) + and TYPE is the type that was invalid. DIAG_KIND indicates the + type of diagnostic (see diagnostic.def). */ + +void +cxx_incomplete_type_diagnostic (location_t loc, const_tree value, + const_tree type, diagnostic_t diag_kind) +{ + bool is_decl = false, complained = false; + + gcc_assert (diag_kind == DK_WARNING || diag_kind == DK_PEDWARN + || diag_kind == DK_ERROR); + + /* Avoid duplicate error message. */ + if (TREE_CODE (type) == ERROR_MARK) + return; + + if (value) + { + STRIP_ANY_LOCATION_WRAPPER (value); + + if (VAR_P (value) || TREE_CODE (value) == PARM_DECL + || TREE_CODE (value) == FIELD_DECL) + { + complained = emit_diagnostic (diag_kind, DECL_SOURCE_LOCATION (value), + 0, "%qD has incomplete type", value); + is_decl = true; + } + } +retry: + /* We must print an error message. Be clever about what it says. */ + + switch (TREE_CODE (type)) + { + case RECORD_TYPE: + case UNION_TYPE: + case ENUMERAL_TYPE: + if (!is_decl) + complained + = emit_diagnostic (diag_kind, loc, 0, + "invalid use of incomplete type %q#T", type); + if (complained) + cxx_incomplete_type_inform (type); + break; + + case VOID_TYPE: + emit_diagnostic (diag_kind, loc, 0, "invalid use of %qT", type); + break; + + case ARRAY_TYPE: + if (TYPE_DOMAIN (type)) + { + type = TREE_TYPE (type); + goto retry; + } + emit_diagnostic (diag_kind, loc, 0, + "invalid use of array with unspecified bounds"); + break; + + case OFFSET_TYPE: + bad_member : { + tree member = TREE_OPERAND (value, 1); + if (is_overloaded_fn (member)) + member = get_first_fn (member); + + if (DECL_FUNCTION_MEMBER_P (member) && !flag_ms_extensions) + { + gcc_rich_location richloc (loc); + /* If "member" has no arguments (other than "this"), then + add a fix-it hint. */ + if (type_num_arguments (TREE_TYPE (member)) == 1) + richloc.add_fixit_insert_after ("()"); + emit_diagnostic (diag_kind, &richloc, 0, + "invalid use of member function %qD " + "(did you forget the %<()%> ?)", + member); + } + else + emit_diagnostic (diag_kind, loc, 0, + "invalid use of member %qD " + "(did you forget the %<&%> ?)", + member); + } + break; + + case LANG_TYPE: + if (type == init_list_type_node) + { + emit_diagnostic (diag_kind, loc, 0, + "invalid use of brace-enclosed initializer list"); + break; + } + gcc_assert (type == unknown_type_node); + if (value && TREE_CODE (value) == COMPONENT_REF) + goto bad_member; + else if (value && TREE_CODE (value) == ADDR_EXPR) + emit_diagnostic (diag_kind, loc, 0, + "address of overloaded function with no contextual " + "type information"); + else if (value && TREE_CODE (value) == OVERLOAD) + emit_diagnostic ( + diag_kind, loc, 0, + "overloaded function with no contextual type information"); + else + emit_diagnostic ( + diag_kind, loc, 0, + "insufficient contextual information to determine type"); + break; + + default: + gcc_unreachable (); + } +} + } // namespace Rust |