Mercurial > hg > CbC > CbC_gcc
diff gcc/c/c-typeck.c @ 146:351920fa3827
merge
author | anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 01 Mar 2020 16:13:28 +0900 |
parents | d34655255c78 1830386684a0 |
children |
line wrap: on
line diff
--- a/gcc/c/c-typeck.c Sun Dec 23 21:23:56 2018 +0900 +++ b/gcc/c/c-typeck.c Sun Mar 01 16:13:28 2020 +0900 @@ -1,5 +1,5 @@ /* Build expressions with type checking for C compiler. - Copyright (C) 1987-2018 Free Software Foundation, Inc. + Copyright (C) 1987-2020 Free Software Foundation, Inc. This file is part of GCC. @@ -100,7 +100,8 @@ tree); static tree pointer_diff (location_t, tree, tree, tree *); static tree convert_for_assignment (location_t, location_t, tree, tree, tree, - enum impl_conv, bool, tree, tree, int); + enum impl_conv, bool, tree, tree, int, + int = 0); static tree valid_compound_expr_initializer (tree, tree); static void push_string (const char *); static void push_member_name (tree); @@ -761,17 +762,18 @@ { if (code1 == VECTOR_TYPE || code2 == VECTOR_TYPE) { - error ("can%'t mix operands of decimal float and vector types"); + error ("cannot mix operands of decimal floating and vector types"); return error_mark_node; } if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE) { - error ("can%'t mix operands of decimal float and complex types"); + error ("cannot mix operands of decimal floating and complex types"); return error_mark_node; } if (code1 == REAL_TYPE && code2 == REAL_TYPE) { - error ("can%'t mix operands of decimal float and other float types"); + error ("cannot mix operands of decimal floating " + "and other floating types"); return error_mark_node; } } @@ -2071,6 +2073,8 @@ mark_exp_read (exp.value); if (convert_p) exp = default_function_array_conversion (loc, exp); + if (!VOID_TYPE_P (TREE_TYPE (exp.value))) + exp.value = require_complete_type (loc, exp.value); if (really_atomic_lvalue (exp.value)) { vec<tree, va_gc> *params; @@ -2567,16 +2571,6 @@ ref = build1 (INDIRECT_REF, t, pointer); - if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE) - { - if (!C_TYPE_ERROR_REPORTED (TREE_TYPE (ptr))) - { - error_at (loc, "dereferencing pointer to incomplete type " - "%qT", t); - C_TYPE_ERROR_REPORTED (TREE_TYPE (ptr)) = 1; - } - return error_mark_node; - } if (VOID_TYPE_P (t) && c_inhibit_evaluation_warnings == 0) warning_at (loc, 0, "dereferencing %<void *%> pointer"); @@ -2627,7 +2621,7 @@ if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE /* Allow vector[index] but not index[vector]. */ - && !VECTOR_TYPE_P (TREE_TYPE (array))) + && !gnu_vector_type_p (TREE_TYPE (array))) { if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE) @@ -3024,6 +3018,8 @@ } /* Build a function call to function FUNCTION with parameters PARAMS. + If FUNCTION is the result of resolving an overloaded target built-in, + ORIG_FUNDECL is the original function decl, otherwise it is null. ORIGTYPES, if not NULL, is a vector of types; each element is either NULL or the original type of the corresponding element in PARAMS. The original type may differ from TREE_TYPE of the @@ -3034,7 +3030,7 @@ tree build_function_call_vec (location_t loc, vec<location_t> arg_loc, tree function, vec<tree, va_gc> *params, - vec<tree, va_gc> *origtypes) + vec<tree, va_gc> *origtypes, tree orig_fundecl) { tree fntype, fundecl = NULL_TREE; tree name = NULL_TREE, result; @@ -3054,6 +3050,8 @@ if (flag_tm) tm_malloc_replacement (function); fundecl = function; + if (!orig_fundecl) + orig_fundecl = fundecl; /* Atomic functions have type checking/casting already done. They are often rewritten and don't match the original parameter list. */ if (name && !strncmp (IDENTIFIER_POINTER (name), "__atomic_", 9)) @@ -3131,9 +3129,10 @@ argarray = vec_safe_address (params); /* Check that arguments to builtin functions match the expectations. */ - if (fundecl && fndecl_built_in_p (fundecl, BUILT_IN_NORMAL) - && !check_builtin_function_arguments (loc, arg_loc, fundecl, nargs, - argarray)) + if (fundecl + && fndecl_built_in_p (fundecl) + && !check_builtin_function_arguments (loc, arg_loc, fundecl, + orig_fundecl, nargs, argarray)) return error_mark_node; /* Check that the arguments to the function are valid. */ @@ -3206,6 +3205,193 @@ return build_function_call_vec (loc, arg_loc, function, params, origtypes); } +/* Helper for convert_arguments called to convert the VALue of argument + number ARGNUM from ORIGTYPE to the corresponding parameter number + PARMNUM and TYPE. + PLOC is the location where the conversion is being performed. + FUNCTION and FUNDECL are the same as in convert_arguments. + VALTYPE is the original type of VAL before the conversion and, + for EXCESS_PRECISION_EXPR, the operand of the expression. + NPC is true if VAL represents the null pointer constant (VAL itself + will have been folded to an integer constant). + RNAME is the same as FUNCTION except in Objective C when it's + the function selector. + EXCESS_PRECISION is true when VAL was originally represented + as EXCESS_PRECISION_EXPR. + WARNOPT is the same as in convert_for_assignment. */ + +static tree +convert_argument (location_t ploc, tree function, tree fundecl, + tree type, tree origtype, tree val, tree valtype, + bool npc, tree rname, int parmnum, int argnum, + bool excess_precision, int warnopt) +{ + /* Formal parm type is specified by a function prototype. */ + + if (type == error_mark_node || !COMPLETE_TYPE_P (type)) + { + error_at (ploc, "type of formal parameter %d is incomplete", + parmnum + 1); + return val; + } + + /* Optionally warn about conversions that differ from the default + conversions. */ + if (warn_traditional_conversion || warn_traditional) + { + unsigned int formal_prec = TYPE_PRECISION (type); + + if (INTEGRAL_TYPE_P (type) + && TREE_CODE (valtype) == REAL_TYPE) + warning_at (ploc, OPT_Wtraditional_conversion, + "passing argument %d of %qE as integer rather " + "than floating due to prototype", + argnum, rname); + if (INTEGRAL_TYPE_P (type) + && TREE_CODE (valtype) == COMPLEX_TYPE) + warning_at (ploc, OPT_Wtraditional_conversion, + "passing argument %d of %qE as integer rather " + "than complex due to prototype", + argnum, rname); + else if (TREE_CODE (type) == COMPLEX_TYPE + && TREE_CODE (valtype) == REAL_TYPE) + warning_at (ploc, OPT_Wtraditional_conversion, + "passing argument %d of %qE as complex rather " + "than floating due to prototype", + argnum, rname); + else if (TREE_CODE (type) == REAL_TYPE + && INTEGRAL_TYPE_P (valtype)) + warning_at (ploc, OPT_Wtraditional_conversion, + "passing argument %d of %qE as floating rather " + "than integer due to prototype", + argnum, rname); + else if (TREE_CODE (type) == COMPLEX_TYPE + && INTEGRAL_TYPE_P (valtype)) + warning_at (ploc, OPT_Wtraditional_conversion, + "passing argument %d of %qE as complex rather " + "than integer due to prototype", + argnum, rname); + else if (TREE_CODE (type) == REAL_TYPE + && TREE_CODE (valtype) == COMPLEX_TYPE) + warning_at (ploc, OPT_Wtraditional_conversion, + "passing argument %d of %qE as floating rather " + "than complex due to prototype", + argnum, rname); + /* ??? At some point, messages should be written about + conversions between complex types, but that's too messy + to do now. */ + else if (TREE_CODE (type) == REAL_TYPE + && TREE_CODE (valtype) == REAL_TYPE) + { + /* Warn if any argument is passed as `float', + since without a prototype it would be `double'. */ + if (formal_prec == TYPE_PRECISION (float_type_node) + && type != dfloat32_type_node) + warning_at (ploc, 0, + "passing argument %d of %qE as %<float%> " + "rather than %<double%> due to prototype", + argnum, rname); + + /* Warn if mismatch between argument and prototype + for decimal float types. Warn of conversions with + binary float types and of precision narrowing due to + prototype. */ + else if (type != valtype + && (type == dfloat32_type_node + || type == dfloat64_type_node + || type == dfloat128_type_node + || valtype == dfloat32_type_node + || valtype == dfloat64_type_node + || valtype == dfloat128_type_node) + && (formal_prec + <= TYPE_PRECISION (valtype) + || (type == dfloat128_type_node + && (valtype + != dfloat64_type_node + && (valtype + != dfloat32_type_node))) + || (type == dfloat64_type_node + && (valtype + != dfloat32_type_node)))) + warning_at (ploc, 0, + "passing argument %d of %qE as %qT " + "rather than %qT due to prototype", + argnum, rname, type, valtype); + + } + /* Detect integer changing in width or signedness. + These warnings are only activated with + -Wtraditional-conversion, not with -Wtraditional. */ + else if (warn_traditional_conversion + && INTEGRAL_TYPE_P (type) + && INTEGRAL_TYPE_P (valtype)) + { + tree would_have_been = default_conversion (val); + tree type1 = TREE_TYPE (would_have_been); + + if (val == error_mark_node) + /* VAL could have been of incomplete type. */; + else if (TREE_CODE (type) == ENUMERAL_TYPE + && (TYPE_MAIN_VARIANT (type) + == TYPE_MAIN_VARIANT (valtype))) + /* No warning if function asks for enum + and the actual arg is that enum type. */ + ; + else if (formal_prec != TYPE_PRECISION (type1)) + warning_at (ploc, OPT_Wtraditional_conversion, + "passing argument %d of %qE " + "with different width due to prototype", + argnum, rname); + else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1)) + ; + /* Don't complain if the formal parameter type + is an enum, because we can't tell now whether + the value was an enum--even the same enum. */ + else if (TREE_CODE (type) == ENUMERAL_TYPE) + ; + else if (TREE_CODE (val) == INTEGER_CST + && int_fits_type_p (val, type)) + /* Change in signedness doesn't matter + if a constant value is unaffected. */ + ; + /* If the value is extended from a narrower + unsigned type, it doesn't matter whether we + pass it as signed or unsigned; the value + certainly is the same either way. */ + else if (TYPE_PRECISION (valtype) < TYPE_PRECISION (type) + && TYPE_UNSIGNED (valtype)) + ; + else if (TYPE_UNSIGNED (type)) + warning_at (ploc, OPT_Wtraditional_conversion, + "passing argument %d of %qE " + "as unsigned due to prototype", + argnum, rname); + else + warning_at (ploc, OPT_Wtraditional_conversion, + "passing argument %d of %qE " + "as signed due to prototype", + argnum, rname); + } + } + + /* Possibly restore an EXCESS_PRECISION_EXPR for the + sake of better warnings from convert_and_check. */ + if (excess_precision) + val = build1 (EXCESS_PRECISION_EXPR, valtype, val); + + tree parmval = convert_for_assignment (ploc, ploc, type, + val, origtype, ic_argpass, + npc, fundecl, function, + parmnum + 1, warnopt); + + if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) : 0) + && INTEGRAL_TYPE_P (type) + && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) + parmval = default_conversion (parmval); + + return parmval; +} + /* Convert the argument expressions in the vector VALUES to the types in the list TYPELIST. @@ -3232,7 +3418,6 @@ vec<tree, va_gc> *values, vec<tree, va_gc> *origtypes, tree function, tree fundecl) { - tree typetail, val; unsigned int parmnum; bool error_args = false; const bool type_generic = fundecl @@ -3250,50 +3435,81 @@ /* Handle an ObjC selector specially for diagnostics. */ selector = objc_message_selector (); + /* For a call to a built-in function declared without a prototype, + set to the built-in function's argument list. */ + tree builtin_typelist = NULL_TREE; + /* For type-generic built-in functions, determine whether excess precision should be removed (classification) or not (comparison). */ - if (type_generic + if (fundecl && fndecl_built_in_p (fundecl, BUILT_IN_NORMAL)) { - switch (DECL_FUNCTION_CODE (fundecl)) - { - case BUILT_IN_ISFINITE: - case BUILT_IN_ISINF: - case BUILT_IN_ISINF_SIGN: - case BUILT_IN_ISNAN: - case BUILT_IN_ISNORMAL: - case BUILT_IN_FPCLASSIFY: - type_generic_remove_excess_precision = true; - break; - - case BUILT_IN_ADD_OVERFLOW_P: - case BUILT_IN_SUB_OVERFLOW_P: - case BUILT_IN_MUL_OVERFLOW_P: - /* The last argument of these type-generic builtins - should not be promoted. */ - type_generic_overflow_p = true; - break; - - default: - break; - } - } - - /* Scan the given expressions and types, producing individual - converted arguments. */ - - for (typetail = typelist, parmnum = 0; + built_in_function code = DECL_FUNCTION_CODE (fundecl); + if (C_DECL_BUILTIN_PROTOTYPE (fundecl)) + { + /* For a call to a built-in function declared without a prototype + use the types of the parameters of the internal built-in to + match those of the arguments to. */ + if (tree bdecl = builtin_decl_explicit (code)) + builtin_typelist = TYPE_ARG_TYPES (TREE_TYPE (bdecl)); + } + + /* For type-generic built-in functions, determine whether excess + precision should be removed (classification) or not + (comparison). */ + if (type_generic) + switch (code) + { + case BUILT_IN_ISFINITE: + case BUILT_IN_ISINF: + case BUILT_IN_ISINF_SIGN: + case BUILT_IN_ISNAN: + case BUILT_IN_ISNORMAL: + case BUILT_IN_FPCLASSIFY: + type_generic_remove_excess_precision = true; + break; + + case BUILT_IN_ADD_OVERFLOW_P: + case BUILT_IN_SUB_OVERFLOW_P: + case BUILT_IN_MUL_OVERFLOW_P: + /* The last argument of these type-generic builtins + should not be promoted. */ + type_generic_overflow_p = true; + break; + + default: + break; + } + } + + /* Scan the given expressions (VALUES) and types (TYPELIST), producing + individual converted arguments. */ + + tree typetail, builtin_typetail, val; + for (typetail = typelist, + builtin_typetail = builtin_typelist, + parmnum = 0; values && values->iterate (parmnum, &val); ++parmnum) { - tree type = typetail ? TREE_VALUE (typetail) : 0; + /* The type of the function parameter (if it was declared with one). */ + tree type = typetail ? TREE_VALUE (typetail) : NULL_TREE; + /* The type of the built-in function parameter (if the function + is a built-in). Used to detect type incompatibilities in + calls to built-ins declared without a prototype. */ + tree builtin_type = (builtin_typetail + ? TREE_VALUE (builtin_typetail) : NULL_TREE); + /* The original type of the argument being passed to the function. */ tree valtype = TREE_TYPE (val); + /* The called function (or function selector in Objective C). */ tree rname = function; int argnum = parmnum + 1; const char *invalid_func_diag; + /* Set for EXCESS_PRECISION_EXPR arguments. */ bool excess_precision = false; - bool npc; + /* The value of the argument after conversion to the type + of the function parameter it is passed to. */ tree parmval; /* Some __atomic_* builtins have additional hidden argument at position 0. */ @@ -3312,13 +3528,23 @@ return error_args ? -1 : (int) parmnum; } + if (builtin_type == void_type_node) + { + if (warning_at (loc, OPT_Wbuiltin_declaration_mismatch, + "too many arguments to built-in function %qE " + "expecting %d", function, parmnum)) + inform_declaration (fundecl); + builtin_typetail = NULL_TREE; + } + if (selector && argnum > 2) { rname = selector; argnum -= 2; } - npc = null_pointer_constant_p (val); + /* Determine if VAL is a null pointer constant before folding it. */ + bool npc = null_pointer_constant_p (val); /* If there is excess precision and a prototype, convert once to the required type rather than converting via the semantic @@ -3363,172 +3589,10 @@ if (type != NULL_TREE) { - /* Formal parm type is specified by a function prototype. */ - - if (type == error_mark_node || !COMPLETE_TYPE_P (type)) - { - error_at (ploc, "type of formal parameter %d is incomplete", - parmnum + 1); - parmval = val; - } - else - { - tree origtype; - - /* Optionally warn about conversions that - differ from the default conversions. */ - if (warn_traditional_conversion || warn_traditional) - { - unsigned int formal_prec = TYPE_PRECISION (type); - - if (INTEGRAL_TYPE_P (type) - && TREE_CODE (valtype) == REAL_TYPE) - warning_at (ploc, OPT_Wtraditional_conversion, - "passing argument %d of %qE as integer rather " - "than floating due to prototype", - argnum, rname); - if (INTEGRAL_TYPE_P (type) - && TREE_CODE (valtype) == COMPLEX_TYPE) - warning_at (ploc, OPT_Wtraditional_conversion, - "passing argument %d of %qE as integer rather " - "than complex due to prototype", - argnum, rname); - else if (TREE_CODE (type) == COMPLEX_TYPE - && TREE_CODE (valtype) == REAL_TYPE) - warning_at (ploc, OPT_Wtraditional_conversion, - "passing argument %d of %qE as complex rather " - "than floating due to prototype", - argnum, rname); - else if (TREE_CODE (type) == REAL_TYPE - && INTEGRAL_TYPE_P (valtype)) - warning_at (ploc, OPT_Wtraditional_conversion, - "passing argument %d of %qE as floating rather " - "than integer due to prototype", - argnum, rname); - else if (TREE_CODE (type) == COMPLEX_TYPE - && INTEGRAL_TYPE_P (valtype)) - warning_at (ploc, OPT_Wtraditional_conversion, - "passing argument %d of %qE as complex rather " - "than integer due to prototype", - argnum, rname); - else if (TREE_CODE (type) == REAL_TYPE - && TREE_CODE (valtype) == COMPLEX_TYPE) - warning_at (ploc, OPT_Wtraditional_conversion, - "passing argument %d of %qE as floating rather " - "than complex due to prototype", - argnum, rname); - /* ??? At some point, messages should be written about - conversions between complex types, but that's too messy - to do now. */ - else if (TREE_CODE (type) == REAL_TYPE - && TREE_CODE (valtype) == REAL_TYPE) - { - /* Warn if any argument is passed as `float', - since without a prototype it would be `double'. */ - if (formal_prec == TYPE_PRECISION (float_type_node) - && type != dfloat32_type_node) - warning_at (ploc, 0, - "passing argument %d of %qE as %<float%> " - "rather than %<double%> due to prototype", - argnum, rname); - - /* Warn if mismatch between argument and prototype - for decimal float types. Warn of conversions with - binary float types and of precision narrowing due to - prototype. */ - else if (type != valtype - && (type == dfloat32_type_node - || type == dfloat64_type_node - || type == dfloat128_type_node - || valtype == dfloat32_type_node - || valtype == dfloat64_type_node - || valtype == dfloat128_type_node) - && (formal_prec - <= TYPE_PRECISION (valtype) - || (type == dfloat128_type_node - && (valtype - != dfloat64_type_node - && (valtype - != dfloat32_type_node))) - || (type == dfloat64_type_node - && (valtype - != dfloat32_type_node)))) - warning_at (ploc, 0, - "passing argument %d of %qE as %qT " - "rather than %qT due to prototype", - argnum, rname, type, valtype); - - } - /* Detect integer changing in width or signedness. - These warnings are only activated with - -Wtraditional-conversion, not with -Wtraditional. */ - else if (warn_traditional_conversion - && INTEGRAL_TYPE_P (type) - && INTEGRAL_TYPE_P (valtype)) - { - tree would_have_been = default_conversion (val); - tree type1 = TREE_TYPE (would_have_been); - - if (val == error_mark_node) - /* VAL could have been of incomplete type. */; - else if (TREE_CODE (type) == ENUMERAL_TYPE - && (TYPE_MAIN_VARIANT (type) - == TYPE_MAIN_VARIANT (valtype))) - /* No warning if function asks for enum - and the actual arg is that enum type. */ - ; - else if (formal_prec != TYPE_PRECISION (type1)) - warning_at (ploc, OPT_Wtraditional_conversion, - "passing argument %d of %qE " - "with different width due to prototype", - argnum, rname); - else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1)) - ; - /* Don't complain if the formal parameter type - is an enum, because we can't tell now whether - the value was an enum--even the same enum. */ - else if (TREE_CODE (type) == ENUMERAL_TYPE) - ; - else if (TREE_CODE (val) == INTEGER_CST - && int_fits_type_p (val, type)) - /* Change in signedness doesn't matter - if a constant value is unaffected. */ - ; - /* If the value is extended from a narrower - unsigned type, it doesn't matter whether we - pass it as signed or unsigned; the value - certainly is the same either way. */ - else if (TYPE_PRECISION (valtype) < TYPE_PRECISION (type) - && TYPE_UNSIGNED (valtype)) - ; - else if (TYPE_UNSIGNED (type)) - warning_at (ploc, OPT_Wtraditional_conversion, - "passing argument %d of %qE " - "as unsigned due to prototype", - argnum, rname); - else - warning_at (ploc, OPT_Wtraditional_conversion, - "passing argument %d of %qE " - "as signed due to prototype", - argnum, rname); - } - } - - /* Possibly restore an EXCESS_PRECISION_EXPR for the - sake of better warnings from convert_and_check. */ - if (excess_precision) - val = build1 (EXCESS_PRECISION_EXPR, valtype, val); - origtype = (!origtypes) ? NULL_TREE : (*origtypes)[parmnum]; - parmval = convert_for_assignment (loc, ploc, type, - val, origtype, ic_argpass, - npc, fundecl, function, - parmnum + 1); - - if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) : 0) - && INTEGRAL_TYPE_P (type) - && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) - parmval = default_conversion (parmval); - } + tree origtype = (!origtypes) ? NULL_TREE : (*origtypes)[parmnum]; + parmval = convert_argument (ploc, function, fundecl, type, origtype, + val, valtype, npc, rname, parmnum, argnum, + excess_precision, 0); } else if (promote_float_arg) { @@ -3570,8 +3634,25 @@ if (parmval == error_mark_node) error_args = true; + if (!type && builtin_type && TREE_CODE (builtin_type) != VOID_TYPE) + { + /* For a call to a built-in function declared without a prototype, + perform the conversions from the argument to the expected type + but issue warnings rather than errors for any mismatches. + Ignore the converted argument and use the PARMVAL obtained + above by applying default conversions instead. */ + tree origtype = (!origtypes) ? NULL_TREE : (*origtypes)[parmnum]; + convert_argument (ploc, function, fundecl, builtin_type, origtype, + val, valtype, npc, rname, parmnum, argnum, + excess_precision, + OPT_Wbuiltin_declaration_mismatch); + } + if (typetail) typetail = TREE_CHAIN (typetail); + + if (builtin_typetail) + builtin_typetail = TREE_CHAIN (builtin_typetail); } gcc_assert (parmnum == vec_safe_length (values)); @@ -3588,6 +3669,18 @@ return -1; } + if (builtin_typetail && TREE_VALUE (builtin_typetail) != void_type_node) + { + unsigned nargs = parmnum; + for (tree t = builtin_typetail; t; t = TREE_CHAIN (t)) + ++nargs; + + if (warning_at (loc, OPT_Wbuiltin_declaration_mismatch, + "too few arguments to built-in function %qE " + "expecting %u", function, nargs - 1)) + inform_declaration (fundecl); + } + return error_args ? -1 : (int) parmnum; } @@ -3819,6 +3912,7 @@ addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op0))); addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op1))); tree target_type = TREE_TYPE (TREE_TYPE (op0)); + tree orig_op0 = op0; tree orig_op1 = op1; /* If the operands point into different address spaces, we need to @@ -3889,6 +3983,10 @@ /* This generates an error if op1 is pointer to incomplete type. */ if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1)))) error_at (loc, "arithmetic on pointer to an incomplete type"); + else if (verify_type_context (loc, TCTX_POINTER_ARITH, + TREE_TYPE (TREE_TYPE (orig_op0)))) + verify_type_context (loc, TCTX_POINTER_ARITH, + TREE_TYPE (TREE_TYPE (orig_op1))); op1 = c_size_in_bytes (target_type); @@ -4287,7 +4385,7 @@ associativity, but won't generate any code. */ if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE || typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE - || typecode == VECTOR_TYPE)) + || gnu_vector_type_p (TREE_TYPE (arg)))) { error_at (location, "wrong type argument to unary plus"); return error_mark_node; @@ -4300,7 +4398,7 @@ case NEGATE_EXPR: if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE || typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE - || typecode == VECTOR_TYPE)) + || gnu_vector_type_p (TREE_TYPE (arg)))) { error_at (location, "wrong type argument to unary minus"); return error_mark_node; @@ -4312,7 +4410,7 @@ case BIT_NOT_EXPR: /* ~ works on integer types and non float vectors. */ if (typecode == INTEGER_TYPE - || (typecode == VECTOR_TYPE + || (gnu_vector_type_p (TREE_TYPE (arg)) && !VECTOR_FLOAT_TYPE_P (TREE_TYPE (arg)))) { tree e = arg; @@ -4498,7 +4596,8 @@ if (typecode != POINTER_TYPE && typecode != FIXED_POINT_TYPE && typecode != INTEGER_TYPE && typecode != REAL_TYPE - && typecode != COMPLEX_TYPE && typecode != VECTOR_TYPE) + && typecode != COMPLEX_TYPE + && !gnu_vector_type_p (TREE_TYPE (arg))) { if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) error_at (location, "wrong type argument to increment"); @@ -4540,6 +4639,9 @@ pedwarn (location, OPT_Wpointer_arith, "wrong type argument to decrement"); } + else + verify_type_context (location, TCTX_POINTER_ARITH, + TREE_TYPE (argtype)); inc = c_size_in_bytes (TREE_TYPE (argtype)); inc = convert_to_ptrofftype_loc (location, inc); @@ -4950,6 +5052,40 @@ return convert (type, expr); } +/* If EXPR refers to a built-in declared without a prototype returns + the actual type of the built-in and, if non-null, set *BLTIN to + a pointer to the built-in. Otherwise return the type of EXPR + and clear *BLTIN if non-null. */ + +static tree +type_or_builtin_type (tree expr, tree *bltin = NULL) +{ + tree dummy; + if (!bltin) + bltin = &dummy; + + *bltin = NULL_TREE; + + tree type = TREE_TYPE (expr); + if (TREE_CODE (expr) != ADDR_EXPR) + return type; + + tree oper = TREE_OPERAND (expr, 0); + if (!DECL_P (oper) + || TREE_CODE (oper) != FUNCTION_DECL + || !fndecl_built_in_p (oper, BUILT_IN_NORMAL)) + return type; + + built_in_function code = DECL_FUNCTION_CODE (oper); + if (!C_DECL_BUILTIN_PROTOTYPE (oper)) + return type; + + if ((*bltin = builtin_decl_implicit (code))) + type = build_pointer_type (TREE_TYPE (*bltin)); + + return type; +} + /* Build and return a conditional expression IFEXP ? OP1 : OP2. If IFEXP_BCP then the condition is a call to __builtin_constant_p, and if folded to an integer constant then the unselected half may @@ -4994,9 +5130,11 @@ || TREE_CODE (TREE_TYPE (op2)) == ERROR_MARK) return error_mark_node; - type1 = TREE_TYPE (op1); + tree bltin1 = NULL_TREE; + tree bltin2 = NULL_TREE; + type1 = type_or_builtin_type (op1, &bltin1); code1 = TREE_CODE (type1); - type2 = TREE_TYPE (op2); + type2 = type_or_builtin_type (op2, &bltin2); code2 = TREE_CODE (type2); if (code1 == POINTER_TYPE && reject_gcc_builtin (op1)) @@ -5150,13 +5288,13 @@ /* OK */; else if (unsigned_op2) warning_at (op1_loc, OPT_Wsign_compare, - "operand of ?: changes signedness from " + "operand of %<?:%> changes signedness from " "%qT to %qT due to unsignedness of other " "operand", TREE_TYPE (orig_op1), TREE_TYPE (orig_op2)); else warning_at (op2_loc, OPT_Wsign_compare, - "operand of ?: changes signedness from " + "operand of %<?:%> changes signedness from " "%qT to %qT due to unsignedness of other " "operand", TREE_TYPE (orig_op2), TREE_TYPE (orig_op1)); @@ -5234,9 +5372,14 @@ else { int qual = ENCODE_QUAL_ADDR_SPACE (as_common); - - pedwarn (colon_loc, 0, - "pointer type mismatch in conditional expression"); + if (bltin1 && bltin2) + warning_at (colon_loc, OPT_Wincompatible_pointer_types, + "pointer type mismatch between %qT and %qT " + "of %qD and %qD in conditional expression", + type1, type2, bltin1, bltin2); + else + pedwarn (colon_loc, 0, + "pointer type mismatch in conditional expression"); result_type = build_pointer_type (build_qualified_type (void_type_node, qual)); } @@ -5316,7 +5459,7 @@ tree elem_type = TREE_TYPE (vectype); tree zero = build_int_cst (elem_type, 0); tree zero_vec = build_vector_from_val (vectype, zero); - tree cmp_type = build_same_sized_truth_vector_type (vectype); + tree cmp_type = truth_type_for (vectype); ifexp = build2 (NE_EXPR, cmp_type, ifexp, zero_vec); } @@ -5594,10 +5737,14 @@ { tree value; + bool int_operands = EXPR_INT_CONST_OPERANDS (expr); + if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR) expr = TREE_OPERAND (expr, 0); value = expr; + if (int_operands) + value = remove_c_maybe_const_expr (value); if (type == error_mark_node || expr == error_mark_node) return error_mark_node; @@ -5828,6 +5975,14 @@ || TREE_CODE (expr) == COMPLEX_CST))) value = build1 (NOP_EXPR, type, value); + /* If the expression has integer operands and so can occur in an + unevaluated part of an integer constant expression, ensure the + return value reflects this. */ + if (int_operands + && INTEGRAL_TYPE_P (type) + && !EXPR_INT_CONST_OPERANDS (value)) + value = note_integer_operands (value); + protected_set_expr_location (value, loc); return value; } @@ -6229,17 +6384,21 @@ GMSGID identifies the message. The component name is taken from the spelling stack. */ -static void -error_init (location_t loc, const char *gmsgid) +static void ATTRIBUTE_GCC_DIAG (2,0) +error_init (location_t loc, const char *gmsgid, ...) { char *ofwhat; auto_diagnostic_group d; /* The gmsgid may be a format string with %< and %>. */ - error_at (loc, gmsgid); + va_list ap; + va_start (ap, gmsgid); + bool warned = emit_diagnostic_valist (DK_ERROR, loc, -1, gmsgid, &ap); + va_end (ap); + ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); - if (*ofwhat) + if (*ofwhat && warned) inform (loc, "(near initialization for %qs)", ofwhat); } @@ -6254,7 +6413,7 @@ /* Use the location where a macro was expanded rather than where it was defined to make sure macros defined in system headers but used incorrectly elsewhere are diagnosed. */ - source_location exploc = expansion_point_location_if_in_system_header (loc); + location_t exploc = expansion_point_location_if_in_system_header (loc); auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -6282,7 +6441,7 @@ /* Use the location where a macro was expanded rather than where it was defined to make sure macros defined in system headers but used incorrectly elsewhere are diagnosed. */ - source_location exploc = expansion_point_location_if_in_system_header (loc); + location_t exploc = expansion_point_location_if_in_system_header (loc); /* The gmsgid may be a format string with %< and %>. */ warned = warning_at (exploc, opt, gmsgid); @@ -6350,6 +6509,48 @@ expected_type, actual_type); } +/* Issue a warning when an argument of ARGTYPE is passed to a built-in + function FUNDECL declared without prototype to parameter PARMNUM of + PARMTYPE when ARGTYPE does not promote to PARMTYPE. */ + +static void +maybe_warn_builtin_no_proto_arg (location_t loc, tree fundecl, int parmnum, + tree parmtype, tree argtype) +{ + tree_code parmcode = TREE_CODE (parmtype); + tree_code argcode = TREE_CODE (argtype); + tree promoted = c_type_promotes_to (argtype); + + /* Avoid warning for enum arguments that promote to an integer type + of the same size/mode. */ + if (parmcode == INTEGER_TYPE + && argcode == ENUMERAL_TYPE + && TYPE_MODE (parmtype) == TYPE_MODE (argtype)) + return; + + if ((parmcode == argcode + || (parmcode == INTEGER_TYPE + && argcode == ENUMERAL_TYPE)) + && TYPE_MAIN_VARIANT (parmtype) == TYPE_MAIN_VARIANT (promoted)) + return; + + /* This diagnoses even signed/unsigned mismatches. Those might be + safe in many cases but GCC may emit suboptimal code for them so + warning on those cases drives efficiency improvements. */ + if (warning_at (loc, OPT_Wbuiltin_declaration_mismatch, + TYPE_MAIN_VARIANT (promoted) == argtype + ? G_("%qD argument %d type is %qT where %qT is expected " + "in a call to built-in function declared without " + "prototype") + : G_("%qD argument %d promotes to %qT where %qT is expected " + "in a call to built-in function declared without " + "prototype"), + fundecl, parmnum, promoted, parmtype)) + inform (DECL_SOURCE_LOCATION (fundecl), + "built-in %qD declared here", + fundecl); +} + /* Convert value RHS to type TYPE as preparation for an assignment to an lvalue of type TYPE. If ORIGTYPE is not NULL_TREE, it is the original type of RHS; this differs from TREE_TYPE (RHS) for enum @@ -6374,13 +6575,16 @@ ^ FUNCTION is a tree for the function being called. - PARMNUM is the number of the argument, for printing in error messages. */ + PARMNUM is the number of the argument, for printing in error messages. + WARNOPT may be set to a warning option to issue the corresponding warning + rather than an error for invalid conversions. Used for calls to built-in + functions declared without a prototype. */ static tree convert_for_assignment (location_t location, location_t expr_loc, tree type, tree rhs, tree origtype, enum impl_conv errtype, bool null_pointer_constant, tree fundecl, - tree function, int parmnum) + tree function, int parmnum, int warnopt /* = 0 */) { enum tree_code codel = TREE_CODE (type); tree orig_rhs = rhs; @@ -6568,8 +6772,26 @@ } } + if (warn_enum_conversion) + { + tree checktype = origtype != NULL_TREE ? origtype : rhstype; + if (checktype != error_mark_node + && TREE_CODE (checktype) == ENUMERAL_TYPE + && TREE_CODE (type) == ENUMERAL_TYPE + && TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (type)) + { + gcc_rich_location loc (location); + warning_at (&loc, OPT_Wenum_conversion, + "implicit conversion from %qT to %qT", + checktype, type); + } + } + if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)) - return rhs; + { + warn_for_address_or_pointer_of_packed_member (type, orig_rhs); + return rhs; + } if (coder == VOID_TYPE) { @@ -6578,7 +6800,11 @@ an unprototyped function, it is compile-time undefined; making it a constraint in that case was rejected in DR#252. */ - error_at (location, "void value not ignored as it ought to be"); + const char msg[] = "void value not ignored as it ought to be"; + if (warnopt) + warning_at (location, warnopt, msg); + else + error_at (location, msg); return error_mark_node; } rhs = require_complete_type (location, rhs); @@ -6594,7 +6820,11 @@ { if (!lvalue_p (rhs)) { - error_at (location, "cannot pass rvalue to reference parameter"); + const char msg[] = "cannot pass rvalue to reference parameter"; + if (warnopt) + warning_at (location, warnopt, msg); + else + error_at (location, msg); return error_mark_node; } if (!c_mark_addressable (rhs)) @@ -6606,7 +6836,7 @@ build_pointer_type (TREE_TYPE (type)), rhs, origtype, errtype, null_pointer_constant, fundecl, function, - parmnum); + parmnum, warnopt); if (rhs == error_mark_node) return error_mark_node; @@ -6628,15 +6858,18 @@ || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE || coder == BOOLEAN_TYPE)) { - tree ret; + if (warnopt && errtype == ic_argpass) + maybe_warn_builtin_no_proto_arg (expr_loc, fundecl, parmnum, type, + rhstype); + bool save = in_late_binary_op; if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE || (coder == REAL_TYPE && (codel == INTEGER_TYPE || codel == ENUMERAL_TYPE) && sanitize_flags_p (SANITIZE_FLOAT_CAST))) in_late_binary_op = true; - ret = convert_and_check (expr_loc != UNKNOWN_LOCATION - ? expr_loc : location, type, orig_rhs); + tree ret = convert_and_check (expr_loc != UNKNOWN_LOCATION + ? expr_loc : location, type, orig_rhs); in_late_binary_op = save; return ret; } @@ -6770,6 +7003,12 @@ else if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE) && (coder == codel)) { + /* If RHS refers to a built-in declared without a prototype + BLTIN is the declaration of the built-in with a prototype + and RHSTYPE is set to the actual type of the built-in. */ + tree bltin; + rhstype = type_or_builtin_type (rhs, &bltin); + tree ttl = TREE_TYPE (type); tree ttr = TREE_TYPE (rhstype); tree mvl = ttl; @@ -6833,21 +7072,45 @@ switch (errtype) { case ic_argpass: - error_at (expr_loc, "passing argument %d of %qE from pointer to " - "non-enclosed address space", parmnum, rname); + { + const char msg[] = G_("passing argument %d of %qE from " + "pointer to non-enclosed address space"); + if (warnopt) + warning_at (expr_loc, warnopt, msg, parmnum, rname); + else + error_at (expr_loc, msg, parmnum, rname); break; + } case ic_assign: - error_at (location, "assignment from pointer to " - "non-enclosed address space"); - break; + { + const char msg[] = G_("assignment from pointer to " + "non-enclosed address space"); + if (warnopt) + warning_at (location, warnopt, msg); + else + error_at (location, msg); + break; + } case ic_init: - error_at (location, "initialization from pointer to " - "non-enclosed address space"); - break; + { + const char msg[] = G_("initialization from pointer to " + "non-enclosed address space"); + if (warnopt) + warning_at (location, warnopt, msg); + else + error_at (location, msg); + break; + } case ic_return: - error_at (location, "return from pointer to " - "non-enclosed address space"); - break; + { + const char msg[] = G_("return from pointer to " + "non-enclosed address space"); + if (warnopt) + warning_at (location, warnopt, msg); + else + error_at (location, msg); + break; + } default: gcc_unreachable (); } @@ -7045,32 +7308,59 @@ } break; case ic_assign: - pedwarn (location, OPT_Wincompatible_pointer_types, - "assignment to %qT from incompatible pointer type %qT", - type, rhstype); + if (bltin) + pedwarn (location, OPT_Wincompatible_pointer_types, + "assignment to %qT from pointer to " + "%qD with incompatible type %qT", + type, bltin, rhstype); + else + pedwarn (location, OPT_Wincompatible_pointer_types, + "assignment to %qT from incompatible pointer type %qT", + type, rhstype); break; case ic_init: - pedwarn_init (location, OPT_Wincompatible_pointer_types, - "initialization of %qT from incompatible pointer " - "type %qT", type, rhstype); + if (bltin) + pedwarn_init (location, OPT_Wincompatible_pointer_types, + "initialization of %qT from pointer to " + "%qD with incompatible type %qT", + type, bltin, rhstype); + else + pedwarn_init (location, OPT_Wincompatible_pointer_types, + "initialization of %qT from incompatible " + "pointer type %qT", + type, rhstype); break; case ic_return: - pedwarn (location, OPT_Wincompatible_pointer_types, - "returning %qT from a function with incompatible " - "return type %qT", rhstype, type); + if (bltin) + pedwarn (location, OPT_Wincompatible_pointer_types, + "returning pointer to %qD of type %qT from " + "a function with incompatible type %qT", + bltin, rhstype, type); + else + pedwarn (location, OPT_Wincompatible_pointer_types, + "returning %qT from a function with incompatible " + "return type %qT", rhstype, type); break; default: gcc_unreachable (); } } + /* If RHS isn't an address, check pointer or array of packed + struct or union. */ + warn_for_address_or_pointer_of_packed_member (type, orig_rhs); + return convert (type, rhs); } else if (codel == POINTER_TYPE && coder == ARRAY_TYPE) { /* ??? This should not be an error when inlining calls to unprototyped functions. */ - error_at (location, "invalid use of non-lvalue array"); + const char msg[] = "invalid use of non-lvalue array"; + if (warnopt) + warning_at (location, warnopt, msg); + else + error_at (location, msg); return error_mark_node; } else if (codel == POINTER_TYPE && coder == INTEGER_TYPE) @@ -7166,25 +7456,44 @@ auto_diagnostic_group d; range_label_for_type_mismatch rhs_label (rhstype, type); gcc_rich_location richloc (expr_loc, &rhs_label); - error_at (&richloc, "incompatible type for argument %d of %qE", parmnum, - rname); + const char msg[] = G_("incompatible type for argument %d of %qE"); + if (warnopt) + warning_at (expr_loc, warnopt, msg, parmnum, rname); + else + error_at (&richloc, msg, parmnum, rname); inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype); } break; case ic_assign: - error_at (location, "incompatible types when assigning to type %qT from " - "type %qT", type, rhstype); - break; + { + const char msg[] + = G_("incompatible types when assigning to type %qT from type %qT"); + if (warnopt) + warning_at (expr_loc, 0, msg, type, rhstype); + else + error_at (expr_loc, msg, type, rhstype); + break; + } case ic_init: - error_at (location, - "incompatible types when initializing type %qT using type %qT", - type, rhstype); - break; + { + const char msg[] + = G_("incompatible types when initializing type %qT using type %qT"); + if (warnopt) + warning_at (location, 0, msg, type, rhstype); + else + error_at (location, msg, type, rhstype); + break; + } case ic_return: - error_at (location, - "incompatible types when returning type %qT but %qT was " - "expected", rhstype, type); - break; + { + const char msg[] + = G_("incompatible types when returning type %qT but %qT was expected"); + if (warnopt) + warning_at (location, 0, msg, rhstype, type); + else + error_at (location, msg, rhstype, type); + break; + } default: gcc_unreachable (); } @@ -7475,6 +7784,7 @@ { struct c_expr expr; tree typ2 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init))); + bool incompat_string_cst = false; expr.value = inside_init; expr.original_code = (strict_string ? STRING_CST : ERROR_MARK); expr.original_type = NULL; @@ -7491,27 +7801,18 @@ if (char_array) { if (typ2 != char_type_node) - { - error_init (init_loc, "char-array initialized from wide " - "string"); - return error_mark_node; - } - } - else - { - if (typ2 == char_type_node) - { - error_init (init_loc, "wide character array initialized " - "from non-wide string"); - return error_mark_node; - } - else if (!comptypes(typ1, typ2)) - { - error_init (init_loc, "wide character array initialized " - "from incompatible wide string"); - return error_mark_node; - } - } + incompat_string_cst = true; + } + else if (!comptypes (typ1, typ2)) + incompat_string_cst = true; + + if (incompat_string_cst) + { + error_init (init_loc, "cannot initialize array of %qT from " + "a string literal with type array of %qT", + typ1, typ2); + return error_mark_node; + } if (TYPE_DOMAIN (type) != NULL_TREE && TYPE_SIZE (type) != NULL_TREE @@ -7525,13 +7826,13 @@ that is counted in the length of the constant. */ if (compare_tree_int (TYPE_SIZE_UNIT (type), len - unit) < 0) pedwarn_init (init_loc, 0, - ("initializer-string for array of chars " - "is too long")); + ("initializer-string for array of %qT " + "is too long"), typ1); else if (warn_cxx_compat && compare_tree_int (TYPE_SIZE_UNIT (type), len) < 0) warning_at (init_loc, OPT_Wc___compat, - ("initializer-string for array chars " - "is too long for C++")); + ("initializer-string for array of %qT " + "is too long for C++"), typ1); if (compare_tree_int (TYPE_SIZE_UNIT (type), len) < 0) { unsigned HOST_WIDE_INT size @@ -7598,7 +7899,7 @@ TYPE_MAIN_VARIANT (type)) || (code == ARRAY_TYPE && comptypes (TREE_TYPE (inside_init), type)) - || (code == VECTOR_TYPE + || (gnu_vector_type_p (type) && comptypes (TREE_TYPE (inside_init), type)) || (code == POINTER_TYPE && TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE @@ -8096,7 +8397,7 @@ constructor_unfilled_index = constructor_index; } - else if (VECTOR_TYPE_P (constructor_type)) + else if (gnu_vector_type_p (constructor_type)) { /* Vectors are like simple fixed-size arrays. */ constructor_max_index = @@ -8270,7 +8571,7 @@ constructor_unfilled_fields = constructor_fields; constructor_bit_index = bitsize_zero_node; } - else if (VECTOR_TYPE_P (constructor_type)) + else if (gnu_vector_type_p (constructor_type)) { /* Vectors are like simple fixed-size arrays. */ constructor_max_index = @@ -8459,7 +8760,7 @@ ; else if (!RECORD_OR_UNION_TYPE_P (constructor_type) && TREE_CODE (constructor_type) != ARRAY_TYPE - && !VECTOR_TYPE_P (constructor_type)) + && !gnu_vector_type_p (constructor_type)) { /* A nonincremental scalar initializer--just return the element, after verifying there is just one. */ @@ -9649,7 +9950,7 @@ && integer_zerop (constructor_unfilled_index)) { if (constructor_stack->replacement_value.value) - error_init (loc, "excess elements in char array initializer"); + error_init (loc, "excess elements in %<char%> array initializer"); constructor_stack->replacement_value = value; return; } @@ -9685,7 +9986,7 @@ last_init_list_comma), true, braced_init_obstack); else if ((TREE_CODE (constructor_type) == ARRAY_TYPE - || VECTOR_TYPE_P (constructor_type)) + || gnu_vector_type_p (constructor_type)) && constructor_max_index && tree_int_cst_lt (constructor_max_index, constructor_index)) @@ -9786,7 +10087,8 @@ && value.value != error_mark_node && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE - || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE)) + || fieldcode == UNION_TYPE + || gnu_vector_type_p (fieldtype))) { push_init_level (loc, 1, braced_init_obstack); continue; @@ -9877,7 +10179,8 @@ && value.value != error_mark_node && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE - || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE)) + || fieldcode == UNION_TYPE + || gnu_vector_type_p (fieldtype))) { push_init_level (loc, 1, braced_init_obstack); continue; @@ -9919,7 +10222,8 @@ && value.value != error_mark_node && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE - || eltcode == UNION_TYPE || eltcode == VECTOR_TYPE)) + || eltcode == UNION_TYPE + || gnu_vector_type_p (elttype))) { push_init_level (loc, 1, braced_init_obstack); continue; @@ -9955,7 +10259,7 @@ constructor_unfilled_index. */ constructor_unfilled_index = constructor_index; } - else if (VECTOR_TYPE_P (constructor_type)) + else if (gnu_vector_type_p (constructor_type)) { tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type)); @@ -10078,9 +10382,9 @@ (guaranteed to be 'volatile' or null) and ARGS (represented using an ASM_EXPR node). */ tree -build_asm_stmt (tree cv_qualifier, tree args) -{ - if (!ASM_VOLATILE_P (args) && cv_qualifier) +build_asm_stmt (bool is_volatile, tree args) +{ + if (is_volatile) ASM_VOLATILE_P (args) = 1; return add_stmt (args); } @@ -10089,10 +10393,12 @@ some INPUTS, and some CLOBBERS. The latter three may be NULL. SIMPLE indicates whether there was anything at all after the string in the asm expression -- asm("blah") and asm("blah" : ) - are subtly different. We use a ASM_EXPR node to represent this. */ + are subtly different. We use a ASM_EXPR node to represent this. + LOC is the location of the asm, and IS_INLINE says whether this + is asm inline. */ tree build_asm_expr (location_t loc, tree string, tree outputs, tree inputs, - tree clobbers, tree labels, bool simple) + tree clobbers, tree labels, bool simple, bool is_inline) { tree tail; tree args; @@ -10210,6 +10516,7 @@ as volatile. */ ASM_INPUT_P (args) = simple; ASM_VOLATILE_P (args) = (noutputs == 0); + ASM_INLINE_P (args) = is_inline; return args; } @@ -10262,7 +10569,7 @@ /* Use the expansion point to handle cases such as returning NULL in a function returning void. */ - source_location xloc = expansion_point_location_if_in_system_header (loc); + location_t xloc = expansion_point_location_if_in_system_header (loc); if (TREE_THIS_VOLATILE (current_function_decl)) warning_at (xloc, 0, @@ -10385,7 +10692,8 @@ if (DECL_P (inner) && !DECL_EXTERNAL (inner) && !TREE_STATIC (inner) - && DECL_CONTEXT (inner) == current_function_decl) + && DECL_CONTEXT (inner) == current_function_decl + && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))) { if (TREE_CODE (inner) == LABEL_DECL) warning_at (loc, OPT_Wreturn_local_addr, @@ -10444,10 +10752,6 @@ /* Remember whether the controlling expression had boolean type before integer promotions for the sake of -Wswitch-bool. */ bool bool_cond_p; - - /* Remember whether there was a case value that is outside the - range of the ORIG_TYPE. */ - bool outside_range_p; }; /* A stack of the currently active switch statements. The innermost @@ -10524,7 +10828,6 @@ cs->cases = splay_tree_new (case_compare, NULL, NULL); cs->bindings = c_get_switch_bindings (); cs->bool_cond_p = bool_cond_p; - cs->outside_range_p = false; cs->next = c_switch_stack; c_switch_stack = cs; @@ -10570,9 +10873,7 @@ label = c_add_case_label (loc, c_switch_stack->cases, SWITCH_COND (c_switch_stack->switch_expr), - c_switch_stack->orig_type, - low_value, high_value, - &c_switch_stack->outside_range_p); + low_value, high_value); if (label == error_mark_node) label = NULL_TREE; return label; @@ -10593,8 +10894,7 @@ switch_location = EXPR_LOCATION (cs->switch_expr); c_do_switch_warnings (cs->cases, switch_location, type ? type : TREE_TYPE (cs->switch_expr), - SWITCH_COND (cs->switch_expr), - cs->bool_cond_p, cs->outside_range_p); + SWITCH_COND (cs->switch_expr), cs->bool_cond_p); if (c_switch_covers_all_cases_p (cs->cases, TREE_TYPE (cs->switch_expr))) SWITCH_ALL_CASES_P (cs->switch_expr) = 1; @@ -10624,11 +10924,14 @@ the beginning of the loop. COND is the loop condition. COND_IS_FIRST is false for DO loops. INCR is the FOR increment expression. BODY is the statement controlled by the loop. BLAB is the break label. CLAB is - the continue label. Everything is allowed to be NULL. */ + the continue label. Everything is allowed to be NULL. + COND_LOCUS is the location of the loop condition, INCR_LOCUS is the + location of the FOR increment expression. */ void -c_finish_loop (location_t start_locus, tree cond, tree incr, tree body, - tree blab, tree clab, bool cond_is_first) +c_finish_loop (location_t start_locus, location_t cond_locus, tree cond, + location_t incr_locus, tree incr, tree body, tree blab, + tree clab, bool cond_is_first) { tree entry = NULL, exit = NULL, t; @@ -10670,12 +10973,8 @@ } t = build_and_jump (&blab); - if (cond_is_first) - exit = fold_build3_loc (start_locus, - COND_EXPR, void_type_node, cond, exit, t); - else - exit = fold_build3_loc (input_location, - COND_EXPR, void_type_node, cond, exit, t); + exit = fold_build3_loc (cond_is_first ? start_locus : input_location, + COND_EXPR, void_type_node, cond, exit, t); } else { @@ -10696,9 +10995,23 @@ if (clab) add_stmt (build1 (LABEL_EXPR, void_type_node, clab)); if (incr) - add_stmt (incr); + { + if (MAY_HAVE_DEBUG_MARKER_STMTS && incr_locus != UNKNOWN_LOCATION) + { + t = build0 (DEBUG_BEGIN_STMT, void_type_node); + SET_EXPR_LOCATION (t, incr_locus); + add_stmt (t); + } + add_stmt (incr); + } if (entry) add_stmt (entry); + if (MAY_HAVE_DEBUG_MARKER_STMTS && cond_locus != UNKNOWN_LOCATION) + { + t = build0 (DEBUG_BEGIN_STMT, void_type_node); + SET_EXPR_LOCATION (t, cond_locus); + add_stmt (t); + } if (exit) add_stmt (exit); if (blab) @@ -11067,43 +11380,11 @@ { tree zero_vec = build_zero_cst (type); tree minus_one_vec = build_minus_one_cst (type); - tree cmp_type = build_same_sized_truth_vector_type (type); + tree cmp_type = truth_type_for (type); tree cmp = build2 (code, cmp_type, arg0, arg1); return build3 (VEC_COND_EXPR, type, cmp, minus_one_vec, zero_vec); } -/* Subclass of range_label for labelling the type of EXPR when reporting - a type mismatch between EXPR and OTHER_EXPR. - Either or both of EXPR and OTHER_EXPR could be NULL. */ - -class maybe_range_label_for_tree_type_mismatch : public range_label -{ - public: - maybe_range_label_for_tree_type_mismatch (tree expr, tree other_expr) - : m_expr (expr), m_other_expr (other_expr) - { - } - - label_text get_text (unsigned range_idx) const FINAL OVERRIDE - { - if (m_expr == NULL_TREE - || !EXPR_P (m_expr)) - return label_text (NULL, false); - tree expr_type = TREE_TYPE (m_expr); - - tree other_type = NULL_TREE; - if (m_other_expr && EXPR_P (m_other_expr)) - other_type = TREE_TYPE (m_other_expr); - - range_label_for_type_mismatch inner (expr_type, other_type); - return inner.get_text (range_idx); - } - - private: - tree m_expr; - tree m_other_expr; -}; - /* Build a binary-operation expression without default conversions. CODE is the kind of expression to build. LOCATION is the operator's location. @@ -11322,7 +11603,8 @@ /* In case when one of the operands of the binary operation is a vector and another is a scalar -- convert scalar to vector. */ - if ((code0 == VECTOR_TYPE) != (code1 == VECTOR_TYPE)) + if ((gnu_vector_type_p (type0) && code1 != VECTOR_TYPE) + || (gnu_vector_type_p (type1) && code0 != VECTOR_TYPE)) { enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1, true); @@ -11417,10 +11699,12 @@ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == FIXED_POINT_TYPE - || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE) + || code0 == COMPLEX_TYPE + || gnu_vector_type_p (type0)) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == FIXED_POINT_TYPE - || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)) + || code1 == COMPLEX_TYPE + || gnu_vector_type_p (type1))) { enum tree_code tcode0 = code0, tcode1 = code1; @@ -11451,8 +11735,8 @@ if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) shorten = -1; /* Allow vector types which are not floating point types. */ - else if (code0 == VECTOR_TYPE - && code1 == VECTOR_TYPE + else if (gnu_vector_type_p (type0) + && gnu_vector_type_p (type1) && !VECTOR_FLOAT_TYPE_P (type0) && !VECTOR_FLOAT_TYPE_P (type1)) common = 1; @@ -11463,7 +11747,8 @@ doing_div_or_mod = true; warn_for_div_by_zero (location, op1); - if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + if (gnu_vector_type_p (type0) + && gnu_vector_type_p (type1) && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE) common = 1; @@ -11542,7 +11827,8 @@ Also set SHORT_SHIFT if shifting rightward. */ case RSHIFT_EXPR: - if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + if (gnu_vector_type_p (type0) + && gnu_vector_type_p (type1) && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE && known_eq (TYPE_VECTOR_SUBPARTS (type0), @@ -11552,7 +11838,7 @@ converted = 1; } else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE - || (code0 == VECTOR_TYPE + || (gnu_vector_type_p (type0) && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)) && code1 == INTEGER_TYPE) { @@ -11601,7 +11887,8 @@ break; case LSHIFT_EXPR: - if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + if (gnu_vector_type_p (type0) + && gnu_vector_type_p (type1) && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE && known_eq (TYPE_VECTOR_SUBPARTS (type0), @@ -11611,7 +11898,7 @@ converted = 1; } else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE - || (code0 == VECTOR_TYPE + || (gnu_vector_type_p (type0) && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)) && code1 == INTEGER_TYPE) { @@ -11670,7 +11957,7 @@ case EQ_EXPR: case NE_EXPR: - if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE) + if (gnu_vector_type_p (type0) && gnu_vector_type_p (type1)) { tree intt; if (!vector_types_compatible_elements_p (type0, type1)) @@ -11722,7 +12009,7 @@ if (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1)) warning_at (location, OPT_Wfloat_equal, - "comparing floating point with == or != is unsafe"); + "comparing floating-point with %<==%> or %<!=%> is unsafe"); /* Result of comparison is always int, but don't convert the args to int! */ build_type = integer_type_node; @@ -11838,7 +12125,7 @@ case GE_EXPR: case LT_EXPR: case GT_EXPR: - if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE) + if (gnu_vector_type_p (type0) && gnu_vector_type_p (type1)) { tree intt; if (!vector_types_compatible_elements_p (type0, type1)) @@ -11985,7 +12272,8 @@ if (code0 == ERROR_MARK || code1 == ERROR_MARK) return error_mark_node; - if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + if (gnu_vector_type_p (type0) + && gnu_vector_type_p (type1) && (!tree_int_cst_equal (TYPE_SIZE (type0), TYPE_SIZE (type1)) || !vector_types_compatible_elements_p (type0, type1))) { @@ -12000,10 +12288,12 @@ } if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE - || code0 == FIXED_POINT_TYPE || code0 == VECTOR_TYPE) + || code0 == FIXED_POINT_TYPE + || gnu_vector_type_p (type0)) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE - || code1 == FIXED_POINT_TYPE || code1 == VECTOR_TYPE)) + || code1 == FIXED_POINT_TYPE + || gnu_vector_type_p (type1))) { bool first_complex = (code0 == COMPLEX_TYPE); bool second_complex = (code1 == COMPLEX_TYPE); @@ -12234,12 +12524,9 @@ if (!result_type) { - gcc_rich_location richloc (location); - maybe_range_label_for_tree_type_mismatch - label_for_op0 (orig_op0, orig_op1), - label_for_op1 (orig_op1, orig_op0); - richloc.maybe_add_expr (orig_op0, &label_for_op0); - richloc.maybe_add_expr (orig_op1, &label_for_op1); + /* Favor showing any expression locations that are available. */ + op_location_t oploc (location, UNKNOWN_LOCATION); + binary_op_rich_location richloc (oploc, orig_op0, orig_op1, true); binary_op_error (&richloc, code, TREE_TYPE (op0), TREE_TYPE (op1)); return error_mark_node; } @@ -12553,6 +12840,23 @@ tree ifc = omp_find_clause (clauses, OMP_CLAUSE_IF); if (ifc != NULL_TREE) { + if (OMP_CLAUSE_IF_MODIFIER (ifc) != ERROR_MARK + && OMP_CLAUSE_IF_MODIFIER (ifc) != VOID_CST) + error_at (OMP_CLAUSE_LOCATION (ifc), + "expected %<cancel%> %<if%> clause modifier"); + else + { + tree ifc2 = omp_find_clause (OMP_CLAUSE_CHAIN (ifc), OMP_CLAUSE_IF); + if (ifc2 != NULL_TREE) + { + gcc_assert (OMP_CLAUSE_IF_MODIFIER (ifc) == VOID_CST + && OMP_CLAUSE_IF_MODIFIER (ifc2) != ERROR_MARK + && OMP_CLAUSE_IF_MODIFIER (ifc2) != VOID_CST); + error_at (OMP_CLAUSE_LOCATION (ifc2), + "expected %<cancel%> %<if%> clause modifier"); + } + } + tree type = TREE_TYPE (OMP_CLAUSE_IF_EXPR (ifc)); ifc = fold_build2_loc (OMP_CLAUSE_LOCATION (ifc), NE_EXPR, boolean_type_node, OMP_CLAUSE_IF_EXPR (ifc), @@ -12633,7 +12937,6 @@ return error_mark_node; } if (TREE_CODE (t) == COMPONENT_REF - && ort == C_ORT_OMP && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM)) @@ -12654,6 +12957,15 @@ return error_mark_node; } t = TREE_OPERAND (t, 0); + if (ort == C_ORT_ACC && TREE_CODE (t) == MEM_REF) + { + if (maybe_ne (mem_ref_offset (t), 0)) + error_at (OMP_CLAUSE_LOCATION (c), + "cannot dereference %qE in %qs clause", t, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + else + t = TREE_OPERAND (t, 0); + } } } if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) @@ -12739,13 +13051,26 @@ length = fold_convert (sizetype, length); if (low_bound == NULL_TREE) low_bound = integer_zero_node; - + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP + && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH + || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)) + { + if (length != integer_one_node) + { + error_at (OMP_CLAUSE_LOCATION (c), + "expected single pointer in %qs clause", + c_omp_map_clause_name (c, ort == C_ORT_ACC)); + return error_mark_node; + } + } if (length != NULL_TREE) { if (!integer_nonzerop (length)) { if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) { if (integer_zerop (length)) { @@ -12811,7 +13136,9 @@ if (tree_int_cst_equal (size, low_bound)) { if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) { error_at (OMP_CLAUSE_LOCATION (c), "zero length array section in %qs clause", @@ -12830,7 +13157,9 @@ else if (length == NULL_TREE) { if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION) + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TASK_REDUCTION) maybe_zero_len = true; if (first_non_one == types.length ()) first_non_one++; @@ -12866,7 +13195,9 @@ else if (length == NULL_TREE) { if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION) + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TASK_REDUCTION) maybe_zero_len = true; if (first_non_one == types.length ()) first_non_one++; @@ -12938,7 +13269,13 @@ bool maybe_zero_len = false; unsigned int first_non_one = 0; auto_vec<tree, 10> types; - tree first = handle_omp_array_sections_1 (c, OMP_CLAUSE_DECL (c), types, + tree *tp = &OMP_CLAUSE_DECL (c); + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND + && TREE_CODE (*tp) == TREE_LIST + && TREE_PURPOSE (*tp) + && TREE_CODE (TREE_PURPOSE (*tp)) == TREE_VEC) + tp = &TREE_VALUE (*tp); + tree first = handle_omp_array_sections_1 (c, *tp, types, maybe_zero_len, first_non_one, ort); if (first == error_mark_node) @@ -12947,7 +13284,7 @@ return false; if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND) { - tree t = OMP_CLAUSE_DECL (c); + tree t = *tp; tree tem = NULL_TREE; /* Need to evaluate side effects in the length expressions if any. */ @@ -12966,7 +13303,7 @@ if (tem) first = build2 (COMPOUND_EXPR, TREE_TYPE (first), tem, first); first = c_fully_fold (first, false, NULL, true); - OMP_CLAUSE_DECL (c) = first; + *tp = first; } else { @@ -13038,7 +13375,9 @@ if (i > first_non_one && ((length && integer_nonzerop (length)) - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)) + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)) continue; if (length) l = fold_convert (sizetype, length); @@ -13066,7 +13405,9 @@ tree eltype = TREE_TYPE (types[num - 1]); while (TREE_CODE (eltype) == ARRAY_TYPE) eltype = TREE_TYPE (eltype); - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) { if (integer_zerop (size) || integer_zerop (size_in_bytes (eltype))) @@ -13090,10 +13431,13 @@ } if (side_effects) size = build2 (COMPOUND_EXPR, sizetype, side_effects, size); - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) { size = size_binop (MINUS_EXPR, size, size_one_node); size = c_fully_fold (size, false, NULL); + size = save_expr (size); tree index_type = build_index_type (size); tree eltype = TREE_TYPE (first); while (TREE_CODE (eltype) == ARRAY_TYPE) @@ -13137,6 +13481,7 @@ switch (OMP_CLAUSE_MAP_KIND (c)) { case GOMP_MAP_ALLOC: + case GOMP_MAP_IF_PRESENT: case GOMP_MAP_TO: case GOMP_MAP_FROM: case GOMP_MAP_TOFROM: @@ -13158,7 +13503,11 @@ if (ort != C_ORT_OMP && ort != C_ORT_ACC) OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER); else if (TREE_CODE (t) == COMPONENT_REF) - OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER); + { + gomp_map_kind k = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH + : GOMP_MAP_ALWAYS_POINTER; + OMP_CLAUSE_SET_MAP_KIND (c2, k); + } else OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER); if (OMP_CLAUSE_MAP_KIND (c2) != GOMP_MAP_FIRSTPRIVATE_POINTER @@ -13223,6 +13572,207 @@ return NULL_TREE; } +/* Similarly, but also walk aggregate fields. */ + +struct c_find_omp_var_s { tree var; hash_set<tree> *pset; }; + +static tree +c_find_omp_var_r (tree *tp, int *, void *data) +{ + if (*tp == ((struct c_find_omp_var_s *) data)->var) + return *tp; + if (RECORD_OR_UNION_TYPE_P (*tp)) + { + tree field; + hash_set<tree> *pset = ((struct c_find_omp_var_s *) data)->pset; + + for (field = TYPE_FIELDS (*tp); field; + field = DECL_CHAIN (field)) + if (TREE_CODE (field) == FIELD_DECL) + { + tree ret = walk_tree (&DECL_FIELD_OFFSET (field), + c_find_omp_var_r, data, pset); + if (ret) + return ret; + ret = walk_tree (&DECL_SIZE (field), c_find_omp_var_r, data, pset); + if (ret) + return ret; + ret = walk_tree (&DECL_SIZE_UNIT (field), c_find_omp_var_r, data, + pset); + if (ret) + return ret; + ret = walk_tree (&TREE_TYPE (field), c_find_omp_var_r, data, pset); + if (ret) + return ret; + } + } + else if (INTEGRAL_TYPE_P (*tp)) + return walk_tree (&TYPE_MAX_VALUE (*tp), c_find_omp_var_r, data, + ((struct c_find_omp_var_s *) data)->pset); + return NULL_TREE; +} + +/* Finish OpenMP iterators ITER. Return true if they are errorneous + and clauses containing them should be removed. */ + +static bool +c_omp_finish_iterators (tree iter) +{ + bool ret = false; + for (tree it = iter; it; it = TREE_CHAIN (it)) + { + tree var = TREE_VEC_ELT (it, 0); + tree begin = TREE_VEC_ELT (it, 1); + tree end = TREE_VEC_ELT (it, 2); + tree step = TREE_VEC_ELT (it, 3); + tree orig_step; + tree type = TREE_TYPE (var); + location_t loc = DECL_SOURCE_LOCATION (var); + if (type == error_mark_node) + { + ret = true; + continue; + } + if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type)) + { + error_at (loc, "iterator %qD has neither integral nor pointer type", + var); + ret = true; + continue; + } + else if (TYPE_ATOMIC (type)) + { + error_at (loc, "iterator %qD has %<_Atomic%> qualified type", var); + ret = true; + continue; + } + else if (TYPE_READONLY (type)) + { + error_at (loc, "iterator %qD has const qualified type", var); + ret = true; + continue; + } + else if (step == error_mark_node + || TREE_TYPE (step) == error_mark_node) + { + ret = true; + continue; + } + else if (!INTEGRAL_TYPE_P (TREE_TYPE (step))) + { + error_at (EXPR_LOC_OR_LOC (step, loc), + "iterator step with non-integral type"); + ret = true; + continue; + } + begin = c_fully_fold (build_c_cast (loc, type, begin), false, NULL); + end = c_fully_fold (build_c_cast (loc, type, end), false, NULL); + orig_step = save_expr (c_fully_fold (step, false, NULL)); + tree stype = POINTER_TYPE_P (type) ? sizetype : type; + step = c_fully_fold (build_c_cast (loc, stype, orig_step), false, NULL); + if (POINTER_TYPE_P (type)) + { + begin = save_expr (begin); + step = pointer_int_sum (loc, PLUS_EXPR, begin, step); + step = fold_build2_loc (loc, MINUS_EXPR, sizetype, + fold_convert (sizetype, step), + fold_convert (sizetype, begin)); + step = fold_convert (ssizetype, step); + } + if (integer_zerop (step)) + { + error_at (loc, "iterator %qD has zero step", var); + ret = true; + continue; + } + + if (begin == error_mark_node + || end == error_mark_node + || step == error_mark_node + || orig_step == error_mark_node) + { + ret = true; + continue; + } + hash_set<tree> pset; + tree it2; + for (it2 = TREE_CHAIN (it); it2; it2 = TREE_CHAIN (it2)) + { + tree var2 = TREE_VEC_ELT (it2, 0); + tree begin2 = TREE_VEC_ELT (it2, 1); + tree end2 = TREE_VEC_ELT (it2, 2); + tree step2 = TREE_VEC_ELT (it2, 3); + tree type2 = TREE_TYPE (var2); + location_t loc2 = DECL_SOURCE_LOCATION (var2); + struct c_find_omp_var_s data = { var, &pset }; + if (walk_tree (&type2, c_find_omp_var_r, &data, &pset)) + { + error_at (loc2, + "type of iterator %qD refers to outer iterator %qD", + var2, var); + break; + } + else if (walk_tree (&begin2, c_find_omp_var_r, &data, &pset)) + { + error_at (EXPR_LOC_OR_LOC (begin2, loc2), + "begin expression refers to outer iterator %qD", var); + break; + } + else if (walk_tree (&end2, c_find_omp_var_r, &data, &pset)) + { + error_at (EXPR_LOC_OR_LOC (end2, loc2), + "end expression refers to outer iterator %qD", var); + break; + } + else if (walk_tree (&step2, c_find_omp_var_r, &data, &pset)) + { + error_at (EXPR_LOC_OR_LOC (step2, loc2), + "step expression refers to outer iterator %qD", var); + break; + } + } + if (it2) + { + ret = true; + continue; + } + TREE_VEC_ELT (it, 1) = begin; + TREE_VEC_ELT (it, 2) = end; + TREE_VEC_ELT (it, 3) = step; + TREE_VEC_ELT (it, 4) = orig_step; + } + return ret; +} + +/* Ensure that pointers are used in OpenACC attach and detach clauses. + Return true if an error has been detected. */ + +static bool +c_oacc_check_attachments (tree c) +{ + if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP) + return false; + + /* OpenACC attach / detach clauses must be pointers. */ + if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH + || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH) + { + tree t = OMP_CLAUSE_DECL (c); + + while (TREE_CODE (t) == TREE_LIST) + t = TREE_CHAIN (t); + + if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE) + { + error_at (OMP_CLAUSE_LOCATION (c), "expected pointer in %qs clause", + c_omp_map_clause_name (c, true)); + return true; + } + } + + return false; +} + /* For all elements of CLAUSES, validate them against their constraints. Remove any elements from the list that are invalid. */ @@ -13237,17 +13787,27 @@ bool copyprivate_seen = false; bool linear_variable_step_check = false; tree *nowait_clause = NULL; - bool ordered_seen = false; + tree ordered_clause = NULL_TREE; tree schedule_clause = NULL_TREE; bool oacc_async = false; + tree last_iterators = NULL_TREE; + bool last_iterators_remove = false; + tree *nogroup_seen = NULL; + tree *order_clause = NULL; + /* 1 if normal/task reduction has been seen, -1 if inscan reduction + has been seen, -2 if mixed inscan/normal reduction diagnosed. */ + int reduction_seen = 0; bitmap_obstack_initialize (NULL); bitmap_initialize (&generic_head, &bitmap_default_obstack); bitmap_initialize (&firstprivate_head, &bitmap_default_obstack); bitmap_initialize (&lastprivate_head, &bitmap_default_obstack); bitmap_initialize (&aligned_head, &bitmap_default_obstack); + /* If ort == C_ORT_OMP_DECLARE_SIMD used as uniform_head instead. */ bitmap_initialize (&map_head, &bitmap_default_obstack); bitmap_initialize (&map_field_head, &bitmap_default_obstack); + /* If ort == C_ORT_OMP used as nontemporal_head or use_device_xxx_head + instead. */ bitmap_initialize (&oacc_reduction_head, &bitmap_default_obstack); if (ort & C_ORT_ACC) @@ -13276,6 +13836,20 @@ goto check_dup_generic; case OMP_CLAUSE_REDUCTION: + if (reduction_seen == 0) + reduction_seen = OMP_CLAUSE_REDUCTION_INSCAN (c) ? -1 : 1; + else if (reduction_seen != -2 + && reduction_seen != (OMP_CLAUSE_REDUCTION_INSCAN (c) + ? -1 : 1)) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<inscan%> and non-%<inscan%> %<reduction%> clauses " + "on the same construct"); + reduction_seen = -2; + } + /* FALLTHRU */ + case OMP_CLAUSE_IN_REDUCTION: + case OMP_CLAUSE_TASK_REDUCTION: need_implicitly_determined = true; t = OMP_CLAUSE_DECL (c); if (TREE_CODE (t) == TREE_LIST) @@ -13287,6 +13861,15 @@ } t = OMP_CLAUSE_DECL (c); + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + && OMP_CLAUSE_REDUCTION_INSCAN (c)) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<inscan%> %<reduction%> clause with array " + "section"); + remove = true; + break; + } } t = require_complete_type (OMP_CLAUSE_LOCATION (c), t); if (t == error_mark_node) @@ -13324,6 +13907,7 @@ break; } size = size_binop (MINUS_EXPR, size, size_one_node); + size = save_expr (size); tree index_type = build_index_type (size); tree atype = build_array_type (type, index_type); tree ptype = build_pointer_type (type); @@ -13339,6 +13923,28 @@ remove = true; break; } + if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION + || OMP_CLAUSE_REDUCTION_TASK (c)) + { + /* Disallow zero sized or potentially zero sized task + reductions. */ + if (integer_zerop (TYPE_SIZE_UNIT (type))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "zero sized type %qT in %qs clause", type, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + remove = true; + break; + } + else if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST) + { + error_at (OMP_CLAUSE_LOCATION (c), + "variable sized type %qT in %qs clause", type, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + remove = true; + break; + } + } if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == NULL_TREE && (FLOAT_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE)) @@ -13540,7 +14146,7 @@ if (TYPE_ATOMIC (TREE_TYPE (t))) { error_at (OMP_CLAUSE_LOCATION (c), - "%<_Atomic%> %qD in %<linear%> clause", t); + "%<_Atomic%> %qD in %<linear%> clause", t); remove = true; break; } @@ -13593,12 +14199,20 @@ omp_clause_code_name[OMP_CLAUSE_CODE (c)]); remove = true; } - else if (ort == C_ORT_ACC - && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) + else if ((ort == C_ORT_ACC + && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) + || (ort == C_ORT_OMP + && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR + || (OMP_CLAUSE_CODE (c) + == OMP_CLAUSE_USE_DEVICE_ADDR)))) { if (bitmap_bit_p (&oacc_reduction_head, DECL_UID (t))) { - error ("%qD appears more than once in reduction clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + ort == C_ORT_ACC + ? "%qD appears more than once in reduction clauses" + : "%qD appears more than once in data clauses", + t); remove = true; } else @@ -13616,9 +14230,11 @@ && bitmap_bit_p (&map_head, DECL_UID (t))) { if (ort == C_ORT_ACC) - error ("%qD appears more than once in data clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data clauses", t); else - error ("%qD appears both in data and map clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears both in data and map clauses", t); remove = true; } else @@ -13645,9 +14261,11 @@ else if (bitmap_bit_p (&map_head, DECL_UID (t))) { if (ort == C_ORT_ACC) - error ("%qD appears more than once in data clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data clauses", t); else - error ("%qD appears both in data and map clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears both in data and map clauses", t); remove = true; } else @@ -13709,6 +14327,25 @@ bitmap_set_bit (&aligned_head, DECL_UID (t)); break; + case OMP_CLAUSE_NONTEMPORAL: + t = OMP_CLAUSE_DECL (c); + if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is not a variable in %<nontemporal%> clause", t); + remove = true; + } + else if (bitmap_bit_p (&oacc_reduction_head, DECL_UID (t))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qE appears more than once in %<nontemporal%> " + "clauses", t); + remove = true; + } + else + bitmap_set_bit (&oacc_reduction_head, DECL_UID (t)); + break; + case OMP_CLAUSE_DEPEND: t = OMP_CLAUSE_DECL (c); if (t == NULL_TREE) @@ -13745,22 +14382,89 @@ } break; } + if (TREE_CODE (t) == TREE_LIST + && TREE_PURPOSE (t) + && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC) + { + if (TREE_PURPOSE (t) != last_iterators) + last_iterators_remove + = c_omp_finish_iterators (TREE_PURPOSE (t)); + last_iterators = TREE_PURPOSE (t); + t = TREE_VALUE (t); + if (last_iterators_remove) + t = error_mark_node; + } + else + last_iterators = NULL_TREE; if (TREE_CODE (t) == TREE_LIST) { if (handle_omp_array_sections (c, ort)) remove = true; + else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_DEPOBJ) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<depend%> clause with %<depobj%> dependence " + "type on array section"); + remove = true; + } break; } if (t == error_mark_node) remove = true; - else if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) + else if (!lvalue_p (t)) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is not lvalue expression nor array section in " + "%<depend%> clause", t); + remove = true; + } + else if (TREE_CODE (t) == COMPONENT_REF + && DECL_C_BIT_FIELD (TREE_OPERAND (t, 1))) { error_at (OMP_CLAUSE_LOCATION (c), - "%qE is not a variable in %<depend%> clause", t); + "bit-field %qE in %qs clause", t, "depend"); + remove = true; + } + else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_DEPOBJ) + { + if (!c_omp_depend_t_p (TREE_TYPE (t))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qE does not have %<omp_depend_t%> type in " + "%<depend%> clause with %<depobj%> dependence " + "type", t); + remove = true; + } + } + else if (c_omp_depend_t_p (TREE_TYPE (t))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qE should not have %<omp_depend_t%> type in " + "%<depend%> clause with dependence type other than " + "%<depobj%>", t); remove = true; } - else if (!c_mark_addressable (t)) - remove = true; + if (!remove) + { + tree addr = build_unary_op (OMP_CLAUSE_LOCATION (c), ADDR_EXPR, + t, false); + if (addr == error_mark_node) + remove = true; + else + { + t = build_indirect_ref (OMP_CLAUSE_LOCATION (c), addr, + RO_UNARY_STAR); + if (t == error_mark_node) + remove = true; + else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST + && TREE_PURPOSE (OMP_CLAUSE_DECL (c)) + && (TREE_CODE (TREE_PURPOSE (OMP_CLAUSE_DECL (c))) + == TREE_VEC)) + TREE_VALUE (OMP_CLAUSE_DECL (c)) = t; + else + OMP_CLAUSE_DECL (c) = t; + } + } break; case OMP_CLAUSE_MAP: @@ -13802,14 +14506,17 @@ if (bitmap_bit_p (&map_head, DECL_UID (t))) { if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP) - error ("%qD appears more than once in motion" - " clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in motion " + "clauses", t); else if (ort == C_ORT_ACC) - error ("%qD appears more than once in data" - " clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data " + "clauses", t); else - error ("%qD appears more than once in map" - " clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in map " + "clauses", t); remove = true; } else @@ -13819,6 +14526,8 @@ } } } + if (c_oacc_check_attachments (c)) + remove = true; break; } if (t == error_mark_node) @@ -13826,8 +14535,13 @@ remove = true; break; } + /* OpenACC attach / detach clauses must be pointers. */ + if (c_oacc_check_attachments (c)) + { + remove = true; + break; + } if (TREE_CODE (t) == COMPONENT_REF - && (ort & C_ORT_OMP) && OMP_CLAUSE_CODE (c) != OMP_CLAUSE__CACHE_) { if (DECL_BIT_FIELD (TREE_OPERAND (t, 1))) @@ -13862,6 +14576,15 @@ break; } t = TREE_OPERAND (t, 0); + if (ort == C_ORT_ACC && TREE_CODE (t) == MEM_REF) + { + if (maybe_ne (mem_ref_offset (t), 0)) + error_at (OMP_CLAUSE_LOCATION (c), + "cannot dereference %qE in %qs clause", t, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + else + t = TREE_OPERAND (t, 0); + } } if (remove) break; @@ -13919,15 +14642,18 @@ if (bitmap_bit_p (&generic_head, DECL_UID (t)) || bitmap_bit_p (&firstprivate_head, DECL_UID (t))) { - error ("%qD appears more than once in data clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data clauses", t); remove = true; } else if (bitmap_bit_p (&map_head, DECL_UID (t))) { if (ort == C_ORT_ACC) - error ("%qD appears more than once in data clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data clauses", t); else - error ("%qD appears both in data and map clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears both in data and map clauses", t); remove = true; } else @@ -13936,20 +14662,25 @@ else if (bitmap_bit_p (&map_head, DECL_UID (t))) { if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP) - error ("%qD appears more than once in motion clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in motion clauses", t); else if (ort == C_ORT_ACC) - error ("%qD appears more than once in data clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data clauses", t); else - error ("%qD appears more than once in map clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in map clauses", t); remove = true; } else if (bitmap_bit_p (&generic_head, DECL_UID (t)) || bitmap_bit_p (&firstprivate_head, DECL_UID (t))) { if (ort == C_ORT_ACC) - error ("%qD appears more than once in data clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data clauses", t); else - error ("%qD appears both in data and map clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears both in data and map clauses", t); remove = true; } else @@ -14027,14 +14758,30 @@ case OMP_CLAUSE_IS_DEVICE_PTR: case OMP_CLAUSE_USE_DEVICE_PTR: t = OMP_CLAUSE_DECL (c); - if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE - && TREE_CODE (TREE_TYPE (t)) != ARRAY_TYPE) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qs variable is neither a pointer nor an array", - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } + if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE) + { + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR + && ort == C_ORT_OMP) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qs variable is not a pointer", + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + remove = true; + } + else if (TREE_CODE (TREE_TYPE (t)) != ARRAY_TYPE) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qs variable is neither a pointer nor an array", + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + remove = true; + } + } + goto check_dup_generic; + + case OMP_CLAUSE_USE_DEVICE_ADDR: + t = OMP_CLAUSE_DECL (c); + if (VAR_P (t) || TREE_CODE (t) == PARM_DECL) + c_mark_addressable (t); goto check_dup_generic; case OMP_CLAUSE_NOWAIT: @@ -14050,6 +14797,25 @@ pc = &OMP_CLAUSE_CHAIN (c); continue; + case OMP_CLAUSE_ORDER: + if (ordered_clause) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<order%> clause must not be used together " + "with %<ordered%>"); + remove = true; + break; + } + else if (order_clause) + { + /* Silently remove duplicates. */ + remove = true; + break; + } + order_clause = pc; + pc = &OMP_CLAUSE_CHAIN (c); + continue; + case OMP_CLAUSE_IF: case OMP_CLAUSE_NUM_THREADS: case OMP_CLAUSE_NUM_TEAMS: @@ -14066,14 +14832,15 @@ case OMP_CLAUSE_SECTIONS: case OMP_CLAUSE_TASKGROUP: case OMP_CLAUSE_PROC_BIND: + case OMP_CLAUSE_DEVICE_TYPE: case OMP_CLAUSE_PRIORITY: case OMP_CLAUSE_GRAINSIZE: case OMP_CLAUSE_NUM_TASKS: - case OMP_CLAUSE_NOGROUP: case OMP_CLAUSE_THREADS: case OMP_CLAUSE_SIMD: case OMP_CLAUSE_HINT: case OMP_CLAUSE_DEFAULTMAP: + case OMP_CLAUSE_BIND: case OMP_CLAUSE_NUM_GANGS: case OMP_CLAUSE_NUM_WORKERS: case OMP_CLAUSE_VECTOR_LENGTH: @@ -14091,36 +14858,26 @@ pc = &OMP_CLAUSE_CHAIN (c); continue; + case OMP_CLAUSE_NOGROUP: + nogroup_seen = pc; + pc = &OMP_CLAUSE_CHAIN (c); + continue; + case OMP_CLAUSE_SCHEDULE: - if (OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_NONMONOTONIC) - { - const char *p = NULL; - switch (OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK) - { - case OMP_CLAUSE_SCHEDULE_STATIC: p = "static"; break; - case OMP_CLAUSE_SCHEDULE_DYNAMIC: break; - case OMP_CLAUSE_SCHEDULE_GUIDED: break; - case OMP_CLAUSE_SCHEDULE_AUTO: p = "auto"; break; - case OMP_CLAUSE_SCHEDULE_RUNTIME: p = "runtime"; break; - default: gcc_unreachable (); - } - if (p) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<nonmonotonic%> modifier specified for %qs " - "schedule kind", p); - OMP_CLAUSE_SCHEDULE_KIND (c) - = (enum omp_clause_schedule_kind) - (OMP_CLAUSE_SCHEDULE_KIND (c) - & ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC); - } - } schedule_clause = c; pc = &OMP_CLAUSE_CHAIN (c); continue; case OMP_CLAUSE_ORDERED: - ordered_seen = true; + ordered_clause = c; + if (order_clause) + { + error_at (OMP_CLAUSE_LOCATION (*order_clause), + "%<order%> clause must not be used together " + "with %<ordered%>"); + *order_clause = OMP_CLAUSE_CHAIN (*order_clause); + order_clause = NULL; + } pc = &OMP_CLAUSE_CHAIN (c); continue; @@ -14147,6 +14904,20 @@ pc = &OMP_CLAUSE_CHAIN (c); continue; + case OMP_CLAUSE_INCLUSIVE: + case OMP_CLAUSE_EXCLUSIVE: + need_complete = true; + need_implicitly_determined = true; + t = OMP_CLAUSE_DECL (c); + if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is not a variable in clause %qs", t, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + remove = true; + } + break; + default: gcc_unreachable (); } @@ -14173,9 +14944,12 @@ case OMP_CLAUSE_DEFAULT_UNSPECIFIED: break; case OMP_CLAUSE_DEFAULT_SHARED: - /* const vars may be specified in firstprivate clause. */ - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE - && TREE_READONLY (t)) + if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE) + && c_omp_predefined_variable (t)) + /* The __func__ variable and similar function-local + predefined variables may be listed in a shared or + firstprivate clause. */ break; share_name = "shared"; break; @@ -14193,6 +14967,15 @@ omp_clause_code_name[OMP_CLAUSE_CODE (c)]); remove = true; } + else if (TREE_READONLY (t) + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SHARED + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<const%> qualified %qE may appear only in " + "%<shared%> or %<firstprivate%> clauses", t); + remove = true; + } } } @@ -14214,7 +14997,7 @@ = OMP_CLAUSE_SAFELEN_EXPR (safelen); } - if (ordered_seen + if (ordered_clause && schedule_clause && (OMP_CLAUSE_SCHEDULE_KIND (schedule_clause) & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)) @@ -14228,7 +15011,23 @@ & ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC); } - if (linear_variable_step_check) + if (reduction_seen < 0 && ordered_clause) + { + error_at (OMP_CLAUSE_LOCATION (ordered_clause), + "%qs clause specified together with %<inscan%> " + "%<reduction%> clause", "ordered"); + reduction_seen = -2; + } + + if (reduction_seen < 0 && schedule_clause) + { + error_at (OMP_CLAUSE_LOCATION (schedule_clause), + "%qs clause specified together with %<inscan%> " + "%<reduction%> clause", "schedule"); + reduction_seen = -2; + } + + if (linear_variable_step_check || reduction_seen == -2) for (pc = &clauses, c = clauses; c ; c = *pc) { bool remove = false; @@ -14243,6 +15042,8 @@ OMP_CLAUSE_LINEAR_STEP (c)); remove = true; } + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) + OMP_CLAUSE_REDUCTION_INSCAN (c) = 0; if (remove) *pc = OMP_CLAUSE_CHAIN (c); @@ -14250,6 +15051,14 @@ pc = &OMP_CLAUSE_CHAIN (c); } + if (nogroup_seen && reduction_seen) + { + error_at (OMP_CLAUSE_LOCATION (*nogroup_seen), + "%<nogroup%> clause must not be used together with " + "%<reduction%> clause"); + *nogroup_seen = OMP_CLAUSE_CHAIN (*nogroup_seen); + } + bitmap_obstack_release (NULL); return clauses; }