diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-06-26 18:39:06 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-06-26 18:39:06 +0000 |
commit | 21543d4cd558cada630271a0cf3075ad7ce94cbf (patch) | |
tree | 08bdb3f3e0a9d0f71e72bb56d9ddb7b916e7dfeb /gcc/cp | |
parent | ed0bc1ffb674fe93d0df68654b5bb76869f0bc8c (diff) | |
download | gcc-21543d4cd558cada630271a0cf3075ad7ce94cbf.tar.gz |
2013-06-26 Basile Starynkevitch <basile@starynkevitch.net>
{{merged with trunk [4.9] svn rev. 196654-200426}}
MELT branch merged with trunk rev. 200426 using svnmerge.py
[gcc/]
2013-06-26 Basile Starynkevitch <basile@starynkevitch.net>
{{merge with trunk [4.9] svn rev. 196654-200426}}
* melt-runtime.c (melt_val2passflag): TODO_ggc_collect &
TODO_do_not_ggc_collect are conditionalized.
* melt/generated/warmelt-first+03.cc: Manually remove calls to
MELT_TRACE_EXIT_LOCATION macro.
* melt/generated/warmelt-base+03.cc: Ditto.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@200430 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
35 files changed, 7310 insertions, 1821 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c728c50c587..bd82693722c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,1580 @@ +2013-06-25 Ed Smith-Rowland <3dw4rd@verizon.net> + + PR c++/57640 + * parser.c (cp_parser_unqualified_id): Add declarator_p to checks + to trigger warning, (cp_literal_operator_id): Remove bogus TODO comment. + +2013-06-22 Gabriel Dos Reis <gdr@integrable-solutions.net> + + * call.c (null_ptr_cst_p): Use cxx11 in lieu of cxx0x. + * class.c (add_implicitly_declared_members): Likewise. + (check_field_decl): Likewise. + (finalize_literal_type_property): Likewise. + (check_bases_and_members): Likewise. + * decl.c (poplevel): Likewise. + (case_conversion): Likewise. + (check_initializer): Likewise. + (grokfndecl): Likewise. + (check_static_variable_definition): Likewise. + (compute_array_index_type): Likewise. + (grokdeclarator): Likewise. + (build_enumerator): Likewise. + * friend.c (make_friend_class): Likewise. + * lex.c (init_reswords): Likewise. + * method.c (synthesized_method_walk): Likewise. + (implicitly_declare_fn): Likewise. + * parser.c (cp_parser_diagnose_invalid_type_name): Likewise. + (cp_parser_constant_expression): Likewise. + (cp_parser_for_init_statement): Likewise. + (cp_parser_block_declaration): Likewise. + (cp_parser_type_name): Likewise. + (cp_parser_enum_specifier): Likewise. + (cp_parser_enumerator_list): Likewise. + (cp_parser_member_declaration): Likewise. + (cp_nth_tokens_can_be_std_attribute_p): Likewise. + (cp_parser_template_declaration_after_export): Likewise. + * pt.c (convert_nontype_argument_function): Likewise. + (convert_nontype_argument): Likewise. + (convert_template_argument): Likewise. + (tsubst_copy_and_build): Likewise. + (build_non_dependent_expr): Likewise. + * semantics.c (non_const_var_error): Likewise. + (potential_constant_expression_1): Likewise. + * tree.c (lvalue_kind): Likewise. + (build_vec_init_expr): Likewise. + (cast_valid_in_integral_constant_expression_p): Likewise. + * typeck.c (build_x_conditional_expr): Likewise. + * typeck2.c (check_narrowing): Likewise. + +2013-06-21 Balaji V. Iyer <balaji.v.iyer@intel.com> + + * cp-array-notation.c (cp_length_mismatch_in_expr_p): Remove. + (expand_an_in_modify_expr): Changed a function call from the above + removed function to length_mismatch_in_expr_p. + +2013-06-21 Balaji V. Iyer <balaji.v.iyer@intel.com> + + * call.c (convert_like_real): Added a check if array notation is present + in expression. If so, then no conversion of arguments is necessary. + (build_over_call): Likewise. + * typeck.c (cp_build_function_call_vec): Likewise. + (convert_for_assignment): Likewise. + (cp_build_array_ref): Reject array notations with a rank greater than 1 + as an array's index. + (cp_build_binary_op): If array notations are preent in op, then call + find_correct_array_notation_type. + (cp_build_addr_expr_1): Handle ARRAY_NOTATION_REF similar to ARRAY_REF. + * cp-array-notation.c: New file. + * cp-objcp-common.c (cp_common_init_ts): Marked ARRAY_NOTATION_REF tree + as typed. + * cp-tree.h (fix_array_notation_exprs): New prototype. + * semantics.c (finish_return_stmt): Reject array notations as + return value. + (cxx_eval_constant_expression): Added ARRAY_NOTATION_REF case. + (potential_constant_expression_1): Likewise. + * tree.c (lvalue_kind): Likewise. + * error.c (dump_decl): Likewise. + (dump_expr): Likewise. + * pt.c (ARRAY_NOTATION_REF): Likewise. + (type_unification_real): Do not unify any arguments if array notations + are found in arg. + (instantiate_decl): Added a check for array notaitons inside the + function body. If so, then expand them. + * parser.c (cp_parser_array_notation): New function. + (cp_parser_postfix_open_square_expression): Added a check for colons + inside square braces. If found, then handle the array access as an + array notation access. Also, disable auto-correction from a single + colon to scope when Cilk Plus is enabled. + (cp_parser_compound_statement): Added a check for array notations + inside the statement. If found, then expand them. + (cp_parser_ctor_initializer_opt_and_function_body): Likewise. + (cp_parser_function_definition_after_declarator): Likewise. + (cp_parser_selection_statement): Searched for array notations inside + condition. If so, then emit an error. + (cp_parser_iteration_statement): Likewise. + (cp_parser_direct_declarator): Reject array notations inside a + variable or array declaration. + * Make-lang.in (CXX_AND_OBJCXX_OBJS): Added cp/cp-array-notation.o. + +2013-06-20 Jason Merrill <jason@redhat.com> + + PR c++/55149 + * decl.c (compute_array_index_type): Don't reject VLAs in SFINAE + context if we're in C++14 mode. + * tree.c (array_of_runtime_bound_p): Return true for a dependent + bound that is not potentually constant. + * cp-tree.h (DECL_VLA_CAPTURE_P, REFERENCE_VLA_OK): New. + * pt.c (tsubst) [REFERENCE_TYPE]: Check REFERENCE_VLA_OK. + * semantics.c (build_lambda_object): Don't rvalue a VLA capture. + (build_capture_proxy): Set REFERENCE_VLA_OK. + (vla_capture_type): Make it a proper C++ class. + (add_capture): Set DECL_VLA_CAPTURE_P. Don't pre-digest the + initializer. + + * decl.c (compute_array_index_type): Use size_one_node. + + * pt.c (process_partial_specialization): Build a TEMPLATE_DECL for + a partial specialization. + (tsubst_decl): Don't clobber CLASSTYPE_TI_TEMPLATE of a partial + specialization. + (most_specialized_class): Adjust. + + * cp-tree.h (DECL_TEMPLATE_PARMS, DECL_TEMPLATE_RESULT) + (DECL_TEMPLATE_INSTANTIATIONS, DECL_TEMPLATE_SPECIALIZATIONS): Use + TEMPLATE_DECL_CHECK. + +2013-06-19 Manuel Lopez-Ibanez <manu@gcc.gnu.org> + + PR c++/57638 + * pt.c (unify, [TEMPLATE_PARM_INDEX]): Pass to unify_type_mismatch + TREE_TYPE (arg), not arg itself. + +2013-06-18 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/53211 + * pt.c (type_dependent_expression_p): Handle an array of unknown + bound depending on a variadic parameter. + * parser.c (cp_parser_range_for): Revert PR56794 changes. + +2013-06-17 Richard Biener <rguenther@suse.de> + + * cp-tree.h (ANON_AGGRNAME_FORMAT, ANON_AGGRNAME_P): Move to tree.h. + +2013-06-17 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/16128 + * parser.c (cp_parser_expression_statement): Check whether + cp_parser_expression returns error_mark_node. + +2013-06-14 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/51413 + * semantics.c (finish_offsetof): Handle INDIRECT_REF as expr. + +2013-06-14 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/57599 + * rtti.c (build_dynamic_cast_1): In case of cast to an unambiguous + accessible base simply forward to build_static_cast. + +2013-06-12 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/38958 + * decl.c (poplevel): For the benefit of -Wunused-variable see + through references. + +2013-06-12 Paolo Carlini <paolo.carlini@oracle.com> + + * parser.c (cp_parser_nested_name_specifier_opt): Fix typo in comment. + +2013-06-12 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/42021 + * parser.c (cp_parser_nested_name_specifier_opt): Avoid emitting + again diagnostic already emitted by cp_parser_lookup_name. + +2013-06-11 Jan Hubicka <jh@suse.cz> + + PR c++/57551 + * cp/pt.c (mark_decl_instantiated): Do not export explicit + instantiations of anonymous namespace templates. + +2013-06-10 Jason Merrill <jason@redhat.com> + + * name-lookup.c (add_decl_to_level): Add decls in an anonymous + namespace to static_decls. + +2013-06-07 Sriraman Tallam <tmsriram@google.com> + + PR c++/57548 + * call.c (build_over_call): Check if current_function_decl is + NULL. + +2013-06-07 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/53658 + * pt.c (lookup_template_class_1): Consistently use TYPE_MAIN_DECL, + not TYPE_STUB_DECL, to access the _DECL for a _TYPE. + +2013-06-06 Jason Merrill <jason@redhat.com> + + PR c++/55520 + * semantics.c (add_capture): Diagnose capture of variable-size + type that is not a C++1y array of runtime bound. + + * decl.c (grokdeclarator): Keep a decl with error type. + (grokfield, grokbitfield): Likewise. + * pt.c (instantiate_class_template_1): Likewise. + (tsubst_decl): Drop redundant error. + * class.c (walk_subobject_offsets): Handle erroneous fields. + * typeck2.c (process_init_constructor_record): Likewise. + +2013-06-05 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/51908 + * parser.c (cp_parser_postfix_expression [RID_*CAST]): Set + parser->in_type_id_in_expr_p before calling cp_parser_type_id. + +2013-06-03 Jan Hubicka <jh@suse.cz> + + * decl2.c (maybe_make_one_only): Use forced_by_abi instead of + mark_decl_referenced. + (mark_needed): Likewise. + +2013-06-03 Jason Merrill <jason@redhat.com> + + * class.c (mark_type_abi_tags): New. + (check_abi_tags): Use it. + +2013-06-03 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/57419 + * decl2.c (mark_used): Add overload taking a tsubst_flags_t too. + * semantics.c (finish_qualified_id_expr): Use it. + * cp-tree.h: Update. + +2013-06-01 Jan Hubicka <jh@suse.cz> + + * decl2.c (cp_write_global_declarations): Replace same_body_alias + by symbol.cpp_implicit_alias. + +2013-05-30 Jason Merrill <jason@redhat.com> + + PR c++/57404 + * cp-lang.c (cp_classify_record): Handle structs without + TYPE_LANG_SPECIFIC. + + PR c++/52377 + * class.c (common_enclosing_class): New. + * cp-tree.h: Declare it. + * init.c (sort_mem_initializers): Don't splice out a union member + with an NSDMI. + +2013-05-29 Jan Hubicka <jh@suse.cz> + + * tree.c (cp_fix_function_decl_p): Update for new symtab flags. + * decl2.c )var_finalized_p, cp_write_global_declarations): Likewise. + +2013-05-25 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/25666 + * decl2.c (check_classfn): Check for destructors declared as member + templates. + +2013-05-24 Jason Merrill <jason@redhat.com> + + PR c++/56971 + * pt.c (any_template_arguments_need_structural_equality_p): A + TEMPLATE_TEMPLATE_PARM can require structural type comparison. + +2013-05-24 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/19618 + * class.c (check_bitfield_decl): Warn for bool and enum bitfields + with width exceeding the type. + +2013-05-24 Jason Merrill <jason@redhat.com> + + PR c++/57391 + * semantics.c (cxx_eval_constant_expression): Handle FMA_EXPR. + (cxx_eval_trinary_expression): Rename from cxx_eval_vec_perm_expr. + +2013-05-23 Jason Merrill <jason@redhat.com> + + PR c++/57388 + * tree.c (build_ref_qualified_type): Clear + FUNCTION_RVALUE_QUALIFIED for lvalue ref-qualifier. + +2013-05-22 Jason Merrill <jason@redhat.com> + + PR c++/56930 + * call.c (convert_like_real): Use cp_convert_and_check. + * cvt.c (cp_convert_and_check): Use maybe_constant_value. + * semantics.c (cxx_eval_constant_expression): Handle LTGT_EXPR. + (potential_constant_expression_1): Handle OMP_ATOMIC*. + + PR c++/56915 + * semantics.c (maybe_add_lambda_conv_op): Give up if the call op + isn't defined. + +2013-05-22 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/57352 + * parser.c (cp_parser_conversion_type_id): Set up + parser->type_definition_forbidden_message before calling + cp_parser_type_specifier_seq. + +2013-05-22 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/57211 + * method.c (defaultable_fn_check): Avoid do_warn_unused_parameter + warnings about defaulted functions. + +2013-05-21 Paolo Carlini <paolo.carlini@oracle.com> + + * call.c (build_conditional_expr_1): Add location_t parameter. + (build_conditional_expr): Likewise. + * typeck.c (rationalize_conditional_expr, cp_build_array_ref, + get_member_function_from_ptrfunc, build_x_conditional_expr, + cp_build_modify_expr): Update. + * init.c (build_new_1): Likewise. + * cp-tree.h: Update declaration. + +2013-05-20 Jason Merrill <jason@redhat.com> + + PR c++/57016 + * pt.c (instantiation_dependent_r) [TRAIT_EXPR]: Only check type2 + if there is one. + + PR c++/57102 + * decl.c (fndecl_declared_return_type): Also look in + DECL_SAVED_FUNCTION_DATA. + +2013-05-20 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/12288 + * parser.c (cp_parser_parameter_declaration): Check return value + of cp_parser_parse_and_diagnose_invalid_type_name. + +2013-05-20 Jason Merrill <jason@redhat.com> + + PR c++/57319 + * class.c (vbase_has_user_provided_move_assign): New. + * method.c (synthesized_method_walk): Check it. + * cp-tree.h: Declare it. + + PR c++/57325 + * tree.c (build_cplus_array_type): Copy layout info if element + type is complete. + +2013-05-20 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/23608 + * call.c (build_new_op_1): Propagate loc to cp_build_binary_op. + +2013-05-20 Jason Merrill <jason@redhat.com> + + PR c++/57317 + * decl2.c (determine_visibility): Use PRIMARY_TEMPLATE_P to decide + whether a template has its own args. + +2013-05-20 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/57327 + * pt.c (unify_no_common_base): Swap arg and parm arguments to inform. + +2013-05-20 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/10207 + * parser.c (cp_parser_postfix_expression): Use cp_parser_braced_list + instead of cp_parser_initializer_list for compound-literals. + +2013-05-20 Marc Glisse <marc.glisse@inria.fr> + + PR c++/57175 + * typeck.c (check_return_expr): Reverse the alignment comparison. + +2013-05-17 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/18126 + * parser.c (cp_parser_sizeof_operand): As a GNU Extension, parse + correctly sizeof compound-literal; update comments. + +2013-05-16 Marc Glisse <marc.glisse@inria.fr> + + * call.c (build_conditional_expr_1): Use cp_build_binary_op + instead of directly calling fold_build2. + +2013-05-16 Jason Merrill <jason@redhat.com> + + * Make-lang.in (cc1plus$(exeext)): Use link mutex. + + PR c++/57279 + * decl.c (grokdeclarator): Allow member function qualifiers in + TYPENAME context in C++11 mode. + +2013-05-16 Dodji Seketeli <dodji@redhat.com> + + PR c++/56782 - Regression with empty pack expansions + * pt.c (use_pack_expansion_extra_args_p): When at least a + parameter pack has an empty argument pack, and another parameter + pack has no argument pack at all, use the PACK_EXPANSION_EXTRA + mechanism. + +2013-05-15 Paolo Carlini <paolo.carlini@oracle.com> + + * name-lookup.c (pushdecl_maybe_friend_1): Replace pairs of + warning_at and permerror with warning_at/inform and permerror/ + inform, respectively. + +2013-05-15 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/31952 + * name-lookup.c (pushdecl_maybe_friend_1): Diagnose illegal + redeclarations. + +2013-05-14 Jason Merrill <jason@redhat.com> + + PR c++/57243 + * parser.c (cp_parser_range_for): Call complete_type. + + PR c++/57041 + * pt.c (tsubst_copy_and_build): Don't recur into a designator. + +2013-05-14 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/53903 + * method.c (defaulted_late_check): Check for compatible exception + specification out of class explicitly defaulted functions too. + +2013-05-14 Jason Merrill <jason@redhat.com> + + PR c++/56998 + * semantics.c (potential_constant_expression_1): Make sure the + called function is potentially constant. + * call.c (null_ptr_cst_p): Revert earlier change. + +2013-05-13 Jason Merrill <jason@redhat.com> + + PR c++/56998 + * call.c (null_ptr_cst_p): An expression with side-effects can't + be a C++03 null pointer constant. + + PR c++/57041 + * decl.c (reshape_init_class): Handle error_mark_node. + + PR c++/57254 + * typeck.c (merge_types): Propagate ref-qualifier + in METHOD_TYPE case. + + PR c++/57253 + * decl.c (grokdeclarator): Apply ref-qualifier + in the TYPENAME case. + + PR c++/57252 + * decl.c (decls_match): Compare ref-qualifiers. + +2013-05-10 Jason Merrill <jason@redhat.com> + + PR c++/57196 + * pt.c (convert_template_argument): Use dependent_template_arg_p, + not uses_template_parms. + + PR c++/57047 + * semantics.c (cxx_fold_indirect_ref): Fix thinko. + + PR c++/55149 + * semantics.c (add_capture): Error rather than abort on copy + capture of VLA. + * typeck.c (maybe_warn_about_returning_address_of_local): Don't + warn about capture proxy. + +2013-05-09 Jason Merrill <jason@redhat.com> + + * decl.c (cp_finish_decl): Only check VLA bound in C++1y mode. + + PR c++/57222 + * pt.c (lookup_template_class_1): Handle getting a template + template parameter as D1. + + N3639 C++1y VLA diagnostics + * decl.c (grokdeclarator): Complain about reference, pointer, or + typedef to VLA. + (create_array_type_for_decl): Complain about array of VLA. + * pt.c (tsubst): Likewise. + * rtti.c (get_tinfo_decl): Talk about "array of runtime bound". + * semantics.c (finish_decltype_type): Complain about decltype of VLA. + * typeck.c (cp_build_addr_expr_1): Complain about VLA. + (cxx_sizeof_or_alignof_type): Likewise. + + N3639 C++1y VLA support + * decl.c (compute_array_index_type): Allow VLAs in C++1y mode. + (check_array_initializer): Allow VLA init. + (reshape_init_array_1): Adjust. + (cp_finish_decl): Check for invalid VLA length. + * typeck2.c (process_init_constructor_array): Adjust. + (store_init_value): Use build_vec_init for VLAs. + * semantics.c (add_capture): Capture VLA as ptr+len. + (vla_capture_type): New. + (build_capture_proxy): Rebuild the VLA. + * typeck.c (build_simple_component_ref): Split out from... + (build_ptrmemfunc_access_expr): ...here. + * tree.c (array_of_runtime_bound_p): New. + * init.c (throw_bad_array_length): New. + (build_vec_init): Use it. + * parser.c (cp_convert_range_for): When iterating over a VLA, + use it directly rather than bind a reference. + * cp-tree.h: Declare new functions. + +2013-05-08 Jason Merrill <jason@redhat.com> + + * except.c (is_admissible_throw_operand_or_catch_parameter): Check + variably_modified_type_p. + (expand_start_catch_block): Mark the typeinfo used here. + * semantics.c (finish_handler_parms): Not here. + + * error.c (dump_type_suffix): Try harder on VLA length. + + Core 624/N2932 + * init.c (throw_bad_array_new_length): New. + (build_new_1): Use it. Don't warn about braced-init-list. + (build_vec_init): Use it. + * call.c (build_operator_new_call): Use it. + + PR c++/57068 + * decl.c (grokdeclarator): Warn about ref-qualifiers here. + * parser.c (cp_parser_ref_qualifier_seq_opt): Not here. + * error.c (maybe_warn_cpp0x): s/0x/11/. + +2013-05-08 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/51226 + * parser.c (cp_parser_enum_specifier): Handle nested_name_specifier + == error_mark_node. + +2013-05-06 Marc Glisse <marc.glisse@inria.fr> + + * typeck.c (cp_build_binary_op): Call save_expr before + build_vector_from_val. + +2013-05-06 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/57183 + * decl.c (cp_finish_decl): After do_auto_deduction copy the + qualifers with cp_apply_type_quals_to_decl. + +2013-05-05 Paolo Carlini <paolo.carlini@oracle.com> + + * pt.c (convert_nontype_argument): Add missing whitespace in + error message. + +2013-05-04 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/53745 + * decl.c (build_enumerator): Improve error message. + +2013-05-03 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/14283 + * parser.c (cp_parser_diagnose_invalid_type_name): Improve error + messages for template types and fix column numbers. + +2013-05-01 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/57132 + * pt.c (tsubst_copy_and_build, MODOP_EXPR): Increase / decrease + c_inhibit_evaluation_warnings around build_x_modify_expr call. + +2013-05-01 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/57092 + * semantics.c (finish_decltype_type): Handle instantiated template + non-type arguments. + +2013-04-28 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/56450 + * semantics.c (finish_decltype_type): Handle COMPOUND_EXPR. + +2013-04-26 Jakub Jelinek <jakub@redhat.com> + + * error.c (cp_print_error_function): Adjust file_name_as_prefix + caller. + +2013-04-25 Jason Merrill <jason@redhat.com> + + PR c++/56859 + * typeck.c (cxx_alignas_expr): Handle value-dependence properly. + + PR c++/50261 + * init.c (perform_member_init): Call reshape_init. + +2013-04-24 Jason Merrill <jason@redhat.com> + + PR c++/53721 + * parser.c (cp_parser_postfix_dot_deref_expression): Fix thinko. + +2013-04-24 Paolo Carlini <paolo.carlini@oracle.com> + + * typeck.c (cxx_sizeof_or_alignof_type): Change -Wpointer-arith + pedwarn to simply use OPT_Wpointer_arith. + (cp_build_unary_op): Likewise. + +2013-04-24 Jason Merrill <jason@redhat.com> + + N3648: init-captures are named. + * semantics.c (add_capture): Don't prepend "__" to init-captures. + (build_capture_proxy): Adjust. + * error.c (dump_simple_decl): Check DECL_NORMAL_CAPTURE_P. + + N3648: Allow braced and parenthesized initializers. + * parser.c (cp_parser_lambda_introducer): Use cp_parser_initializer. + * pt.c (tsubst) [DECLTYPE_TYPE]: Handle DECLTYPE_FOR_INIT_CAPTURE. + * semantics.c (lambda_capture_field_type): Use do_auto_deduction. + (add_capture): Collapse a parenthesized initializer into a single + expression. + * cp-tree.h (DECLTYPE_FOR_INIT_CAPTURE): New. + +2013-04-24 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/56970 + * init.c (build_offset_ref): Add tsubst_flags_t parameter. + * semantics.c (finish_qualified_id_expr): Likewise. + (finish_id_expression): Update. + * typeck.c (cp_build_addr_expr_1): Likewise. + * pt.c (tsubst_qualified_id, resolve_nondeduced_context): Likewise. + * cp-tree.h: Update declarations. + +2013-04-22 Jason Merrill <jason@redhat.com> + + Core 1586 + * parser.c (cp_parser_unqualified_id): Handle ~auto. + (cp_parser_pseudo_destructor_name): Likewise. + (cp_parser_postfix_dot_deref_expression): Adjust. + (cp_lexer_nth_token_is_keyword): New. + * semantics.c (finish_pseudo_destructor_expr): Handle ~auto. + * typeck.c (lookup_destructor): Handle ~auto. + + * pt.c (fn_type_unification): Push tinst level around + type_unification_real if we aren't explaining. + * cp-tree.h (TFF_NO_TEMPLATE_BINDINGS): New. + * error.c (dump_function_decl): Respect it. + (subst_to_string): Pass it. + + PR c++/48665 + * rtti.c (get_typeid): Diagnose qualified function type. + * pt.c (tsubst) [POINTER_TYPE]: Likewise. + + * error.c (dump_aggr_type): Fix lambda detection. + (dump_simple_decl): Pretty-print capture field. + + N3323 + * cvt.c (build_expr_type_conversion): Two conversions that return + the same type aren't necessarily ambiguous. + + N3648 + * parser.c (cp_parser_lambda_introducer): Make lambda capture init + pedwarn unconditional except in C++1y mode. + + * semantics.c (potential_constant_expression_1): Don't crash on + 'this' in NSDMI. + + Core 1612 + * semantics.c (finish_id_expression): Reject capture of anonymous + union member. + + Core 1609 + * decl2.c (check_default_args): Check for pack expansion. + + * mangle.c (write_type): Mangle decltype(auto). + +2013-04-19 Jason Merrill <jason@redhat.com> + + N3638 changes to return type deduction + * decl.c (undeduced_auto_decl): New. + (require_deduced_type): New. + (fndecl_declared_return_type): New. + (decls_match): Use it. + (duplicate_decls): Don't check for auto return. + (grokdeclarator): Reject virtual auto. + * class.c (resolve_address_of_overloaded_function): Handle + auto function templates. + * decl2.c (mark_used): Use undeduced_auto_decl, require_deduced_type. + * cp-tree.h: Declare new fns. + * error.c (dump_function_decl): Use fndecl_declared_return_type. + * search.c (check_final_overrider): Likewise. + * pt.c (make_decltype_auto): New. + (do_auto_deduction): Require plain decltype(auto). + (is_auto): Adjust. + + DR 941 + * decl.c (duplicate_decls): Don't propagate DECL_DELETED_FN to + template specializations. + +2013-04-16 Ed Smith-Rowland <3dw4rd@verizon.net> + + Implement n3599 - Literal operator templates for strings. + * parser.c (make_string_pack (tree value)): New function. + (cp_parser_userdef_string_literal (cp_token *)): Use it + to construct calls to character string literal operator templates. + (cp_parser_template_declaration_after_export): Check for new string + literal operator template parameter form. + +2013-04-15 Jason Merrill <jason@redhat.com> + + * pt.c (tsubst) [DECLTYPE_TYPE]: Use tsubst_copy_and_build. + + PR c++/52748 + * pt.c (tsubst) [DECLTYPE_TYPE]: If ~id is an expression + rather than a destructor name, it isn't an unqualified-name. + (tsubst_copy_and_build): Pass down decltype_flag to operator + handling code, too. + + PR c++/56388 + * semantics.c (insert_capture_proxy): Just use index 1 in the + stmt_list_stack. + +2013-04-12 Jakub Jelinek <jakub@redhat.com> + + * error.c (cp_print_error_function, + print_instantiation_partial_context_line, + maybe_print_constexpr_context): Colorize locus strings. + +2013-04-11 Jason Merrill <jason@redhat.com> + + PR c++/52748 + * parser.c (complain_flags): New. + (cp_parser_postfix_expression): Use it. + (cp_parser_unary_expression): Likewise. + (cp_parser_binary_expression): Likewise. + (cp_parser_assignment_expression): Likewise. + (cp_parser_expression): Likewise. + (cp_parser_postfix_open_square_expression): Take decltype_p. + (cp_parser_builtin_offsetof): Adjust. + (cp_convert_range_for): Pass complain to finish_unary_op_expr. + * decl2.c (grok_array_decl): Add decltype_p parm. + * cp-tree.h: Adjust prototype. + * semantics.c (finish_unary_op_expr): Add complain parm. + +2013-04-11 Jakub Jelinek <jakub@redhat.com> + + PR c++/56895 + * call.c (null_ptr_cst_p): Call fold_non_dependent_expr_sfinae before + calling maybe_constant_value for C++98. + +2013-04-11 Jason Merrill <jason@redhat.com> + + PR c++/56901 + * semantics.c (lambda_capture_field_type, lambda_proxy_type): + Strip references before checking WILDCARD_TYPE_P. + +2013-04-11 Paolo Carlini <paolo.carlini@oracle.com> + + * call.c (build_conditional_expr_1, build_over_call): Protect + error calls with complain & tf_error. + * typeck.c (finish_class_member_access_expr, cp_build_binary_op, + build_x_unary_op, cp_build_unary_op, cp_build_compound_expr, + build_ptrmemfunc): Likewise. + (lookup_destructor): Take tsubst_flags_t parameter, adjust. + + * cvt.c (warn_ref_binding): Rename to diagnose_ref_binding. + (convert_to_reference): Adjust. + +2013-04-11 Jason Merrill <jason@redhat.com> + + * pt.c (tsubst_copy) [VAR_DECL]: Don't call tsubst for + local variables, look them up instead. + (tsubst_decl) [VAR_DECL]: Remove handling for anonymous union + proxies and substitution in unevaluated context. + (tsubst_expr) [OMP_FOR]: Instantiate OMP_FOR_PRE_BODY + before the iterators. + + PR c++/23055 + * pt.c (uses_deducible_template_parms): New. + (deducible_array_bound, deducible_expression): New. + (deducible_template_args): New. + (unify_one_argument): Call uses_deducible_template_parms. + +2013-04-11 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/56913 + * typeck2.c (build_m_component_ref): Protect error calls with + (complain & tf_error). + +2013-04-11 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/54216 + * parser.c (cp_parser_enum_specifier): Check for empty + anonymous enums and anonymous scoped enums. + +2013-04-10 Jakub Jelinek <jakub@redhat.com> + + PR c++/56895 + * typeck.c (cp_build_binary_op): Call fold_non_dependent_expr_sfinae + first before calling maybe_constant_value for warn_for_div_by_zero + or invalid shift count warning purposes. + +2013-04-09 Jason Merrill <jason@redhat.com> + + PR c++/25466 + * rtti.c (build_typeid): Check the address of the argument + rather than looking for an INDIRECT_REF. + +2013-04-04 Jason Merrill <jason@redhat.com> + + PR c++/56838 + PR c++/17232 + * typeck2.c (abstract_virtuals_error_sfinae): Disable + complete_type again. + +2013-04-08 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/56871 + * decl.c (validate_constexpr_redeclaration): Allow an explicit + specialization to be different wrt the constexpr specifier. + +2013-04-06 Jason Merrill <jason@redhat.com> + + * parser.c (cp_parser_std_attribute): Treat [[noreturn]] like GNU + noreturn attribute. + +2013-04-05 Ed Smith-Rowland <3dw4rd@verizon.net> + + * parser.c (cp_parser_ref_qualifier_seq_opt): Move to + cp_parser_ref_qualifier_opt. Error if more than one ref-qual found. + +2013-04-03 Jason Merrill <jason@redhat.com> + + * cp-tree.h (FUNCTION_OR_METHOD_TYPE_CHECK): Remove. + (TYPE_RAISES_EXCEPTIONS): Use FUNC_OR_METHOD_CHECK instead. + (FUNCTION_REF_QUALIFIED, FUNCTION_RVALUE_QUALIFIED): Likewise. + + * mangle.c (write_type): When writing a function type with + function-cv-quals, don't add the unqualified type as a + substitution candidate. + +2013-04-03 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/56815 + * typeck.c (cp_build_unary_op): Change -Wpointer-arith permerror to + pedwarn. + +2013-04-03 Jakub Jelinek <jakub@redhat.com> + + PR debug/56819 + * tree.c (strip_typedefs): Copy NON_DEFAULT_TEMPLATE_ARGS_COUNT + from args to new_args. + (strip_typedefs_expr): Copy NON_DEFAULT_TEMPLATE_ARGS_COUNT from t to + r instead of doing {S,G}ET_NON_DEFAULT_TEMPLATE_ARGS_COUNT. + +2013-04-02 Jason Merrill <jason@redhat.com> + + PR c++/56821 + * mangle.c (write_function_type): Mangle ref-qualifier. + (write_nested_name): Likewise. + (canonicalize_for_substitution): Preserve ref-qualifier. + (write_type): Likewise. + + PR c++/34949 + * decl.c (begin_destructor_body): Clobber the object in a cleanup. + +2013-04-02 Paolo Carlini <paolo.carlini@oracle.com> + + * friend.c (do_friend): Use COMPLETE_OR_OPEN_TYPE_P. + * pt.c (find_parameter_packs_r): Use TYPE_ALIAS_P and TYPE_TI_ARGS. + (for_each_template_parm_r): Use TYPE_TI_ARGS. + +2013-04-02 Paolo Carlini <paolo.carlini@oracle.com> + + * cp-tree.h (TAGGED_TYPE_P): Remove. + (IS_OVERLOAD_TYPE): Rename to OVERLOAD_TYPE_P, adjust. + (TYPE_ANONYMOUS_P): Adjust. + * call.c (build_new_op_1): Likewise. + * class.c (find_abi_tags_r): Likewise. + * decl.c (warn_misplaced_attr_for_class_type, start_decl, + type_is_deprecated): Likewise. + * decl2.c (grokfield, min_vis_r): Likewise. + * pt.c (get_template_info): Likewise. + * tree.c (handle_abi_tag_attribute): Likewise. + +2013-04-01 Jason Merrill <jason@redhat.com> + + * semantics.c (maybe_constant_value): Check + instantiation_dependent_expression_p. + * pt.c (build_non_dependent_expr): Don't check it here. + + PR c++/56772 + * init.c (build_new): Don't try to process an array initializer + at template definition time. + + PR c++/56793 + * typeck.c (finish_class_member_access_expr): Handle enum scope. + + PR c++/56794 + * parser.c (cp_parser_range_for): Don't try to do auto deduction + in a template if the type of the range is incomplete. + + * call.c (add_function_candidate): Take the address of 'this' here. + (build_over_call): And here. + (build_new_method_call_1, build_op_call_1): Not here. + (build_user_type_conversion_1): Or here. + (add_candidates): Adjust. + + * cxx-pretty-print.h (pp_cxx_cv_qualifiers): New. + * class.c (same_signature_p): Use type_memfn_quals. + * cp-tree.h (TYPE_RAISES_EXCEPTIONS): Use + FUNCTION_OR_METHOD_TYPE_CHECK. + * error.c (dump_type_suffix): Add padding before cv-qualifiers. + * pt.c (unify): Use static_fn_type. + +2013-04-01 Bronek Kozicki <b.kozicki@gmail.com> + Jason Merrill <jason@redhat.com> + + Implement N2439 (ref-qualifiers for 'this') + * cp-tree.h (FUNCTION_REF_QUALIFIED): New. + (FUNCTION_RVALUE_QUALIFIED): New. + (FUNCTION_OR_METHOD_TYPE_CHECK): New. + (cpp0x_warn_str): Add CPP0X_REF_QUALIFIER. + (cp_ref_qualifier): New enum. + (cp_declarator): Add ref_qualifier. + * parser.c (cp_parser_ref_qualifier_seq_opt): New. + (cp_parser_direct_declarator): Use it. + (make_call_declarator): Adjust. + (cp_parser_lambda_declarator_opt): Adjust. + * call.c (add_function_candidate): Handle ref-qualifier overload + resolution semantics. + (standard_conversion): Adjust. + * class.c (add_method, same_signature_p): Compare ref-qualifiers. + * decl.c (grokdeclarator): Handle ref-qualifiers. + (grokfndecl): Check for invalid ref-qualifiers. + (static_fn_type, revert_static_member_fn): Adjust. + * decl2.c (build_memfn_type): Handle ref-qualifiers. + (check_classfn): Check them. + (cp_reconstruct_complex_type): Retain them. + * error.c (dump_ref_qualifier): New. + (dump_type_suffix, dump_function_decl): Use it. + (maybe_warn_cpp0x): Handle CPP0X_REF_QUALIFIER. + * pt.c (tsubst, tsubst_function_type): Instantiate ref-quals. + (unify): Retain them. + * tree.c (cp_check_qualified_type): New. + (cp_build_qualified_type_real): Keep exception spec and ref-qual. + (build_ref_qualified_type): New. + (strip_typedefs, build_exception_variant): Keep ref-qualifier. + (cp_build_type_attribute_variant): Keep ref-qualifier. + * typeck.c (merge_types): Keep ref-qualifier. + (structural_comptypes): Compare ref-qualifier. + (type_memfn_rqual): New. + (apply_memfn_quals): Take ref-qual argument. + * typeck2.c (build_m_component_ref): Check ref-qualifier. + +2013-04-01 Paolo Carlini <paolo.carlini@oracle.com> + + * cp-tree.h (DECL_UNBOUND_CLASS_TEMPLATE_P): Remove. + (DECL_FUNCTION_TEMPLATE_P): Adjust. + + * cxx-pretty-print.c (pp_cxx_nested_name_specifier, + pp_cxx_qualified_id): Use get_containing_scope. + * parser.c (cp_parser_class_head): Likewise. + * pt.c (push_template_decl_real): Likewise. + + * decl2.c (import_export_decl): Use DECL_TEMPLOID_INSTANTIATION. + * pt.c (unify): Use CP_INTEGRAL_TYPE_P. + +2013-03-31 Paolo Carlini <paolo.carlini@oracle.com> + + * decl2.c (collect_candidates_for_java_method_aliases): Use + DECL_CLASS_SCOPE_P. + * name-lookup.c (pushtag_1) Use TYPE_FUNCTION_SCOPE_P. + (pushdecl_maybe_friend_1): Use DECL_DECLARES_FUNCTION_P. + * decl.c (duplicate_decls): Likewise. + * parser.c (cp_parser_template_declaration_after_export): Likewise, + also DECL_DECLARES_TYPE_P. + * pt.c (instantiate_class_template_1): Likewise. + * search.c (lookup_field_1): Use DECL_DECLARES_TYPE_P. + (lookup_field_r): Likewise. + (friend_accessible_p): Use DECL_DECLARES_FUNCTION_P. + (lookup_fnfields_slot_nolazy): Likewise. + * semantics.c (finish_member_declaration): Likewise. + * typeck.c (convert_for_initialization): Use TYPE_REFFN_P. + +2013-03-29 Gabriel Dos Reis <gdr@integrable-solutions.net> + + * pt.c (template_parms_to_args): Fix typo in comment. + +2013-03-29 Paolo Carlini <paolo.carlini@oracle.com> + + * call.c (build_op_call_1): Use TYPE_PTRFN_P and TYPE_REFFN_P. + +2013-03-29 Paolo Carlini <paolo.carlini@oracle.com> + + * call.c (add_builtin_candidate): Use TYPE_PTR_P and VOID_TYPE_P. + (build_op_call_1): Likewise. + (build_over_call): Likewise. + (compare_ics): Likewise. + * class.c (build_base_path): Likewise. + (resolve_address_of_overloaded_function): Likewise. + * cp-tree.h: Likewise. + * cvt.c (cp_convert_to_pointer): Likewise. + (convert_to_reference): Likewise. + (ocp_convert): Likewise. + (convert_force): Likewise, tidy. + * cxx-pretty-print.c (pp_cxx_postfix_expression): Likewise. + (pp_cxx_ptr_operator): Likewise. + * decl.c (duplicate_decls): Likewise. + (start_decl): Likewise. + (grok_op_properties): Likewise. + (start_preparsed_function): Likewise. + (store_parm_decls): Likewise. + (finish_function): Likewise. + * decl2.c (delete_sanity): Likewise. + (acceptable_java_type): Likewise. + (grokbitfield): Likewise. + (cp_reconstruct_complex_type): Likewise. + * error.c (dump_type_prefix): Likewise. + (dump_expr): Likewise. + * except.c (push_eh_cleanup): Likewise. + (complete_ptr_ref_or_void_ptr_p): Likewise. + (can_convert_eh): Likewise. + * init.c (build_new_1): Likewise. + (build_delete): Likewise. + (build_vec_delete): Likewise. + * mangle.c (write_type): Likewise. + * parser.c (lookup_literal_operator): Likewise. + * pt.c (convert_nontype_argument_function): Likewise. + (convert_nontype_argument): Likewise. + (tsubst): Likewise. + (unify): Likewise. + (dependent_type_p_r): Likewise. + * rtti.c (build_headof): Likewise. + (build_typeid): Likewise. + (build_dynamic_cast_1): Likewise. + (target_incomplete_p): Likewise. + (typeinfo_in_lib_p): Likewise. + * semantics.c (finish_omp_for): Likewise. + (cxx_eval_call_expression): Likewise. + (maybe_resolve_dummy): Likewise. + * tree.c (build_target_expr): Likewise. + (cp_build_qualified_type_real): Likewise. + * typeck.c (composite_pointer_type_r): Likewise. + (composite_pointer_type): Likewise. + (comp_except_types): Likewise. + (cxx_sizeof_nowarn): Likewise. + (string_conv_p): Likewise. + (cp_build_array_ref): Likewise. + (cp_build_function_call_vec): Likewise, also use TYPE_PTRFN_P. + (pointer_diff): Likewise. + (cp_build_addr_expr_1): Likewise. + (cp_build_unary_op): Likewise. + (build_static_cast_1): Likewise. + (cp_build_c_cast): Likewise. + (comp_ptr_ttypes_real): Likewise. + (ptr_reasonably_similar): Likewise. + (comp_ptr_ttypes_const): Likewise. + (casts_away_constness): Likewise. + (check_literal_operator_args): Likewise. + * typeck2.c (build_x_arrow): Likewise. + (add_exception_specifier): Likewise. + +2013-03-29 Jason Merrill <jason@redhat.com> + + N3582 + * cp-tree.h (AUTO_IS_DECLTYPE): New. + * parser.c (cp_parser_decltype): Handle decltype(auto). + (cp_parser_type_id_1): Allow auto without a late-specified + return in C++1y. + (cp_parser_primary_expression): Use the return value of + finish_parenthesized_expr. + (cp_parser_transaction_expression): Likewise. + * semantics.c (force_paren_expr): New. + (finish_parenthesized_expr): Use it. + * call.c (build_conditional_expr_1): Likewise. + * pt.c (do_auto_deduction): Handle decltype(auto). + (tsubst_copy): Handle PAREN_EXPR. + (tsubst_copy_and_build): Likewise. + * error.c (dump_expr): Handle PAREN_EXPR. + * cxx-pretty-print.c (pp_cxx_expression): Likewise. + * mangle.c (write_expression): Ignore PAREN_EXPR. + + * parser.c (cp_parser_decltype_expr): Split out... + (cp_parser_decltype): ...from here. + + PR c++/56774 + PR c++/35722 + * pt.c (unify_pack_expansion): Fix indexing. + +2013-03-29 Gabriel Dos Reis <gdr@integrable-solutions.net> + + * call.c (build_java_interface_fn_ref): Likewise. + (make_temporary_var_for_ref_to_temp): Likewise. + * class.c (check_field_decls): Likewise. + (layout_class_type): Likewise. + (finish_struct_1): Likewise. + (fixed_type_or_null): Likewise. + (get_vtbl_decl_for_binfo): Likewise. + * cp-gimplify.c (omp_var_to_track): Likewise. + (cp_genericize_r): Likewise. + * cp-objcp-common.c (cxx_warn_unused_global_decl): Likewise. + * cp-tree.h (LANG_DECL_HAS_MIN): Likewise. + (DECL_DISCRIMINATOR_P): Likewise. + * decl.c (poplevel): Likewise. + (decls_match): Likewise. + (duplicate_decls): Likewise. + (decl_jump_unsafe): Likewise. + (start_decl): Likewise. + (check_for_uninitialized_const_var): Likewise. + (make_rtl_for_nonlocal_decl): Likewise. + (cp_finish_decl): Likewise. + (expand_static_init): Likewise. + (local_variable_p): Likewise. + (maybe_register_incomplete_var): Likewise. + * decl2.c (grokfield): Likewise. + (comdat_linkage): Likewise. + (determine_visibility): Likewise. + (import_export_decl): Likewise. + (prune_vars_needing_no_initialization): Likewise. + (decl_maybe_constant_var_p): Likewise. + * error.c (dump_simple_decl): Likewise. + (dump_template_decl): Likewise. + (cp_printer): Likewise. + * except.c (build_throw): Likewise. + * init.c (build_vtbl_address): Likewise. + (member_init_ok_or_else): Likewise. + (build_aggr_init): Likewise. + (expand_aggr_init_1): Likewise. + (build_offset_ref): Likewise. + (constant_value_1): Likewise. + * mangle.c (write_mangled_name): Likewise. + (write_prefix): Likewise. + * name-lookup.c (supplement_binding_1): Likewise. + (add_decl_to_level): Likewise. + (pushdecl_maybe_friend_1): Likewise. + (check_for_out_of_scope_variable): Likewise. + (validate_nonmember_using_decl): Likewise. + (lookup_name_innermost_nonclass_level_1): Likewise. + (lookup_arg_dependent_1): Likewise. + * parser.c (cp_parser_lambda_introducer): Likewise. + (cp_parser_template_argument): Likewise. + (cp_parser_single_declaration): Likewise. + * pt.c (convert_nontype_argument): Likewise. + (instantiate_class_template_1): Likewise. + (tsubst_decl): Likewise. + (tsubst_expr): Likewise. + (do_decl_instantiation): Likewise. + (do_type_instantiation): Likewise. + (regenerate_decl_from_template): Likewise. + (always_instantiate_p): Likewise. + (instantiate_decl): Likewise. + (type_dependent_expression_p): Likewise. + (build_non_dependent_expr): Likewise. + * repo.c (repo_emit_p): Likewise. + * rtti.c (build_dynamic_cast_1): Likewise. + * search.c (shared_member_p): Likewise. + * semantics.c (outer_var_p): Likewise. + (finish_id_expression): Likewise. + (finish_omp_clauses): Likewise. + (finish_decltype_type): Likewise. + (ensure_literal_type_for_constexpr_object): Likewise. + * tree.c (lvalue_kind): Likewise. + (bot_replace): Likewise. + (cp_tree_equal): Likewise. + (handle_init_priority_attribute): Likewise. + (decl_storage_duration): Likewise. + * typeck.c (cxx_sizeof_expr): Likewise. + (cxx_alignof_expr): Likewise. + (decay_conversion): Likewise. + (build_class_member_access_expr): Likewise. + (cp_build_array_ref): Likewise. + (cxx_mark_addressable): Likewise. + (maybe_warn_about_returning_address_of_local): Likewise. + (check_return_expr): Likewise. + * typeck2.c (cxx_readonly_error): Likewise. + (abstract_virtuals_error_sfinae): Likewise. + (cxx_incomplete_type_diagnostic): Likewise. + +2013-03-28 Lawrence Crowl <crowl@google.com> + + * Make-lang.in + (CXX_PARSER_H): Add header dependence. + * cp-tree.h + (extern debug (cp_binding_level &)): New. + (extern debug (cp_binding_level *)): New. + * name-lookup.h + (debug (cp_binding_level &)): New. + (debug (cp_binding_level *)): New. + * parser.c + (debug (cp_parser &)): New. + (debug (cp_parser *)): New. + (debug (cp_token &)): New. + (debug (cp_token *)): New. + (debug (vec<cp_token, va_gc> &)): New. + (debug (vec<cp_token, va_gc> *)): New. + * parser.c: Add header dependence. + (extern debug (cp_parser &)): New. + (extern debug (cp_parser *)): New. + (extern debug (cp_token &)): New. + (extern debug (cp_token *)): New. + (extern debug (vec<cp_token, va_gc> &)): New. + (extern debug (vec<cp_token, va_gc> *)): New. + +2013-03-28 Jason Merrill <jason@redhat.com> + + PR c++/17232 + PR c++/52748 + * typeck2.c (abstract_virtuals_error_sfinae): Don't complete + the type if tf_decltype is set. + * pt.c (fn_type_unification): Add decltype_p parm. + (get_bindings): Adjust. + * cp-tree.h: Adjust. + * class.c (resolve_address_of_overloaded_function): Adjust. + * call.c (add_template_candidate_real, print_z_candidate): Adjust. + + PR c++/56679 + * parser.c (cp_parser_sizeof_pack): Split out from... + (cp_parser_sizeof_operand): ...here. Require (id). + + PR c++/56701 + * semantics.c (finish_this_expr): 'this' is an rvalue. + * typeck.c (cp_build_indirect_ref): Handle NOP_EXPR of 'this'. + + PR c++/56710 + * semantics.c (finish_member_declaration): Don't push closure + members. + + * name-lookup.c (pushdecl_maybe_friend_1): Use + nonlambda_method_basetype and current_nonlambda_class_type. + + PR c++/56728 + * semantics.c (potential_constant_expression_1) [NOP_EXPR]: Reject + conversion from integer to pointer. + (cxx_eval_constant_expression): Likewise. + (cxx_eval_indirect_ref): Use the folded operand if we still think + this might be constant. + +2013-03-28 Paolo Carlini <paolo.carlini@oracle.com> + Manuel Lopez-Ibanez <manu@gcc.gnu.org> + + PR c++/56725 + * call.c (convert_like_real): Change series of two permerrors + to permerror + inform (and likewise for two errors). + (build_new_method_call_1): Likewise. + * typeck.c (convert_for_initialization): Change additional + warning or error to inform. + +2013-03-28 Gabriel Dos Reis <gdr@integrable-solutions.net> + + * cp-tree.h (next_aggr_init_expr_arg): Remove static specifier. + (first_aggr_init_expr): Likewise. + (more_aggr_init_expr_args_p): Likewise. + (type_of_this_parm): Likewise. + (class_of_this_parm): Likewise. + * name-lookup.h (get_global_value_if_present): Likewise. + (is_typename_at_global_scope): Likewise. + +2013-03-28 Paolo Carlini <paolo.carlini@oracle.com> + + * call.c (joust): Don't call inform for a permerror returning false. + * parser.c (cp_parser_check_class_key): Likewise. + * pt.c (tsubst_copy_and_build): Likewise. + +2013-03-27 Jason Merrill <jason@redhat.com> + + PR c++/56749 + * semantics.c (finish_qualified_id_expr): Return early + for enum scope. + +2013-03-26 Gabriel Dos Reis <gdr@integrable-solutions.net> + + * call.c (build_new_method_call_1): Use INDIRECT_REF_P. + * cvt.c (convert_to_void): Likewise. + * error.c (dump_expr): Likewise. + * mangle.c (write_expression): Likewise. + * parser.c (cp_parser_template_argument): Likewise. + * pt.c (convert_nontype_argument): Likewise. + (tsubst_copy_and_build): Likewise. + * rtti.c (build_typeid): Likewise. + * semantics.c (finish_call_expr): Likewise. + (finish_decltype_type): Likewise. + (build_data_member_initialization): Likewise. + * tree.c (is_dummy_object): Likewise. + * typeck.c (decay_conversion): Likewise. + (build_class_member_access_expr): Likewise. + (cp_build_addr_expr_1): Likewise. + (unary_complex_lvalue): Likewise. + (check_return_expr): Likewise. + * typeck2.c (cxx_readonly_error): Likewise. + +2013-03-26 Jason Merrill <jason@redhat.com> + + PR c++/52597 + * typeck.c (invalid_nonstatic_memfn_p): Use get_first_fn. Take tree. + * semantics.c (finish_decltype_type): Check it before type_unknown_p. + * cp-tree.h: Adjust prototype. + + PR c++/45282 + * typeck2.c (build_m_component_ref): Handle prvalue object. + +2013-03-26 Gabriel Dos Reis <gdr@integrable-solutions.net> + + * cp-gimplify.c (cp_genericize_r): Use VAR_OR_FUNCTION_DECL_P. + * decl.c (duplicate_decls): Likewise. + (cp_finish_decl): Likewise. + (check_class_member_definition_namespace): Likewise. + * decl2.c (grokfield): Likewise. + (decl_needed_p): Likewise. + (import_export_decl): Likewise. + (mark_used): Likewise. + * name-lookup.c (pushdecl_maybe_friend_1): Likewise. + * pt.c (push_access_scope): Likewise. + (instantiate_decl): Likewise. + * ptree.c (cxx_print_decl): Likewise. + * repo.c (repo_emit_p): Likewise. + * semantics.c (note_decl_for_pch): Likewise. + * tree.c (decl_linkage): Likewise. + +2013-03-26 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/55951 + * decl.c (check_array_designated_initializer): Handle CONST_DECL + as ce->index. + +2013-03-26 Paolo Carlini <paolo.carlini@oracle.com> + + * decl.c (grokfndecl): Handle separately <inline> and <constexpr> + error messages. + + * decl.c (grokdeclarator): Declare typedef_p and use it everywhere. + +2013-03-25 Jason Merrill <jason@redhat.com> + + PR c++/56699 + * semantics.c (maybe_resolve_dummy): Make sure that the enclosing + class is derived from the type of the object. + + PR c++/52014 + * semantics.c (lambda_expr_this_capture): Don't capture 'this' in + unevaluated context. + +2013-03-25 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/56722 + * decl.c (cp_finish_decl): Check DECL_LANG_SPECIFIC before + DECL_TEMPLATE_INSTANTIATION. + +2013-03-22 Jason Merrill <jason@redhat.com> + + PR c++/56684 + * pt.c (instantiation_dependent_r): Check DECL_INITIAL of VAR_DECL + and CONST_DECL. + +2013-03-21 Gabriel Dos Reis <gdr@integrable-solutions.net> + + * cp-tree.h (identifier_p): New. + * call.c: Throughout, call identifier_p insstead of direct + comparaison of TREE_CODE against IDENTIFIER_NODE. + * decl.c: Likewisse. + * decl2.c: Likewise. + * init.c: Likewise. + * mangle.c: Likewise. + * name-lookup.c: Likewise. + * parser.c: Likewise. + * pt.c: Likewise. + * search.c: Likewise. + * semantics.c: Likewise. + * tree.c: Likewise. + * typeck.c: Likewise. + * typeck2.c: Likewise. + +2013-03-21 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/48087 + * pt.c (convert_nontype_argument): Count werrorcount as warnings. + * call.c (build_temp): Likewise. + * method.c (synthesize_method): Likewise. + * typeck.c (convert_for_initialization): Likewise. + +2013-03-21 Marc Glisse <marc.glisse@inria.fr> + + * call.c (build_conditional_expr_1): Fold VEC_COND_EXPR. + +2013-03-21 Richard Biener <rguenther@suse.de> + + * error.c (cp_printer): Use DECL_HAS_DEBUG_EXPR_P instead of + DECL_DEBUG_EXPR_IS_FROM. Guard properly. + +2013-03-20 Jason Merrill <jason@redhat.com> + + PR c++/56646 + * parser.c (cp_parser_late_return_type_opt): Save and restore + current_class_ptr/ref. + + PR c++/54532 + * expr.c (cplus_expand_constant): Do nothing if the class is + incomplete. + * semantics.c (reduced_constant_expression_p): Allow PTRMEM_CST. + * typeck2.c (store_init_value): Use reduced_constant_expression_p. + * decl.c (maybe_register_incomplete_var): Handle PTRMEM_CST. + (complete_vars): Likewise. + + * name-lookup.c (get_anonymous_namespace_name): Never use + get_file_function_name. + + * pt.c (retrieve_specialization): Handle null tmpl argument. + + PR c++/17232 + PR c++/56642 + * pt.c (tsubst_decl): Check return value of register_specialization. + * typeck2.c (abstract_virtuals_error_sfinae): Re-apply complete_type + change. + +2013-03-17 Jason Merrill <jason@redhat.com> + + PR c++/54359 + PR c++/56639 + * parser.c (cp_parser_direct_declarator): Bail if we see a + qualified-id not at namespace scope. + + PR c++/17232 + PR c++/56642 + * typeck2.c (abstract_virtuals_error_sfinae): Revert complete_type + change for now. + +2013-03-16 Jason Merrill <jason@redhat.com> + + * decl.c (grokdeclarator): Assert that we won't see a pointer to + METHOD_TYPE. + + PR c++/54277 + * cp-tree.h (WILDCARD_TYPE_P): Split out from... + (MAYBE_CLASS_TYPE_P): ...here. + * semantics.c (lambda_capture_field_type): Only build a + magic decltype for wildcard types. + (lambda_proxy_type): Likewise. + (finish_non_static_data_member): Get the quals from + the object. + + PR c++/55931 + * parser.c (cp_parser_template_argument): Don't + fold_non_dependent_expr. + + * parser.c (cp_parser_lambda_declarator_opt): Use + cp_parser_trailing_type_id. + + PR c++/45917 + * parser.c (cp_parser_template_id): Don't forget access checks. + + PR c++/52374 + * pt.c (tsubst_qualified_id): Use current_nonlambda_class_type. + + PR c++/54764 + PR c++/55972 + * name-lookup.h (tag_scope): Add ts_lambda. + * semantics.c (begin_lambda_type): Use it. + * decl.c (xref_tag_1): Set CLASSTYPE_LAMBDA_EXPR. + * pt.c (check_default_tmpl_args): Ignore lambdas. + (push_template_decl_real): Handle lambdas. + * tree.c (no_linkage_check): Adjust lambda check. + + PR c++/56039 + * tree.c (strip_typedefs_expr): Complain about lambda, don't abort. + + PR c++/54359 + * parser.c (cp_parser_direct_declarator): Fix late return + for out-of-class defn of member function. + + PR c++/55357 + * semantics.c (maybe_add_lambda_conv_op): Clear DECL_NAME of copied + parms to avoid duplicate -Wshadow warnings. + + * search.c (lookup_base): Handle NULL_TREE. + + PR c++/56481 + * semantics.c (potential_constant_expression_1): Use of 'this' in + a non-constexpr function makes the expression not potentially + constant. + + N3276 + PR c++/52748 + * cp-tree.h (tsubst_flags): Add tf_decltype. + * call.c (build_cxx_call): Don't build a temporary if it's set. + (build_over_call): Make sure it's only passed to build_cxx_call. + * parser.c (cp_parser_primary_expression): Add decltype_p parm. + (cp_parser_unary_expression): Likewise. + (cp_parser_cast_expression): Likewise. + (cp_parser_binary_expression): Likewise. + (cp_parser_assignment_expression): Likewise. + (cp_parser_postfix_expression): Likewise. Pass tf_decltype. + (cp_parser_expression): Add decltype_p. Force a + temporary for a call on the LHS of a comma. + (cp_parser_decltype): Pass true to decltype_p parms. + * pt.c (tsubst) [DECLTYPE_TYPE]: Pass tf_decltype. + (tsubst_copy_and_build): Pass tf_decltype down only for + CALL_EXPR and the RHS of COMPOUND_EXPR. + * tree.c (build_cplus_new): Call complete_type_or_maybe_complain. + + * cp-tree.h (abstract_class_use): New enum. + * typeck2.c (pending_abstract_type): Add use field. + (abstract_virtuals_error_sfinae): Add overloads taking + abstract_class_use instead of tree. + * typeck.c (build_static_cast_1): Call it. + * except.c (is_admissible_throw_operand_or_catch_parameter): Call it. + * pt.c: Adjust calls. + * decl.c (cp_finish_decl): Don't handle functions specially. + (grokdeclarator): Always check return type. + * init.c (build_new_1): Adjust call. + + DR 337 + PR c++/17232 + * pt.c (tsubst) [ARRAY_TYPE]: Use abstract_virtuals_error_sfinae. + * typeck2.c (abstract_virtuals_error_sfinae): Call complete_type. + + DR 657 + * pt.c (tsubst_function_type): Call abstract_virtuals_error_sfinae. + (tsubst_arg_types): Likewise. + + DR 1518 + PR c++/54835 + * call.c (convert_like_real): Check for explicit constructors + even for value-initialization. + + PR c++/54946 + * pt.c (convert_nontype_argument): Handle invalid pointer. + + * parser.c (cp_parser_lambda_expression): Use nreverse. + + PR c++/56447 + PR c++/55532 + * pt.c (instantiate_class_template_1): Instantiate lambda capture + list here. + (tsubst_copy_and_build): Not here. + + PR c++/55017 + * method.c (walk_field_subobs): Disallow copy of rvalue ref. + + PR c++/55240 + * parser.c (parsing_nsdmi): New. + * semantics.c (outer_automatic_var_p): Check it. + (finish_id_expression): Likewise. + * cp-tree.h: Declare it. + + PR c++/55241 + * error.c (dump_expr) [SIZEOF_EXPR]: Print sizeof... properly. + + * parser.c (lookup_literal_operator): Correct parm/arg naming + mixup. + + PR c++/56238 + * pt.c (fold_non_dependent_expr_sfinae): Check + instantiation_dependent_expression_p. + + PR c++/56095 + * class.c (resolve_address_of_overloaded_function): Accept a + reference to function for target_type. + (instantiate_type): Likewise. + * pt.c (convert_nontype_argument): Pass it to + convert_nontype_argument_function. + +2013-03-16 Jakub Jelinek <jakub@redhat.com> + + * tree.c (cp_tree_equal): Fix a pasto. + + PR c++/56607 + * typeck.c (cp_build_binary_op): When calling warn_for_div_by_zero, + pass op1 through maybe_constant_value first. + +2013-03-16 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/56582 + * semantics.c (cxx_eval_array_reference): Check for negative index. + +2013-03-14 Jason Merrill <jason@redhat.com> + + PR c++/56614 + * decl.c (local_variable_p_walkfn): Check DECL_ARTIFICIAL again. + + PR c++/56346 + * decl.c (register_dtor_fn): Pass null to __cxa_thread_atexit + dso_handle parm on targets without __cxa_atexit. + 2013-03-11 Jason Merrill <jason@redhat.com> PR c++/56567 diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index dce523a94e8..6e80bcf8c10 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -80,7 +80,7 @@ CXX_AND_OBJCXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \ cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \ cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o \ cp/mangle.o cp/cp-objcp-common.o cp/name-lookup.o cp/cxx-pretty-print.o \ - cp/cp-gimplify.o $(CXX_C_OBJS) + cp/cp-gimplify.o cp/cp-array-notation.o $(CXX_C_OBJS) # Language-specific object files for C++. CXX_OBJS = cp/cp-lang.o c-family/stub-objc.o $(CXX_AND_OBJCXX_OBJS) @@ -100,7 +100,7 @@ cc1plus-checksum.c : build/genchecksum$(build_exeext) checksum-options \ cc1plus-checksum.o : cc1plus-checksum.c $(CONFIG_H) $(SYSTEM_H) cc1plus$(exeext): $(CXX_OBJS) cc1plus-checksum.o $(BACKEND) $(LIBDEPS) - +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ + +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ $(CXX_OBJS) cc1plus-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS) ifeq ($(ENABLE_MAINTAINER_RULES), true) @@ -260,12 +260,15 @@ CXX_TREE_H = $(TREE_H) cp/name-lookup.h cp/cp-tree.h $(C_COMMON_H) \ $(FUNCTION_H) \ $(SYSTEM_H) coretypes.h $(CONFIG_H) $(TARGET_H) $(GGC_H) \ $(srcdir)/../include/hashtab.h -CXX_PARSER_H = tree.h c-family/c-pragma.h cp/parser.h +CXX_PARSER_H = tree.h $(CXX_TREE_H) c-family/c-pragma.h cp/parser.h CXX_PRETTY_PRINT_H = cp/cxx-pretty-print.h $(C_PRETTY_PRINT_H) cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \ $(C_PRAGMA_H) input.h cp/operators.def $(TM_P_H) \ c-family/c-objc.h +cp/cp-array-notation.o: cp/cp-array-notation.c $(CONFIG_H) $(SYSTEM_H) \ + coretypes.h $(TREE_H) $(CXX_TREE_H) $(DIAGNOSTIC_H) tree-iterator.h vec.h \ + $(GIMPLE_H) c-family/array-notation-common.o $(C_COMMON_H) cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) debug.h langhooks.h \ $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-cp.h gt-cp-cp-lang.h \ cp/cp-objcp-common.h $(EXPR_H) $(TARGET_H) $(CXX_PARSER_H) diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 530835b87c8..6817bfc25a0 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -233,7 +233,7 @@ check_dtor_name (tree basetype, tree name) name = TREE_TYPE (name); else if (TYPE_P (name)) /* OK */; - else if (TREE_CODE (name) == IDENTIFIER_NODE) + else if (identifier_p (name)) { if ((MAYBE_CLASS_TYPE_P (basetype) && name == constructor_name (basetype)) @@ -554,8 +554,8 @@ null_ptr_cst_p (tree t) if (CP_INTEGRAL_TYPE_P (TREE_TYPE (t))) { /* Core issue 903 says only literal 0 is a null pointer constant. */ - if (cxx_dialect < cxx0x) - t = maybe_constant_value (t); + if (cxx_dialect < cxx11) + t = maybe_constant_value (fold_non_dependent_expr_sfinae (t, tf_none)); STRIP_NOPS (t); if (integer_zerop (t) && !TREE_OVERFLOW (t)) return true; @@ -1276,7 +1276,10 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p, static_fn_type (tofn))) return NULL; - from = build_memfn_type (fromfn, tbase, cp_type_quals (tbase)); + from = build_memfn_type (fromfn, + tbase, + cp_type_quals (tbase), + type_memfn_rqual (tofn)); from = build_ptrmemfunc_type (build_pointer_type (from)); conv = build_conv (ck_pmem, from, conv); conv->base_p = true; @@ -1950,7 +1953,19 @@ add_function_candidate (struct z_candidate **candidates, { parmtype = cp_build_qualified_type (ctype, cp_type_quals (TREE_TYPE (parmtype))); - parmtype = build_pointer_type (parmtype); + if (FUNCTION_REF_QUALIFIED (TREE_TYPE (fn))) + { + /* If the function has a ref-qualifier, the implicit + object parameter has reference type. */ + bool rv = FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (fn)); + parmtype = cp_build_reference_type (parmtype, rv); + } + else + { + parmtype = build_pointer_type (parmtype); + arg = build_this (arg); + argtype = lvalue_type (arg); + } } /* Core issue 899: When [copy-]initializing a temporary to be bound @@ -2285,7 +2300,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code, T& operator*(T*); */ case INDIRECT_REF: - if (TREE_CODE (type1) == POINTER_TYPE + if (TYPE_PTR_P (type1) && !uses_template_parms (TREE_TYPE (type1)) && (TYPE_PTROB_P (type1) || TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)) @@ -2301,7 +2316,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code, T operator-(T); */ case UNARY_PLUS_EXPR: /* unary + */ - if (TREE_CODE (type1) == POINTER_TYPE) + if (TYPE_PTR_P (type1)) break; case NEGATE_EXPR: if (ARITHMETIC_TYPE_P (type1)) @@ -2325,8 +2340,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code, where CV12 is the union of CV1 and CV2. */ case MEMBER_REF: - if (TREE_CODE (type1) == POINTER_TYPE - && TYPE_PTRMEM_P (type2)) + if (TYPE_PTR_P (type1) && TYPE_PTRMEM_P (type2)) { tree c1 = TREE_TYPE (type1); tree c2 = TYPE_PTRMEM_CLASS_TYPE (type2); @@ -2546,7 +2560,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code, || (TYPE_PTR_P (type1) && TYPE_PTR_P (type2)) || (TYPE_PTRDATAMEM_P (type1) && TYPE_PTRDATAMEM_P (type2)) || ((TYPE_PTRMEMFUNC_P (type1) - || TREE_CODE (type1) == POINTER_TYPE) + || TYPE_PTR_P (type1)) && null_ptr_cst_p (args[1]))) { type2 = type1; @@ -2905,7 +2919,8 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, fn = fn_type_unification (tmpl, explicit_targs, targs, args_without_in_chrg, nargs_without_in_chrg, - return_type, strict, flags, false); + return_type, strict, flags, false, + complain & tf_decltype); if (fn == error_mark_node) { @@ -3147,7 +3162,7 @@ print_z_candidate (location_t loc, const char *msgstr, : ACONCAT ((msgstr, " ", NULL))); location_t cloc = location_of (candidate->fn); - if (TREE_CODE (candidate->fn) == IDENTIFIER_NODE) + if (identifier_p (candidate->fn)) { cloc = loc; if (candidate->num_convs == 3) @@ -3221,7 +3236,7 @@ print_z_candidate (location_t loc, const char *msgstr, r->u.template_unification.return_type, r->u.template_unification.strict, r->u.template_unification.flags, - true); + true, false); break; case rr_invalid_copy: inform (cloc, @@ -3447,6 +3462,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags, int ctorflags = flags; first_arg = build_int_cst (build_pointer_type (totype), 0); + first_arg = build_fold_indirect_ref (first_arg); /* We should never try to call the abstract or base constructor from here. */ @@ -3488,7 +3504,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags, } if (conv_fns) - first_arg = build_this (expr); + first_arg = expr; for (; conv_fns; conv_fns = TREE_CHAIN (conv_fns)) { @@ -3935,8 +3951,13 @@ build_operator_new_call (tree fnname, vec<tree, va_gc> **args, *fn = NULL_TREE; /* Set to (size_t)-1 if the size check fails. */ if (size_check != NULL_TREE) - *size = fold_build3 (COND_EXPR, sizetype, size_check, - original_size, TYPE_MAX_VALUE (sizetype)); + { + tree errval = TYPE_MAX_VALUE (sizetype); + if (cxx_dialect >= cxx11) + errval = throw_bad_array_new_length (); + *size = fold_build3 (COND_EXPR, sizetype, size_check, + original_size, errval); + } vec_safe_insert (*args, 0, *size); *args = resolve_args (*args, complain); if (*args == NULL) @@ -4066,7 +4087,7 @@ build_op_call_1 (tree obj, vec<tree, va_gc> **args, tsubst_flags_t complain) if (fns) { - first_mem_arg = build_this (obj); + first_mem_arg = obj; add_candidates (BASELINK_FUNCTIONS (fns), first_mem_arg, *args, NULL_TREE, @@ -4082,13 +4103,10 @@ build_op_call_1 (tree obj, vec<tree, va_gc> **args, tsubst_flags_t complain) tree fns = TREE_VALUE (convs); tree totype = TREE_TYPE (convs); - if ((TREE_CODE (totype) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE) + if (TYPE_PTRFN_P (totype) + || TYPE_REFFN_P (totype) || (TREE_CODE (totype) == REFERENCE_TYPE - && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE) - || (TREE_CODE (totype) == REFERENCE_TYPE - && TREE_CODE (TREE_TYPE (totype)) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (TREE_TYPE (totype))) == FUNCTION_TYPE)) + && TYPE_PTRFN_P (TREE_TYPE (totype)))) for (; fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); @@ -4335,7 +4353,7 @@ conditional_conversion (tree e1, tree e2, tsubst_flags_t complain) arguments to the conditional expression. */ static tree -build_conditional_expr_1 (tree arg1, tree arg2, tree arg3, +build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3, tsubst_flags_t complain) { tree arg2_type; @@ -4355,7 +4373,7 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3, if (!arg2) { if (complain & tf_error) - pedwarn (input_location, OPT_Wpedantic, + pedwarn (loc, OPT_Wpedantic, "ISO C++ forbids omitting the middle term of a ?: expression"); /* Make sure that lvalues remain lvalues. See g++.oliva/ext1.C. */ @@ -4389,8 +4407,8 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3, && TREE_CODE (arg3_type) != VECTOR_TYPE) { if (complain & tf_error) - error ("at least one operand of a vector conditional operator " - "must be a vector"); + error_at (loc, "at least one operand of a vector conditional " + "operator must be a vector"); return error_mark_node; } @@ -4398,7 +4416,7 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3, != (TREE_CODE (arg3_type) == VECTOR_TYPE)) { enum stv_conv convert_flag = - scalar_to_vector (input_location, VEC_COND_EXPR, arg2, arg3, + scalar_to_vector (loc, VEC_COND_EXPR, arg2, arg3, complain & tf_error); switch (convert_flag) @@ -4430,16 +4448,17 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3, || TYPE_SIZE (arg1_type) != TYPE_SIZE (arg2_type)) { if (complain & tf_error) - error ("incompatible vector types in conditional expression: " - "%qT, %qT and %qT", TREE_TYPE (arg1), TREE_TYPE (orig_arg2), - TREE_TYPE (orig_arg3)); + error_at (loc, + "incompatible vector types in conditional expression: " + "%qT, %qT and %qT", TREE_TYPE (arg1), + TREE_TYPE (orig_arg2), TREE_TYPE (orig_arg3)); return error_mark_node; } if (!COMPARISON_CLASS_P (arg1)) - arg1 = build2 (NE_EXPR, signed_type_for (arg1_type), arg1, - build_zero_cst (arg1_type)); - return build3 (VEC_COND_EXPR, arg2_type, arg1, arg2, arg3); + arg1 = cp_build_binary_op (loc, NE_EXPR, arg1, + build_zero_cst (arg1_type), complain); + return fold_build3 (VEC_COND_EXPR, arg2_type, arg1, arg2, arg3); } /* [expr.cond] @@ -4517,15 +4536,15 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3, if (complain & tf_error) { if (VOID_TYPE_P (arg2_type)) - error ("second operand to the conditional operator " - "is of type %<void%>, " - "but the third operand is neither a throw-expression " - "nor of type %<void%>"); + error_at (EXPR_LOC_OR_LOC (arg3, loc), + "second operand to the conditional operator " + "is of type %<void%>, but the third operand is " + "neither a throw-expression nor of type %<void%>"); else - error ("third operand to the conditional operator " - "is of type %<void%>, " - "but the second operand is neither a throw-expression " - "nor of type %<void%>"); + error_at (EXPR_LOC_OR_LOC (arg2, loc), + "third operand to the conditional operator " + "is of type %<void%>, but the second operand is " + "neither a throw-expression nor of type %<void%>"); } return error_mark_node; } @@ -4564,8 +4583,9 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3, || (conv2 && conv2->kind == ck_ambig) || (conv3 && conv3->kind == ck_ambig)) { - error ("operands to ?: have different types %qT and %qT", - arg2_type, arg3_type); + if (complain & tf_error) + error_at (loc, "operands to ?: have different types %qT and %qT", + arg2_type, arg3_type); result = error_mark_node; } else if (conv2 && (!conv2->bad_p || !conv3)) @@ -4671,9 +4691,8 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3, { if (complain & tf_error) { - op_error (input_location, COND_EXPR, NOP_EXPR, - arg1, arg2, arg3, FALSE); - print_z_candidates (location_of (arg1), candidates); + op_error (loc, COND_EXPR, NOP_EXPR, arg1, arg2, arg3, FALSE); + print_z_candidates (loc, candidates); } return error_mark_node; } @@ -4682,9 +4701,8 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3, { if (complain & tf_error) { - op_error (input_location, COND_EXPR, NOP_EXPR, - arg1, arg2, arg3, FALSE); - print_z_candidates (location_of (arg1), candidates); + op_error (loc, COND_EXPR, NOP_EXPR, arg1, arg2, arg3, FALSE); + print_z_candidates (loc, candidates); } return error_mark_node; } @@ -4747,10 +4765,11 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3, /* In this case, there is always a common type. */ result_type = type_after_usual_arithmetic_conversions (arg2_type, arg3_type); - do_warn_double_promotion (result_type, arg2_type, arg3_type, - "implicit conversion from %qT to %qT to " - "match other result of conditional", - input_location); + if (complain & tf_warning) + do_warn_double_promotion (result_type, arg2_type, arg3_type, + "implicit conversion from %qT to %qT to " + "match other result of conditional", + loc); if (TREE_CODE (arg2_type) == ENUMERAL_TYPE && TREE_CODE (arg3_type) == ENUMERAL_TYPE) @@ -4761,19 +4780,20 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3, /* Two enumerators from the same enumeration can have different types when the enumeration is still being defined. */; else if (complain & tf_warning) - warning (OPT_Wenum_compare, - "enumeral mismatch in conditional expression: %qT vs %qT", - arg2_type, arg3_type); + warning_at (loc, OPT_Wenum_compare, "enumeral mismatch in " + "conditional expression: %qT vs %qT", + arg2_type, arg3_type); } else if (extra_warnings && ((TREE_CODE (arg2_type) == ENUMERAL_TYPE && !same_type_p (arg3_type, type_promotes_to (arg2_type))) || (TREE_CODE (arg3_type) == ENUMERAL_TYPE - && !same_type_p (arg2_type, type_promotes_to (arg3_type))))) + && !same_type_p (arg2_type, + type_promotes_to (arg3_type))))) { if (complain & tf_warning) - warning (0, - "enumeral and non-enumeral type in conditional expression"); + warning_at (loc, 0, "enumeral and non-enumeral type in " + "conditional expression"); } arg2 = perform_implicit_conversion (result_type, arg2, complain); @@ -4815,8 +4835,8 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3, if (!result_type) { if (complain & tf_error) - error ("operands to ?: have different types %qT and %qT", - arg2_type, arg3_type); + error_at (loc, "operands to ?: have different types %qT and %qT", + arg2_type, arg3_type); return error_mark_node; } @@ -4844,6 +4864,8 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3, lvalue, we must add a NON_LVALUE_EXPR. */ result = rvalue (result); } + else + result = force_paren_expr (result); return result; } @@ -4851,12 +4873,12 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3, /* Wrapper for above. */ tree -build_conditional_expr (tree arg1, tree arg2, tree arg3, +build_conditional_expr (location_t loc, tree arg1, tree arg2, tree arg3, tsubst_flags_t complain) { tree ret; bool subtime = timevar_cond_start (TV_OVERLOAD); - ret = build_conditional_expr_1 (arg1, arg2, arg3, complain); + ret = build_conditional_expr_1 (loc, arg1, arg2, arg3, complain); timevar_cond_stop (TV_OVERLOAD, subtime); return ret; } @@ -4924,7 +4946,7 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args, is considered to be a member of the class of the implicit object argument for the purpose of defining the type of the implicit object parameter. */ - ctype = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (first_arg))); + ctype = TYPE_MAIN_VARIANT (TREE_TYPE (first_arg)); } else { @@ -4978,7 +5000,7 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args, for (ix = 1; args->iterate (ix, &arg); ++ix) tempvec->quick_push (arg); non_static_args = tempvec; - first_arg = build_this ((*args)[0]); + first_arg = (*args)[0]; } fn_first_arg = first_arg; @@ -5082,8 +5104,8 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1, if (code == COND_EXPR) /* Use build_conditional_expr instead. */ gcc_unreachable (); - else if (! IS_OVERLOAD_TYPE (TREE_TYPE (arg1)) - && (! arg2 || ! IS_OVERLOAD_TYPE (TREE_TYPE (arg2)))) + else if (! OVERLOAD_TYPE_P (TREE_TYPE (arg1)) + && (! arg2 || ! OVERLOAD_TYPE_P (TREE_TYPE (arg2)))) goto builtin; if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR) @@ -5396,7 +5418,7 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1, case BIT_AND_EXPR: case BIT_IOR_EXPR: case BIT_XOR_EXPR: - return cp_build_binary_op (input_location, code, arg1, arg2, complain); + return cp_build_binary_op (loc, code, arg1, arg2, complain); case UNARY_PLUS_EXPR: case NEGATE_EXPR: @@ -5709,12 +5731,12 @@ build_temp (tree expr, tree type, int flags, int savew, savee; vec<tree, va_gc> *args; - savew = warningcount, savee = errorcount; + savew = warningcount + werrorcount, savee = errorcount; args = make_tree_vector_single (expr); expr = build_special_member_call (NULL_TREE, complete_ctor_identifier, &args, type, flags, complain); release_tree_vector (args); - if (warningcount > savew) + if (warningcount + werrorcount > savew) *diagnostic_kind = DK_WARNING; else if (errorcount > savee) *diagnostic_kind = DK_ERROR; @@ -5836,11 +5858,17 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, break; } - permerror (loc, "invalid conversion from %qT to %qT", - TREE_TYPE (expr), totype); - if (fn) - permerror (DECL_SOURCE_LOCATION (fn), - " initializing argument %P of %qD", argnum, fn); + if (flag_enable_cilkplus + && (contains_array_notation_expr (expr) + || contains_array_notation_expr (fn))) + /* If we are using array notations, we fix them up at a later stage + and we will do these checks then. */ + ; + else if (permerror (loc, "invalid conversion from %qT to %qT", + TREE_TYPE (expr), totype) + && fn) + inform (DECL_SOURCE_LOCATION (fn), + "initializing argument %P of %qD", argnum, fn); return cp_convert (totype, expr, complain); } @@ -5856,6 +5884,17 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, tree convfn = cand->fn; unsigned i; + /* When converting from an init list we consider explicit + constructors, but actually trying to call one is an error. */ + if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn) + /* Unless this is for direct-list-initialization. */ + && !(BRACE_ENCLOSED_INITIALIZER_P (expr) + && CONSTRUCTOR_IS_DIRECT_INIT (expr))) + { + error ("converting to %qT from initializer list would use " + "explicit constructor %qD", totype, convfn); + } + /* If we're initializing from {}, it's value-initialization. */ if (BRACE_ENCLOSED_INITIALIZER_P (expr) && CONSTRUCTOR_NELTS (expr) == 0 @@ -5874,20 +5913,6 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, expr = mark_rvalue_use (expr); - /* When converting from an init list we consider explicit - constructors, but actually trying to call one is an error. */ - if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn) - /* Unless this is for direct-list-initialization. */ - && !(BRACE_ENCLOSED_INITIALIZER_P (expr) - && CONSTRUCTOR_IS_DIRECT_INIT (expr)) - /* Unless we're calling it for value-initialization from an - empty list, since that is handled separately in 8.5.4. */ - && cand->num_convs > 0) - { - error ("converting to %qT from initializer list would use " - "explicit constructor %qD", totype, convfn); - } - /* Set user_conv_p on the argument conversions, so rvalue/base handling knows not to allow any more UDCs. */ for (i = 0; i < cand->num_convs; ++i) @@ -5946,7 +5971,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, build_user_type_conversion (totype, convs->u.expr, LOOKUP_NORMAL, complain); if (fn) - error (" initializing argument %P of %q+D", argnum, fn); + inform (input_location, "initializing argument %P of %q+D", + argnum, fn); } return error_mark_node; @@ -6077,7 +6103,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, error_at (loc, "cannot bind %qT lvalue to %qT", TREE_TYPE (expr), totype); if (fn) - error (" initializing argument %P of %q+D", argnum, fn); + inform (input_location, + "initializing argument %P of %q+D", argnum, fn); return error_mark_node; } @@ -6178,10 +6205,10 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, if (convs->check_narrowing) check_narrowing (totype, expr); - if (issue_conversion_warnings && (complain & tf_warning)) - expr = convert_and_check (totype, expr); + if (issue_conversion_warnings) + expr = cp_convert_and_check (totype, expr, complain); else - expr = convert (totype, expr); + expr = cp_convert (totype, expr, complain); return expr; } @@ -6696,6 +6723,10 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) /* else continue to get conversion error. */ } + /* N3276 magic doesn't apply to nested calls. */ + int decltype_flag = (complain & tf_decltype); + complain &= ~tf_decltype; + /* Find maximum size of vector to hold converted arguments. */ parmlen = list_length (parm); nargs = vec_safe_length (args) + (first_arg != NULL_TREE ? 1 : 0); @@ -6707,16 +6738,18 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) resolution, and must be of the proper type. */ if (DECL_CONSTRUCTOR_P (fn)) { + tree object_arg; if (first_arg != NULL_TREE) { - argarray[j++] = first_arg; + object_arg = first_arg; first_arg = NULL_TREE; } else { - argarray[j++] = (*args)[arg_index]; + object_arg = (*args)[arg_index]; ++arg_index; } + argarray[j++] = build_this (object_arg); parm = TREE_CHAIN (parm); /* We should never try to call the abstract constructor. */ gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (fn)); @@ -6732,9 +6765,9 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) else if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) { tree parmtype = TREE_VALUE (parm); - tree arg = (first_arg != NULL_TREE - ? first_arg - : (*args)[arg_index]); + tree arg = build_this (first_arg != NULL_TREE + ? first_arg + : (*args)[arg_index]); tree argtype = TREE_TYPE (arg); tree converted_arg; tree base_binfo; @@ -6760,7 +6793,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) So we can assume that anything passed as 'this' is non-null, and optimize accordingly. */ - gcc_assert (TREE_CODE (parmtype) == POINTER_TYPE); + gcc_assert (TYPE_PTR_P (parmtype)); /* Convert to the base in which the function was declared. */ gcc_assert (cand->conversion_path != NULL_TREE); converted_arg = build_base_path (PLUS_EXPR, @@ -6770,9 +6803,14 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) /* Check that the base class is accessible. */ if (!accessible_base_p (TREE_TYPE (argtype), BINFO_TYPE (cand->conversion_path), true)) - error ("%qT is not an accessible base of %qT", - BINFO_TYPE (cand->conversion_path), - TREE_TYPE (argtype)); + { + if (complain & tf_error) + error ("%qT is not an accessible base of %qT", + BINFO_TYPE (cand->conversion_path), + TREE_TYPE (argtype)); + else + return error_mark_node; + } /* If fn was found by a using declaration, the conversion path will be to the derived class, not the base declaring fn. We must convert from derived to base. */ @@ -6858,12 +6896,20 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) } } - val = convert_like_with_context (conv, arg, fn, i-is_method, - conversion_warning - ? complain - : complain & (~tf_warning)); + /* If the function call is builtin array notation function then no need + to do any type conversion. */ + if (flag_enable_cilkplus + && is_cilkplus_reduce_builtin (fn) != BUILT_IN_NONE) + val = arg; + else + { + val = convert_like_with_context (conv, arg, fn, i - is_method, + conversion_warning + ? complain + : complain & (~tf_warning)); - val = convert_for_arg_passing (type, val, complain); + val = convert_for_arg_passing (type, val, complain); + } if (val == error_mark_node) return error_mark_node; else @@ -7021,7 +7067,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) otherwise the call should go through the dispatcher. */ if (DECL_FUNCTION_VERSIONED (fn) - && !targetm.target_option.can_inline_p (current_function_decl, fn)) + && (current_function_decl == NULL + || !targetm.target_option.can_inline_p (current_function_decl, fn))) { fn = get_function_version_dispatcher (fn); if (fn == NULL) @@ -7067,7 +7114,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) return error_mark_node; } - return build_cxx_call (fn, nargs, argarray, complain); + return build_cxx_call (fn, nargs, argarray, complain|decltype_flag); } /* Build and return a call to FN, using NARGS arguments in ARGARRAY. @@ -7109,12 +7156,20 @@ build_cxx_call (tree fn, int nargs, tree *argarray, if (VOID_TYPE_P (TREE_TYPE (fn))) return fn; - fn = require_complete_type_sfinae (fn, complain); - if (fn == error_mark_node) - return error_mark_node; + /* 5.2.2/11: If a function call is a prvalue of object type: if the + function call is either the operand of a decltype-specifier or the + right operand of a comma operator that is the operand of a + decltype-specifier, a temporary object is not introduced for the + prvalue. The type of the prvalue may be incomplete. */ + if (!(complain & tf_decltype)) + { + fn = require_complete_type_sfinae (fn, complain); + if (fn == error_mark_node) + return error_mark_node; - if (MAYBE_CLASS_TYPE_P (TREE_TYPE (fn))) - fn = build_cplus_new (TREE_TYPE (fn), fn, complain); + if (MAYBE_CLASS_TYPE_P (TREE_TYPE (fn))) + fn = build_cplus_new (TREE_TYPE (fn), fn, complain); + } return convert_from_reference (fn); } @@ -7150,7 +7205,7 @@ build_java_interface_fn_ref (tree fn, tree instance) /* Get the java.lang.Class pointer for the interface being called. */ iface = DECL_CONTEXT (fn); iface_ref = lookup_field (iface, get_identifier ("class$"), 0, false); - if (!iface_ref || TREE_CODE (iface_ref) != VAR_DECL + if (!iface_ref || !VAR_P (iface_ref) || DECL_CONTEXT (iface_ref) != iface) { error ("could not find class$ field in java interface type %qT", @@ -7388,7 +7443,6 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, tree access_binfo; tree optype; tree first_mem_arg = NULL_TREE; - tree instance_ptr; tree name; bool skip_first_for_error; vec<tree, va_gc> *user_args; @@ -7458,11 +7512,11 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, if (! (complain & tf_error)) return error_mark_node; - permerror (input_location, - "cannot call constructor %<%T::%D%> directly", - basetype, name); - permerror (input_location, " for a function-style cast, remove the " - "redundant %<::%D%>", name); + if (permerror (input_location, + "cannot call constructor %<%T::%D%> directly", + basetype, name)) + inform (input_location, "for a function-style cast, remove the " + "redundant %<::%D%>", name); call = build_functional_cast (basetype, build_tree_list_vec (user_args), complain); return call; @@ -7496,22 +7550,27 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, return error_mark_node; } - instance_ptr = build_this (instance); + /* Consider the object argument to be used even if we end up selecting a + static member function. */ + instance = mark_type_use (instance); /* It's OK to call destructors and constructors on cv-qualified objects. - Therefore, convert the INSTANCE_PTR to the unqualified type, if + Therefore, convert the INSTANCE to the unqualified type, if necessary. */ if (DECL_DESTRUCTOR_P (fn) || DECL_CONSTRUCTOR_P (fn)) { - tree type = build_pointer_type (basetype); - if (!same_type_p (type, TREE_TYPE (instance_ptr))) - instance_ptr = build_nop (type, instance_ptr); + if (!same_type_p (basetype, TREE_TYPE (instance))) + { + instance = build_this (instance); + instance = build_nop (build_pointer_type (basetype), instance); + instance = build_fold_indirect_ref (instance); + } } if (DECL_DESTRUCTOR_P (fn)) name = complete_dtor_identifier; - first_mem_arg = instance_ptr; + first_mem_arg = instance; /* Get the high-water mark for the CONVERSION_OBSTACK. */ p = conversion_obstack_alloc (0); @@ -7547,11 +7606,10 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, if (init) { - tree ob; - if (integer_zerop (instance_ptr)) + if (TREE_CODE (instance) == INDIRECT_REF + && integer_zerop (TREE_OPERAND (instance, 0))) return get_target_expr_sfinae (init, complain); - ob = build_fold_indirect_ref (instance_ptr); - init = build2 (INIT_EXPR, TREE_TYPE (ob), ob, init); + init = build2 (INIT_EXPR, TREE_TYPE (instance), instance, init); TREE_SIDE_EFFECTS (init) = true; return init; } @@ -7576,11 +7634,11 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, if (complain & tf_error) { if (!COMPLETE_OR_OPEN_TYPE_P (basetype)) - cxx_incomplete_type_error (instance_ptr, basetype); + cxx_incomplete_type_error (instance, basetype); else if (optype) error ("no matching function for call to %<%T::operator %T(%A)%#V%>", basetype, optype, build_tree_list_vec (user_args), - TREE_TYPE (TREE_TYPE (instance_ptr))); + TREE_TYPE (instance)); else { char *pretty_name; @@ -7593,7 +7651,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, arglist = TREE_CHAIN (arglist); error ("no matching function for call to %<%T::%s(%A)%#V%>", basetype, pretty_name, arglist, - TREE_TYPE (TREE_TYPE (instance_ptr))); + TREE_TYPE (instance)); if (free_p) free (pretty_name); } @@ -7643,7 +7701,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, fn); if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE - && is_dummy_object (instance_ptr)) + && is_dummy_object (instance)) { instance = maybe_resolve_dummy (instance); if (instance == error_mark_node) @@ -7652,8 +7710,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, { /* We captured 'this' in the current lambda now that we know we really need it. */ - instance_ptr = build_this (instance); - cand->first_arg = instance_ptr; + cand->first_arg = instance; } else { @@ -7688,10 +7745,10 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, out to be a static member function, `a' is none-the-less evaluated. */ if (TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE - && !is_dummy_object (instance_ptr) - && TREE_SIDE_EFFECTS (instance_ptr)) + && !is_dummy_object (instance) + && TREE_SIDE_EFFECTS (instance)) call = build2 (COMPOUND_EXPR, TREE_TYPE (call), - instance_ptr, call); + instance, call); else if (call != error_mark_node && DECL_DESTRUCTOR_P (cand->fn) && !VOID_TYPE_P (TREE_TYPE (call))) @@ -7721,7 +7778,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, cast_to_void = true; call = TREE_OPERAND (call, 0); } - if (TREE_CODE (call) == INDIRECT_REF) + if (INDIRECT_REF_P (call)) call = TREE_OPERAND (call, 0); call = (build_min_non_dep_call_vec (call, @@ -8122,8 +8179,8 @@ compare_ics (conversion *ics1, conversion *ics2) conversion of B* to A* is better than conversion of B* to void*, and conversion of A* to void* is better than conversion of B* to void*. */ - if (TREE_CODE (deref_to_type1) == VOID_TYPE - && TREE_CODE (deref_to_type2) == VOID_TYPE) + if (VOID_TYPE_P (deref_to_type1) + && VOID_TYPE_P (deref_to_type2)) { if (is_properly_derived_from (deref_from_type1, deref_from_type2)) @@ -8132,12 +8189,12 @@ compare_ics (conversion *ics1, conversion *ics2) deref_from_type1)) return 1; } - else if (TREE_CODE (deref_to_type1) == VOID_TYPE - || TREE_CODE (deref_to_type2) == VOID_TYPE) + else if (VOID_TYPE_P (deref_to_type1) + || VOID_TYPE_P (deref_to_type2)) { if (same_type_p (deref_from_type1, deref_from_type2)) { - if (TREE_CODE (deref_to_type2) == VOID_TYPE) + if (VOID_TYPE_P (deref_to_type2)) { if (is_properly_derived_from (deref_from_type1, deref_to_type1)) @@ -8554,8 +8611,7 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn, - do not have the same parameter type list as any non-template non-member candidate. */ - if (TREE_CODE (cand1->fn) == IDENTIFIER_NODE - || TREE_CODE (cand2->fn) == IDENTIFIER_NODE) + if (identifier_p (cand1->fn) || identifier_p (cand2->fn)) { for (i = 0; i < len; ++i) if (!same_type_p (cand1->convs[i]->type, @@ -8566,7 +8622,7 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn, if (cand1->fn == cand2->fn) /* Two built-in candidates; arbitrarily pick one. */ return 1; - else if (TREE_CODE (cand1->fn) == IDENTIFIER_NODE) + else if (identifier_p (cand1->fn)) /* cand1 is built-in; prefer cand2. */ return -1; else @@ -8642,13 +8698,15 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn, { if (complain & tf_error) { - permerror (input_location, - "default argument mismatch in " - "overload resolution"); - inform (input_location, - " candidate 1: %q+#F", cand1->fn); - inform (input_location, - " candidate 2: %q+#F", cand2->fn); + if (permerror (input_location, + "default argument mismatch in " + "overload resolution")) + { + inform (input_location, + " candidate 1: %q+#F", cand1->fn); + inform (input_location, + " candidate 2: %q+#F", cand2->fn); + } } else return 0; @@ -8996,7 +9054,7 @@ make_temporary_var_for_ref_to_temp (tree decl, tree type) var = create_temporary_var (type); /* Register the variable. */ - if (TREE_CODE (decl) == VAR_DECL + if (VAR_P (decl) && (TREE_STATIC (decl) || DECL_THREAD_LOCAL_P (decl))) { /* Namespace-scope or local static; give it a mangled name. */ diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 746c29d2dea..0067605969a 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -244,7 +244,7 @@ build_base_path (enum tree_code code, tree null_test = NULL; tree ptr_target_type; int fixed_type_p; - int want_pointer = TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE; + int want_pointer = TYPE_PTR_P (TREE_TYPE (expr)); bool has_empty = false; bool virtual_access; @@ -1045,6 +1045,12 @@ add_method (tree type, tree method, tree using_decl) overloaded if any of them is a static member function declaration. + [over.load] Member function declarations with the same name and + the same parameter-type-list as well as member function template + declarations with the same name, the same parameter-type-list, and + the same template parameter lists cannot be overloaded if any of + them, but not all, have a ref-qualifier. + [namespace.udecl] When a using-declaration brings names from a base class into a derived class scope, member functions in the derived class override and/or hide member @@ -1060,11 +1066,13 @@ add_method (tree type, tree method, tree using_decl) coming from the using class in overload resolution. */ if (! DECL_STATIC_FUNCTION_P (fn) && ! DECL_STATIC_FUNCTION_P (method) - && TREE_TYPE (TREE_VALUE (parms1)) != error_mark_node - && TREE_TYPE (TREE_VALUE (parms2)) != error_mark_node - && (cp_type_quals (TREE_TYPE (TREE_VALUE (parms1))) - != cp_type_quals (TREE_TYPE (TREE_VALUE (parms2))))) - continue; + /* Either both or neither need to be ref-qualified for + differing quals to allow overloading. */ + && (FUNCTION_REF_QUALIFIED (fn_type) + == FUNCTION_REF_QUALIFIED (method_type)) + && (type_memfn_quals (fn_type) != type_memfn_quals (method_type) + || type_memfn_rqual (fn_type) != type_memfn_rqual (method_type))) + continue; /* For templates, the return type and template parameters must be identical. */ @@ -1311,7 +1319,7 @@ struct abi_tag_data static tree find_abi_tags_r (tree *tp, int */*walk_subtrees*/, void *data) { - if (!TAGGED_TYPE_P (*tp)) + if (!OVERLOAD_TYPE_P (*tp)) return NULL_TREE; if (tree attributes = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (*tp))) @@ -1346,11 +1354,11 @@ find_abi_tags_r (tree *tp, int */*walk_subtrees*/, void *data) return NULL_TREE; } -/* Check that class T has all the abi tags that subobject SUBOB has, or - warn if not. */ +/* Set IDENTIFIER_MARKED on all the ABI tags on T and its (transitively + complete) template arguments. */ static void -check_abi_tags (tree t, tree subob) +mark_type_abi_tags (tree t, bool val) { tree attributes = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (t)); if (attributes) @@ -1360,25 +1368,41 @@ check_abi_tags (tree t, tree subob) { tree tag = TREE_VALUE (list); tree id = get_identifier (TREE_STRING_POINTER (tag)); - IDENTIFIER_MARKED (id) = true; + IDENTIFIER_MARKED (id) = val; } } + /* Also mark ABI tags from template arguments. */ + if (CLASSTYPE_TEMPLATE_INFO (t)) + { + tree args = CLASSTYPE_TI_ARGS (t); + for (int i = 0; i < TMPL_ARGS_DEPTH (args); ++i) + { + tree level = TMPL_ARGS_LEVEL (args, i+1); + for (int j = 0; j < TREE_VEC_LENGTH (level); ++j) + { + tree arg = TREE_VEC_ELT (level, j); + if (CLASS_TYPE_P (arg)) + mark_type_abi_tags (arg, val); + } + } + } +} + +/* Check that class T has all the abi tags that subobject SUBOB has, or + warn if not. */ + +static void +check_abi_tags (tree t, tree subob) +{ + mark_type_abi_tags (t, true); + tree subtype = TYPE_P (subob) ? subob : TREE_TYPE (subob); struct abi_tag_data data = { t, subob }; cp_walk_tree_without_duplicates (&subtype, find_abi_tags_r, &data); - if (attributes) - { - for (tree list = TREE_VALUE (attributes); list; - list = TREE_CHAIN (list)) - { - tree tag = TREE_VALUE (list); - tree id = get_identifier (TREE_STRING_POINTER (tag)); - IDENTIFIER_MARKED (id) = false; - } - } + mark_type_abi_tags (t, false); } /* Run through the base classes of T, updating CANT_HAVE_CONST_CTOR_P, @@ -2058,12 +2082,12 @@ same_signature_p (const_tree fndecl, const_tree base_fndecl) && same_type_p (DECL_CONV_FN_TYPE (fndecl), DECL_CONV_FN_TYPE (base_fndecl)))) { - tree types, base_types; - types = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); - base_types = TYPE_ARG_TYPES (TREE_TYPE (base_fndecl)); - if ((cp_type_quals (TREE_TYPE (TREE_VALUE (base_types))) - == cp_type_quals (TREE_TYPE (TREE_VALUE (types)))) - && compparms (TREE_CHAIN (base_types), TREE_CHAIN (types))) + tree fntype = TREE_TYPE (fndecl); + tree base_fntype = TREE_TYPE (base_fndecl); + if (type_memfn_quals (fntype) == type_memfn_quals (base_fntype) + && type_memfn_rqual (fntype) == type_memfn_rqual (base_fntype) + && compparms (FUNCTION_FIRST_USER_PARMTYPE (fndecl), + FUNCTION_FIRST_USER_PARMTYPE (base_fndecl))) return 1; } return 0; @@ -2947,7 +2971,7 @@ add_implicitly_declared_members (tree t, tree* access_decls, { bool move_ok = false; - if (cxx_dialect >= cxx0x && !CLASSTYPE_DESTRUCTORS (t) + if (cxx_dialect >= cxx11 && !CLASSTYPE_DESTRUCTORS (t) && !TYPE_HAS_COPY_CTOR (t) && !TYPE_HAS_COPY_ASSIGN (t) && !type_has_move_constructor (t) && !type_has_move_assign (t)) move_ok = true; @@ -2974,7 +2998,7 @@ add_implicitly_declared_members (tree t, tree* access_decls, { TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 1; CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1; - if (cxx_dialect >= cxx0x) + if (cxx_dialect >= cxx11) TYPE_HAS_CONSTEXPR_CTOR (t) /* This might force the declaration. */ = type_has_constexpr_default_constructor (t); @@ -3132,9 +3156,12 @@ check_bitfield_decl (tree field) error ("zero width for bit-field %q+D", field); w = error_mark_node; } - else if (compare_tree_int (w, TYPE_PRECISION (type)) > 0 - && TREE_CODE (type) != ENUMERAL_TYPE - && TREE_CODE (type) != BOOLEAN_TYPE) + else if ((TREE_CODE (type) != ENUMERAL_TYPE + && TREE_CODE (type) != BOOLEAN_TYPE + && compare_tree_int (w, TYPE_PRECISION (type)) > 0) + || ((TREE_CODE (type) == ENUMERAL_TYPE + || TREE_CODE (type) == BOOLEAN_TYPE) + && tree_int_cst_lt (TYPE_SIZE (type), w))) warning (0, "width of %q+D exceeds its type", field); else if (TREE_CODE (type) == ENUMERAL_TYPE && (0 > (compare_tree_int @@ -3172,7 +3199,7 @@ check_field_decl (tree field, /* In C++98 an anonymous union cannot contain any fields which would change the settings of CANT_HAVE_CONST_CTOR and friends. */ - if (ANON_UNION_TYPE_P (type) && cxx_dialect < cxx0x) + if (ANON_UNION_TYPE_P (type) && cxx_dialect < cxx11) ; /* And, we don't set TYPE_HAS_CONST_COPY_CTOR, etc., for anonymous structs. So, we recurse through their fields here. */ @@ -3193,7 +3220,7 @@ check_field_decl (tree field, make it through without complaint. */ abstract_virtuals_error (field, type); - if (TREE_CODE (t) == UNION_TYPE && cxx_dialect < cxx0x) + if (TREE_CODE (t) == UNION_TYPE && cxx_dialect < cxx11) { static bool warned; int oldcount = errorcount; @@ -3327,7 +3354,7 @@ check_field_decls (tree t, tree *access_decls, If a union contains a static data member, or a member of reference type, the program is ill-formed. */ - if (TREE_CODE (x) == VAR_DECL) + if (VAR_P (x)) { error ("%q+D may not be static because it is a member of a union", x); continue; @@ -3359,7 +3386,7 @@ check_field_decls (tree t, tree *access_decls, if (type == error_mark_node) continue; - if (TREE_CODE (x) == CONST_DECL || TREE_CODE (x) == VAR_DECL) + if (TREE_CODE (x) == CONST_DECL || VAR_P (x)) continue; /* Now it can only be a FIELD_DECL. */ @@ -3752,7 +3779,9 @@ walk_subobject_offsets (tree type, /* Iterate through the fields of TYPE. */ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) - if (TREE_CODE (field) == FIELD_DECL && !DECL_ARTIFICIAL (field)) + if (TREE_CODE (field) == FIELD_DECL + && TREE_TYPE (field) != error_mark_node + && !DECL_ARTIFICIAL (field)) { tree field_offset; @@ -4823,6 +4852,44 @@ type_has_user_provided_default_constructor (tree t) return false; } +/* TYPE is being used as a virtual base, and has a non-trivial move + assignment. Return true if this is due to there being a user-provided + move assignment in TYPE or one of its subobjects; if there isn't, then + multiple move assignment can't cause any harm. */ + +bool +vbase_has_user_provided_move_assign (tree type) +{ + /* Does the type itself have a user-provided move assignment operator? */ + for (tree fns + = lookup_fnfields_slot_nolazy (type, ansi_assopname (NOP_EXPR)); + fns; fns = OVL_NEXT (fns)) + { + tree fn = OVL_CURRENT (fns); + if (move_fn_p (fn) && user_provided_p (fn)) + return true; + } + + /* Do any of its bases? */ + tree binfo = TYPE_BINFO (type); + tree base_binfo; + for (int i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i) + if (vbase_has_user_provided_move_assign (BINFO_TYPE (base_binfo))) + return true; + + /* Or non-static data members? */ + for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + { + if (TREE_CODE (field) == FIELD_DECL + && CLASS_TYPE_P (TREE_TYPE (field)) + && vbase_has_user_provided_move_assign (TREE_TYPE (field))) + return true; + } + + /* Seems not. */ + return false; +} + /* If default-initialization leaves part of TYPE uninitialized, returns a DECL for the field or TYPE itself (DR 253). */ @@ -5114,7 +5181,7 @@ finalize_literal_type_property (tree t) { tree fn; - if (cxx_dialect < cxx0x + if (cxx_dialect < cxx11 || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)) CLASSTYPE_LITERAL_P (t) = false; else if (CLASSTYPE_LITERAL_P (t) && !TYPE_HAS_TRIVIAL_DFLT (t) @@ -5254,7 +5321,7 @@ check_bases_and_members (tree t) /* Deduce noexcept on destructors. This needs to happen after we've set triviality flags appropriately for our bases. */ - if (cxx_dialect >= cxx0x) + if (cxx_dialect >= cxx11) deduce_noexcept_on_destructors (t); /* Check all the method declarations. */ @@ -5826,7 +5893,7 @@ layout_class_type (tree t, tree *virtuals_p) At this point, finish_record_layout will be called, but S1 is still incomplete.) */ - if (TREE_CODE (field) == VAR_DECL) + if (VAR_P (field)) { maybe_register_incomplete_var (field); /* The visibility of static data members is determined @@ -6327,7 +6394,7 @@ finish_struct_1 (tree t) /* Complete the rtl for any static member objects of the type we're working on. */ for (x = TYPE_FIELDS (t); x; x = DECL_CHAIN (x)) - if (TREE_CODE (x) == VAR_DECL && TREE_STATIC (x) + if (VAR_P (x) && TREE_STATIC (x) && TREE_TYPE (x) != error_mark_node && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (x)), t)) DECL_MODE (x) = TYPE_MODE (t); @@ -6700,7 +6767,7 @@ fixed_type_or_null (tree instance, int *nonnull, int *cdtorp) /* Enter the INSTANCE in a table to prevent recursion; a variable's initializer may refer to the variable itself. */ - if (TREE_CODE (instance) == VAR_DECL + if (VAR_P (instance) && DECL_INITIAL (instance) && !type_dependent_expression_p_push (DECL_INITIAL (instance)) && !fixed_type_or_null_ref_ht.find (instance)) @@ -7142,13 +7209,14 @@ resolve_address_of_overloaded_function (tree target_type, /* By the time we get here, we should be seeing only real pointer-to-member types, not the internal POINTER_TYPE to METHOD_TYPE representation. */ - gcc_assert (TREE_CODE (target_type) != POINTER_TYPE + gcc_assert (!TYPE_PTR_P (target_type) || TREE_CODE (TREE_TYPE (target_type)) != METHOD_TYPE); gcc_assert (is_overloaded_fn (overload)); /* Check that the TARGET_TYPE is reasonable. */ - if (TYPE_PTRFN_P (target_type)) + if (TYPE_PTRFN_P (target_type) + || TYPE_REFFN_P (target_type)) /* This is OK. */; else if (TYPE_PTRMEMFUNC_P (target_type)) /* This is OK, too. */ @@ -7247,19 +7315,38 @@ resolve_address_of_overloaded_function (tree target_type, one, or vice versa. */ continue; + tree ret = target_ret_type; + + /* If the template has a deduced return type, don't expose it to + template argument deduction. */ + if (undeduced_auto_decl (fn)) + ret = NULL_TREE; + /* Try to do argument deduction. */ targs = make_tree_vec (DECL_NTPARMS (fn)); instantiation = fn_type_unification (fn, explicit_targs, targs, args, - nargs, target_ret_type, + nargs, ret, DEDUCE_EXACT, LOOKUP_NORMAL, - false); + false, false); if (instantiation == error_mark_node) /* Instantiation failed. */ continue; + /* And now force instantiation to do return type deduction. */ + if (undeduced_auto_decl (instantiation)) + { + ++function_depth; + instantiate_decl (instantiation, /*defer*/false, /*class*/false); + --function_depth; + + require_deduced_type (instantiation); + } + /* See if there's a match. */ if (same_type_p (target_fn_type, static_fn_type (instantiation))) matches = tree_cons (instantiation, fn, matches); + + ggc_free (targs); } /* Now, remove all but the most specialized of the matches. */ @@ -7419,10 +7506,11 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags) if (TREE_TYPE (rhs) != NULL_TREE && ! (type_unknown_p (rhs))) { - if (same_type_p (lhstype, TREE_TYPE (rhs))) + tree fntype = non_reference (lhstype); + if (same_type_p (fntype, TREE_TYPE (rhs))) return rhs; if (flag_ms_extensions - && TYPE_PTRMEMFUNC_P (lhstype) + && TYPE_PTRMEMFUNC_P (fntype) && !TYPE_PTRMEMFUNC_P (TREE_TYPE (rhs))) /* Microsoft allows `A::f' to be resolved to a pointer-to-member. */ @@ -7431,7 +7519,7 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags) { if (flags & tf_error) error ("cannot convert %qE from type %qT to type %qT", - rhs, TREE_TYPE (rhs), lhstype); + rhs, TREE_TYPE (rhs), fntype); return error_mark_node; } } @@ -7764,7 +7852,7 @@ get_vtbl_decl_for_binfo (tree binfo) decl = TREE_OPERAND (TREE_OPERAND (decl, 0), 0); } if (decl) - gcc_assert (TREE_CODE (decl) == VAR_DECL); + gcc_assert (VAR_P (decl)); return decl; } @@ -9189,4 +9277,30 @@ publicly_uniquely_derived_p (tree parent, tree type) return base && base != error_mark_node; } +/* CTX1 and CTX2 are declaration contexts. Return the innermost common + class between them, if any. */ + +tree +common_enclosing_class (tree ctx1, tree ctx2) +{ + if (!TYPE_P (ctx1) || !TYPE_P (ctx2)) + return NULL_TREE; + gcc_assert (ctx1 == TYPE_MAIN_VARIANT (ctx1) + && ctx2 == TYPE_MAIN_VARIANT (ctx2)); + if (ctx1 == ctx2) + return ctx1; + for (tree t = ctx1; TYPE_P (t); t = TYPE_CONTEXT (t)) + TYPE_MARKED_P (t) = true; + tree found = NULL_TREE; + for (tree t = ctx2; TYPE_P (t); t = TYPE_CONTEXT (t)) + if (TYPE_MARKED_P (t)) + { + found = t; + break; + } + for (tree t = ctx1; TYPE_P (t); t = TYPE_CONTEXT (t)) + TYPE_MARKED_P (t) = false; + return found; +} + #include "gt-cp-class.h" diff --git a/gcc/cp/cp-array-notation.c b/gcc/cp/cp-array-notation.c new file mode 100644 index 00000000000..491da0fecc4 --- /dev/null +++ b/gcc/cp/cp-array-notation.c @@ -0,0 +1,1501 @@ +/* This file is part of the Intel(R) Cilk(TM) Plus support + It contains routines to handle Array Notation expression + handling routines in the C++ Compiler. + Copyright (C) 2013 Free Software Foundation, Inc. + Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>, + Intel Corporation + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +/* The Array Notation Transformation Technique: + + An array notation expression has 4 major components: + 1. The array name + 2. Start Index + 3. Number of elements we need to acess (we call it length) + 4. Stride + + So, if we have something like A[0:5:2], we are accessing A[0], A[2], A[4], + A[6] and A[8]. The user is responsible to make sure the access length does + not step outside the array's size. + + In this section, I highlight the overall method on how array notations are + broken up into C/C++ code. Almost all the functions follows this step: + + Let's say the user has used the array notation in a statement like this: + + A[St1:Ln:Str1] = B[St2:Ln:Str2] + <NON ARRAY_NOT STMT> + + where St{1,2} = Starting index, Ln = Number of elements we need to access, + and Str{1,2} = the stride. + Note: The length of both the array notation expressions must be the same. + + The above expression is broken into the following: + + for (Tmp_Var = 0; Tmp_Var < Ln; Tmp_Var++) + A[St1 + Tmp_Var * Str1] = B[St1 + Tmp_Var * Str2] + <NON_ARRAY_NOT_STMT>; +*/ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "cp-tree.h" +#include "c-family/c-common.h" +#include "diagnostic.h" +#include "tree-iterator.h" +#include "vec.h" +#include "gimple.h" + +/* Creates a FOR_STMT with INIT, COND, INCR and BODY as the initializer, + condition, increment expression and the loop-body, respectively. */ + +static void +create_an_loop (tree init, tree cond, tree incr, tree body) +{ + tree for_stmt; + + finish_expr_stmt (init); + for_stmt = begin_for_stmt (NULL_TREE, NULL_TREE); + finish_for_init_stmt (for_stmt); + finish_for_cond (cond, for_stmt); + finish_for_expr (incr, for_stmt); + finish_expr_stmt (body); + finish_for_stmt (for_stmt); +} + +/* If *VALUE is not a constant integer, then this function replaces it with + a variable to make it loop invariant for array notations. */ + +static inline void +make_triplet_val_inv (location_t loc, tree *value, tsubst_flags_t cry) +{ + tree var; + if (TREE_CODE (*value) != INTEGER_CST + && TREE_CODE (*value) != PARM_DECL + && TREE_CODE (*value) != VAR_DECL) + { + var = build_decl (loc, VAR_DECL, NULL_TREE, integer_type_node); + finish_expr_stmt (build_x_modify_expr (loc, var, NOP_EXPR, *value, cry)); + *value = var; + } +} + +/* Returns a vector of size RANK that contains an ARRAY_REF. This vector is + created using array notation-triplet information stored in AN_INFO. The + induction var is taken from AN_LOOP_INFO. + + For example: For an array notation A[5:10:2], the vector start will be + of size 1 holding '5', stride of same size as start but holding the value of + as 2, and is_vector as true. Let's assume VAR is 'x' + This function returns a vector of size 1 with the following data: + A[5 + (x * 2)] . +*/ + +static vec<tree, va_gc> * +create_array_refs (location_t loc, vec<vec<an_parts> > an_info, + vec<an_loop_parts> an_loop_info, size_t size, size_t rank) +{ + tree ind_mult, ind_incr; + vec<tree, va_gc> *array_operand = NULL; + for (size_t ii = 0; ii < size; ii++) + if (an_info[ii][0].is_vector) + { + tree array_opr = an_info[ii][rank - 1].value; + for (int s_jj = rank -1; s_jj >= 0; s_jj--) + { + tree str = NULL_TREE, v = NULL_TREE, st = NULL_TREE; + tree start = an_info[ii][s_jj].start; + tree stride = an_info[ii][s_jj].stride; + tree var = an_loop_info[s_jj].var; + + /* If stride and start are of same type and the induction var + is not, convert induction variable to stride's type. */ + if (TREE_TYPE (start) == TREE_TYPE (stride) + && TREE_TYPE (stride) != TREE_TYPE (var)) + { + st = start; + str = stride; + v = build_c_cast (loc, TREE_TYPE (str), var); + } + else if (TREE_TYPE (start) != TREE_TYPE (stride)) + { + /* If we reach here, then the stride and start are of + different types, and so it doesn't really matter what + the induction variable type is, convert everything to + integer. The reason why we pick an integer + instead of something like size_t is because the stride + and length can be + or -. */ + st = build_c_cast (loc, integer_type_node, start); + str = build_c_cast (loc, integer_type_node, stride); + v = build_c_cast (loc, integer_type_node, var); + } + else + { + st = start; + str = stride; + v = var; + } + + ind_mult = build2 (MULT_EXPR, TREE_TYPE (v), v, str); + ind_incr = build2 (PLUS_EXPR, TREE_TYPE (v), st, ind_mult); + /* Array [ start_index + (induction_var * stride)] */ + array_opr = grok_array_decl (loc, array_opr, ind_incr, false); + } + vec_safe_push (array_operand, array_opr); + } + else + vec_safe_push (array_operand, integer_one_node); + return array_operand; +} + +/* Populates the INCR and CMP fields in *NODE with the increment + (of type POSTINCREMENT) and comparison (of TYPE LT_EXPR) expressions, using + data from AN_INFO. */ + +void +create_cmp_incr (location_t loc, vec <an_loop_parts> *node, size_t rank, + vec<vec<an_parts> > an_info, tsubst_flags_t complain) +{ + for (size_t ii = 0; ii < rank; ii++) + { + (*node)[ii].incr = build_x_unary_op (loc, POSTINCREMENT_EXPR, + (*node)[ii].var, complain); + (*node)[ii].cmp = build_x_binary_op (loc, LT_EXPR, (*node)[ii].var, + TREE_CODE ((*node)[ii].var), + an_info[0][ii].length, + TREE_CODE (an_info[0][ii].length), + NULL, complain); + } +} + +/* Replaces all the scalar expressions in *NODE. Returns a STATEMENT LIST that + holds the NODE along with the variables that hold the results of the + invariant expressions. */ + +static tree +replace_invariant_exprs (tree *node) +{ + size_t ix = 0; + tree node_list = NULL_TREE; + tree t = NULL_TREE, new_var = NULL_TREE, new_node; + struct inv_list data; + + data.list_values = NULL; + data.replacement = NULL; + data.additional_tcodes = NULL; + cp_walk_tree (node, find_inv_trees, (void *) &data, NULL); + + if (vec_safe_length (data.list_values)) + { + node_list = push_stmt_list (); + for (ix = 0; vec_safe_iterate (data.list_values, ix, &t); ix++) + { + if (processing_template_decl || !TREE_TYPE (t)) + new_var = build_min_nt_loc (EXPR_LOCATION (t), VAR_DECL, NULL_TREE, + NULL_TREE); + else + new_var = build_decl (EXPR_LOCATION (t), VAR_DECL, NULL_TREE, + TREE_TYPE (t)); + gcc_assert (new_var != NULL_TREE && new_var != error_mark_node); + new_node = build_x_modify_expr (EXPR_LOCATION (t), new_var, NOP_EXPR, + t, tf_warning_or_error); + finish_expr_stmt (new_node); + vec_safe_push (data.replacement, new_var); + } + cp_walk_tree (node, replace_inv_trees, (void *) &data, NULL); + node_list = pop_stmt_list (node_list); + } + return node_list; +} + +/* Replace array notation's built-in function passed in AN_BUILTIN_FN with + the appropriate loop and computation (all stored in variable LOOP of type + tree node). The output of the function function is always a scalar and that + result is returned in *NEW_VAR. *NEW_VAR is NULL_TREE if the function is + __sec_reduce_mutating. */ + +static tree +expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var) +{ + tree new_var_type = NULL_TREE, func_parm, new_yes_expr, new_no_expr; + tree array_ind_value = NULL_TREE, new_no_ind, new_yes_ind, new_no_list; + tree new_yes_list, new_cond_expr, new_expr = NULL_TREE; + tree new_var_init = NULL_TREE, new_exp_init = NULL_TREE; + vec<tree, va_gc> *array_list = NULL, *array_operand = NULL; + size_t list_size = 0, rank = 0, ii = 0; + tree body, an_init, loop_with_init = alloc_stmt_list (); + tree array_op0, comp_node = NULL_TREE; + tree call_fn = NULL_TREE, identity_value = NULL_TREE; + tree init = NULL_TREE, cond_init = NULL_TREE; + enum tree_code code = NOP_EXPR; + location_t location = UNKNOWN_LOCATION; + vec<vec<an_parts> > an_info = vNULL; + vec<an_loop_parts> an_loop_info = vNULL; + enum built_in_function an_type = + is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn)); + vec <tree, va_gc> *func_args; + + if (an_type == BUILT_IN_NONE) + return NULL_TREE; + + if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE + && an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING) + func_parm = CALL_EXPR_ARG (an_builtin_fn, 0); + else + { + call_fn = CALL_EXPR_ARG (an_builtin_fn, 2); + + /* We need to do this because we are "faking" the builtin function types, + so the compiler does a bunch of typecasts and this will get rid of + all that! */ + STRIP_NOPS (call_fn); + if (TREE_CODE (call_fn) != OVERLOAD + && TREE_CODE (call_fn) != FUNCTION_DECL) + call_fn = TREE_OPERAND (call_fn, 0); + identity_value = CALL_EXPR_ARG (an_builtin_fn, 0); + func_parm = CALL_EXPR_ARG (an_builtin_fn, 1); + STRIP_NOPS (identity_value); + } + STRIP_NOPS (func_parm); + + location = EXPR_LOCATION (an_builtin_fn); + + /* Note about using find_rank (): If find_rank returns false, then it must + have already reported an error, thus we just return an error_mark_node + without any doing any error emission. */ + if (!find_rank (location, an_builtin_fn, an_builtin_fn, true, &rank)) + return error_mark_node; + if (rank == 0) + return an_builtin_fn; + else if (rank > 1 + && (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND + || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)) + { + error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot " + "have arrays with dimension greater than 1"); + return error_mark_node; + } + + extract_array_notation_exprs (func_parm, true, &array_list); + list_size = vec_safe_length (array_list); + switch (an_type) + { + case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD: + case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL: + case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX: + case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN: + new_var_type = TREE_TYPE ((*array_list)[0]); + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO: + case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO: + case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO: + case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO: + new_var_type = integer_type_node; + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND: + case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND: + new_var_type = size_type_node; + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE: + if (call_fn && identity_value) + new_var_type = TREE_TYPE ((*array_list)[0]); + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING: + new_var_type = NULL_TREE; + break; + default: + gcc_unreachable (); + } + + if (new_var_type && TREE_CODE (new_var_type) == ARRAY_TYPE) + new_var_type = TREE_TYPE (new_var_type); + an_loop_info.safe_grow_cleared (rank); + + an_init = push_stmt_list (); + + /* Assign the array notation components to variable so that they can satisfy + the exec-once rule. */ + for (ii = 0; ii < list_size; ii++) + if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF) + { + tree anode = (*array_list)[ii]; + make_triplet_val_inv (location, &ARRAY_NOTATION_START (anode), + tf_warning_or_error); + make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (anode), + tf_warning_or_error); + make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (anode), + tf_warning_or_error); + } + cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info); + for (ii = 0; ii < rank; ii++) + { + an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE, + TREE_TYPE (an_info[0][ii].start)); + an_loop_info[ii].ind_init = build_x_modify_expr + (location, an_loop_info[ii].var, NOP_EXPR, + build_zero_cst (TREE_TYPE (an_loop_info[ii].var)), + tf_warning_or_error); + } + + array_operand = create_array_refs (location, an_info, an_loop_info, + list_size, rank); + replace_array_notations (&func_parm, true, array_list, array_operand); + + if (!TREE_TYPE (func_parm)) + TREE_TYPE (func_parm) = TREE_TYPE ((*array_list)[0]); + + create_cmp_incr (location, &an_loop_info, rank, an_info, tf_warning_or_error); + if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING) + { + if (processing_template_decl) + *new_var = build_decl (location, VAR_DECL, NULL_TREE, new_var_type); + else + *new_var = create_tmp_var (new_var_type, NULL); + } + else + /* We do not require a new variable for mutating. The "identity value" + itself is the variable. */ + *new_var = NULL_TREE; + + if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND + || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) + { + array_ind_value = create_tmp_var (TREE_TYPE (func_parm), NULL); + gcc_assert (array_ind_value && (array_ind_value != error_mark_node)); + DECL_INITIAL (array_ind_value) = NULL_TREE; + pushdecl (array_ind_value); + } + + array_op0 = (*array_operand)[0]; + switch (an_type) + { + case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD: + code = PLUS_EXPR; + init = build_zero_cst (new_var_type); + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL: + code = MULT_EXPR; + init = build_one_cst (new_var_type); + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO: + case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO: + code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO) ? EQ_EXPR + : NE_EXPR; + init = build_zero_cst (new_var_type); + cond_init = build_one_cst (new_var_type); + comp_node = build_zero_cst (TREE_TYPE (func_parm)); + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO: + case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO: + code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO) ? NE_EXPR + : EQ_EXPR; + init = build_one_cst (new_var_type); + cond_init = build_zero_cst (new_var_type); + comp_node = build_zero_cst (TREE_TYPE (func_parm)); + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX: + code = MAX_EXPR; + init = TYPE_MIN_VALUE (new_var_type) ? TYPE_MIN_VALUE (new_var_type) + : func_parm; + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN: + code = MIN_EXPR; + init = TYPE_MAX_VALUE (new_var_type) ? TYPE_MAX_VALUE (new_var_type) + : func_parm; + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND: + case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND: + code = an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND ? LE_EXPR + : GE_EXPR; + init = an_loop_info[0].var; + case BUILT_IN_CILKPLUS_SEC_REDUCE: + init = identity_value; + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING: + init = NULL_TREE; + break; + default: + gcc_unreachable (); + } + + if (init) + new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR, init, + tf_warning_or_error); + switch (an_type) + { + case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD: + case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL: + new_expr = build_x_modify_expr (location, *new_var, code, func_parm, + tf_warning_or_error); + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO: + case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO: + case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO: + case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO: + /* In all these cases, assume the false case is true and as soon as + we find a true case, set the true flag on and latch it in. */ + new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, + cond_init, tf_warning_or_error); + new_no_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, + *new_var, tf_warning_or_error); + new_cond_expr = build_x_binary_op + (location, code, func_parm, TREE_CODE (func_parm), comp_node, + TREE_CODE (comp_node), NULL, tf_warning_or_error); + new_expr = build_x_conditional_expr (location, new_cond_expr, + new_yes_expr, new_no_expr, + tf_warning_or_error); + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX: + case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN: + new_cond_expr = build_x_binary_op + (location, code, *new_var, TREE_CODE (*new_var), func_parm, + TREE_CODE (func_parm), NULL, tf_warning_or_error); + new_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, func_parm, + tf_warning_or_error); + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND: + case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND: + new_exp_init = build_x_modify_expr (location, array_ind_value, NOP_EXPR, + func_parm, tf_warning_or_error); + new_yes_expr = build_x_modify_expr (location, array_ind_value, NOP_EXPR, + func_parm, tf_warning_or_error); + new_no_expr = build_x_modify_expr (location, array_ind_value, NOP_EXPR, + array_ind_value, tf_warning_or_error); + if (list_size > 1) + new_yes_ind = build_x_modify_expr (location, *new_var, NOP_EXPR, + an_loop_info[0].var, + tf_warning_or_error); + else + new_yes_ind = build_x_modify_expr (location, *new_var, NOP_EXPR, + TREE_OPERAND (array_op0, 1), + tf_warning_or_error); + new_no_ind = build_x_modify_expr (location, *new_var, NOP_EXPR, *new_var, + tf_warning_or_error); + new_yes_list = alloc_stmt_list (); + append_to_statement_list (new_yes_ind, &new_yes_list); + append_to_statement_list (new_yes_expr, &new_yes_list); + + new_no_list = alloc_stmt_list (); + append_to_statement_list (new_no_ind, &new_no_list); + append_to_statement_list (new_no_expr, &new_no_list); + + new_cond_expr = build_x_binary_op (location, code, array_ind_value, + TREE_CODE (array_ind_value), func_parm, + TREE_CODE (func_parm), NULL, + tf_warning_or_error); + new_expr = build_x_conditional_expr (location, new_cond_expr, + new_yes_list, new_no_list, + tf_warning_or_error); + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE: + case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING: + func_args = make_tree_vector (); + if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE) + vec_safe_push (func_args, *new_var); + else + vec_safe_push (func_args, identity_value); + vec_safe_push (func_args, func_parm); + + new_expr = finish_call_expr (call_fn, &func_args, false, true, + tf_warning_or_error); + if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE) + new_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, new_expr, + tf_warning_or_error); + release_tree_vector (func_args); + break; + default: + gcc_unreachable (); + } + + /* The reason we are putting initial variable twice is because the + new exp init below depends on this value being initialized. */ + for (ii = 0; ii < rank; ii++) + finish_expr_stmt (an_loop_info[ii].ind_init); + + if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING) + finish_expr_stmt (new_var_init); + + if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND + || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) + finish_expr_stmt (new_exp_init); + + an_init = pop_stmt_list (an_init); + append_to_statement_list_force (an_init, &loop_with_init); + body = new_expr; + + for (ii = 0; ii < rank; ii++) + { + tree new_loop = push_stmt_list (); + create_an_loop (an_loop_info[ii].ind_init, an_loop_info[ii].cmp, + an_loop_info[ii].incr, body); + body = pop_stmt_list (new_loop); + } + append_to_statement_list_force (body, &loop_with_init); + + an_info.release (); + an_loop_info.release (); + + return loop_with_init; +} + +/* Returns a loop with ARRAY_REF inside it with an appropriate modify expr. + The LHS and/or RHS will be array notation expressions that have a + MODIFYCODE. The location of the variable is specified by LOCATION. */ + +static tree +expand_an_in_modify_expr (location_t location, tree lhs, + enum tree_code modifycode, tree rhs, + tsubst_flags_t complain) +{ + tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE; + tree array_expr = NULL_TREE; + tree body = NULL_TREE; + vec<tree> cond_expr = vNULL; + vec<tree, va_gc> *lhs_array_operand = NULL, *rhs_array_operand = NULL; + size_t lhs_rank = 0, rhs_rank = 0, ii = 0; + vec<tree, va_gc> *rhs_list = NULL, *lhs_list = NULL; + size_t rhs_list_size = 0, lhs_list_size = 0; + tree new_modify_expr, new_var = NULL_TREE, builtin_loop, scalar_mods; + bool found_builtin_fn = false; + tree an_init, loop_with_init = alloc_stmt_list (); + vec<vec<an_parts> > lhs_an_info = vNULL, rhs_an_info = vNULL; + vec<an_loop_parts> lhs_an_loop_info = vNULL, rhs_an_loop_info = vNULL; + + if (!find_rank (location, rhs, rhs, false, &rhs_rank)) + return error_mark_node; + extract_array_notation_exprs (rhs, false, &rhs_list); + rhs_list_size = vec_safe_length (rhs_list); + an_init = push_stmt_list (); + if (rhs_rank) + { + scalar_mods = replace_invariant_exprs (&rhs); + if (scalar_mods) + finish_expr_stmt (scalar_mods); + } + for (ii = 0; ii < rhs_list_size; ii++) + { + tree rhs_node = (*rhs_list)[ii]; + if (TREE_CODE (rhs_node) == CALL_EXPR) + { + builtin_loop = expand_sec_reduce_builtin (rhs_node, &new_var); + if (builtin_loop == error_mark_node) + return error_mark_node; + else if (builtin_loop) + { + finish_expr_stmt (builtin_loop); + found_builtin_fn = true; + if (new_var) + { + vec <tree, va_gc> *rhs_sub_list = NULL, *new_var_list = NULL; + vec_safe_push (rhs_sub_list, rhs_node); + vec_safe_push (new_var_list, new_var); + replace_array_notations (&rhs, false, rhs_sub_list, + new_var_list); + } + } + } + } + lhs_rank = 0; + rhs_rank = 0; + if (!find_rank (location, lhs, lhs, true, &lhs_rank) + || !find_rank (location, rhs, rhs, true, &rhs_rank)) + { + pop_stmt_list (an_init); + return error_mark_node; + } + + /* If both are scalar, then the only reason why we will get this far is if + there is some array notations inside it and was using a builtin array + notation functions. If so, we have already broken those guys up and now + a simple build_x_modify_expr would do. */ + if (lhs_rank == 0 && rhs_rank == 0) + { + if (found_builtin_fn) + { + new_modify_expr = build_x_modify_expr (location, lhs, + modifycode, rhs, complain); + finish_expr_stmt (new_modify_expr); + pop_stmt_list (an_init); + return an_init; + } + else + { + pop_stmt_list (an_init); + return NULL_TREE; + } + } + + /* If for some reason location is not set, then find if LHS or RHS has + location info. If so, then use that so we atleast have an idea. */ + if (location == UNKNOWN_LOCATION) + { + if (EXPR_LOCATION (lhs) != UNKNOWN_LOCATION) + location = EXPR_LOCATION (lhs); + else if (EXPR_LOCATION (rhs) != UNKNOWN_LOCATION) + location = EXPR_LOCATION (rhs); + } + + /* We need this when we have a scatter issue. */ + extract_array_notation_exprs (lhs, true, &lhs_list); + rhs_list = NULL; + extract_array_notation_exprs (rhs, true, &rhs_list); + rhs_list_size = vec_safe_length (rhs_list); + lhs_list_size = vec_safe_length (lhs_list); + + if (lhs_rank == 0 && rhs_rank != 0) + { + if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (rhs)) + location = EXPR_LOCATION (rhs); + error_at (location, "%qD cannot be scalar when %qD is not", lhs, rhs); + return error_mark_node; + } + if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank) + { + error_at (location, "rank mismatch between %qE and %qE", lhs, rhs); + return error_mark_node; + } + + /* Assign the array notation components to variable so that they can satisfy + the execute-once rule. */ + for (ii = 0; ii < lhs_list_size; ii++) + { + tree anode = (*lhs_list)[ii]; + make_triplet_val_inv (location, &ARRAY_NOTATION_START (anode), complain); + make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (anode), complain); + make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (anode), complain); + } + for (ii = 0; ii < rhs_list_size; ii++) + if ((*rhs_list)[ii] && TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF) + { + tree aa = (*rhs_list)[ii]; + make_triplet_val_inv (location, &ARRAY_NOTATION_START (aa), complain); + make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (aa), complain); + make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (aa), complain); + } + lhs_an_loop_info.safe_grow_cleared (lhs_rank); + + if (rhs_rank) + rhs_an_loop_info.safe_grow_cleared (rhs_rank); + + cond_expr.safe_grow_cleared (MAX (lhs_rank, rhs_rank)); + cilkplus_extract_an_triplets (lhs_list, lhs_list_size, lhs_rank, + &lhs_an_info); + if (rhs_list) + cilkplus_extract_an_triplets (rhs_list, rhs_list_size, rhs_rank, + &rhs_an_info); + if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_an_info) + || (rhs_list && length_mismatch_in_expr_p (EXPR_LOCATION (rhs), + rhs_an_info))) + { + pop_stmt_list (an_init); + return error_mark_node; + } + tree rhs_len = (rhs_list_size > 0 && rhs_rank > 0) ? + rhs_an_info[0][0].length : NULL_TREE; + tree lhs_len = (lhs_list_size > 0 && lhs_rank > 0) ? + lhs_an_info[0][0].length : NULL_TREE; + if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0 + && TREE_CODE (lhs_len) == INTEGER_CST && rhs_len + && TREE_CODE (rhs_len) == INTEGER_CST) + { + HOST_WIDE_INT l_length = int_cst_value (lhs_len); + HOST_WIDE_INT r_length = int_cst_value (rhs_len); + if (absu_hwi (l_length) != absu_hwi (r_length)) + { + error_at (location, "length mismatch between LHS and RHS"); + pop_stmt_list (an_init); + return error_mark_node; + } + } + for (ii = 0; ii < lhs_rank; ii++) + if (lhs_an_info[0][ii].start && TREE_TYPE (lhs_an_info[0][ii].start)) + lhs_an_loop_info[ii].var = + build_decl (location, VAR_DECL, NULL_TREE, + TREE_TYPE (lhs_an_info[0][ii].start)); + else + lhs_an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE, + integer_type_node); + if (rhs_list_size > 0) + { + rhs_array_operand = fix_sec_implicit_args (location, rhs_list, + lhs_an_loop_info, lhs_rank, + lhs); + if (!rhs_array_operand) + return error_mark_node; + } + replace_array_notations (&rhs, true, rhs_list, rhs_array_operand); + rhs_list_size = 0; + rhs_list = NULL; + extract_array_notation_exprs (rhs, true, &rhs_list); + rhs_list_size = vec_safe_length (rhs_list); + + for (ii = 0; ii < lhs_rank; ii++) + if (lhs_an_info[0][ii].is_vector) + { + lhs_an_loop_info[ii].ind_init = build_x_modify_expr + (location, lhs_an_loop_info[ii].var, NOP_EXPR, + build_zero_cst (TREE_TYPE (lhs_an_loop_info[ii].var)), complain); + } + for (ii = 0; ii < rhs_rank; ii++) + { + /* When we have a polynomial, we assume that the indices are of type + integer. */ + rhs_an_loop_info[ii].var = + build_decl (location, VAR_DECL, NULL_TREE, + TREE_TYPE (rhs_an_info[0][ii].start)); + rhs_an_loop_info[ii].ind_init = build_x_modify_expr + (location, rhs_an_loop_info[ii].var, NOP_EXPR, + build_zero_cst (TREE_TYPE (rhs_an_loop_info[ii].var)), complain); + } + + if (lhs_rank) + { + lhs_array_operand = + create_array_refs (location, lhs_an_info, lhs_an_loop_info, + lhs_list_size, lhs_rank); + replace_array_notations (&lhs, true, lhs_list, lhs_array_operand); + } + + if (rhs_array_operand) + vec_safe_truncate (rhs_array_operand, 0); + if (rhs_rank) + { + rhs_array_operand = create_array_refs (location, rhs_an_info, + rhs_an_loop_info, rhs_list_size, + rhs_rank); + /* Replace all the array refs created by the above function because this + variable is blown away by the fix_sec_implicit_args function below. */ + replace_array_notations (&rhs, true, rhs_list, rhs_array_operand); + vec_safe_truncate (rhs_array_operand , 0); + rhs_array_operand = fix_sec_implicit_args (location, rhs_list, + rhs_an_loop_info, rhs_rank, + rhs); + if (!rhs_array_operand) + return error_mark_node; + replace_array_notations (&rhs, true, rhs_list, rhs_array_operand); + } + + array_expr_rhs = rhs; + array_expr_lhs = lhs; + + array_expr = build_x_modify_expr (location, array_expr_lhs, modifycode, + array_expr_rhs, complain); + create_cmp_incr (location, &lhs_an_loop_info, lhs_rank, lhs_an_info, + complain); + if (rhs_rank) + create_cmp_incr (location, &rhs_an_loop_info, rhs_rank, rhs_an_info, + complain); + for (ii = 0; ii < MAX (rhs_rank, lhs_rank); ii++) + if (ii < lhs_rank && ii < rhs_rank) + cond_expr[ii] = build_x_binary_op + (location, TRUTH_ANDIF_EXPR, lhs_an_loop_info[ii].cmp, + TREE_CODE (lhs_an_loop_info[ii].cmp), rhs_an_loop_info[ii].cmp, + TREE_CODE (rhs_an_loop_info[ii].cmp), NULL, complain); + else if (ii < lhs_rank && ii >= rhs_rank) + cond_expr[ii] = lhs_an_loop_info[ii].cmp; + else + /* No need to compare ii < rhs_rank && ii >= lhs_rank because valid Array + notation expression cannot RHS's rank cannot be greater than LHS. */ + gcc_unreachable (); + + an_init = pop_stmt_list (an_init); + append_to_statement_list_force (an_init, &loop_with_init); + body = array_expr; + for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++) + { + tree incr_list = alloc_stmt_list (); + tree init_list = alloc_stmt_list (); + tree new_loop = push_stmt_list (); + + if (lhs_rank) + { + append_to_statement_list_force (lhs_an_loop_info[ii].ind_init, + &init_list); + append_to_statement_list_force (lhs_an_loop_info[ii].incr, + &incr_list); + } + if (rhs_rank) + { + append_to_statement_list_force (rhs_an_loop_info[ii].ind_init, + &init_list); + append_to_statement_list_force (rhs_an_loop_info[ii].incr, + &incr_list); + } + create_an_loop (init_list, cond_expr[ii], incr_list, body); + body = pop_stmt_list (new_loop); + } + append_to_statement_list (body, &loop_with_init); + + lhs_an_info.release (); + lhs_an_loop_info.release (); + if (rhs_rank) + { + rhs_an_info.release (); + rhs_an_loop_info.release (); + } + cond_expr.release (); + + return loop_with_init; +} + +/* Helper function for expand_conditonal_array_notations. Encloses the + conditional statement passed in ORIG_STMT with a loop around it and + replaces the condition in STMT with a ARRAY_REF tree-node to the array. + The condition must have a ARRAY_NOTATION_REF tree. */ + +static tree +cp_expand_cond_array_notations (tree orig_stmt) +{ + vec<tree, va_gc> *array_list = NULL, *array_operand = NULL; + size_t list_size = 0; + size_t rank = 0, ii = 0; + tree an_init, body, stmt = NULL_TREE; + tree builtin_loop, new_var = NULL_TREE; + tree loop_with_init = alloc_stmt_list (); + tsubst_flags_t complain = tf_warning_or_error; + location_t location = UNKNOWN_LOCATION; + vec<vec<an_parts> > an_info = vNULL; + vec<an_loop_parts> an_loop_info = vNULL; + + if (TREE_CODE (orig_stmt) == COND_EXPR) + { + size_t cond_rank = 0, yes_rank = 0, no_rank = 0; + tree yes_expr = COND_EXPR_THEN (orig_stmt); + tree no_expr = COND_EXPR_ELSE (orig_stmt); + tree cond = COND_EXPR_COND (orig_stmt); + if (!find_rank (EXPR_LOCATION (cond), cond, cond, true, &cond_rank) + || !find_rank (EXPR_LOCATION (yes_expr), yes_expr, yes_expr, true, + &yes_rank) + || find_rank (EXPR_LOCATION (no_expr), no_expr, no_expr, true, + &no_rank)) + return error_mark_node; + if (cond_rank != 0 && cond_rank != yes_rank && yes_rank != 0) + { + error_at (EXPR_LOCATION (yes_expr), "rank mismatch with controlling" + " expression of parent if-statement"); + return error_mark_node; + } + else if (cond_rank != 0 && cond_rank != no_rank && no_rank != 0) + { + error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling " + "expression of parent if-statement"); + return error_mark_node; + } + } + else if (TREE_CODE (orig_stmt) == IF_STMT) + { + size_t cond_rank = 0, yes_rank = 0, no_rank = 0; + tree yes_expr = THEN_CLAUSE (orig_stmt); + tree no_expr = ELSE_CLAUSE (orig_stmt); + tree cond = IF_COND (orig_stmt); + if (!find_rank (EXPR_LOCATION (cond), cond, cond, true, &cond_rank) + || (yes_expr + && !find_rank (EXPR_LOCATION (yes_expr), yes_expr, yes_expr, true, + &yes_rank)) + || (no_expr + && !find_rank (EXPR_LOCATION (no_expr), no_expr, no_expr, true, + &no_rank))) + return error_mark_node; + if (cond_rank != 0 && cond_rank != yes_rank && yes_rank != 0) + { + error_at (EXPR_LOCATION (yes_expr), "rank mismatch with controlling" + " expression of parent if-statement"); + return error_mark_node; + } + else if (cond_rank != 0 && cond_rank != no_rank && no_rank != 0) + { + error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling " + "expression of parent if-statement"); + return error_mark_node; + } + } + + if (!find_rank (EXPR_LOCATION (orig_stmt), orig_stmt, orig_stmt, true, + &rank)) + return error_mark_node; + if (rank == 0) + return orig_stmt; + + extract_array_notation_exprs (orig_stmt, false, &array_list); + stmt = alloc_stmt_list (); + for (ii = 0; ii < vec_safe_length (array_list); ii++) + { + tree array_node = (*array_list)[ii]; + if (TREE_CODE (array_node) == CALL_EXPR + || TREE_CODE (array_node) == AGGR_INIT_EXPR) + { + builtin_loop = expand_sec_reduce_builtin (array_node, &new_var); + if (builtin_loop == error_mark_node) + finish_expr_stmt (error_mark_node); + else if (new_var) + { + vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL; + vec_safe_push (sub_list, array_node); + vec_safe_push (new_var_list, new_var); + replace_array_notations (&orig_stmt, false, sub_list, + new_var_list); + append_to_statement_list_force (builtin_loop, &stmt); + } + } + } + append_to_statement_list_force (orig_stmt, &stmt); + rank = 0; + array_list = NULL; + if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank)) + return error_mark_node; + if (rank == 0) + return stmt; + + extract_array_notation_exprs (stmt, true, &array_list); + list_size = vec_safe_length (array_list); + if (list_size == 0) + return stmt; + + location = EXPR_LOCATION (orig_stmt); + list_size = vec_safe_length (array_list); + an_loop_info.safe_grow_cleared (rank); + + an_init = push_stmt_list (); + + /* Assign the array notation components to variable so that they can + satisfy the exec-once rule. */ + for (ii = 0; ii < list_size; ii++) + { + tree anode = (*array_list)[ii]; + make_triplet_val_inv (location, &ARRAY_NOTATION_START (anode), complain); + make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (anode), complain); + make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (anode), complain); + } + cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info); + for (ii = 0; ii < rank; ii++) + if (TREE_TYPE (an_info[0][ii].start) + && TREE_CODE (TREE_TYPE (an_info[0][ii].start)) != TEMPLATE_TYPE_PARM) + { + an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE, + TREE_TYPE (an_info[0][ii].start)); + an_loop_info[ii].ind_init = build_x_modify_expr + (location, an_loop_info[ii].var, NOP_EXPR, + build_zero_cst (TREE_TYPE (an_loop_info[ii].var)), + tf_warning_or_error); + } + else + { + an_loop_info[ii].var = build_min_nt_loc (location, VAR_DECL, + NULL_TREE, NULL_TREE); + an_loop_info[ii].ind_init = + build_x_modify_expr (location, an_loop_info[ii].var, NOP_EXPR, + integer_zero_node, tf_warning_or_error); + } + array_operand = create_array_refs (location, an_info, an_loop_info, + list_size, rank); + replace_array_notations (&stmt, true, array_list, array_operand); + create_cmp_incr (location, &an_loop_info, rank, an_info, tf_warning_or_error); + + an_init = pop_stmt_list (an_init); + append_to_statement_list_force (an_init, &loop_with_init); + body = stmt; + + for (ii = 0; ii < rank; ii++) + { + tree new_loop = push_stmt_list (); + create_an_loop (an_loop_info[ii].ind_init, an_loop_info[ii].cmp, + an_loop_info[ii].incr, body); + body = pop_stmt_list (new_loop); + } + append_to_statement_list_force (body, &loop_with_init); + + an_info.release (); + an_loop_info.release (); + + return loop_with_init; +} + +/* Transforms array notations inside unary expression ORIG_STMT with an + appropriate loop and ARRAY_REF (and returns all this as a super-tree called + LOOP). */ + +static tree +expand_unary_array_notation_exprs (tree orig_stmt) +{ + vec<tree, va_gc> *array_list = NULL, *array_operand = NULL; + size_t list_size = 0, rank = 0, ii = 0; + tree body; + tree builtin_loop, stmt = NULL_TREE, new_var = NULL_TREE; + location_t location = EXPR_LOCATION (orig_stmt); + tree an_init, loop_with_init = alloc_stmt_list (); + vec<vec<an_parts> > an_info = vNULL; + vec<an_loop_parts> an_loop_info = vNULL; + + if (!find_rank (location, orig_stmt, orig_stmt, true, &rank)) + return error_mark_node; + if (rank == 0) + return orig_stmt; + + extract_array_notation_exprs (orig_stmt, false, &array_list); + list_size = vec_safe_length (array_list); + location = EXPR_LOCATION (orig_stmt); + stmt = NULL_TREE; + for (ii = 0; ii < list_size; ii++) + if (TREE_CODE ((*array_list)[ii]) == CALL_EXPR + || TREE_CODE ((*array_list)[ii]) == AGGR_INIT_EXPR) + { + tree list_node = (*array_list)[ii]; + builtin_loop = expand_sec_reduce_builtin (list_node, &new_var); + if (builtin_loop == error_mark_node) + return error_mark_node; + else if (builtin_loop) + { + vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL; + stmt = alloc_stmt_list (); + append_to_statement_list_force (builtin_loop, &stmt); + vec_safe_push (sub_list, list_node); + vec_safe_push (new_var_list, new_var); + replace_array_notations (&orig_stmt, false, sub_list, new_var_list); + } + } + if (stmt != NULL_TREE) + append_to_statement_list_force (finish_expr_stmt (orig_stmt), &stmt); + else + stmt = orig_stmt; + rank = 0; + list_size = 0; + array_list = NULL; + extract_array_notation_exprs (stmt, true, &array_list); + list_size = vec_safe_length (array_list); + + if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank)) + return error_mark_node; + if (rank == 0 || list_size == 0) + return stmt; + an_loop_info.safe_grow_cleared (rank); + an_init = push_stmt_list (); + /* Assign the array notation components to variable so that they can satisfy + the exec-once rule. */ + for (ii = 0; ii < list_size; ii++) + { + tree array_node = (*array_list)[ii]; + make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node), + tf_warning_or_error); + make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node), + tf_warning_or_error); + make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node), + tf_warning_or_error); + } + cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info); + + for (ii = 0; ii < rank; ii++) + { + an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE, + TREE_TYPE (an_info[0][ii].start)); + an_loop_info[ii].ind_init = build_x_modify_expr + (location, an_loop_info[ii].var, NOP_EXPR, + build_zero_cst (TREE_TYPE (an_loop_info[ii].var)), + tf_warning_or_error); + } + array_operand = create_array_refs (location, an_info, an_loop_info, + list_size, rank); + replace_array_notations (&stmt, true, array_list, array_operand); + create_cmp_incr (location, &an_loop_info, rank, an_info, tf_warning_or_error); + + an_init = pop_stmt_list (an_init); + append_to_statement_list_force (an_init, &loop_with_init); + body = stmt; + + for (ii = 0; ii < rank; ii++) + { + tree new_loop = push_stmt_list (); + create_an_loop (an_loop_info[ii].ind_init, an_loop_info[ii].cmp, + an_loop_info[ii].incr, body); + body = pop_stmt_list (new_loop); + } + append_to_statement_list_force (body, &loop_with_init); + + an_info.release (); + an_loop_info.release (); + + return loop_with_init; +} + +/* Expands the array notation's builtin reduction function in EXPR + (of type RETURN_EXPR) and returns a STATEMENT_LIST that contains a loop + with the builtin function expansion and a return statement at the end. */ + +static tree +expand_return_expr (tree expr) +{ + tree new_mod_list, new_var, new_mod, retval_expr; + + if (TREE_CODE (expr) != RETURN_EXPR) + return expr; + + location_t loc = EXPR_LOCATION (expr); + new_mod_list = alloc_stmt_list (); + retval_expr = TREE_OPERAND (expr, 0); + new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr)); + new_mod = expand_an_in_modify_expr (loc, new_var, NOP_EXPR, + TREE_OPERAND (retval_expr, 1), + tf_warning_or_error); + TREE_OPERAND (retval_expr, 1) = new_var; + TREE_OPERAND (expr, 0) = retval_expr; + append_to_statement_list_force (new_mod, &new_mod_list); + append_to_statement_list_force (expr, &new_mod_list); + return new_mod_list; +} + +/* Expands ARRAY_NOTATION_REF and builtin functions in a compound statement, + STMT. Returns the STMT with expanded array notations. */ + +tree +expand_array_notation_exprs (tree t) +{ + enum tree_code code; + bool is_expr; + location_t loc = UNKNOWN_LOCATION; + + if (!t) + return t; + + loc = EXPR_LOCATION (t); + + code = TREE_CODE (t); + is_expr = IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)); + switch (code) + { + case ERROR_MARK: + case IDENTIFIER_NODE: + case INTEGER_CST: + case REAL_CST: + case FIXED_CST: + case STRING_CST: + case BLOCK: + case PLACEHOLDER_EXPR: + case FIELD_DECL: + case VOID_TYPE: + case REAL_TYPE: + case SSA_NAME: + case LABEL_DECL: + case RESULT_DECL: + case VAR_DECL: + case PARM_DECL: + case NON_LVALUE_EXPR: + case NOP_EXPR: + case INIT_EXPR: + case ADDR_EXPR: + case ARRAY_REF: + case BIT_FIELD_REF: + case VECTOR_CST: + case COMPLEX_CST: + return t; + case MODIFY_EXPR: + if (contains_array_notation_expr (t)) + t = expand_an_in_modify_expr (loc, TREE_OPERAND (t, 0), NOP_EXPR, + TREE_OPERAND (t, 1), + tf_warning_or_error); + return t; + case MODOP_EXPR: + if (contains_array_notation_expr (t) && !processing_template_decl) + t = expand_an_in_modify_expr + (loc, TREE_OPERAND (t, 0), TREE_CODE (TREE_OPERAND (t, 1)), + TREE_OPERAND (t, 2), tf_warning_or_error); + return t; + case CONSTRUCTOR: + return t; + case BIND_EXPR: + { + BIND_EXPR_BODY (t) = + expand_array_notation_exprs (BIND_EXPR_BODY (t)); + return t; + } + case DECL_EXPR: + { + tree x = DECL_EXPR_DECL (t); + if (t && TREE_CODE (x) != FUNCTION_DECL) + if (DECL_INITIAL (x)) + t = expand_unary_array_notation_exprs (t); + return t; + } + case STATEMENT_LIST: + { + tree_stmt_iterator i; + for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) + *tsi_stmt_ptr (i) = + expand_array_notation_exprs (*tsi_stmt_ptr (i)); + return t; + } + + case OMP_PARALLEL: + case OMP_TASK: + case OMP_FOR: + case OMP_SINGLE: + case OMP_SECTION: + case OMP_SECTIONS: + case OMP_MASTER: + case OMP_ORDERED: + case OMP_CRITICAL: + case OMP_ATOMIC: + case OMP_CLAUSE: + case TARGET_EXPR: + case INTEGER_TYPE: + case ENUMERAL_TYPE: + case BOOLEAN_TYPE: + case POINTER_TYPE: + case ARRAY_TYPE: + case RECORD_TYPE: + case METHOD_TYPE: + return t; + case RETURN_EXPR: + if (contains_array_notation_expr (t)) + t = expand_return_expr (t); + return t; + case PREDECREMENT_EXPR: + case PREINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + case POSTINCREMENT_EXPR: + case AGGR_INIT_EXPR: + case CALL_EXPR: + t = expand_unary_array_notation_exprs (t); + return t; + case CONVERT_EXPR: + case CLEANUP_POINT_EXPR: + case EXPR_STMT: + TREE_OPERAND (t, 0) = expand_array_notation_exprs (TREE_OPERAND (t, 0)); + /* It is not necessary to wrap error_mark_node in EXPR_STMT. */ + if (TREE_OPERAND (t, 0) == error_mark_node) + return TREE_OPERAND (t, 0); + return t; + case COND_EXPR: + t = cp_expand_cond_array_notations (t); + if (TREE_CODE (t) == COND_EXPR) + { + COND_EXPR_THEN (t) = + expand_array_notation_exprs (COND_EXPR_THEN (t)); + COND_EXPR_ELSE (t) = + expand_array_notation_exprs (COND_EXPR_ELSE (t)); + } + else + t = expand_array_notation_exprs (t); + return t; + + case SWITCH_EXPR: + t = cp_expand_cond_array_notations (t); + if (TREE_CODE (t) == SWITCH_EXPR) + SWITCH_BODY (t) = expand_array_notation_exprs (SWITCH_BODY (t)); + else + t = expand_array_notation_exprs (t); + return t; + case FOR_STMT: + /* FIXME: Add a check for CILK_FOR_STMT here when we add Cilk tasking + keywords. */ + if (TREE_CODE (t) == FOR_STMT) + FOR_BODY (t) = expand_array_notation_exprs (FOR_BODY (t)); + else + t = expand_array_notation_exprs (t); + return t; + case IF_STMT: + t = cp_expand_cond_array_notations (t); + /* If the above function added some extra instructions above the original + if statement, then we can't assume it is still IF_STMT so we have to + check again. */ + if (TREE_CODE (t) == IF_STMT) + { + if (THEN_CLAUSE (t)) + THEN_CLAUSE (t) = expand_array_notation_exprs (THEN_CLAUSE (t)); + if (ELSE_CLAUSE (t)) + ELSE_CLAUSE (t) = expand_array_notation_exprs (ELSE_CLAUSE (t)); + } + else + t = expand_array_notation_exprs (t); + return t; + case SWITCH_STMT: + t = cp_expand_cond_array_notations (t); + /* If the above function added some extra instructions above the original + switch statement, then we can't assume it is still SWITCH_STMT so we + have to check again. */ + if (TREE_CODE (t) == SWITCH_STMT) + { + if (SWITCH_STMT_BODY (t)) + SWITCH_STMT_BODY (t) = + expand_array_notation_exprs (SWITCH_STMT_BODY (t)); + } + else + t = expand_array_notation_exprs (t); + return t; + case WHILE_STMT: + t = cp_expand_cond_array_notations (t); + /* If the above function added some extra instructions above the original + while statement, then we can't assume it is still WHILE_STMTso we + have to check again. */ + if (TREE_CODE (t) == WHILE_STMT) + { + if (WHILE_BODY (t)) + WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (t)); + } + else + t = expand_array_notation_exprs (t); + return t; + case DO_STMT: + t = cp_expand_cond_array_notations (t); + /* If the above function added some extra instructions above the original + do-while statement, then we can't assume it is still DO_STMT so we + have to check again. */ + if (TREE_CODE (t) == DO_STMT) + { + if (DO_BODY (t)) + DO_BODY (t) = expand_array_notation_exprs (DO_BODY (t)); + } + else + t = expand_array_notation_exprs (t); + return t; + default: + if (is_expr) + { + int i, len; + + /* Walk over all the sub-trees of this operand. */ + len = TREE_CODE_LENGTH (code); + + /* Go through the subtrees. We need to do this in forward order so + that the scope of a FOR_EXPR is handled properly. */ + for (i = 0; i < len; ++i) + TREE_OPERAND (t, i) = + expand_array_notation_exprs (TREE_OPERAND (t, i)); + } + return t; + } + return t; +} + +/* Given the base of an array (ARRAY), the START_INDEX, the number of elements + to be accessed (LENGTH) and the STRIDE, construct an ARRAY_NOTATION_REF tree + of type TYPE and return it. Restrictions on START_INDEX, LENGTH and STRIDE + are the same as that of index field passed into ARRAY_REF. The only + additional restriction is that, unlike index in ARRAY_REF, stride, length + and start_index cannot contain array notations. */ + +tree +build_array_notation_ref (location_t loc, tree array, tree start_index, + tree length, tree stride, tree type) +{ + tree array_ntn_expr = NULL_TREE; + + /* When dealing with templates, do the type checking at a later time. */ + if (processing_template_decl || !type) + { + if (!type && TREE_TYPE (array)) + type = TREE_TYPE (array); + array_ntn_expr = build_min_nt_loc (loc, ARRAY_NOTATION_REF, array, + start_index, length, stride, type, + NULL_TREE); + TREE_TYPE (array_ntn_expr) = type; + } + if (!stride) + { + if (TREE_CONSTANT (start_index) && TREE_CONSTANT (length) + && TREE_CODE (start_index) != VAR_DECL + && TREE_CODE (length) != VAR_DECL + && tree_int_cst_lt (length, start_index)) + stride = build_int_cst (TREE_TYPE (start_index), -1); + else + stride = build_int_cst (TREE_TYPE (start_index), 1); + } + + if (!cilkplus_an_triplet_types_ok_p (loc, start_index, length, stride, type)) + return error_mark_node; + + if (!processing_template_decl) + { + array_ntn_expr = build4 (ARRAY_NOTATION_REF, NULL_TREE, NULL_TREE, + NULL_TREE, NULL_TREE, NULL_TREE); + ARRAY_NOTATION_ARRAY (array_ntn_expr) = array; + ARRAY_NOTATION_START (array_ntn_expr) = start_index; + ARRAY_NOTATION_LENGTH (array_ntn_expr) = length; + ARRAY_NOTATION_STRIDE (array_ntn_expr) = stride; + if (type && (TREE_CODE (type) == ARRAY_TYPE + || TREE_CODE (type) == POINTER_TYPE)) + TREE_TYPE (array_ntn_expr) = TREE_TYPE (type); + else + TREE_TYPE (array_ntn_expr) = type; + } + SET_EXPR_LOCATION (array_ntn_expr, loc); + + return array_ntn_expr; +} + +/* Returns false if any of the Array notation triplet values: START_INDEX, + LENGTH and STRIDE, are not of integral type and have a rank greater than + zero. */ + +bool +cilkplus_an_triplet_types_ok_p (location_t loc, tree start_index, tree length, + tree stride, tree type) +{ + size_t stride_rank = 0, length_rank = 0, start_rank = 0; + if (!TREE_TYPE (start_index) || !INTEGRAL_TYPE_P (TREE_TYPE (start_index))) + { + error_at (loc, "start-index of array notation triplet is not an integer"); + return false; + } + if (!TREE_TYPE (length) || !INTEGRAL_TYPE_P (TREE_TYPE (length))) + { + error_at (loc, "length of array notation triplet is not an integer"); + return false; + } + if (!TREE_TYPE (stride) || !INTEGRAL_TYPE_P (TREE_TYPE (stride))) + { + error_at (loc, "stride of array notation triplet is not an integer"); + return false; + } + if (!TREE_CODE (type) == FUNCTION_TYPE) + { + error_at (loc, "array notations cannot be used with function type"); + return false; + } + while (type && (TREE_CODE (type) == POINTER_TYPE + || TREE_CODE (type) == ARRAY_TYPE)) + { + type = TREE_TYPE (type); + if (type && TREE_CODE (type) == FUNCTION_TYPE) + { + error_at (loc, "array notations cannot be used with function pointer" + " arrays"); + return false; + } + } + if (!find_rank (loc, start_index, start_index, false, &start_rank) + || !find_rank (loc, length, length, false, &length_rank) + || !find_rank (loc, stride, stride, false, &stride_rank)) + return false; + + if (start_rank != 0) + { + error_at (loc, "rank of an array notation triplet%'s start-index is not " + "zero"); + return false; + } + if (length_rank != 0) + { + error_at (loc, "rank of an array notation triplet%'s length is not zero"); + return false; + } + if (stride_rank != 0) + { + error_at (loc, "rank of array notation triplet%'s stride is not zero"); + return false; + } + return true; +} diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index b2bfd0c1fdc..38ef87868a8 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -759,7 +759,7 @@ omp_var_to_track (tree decl) type = TREE_TYPE (type); if (type == error_mark_node || !CLASS_TYPE_P (type)) return false; - if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl)) + if (VAR_P (decl) && DECL_THREAD_LOCAL_P (decl)) return false; if (cxx_omp_predetermined_sharing (decl) != OMP_CLAUSE_DEFAULT_UNSPECIFIED) return false; @@ -838,7 +838,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) /* If in an OpenMP context, note var uses. */ if (__builtin_expect (wtd->omp_ctx != NULL, 0) - && (TREE_CODE (stmt) == VAR_DECL + && (VAR_P (stmt) || TREE_CODE (stmt) == PARM_DECL || TREE_CODE (stmt) == RESULT_DECL) && omp_var_to_track (stmt)) @@ -857,7 +857,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) /* Map block scope extern declarations to visible declarations with the same name and type in outer scopes if any. */ if (cp_function_chain->extern_decl_map - && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL) + && VAR_OR_FUNCTION_DECL_P (stmt) && DECL_EXTERNAL (stmt)) { struct cxx_int_tree_map *h, in; @@ -998,7 +998,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) { tree decl; for (decl = BIND_EXPR_VARS (stmt); decl; decl = DECL_CHAIN (decl)) - if (TREE_CODE (decl) == VAR_DECL + if (VAR_P (decl) && !DECL_EXTERNAL (decl) && omp_var_to_track (decl)) { diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c index 47a6004258b..a7fa8e4b1e9 100644 --- a/gcc/cp/cp-lang.c +++ b/gcc/cp/cp-lang.c @@ -127,7 +127,8 @@ cxx_dwarf_name (tree t, int verbosity) static enum classify_record cp_classify_record (tree type) { - if (CLASSTYPE_DECLARED_CLASS (type)) + if (TYPE_LANG_SPECIFIC (type) + && CLASSTYPE_DECLARED_CLASS (type)) return RECORD_IS_CLASS; return RECORD_IS_STRUCT; diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c index fe96757bc07..d301db01a78 100644 --- a/gcc/cp/cp-objcp-common.c +++ b/gcc/cp/cp-objcp-common.c @@ -62,7 +62,7 @@ cxx_warn_unused_global_decl (const_tree decl) return false; /* Const variables take the place of #defines in C++. */ - if (TREE_CODE (decl) == VAR_DECL && TREE_READONLY (decl)) + if (VAR_P (decl) && TREE_READONLY (decl)) return false; return true; @@ -321,6 +321,7 @@ cp_common_init_ts (void) MARK_TS_TYPED (USING_STMT); MARK_TS_TYPED (LAMBDA_EXPR); MARK_TS_TYPED (CTOR_INITIALIZER); + MARK_TS_TYPED (ARRAY_NOTATION_REF); } #include "gt-cp-cp-objcp-common.h" diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index c3b2aecf3b1..00ee45013b3 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -90,6 +90,7 @@ c-common.h, not after. LAMBDA_EXPR_MUTABLE_P (in LAMBDA_EXPR) DECL_FINAL_P (in FUNCTION_DECL) QUALIFIED_NAME_IS_TEMPLATE (in SCOPE_REF) + DECLTYPE_FOR_INIT_CAPTURE (in DECLTYPE_TYPE) 2: IDENTIFIER_OPNAME_P (in IDENTIFIER_NODE) ICS_THIS_FLAG (in _CONV) DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL) @@ -97,6 +98,7 @@ c-common.h, not after. TYPENAME_IS_RESOLVING_P (in TYPE_NAME_TYPE) TARGET_EXPR_DIRECT_INIT_P (in TARGET_EXPR) FNDECL_USED_AUTO (in FUNCTION_DECL) + DECLTYPE_FOR_LAMBDA_PROXY (in DECLTYPE_TYPE) 3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out). ICS_BAD_FLAG (in _CONV) FN_TRY_BLOCK_P (in TRY_BLOCK) @@ -107,8 +109,10 @@ c-common.h, not after. or FIELD_DECL). IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE) DECL_TINFO_P (in VAR_DECL) + FUNCTION_REF_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE) 5: C_IS_RESERVED_WORD (in IDENTIFIER_NODE) DECL_VTABLE_OR_VTT_P (in VAR_DECL) + FUNCTION_RVALUE_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE) 6: IDENTIFIER_REPO_CHOSEN (in IDENTIFIER_NODE) DECL_CONSTRUCTION_VTABLE_P (in VAR_DECL) TYPE_MARKED_P (in _TYPE) @@ -121,6 +125,8 @@ c-common.h, not after. 4: TYPE_HAS_NONTRIVIAL_DESTRUCTOR 5: CLASS_TYPE_P (in RECORD_TYPE and UNION_TYPE) ENUM_FIXED_UNDERLYING_TYPE_P (in ENUMERAL_TYPE) + AUTO_IS_DECLTYPE (in TEMPLATE_TYPE_PARM) + REFERENCE_VLA_OK (in REFERENCE_TYPE) 6: TYPE_DEPENDENT_P_VALID Usage of DECL_LANG_FLAG_?: @@ -134,6 +140,7 @@ c-common.h, not after. DECL_MEMBER_TEMPLATE_P (in TEMPLATE_DECL) FUNCTION_PARAMETER_PACK_P (in PARM_DECL) USING_DECL_TYPENAME_P (in USING_DECL) + DECL_VLA_CAPTURE_P (in FIELD_DECL) 2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL). DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL) 3: DECL_IN_AGGR_P. @@ -241,6 +248,16 @@ struct GTY(()) lang_identifier { tree label_value; }; +/* Return a typed pointer version of T if it designates a + C++ front-end identifier. */ +inline lang_identifier* +identifier_p (tree t) +{ + if (TREE_CODE (t) == IDENTIFIER_NODE) + return (lang_identifier*) t; + return NULL; +} + /* In an IDENTIFIER_NODE, nonzero if this identifier is actually a keyword. C_RID_CODE (node) is then the RID_* value of the keyword, and C_RID_YYCODE is the token number wanted by Yacc. */ @@ -420,9 +437,11 @@ typedef enum cpp0x_warn_str /* inheriting constructors */ CPP0X_INHERITING_CTORS, /* C++11 attributes */ - CPP0X_ATTRIBUTES + CPP0X_ATTRIBUTES, + /* ref-qualified member functions */ + CPP0X_REF_QUALIFIER } cpp0x_warn_str; - + /* The various kinds of operation used by composite_pointer_type. */ typedef enum composite_pointer_operation @@ -463,6 +482,19 @@ typedef enum impl_conv_void { ICV_THIRD_IN_FOR /* for increment expression */ } impl_conv_void; +/* Possible invalid uses of an abstract class that might not have a + specific associated declaration. */ +typedef enum abstract_class_use { + ACU_UNKNOWN, /* unknown or decl provided */ + ACU_CAST, /* cast to abstract class */ + ACU_NEW, /* new-expression of abstract class */ + ACU_THROW, /* throw-expression of abstract class */ + ACU_CATCH, /* catch-parameter of abstract class */ + ACU_ARRAY, /* array of abstract class */ + ACU_RETURN, /* return type of abstract class */ + ACU_PARM /* parameter type of abstract class */ +} abstract_class_use; + /* Macros for access to language-specific slots in an identifier. */ #define IDENTIFIER_NAMESPACE_BINDINGS(NODE) \ @@ -1202,22 +1234,25 @@ enum languages { lang_c, lang_cplusplus, lang_java }; /* Nonzero if NODE has no name for linkage purposes. */ #define TYPE_ANONYMOUS_P(NODE) \ - (TAGGED_TYPE_P (NODE) && ANON_AGGRNAME_P (TYPE_LINKAGE_IDENTIFIER (NODE))) + (OVERLOAD_TYPE_P (NODE) && ANON_AGGRNAME_P (TYPE_LINKAGE_IDENTIFIER (NODE))) /* The _DECL for this _TYPE. */ #define TYPE_MAIN_DECL(NODE) (TYPE_STUB_DECL (TYPE_MAIN_VARIANT (NODE))) -/* Nonzero if T is a class (or struct or union) type. Also nonzero - for template type parameters, typename types, and instantiated - template template parameters. Keep these checks in ascending code - order. */ -#define MAYBE_CLASS_TYPE_P(T) \ +/* Nonzero if T is a type that could resolve to any kind of concrete type + at instantiation time. */ +#define WILDCARD_TYPE_P(T) \ (TREE_CODE (T) == TEMPLATE_TYPE_PARM \ || TREE_CODE (T) == TYPENAME_TYPE \ || TREE_CODE (T) == TYPEOF_TYPE \ || TREE_CODE (T) == BOUND_TEMPLATE_TEMPLATE_PARM \ - || TREE_CODE (T) == DECLTYPE_TYPE \ - || CLASS_TYPE_P (T)) + || TREE_CODE (T) == DECLTYPE_TYPE) + +/* Nonzero if T is a class (or struct or union) type. Also nonzero + for template type parameters, typename types, and instantiated + template template parameters. Keep these checks in ascending code + order. */ +#define MAYBE_CLASS_TYPE_P(T) (WILDCARD_TYPE_P (T) || CLASS_TYPE_P (T)) /* Set CLASS_TYPE_P for T to VAL. T must be a class, struct, or union type. */ @@ -1236,9 +1271,8 @@ enum languages { lang_c, lang_cplusplus, lang_java }; /* Keep these checks in ascending code order. */ #define RECORD_OR_UNION_CODE_P(T) \ ((T) == RECORD_TYPE || (T) == UNION_TYPE) -#define TAGGED_TYPE_P(T) \ +#define OVERLOAD_TYPE_P(T) \ (CLASS_TYPE_P (T) || TREE_CODE (T) == ENUMERAL_TYPE) -#define IS_OVERLOAD_TYPE(T) TAGGED_TYPE_P (T) /* True if this a "Java" type, defined in 'extern "Java"'. */ #define TYPE_FOR_JAVA(NODE) TYPE_LANG_FLAG_3 (NODE) @@ -1854,7 +1888,8 @@ struct GTY((variable_size)) lang_type { a deferred noexcept-specification, TREE_PURPOSE is a DEFERRED_NOEXCEPT (for templates) or an OVERLOAD list of functions (for implicitly declared functions). */ -#define TYPE_RAISES_EXCEPTIONS(NODE) TYPE_LANG_SLOT_1 (NODE) +#define TYPE_RAISES_EXCEPTIONS(NODE) \ + TYPE_LANG_SLOT_1 (FUNC_OR_METHOD_CHECK (NODE)) /* For FUNCTION_TYPE or METHOD_TYPE, return 1 iff it is declared `throw()' or noexcept(true). */ @@ -1892,9 +1927,8 @@ struct GTY(()) lang_decl_base { /* True for DECL codes which have template info and access. */ #define LANG_DECL_HAS_MIN(NODE) \ - (TREE_CODE (NODE) == FUNCTION_DECL \ + (VAR_OR_FUNCTION_DECL_P (NODE) \ || TREE_CODE (NODE) == FIELD_DECL \ - || TREE_CODE (NODE) == VAR_DECL \ || TREE_CODE (NODE) == CONST_DECL \ || TREE_CODE (NODE) == TYPE_DECL \ || TREE_CODE (NODE) == TEMPLATE_DECL \ @@ -2174,8 +2208,7 @@ struct GTY((variable_size)) lang_decl { /* Nonzero if NODE has DECL_DISCRIMINATOR and not DECL_ACCESS. */ #define DECL_DISCRIMINATOR_P(NODE) \ - (TREE_CODE (NODE) == VAR_DECL \ - && DECL_FUNCTION_SCOPE_P (NODE)) + (VAR_P (NODE) && DECL_FUNCTION_SCOPE_P (NODE)) /* Discriminator for name mangling. */ #define DECL_DISCRIMINATOR(NODE) (LANG_DECL_U2_CHECK (NODE, 1)->discriminator) @@ -2502,6 +2535,14 @@ struct GTY((variable_size)) lang_decl { /* 1 iff VAR_DECL node NODE is virtual table or VTT. */ #define DECL_VTABLE_OR_VTT_P(NODE) TREE_LANG_FLAG_5 (VAR_DECL_CHECK (NODE)) +/* 1 iff FUNCTION_TYPE or METHOD_TYPE has a ref-qualifier (either & or &&). */ +#define FUNCTION_REF_QUALIFIED(NODE) \ + TREE_LANG_FLAG_4 (FUNC_OR_METHOD_CHECK (NODE)) + +/* 1 iff FUNCTION_TYPE or METHOD_TYPE has &&-ref-qualifier. */ +#define FUNCTION_RVALUE_QUALIFIED(NODE) \ + TREE_LANG_FLAG_5 (FUNC_OR_METHOD_CHECK (NODE)) + /* Returns 1 iff VAR_DECL is a construction virtual table. DECL_VTABLE_OR_VTT_P will be true in this case and must be checked before using this macro. */ @@ -2698,7 +2739,10 @@ extern void decl_shadowed_for_var_insert (tree, tree); : TREE_VEC_LENGTH (INNERMOST_TEMPLATE_ARGS (NODE)) #endif /* The list of typedefs - used in the template - that need - access checking at template instantiation time. */ + access checking at template instantiation time. + + FIXME this should be associated with the TEMPLATE_DECL, not the + TEMPLATE_INFO. */ #define TI_TYPEDEFS_NEEDING_ACCESS_CHECKING(NODE) \ ((struct tree_template_info*)TEMPLATE_INFO_CHECK \ (NODE))->typedefs_needing_access_checking @@ -2937,6 +2981,11 @@ extern void decl_shadowed_for_var_insert (tree, tree); && (TREE_CODE (TREE_TYPE (TREE_OPERAND ((NODE), 0))) \ == REFERENCE_TYPE)) +/* True if NODE is a REFERENCE_TYPE which is OK to instantiate to be a + reference to VLA type, because it's used for VLA capture. */ +#define REFERENCE_VLA_OK(NODE) \ + (TYPE_LANG_FLAG_5 (REFERENCE_TYPE_CHECK (NODE))) + #define NEW_EXPR_USE_GLOBAL(NODE) \ TREE_LANG_FLAG_0 (NEW_EXPR_CHECK (NODE)) #define DELETE_EXPR_USE_GLOBAL(NODE) \ @@ -3000,7 +3049,7 @@ typedef struct aggr_init_expr_arg_iterator_d { /* Initialize the abstract argument list iterator object ITER with the arguments from AGGR_INIT_EXPR node EXP. */ -static inline void +inline void init_aggr_init_expr_arg_iterator (tree exp, aggr_init_expr_arg_iterator *iter) { @@ -3011,7 +3060,7 @@ init_aggr_init_expr_arg_iterator (tree exp, /* Return the next argument from abstract argument list iterator object ITER, and advance its state. Return NULL_TREE if there are no more arguments. */ -static inline tree +inline tree next_aggr_init_expr_arg (aggr_init_expr_arg_iterator *iter) { tree result; @@ -3026,7 +3075,7 @@ next_aggr_init_expr_arg (aggr_init_expr_arg_iterator *iter) past and return the first argument. Useful in for expressions, e.g. for (arg = first_aggr_init_expr_arg (exp, &iter); arg; arg = next_aggr_init_expr_arg (&iter)) */ -static inline tree +inline tree first_aggr_init_expr_arg (tree exp, aggr_init_expr_arg_iterator *iter) { init_aggr_init_expr_arg_iterator (exp, iter); @@ -3035,7 +3084,7 @@ first_aggr_init_expr_arg (tree exp, aggr_init_expr_arg_iterator *iter) /* Test whether there are more arguments in abstract argument list iterator ITER, without changing its state. */ -static inline bool +inline bool more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) { return (iter->i < iter->n); @@ -3425,7 +3474,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) Keep these checks in ascending order, for speed. */ #define TYPE_OBJ_P(NODE) \ (TREE_CODE (NODE) != REFERENCE_TYPE \ - && TREE_CODE (NODE) != VOID_TYPE \ + && !VOID_TYPE_P (NODE) \ && TREE_CODE (NODE) != FUNCTION_TYPE \ && TREE_CODE (NODE) != METHOD_TYPE) @@ -3448,7 +3497,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) /* Returns true if NODE is a pointer to function. */ #define TYPE_PTRFN_P(NODE) \ - (TREE_CODE (NODE) == POINTER_TYPE \ + (TYPE_PTR_P (NODE) \ && TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE) /* Returns true if NODE is a reference to function. */ @@ -3553,10 +3602,12 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) (DECLTYPE_TYPE_CHECK (NODE))->type_common.string_flag /* These flags indicate that we want different semantics from normal - decltype: lambda capture just drops references, lambda proxies look - through implicit dereference. */ + decltype: lambda capture just drops references, init capture + uses auto semantics, lambda proxies look through implicit dereference. */ #define DECLTYPE_FOR_LAMBDA_CAPTURE(NODE) \ TREE_LANG_FLAG_0 (DECLTYPE_TYPE_CHECK (NODE)) +#define DECLTYPE_FOR_INIT_CAPTURE(NODE) \ + TREE_LANG_FLAG_1 (DECLTYPE_TYPE_CHECK (NODE)) #define DECLTYPE_FOR_LAMBDA_PROXY(NODE) \ TREE_LANG_FLAG_2 (DECLTYPE_TYPE_CHECK (NODE)) @@ -3572,6 +3623,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define DECL_THIS_STATIC(NODE) \ DECL_LANG_FLAG_6 (VAR_FUNCTION_OR_PARM_DECL_CHECK (NODE)) +/* Nonzero for FIELD_DECL node means that this field is a lambda capture + field for an array of runtime bound. */ +#define DECL_VLA_CAPTURE_P(NODE) \ + DECL_LANG_FLAG_1 (FIELD_DECL_CHECK (NODE)) + /* Nonzero for FIELD_DECL node means that this field is a base class of the parent object, as opposed to a member field. */ #define DECL_FIELD_IS_BASE(NODE) \ @@ -3639,13 +3695,15 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) TEMPLATE_PARM_INDEX for the parameter is available as the DECL_INITIAL (for a PARM_DECL) or as the TREE_TYPE (for a TYPE_DECL). */ -#define DECL_TEMPLATE_PARMS(NODE) DECL_NON_COMMON_CHECK (NODE)->decl_non_common.arguments +#define DECL_TEMPLATE_PARMS(NODE) \ + TEMPLATE_DECL_CHECK (NODE)->decl_non_common.arguments #define DECL_INNERMOST_TEMPLATE_PARMS(NODE) \ INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (NODE)) #define DECL_NTPARMS(NODE) \ TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (NODE)) /* For function, method, class-data templates. */ -#define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT_FLD (NODE) +#define DECL_TEMPLATE_RESULT(NODE) \ + DECL_RESULT_FLD (TEMPLATE_DECL_CHECK (NODE)) /* For a function template at namespace scope, DECL_TEMPLATE_INSTANTIATIONS lists all instantiations and specializations of the function so that tsubst_friend_function can reassign them to another template if we find @@ -3674,19 +3732,21 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) <class U> struct S1<T>::S2'. This list is not used for other templates. */ -#define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX (NODE) +#define DECL_TEMPLATE_INSTANTIATIONS(NODE) \ + DECL_VINDEX (TEMPLATE_DECL_CHECK (NODE)) + /* For a class template, this list contains the partial specializations of this template. (Full specializations are not recorded on this list.) The TREE_PURPOSE holds the arguments used in the partial specialization (e.g., for `template <class T> struct - S<T*, int>' this will be `T*'.) The arguments will also include - any outer template arguments. The TREE_VALUE holds the innermost - template parameters for the specialization (e.g., `T' in the - example above.) The TREE_TYPE is the _TYPE node for the partial - specialization. + S<T*, int>' this will be `T*, int'.) The arguments will also include + any outer template arguments. The TREE_VALUE holds the TEMPLATE_DECL + for the partial specialization. The TREE_TYPE is the _TYPE node for + the partial specialization. This list is not used for other templates. */ -#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE (NODE) +#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) \ + DECL_SIZE (TEMPLATE_DECL_CHECK (NODE)) /* Nonzero for a DECL which is actually a template parameter. Keep these checks in ascending tree code order. */ @@ -3705,14 +3765,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define DECL_TEMPLATE_TEMPLATE_PARM_P(NODE) \ (TREE_CODE (NODE) == TEMPLATE_DECL && DECL_TEMPLATE_PARM_P (NODE)) -/* Nonzero if NODE is a TEMPLATE_DECL representing an - UNBOUND_CLASS_TEMPLATE tree node. */ -#define DECL_UNBOUND_CLASS_TEMPLATE_P(NODE) \ - (TREE_CODE (NODE) == TEMPLATE_DECL && !DECL_TEMPLATE_RESULT (NODE)) - -#define DECL_FUNCTION_TEMPLATE_P(NODE) \ - (TREE_CODE (NODE) == TEMPLATE_DECL \ - && !DECL_UNBOUND_CLASS_TEMPLATE_P (NODE) \ +/* Nonzero for a DECL that represents a function template. */ +#define DECL_FUNCTION_TEMPLATE_P(NODE) \ + (TREE_CODE (NODE) == TEMPLATE_DECL \ + && DECL_TEMPLATE_RESULT (NODE) != NULL_TREE \ && TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL) /* Nonzero for a DECL that represents a class template or alias @@ -3756,9 +3812,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define SET_DECL_SELF_REFERENCE_P(NODE) \ (DECL_LANG_FLAG_4 (NODE) = 1) -/* A `primary' template is one that has its own template header. A - member function of a class template is a template, but not primary. - A member template is primary. Friend templates are primary, too. */ +/* A `primary' template is one that has its own template header and is not + a partial specialization. A member function of a class template is a + template, but not primary. A member template is primary. Friend + templates are primary, too. */ /* Returns the primary template corresponding to these parameters. */ #define DECL_PRIMARY_TEMPLATE(NODE) \ @@ -4190,6 +4247,9 @@ enum tsubst_flags { conversion might be permissible, not actually performing the conversion. */ + tf_decltype = 1 << 7, /* We are the operand of decltype. + Used to implement the special rules + for calls in decltype (5.2.2/11). */ tf_partial = 1 << 8, /* Doing initial explicit argument substitution in fn_type_unification. */ /* Convenient substitution flags combinations. */ @@ -4259,6 +4319,7 @@ extern int comparing_specializations; extern int cp_unevaluated_operand; extern tree cp_convert_range_for (tree, tree, tree); +extern bool parsing_nsdmi (void); /* in pt.c */ @@ -4301,8 +4362,6 @@ extern GTY(()) vec<tree, va_gc> *local_classes; #define VFIELD_NAME "_vptr." #define VFIELD_NAME_FORMAT "_vptr.%s" -#define ANON_AGGRNAME_FORMAT "._%d" - #else /* NO_DOT_IN_LABEL */ #ifndef NO_DOLLAR_IN_LABEL @@ -4313,7 +4372,6 @@ extern GTY(()) vec<tree, va_gc> *local_classes; #define VFIELD_BASE "$vf" #define VFIELD_NAME "_vptr$" #define VFIELD_NAME_FORMAT "_vptr$%s" -#define ANON_AGGRNAME_FORMAT "$_%d" #else /* NO_DOLLAR_IN_LABEL */ @@ -4332,12 +4390,6 @@ extern GTY(()) vec<tree, va_gc> *local_classes; sizeof (VFIELD_NAME) - 1)) #define VFIELD_NAME_FORMAT "__vptr_%s" -#define ANON_AGGRNAME_PREFIX "__anon_" -#define ANON_AGGRNAME_P(ID_NODE) \ - (!strncmp (IDENTIFIER_POINTER (ID_NODE), ANON_AGGRNAME_PREFIX, \ - sizeof (ANON_AGGRNAME_PREFIX) - 1)) -#define ANON_AGGRNAME_FORMAT "__anon_%d" - #endif /* NO_DOLLAR_IN_LABEL */ #endif /* NO_DOT_IN_LABEL */ @@ -4374,11 +4426,6 @@ extern GTY(()) vec<tree, va_gc> *local_classes; #define VFIELD_NAME_P(ID_NODE) \ (!strncmp (IDENTIFIER_POINTER (ID_NODE), VFIELD_NAME, sizeof(VFIELD_NAME)-1)) -/* For anonymous aggregate types, we need some sort of name to - hold on to. In practice, this should not appear, but it should - not be harmful if it does. */ -#define ANON_AGGRNAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[0] == JOINER \ - && IDENTIFIER_POINTER (ID_NODE)[1] == '_') #endif /* !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL) */ @@ -4576,6 +4623,10 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG }; #define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \ (TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE))) +/* True iff this TEMPLATE_TYPE_PARM represents decltype(auto). */ +#define AUTO_IS_DECLTYPE(NODE) \ + (TYPE_LANG_FLAG_5 (TEMPLATE_TYPE_PARM_CHECK (NODE))) + /* These constants can used as bit flags in the process of tree formatting. TFF_PLAIN_IDENTIFIER: unqualified part of a name. @@ -4595,7 +4646,9 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG }; TFF_UNQUALIFIED_NAME: do not print the qualifying scope of the top-level entity. TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS: do not omit template arguments - identical to their defaults. */ + identical to their defaults. + TFF_NO_TEMPLATE_BINDINGS: do not print information about the template + arguments for a function template specialization. */ #define TFF_PLAIN_IDENTIFIER (0) #define TFF_SCOPE (1) @@ -4611,6 +4664,7 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG }; #define TFF_NO_FUNCTION_ARGUMENTS (1 << 10) #define TFF_UNQUALIFIED_NAME (1 << 11) #define TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS (1 << 12) +#define TFF_NO_TEMPLATE_BINDINGS (1 << 13) /* Returns the TEMPLATE_DECL associated to a TEMPLATE_TEMPLATE_PARM node. */ @@ -4662,6 +4716,23 @@ enum virt_specifier typedef int cp_virt_specifiers; +/* Wherever there is a function-cv-qual, there could also be a ref-qualifier: + + [dcl.fct] + The return type, the parameter-type-list, the ref-qualifier, and + the cv-qualifier-seq, but not the default arguments or the exception + specification, are part of the function type. + + REF_QUAL_NONE Ordinary member function with no ref-qualifier + REF_QUAL_LVALUE Member function with the &-ref-qualifier + REF_QUAL_RVALUE Member function with the &&-ref-qualifier */ + +enum cp_ref_qualifier { + REF_QUAL_NONE = 0, + REF_QUAL_LVALUE = 1, + REF_QUAL_RVALUE = 2 +}; + /* A storage class. */ typedef enum cp_storage_class { @@ -4823,6 +4894,8 @@ struct cp_declarator { cp_cv_quals qualifiers; /* The virt-specifiers for the function. */ cp_virt_specifiers virt_specifiers; + /* The ref-qualifier for the function. */ + cp_ref_qualifier ref_qualifier; /* The exception-specification for the function. */ tree exception_specification; /* The late-specified return type, if any. */ @@ -4875,7 +4948,7 @@ bool decl_spec_seq_has_spec_p (const cp_decl_specifier_seq *, cp_decl_spec); /* Return the type of the `this' parameter of FNTYPE. */ -static inline tree +inline tree type_of_this_parm (const_tree fntype) { function_args_iterator iter; @@ -4886,7 +4959,7 @@ type_of_this_parm (const_tree fntype) /* Return the class of the `this' parameter of FNTYPE. */ -static inline tree +inline tree class_of_this_parm (const_tree fntype) { return TREE_TYPE (type_of_this_parm (fntype)); @@ -4902,7 +4975,7 @@ extern bool pragma_java_exceptions; /* in call.c */ extern bool check_dtor_name (tree, tree); -extern tree build_conditional_expr (tree, tree, tree, +extern tree build_conditional_expr (location_t, tree, tree, tree, tsubst_flags_t); extern tree build_addr_func (tree, tsubst_flags_t); extern void set_flags_from_callee (tree); @@ -5023,6 +5096,7 @@ extern tree in_class_defaulted_default_constructor (tree); extern bool user_provided_p (tree); extern bool type_has_user_provided_constructor (tree); extern bool type_has_user_provided_default_constructor (tree); +extern bool vbase_has_user_provided_move_assign (tree); extern tree default_init_uninitialized_part (tree); extern bool trivial_default_constructor_is_constexpr (tree); extern bool type_has_constexpr_default_constructor (tree); @@ -5044,6 +5118,7 @@ extern void deduce_noexcept_on_destructor (tree); extern void insert_late_enum_def_into_classtype_sorted_fields (tree, tree); extern bool uniquely_derived_from_p (tree, tree); extern bool publicly_uniquely_derived_p (tree, tree); +extern tree common_enclosing_class (tree, tree); /* in cvt.c */ extern tree convert_to_reference (tree, tree, int, int, tree, @@ -5072,6 +5147,8 @@ extern tree make_anon_name (void); extern tree pushdecl_top_level_maybe_friend (tree, bool); extern tree pushdecl_top_level_and_finish (tree, tree); extern tree check_for_out_of_scope_variable (tree); +extern void dump (cp_binding_level &ref); +extern void dump (cp_binding_level *ptr); extern void print_other_binding_stack (cp_binding_level *); extern tree maybe_push_decl (tree); extern tree current_decl_namespace (void); @@ -5163,6 +5240,9 @@ extern void initialize_artificial_var (tree, vec<constructor_elt, va_gc> *); extern tree check_var_type (tree, tree); extern tree reshape_init (tree, tree, tsubst_flags_t); extern tree next_initializable_field (tree); +extern tree fndecl_declared_return_type (tree); +extern bool undeduced_auto_decl (tree); +extern void require_deduced_type (tree); extern bool defer_mark_used_calls; extern GTY(()) vec<tree, va_gc> *deferred_mark_used_calls; @@ -5171,14 +5251,15 @@ extern tree cxx_maybe_build_cleanup (tree, tsubst_flags_t); /* in decl2.c */ extern bool check_java_method (tree); -extern tree build_memfn_type (tree, tree, cp_cv_quals); +extern tree build_memfn_type (tree, tree, cp_cv_quals, cp_ref_qualifier); +extern tree build_pointer_ptrmemfn_type (tree); extern tree change_return_type (tree, tree); extern void maybe_retrofit_in_chrg (tree); extern void maybe_make_one_only (tree); extern bool vague_linkage_p (tree); extern void grokclassfn (tree, tree, enum overload_flags); -extern tree grok_array_decl (location_t, tree, tree); +extern tree grok_array_decl (location_t, tree, tree, bool); extern tree delete_sanity (tree, tree, bool, int, tsubst_flags_t); extern tree check_classfn (tree, tree, tree); extern void check_member_template (tree); @@ -5203,6 +5284,7 @@ extern bool decl_constant_var_p (tree); extern bool decl_maybe_constant_var_p (tree); extern void check_default_args (tree); extern bool mark_used (tree); +extern bool mark_used (tree, tsubst_flags_t); extern void finish_static_data_member_decl (tree, tree, bool, tree, int); extern tree cp_build_parm_decl (tree, tree); extern tree get_guard (tree); @@ -5282,7 +5364,10 @@ extern tree get_type_value (tree); extern tree build_zero_init (tree, tree, bool); extern tree build_value_init (tree, tsubst_flags_t); extern tree build_value_init_noctor (tree, tsubst_flags_t); -extern tree build_offset_ref (tree, tree, bool); +extern tree build_offset_ref (tree, tree, bool, + tsubst_flags_t); +extern tree throw_bad_array_new_length (void); +extern tree throw_bad_array_length (void); extern tree build_new (vec<tree, va_gc> **, tree, tree, vec<tree, va_gc> **, int, tsubst_flags_t); @@ -5362,6 +5447,7 @@ extern tree check_explicit_specialization (tree, tree, int, int); extern int num_template_headers_for_class (tree); extern void check_template_variable (tree); extern tree make_auto (void); +extern tree make_decltype_auto (void); extern tree do_auto_deduction (tree, tree, tree); extern tree type_uses_auto (tree); extern void append_type_to_template_for_access_check (tree, tree, tree, @@ -5389,7 +5475,7 @@ extern tree instantiate_template (tree, tree, tsubst_flags_t); extern tree fn_type_unification (tree, tree, tree, const tree *, unsigned int, tree, unification_kind_t, int, - bool); + bool, bool); extern void mark_decl_instantiated (tree, int); extern int more_specialized_fn (tree, tree, int); extern void do_decl_instantiation (tree, tree); @@ -5629,6 +5715,7 @@ extern tree finish_asm_stmt (int, tree, tree, tree, tree, extern tree finish_label_stmt (tree); extern void finish_label_decl (tree); extern tree finish_parenthesized_expr (tree); +extern tree force_paren_expr (tree); extern tree finish_non_static_data_member (tree, tree, tree); extern tree begin_stmt_expr (void); extern tree finish_stmt_expr_expr (tree, tree); @@ -5642,7 +5729,8 @@ extern tree finish_call_expr (tree, vec<tree, va_gc> **, bool, extern tree finish_increment_expr (tree, enum tree_code); extern tree finish_this_expr (void); extern tree finish_pseudo_destructor_expr (tree, tree, tree); -extern tree finish_unary_op_expr (location_t, enum tree_code, tree); +extern tree finish_unary_op_expr (location_t, enum tree_code, tree, + tsubst_flags_t); extern tree finish_compound_literal (tree, tree, tsubst_flags_t); extern tree finish_fname (tree); extern void finish_translation_unit (void); @@ -5676,7 +5764,7 @@ extern void add_typedef_to_current_template_for_access_check (tree, tree, location_t); extern void check_accessibility_of_qualified_id (tree, tree, tree); extern tree finish_qualified_id_expr (tree, tree, bool, bool, - bool, bool); + bool, bool, tsubst_flags_t); extern void simplify_aggr_init_expr (tree *); extern void finalize_nrv (tree *, tree, tree); extern void note_decl_for_pch (tree); @@ -5708,7 +5796,7 @@ extern tree finish_trait_expr (enum cp_trait_kind, tree, tree); extern tree build_lambda_expr (void); extern tree build_lambda_object (tree); extern tree begin_lambda_type (tree); -extern tree lambda_capture_field_type (tree); +extern tree lambda_capture_field_type (tree, bool); extern tree lambda_return_type (tree); extern tree lambda_proxy_type (tree); extern tree lambda_function (tree); @@ -5771,12 +5859,14 @@ extern tree get_target_expr (tree); extern tree get_target_expr_sfinae (tree, tsubst_flags_t); extern tree build_cplus_array_type (tree, tree); extern tree build_array_of_n_type (tree, int); +extern bool array_of_runtime_bound_p (tree); extern tree build_array_copy (tree); extern tree build_vec_init_expr (tree, tree, tsubst_flags_t); extern void diagnose_non_constexpr_vec_init (tree); extern tree hash_tree_cons (tree, tree, tree); extern tree hash_tree_chain (tree, tree); extern tree build_qualified_name (tree, tree, tree, bool); +extern tree build_ref_qualified_type (tree, cp_ref_qualifier); extern int is_overloaded_fn (tree); extern tree dependent_name (tree); extern tree get_fns (tree); @@ -5934,7 +6024,8 @@ extern tree build_ptrmemfunc (tree, tree, int, bool, tsubst_flags_t); extern int cp_type_quals (const_tree); extern int type_memfn_quals (const_tree); -extern tree apply_memfn_quals (tree, cp_cv_quals); +extern cp_ref_qualifier type_memfn_rqual (const_tree); +extern tree apply_memfn_quals (tree, cp_cv_quals, cp_ref_qualifier); extern bool cp_has_mutable_p (const_tree); extern bool at_least_as_qualified_p (const_tree, const_tree); extern void cp_apply_type_quals_to_decl (int, tree); @@ -5952,13 +6043,14 @@ extern tree cp_build_binary_op (location_t, enum tree_code, tree, tree, tsubst_flags_t); #define cxx_sizeof(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, true) +extern tree build_simple_component_ref (tree, tree); extern tree build_ptrmemfunc_access_expr (tree, tree); extern tree build_address (tree); extern tree build_typed_address (tree, tree); extern tree build_nop (tree, tree); extern tree non_reference (tree); extern tree lookup_anon_field (tree, tree); -extern bool invalid_nonstatic_memfn_p (const_tree, tsubst_flags_t); +extern bool invalid_nonstatic_memfn_p (tree, tsubst_flags_t); extern tree convert_member_func_to_ptr (tree, tree, tsubst_flags_t); extern tree convert_ptrmem (tree, tree, bool, bool, tsubst_flags_t); @@ -5982,7 +6074,9 @@ extern tree binfo_or_else (tree, tree); extern void cxx_readonly_error (tree, enum lvalue_use); extern void complete_type_check_abstract (tree); extern int abstract_virtuals_error (tree, tree); +extern int abstract_virtuals_error (abstract_class_use, tree); extern int abstract_virtuals_error_sfinae (tree, tree, tsubst_flags_t); +extern int abstract_virtuals_error_sfinae (abstract_class_use, tree, tsubst_flags_t); extern tree store_init_value (tree, tree, vec<tree, va_gc>**, int); extern void check_narrowing (tree, tree); @@ -6044,6 +6138,10 @@ extern bool cxx_omp_privatize_by_reference (const_tree); extern void suggest_alternatives_for (location_t, tree); extern tree strip_using_decl (tree); +/* In cp/cp-array-notations.c */ +extern tree expand_array_notation_exprs (tree); +bool cilkplus_an_triplet_types_ok_p (location_t, tree, tree, tree, + tree); /* -- end of C++ */ #endif /* ! GCC_CP_TREE_H */ diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 348e6082ceb..d9e905e3504 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -40,7 +40,7 @@ static tree cp_convert_to_pointer (tree, tree, tsubst_flags_t); static tree convert_to_pointer_force (tree, tree, tsubst_flags_t); static tree build_type_conversion (tree, tree); static tree build_up_reference (tree, tree, int, tree, tsubst_flags_t); -static void warn_ref_binding (location_t, tree, tree, tree); +static void diagnose_ref_binding (location_t, tree, tree, tree); /* Change of width--truncation and extension of integers or reals-- is represented with NOP_EXPR. Proper functioning of many things @@ -105,14 +105,14 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain) } /* Handle anachronistic conversions from (::*)() to cv void* or (*)(). */ - if (TREE_CODE (type) == POINTER_TYPE + if (TYPE_PTR_P (type) && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE || VOID_TYPE_P (TREE_TYPE (type)))) { if (TYPE_PTRMEMFUNC_P (intype) || TREE_CODE (intype) == METHOD_TYPE) return convert_member_func_to_ptr (type, expr, complain); - if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) + if (TYPE_PTR_P (TREE_TYPE (expr))) return build_nop (type, expr); intype = TREE_TYPE (expr); } @@ -127,7 +127,7 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain) intype = TYPE_MAIN_VARIANT (intype); if (TYPE_MAIN_VARIANT (type) != intype - && TREE_CODE (type) == POINTER_TYPE + && TYPE_PTR_P (type) && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE && MAYBE_CLASS_TYPE_P (TREE_TYPE (type)) && MAYBE_CLASS_TYPE_P (TREE_TYPE (intype)) @@ -371,7 +371,7 @@ build_up_reference (tree type, tree arg, int flags, tree decl, non-volatile const type. */ static void -warn_ref_binding (location_t loc, tree reftype, tree intype, tree decl) +diagnose_ref_binding (location_t loc, tree reftype, tree intype, tree decl) { tree ttl = TREE_TYPE (reftype); @@ -456,9 +456,9 @@ convert_to_reference (tree reftype, tree expr, int convtype, tree ttl = TREE_TYPE (reftype); tree ttr = lvalue_type (expr); - if ((complain & tf_warning) + if ((complain & tf_error) && ! real_lvalue_p (expr)) - warn_ref_binding (loc, reftype, intype, decl); + diagnose_ref_binding (loc, reftype, intype, decl); if (! (convtype & CONV_CONST) && !at_least_as_qualified_p (ttl, ttr)) @@ -483,7 +483,7 @@ convert_to_reference (tree reftype, tree expr, int convtype, /* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they meant. */ if ((complain & tf_warning) - && TREE_CODE (intype) == POINTER_TYPE + && TYPE_PTR_P (intype) && (comptypes (TREE_TYPE (intype), type, COMPARE_BASE | COMPARE_DERIVED))) warning_at (loc, 0, "casting %qT to %qT does not dereference pointer", @@ -502,8 +502,8 @@ convert_to_reference (tree reftype, tree expr, int convtype, ICR_CONVERTING, 0, 0, complain); if (rval == NULL_TREE || rval == error_mark_node) return rval; - if (complain & tf_warning) - warn_ref_binding (loc, reftype, intype, decl); + if (complain & tf_error) + diagnose_ref_binding (loc, reftype, intype, decl); rval = build_up_reference (reftype, rval, flags, decl, complain); } @@ -624,10 +624,20 @@ cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain) result = cp_convert (type, expr, complain); if ((complain & tf_warning) - && c_inhibit_evaluation_warnings == 0 - && !TREE_OVERFLOW_P (expr) - && result != error_mark_node) - warnings_for_convert_and_check (type, expr, result); + && c_inhibit_evaluation_warnings == 0) + { + tree folded = maybe_constant_value (expr); + tree stripped = folded; + tree folded_result = cp_convert (type, folded, complain); + + /* maybe_constant_value wraps an INTEGER_CST with TREE_OVERFLOW in a + NOP_EXPR so that it isn't TREE_CONSTANT anymore. */ + STRIP_NOPS (stripped); + + if (!TREE_OVERFLOW_P (stripped) + && folded_result != error_mark_node) + warnings_for_convert_and_check (type, folded, folded_result); + } return result; } @@ -723,7 +733,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags, if (((INTEGRAL_OR_ENUMERATION_TYPE_P (intype) || TREE_CODE (intype) == REAL_TYPE) && ! (convtype & CONV_STATIC)) - || TREE_CODE (intype) == POINTER_TYPE) + || TYPE_PTR_P (intype)) { if (complain & tf_error) permerror (loc, "conversion from %q#T to %q#T", intype, type); @@ -758,7 +768,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags, } if (code == BOOLEAN_TYPE) { - if (TREE_CODE (intype) == VOID_TYPE) + if (VOID_TYPE_P (intype)) { if (complain & tf_error) error_at (loc, @@ -916,7 +926,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain) exprv = TREE_OPERAND (exprv, 1); if (DECL_P (exprv) || handled_component_p (exprv) - || TREE_CODE (exprv) == INDIRECT_REF) + || INDIRECT_REF_P (exprv)) /* Expr is not being 'used' here, otherwise we whould have called mark_{rl}value_use use here, which would have in turn called mark_exp_read. Rather, we call mark_exp_read directly @@ -1457,8 +1467,7 @@ convert_force (tree type, tree expr, int convtype, tsubst_flags_t complain) complain)); /* From typeck.c convert_for_assignment */ - if (((TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (e) == ADDR_EXPR - && TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE + if (((TYPE_PTR_P (TREE_TYPE (e)) && TREE_CODE (e) == ADDR_EXPR && TREE_CODE (TREE_TYPE (TREE_TYPE (e))) == METHOD_TYPE) || integer_zerop (e) || TYPE_PTRMEMFUNC_P (TREE_TYPE (e))) @@ -1631,17 +1640,24 @@ build_expr_type_conversion (int desires, tree expr, bool complain) { if (winner) { - if (complain) + tree winner_type + = non_reference (TREE_TYPE (TREE_TYPE (winner))); + + if (!same_type_ignoring_top_level_qualifiers_p (winner_type, + candidate)) { - error ("ambiguous default type conversion from %qT", - basetype); - error (" candidate conversions include %qD and %qD", - winner, cand); + if (complain) + { + error ("ambiguous default type conversion from %qT", + basetype); + error (" candidate conversions include %qD and %qD", + winner, cand); + } + return error_mark_node; } - return error_mark_node; } - else - winner = cand; + + winner = cand; } } diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c index 45ad20cd9a9..ef8df706758 100644 --- a/gcc/cp/cxx-pretty-print.c +++ b/gcc/cp/cxx-pretty-print.c @@ -260,7 +260,7 @@ pp_cxx_nested_name_specifier (cxx_pretty_printer *pp, tree t) { if (!SCOPE_FILE_SCOPE_P (t) && t != pp->enclosing_scope) { - tree scope = TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT (t); + tree scope = get_containing_scope (t); pp_cxx_nested_name_specifier (pp, scope); pp_cxx_template_keyword_if_needed (pp, scope, t); pp_cxx_unqualified_id (pp, t); @@ -308,7 +308,7 @@ pp_cxx_qualified_id (cxx_pretty_printer *pp, tree t) default: { - tree scope = TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT (t); + tree scope = get_containing_scope (t); if (scope != pp->enclosing_scope) { pp_cxx_nested_name_specifier (pp, scope); @@ -530,7 +530,7 @@ pp_cxx_postfix_expression (cxx_pretty_printer *pp, tree t) if (TREE_CODE (object) == ADDR_EXPR) object = TREE_OPERAND (object, 0); - if (TREE_CODE (TREE_TYPE (object)) != POINTER_TYPE) + if (!TYPE_PTR_P (TREE_TYPE (object))) { pp_cxx_postfix_expression (pp, object); pp_cxx_dot (pp); @@ -1167,6 +1167,12 @@ pp_cxx_expression (cxx_pretty_printer *pp, tree t) pp_cxx_ws_string (pp, "<lambda>"); break; + case PAREN_EXPR: + pp_cxx_left_paren (pp); + pp_cxx_expression (pp, TREE_OPERAND (t, 0)); + pp_cxx_right_paren (pp); + break; + default: pp_c_expression (pp_c_base (pp), t); break; @@ -1358,7 +1364,7 @@ pp_cxx_ptr_operator (cxx_pretty_printer *pp, tree t) pp_cxx_ptr_operator (pp, TREE_TYPE (t)); pp_c_attributes_display (pp_c_base (pp), TYPE_ATTRIBUTES (TREE_TYPE (t))); - if (TREE_CODE (t) == POINTER_TYPE) + if (TYPE_PTR_P (t)) { pp_star (pp); pp_cxx_cv_qualifier_seq (pp, t); diff --git a/gcc/cp/cxx-pretty-print.h b/gcc/cp/cxx-pretty-print.h index f1ab0e6ec78..0f7dc4a8174 100644 --- a/gcc/cp/cxx-pretty-print.h +++ b/gcc/cp/cxx-pretty-print.h @@ -42,6 +42,8 @@ typedef struct #define pp_cxx_cv_qualifier_seq(PP, T) \ pp_c_type_qualifier_list (pp_c_base (PP), T) +#define pp_cxx_cv_qualifiers(PP, CV) \ + pp_c_cv_qualifiers (pp_c_base (PP), CV, false) #define pp_cxx_whitespace(PP) pp_c_whitespace (pp_c_base (PP)) #define pp_cxx_left_paren(PP) pp_c_left_paren (pp_c_base (PP)) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 150e8662a5e..f562546db0c 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -622,17 +622,20 @@ poplevel (int keep, int reverse, int functionbody) push_local_binding where the list of decls returned by getdecls is built. */ decl = TREE_CODE (d) == TREE_LIST ? TREE_VALUE (d) : d; - if (TREE_CODE (decl) == VAR_DECL + // See through references for improved -Wunused-variable (PR 38958). + tree type = non_reference (TREE_TYPE (decl)); + if (VAR_P (decl) && (! TREE_USED (decl) || !DECL_READ_P (decl)) && ! DECL_IN_SYSTEM_HEADER (decl) && DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl) - && TREE_TYPE (decl) != error_mark_node - && (!CLASS_TYPE_P (TREE_TYPE (decl)) - || !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))) + && type != error_mark_node + && (!CLASS_TYPE_P (type) + || !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))) { if (! TREE_USED (decl)) warning (OPT_Wunused_variable, "unused variable %q+D", decl); else if (DECL_CONTEXT (decl) == current_function_decl + // For -Wunused-but-set-variable leave references alone. && TREE_CODE (TREE_TYPE (decl)) != REFERENCE_TYPE && errorcount == unused_but_set_errorcount) { @@ -646,10 +649,10 @@ poplevel (int keep, int reverse, int functionbody) /* Remove declarations for all the DECLs in this level. */ for (link = decls; link; link = TREE_CHAIN (link)) { - if (leaving_for_scope && TREE_CODE (link) == VAR_DECL + if (leaving_for_scope && VAR_P (link) /* It's hard to make this ARM compatibility hack play nicely with lambdas, and it really isn't necessary in C++11 mode. */ - && cxx_dialect < cxx0x + && cxx_dialect < cxx11 && DECL_NAME (link)) { tree name = DECL_NAME (link); @@ -992,10 +995,7 @@ decls_match (tree newdecl, tree olddecl) /* A declaration with deduced return type should use its pre-deduction type for declaration matching. */ - if (FNDECL_USED_AUTO (olddecl)) - r2 = DECL_STRUCT_FUNCTION (olddecl)->language->x_auto_return_pattern; - else - r2 = TREE_TYPE (f2); + r2 = fndecl_declared_return_type (olddecl); if (same_type_p (TREE_TYPE (f1), r2)) { @@ -1027,6 +1027,7 @@ decls_match (tree newdecl, tree olddecl) else types_match = compparms (p1, p2) + && type_memfn_rqual (f1) == type_memfn_rqual (f2) && (TYPE_ATTRIBUTES (TREE_TYPE (newdecl)) == NULL_TREE || comp_type_attributes (TREE_TYPE (newdecl), TREE_TYPE (olddecl)) != 0); @@ -1084,7 +1085,7 @@ decls_match (tree newdecl, tree olddecl) { /* Need to check scope for variable declaration (VAR_DECL). For typedef (TYPE_DECL), scope is ignored. */ - if (TREE_CODE (newdecl) == VAR_DECL + if (VAR_P (newdecl) && CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl) /* [dcl.link] Two declarations for an object with C language linkage @@ -1196,12 +1197,21 @@ validate_constexpr_redeclaration (tree old_decl, tree new_decl) if (DECL_DECLARED_CONSTEXPR_P (old_decl) == DECL_DECLARED_CONSTEXPR_P (new_decl)) return true; - if (TREE_CODE (old_decl) == FUNCTION_DECL && DECL_BUILT_IN (old_decl)) + if (TREE_CODE (old_decl) == FUNCTION_DECL) { - /* Hide a built-in declaration. */ - DECL_DECLARED_CONSTEXPR_P (old_decl) - = DECL_DECLARED_CONSTEXPR_P (new_decl); - return true; + if (DECL_BUILT_IN (old_decl)) + { + /* Hide a built-in declaration. */ + DECL_DECLARED_CONSTEXPR_P (old_decl) + = DECL_DECLARED_CONSTEXPR_P (new_decl); + return true; + } + /* 7.1.5 [dcl.constexpr] + Note: An explicit specialization can differ from the template + declaration with respect to the constexpr specifier. */ + if (! DECL_TEMPLATE_SPECIALIZATION (old_decl) + && DECL_TEMPLATE_SPECIALIZATION (new_decl)) + return true; } error ("redeclaration %qD differs in %<constexpr%>", new_decl); error ("from previous declaration %q+D", old_decl); @@ -1348,7 +1358,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) { tree t = TREE_VALUE (t1); - if (TREE_CODE (t) == POINTER_TYPE + if (TYPE_PTR_P (t) && TYPE_NAME (TREE_TYPE (t)) && DECL_NAME (TYPE_NAME (TREE_TYPE (t))) == get_identifier ("FILE") @@ -1529,11 +1539,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) TYPE_ARG_TYPES (TREE_TYPE (olddecl)))) { error ("new declaration %q#D", newdecl); - if (FNDECL_USED_AUTO (olddecl)) - error_at (DECL_SOURCE_LOCATION (olddecl), "ambiguates old " - "declaration with deduced return type"); - else - error ("ambiguates old declaration %q+#D", olddecl); + error ("ambiguates old declaration %q+#D", olddecl); return error_mark_node; } else @@ -1620,8 +1626,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) warning_at (DECL_SOURCE_LOCATION (olddecl), 0, "follows non-prototype definition here"); } - else if ((TREE_CODE (olddecl) == FUNCTION_DECL - || TREE_CODE (olddecl) == VAR_DECL) + else if (VAR_OR_FUNCTION_DECL_P (olddecl) && DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl)) { /* [dcl.link] @@ -1756,12 +1761,16 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) warning (OPT_Wredundant_decls, "previous declaration of %q+D", olddecl); } - if (DECL_DELETED_FN (newdecl)) + if (!(DECL_TEMPLATE_INSTANTIATION (olddecl) + && DECL_TEMPLATE_SPECIALIZATION (newdecl))) { - error ("deleted definition of %qD", newdecl); - error ("after previous declaration %q+D", olddecl); + if (DECL_DELETED_FN (newdecl)) + { + error ("deleted definition of %qD", newdecl); + error ("after previous declaration %q+D", olddecl); + } + DECL_DELETED_FN (newdecl) |= DECL_DELETED_FN (olddecl); } - DECL_DELETED_FN (newdecl) |= DECL_DELETED_FN (olddecl); } /* Deal with C++: must preserve virtual function table size. */ @@ -1867,7 +1876,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) && newtype == DECL_ORIGINAL_TYPE (newdecl)) newtype = oldtype; - if (TREE_CODE (newdecl) == VAR_DECL) + if (VAR_P (newdecl)) { DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl); DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl); @@ -1904,7 +1913,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) && !(processing_template_decl && uses_template_parms (newdecl))) layout_type (TREE_TYPE (newdecl)); - if ((TREE_CODE (newdecl) == VAR_DECL + if ((VAR_P (newdecl) || TREE_CODE (newdecl) == PARM_DECL || TREE_CODE (newdecl) == RESULT_DECL || TREE_CODE (newdecl) == FIELD_DECL @@ -1974,7 +1983,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) /* Keep the old RTL. */ COPY_DECL_RTL (olddecl, newdecl); } - else if (TREE_CODE (newdecl) == VAR_DECL + else if (VAR_P (newdecl) && (DECL_SIZE (olddecl) || !DECL_SIZE (newdecl))) { /* Keep the old RTL. We cannot keep the old RTL if the old @@ -2064,8 +2073,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl); } /* Only functions have these fields. */ - if (TREE_CODE (newdecl) == FUNCTION_DECL - || DECL_FUNCTION_TEMPLATE_P (newdecl)) + if (DECL_DECLARES_FUNCTION_P (newdecl)) { DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl); olddecl_friend = DECL_FRIEND_P (olddecl); @@ -2081,7 +2089,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) SET_DECL_THUNKS (newdecl, DECL_THUNKS (olddecl)); } /* Only variables have this field. */ - else if (TREE_CODE (newdecl) == VAR_DECL + else if (VAR_P (newdecl) && VAR_HAD_UNKNOWN_BOUND (olddecl)) SET_VAR_HAD_UNKNOWN_BOUND (newdecl); } @@ -2257,7 +2265,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) } /* Init priority used to be merged from newdecl to olddecl by the memcpy, so keep this behavior. */ - if (TREE_CODE (newdecl) == VAR_DECL && DECL_HAS_INIT_PRIORITY_P (newdecl)) + if (VAR_P (newdecl) && DECL_HAS_INIT_PRIORITY_P (newdecl)) { SET_DECL_INIT_PRIORITY (olddecl, DECL_INIT_PRIORITY (newdecl)); DECL_HAS_INIT_PRIORITY_P (olddecl) = 1; @@ -2286,7 +2294,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) TREE_USED (newdecl) = 1; else if (TREE_USED (newdecl)) TREE_USED (olddecl) = 1; - if (TREE_CODE (newdecl) == VAR_DECL) + if (VAR_P (newdecl)) { if (DECL_READ_P (olddecl)) DECL_READ_P (newdecl) = 1; @@ -2397,7 +2405,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) flags and attributes. */ if (DECL_RTL_SET_P (olddecl) && (TREE_CODE (olddecl) == FUNCTION_DECL - || (TREE_CODE (olddecl) == VAR_DECL + || (VAR_P (olddecl) && TREE_STATIC (olddecl)))) make_decl_rtl (olddecl); @@ -2540,7 +2548,7 @@ redeclaration_error_message (tree newdecl, tree olddecl) return NULL; } - else if (TREE_CODE (newdecl) == VAR_DECL + else if (VAR_P (newdecl) && DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl) && (! DECL_LANG_SPECIFIC (olddecl) || ! CP_DECL_THREADPRIVATE_P (olddecl) @@ -2565,8 +2573,8 @@ redeclaration_error_message (tree newdecl, tree olddecl) union { int i; }; is invalid. */ - if ((TREE_CODE (newdecl) == VAR_DECL && DECL_ANON_UNION_VAR_P (newdecl)) - || (TREE_CODE (olddecl) == VAR_DECL && DECL_ANON_UNION_VAR_P (olddecl))) + if ((VAR_P (newdecl) && DECL_ANON_UNION_VAR_P (newdecl)) + || (VAR_P (olddecl) && DECL_ANON_UNION_VAR_P (olddecl))) return G_("redeclaration of %q#D"); /* If at least one declaration is a reference, there is no conflict. For example: @@ -2718,7 +2726,7 @@ decl_jump_unsafe (tree decl) preceding types and is declared without an initializer (8.5). */ tree type = TREE_TYPE (decl); - if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl) + if (!VAR_P (decl) || TREE_STATIC (decl) || type == error_mark_node) return 0; @@ -3082,7 +3090,7 @@ case_conversion (tree type, tree value) if (value == NULL_TREE) return value; - if (cxx_dialect >= cxx0x + if (cxx_dialect >= cxx11 && (SCOPED_ENUM_P (type) || !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (value)))) { @@ -3296,7 +3304,7 @@ make_typename_type (tree context, tree name, enum tag_types tag_type, error ("%qD used without template parameters", name); return error_mark_node; } - gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); + gcc_assert (identifier_p (name)); gcc_assert (TYPE_P (context)); if (!MAYBE_CLASS_TYPE_P (context)) @@ -3402,7 +3410,7 @@ make_unbound_class_template (tree context, tree name, tree parm_list, name = TYPE_IDENTIFIER (name); else if (DECL_P (name)) name = DECL_NAME (name); - gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); + gcc_assert (identifier_p (name)); if (!dependent_type_p (context) || currently_open_class (context)) @@ -4184,7 +4192,7 @@ void warn_misplaced_attr_for_class_type (source_location location, tree class_type) { - gcc_assert (TAGGED_TYPE_P (class_type)); + gcc_assert (OVERLOAD_TYPE_P (class_type)); warning_at (location, OPT_Wattributes, "attribute ignored in declaration " @@ -4452,7 +4460,7 @@ start_decl (const cp_declarator *declarator, deprecated_state = DEPRECATED_NORMAL; - if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE + if (decl == NULL_TREE || VOID_TYPE_P (decl) || decl == error_mark_node) return error_mark_node; @@ -4499,7 +4507,7 @@ start_decl (const cp_declarator *declarator, /* If this is a typedef that names the class for linkage purposes (7.1.3p8), apply any attributes directly to the type. */ if (TREE_CODE (decl) == TYPE_DECL - && TAGGED_TYPE_P (TREE_TYPE (decl)) + && OVERLOAD_TYPE_P (TREE_TYPE (decl)) && decl == TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl)))) flags = ATTR_FLAG_TYPE_IN_PLACE; else @@ -4530,10 +4538,10 @@ start_decl (const cp_declarator *declarator, if (TYPE_P (context) && COMPLETE_TYPE_P (complete_type (context))) { - if (TREE_CODE (decl) == VAR_DECL) + if (VAR_P (decl)) { tree field = lookup_field (context, DECL_NAME (decl), 0, false); - if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL) + if (field == NULL_TREE || !VAR_P (field)) error ("%q#D is not a static member of %q#T", decl, context); else { @@ -4610,7 +4618,7 @@ start_decl (const cp_declarator *declarator, if (decl == error_mark_node) return error_mark_node; - if (TREE_CODE (decl) == VAR_DECL + if (VAR_P (decl) && DECL_NAMESPACE_SCOPE_P (decl) && !TREE_PUBLIC (decl) && !was_public && !DECL_THIS_STATIC (decl) && !DECL_ARTIFICIAL (decl)) { @@ -4621,7 +4629,7 @@ start_decl (const cp_declarator *declarator, DECL_THIS_STATIC (decl) = 1; } - if (!processing_template_decl && TREE_CODE (decl) == VAR_DECL) + if (!processing_template_decl && VAR_P (decl)) start_decl_1 (decl, initialized); return decl; @@ -4646,7 +4654,7 @@ start_decl_1 (tree decl, bool initialized) if (error_operand_p (decl)) return; - gcc_assert (TREE_CODE (decl) == VAR_DECL); + gcc_assert (VAR_P (decl)); type = TREE_TYPE (decl); complete_p = COMPLETE_TYPE_P (type); @@ -4760,7 +4768,7 @@ grok_reference_init (tree decl, tree type, tree init, int flags) is valid, i.e., does not have a designated initializer. */ static bool -check_array_designated_initializer (const constructor_elt *ce, +check_array_designated_initializer (constructor_elt *ce, unsigned HOST_WIDE_INT index) { /* Designated initializers for array elements are not supported. */ @@ -4769,9 +4777,21 @@ check_array_designated_initializer (const constructor_elt *ce, /* The parser only allows identifiers as designated initializers. */ if (ce->index == error_mark_node) - error ("name used in a GNU-style designated " - "initializer for an array"); - else if (TREE_CODE (ce->index) == INTEGER_CST) + { + error ("name used in a GNU-style designated " + "initializer for an array"); + return false; + } + else if (identifier_p (ce->index)) + { + error ("name %qD used in a GNU-style designated " + "initializer for an array", ce->index); + return false; + } + + ce->index = cxx_constant_value (ce->index); + + if (TREE_CODE (ce->index) == INTEGER_CST) { /* A C99 designator is OK if it matches the current index. */ if (TREE_INT_CST_LOW (ce->index) == index) @@ -4780,11 +4800,8 @@ check_array_designated_initializer (const constructor_elt *ce, sorry ("non-trivial designated initializers not supported"); } else - { - gcc_assert (TREE_CODE (ce->index) == IDENTIFIER_NODE); - error ("name %qD used in a GNU-style designated " - "initializer for an array", ce->index); - } + gcc_unreachable (); + return false; } @@ -4983,7 +5000,7 @@ check_for_uninitialized_const_var (tree decl) /* ``Unless explicitly declared extern, a const object does not have external linkage and must be initialized. ($8.4; $12.1)'' ARM 7.1.6 */ - if (TREE_CODE (decl) == VAR_DECL + if (VAR_P (decl) && TREE_CODE (type) != REFERENCE_TYPE && CP_TYPE_CONST_P (type) && !DECL_INITIAL (decl)) @@ -5051,7 +5068,7 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d, tsubst_flags_t complain) { tree new_init; - bool sized_array_p = (max_index != NULL_TREE); + bool sized_array_p = (max_index && TREE_CONSTANT (max_index)); unsigned HOST_WIDE_INT max_index_cst = 0; unsigned HOST_WIDE_INT index; @@ -5186,6 +5203,9 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p, /* Handle designated initializers, as an extension. */ if (d->cur->index) { + if (d->cur->index == error_mark_node) + return error_mark_node; + if (TREE_CODE (d->cur->index) == INTEGER_CST) { if (complain & tf_error) @@ -5501,15 +5521,12 @@ check_array_initializer (tree decl, tree type, tree init) error ("elements of array %q#T have incomplete type", type); return true; } - /* It is not valid to initialize a VLA. */ - if (init + /* A compound literal can't have variable size. */ + if (init && !decl && ((COMPLETE_TYPE_P (type) && !TREE_CONSTANT (TYPE_SIZE (type))) || !TREE_CONSTANT (TYPE_SIZE (element_type)))) { - if (decl) - error ("variable-sized object %qD may not be initialized", decl); - else - error ("variable-sized compound literal"); + error ("variable-sized compound literal"); return true; } return false; @@ -5740,7 +5757,7 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups) { static int explained = 0; - if (cxx_dialect < cxx0x) + if (cxx_dialect < cxx11) error ("initializer invalid for static member with constructor"); else error ("non-constant in-class initialization invalid for static " @@ -5770,7 +5787,7 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec) /* The `register' keyword, when used together with an asm-specification, indicates that the variable should be placed in a particular register. */ - if (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl)) + if (VAR_P (decl) && DECL_REGISTER (decl)) { set_user_assembler_name (decl, asmspec); DECL_HARD_REGISTER (decl) = 1; @@ -5785,7 +5802,7 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec) } /* Handle non-variables up front. */ - if (TREE_CODE (decl) != VAR_DECL) + if (!VAR_P (decl)) { rest_of_decl_compilation (decl, toplev, at_eof); return; @@ -5903,7 +5920,7 @@ initialize_local_var (tree decl, tree init) tree cleanup; int already_used; - gcc_assert (TREE_CODE (decl) == VAR_DECL + gcc_assert (VAR_P (decl) || TREE_CODE (decl) == RESULT_DECL); gcc_assert (!TREE_STATIC (decl)); @@ -6111,7 +6128,8 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, tree d_init; if (init == NULL_TREE) { - if (DECL_TEMPLATE_INSTANTIATION (decl) + if (DECL_LANG_SPECIFIC (decl) + && DECL_TEMPLATE_INSTANTIATION (decl) && !DECL_TEMPLATE_INSTANTIATED (decl)) { /* init is null because we're deferring instantiating the @@ -6133,12 +6151,13 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, auto_node); if (type == error_mark_node) return; + cp_apply_type_quals_to_decl (cp_type_quals (type), decl); } if (!ensure_literal_type_for_constexpr_object (decl)) DECL_DECLARED_CONSTEXPR_P (decl) = 0; - if (TREE_CODE (decl) == VAR_DECL + if (VAR_P (decl) && DECL_CLASS_SCOPE_P (decl) && DECL_INITIALIZED_IN_CLASS_P (decl)) check_static_variable_definition (decl, type); @@ -6169,7 +6188,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, } } - if (init && TREE_CODE (decl) == VAR_DECL) + if (init && VAR_P (decl)) { DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1; /* If DECL is a reference, then we want to know whether init is a @@ -6208,7 +6227,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, then it can be used in future constant expressions, so its value must be available. */ - if (TREE_CODE (decl) != VAR_DECL || dependent_type_p (type)) + if (!VAR_P (decl) || dependent_type_p (type)) /* We can't do anything if the decl has dependent type. */; else if (init && init_const_expr_p @@ -6279,7 +6298,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, TREE_READONLY (decl) = 0; } - if (TREE_CODE (decl) == VAR_DECL) + if (VAR_P (decl)) { /* If this is a local variable that will need a mangled name, register it now. We must do this before processing the @@ -6390,6 +6409,21 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, && TYPE_FOR_JAVA (type) && MAYBE_CLASS_TYPE_P (type)) error ("non-static data member %qD has Java class type", decl); + if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type)) + { + /* If the VLA bound is larger than half the address space, or less + than zero, throw std::bad_array_length. */ + tree max = convert (ssizetype, TYPE_MAX_VALUE (TYPE_DOMAIN (type))); + /* C++1y says we should throw for length <= 0, but we have + historically supported zero-length arrays. Let's treat that as an + extension to be disabled by -std=c++NN. */ + int lower = flag_iso ? 0 : -1; + tree comp = build2 (LT_EXPR, boolean_type_node, max, ssize_int (lower)); + comp = build3 (COND_EXPR, void_type_node, comp, + throw_bad_array_length (), void_zero_node); + finish_expr_stmt (comp); + } + /* Add this declaration to the statement-tree. This needs to happen after the call to check_initializer so that the DECL_EXPR for a reference temp is added before the DECL_EXPR for the reference itself. */ @@ -6398,10 +6432,9 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, /* Let the middle end know about variables and functions -- but not static data members in uninstantiated class templates. */ - if (TREE_CODE (decl) == VAR_DECL - || TREE_CODE (decl) == FUNCTION_DECL) + if (VAR_OR_FUNCTION_DECL_P (decl)) { - if (TREE_CODE (decl) == VAR_DECL) + if (VAR_P (decl)) { layout_var_decl (decl); maybe_commonize_var (decl); @@ -6434,11 +6467,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, /* Check for abstractness of the type. Notice that there is no need to strip array types here since the check for those types is already done within create_array_type_for_decl. */ - if (TREE_CODE (type) == FUNCTION_TYPE - || TREE_CODE (type) == METHOD_TYPE) - abstract_virtuals_error (decl, TREE_TYPE (type)); - else - abstract_virtuals_error (decl, type); + abstract_virtuals_error (decl, type); if (TREE_TYPE (decl) == error_mark_node) /* No initialization required. */ @@ -6758,10 +6787,9 @@ register_dtor_fn (tree decl) "__aeabi_atexit"), and DECL is a class object, we can just pass the destructor to "__cxa_atexit"; we don't have to build a temporary function to do the cleanup. */ - ob_parm = (DECL_THREAD_LOCAL_P (decl) - || (flag_use_cxa_atexit - && !targetm.cxx.use_atexit_for_cxa_atexit ())); - dso_parm = ob_parm; + dso_parm = (flag_use_cxa_atexit + && !targetm.cxx.use_atexit_for_cxa_atexit ()); + ob_parm = (DECL_THREAD_LOCAL_P (decl) || dso_parm); use_dtor = ob_parm && CLASS_TYPE_P (type); if (use_dtor) { @@ -6825,7 +6853,7 @@ register_dtor_fn (tree decl) before passing it in, to avoid spurious errors. */ addr = build_nop (ptr_type_node, addr); } - else if (ob_parm) + else /* Since the cleanup functions we build ignore the address they're given, there's no reason to pass the actual address in, and, in general, it's cheaper to pass NULL than any @@ -6835,6 +6863,10 @@ register_dtor_fn (tree decl) if (dso_parm) arg2 = cp_build_addr_expr (get_dso_handle_node (), tf_warning_or_error); + else if (ob_parm) + /* Just pass NULL to the dso handle parm if we don't actually + have a DSO handle on this target. */ + arg2 = null_pointer_node; else arg2 = NULL_TREE; @@ -6868,7 +6900,7 @@ register_dtor_fn (tree decl) static void expand_static_init (tree decl, tree init) { - gcc_assert (TREE_CODE (decl) == VAR_DECL); + gcc_assert (VAR_P (decl)); gcc_assert (TREE_STATIC (decl)); /* Some variables require no dynamic initialization. */ @@ -7221,8 +7253,7 @@ check_class_member_definition_namespace (tree decl) { /* These checks only apply to member functions and static data members. */ - gcc_assert (TREE_CODE (decl) == FUNCTION_DECL - || TREE_CODE (decl) == VAR_DECL); + gcc_assert (VAR_OR_FUNCTION_DECL_P (decl)); /* We check for problems with specializations in pt.c in check_specialization_namespace, where we can issue better diagnostics. */ @@ -7314,6 +7345,7 @@ grokfndecl (tree ctype, int virtualp, enum overload_flags flags, cp_cv_quals quals, + cp_ref_qualifier rqual, tree raises, int check, int friendp, @@ -7330,6 +7362,8 @@ grokfndecl (tree ctype, int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE; tree t; + if (rqual) + type = build_ref_qualified_type (type, rqual); if (raises) type = build_exception_variant (type, raises); @@ -7414,8 +7448,7 @@ grokfndecl (tree ctype, == current_class_type); fns = TREE_OPERAND (fns, 1); } - gcc_assert (TREE_CODE (fns) == IDENTIFIER_NODE - || TREE_CODE (fns) == OVERLOAD); + gcc_assert (identifier_p (fns) || TREE_CODE (fns) == OVERLOAD); DECL_TEMPLATE_INFO (decl) = build_template_info (fns, args); for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t)) @@ -7428,13 +7461,16 @@ grokfndecl (tree ctype, return NULL_TREE; } + if (inlinep & 1) + error ("%<inline%> is not allowed in declaration of friend " + "template specialization %qD", + decl); + if (inlinep & 2) + error ("%<constexpr%> is not allowed in declaration of friend " + "template specialization %qD", + decl); if (inlinep) - { - error ("%<inline%> is not allowed in declaration of friend " - "template specialization %qD", - decl); - return NULL_TREE; - } + return NULL_TREE; } } @@ -7473,8 +7509,10 @@ grokfndecl (tree ctype, { if (PROCESSING_REAL_TEMPLATE_DECL_P()) error ("cannot declare %<::main%> to be a template"); - if (inlinep) + if (inlinep & 1) error ("cannot declare %<::main%> to be inline"); + if (inlinep & 2) + error ("cannot declare %<::main%> to be constexpr"); if (!publicp) error ("cannot declare %<::main%> to be static"); inlinep = 0; @@ -7533,13 +7571,25 @@ grokfndecl (tree ctype, DECL_DECLARED_CONSTEXPR_P (decl) = true; DECL_EXTERNAL (decl) = 1; - if (quals && TREE_CODE (type) == FUNCTION_TYPE) + if (TREE_CODE (type) == FUNCTION_TYPE) { - error (ctype - ? G_("static member function %qD cannot have cv-qualifier") - : G_("non-member function %qD cannot have cv-qualifier"), - decl); - quals = TYPE_UNQUALIFIED; + if (quals) + { + error (ctype + ? G_("static member function %qD cannot have cv-qualifier") + : G_("non-member function %qD cannot have cv-qualifier"), + decl); + quals = TYPE_UNQUALIFIED; + } + + if (rqual) + { + error (ctype + ? G_("static member function %qD cannot have ref-qualifier") + : G_("non-member function %qD cannot have ref-qualifier"), + decl); + rqual = REF_QUAL_NONE; + } } if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)) @@ -7603,7 +7653,7 @@ grokfndecl (tree ctype, grokclassfn (ctype, decl, flags); /* 12.4/3 */ - if (cxx_dialect >= cxx0x + if (cxx_dialect >= cxx11 && DECL_DESTRUCTOR_P (decl) && !TYPE_BEING_DEFINED (DECL_CONTEXT (decl)) && !processing_template_decl) @@ -7773,7 +7823,7 @@ grokvardecl (tree type, tree decl; tree explicit_scope; - gcc_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE); + gcc_assert (!name || identifier_p (name)); /* Compute the scope in which to place the variable, but remember whether or not that scope was explicitly specified by the user. */ @@ -7977,7 +8027,8 @@ build_ptrmem_type (tree class_type, tree member_type) if (TREE_CODE (member_type) == METHOD_TYPE) { cp_cv_quals quals = type_memfn_quals (member_type); - member_type = build_memfn_type (member_type, class_type, quals); + cp_ref_qualifier rqual = type_memfn_rqual (member_type); + member_type = build_memfn_type (member_type, class_type, quals, rqual); return build_ptrmemfunc_type (build_pointer_type (member_type)); } else @@ -8002,7 +8053,7 @@ check_static_variable_definition (tree decl, tree type) in check_initializer. */ if (DECL_P (decl) && DECL_DECLARED_CONSTEXPR_P (decl)) return 0; - else if (cxx_dialect >= cxx0x && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)) + else if (cxx_dialect >= cxx11 && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)) { if (!COMPLETE_TYPE_P (type)) error ("in-class initialization of static data member %q#D of " @@ -8124,7 +8175,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain) mark_rvalue_use (size); - if (cxx_dialect < cxx0x && TREE_CODE (size) == NOP_EXPR + if (cxx_dialect < cxx11 && TREE_CODE (size) == NOP_EXPR && TREE_SIDE_EFFECTS (size)) /* In C++98, we mark a non-constant array bound with a magic NOP_EXPR with TREE_SIDE_EFFECTS; don't fold in that case. */; @@ -8190,7 +8241,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain) constant. Just build the index type and mark that it requires structural equality checks. */ itype = build_index_type (build_min (MINUS_EXPR, sizetype, - size, integer_one_node)); + size, size_one_node)); TYPE_DEPENDENT_P (itype) = 1; TYPE_DEPENDENT_P_VALID (itype) = 1; SET_TYPE_STRUCTURAL_EQUALITY (itype); @@ -8245,7 +8296,8 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain) else if (TREE_CONSTANT (size) /* We don't allow VLAs at non-function scopes, or during tentative template substitution. */ - || !at_function_scope_p () || !(complain & tf_error)) + || !at_function_scope_p () + || (cxx_dialect < cxx1y && !(complain & tf_error))) { if (!(complain & tf_error)) return error_mark_node; @@ -8257,7 +8309,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain) error ("size of array is not an integral constant-expression"); size = integer_one_node; } - else if (pedantic && warn_vla != 0) + else if (cxx_dialect < cxx1y && pedantic && warn_vla != 0) { if (name) pedwarn (input_location, OPT_Wvla, "ISO C++ forbids variable length array %qD", name); @@ -8435,6 +8487,9 @@ create_array_type_for_decl (tree name, tree type, tree size) return error_mark_node; } + if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type)) + pedwarn (input_location, OPT_Wvla, "array of array of runtime bound"); + /* Figure out the index type for the array. */ if (size) itype = compute_array_index_type (name, size, tf_warning_or_error); @@ -8510,7 +8565,7 @@ check_var_type (tree identifier, tree type) { if (!identifier) error ("unnamed variable or field declared void"); - else if (TREE_CODE (identifier) == IDENTIFIER_NODE) + else if (identifier_p (identifier)) { gcc_assert (!IDENTIFIER_OPNAME_P (identifier)); error ("variable or field %qE declared void", identifier); @@ -8626,6 +8681,9 @@ grokdeclarator (const cp_declarator *declarator, /* virt-specifiers that apply to the declarator, for a declaration of a member function. */ cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED; + /* ref-qualifier that applies to the declarator, for a declaration of + a member function. */ + cp_ref_qualifier rqual = REF_QUAL_NONE; /* cv-qualifiers that apply to the type specified by the DECLSPECS. */ int type_quals; tree raises = NULL_TREE; @@ -8652,7 +8710,9 @@ grokdeclarator (const cp_declarator *declarator, bool parameter_pack_p = declarator? declarator->parameter_pack_p : false; bool template_type_arg = false; bool template_parm_flag = false; + bool typedef_p = decl_spec_seq_has_spec_p (declspecs, ds_typedef); bool constexpr_p = decl_spec_seq_has_spec_p (declspecs, ds_constexpr); + source_location saved_loc = input_location; const char *errmsg; signed_p = decl_spec_seq_has_spec_p (declspecs, ds_signed); @@ -8778,7 +8838,7 @@ grokdeclarator (const cp_declarator *declarator, tree fns = TREE_OPERAND (decl, 0); dname = fns; - if (TREE_CODE (dname) != IDENTIFIER_NODE) + if (!identifier_p (dname)) { gcc_assert (is_overloaded_fn (dname)); dname = DECL_NAME (get_first_fn (dname)); @@ -8787,7 +8847,7 @@ grokdeclarator (const cp_declarator *declarator, /* Fall through. */ case IDENTIFIER_NODE: - if (TREE_CODE (decl) == IDENTIFIER_NODE) + if (identifier_p (decl)) dname = decl; if (C_IS_RESERVED_WORD (dname)) @@ -8852,7 +8912,7 @@ grokdeclarator (const cp_declarator *declarator, } if (dname - && TREE_CODE (dname) == IDENTIFIER_NODE + && identifier_p (dname) && UDLIT_OPER_P (dname) && innermost_code != cdk_function) { @@ -8862,7 +8922,7 @@ grokdeclarator (const cp_declarator *declarator, if (dname && IDENTIFIER_OPNAME_P (dname)) { - if (decl_spec_seq_has_spec_p (declspecs, ds_typedef)) + if (typedef_p) { error ("declaration of %qD as %<typedef%>", dname); return error_mark_node; @@ -8900,7 +8960,7 @@ grokdeclarator (const cp_declarator *declarator, if (name == NULL) name = decl_context == PARM ? "parameter" : "type name"; - if (constexpr_p && decl_spec_seq_has_spec_p (declspecs, ds_typedef)) + if (constexpr_p && typedef_p) { error ("%<constexpr%> cannot appear in a typedef declaration"); return error_mark_node; @@ -8977,7 +9037,7 @@ grokdeclarator (const cp_declarator *declarator, common. With no options, it is allowed. With -Wreturn-type, it is a warning. It is only an error with -pedantic-errors. */ is_main = (funcdef_flag - && dname && TREE_CODE (dname) == IDENTIFIER_NODE + && dname && identifier_p (dname) && MAIN_NAME_P (dname) && ctype == NULL_TREE && in_namespace == NULL_TREE @@ -9198,7 +9258,7 @@ grokdeclarator (const cp_declarator *declarator, /* Issue errors about use of storage classes for parameters. */ if (decl_context == PARM) { - if (decl_spec_seq_has_spec_p (declspecs, ds_typedef)) + if (typedef_p) { error ("typedef declaration invalid in parameter declaration"); return error_mark_node; @@ -9242,7 +9302,7 @@ grokdeclarator (const cp_declarator *declarator, && ((storage_class && storage_class != sc_extern && storage_class != sc_static) - || decl_spec_seq_has_spec_p (declspecs, ds_typedef))) + || typedef_p)) { error ("multiple storage classes in declaration of %qs", name); thread_p = false; @@ -9256,7 +9316,7 @@ grokdeclarator (const cp_declarator *declarator, && (storage_class == sc_register || storage_class == sc_auto)) ; - else if (decl_spec_seq_has_spec_p (declspecs, ds_typedef)) + else if (typedef_p) ; else if (decl_context == FIELD /* C++ allows static class elements. */ @@ -9337,7 +9397,6 @@ grokdeclarator (const cp_declarator *declarator, if (declspecs->std_attributes) { /* Apply the c++11 attributes to the type preceding them. */ - source_location saved_loc = input_location; input_location = declspecs->locations[ds_std_attribute]; decl_attributes (&type, declspecs->std_attributes, 0); input_location = saved_loc; @@ -9425,16 +9484,17 @@ grokdeclarator (const cp_declarator *declarator, error ("%qs declared as function returning an array", name); return error_mark_node; } - /* When decl_context == NORMAL we emit a better error message - later in abstract_virtuals_error. */ - if (decl_context == TYPENAME && ABSTRACT_CLASS_TYPE_P (type)) - error ("%qs declared as function returning an abstract " - "class type", name); + + input_location = declspecs->locations[ds_type_spec]; + abstract_virtuals_error (ACU_RETURN, type); + input_location = saved_loc; /* Pick up type qualifiers which should be applied to `this'. */ memfn_quals = declarator->u.function.qualifiers; /* Pick up virt-specifiers. */ virt_specifiers = declarator->u.function.virt_specifiers; + /* And ref-qualifier, too */ + rqual = declarator->u.function.ref_qualifier; /* Pick up the exception specifications. */ raises = declarator->u.function.exception_specification; /* If the exception-specification is ill-formed, let's pretend @@ -9460,6 +9520,9 @@ grokdeclarator (const cp_declarator *declarator, pedwarn (input_location, 0, "%qs function uses " "%<auto%> type specifier without trailing " "return type", name); + else if (virtualp) + permerror (input_location, "virtual function cannot " + "have deduced return type"); } else if (!is_auto (type)) { @@ -9471,7 +9534,7 @@ grokdeclarator (const cp_declarator *declarator, } else if (declarator->u.function.late_return_type) { - if (cxx_dialect < cxx0x) + if (cxx_dialect < cxx11) /* Not using maybe_warn_cpp0x because this should always be an error. */ error ("trailing return type only available with " @@ -9502,12 +9565,13 @@ grokdeclarator (const cp_declarator *declarator, therefore returns a void type. */ /* ISO C++ 12.4/2. A destructor may not be declared - const or volatile. A destructor may not be - static. + const or volatile. A destructor may not be static. + A destructor may not be declared with ref-qualifier. ISO C++ 12.1. A constructor may not be declared const or volatile. A constructor may not be - virtual. A constructor may not be static. */ + virtual. A constructor may not be static. + A constructor may not be declared with ref-qualifier. */ if (staticp == 2) error ((flags == DTOR_FLAG) ? G_("destructor cannot be static member function") @@ -9520,6 +9584,15 @@ grokdeclarator (const cp_declarator *declarator, memfn_quals = TYPE_UNQUALIFIED; } + if (rqual) + { + maybe_warn_cpp0x (CPP0X_REF_QUALIFIER); + error ((flags == DTOR_FLAG) + ? "destructors may not be ref-qualified" + : "constructors may not be ref-qualified"); + rqual = REF_QUAL_NONE; + } + if (decl_context == FIELD && !member_function_or_else (ctype, current_class_type, @@ -9632,26 +9705,38 @@ grokdeclarator (const cp_declarator *declarator, but to the target of the pointer. */ type_quals = TYPE_UNQUALIFIED; + /* This code used to handle METHOD_TYPE, but I don't think it's + possible to get it here anymore. */ + gcc_assert (TREE_CODE (type) != METHOD_TYPE); if (declarator->kind == cdk_ptrmem - && (TREE_CODE (type) == FUNCTION_TYPE - || (memfn_quals && TREE_CODE (type) == METHOD_TYPE))) + && TREE_CODE (type) == FUNCTION_TYPE) { memfn_quals |= type_memfn_quals (type); type = build_memfn_type (type, declarator->u.pointer.class_type, - memfn_quals); + memfn_quals, + rqual); if (type == error_mark_node) return error_mark_node; + + rqual = REF_QUAL_NONE; memfn_quals = TYPE_UNQUALIFIED; } if (TREE_CODE (type) == FUNCTION_TYPE - && type_memfn_quals (type) != TYPE_UNQUALIFIED) + && (type_memfn_quals (type) != TYPE_UNQUALIFIED + || type_memfn_rqual (type) != REF_QUAL_NONE)) error (declarator->kind == cdk_reference ? G_("cannot declare reference to qualified function type %qT") : G_("cannot declare pointer to qualified function type %qT"), type); + if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type)) + pedwarn (input_location, OPT_Wvla, + declarator->kind == cdk_reference + ? G_("reference to array of runtime bound") + : G_("pointer to array of runtime bound")); + /* When the pointed-to type involves components of variable size, care must be taken to ensure that the size evaluation code is emitted early enough to dominate all the possible later uses @@ -9866,8 +9951,7 @@ grokdeclarator (const cp_declarator *declarator, return error_mark_node; } } - else if (decl_spec_seq_has_spec_p (declspecs, ds_typedef) - && current_class_type) + else if (typedef_p && current_class_type) { error ("cannot declare member %<%T::%s%> within %qT", ctype, name, current_class_type); @@ -9944,8 +10028,7 @@ grokdeclarator (const cp_declarator *declarator, error ("non-member %qs cannot be declared %<mutable%>", name); storage_class = sc_none; } - else if (decl_context == TYPENAME - || decl_spec_seq_has_spec_p (declspecs, ds_typedef)) + else if (decl_context == TYPENAME || typedef_p) { error ("non-object member %qs cannot be declared %<mutable%>", name); storage_class = sc_none; @@ -9975,7 +10058,7 @@ grokdeclarator (const cp_declarator *declarator, } /* If this is declaring a typedef name, return a TYPE_DECL. */ - if (decl_spec_seq_has_spec_p (declspecs, ds_typedef) && decl_context != TYPENAME) + if (typedef_p && decl_context != TYPENAME) { tree decl; @@ -9993,12 +10076,13 @@ grokdeclarator (const cp_declarator *declarator, example "f S::*" declares a pointer to a const-qualified member function of S. We record the cv-qualification in the function type. */ - if (memfn_quals && TREE_CODE (type) == FUNCTION_TYPE) + if ((rqual || memfn_quals) && TREE_CODE (type) == FUNCTION_TYPE) { - type = apply_memfn_quals (type, memfn_quals); + type = apply_memfn_quals (type, memfn_quals, rqual); /* We have now dealt with these qualifiers. */ memfn_quals = TYPE_UNQUALIFIED; + rqual = REF_QUAL_NONE; } if (type_uses_auto (type)) @@ -10007,6 +10091,10 @@ grokdeclarator (const cp_declarator *declarator, type = error_mark_node; } + if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type)) + pedwarn (input_location, OPT_Wvla, + "typedef naming array of runtime bound"); + if (decl_context == FIELD) decl = build_lang_decl (TYPE_DECL, unqualified_id, type); else @@ -10128,8 +10216,10 @@ grokdeclarator (const cp_declarator *declarator, if (decl_context != TYPENAME) { /* A cv-qualifier-seq shall only be part of the function type - for a non-static member function. [8.3.5/4 dcl.fct] */ - if (type_memfn_quals (type) != TYPE_UNQUALIFIED + for a non-static member function. A ref-qualifier shall only + .... /same as above/ [dcl.fct] */ + if ((type_memfn_quals (type) != TYPE_UNQUALIFIED + || type_memfn_rqual (type) != REF_QUAL_NONE) && (current_class_type == NULL_TREE || staticp) ) { error (staticp @@ -10143,6 +10233,7 @@ grokdeclarator (const cp_declarator *declarator, /* The qualifiers on the function type become the qualifiers on the non-static member function. */ memfn_quals |= type_memfn_quals (type); + rqual = type_memfn_rqual (type); type_quals = TYPE_UNQUALIFIED; } } @@ -10200,17 +10291,19 @@ grokdeclarator (const cp_declarator *declarator, type = void_type_node; } } - else if (memfn_quals) + else if (memfn_quals || rqual) { if (ctype == NULL_TREE && TREE_CODE (type) == METHOD_TYPE) ctype = TYPE_METHOD_BASETYPE (type); if (ctype) - type = build_memfn_type (type, ctype, memfn_quals); - /* Core issue #547: need to allow this in template type args. */ - else if (template_type_arg && TREE_CODE (type) == FUNCTION_TYPE) - type = apply_memfn_quals (type, memfn_quals); + type = build_memfn_type (type, ctype, memfn_quals, rqual); + /* Core issue #547: need to allow this in template type args. + Allow it in general in C++11 for alias-declarations. */ + else if ((template_type_arg || cxx_dialect >= cxx11) + && TREE_CODE (type) == FUNCTION_TYPE) + type = apply_memfn_quals (type, memfn_quals, rqual); else error ("invalid qualifiers on non-member function type"); } @@ -10279,7 +10372,7 @@ grokdeclarator (const cp_declarator *declarator, cp_cv_quals real_quals = memfn_quals; if (constexpr_p && sfk != sfk_constructor && sfk != sfk_destructor) real_quals |= TYPE_QUAL_CONST; - type = build_memfn_type (type, ctype, real_quals); + type = build_memfn_type (type, ctype, real_quals, rqual); } { @@ -10411,7 +10504,7 @@ grokdeclarator (const cp_declarator *declarator, ? unqualified_id : dname, parms, unqualified_id, - virtualp, flags, memfn_quals, raises, + virtualp, flags, memfn_quals, rqual, raises, friendp ? -1 : 0, friendp, publicp, inlinep | (2 * constexpr_p), sfk, @@ -10441,21 +10534,13 @@ grokdeclarator (const cp_declarator *declarator, && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0)) { if (unqualified_id) - error ("field %qD has incomplete type", unqualified_id); + error ("field %qD has incomplete type %qT", + unqualified_id, type); else error ("name %qT has incomplete type", type); - /* If we're instantiating a template, tell them which - instantiation made the field's type be incomplete. */ - if (current_class_type - && TYPE_NAME (current_class_type) - && IDENTIFIER_TEMPLATE (current_class_name) - && declspecs->type - && declspecs->type == type) - error (" in instantiation of template %qT", - current_class_type); - - return error_mark_node; + type = error_mark_node; + decl = NULL_TREE; } else { @@ -10632,7 +10717,7 @@ grokdeclarator (const cp_declarator *declarator, || storage_class != sc_static); decl = grokfndecl (ctype, type, original_name, parms, unqualified_id, - virtualp, flags, memfn_quals, raises, + virtualp, flags, memfn_quals, rqual, raises, 1, friendp, publicp, inlinep | (2 * constexpr_p), sfk, funcdef_flag, @@ -10739,7 +10824,7 @@ grokdeclarator (const cp_declarator *declarator, DECL_THIS_STATIC (decl) = 1; /* Set constexpr flag on vars (functions got it in grokfndecl). */ - if (constexpr_p && TREE_CODE (decl) == VAR_DECL) + if (constexpr_p && VAR_P (decl)) DECL_DECLARED_CONSTEXPR_P (decl) = true; /* Record constancy and volatility on the DECL itself . There's @@ -10781,7 +10866,7 @@ require_complete_types_for_parms (tree parms) int local_variable_p (const_tree t) { - if ((TREE_CODE (t) == VAR_DECL + if ((VAR_P (t) /* A VAR_DECL with a context that is a _TYPE is a static data member. */ && !TYPE_P (CP_DECL_CONTEXT (t)) @@ -10800,9 +10885,8 @@ static tree local_variable_p_walkfn (tree *tp, int *walk_subtrees, void * /*data*/) { - /* Check DECL_NAME to avoid including temporaries. We don't check - DECL_ARTIFICIAL because we do want to complain about 'this'. */ - if (local_variable_p (*tp) && DECL_NAME (*tp)) + if (local_variable_p (*tp) + && (!DECL_ARTIFICIAL (*tp) || DECL_NAME (*tp) == this_identifier)) return *tp; else if (TYPE_P (*tp)) *walk_subtrees = 0; @@ -10892,7 +10976,7 @@ type_is_deprecated (tree type) return type; /* Do warn about using typedefs to a deprecated class. */ - if (TAGGED_TYPE_P (type) && type != TYPE_MAIN_VARIANT (type)) + if (OVERLOAD_TYPE_P (type) && type != TYPE_MAIN_VARIANT (type)) return type_is_deprecated (TYPE_MAIN_VARIANT (type)); code = TREE_CODE (type); @@ -11478,7 +11562,7 @@ grok_op_properties (tree decl, bool complain) if (ref) t = TYPE_MAIN_VARIANT (TREE_TYPE (t)); - if (TREE_CODE (t) == VOID_TYPE) + if (VOID_TYPE_P (t)) warning (OPT_Wconversion, ref ? G_("conversion to a reference to void " @@ -11890,13 +11974,14 @@ lookup_and_check_tag (enum tag_types tag_code, tree name, static tree xref_tag_1 (enum tag_types tag_code, tree name, - tag_scope scope, bool template_header_p) + tag_scope orig_scope, bool template_header_p) { enum tree_code code; tree t; tree context = NULL_TREE; + tag_scope scope; - gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); + gcc_assert (identifier_p (name)); switch (tag_code) { @@ -11914,6 +11999,11 @@ xref_tag_1 (enum tag_types tag_code, tree name, gcc_unreachable (); } + if (orig_scope == ts_lambda) + scope = ts_current; + else + scope = orig_scope; + /* In case of anonymous name, xref_tag is only called to make type node and push name. Name lookup is not required. */ if (ANON_AGGRNAME_P (name)) @@ -11987,6 +12077,10 @@ xref_tag_1 (enum tag_types tag_code, tree name, { t = make_class_type (code); TYPE_CONTEXT (t) = context; + if (orig_scope == ts_lambda) + /* Remember that we're declaring a lambda to avoid bogus errors + in push_template_decl. */ + CLASSTYPE_LAMBDA_EXPR (t) = error_mark_node; t = pushtag (name, t, scope); } } @@ -12314,7 +12408,7 @@ start_enum (tree name, tree enumtype, tree underlying_type, bool scoped_enum_p, bool *is_new) { tree prevtype = NULL_TREE; - gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); + gcc_assert (identifier_p (name)); if (is_new) *is_new = false; @@ -12748,7 +12842,7 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc) && double_int_fits_to_tree_p (type, di)) break; } - if (type && cxx_dialect < cxx0x + if (type && cxx_dialect < cxx11 && itk > itk_unsigned_long) pedwarn (input_location, OPT_Wlong_long, pos ? "\ incremented enumerator value is too large for %<unsigned long%>" : "\ @@ -12782,8 +12876,8 @@ incremented enumerator value is too large for %<long%>"); && TREE_CODE (value) == INTEGER_CST) { if (!int_fits_type_p (value, ENUM_UNDERLYING_TYPE (enumtype))) - error ("enumerator value %E is too large for underlying type %<%T%>", - value, ENUM_UNDERLYING_TYPE (enumtype)); + error ("enumerator value %E is outside the range of underlying " + "type %<%T%>", value, ENUM_UNDERLYING_TYPE (enumtype)); /* Convert the value to the appropriate type. */ value = convert (ENUM_UNDERLYING_TYPE (enumtype), value); @@ -12932,7 +13026,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) bool honor_interface; /* Sanity check. */ - gcc_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE); + gcc_assert (VOID_TYPE_P (TREE_VALUE (void_list_node))); gcc_assert (TREE_CHAIN (void_list_node) == NULL_TREE); fntype = TREE_TYPE (decl1); @@ -12997,7 +13091,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) /* Effective C++ rule 15. */ if (warn_ecpp && DECL_OVERLOADED_OPERATOR_P (decl1) == NOP_EXPR - && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE) + && VOID_TYPE_P (TREE_TYPE (fntype))) warning (OPT_Weffc__, "%<operator=%> should return a reference to %<*this%>"); /* Make the init_value nonzero so pushdecl knows this is not tentative. @@ -13168,7 +13262,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) tree t = DECL_ARGUMENTS (decl1); gcc_assert (t != NULL_TREE && TREE_CODE (t) == PARM_DECL); - gcc_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE); + gcc_assert (TYPE_PTR_P (TREE_TYPE (t))); cp_function_chain->x_current_class_ref = cp_build_indirect_ref (t, RO_NULL, tf_warning_or_error); @@ -13396,7 +13490,7 @@ store_parm_decls (tree current_function_parms) if (TREE_CODE (parm) == PARM_DECL) { if (DECL_NAME (parm) == NULL_TREE - || TREE_CODE (parm) != VOID_TYPE) + || !VOID_TYPE_P (parm)) pushdecl (parm); else error ("parameter %qD declared void", parm); @@ -13499,6 +13593,14 @@ begin_destructor_body (void) initialize_vtbl_ptrs (current_class_ptr); finish_compound_stmt (compound_stmt); + /* Insert a cleanup to let the back end know that the object is dead + when we exit the destructor, either normally or via exception. */ + tree clobber = build_constructor (current_class_type, NULL); + TREE_THIS_VOLATILE (clobber) = true; + tree exprstmt = build2 (MODIFY_EXPR, current_class_type, + current_class_ref, clobber); + finish_decl_cleanup (NULL_TREE, exprstmt); + /* And insert cleanups for our bases and members so that they will be properly destroyed if we throw. */ push_base_cleanups (); @@ -13819,7 +13921,7 @@ finish_function (int flags) /* Complain if there's just no return statement. */ if (warn_return_type - && TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE + && !VOID_TYPE_P (TREE_TYPE (fntype)) && !dependent_type_p (TREE_TYPE (fntype)) && !current_function_returns_value && !current_function_returns_null /* Don't complain if we abort or throw. */ @@ -14009,12 +14111,15 @@ grokmethod (cp_decl_specifier_seq *declspecs, /* VAR is a VAR_DECL. If its type is incomplete, remember VAR so that - we can lay it out later, when and if its type becomes complete. */ + we can lay it out later, when and if its type becomes complete. + + Also handle constexpr pointer to member variables where the initializer + is an unlowered PTRMEM_CST because the class isn't complete yet. */ void maybe_register_incomplete_var (tree var) { - gcc_assert (TREE_CODE (var) == VAR_DECL); + gcc_assert (VAR_P (var)); /* Keep track of variables with incomplete types. */ if (!processing_template_decl && TREE_TYPE (var) != error_mark_node @@ -14034,6 +14139,15 @@ maybe_register_incomplete_var (tree var) incomplete_var iv = {var, inner_type}; vec_safe_push (incomplete_vars, iv); } + else if (TYPE_PTRMEM_P (inner_type) + && DECL_INITIAL (var) + && TREE_CODE (DECL_INITIAL (var)) == PTRMEM_CST) + { + tree context = TYPE_PTRMEM_CLASS_TYPE (inner_type); + gcc_assert (TYPE_BEING_DEFINED (context)); + incomplete_var iv = {var, context}; + vec_safe_push (incomplete_vars, iv); + } } } @@ -14053,10 +14167,17 @@ complete_vars (tree type) { tree var = iv->decl; tree type = TREE_TYPE (var); - /* Complete the type of the variable. The VAR_DECL itself - will be laid out in expand_expr. */ - complete_type (type); - cp_apply_type_quals_to_decl (cp_type_quals (type), var); + + if (TYPE_PTRMEM_P (type)) + DECL_INITIAL (var) = cplus_expand_constant (DECL_INITIAL (var)); + else + { + /* Complete the type of the variable. The VAR_DECL itself + will be laid out in expand_expr. */ + complete_type (type); + cp_apply_type_quals_to_decl (cp_type_quals (type), var); + } + /* Remove this entry from the list. */ incomplete_vars->unordered_remove (ix); } @@ -14179,8 +14300,9 @@ static_fn_type (tree memfntype) return memfntype; gcc_assert (TREE_CODE (memfntype) == METHOD_TYPE); args = TYPE_ARG_TYPES (memfntype); + cp_ref_qualifier rqual = type_memfn_rqual (memfntype); fntype = build_function_type (TREE_TYPE (memfntype), TREE_CHAIN (args)); - fntype = apply_memfn_quals (fntype, type_memfn_quals (memfntype)); + fntype = apply_memfn_quals (fntype, type_memfn_quals (memfntype), rqual); fntype = (cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (memfntype))); fntype = (build_exception_variant @@ -14196,9 +14318,10 @@ revert_static_member_fn (tree decl) { tree stype = static_fn_type (decl); cp_cv_quals quals = type_memfn_quals (stype); + cp_ref_qualifier rqual = type_memfn_rqual (stype); - if (quals != TYPE_UNQUALIFIED) - stype = apply_memfn_quals (stype, TYPE_UNQUALIFIED); + if (quals != TYPE_UNQUALIFIED || rqual != REF_QUAL_NONE) + stype = apply_memfn_quals (stype, TYPE_UNQUALIFIED, REF_QUAL_NONE); TREE_TYPE (decl) = stype; @@ -14257,7 +14380,7 @@ cxx_comdat_group (tree decl) /* Virtual tables, construction virtual tables, and virtual table tables all go in a single COMDAT group, named after the primary virtual table. */ - if (TREE_CODE (decl) == VAR_DECL && DECL_VTABLE_OR_VTT_P (decl)) + if (VAR_P (decl) && DECL_VTABLE_OR_VTT_P (decl)) name = DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (DECL_CONTEXT (decl))); /* For all other DECLs, the COMDAT group is the mangled name of the declaration itself. */ @@ -14282,4 +14405,43 @@ cxx_comdat_group (tree decl) return name; } +/* Returns the return type for FN as written by the user, which may include + a placeholder for a deduced return type. */ + +tree +fndecl_declared_return_type (tree fn) +{ + fn = STRIP_TEMPLATE (fn); + if (FNDECL_USED_AUTO (fn)) + { + struct language_function *f = NULL; + if (DECL_STRUCT_FUNCTION (fn)) + f = DECL_STRUCT_FUNCTION (fn)->language; + if (f == NULL) + f = DECL_SAVED_FUNCTION_DATA (fn); + return f->x_auto_return_pattern; + } + return TREE_TYPE (TREE_TYPE (fn)); +} + +/* Returns true iff DECL was declared with an auto return type and it has + not yet been deduced to a real type. */ + +bool +undeduced_auto_decl (tree decl) +{ + if (cxx_dialect < cxx1y) + return false; + return type_uses_auto (TREE_TYPE (decl)); +} + +/* Complain if DECL has an undeduced return type. */ + +void +require_deduced_type (tree decl) +{ + if (undeduced_auto_decl (decl)) + error ("use of %qD before deduction of %<auto%>", decl); +} + #include "gt-cp-decl.h" diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 82bc6f79e5b..1573cede899 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -109,7 +109,8 @@ int at_eof; that apply to the function). */ tree -build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals) +build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals, + cp_ref_qualifier rqual) { tree raises; tree attrs; @@ -129,10 +130,12 @@ build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals) (TREE_CODE (fntype) == METHOD_TYPE ? TREE_CHAIN (TYPE_ARG_TYPES (fntype)) : TYPE_ARG_TYPES (fntype))); - if (raises) - fntype = build_exception_variant (fntype, raises); if (attrs) fntype = cp_build_type_attribute_variant (fntype, attrs); + if (rqual) + fntype = build_ref_qualified_type (fntype, rqual); + if (raises) + fntype = build_exception_variant (fntype, raises); return fntype; } @@ -157,7 +160,9 @@ change_return_type (tree new_ret, tree fntype) if (TREE_CODE (fntype) == FUNCTION_TYPE) { newtype = build_function_type (new_ret, args); - newtype = apply_memfn_quals (newtype, type_memfn_quals (fntype)); + newtype = apply_memfn_quals (newtype, + type_memfn_quals (fntype), + type_memfn_rqual (fntype)); } else newtype = build_method_type_directly @@ -330,10 +335,11 @@ grokclassfn (tree ctype, tree function, enum overload_flags flags) } /* Create an ARRAY_REF, checking for the user doing things backwards - along the way. */ + along the way. DECLTYPE_P is for N3276, as in the parser. */ tree -grok_array_decl (location_t loc, tree array_expr, tree index_exp) +grok_array_decl (location_t loc, tree array_expr, tree index_exp, + bool decltype_p) { tree type; tree expr; @@ -359,8 +365,13 @@ grok_array_decl (location_t loc, tree array_expr, tree index_exp) /* If they have an `operator[]', use that. */ if (MAYBE_CLASS_TYPE_P (type) || MAYBE_CLASS_TYPE_P (TREE_TYPE (index_exp))) - expr = build_new_op (loc, ARRAY_REF, LOOKUP_NORMAL, array_expr, index_exp, - NULL_TREE, /*overload=*/NULL, tf_warning_or_error); + { + tsubst_flags_t complain = tf_warning_or_error; + if (decltype_p) + complain |= tf_decltype; + expr = build_new_op (loc, ARRAY_REF, LOOKUP_NORMAL, array_expr, + index_exp, NULL_TREE, /*overload=*/NULL, complain); + } else { tree p1, p2, i1, i2; @@ -460,7 +471,7 @@ delete_sanity (tree exp, tree size, bool doing_vec, int use_global_delete, } /* Deleting ptr to void is undefined behavior [expr.delete/3]. */ - if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE) + if (VOID_TYPE_P (TREE_TYPE (type))) { warning (0, "deleting %qT is undefined", type); doing_vec = 0; @@ -518,9 +529,9 @@ acceptable_java_type (tree type) if (type == error_mark_node) return false; - if (TREE_CODE (type) == VOID_TYPE || TYPE_FOR_JAVA (type)) + if (VOID_TYPE_P (type) || TYPE_FOR_JAVA (type)) return true; - if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE) + if (TYPE_PTR_P (type) || TREE_CODE (type) == REFERENCE_TYPE) { type = TREE_TYPE (type); if (TREE_CODE (type) == RECORD_TYPE) @@ -535,7 +546,7 @@ acceptable_java_type (tree type) while (--i >= 0) { type = TREE_VEC_ELT (args, i); - if (TREE_CODE (type) == POINTER_TYPE) + if (TYPE_PTR_P (type)) type = TREE_TYPE (type); if (! TYPE_FOR_JAVA (type)) return false; @@ -635,6 +646,15 @@ check_classfn (tree ctype, tree function, tree template_parms) /* OK, is this a definition of a member template? */ is_template = (template_parms != NULL_TREE); + /* [temp.mem] + + A destructor shall not be a member template. */ + if (DECL_DESTRUCTOR_P (function) && is_template) + { + error ("destructor %qD declared as member template", function); + return error_mark_node; + } + /* We must enter the scope here, because conversion operators are named by target type, and type equivalence relies on typenames resolving within the scope of CTYPE. */ @@ -672,6 +692,11 @@ check_classfn (tree ctype, tree function, tree template_parms) if (is_template != (TREE_CODE (fndecl) == TEMPLATE_DECL)) continue; + /* ref-qualifier or absence of same must match. */ + if (type_memfn_rqual (TREE_TYPE (function)) + != type_memfn_rqual (TREE_TYPE (fndecl))) + continue; + /* While finding a match, same types and params are not enough if the function is versioned. Also check version ("target") attributes. */ @@ -810,9 +835,11 @@ grokfield (const cp_declarator *declarator, init = NULL_TREE; value = grokdeclarator (declarator, declspecs, FIELD, init != 0, &attrlist); - if (! value || error_operand_p (value)) + if (! value || value == error_mark_node) /* friend or constructor went bad. */ return error_mark_node; + if (TREE_TYPE (value) == error_mark_node) + return value; if (TREE_CODE (value) == TYPE_DECL && init) { @@ -858,7 +885,7 @@ grokfield (const cp_declarator *declarator, /* If this is a typedef that names the class for linkage purposes (7.1.3p8), apply any attributes directly to the type. */ - if (TAGGED_TYPE_P (TREE_TYPE (value)) + if (OVERLOAD_TYPE_P (TREE_TYPE (value)) && value == TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value)))) attrflags = ATTR_FLAG_TYPE_IN_PLACE; @@ -931,7 +958,7 @@ grokfield (const cp_declarator *declarator, } else if (TREE_CODE (value) == FIELD_DECL) /* C++11 NSDMI, keep going. */; - else if (TREE_CODE (value) != VAR_DECL) + else if (!VAR_P (value)) gcc_unreachable (); else if (!processing_template_decl) { @@ -955,8 +982,7 @@ grokfield (const cp_declarator *declarator, } } - if (processing_template_decl - && (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL)) + if (processing_template_decl && VAR_OR_FUNCTION_DECL_P (value)) { value = push_template_decl (value); if (error_operand_p (value)) @@ -1021,11 +1047,13 @@ grokbitfield (const cp_declarator *declarator, { tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, &attrlist); - if (value == error_mark_node) + if (value == error_mark_node) return NULL_TREE; /* friends went bad. */ + if (TREE_TYPE (value) == error_mark_node) + return value; /* Pass friendly classes back. */ - if (TREE_CODE (value) == VOID_TYPE) + if (VOID_TYPE_P (value)) return void_type_node; if (!INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (value)) @@ -1121,7 +1149,7 @@ is_late_template_attribute (tree attr, tree decl) second and following arguments. Attributes like mode, format, cleanup and several target specific attributes aren't late just because they have an IDENTIFIER_NODE as first argument. */ - if (arg == args && TREE_CODE (t) == IDENTIFIER_NODE) + if (arg == args && identifier_p (t)) continue; if (value_dependent_expression_p (t) @@ -1235,7 +1263,7 @@ cp_reconstruct_complex_type (tree type, tree bottom) { tree inner, outer; - if (TREE_CODE (type) == POINTER_TYPE) + if (TYPE_PTR_P (type)) { inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom); outer = build_pointer_type_for_mode (inner, TYPE_MODE (type), @@ -1261,7 +1289,9 @@ cp_reconstruct_complex_type (tree type, tree bottom) { inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom); outer = build_function_type (inner, TYPE_ARG_TYPES (type)); - outer = apply_memfn_quals (outer, type_memfn_quals (type)); + outer = apply_memfn_quals (outer, + type_memfn_quals (type), + type_memfn_rqual (type)); } else if (TREE_CODE (type) == METHOD_TYPE) { @@ -1604,7 +1634,7 @@ comdat_linkage (tree decl) if (flag_weak) make_decl_one_only (decl, cxx_comdat_group (decl)); else if (TREE_CODE (decl) == FUNCTION_DECL - || (TREE_CODE (decl) == VAR_DECL && DECL_ARTIFICIAL (decl))) + || (VAR_P (decl) && DECL_ARTIFICIAL (decl))) /* We can just emit function and compiler-generated variables statically; having multiple copies is (for the most part) only a waste of space. @@ -1675,11 +1705,12 @@ maybe_make_one_only (tree decl) { make_decl_one_only (decl, cxx_comdat_group (decl)); - if (TREE_CODE (decl) == VAR_DECL) + if (VAR_P (decl)) { + struct varpool_node *node = varpool_node_for_decl (decl); DECL_COMDAT (decl) = 1; /* Mark it needed so we don't forget to emit it. */ - mark_decl_referenced (decl); + node->symbol.forced_by_abi = true; TREE_USED (decl) = 1; } } @@ -1777,7 +1808,7 @@ import_export_class (tree ctype) static bool var_finalized_p (tree var) { - return varpool_node_for_decl (var)->finalized; + return varpool_node_for_decl (var)->symbol.definition; } /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason, @@ -1787,7 +1818,22 @@ void mark_needed (tree decl) { TREE_USED (decl) = 1; - mark_decl_referenced (decl); + if (TREE_CODE (decl) == FUNCTION_DECL) + { + /* Extern inline functions don't become needed when referenced. + If we know a method will be emitted in other TU and no new + functions can be marked reachable, just use the external + definition. */ + struct cgraph_node *node = cgraph_get_create_node (decl); + node->symbol.forced_by_abi = true; + } + else if (TREE_CODE (decl) == VAR_DECL) + { + struct varpool_node *node = varpool_node_for_decl (decl); + /* C++ frontend use mark_decl_references to force COMDAT variables + to be output that might appear dead otherwise. */ + node->symbol.forced_by_abi = true; + } } /* DECL is either a FUNCTION_DECL or a VAR_DECL. This function @@ -1799,8 +1845,7 @@ mark_needed (tree decl) bool decl_needed_p (tree decl) { - gcc_assert (TREE_CODE (decl) == VAR_DECL - || TREE_CODE (decl) == FUNCTION_DECL); + gcc_assert (VAR_OR_FUNCTION_DECL_P (decl)); /* This function should only be called at the end of the translation unit. We cannot be sure of whether or not something will be COMDAT until that point. */ @@ -1924,7 +1969,7 @@ min_vis_r (tree *tp, int *walk_subtrees, void *data) { *walk_subtrees = 0; } - else if (TAGGED_TYPE_P (*tp) + else if (OVERLOAD_TYPE_P (*tp) && !TREE_PUBLIC (TYPE_MAIN_DECL (*tp))) { *vis_p = VISIBILITY_ANON; @@ -2002,8 +2047,7 @@ constrain_visibility_for_template (tree decl, tree targs) STRIP_NOPS (arg); if (TREE_CODE (arg) == ADDR_EXPR) arg = TREE_OPERAND (arg, 0); - if (TREE_CODE (arg) == VAR_DECL - || TREE_CODE (arg) == FUNCTION_DECL) + if (VAR_OR_FUNCTION_DECL_P (arg)) { if (! TREE_PUBLIC (arg)) vis = VISIBILITY_ANON; @@ -2078,7 +2122,7 @@ determine_visibility (tree decl) /* Virtual tables have DECL_CONTEXT set to their associated class, so they are automatically handled above. */ - gcc_assert (TREE_CODE (decl) != VAR_DECL + gcc_assert (!VAR_P (decl) || !DECL_VTABLE_OR_VTT_P (decl)); if (DECL_FUNCTION_SCOPE_P (decl) && ! DECL_VISIBILITY_SPECIFIED (decl)) @@ -2115,7 +2159,7 @@ determine_visibility (tree decl) but have no TEMPLATE_INFO, so don't try to check it. */ use_template = 0; } - else if (TREE_CODE (decl) == VAR_DECL && DECL_TINFO_P (decl) + else if (VAR_P (decl) && DECL_TINFO_P (decl) && flag_visibility_ms_compat) { /* Under -fvisibility-ms-compat, types are visible by default, @@ -2129,7 +2173,7 @@ determine_visibility (tree decl) else DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; } - else if (TREE_CODE (decl) == VAR_DECL && DECL_TINFO_P (decl)) + else if (VAR_P (decl) && DECL_TINFO_P (decl)) { /* tinfo visibility is based on the type it's for. */ constrain_visibility @@ -2195,9 +2239,6 @@ determine_visibility (tree decl) && !lookup_attribute ("visibility", attribs)) { int depth = TMPL_ARGS_DEPTH (args); - int class_depth = 0; - if (class_type && CLASSTYPE_TEMPLATE_INFO (class_type)) - class_depth = TMPL_ARGS_DEPTH (CLASSTYPE_TI_ARGS (class_type)); if (DECL_VISIBILITY_SPECIFIED (decl)) { /* A class template member with explicit visibility @@ -2210,7 +2251,7 @@ determine_visibility (tree decl) constrain_visibility_for_template (decl, lev); } } - else if (depth > class_depth) + else if (PRIMARY_TEMPLATE_P (TI_TEMPLATE (tinfo))) /* Limit visibility based on its template arguments. */ constrain_visibility_for_template (decl, args); } @@ -2247,7 +2288,7 @@ determine_visibility (tree decl) symbol flags are updated. */ if ((DECL_VISIBILITY (decl) != orig_visibility || DECL_VISIBILITY_SPECIFIED (decl) != orig_visibility_specified) - && ((TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)) + && ((VAR_P (decl) && TREE_STATIC (decl)) || TREE_CODE (decl) == FUNCTION_DECL) && DECL_RTL_SET_P (decl)) make_decl_rtl (decl); @@ -2274,7 +2315,7 @@ determine_visibility_from_class (tree decl, tree class_type) /* Give the target a chance to override the visibility associated with DECL. */ - if (TREE_CODE (decl) == VAR_DECL + if (VAR_P (decl) && (DECL_TINFO_P (decl) || (DECL_VTABLE_OR_VTT_P (decl) /* Construction virtual tables are not exported because @@ -2419,8 +2460,7 @@ import_export_decl (tree decl) definition available in this translation unit. The following assertions check these conditions. */ - gcc_assert (TREE_CODE (decl) == FUNCTION_DECL - || TREE_CODE (decl) == VAR_DECL); + gcc_assert (VAR_OR_FUNCTION_DECL_P (decl)); /* Any code that creates entities with TREE_PUBLIC cleared should also set DECL_INTERFACE_KNOWN. */ gcc_assert (TREE_PUBLIC (decl)); @@ -2451,7 +2491,7 @@ import_export_decl (tree decl) { /* The repository indicates that this entity should be defined here. Make sure the back end honors that request. */ - if (TREE_CODE (decl) == VAR_DECL) + if (VAR_P (decl)) mark_needed (decl); else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl) || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl)) @@ -2472,7 +2512,7 @@ import_export_decl (tree decl) /* We have already decided what to do with this DECL; there is no need to check anything further. */ ; - else if (TREE_CODE (decl) == VAR_DECL && DECL_VTABLE_OR_VTT_P (decl)) + else if (VAR_P (decl) && DECL_VTABLE_OR_VTT_P (decl)) { class_type = DECL_CONTEXT (decl); import_export_class (class_type); @@ -2538,7 +2578,7 @@ import_export_decl (tree decl) else comdat_p = true; } - else if (TREE_CODE (decl) == VAR_DECL && DECL_TINFO_P (decl)) + else if (VAR_P (decl) && DECL_TINFO_P (decl)) { tree type = TREE_TYPE (DECL_NAME (decl)); if (CLASS_TYPE_P (type)) @@ -2576,8 +2616,7 @@ import_export_decl (tree decl) else comdat_p = true; } - else if (DECL_TEMPLATE_INSTANTIATION (decl) - || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)) + else if (DECL_TEMPLOID_INSTANTIATION (decl)) { /* DECL is an implicit instantiation of a function or static data member. */ @@ -3271,7 +3310,7 @@ fix_temporary_vars_context_r (tree *node, tree var; for (var = BIND_EXPR_VARS (*node); var; var = DECL_CHAIN (var)) - if (TREE_CODE (var) == VAR_DECL + if (VAR_P (var) && !DECL_NAME (var) && DECL_ARTIFICIAL (var) && !DECL_CONTEXT (var)) @@ -3520,7 +3559,7 @@ prune_vars_needing_no_initialization (tree *vars) } /* The only things that can be initialized are variables. */ - gcc_assert (TREE_CODE (decl) == VAR_DECL); + gcc_assert (VAR_P (decl)); /* If this object is not defined, we don't need to do anything here. */ @@ -3669,8 +3708,7 @@ collect_candidates_for_java_method_aliases (void) { tree fndecl = node->symbol.decl; - if (DECL_CONTEXT (fndecl) - && TYPE_P (DECL_CONTEXT (fndecl)) + if (DECL_CLASS_SCOPE_P (fndecl) && TYPE_FOR_JAVA (DECL_CONTEXT (fndecl)) && TARGET_USE_LOCAL_THUNK_ALIAS_P (fndecl)) { @@ -3800,7 +3838,7 @@ decl_defined_p (tree decl) return (DECL_INITIAL (decl) != NULL_TREE); else { - gcc_assert (TREE_CODE (decl) == VAR_DECL); + gcc_assert (VAR_P (decl)); return !DECL_EXTERNAL (decl); } } @@ -3842,7 +3880,7 @@ bool decl_maybe_constant_var_p (tree decl) { tree type = TREE_TYPE (decl); - if (TREE_CODE (decl) != VAR_DECL) + if (!VAR_P (decl)) return false; if (DECL_DECLARED_CONSTEXPR_P (decl)) return true; @@ -4183,8 +4221,8 @@ cp_write_global_declarations (void) struct cgraph_node *node, *next; node = cgraph_get_node (decl); - if (node->same_body_alias) - node = cgraph_alias_aliased_node (node); + if (node->symbol.cpp_implicit_alias) + node = cgraph_alias_target (node); cgraph_for_node_and_aliases (node, clear_decl_external, NULL, true); @@ -4206,7 +4244,7 @@ cp_write_global_declarations (void) if (!DECL_EXTERNAL (decl) && decl_needed_p (decl) && !TREE_ASM_WRITTEN (decl) - && !cgraph_get_node (decl)->local.finalized) + && !cgraph_get_node (decl)->symbol.definition) { /* We will output the function; no longer consider it in this loop. */ @@ -4451,7 +4489,7 @@ check_default_args (tree x) { if (TREE_PURPOSE (arg)) saw_def = true; - else if (saw_def) + else if (saw_def && !PACK_EXPANSION_P (TREE_VALUE (arg))) { error ("default argument missing for parameter %P of %q+#D", i, x); TREE_PURPOSE (arg) = error_mark_node; @@ -4481,7 +4519,7 @@ possibly_inlined_p (tree decl) wrong, true otherwise. */ bool -mark_used (tree decl) +mark_used (tree decl, tsubst_flags_t complain) { /* If DECL is a BASELINK for a single function, then treat it just like the DECL for the function. Otherwise, if the BASELINK is @@ -4519,22 +4557,26 @@ mark_used (tree decl) return false; } } - error ("use of deleted function %qD", decl); - if (!maybe_explain_implicit_delete (decl)) - error_at (DECL_SOURCE_LOCATION (decl), "declared here"); + if (complain & tf_error) + { + error ("use of deleted function %qD", decl); + if (!maybe_explain_implicit_delete (decl)) + inform (DECL_SOURCE_LOCATION (decl), "declared here"); + } return false; } /* We can only check DECL_ODR_USED on variables or functions with DECL_LANG_SPECIFIC set, and these are also the only decls that we might need special handling for. */ - if ((TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL) + if (!VAR_OR_FUNCTION_DECL_P (decl) || DECL_LANG_SPECIFIC (decl) == NULL || DECL_THUNK_P (decl)) { if (!processing_template_decl && type_uses_auto (TREE_TYPE (decl))) { - error ("use of %qD before deduction of %<auto%>", decl); + if (complain & tf_error) + error ("use of %qD before deduction of %<auto%>", decl); return false; } return true; @@ -4566,7 +4608,7 @@ mark_used (tree decl) if ((decl_maybe_constant_var_p (decl) || (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_CONSTEXPR_P (decl)) - || type_uses_auto (TREE_TYPE (decl))) + || undeduced_auto_decl (decl)) && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl) && !uses_template_parms (DECL_TI_ARGS (decl))) @@ -4589,11 +4631,7 @@ mark_used (tree decl) && uses_template_parms (DECL_TI_ARGS (decl))) return true; - if (type_uses_auto (TREE_TYPE (decl))) - { - error ("use of %qD before deduction of %<auto%>", decl); - return false; - } + require_deduced_type (decl); /* If we don't need a value, then we don't need to synthesize DECL. */ if (cp_unevaluated_operand != 0) @@ -4664,7 +4702,7 @@ mark_used (tree decl) /* If this is a synthesized method we don't need to do the instantiation test below. */ } - else if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL) + else if (VAR_OR_FUNCTION_DECL_P (decl) && DECL_TEMPLATE_INFO (decl) && (!DECL_EXPLICIT_INSTANTIATION (decl) || always_instantiate_p (decl))) @@ -4687,4 +4725,10 @@ mark_used (tree decl) return true; } +bool +mark_used (tree decl) +{ + return mark_used (decl, tf_warning_or_error); +} + #include "gt-cp-decl2.h" diff --git a/gcc/cp/error.c b/gcc/cp/error.c index c2bf54dcb2c..a8f52cda0ae 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -78,6 +78,7 @@ static void dump_aggr_init_expr_args (tree, int, bool); static void dump_expr_list (tree, int); static void dump_global_iord (tree); static void dump_parameters (tree, int); +static void dump_ref_qualifier (tree, int); static void dump_exception_spec (tree, int); static void dump_template_argument (tree, int); static void dump_template_argument_list (tree, int); @@ -655,7 +656,7 @@ dump_aggr_type (tree t, int flags) else pp_printf (pp_base (cxx_pp), M_("<anonymous %s>"), variety); } - else if (LAMBDA_TYPE_P (name)) + else if (LAMBDA_TYPE_P (t)) { /* A lambda's "type" is essentially its signature. */ pp_string (cxx_pp, M_("<lambda")); @@ -708,7 +709,7 @@ dump_type_prefix (tree t, int flags) pp_c_attributes_display (pp_c_base (cxx_pp), TYPE_ATTRIBUTES (sub)); } - if (TREE_CODE (t) == POINTER_TYPE) + if (TYPE_PTR_P (t)) pp_character(cxx_pp, '*'); else if (TREE_CODE (t) == REFERENCE_TYPE) { @@ -828,10 +829,9 @@ dump_type_suffix (tree t, int flags) anyway; they may in g++, but we'll just pretend otherwise. */ dump_parameters (arg, flags & ~TFF_FUNCTION_DEFAULT_ARGUMENTS); - if (TREE_CODE (t) == METHOD_TYPE) - pp_cxx_cv_qualifier_seq (cxx_pp, class_of_this_parm (t)); - else - pp_cxx_cv_qualifier_seq (cxx_pp, t); + pp_base (cxx_pp)->padding = pp_before; + pp_cxx_cv_qualifiers (cxx_pp, type_memfn_quals (t)); + dump_ref_qualifier (t, flags); dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), flags); dump_type_suffix (TREE_TYPE (t), flags); break; @@ -848,14 +848,24 @@ dump_type_suffix (tree t, int flags) pp_character (cxx_pp, '0'); else if (host_integerp (max, 0)) pp_wide_integer (cxx_pp, tree_low_cst (max, 0) + 1); - else if (TREE_CODE (max) == MINUS_EXPR) - dump_expr (TREE_OPERAND (max, 0), - flags & ~TFF_EXPR_IN_PARENS); else - dump_expr (fold_build2_loc (input_location, - PLUS_EXPR, dtype, max, - build_int_cst (dtype, 1)), - flags & ~TFF_EXPR_IN_PARENS); + { + STRIP_NOPS (max); + if (TREE_CODE (max) == SAVE_EXPR) + max = TREE_OPERAND (max, 0); + if (TREE_CODE (max) == MINUS_EXPR + || TREE_CODE (max) == PLUS_EXPR) + { + max = TREE_OPERAND (max, 0); + while (CONVERT_EXPR_P (max)) + max = TREE_OPERAND (max, 0); + } + else + max = fold_build2_loc (input_location, + PLUS_EXPR, dtype, max, + build_int_cst (dtype, 1)); + dump_expr (max, flags & ~TFF_EXPR_IN_PARENS); + } } pp_cxx_right_bracket (cxx_pp); dump_type_suffix (TREE_TYPE (t), flags); @@ -916,7 +926,7 @@ dump_simple_decl (tree t, tree type, int flags) { if (flags & TFF_DECL_SPECIFIERS) { - if (TREE_CODE (t) == VAR_DECL + if (VAR_P (t) && DECL_DECLARED_CONSTEXPR_P (t)) pp_cxx_ws_string (cxx_pp, "constexpr"); dump_type_prefix (type, flags & ~TFF_UNQUALIFIED_NAME); @@ -933,7 +943,16 @@ dump_simple_decl (tree t, tree type, int flags) && TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (t))) pp_string (cxx_pp, "..."); if (DECL_NAME (t)) - dump_decl (DECL_NAME (t), flags); + { + if (TREE_CODE (t) == FIELD_DECL && DECL_NORMAL_CAPTURE_P (t)) + { + pp_character (cxx_pp, '<'); + pp_string (cxx_pp, IDENTIFIER_POINTER (DECL_NAME (t)) + 2); + pp_string (cxx_pp, " capture>"); + } + else + dump_decl (DECL_NAME (t), flags); + } else pp_string (cxx_pp, M_("<anonymous>")); if (flags & TFF_DECL_SPECIFIERS) @@ -1052,6 +1071,17 @@ dump_decl (tree t, int flags) pp_cxx_right_bracket (cxx_pp); break; + case ARRAY_NOTATION_REF: + dump_decl (ARRAY_NOTATION_ARRAY (t), flags | TFF_EXPR_IN_PARENS); + pp_cxx_left_bracket (cxx_pp); + dump_decl (ARRAY_NOTATION_START (t), flags | TFF_EXPR_IN_PARENS); + pp_string (cxx_pp, ":"); + dump_decl (ARRAY_NOTATION_LENGTH (t), flags | TFF_EXPR_IN_PARENS); + pp_string (cxx_pp, ":"); + dump_decl (ARRAY_NOTATION_STRIDE (t), flags | TFF_EXPR_IN_PARENS); + pp_cxx_right_bracket (cxx_pp); + break; + /* So that we can do dump_decl on an aggr type. */ case RECORD_TYPE: case UNION_TYPE: @@ -1249,7 +1279,7 @@ dump_template_decl (tree t, int flags) ((flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME | (flags & TFF_DECL_SPECIFIERS ? TFF_CLASS_KEY_OR_ENUM : 0))); else if (DECL_TEMPLATE_RESULT (t) - && (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL + && (VAR_P (DECL_TEMPLATE_RESULT (t)) /* Alias template. */ || DECL_TYPE_TEMPLATE_P (t))) dump_decl (DECL_TEMPLATE_RESULT (t), flags | TFF_TEMPLATE_NAME); @@ -1403,7 +1433,10 @@ dump_function_decl (tree t, int flags) show_return = !DECL_CONV_FN_P (t) && !DECL_CONSTRUCTOR_P (t) && !DECL_DESTRUCTOR_P (t); if (show_return) - dump_type_prefix (TREE_TYPE (fntype), flags); + { + tree ret = fndecl_declared_return_type (t); + dump_type_prefix (ret, flags); + } /* Print the function name. */ if (!do_outer_scope) @@ -1426,6 +1459,7 @@ dump_function_decl (tree t, int flags) { pp_base (cxx_pp)->padding = pp_before; pp_cxx_cv_qualifier_seq (cxx_pp, class_of_this_parm (fntype)); + dump_ref_qualifier (fntype, flags); } if (flags & TFF_EXCEPTION_SPECIFICATION) @@ -1438,7 +1472,8 @@ dump_function_decl (tree t, int flags) dump_type_suffix (TREE_TYPE (fntype), flags); /* If T is a template instantiation, dump the parameter binding. */ - if (template_parms != NULL_TREE && template_args != NULL_TREE) + if (template_parms != NULL_TREE && template_args != NULL_TREE + && !(flags & TFF_NO_TEMPLATE_BINDINGS)) { pp_cxx_whitespace (cxx_pp); pp_cxx_left_bracket (cxx_pp); @@ -1507,6 +1542,21 @@ dump_parameters (tree parmtypes, int flags) pp_cxx_right_paren (cxx_pp); } +/* Print ref-qualifier of a FUNCTION_TYPE or METHOD_TYPE. FLAGS are ignored. */ + +static void +dump_ref_qualifier (tree t, int flags ATTRIBUTE_UNUSED) +{ + if (FUNCTION_REF_QUALIFIED (t)) + { + pp_base (cxx_pp)->padding = pp_before; + if (FUNCTION_RVALUE_QUALIFIED (t)) + pp_cxx_ws_string (cxx_pp, "&&"); + else + pp_cxx_ws_string (cxx_pp, "&"); + } +} + /* Print an exception specification. T is the exception specification. */ static void @@ -1783,6 +1833,8 @@ resolve_virtual_fun_from_obj_type_ref (tree ref) static void dump_expr (tree t, int flags) { + tree op; + if (t == 0) return; @@ -1986,7 +2038,7 @@ dump_expr (tree t, int flags) case COMPONENT_REF: { tree ob = TREE_OPERAND (t, 0); - if (TREE_CODE (ob) == INDIRECT_REF) + if (INDIRECT_REF_P (ob)) { ob = TREE_OPERAND (ob, 0); if (TREE_CODE (ob) != PARM_DECL @@ -2016,6 +2068,17 @@ dump_expr (tree t, int flags) pp_cxx_right_bracket (cxx_pp); break; + case ARRAY_NOTATION_REF: + dump_expr (ARRAY_NOTATION_ARRAY (t), flags | TFF_EXPR_IN_PARENS); + pp_cxx_left_bracket (cxx_pp); + dump_expr (ARRAY_NOTATION_START (t), flags | TFF_EXPR_IN_PARENS); + pp_string (cxx_pp, ":"); + dump_expr (ARRAY_NOTATION_LENGTH (t), flags | TFF_EXPR_IN_PARENS); + pp_string (cxx_pp, ":"); + dump_expr (ARRAY_NOTATION_STRIDE (t), flags | TFF_EXPR_IN_PARENS); + pp_cxx_right_bracket (cxx_pp); + break; + case UNARY_PLUS_EXPR: dump_unary_op ("+", t, flags); break; @@ -2106,7 +2169,7 @@ dump_expr (tree t, int flags) { tree next = TREE_TYPE (TREE_TYPE (t)); - while (TREE_CODE (next) == POINTER_TYPE) + while (TYPE_PTR_P (next)) next = TREE_TYPE (next); if (TREE_CODE (next) == FUNCTION_TYPE) @@ -2241,7 +2304,7 @@ dump_expr (tree t, int flags) } else { - if (TREE_CODE (ob) == INDIRECT_REF) + if (INDIRECT_REF_P (ob)) { dump_expr (TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS); pp_cxx_arrow (cxx_pp); @@ -2316,14 +2379,20 @@ dump_expr (tree t, int flags) gcc_assert (TREE_CODE (t) == ALIGNOF_EXPR); pp_cxx_ws_string (cxx_pp, "__alignof__"); } + op = TREE_OPERAND (t, 0); + if (PACK_EXPANSION_P (op)) + { + pp_string (cxx_pp, "..."); + op = PACK_EXPANSION_PATTERN (op); + } pp_cxx_whitespace (cxx_pp); pp_cxx_left_paren (cxx_pp); if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t)) - dump_type (TREE_TYPE (TREE_OPERAND (t, 0)), flags); + dump_type (TREE_TYPE (op), flags); else if (TYPE_P (TREE_OPERAND (t, 0))) - dump_type (TREE_OPERAND (t, 0), flags); + dump_type (op, flags); else - dump_expr (TREE_OPERAND (t, 0), flags); + dump_expr (op, flags); pp_cxx_right_paren (cxx_pp); break; @@ -2498,6 +2567,12 @@ dump_expr (tree t, int flags) pp_string (cxx_pp, M_("<lambda>")); break; + case PAREN_EXPR: + pp_cxx_left_paren (cxx_pp); + dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS); + pp_cxx_right_paren (cxx_pp); + break; + /* This list is incomplete, but should suffice for now. It is very important that `sorry' does not call `report_error_function'. That could cause an infinite loop. */ @@ -2847,7 +2922,8 @@ subst_to_string (tree p) tree decl = TREE_PURPOSE (p); tree targs = TREE_VALUE (p); tree tparms = DECL_TEMPLATE_PARMS (decl); - int flags = TFF_DECL_SPECIFIERS|TFF_TEMPLATE_HEADER; + int flags = (TFF_DECL_SPECIFIERS|TFF_TEMPLATE_HEADER + |TFF_NO_TEMPLATE_BINDINGS); if (p == NULL_TREE) return ""; @@ -2918,7 +2994,7 @@ cp_print_error_function (diagnostic_context *context, const char *file = LOCATION_FILE (diagnostic->location); tree abstract_origin = diagnostic_abstract_origin (diagnostic); char *new_prefix = (file && abstract_origin == NULL) - ? file_name_as_prefix (file) : NULL; + ? file_name_as_prefix (context, file) : NULL; pp_base_set_prefix (context->printer, new_prefix); @@ -2992,14 +3068,14 @@ cp_print_error_function (diagnostic_context *context, { if (context->show_column && s.column != 0) pp_printf (context->printer, - _(" inlined from %qs at %s:%d:%d"), + _(" inlined from %qs at %r%s:%d:%d%R"), cxx_printable_name_translate (fndecl, 2), - s.file, s.line, s.column); + "locus", s.file, s.line, s.column); else pp_printf (context->printer, - _(" inlined from %qs at %s:%d"), + _(" inlined from %qs at %r%s:%d%R"), cxx_printable_name_translate (fndecl, 2), - s.file, s.line); + "locus", s.file, s.line); } else @@ -3081,11 +3157,11 @@ print_instantiation_partial_context_line (diagnostic_context *context, xloc = expand_location (loc); if (context->show_column) - pp_verbatim (context->printer, _("%s:%d:%d: "), - xloc.file, xloc.line, xloc.column); + pp_verbatim (context->printer, _("%r%s:%d:%d:%R "), + "locus", xloc.file, xloc.line, xloc.column); else - pp_verbatim (context->printer, _("%s:%d: "), - xloc.file, xloc.line); + pp_verbatim (context->printer, _("%r%s:%d:%R "), + "locus", xloc.file, xloc.line); if (t != NULL) { @@ -3159,14 +3235,16 @@ print_instantiation_partial_context (diagnostic_context *context, xloc = expand_location (loc); if (context->show_column) pp_verbatim (context->printer, - _("%s:%d:%d: [ skipping %d instantiation contexts, " - "use -ftemplate-backtrace-limit=0 to disable ]\n"), - xloc.file, xloc.line, xloc.column, skip); + _("%r%s:%d:%d:%R [ skipping %d instantiation " + "contexts, use -ftemplate-backtrace-limit=0 to " + "disable ]\n"), + "locus", xloc.file, xloc.line, xloc.column, skip); else pp_verbatim (context->printer, - _("%s:%d: [ skipping %d instantiation contexts, " - "use -ftemplate-backtrace-limit=0 to disable ]\n"), - xloc.file, xloc.line, skip); + _("%r%s:%d:%R [ skipping %d instantiation " + "contexts, use -ftemplate-backtrace-limit=0 to " + "disable ]\n"), + "locus", xloc.file, xloc.line, skip); do { loc = t->locus; @@ -3228,12 +3306,12 @@ maybe_print_constexpr_context (diagnostic_context *context) const char *s = expr_as_string (t, 0); if (context->show_column) pp_verbatim (context->printer, - _("%s:%d:%d: in constexpr expansion of %qs"), - xloc.file, xloc.line, xloc.column, s); + _("%r%s:%d:%d:%R in constexpr expansion of %qs"), + "locus", xloc.file, xloc.line, xloc.column, s); else pp_verbatim (context->printer, - _("%s:%d: in constexpr expansion of %qs"), - xloc.file, xloc.line, s); + _("%r%s:%d:%R in constexpr expansion of %qs"), + "locus", xloc.file, xloc.line, s); pp_base_newline (context->printer); } } @@ -3275,8 +3353,8 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec, case 'D': { tree temp = next_tree; - if (DECL_P (temp) - && DECL_DEBUG_EXPR_IS_FROM (temp) && DECL_DEBUG_EXPR (temp)) + if (VAR_P (temp) + && DECL_HAS_DEBUG_EXPR_P (temp)) { temp = DECL_DEBUG_EXPR (temp); if (!DECL_P (temp)) @@ -3348,7 +3426,7 @@ maybe_warn_cpp0x (cpp0x_warn_str str) break; case CPP0X_AUTO: pedwarn (input_location, 0, - "C++0x auto only available with -std=c++11 or -std=gnu++11"); + "C++11 auto only available with -std=c++11 or -std=gnu++11"); break; case CPP0X_SCOPED_ENUMS: pedwarn (input_location, 0, @@ -3394,6 +3472,11 @@ maybe_warn_cpp0x (cpp0x_warn_str str) "c++11 attributes " "only available with -std=c++11 or -std=gnu++11"); break; + case CPP0X_REF_QUALIFIER: + pedwarn (input_location, 0, + "ref-qualifiers " + "only available with -std=c++11 or -std=gnu++11"); + break; default: gcc_unreachable (); } diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 216ec103f52..be003d2994b 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -277,7 +277,7 @@ push_eh_cleanup (tree type) static bool decl_is_java_type (tree decl, int err) { - bool r = (TREE_CODE (decl) == POINTER_TYPE + bool r = (TYPE_PTR_P (decl) && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE && TYPE_FOR_JAVA (TREE_TYPE (decl))); @@ -490,6 +490,7 @@ expand_start_catch_block (tree decl) decl = error_mark_node; type = prepare_eh_type (TREE_TYPE (decl)); + mark_used (eh_type_info (type)); } else type = NULL_TREE; @@ -828,7 +829,7 @@ build_throw (tree exp) treated as an rvalue for the purposes of overload resolution to favor move constructors over copy constructors. */ if (/* Must be a local, automatic variable. */ - TREE_CODE (exp) == VAR_DECL + VAR_P (exp) && DECL_CONTEXT (exp) == current_function_decl && ! TREE_STATIC (exp) /* The variable must not have the `volatile' qualifier. */ @@ -930,7 +931,7 @@ complete_ptr_ref_or_void_ptr_p (tree type, tree from) return 0; /* Or a pointer or ref to one, or cv void *. */ - is_ptr = TREE_CODE (type) == POINTER_TYPE; + is_ptr = TYPE_PTR_P (type); if (is_ptr || TREE_CODE (type) == REFERENCE_TYPE) { tree core = TREE_TYPE (type); @@ -972,16 +973,8 @@ is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw) /* 10.4/3 An abstract class shall not be used as a parameter type, as a function return type or as type of an explicit conversion. */ - else if (ABSTRACT_CLASS_TYPE_P (type)) - { - if (is_throw) - error ("expression %qE of abstract class type %qT cannot " - "be used in throw-expression", expr, type); - else - error ("cannot declare catch parameter to be of abstract " - "class type %qT", type); - return false; - } + else if (abstract_virtuals_error (is_throw ? ACU_THROW : ACU_CATCH, type)) + return false; else if (!is_throw && TREE_CODE (type) == REFERENCE_TYPE && TYPE_REF_IS_RVALUE (type)) @@ -990,6 +983,16 @@ is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw) "reference type %qT", type); return false; } + else if (variably_modified_type_p (type, NULL_TREE)) + { + if (is_throw) + error ("cannot throw expression of type %qT because it involves " + "types of variable size", type); + else + error ("cannot catch type %qT because it involves types of " + "variable size", type); + return false; + } return true; } @@ -1034,7 +1037,7 @@ can_convert_eh (tree to, tree from) to = non_reference (to); from = non_reference (from); - if (TREE_CODE (to) == POINTER_TYPE && TREE_CODE (from) == POINTER_TYPE) + if (TYPE_PTR_P (to) && TYPE_PTR_P (from)) { to = TREE_TYPE (to); from = TREE_TYPE (from); @@ -1042,7 +1045,7 @@ can_convert_eh (tree to, tree from) if (! at_least_as_qualified_p (to, from)) return 0; - if (TREE_CODE (to) == VOID_TYPE) + if (VOID_TYPE_P (to)) return 1; /* Else fall through. */ diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c index ffd18ca6785..f15b049baf8 100644 --- a/gcc/cp/expr.c +++ b/gcc/cp/expr.c @@ -43,6 +43,10 @@ cplus_expand_constant (tree cst) /* Find the member. */ member = PTRMEM_CST_MEMBER (cst); + /* We can't lower this until the class is complete. */ + if (!COMPLETE_TYPE_P (DECL_CONTEXT (member))) + return cst; + if (TREE_CODE (member) == FIELD_DECL) { /* Find the offset for the field. */ diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index 083372849b9..3e018e8e84c 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -230,8 +230,8 @@ make_friend_class (tree type, tree friend_type, bool complain) (possibly cv-qualified) class type, that class is declared as a friend; otherwise, the friend declaration is ignored. - So don't complain in C++0x mode. */ - if (cxx_dialect < cxx0x) + So don't complain in C++11 mode. */ + if (cxx_dialect < cxx11) pedwarn (input_location, complain ? 0 : OPT_Wpedantic, "invalid type %qT declared %<friend%>", friend_type); return; @@ -485,8 +485,7 @@ do_friend (tree ctype, tree declarator, tree decl, to be a friend, so we do lookup here even if CTYPE is in the process of being defined. */ if (class_template_depth - || COMPLETE_TYPE_P (ctype) - || (CLASS_TYPE_P (ctype) && TYPE_BEING_DEFINED (ctype))) + || COMPLETE_OR_OPEN_TYPE_P (ctype)) { if (DECL_TEMPLATE_INFO (decl)) /* DECL is a template specialization. No need to diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 697f11ff52e..4edd150d913 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -634,7 +634,12 @@ perform_member_init (tree member, tree init) init = build_x_compound_expr_from_list (init, ELK_MEM_INIT, tf_warning_or_error); if (TREE_TYPE (init) != type) - init = digest_init (type, init, tf_warning_or_error); + { + if (BRACE_ENCLOSED_INITIALIZER_P (init) + && CP_AGGREGATE_TYPE_P (type)) + init = reshape_init (type, init, tf_warning_or_error); + init = digest_init (type, init, tf_warning_or_error); + } if (init == error_mark_node) return; /* A FIELD_DECL doesn't really have a suitable lifetime, but @@ -909,13 +914,12 @@ sort_mem_initializers (tree t, tree mem_inits) Here we also splice out uninitialized union members. */ if (uses_unions_p) { - tree last_field = NULL_TREE; + tree *last_p = NULL; tree *p; for (p = &sorted_inits; *p; ) { tree field; tree ctx; - int done; init = *p; @@ -935,22 +939,25 @@ sort_mem_initializers (tree t, tree mem_inits) for (ctx = DECL_CONTEXT (field); !same_type_p (ctx, t); ctx = TYPE_CONTEXT (ctx)) - if (TREE_CODE (ctx) == UNION_TYPE) + if (TREE_CODE (ctx) == UNION_TYPE + || !ANON_AGGR_TYPE_P (ctx)) break; /* If this field is not a member of a union, skip it. */ if (TREE_CODE (ctx) != UNION_TYPE) goto next; - /* If this union member has no explicit initializer, splice - it out. */ - if (!TREE_VALUE (init)) + /* If this union member has no explicit initializer and no NSDMI, + splice it out. */ + if (TREE_VALUE (init) || DECL_INITIAL (field)) + /* OK. */; + else goto splice; /* It's only an error if we have two initializers for the same union type. */ - if (!last_field) + if (!last_p) { - last_field = field; + last_p = p; goto next; } @@ -962,41 +969,23 @@ sort_mem_initializers (tree t, tree mem_inits) union { struct { int i; int j; }; }; initializing both `i' and `j' makes sense. */ - ctx = DECL_CONTEXT (field); - done = 0; - do - { - tree last_ctx; + ctx = common_enclosing_class (DECL_CONTEXT (field), + DECL_CONTEXT (TREE_PURPOSE (*last_p))); - last_ctx = DECL_CONTEXT (last_field); - while (1) - { - if (same_type_p (last_ctx, ctx)) - { - if (TREE_CODE (ctx) == UNION_TYPE) - error_at (DECL_SOURCE_LOCATION (current_function_decl), - "initializations for multiple members of %qT", - last_ctx); - done = 1; - break; - } - - if (same_type_p (last_ctx, t)) - break; - - last_ctx = TYPE_CONTEXT (last_ctx); - } - - /* If we've reached the outermost class, then we're - done. */ - if (same_type_p (ctx, t)) - break; - - ctx = TYPE_CONTEXT (ctx); + if (ctx && TREE_CODE (ctx) == UNION_TYPE) + { + /* A mem-initializer hides an NSDMI. */ + if (TREE_VALUE (init) && !TREE_VALUE (*last_p)) + *last_p = TREE_CHAIN (*last_p); + else if (TREE_VALUE (*last_p) && !TREE_VALUE (init)) + goto splice; + else + error_at (DECL_SOURCE_LOCATION (current_function_decl), + "initializations for multiple members of %qT", + ctx); } - while (!done); - last_field = field; + last_p = p; next: p = &TREE_CHAIN (*p); @@ -1131,7 +1120,7 @@ build_vtbl_address (tree binfo) /* Now compute the address to use when initializing the vptr. */ vtbl = unshare_expr (BINFO_VTABLE (binfo_for)); - if (TREE_CODE (vtbl) == VAR_DECL) + if (VAR_P (vtbl)) vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl); return vtbl; @@ -1293,7 +1282,7 @@ member_init_ok_or_else (tree field, tree type, tree member_name) member_name); return 0; } - if (TREE_CODE (field) == VAR_DECL) + if (VAR_P (field)) { error ("%q#D is a static data member; it can only be " "initialized at its definition", @@ -1416,7 +1405,7 @@ expand_member_init (tree name) } else { - if (TREE_CODE (name) == IDENTIFIER_NODE) + if (identifier_p (name)) field = lookup_field (current_class_type, name, 1, false); else field = name; @@ -1515,7 +1504,7 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) return stmt_expr; } - if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL) + if (VAR_P (exp) || TREE_CODE (exp) == PARM_DECL) /* Just know that we've seen something for this node. */ TREE_USED (exp) = 1; @@ -1728,7 +1717,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, in and expand the constructor. Constructors now come as TARGET_EXPRs. */ - if (init && TREE_CODE (exp) == VAR_DECL + if (init && VAR_P (exp) && COMPOUND_LITERAL_P (init)) { vec<tree, va_gc> *cleanups = NULL; @@ -1817,7 +1806,8 @@ get_type_value (tree name) @@ This function should be rewritten and placed in search.c. */ tree -build_offset_ref (tree type, tree member, bool address_p) +build_offset_ref (tree type, tree member, bool address_p, + tsubst_flags_t complain) { tree decl; tree basebinfo = NULL_TREE; @@ -1841,7 +1831,8 @@ build_offset_ref (tree type, tree member, bool address_p) type = TYPE_MAIN_VARIANT (type); if (!COMPLETE_OR_OPEN_TYPE_P (complete_type (type))) { - error ("incomplete type %qT does not have member %qD", type, member); + if (complain & tf_error) + error ("incomplete type %qT does not have member %qD", type, member); return error_mark_node; } @@ -1849,12 +1840,13 @@ build_offset_ref (tree type, tree member, bool address_p) processing. */ if (TREE_CODE (member) == TYPE_DECL) return member; - if (TREE_CODE (member) == VAR_DECL || TREE_CODE (member) == CONST_DECL) + if (VAR_P (member) || TREE_CODE (member) == CONST_DECL) return convert_from_reference (member); if (TREE_CODE (member) == FIELD_DECL && DECL_C_BIT_FIELD (member)) { - error ("invalid pointer to bit-field %qD", member); + if (complain & tf_error) + error ("invalid pointer to bit-field %qD", member); return error_mark_node; } @@ -1883,10 +1875,10 @@ build_offset_ref (tree type, tree member, bool address_p) if (address_p && DECL_P (t) && DECL_NONSTATIC_MEMBER_P (t)) perform_or_defer_access_check (TYPE_BINFO (type), t, t, - tf_warning_or_error); + complain); else perform_or_defer_access_check (basebinfo, t, t, - tf_warning_or_error); + complain); if (DECL_STATIC_FUNCTION_P (t)) return t; @@ -1900,7 +1892,7 @@ build_offset_ref (tree type, tree member, bool address_p) check_accessibility_of_qualified_id in case it is a pointer to non-static member. */ perform_or_defer_access_check (TYPE_BINFO (type), member, member, - tf_warning_or_error); + complain); if (!address_p) { @@ -1932,15 +1924,17 @@ build_offset_ref (tree type, tree member, bool address_p) if (flag_ms_extensions) { PTRMEM_OK_P (member) = 1; - return cp_build_addr_expr (member, tf_warning_or_error); + return cp_build_addr_expr (member, complain); } - error ("invalid use of non-static member function %qD", - TREE_OPERAND (member, 1)); + if (complain & tf_error) + error ("invalid use of non-static member function %qD", + TREE_OPERAND (member, 1)); return error_mark_node; } else if (TREE_CODE (member) == FIELD_DECL) { - error ("invalid use of non-static data member %qD", member); + if (complain & tf_error) + error ("invalid use of non-static data member %qD", member); return error_mark_node; } return member; @@ -1964,7 +1958,7 @@ constant_value_1 (tree decl, bool integral_p, bool return_aggregate_cst_ok_p) while (TREE_CODE (decl) == CONST_DECL || (integral_p ? decl_constant_var_p (decl) - : (TREE_CODE (decl) == VAR_DECL + : (VAR_P (decl) && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl))))) { tree init; @@ -2160,6 +2154,35 @@ diagnose_uninitialized_cst_or_ref_member (tree type, bool using_new, bool compla return diagnose_uninitialized_cst_or_ref_member_1 (type, type, using_new, complain); } +/* Call __cxa_bad_array_new_length to indicate that the size calculation + overflowed. Pretend it returns sizetype so that it plays nicely in the + COND_EXPR. */ + +tree +throw_bad_array_new_length (void) +{ + tree fn = get_identifier ("__cxa_throw_bad_array_new_length"); + if (!get_global_value_if_present (fn, &fn)) + fn = push_throw_library_fn (fn, build_function_type_list (sizetype, + NULL_TREE)); + + return build_cxx_call (fn, 0, NULL, tf_warning_or_error); +} + +/* Call __cxa_bad_array_length to indicate that there were too many + initializers. */ + +tree +throw_bad_array_length (void) +{ + tree fn = get_identifier ("__cxa_throw_bad_array_length"); + if (!get_global_value_if_present (fn, &fn)) + fn = push_throw_library_fn (fn, build_function_type_list (void_type_node, + NULL_TREE)); + + return build_cxx_call (fn, 0, NULL, tf_warning_or_error); +} + /* Generate code for a new-expression, including calling the "operator new" function, initializing the object, and, if an exception occurs during construction, cleaning up. The arguments are as for @@ -2294,14 +2317,14 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, return error_mark_node; } - if (TREE_CODE (elt_type) == VOID_TYPE) + if (VOID_TYPE_P (elt_type)) { if (complain & tf_error) error ("invalid type %<void%> for new"); return error_mark_node; } - if (abstract_virtuals_error_sfinae (NULL_TREE, elt_type, complain)) + if (abstract_virtuals_error_sfinae (ACU_NEW, elt_type, complain)) return error_mark_node; is_initialized = (type_build_ctor_call (elt_type) || *init != NULL); @@ -2399,7 +2422,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, this now, since PLACEMENT will change in the calls below. */ placement_first = NULL_TREE; if (vec_safe_length (*placement) == 1 - && (TREE_CODE (TREE_TYPE ((**placement)[0])) == POINTER_TYPE)) + && (TYPE_PTR_P (TREE_TYPE ((**placement)[0])))) placement_first = (**placement)[0]; /* Allocate the object. */ @@ -2462,9 +2485,12 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, outer_nelts_check = NULL_TREE; } /* Perform the overflow check. */ + tree errval = TYPE_MAX_VALUE (sizetype); + if (cxx_dialect >= cxx11) + errval = throw_bad_array_new_length (); if (outer_nelts_check != NULL_TREE) size = fold_build3 (COND_EXPR, sizetype, outer_nelts_check, - size, TYPE_MAX_VALUE (sizetype)); + size, errval); /* Create the argument list. */ vec_safe_insert (*placement, 0, size); /* Do name-lookup to find the appropriate operator. */ @@ -2523,7 +2549,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, && TREE_CODE (alloc_call) == CALL_EXPR && call_expr_nargs (alloc_call) == 2 && TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (alloc_call, 0))) == INTEGER_TYPE - && TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (alloc_call, 1))) == POINTER_TYPE) + && TYPE_PTR_P (TREE_TYPE (CALL_EXPR_ARG (alloc_call, 1)))) { tree placement_arg = CALL_EXPR_ARG (alloc_call, 1); @@ -2689,12 +2715,8 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, domain = compute_array_index_type (NULL_TREE, nelts, complain); else - { - domain = NULL_TREE; - if (CONSTRUCTOR_NELTS (vecinit) > 0) - warning (0, "non-constant array size in new, unable " - "to verify length of initializer-list"); - } + /* We'll check the length at runtime. */ + domain = NULL_TREE; arraytype = build_cplus_array_type (type, domain); vecinit = digest_init (arraytype, vecinit, complain); } @@ -2862,8 +2884,8 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, NE_EXPR, alloc_node, nullptr_node, complain); - rval = build_conditional_expr (ifexp, rval, alloc_node, - complain); + rval = build_conditional_expr (input_location, ifexp, rval, + alloc_node, complain); } /* Perform the allocation before anything else, so that ALLOC_NODE @@ -2920,6 +2942,7 @@ build_new (vec<tree, va_gc> **placement, tree type, tree nelts, if (dependent_type_p (type) || any_type_dependent_arguments_p (*placement) || (nelts && type_dependent_expression_p (nelts)) + || (nelts && *init) || any_type_dependent_arguments_p (*init)) return build_raw_new_expr (*placement, type, nelts, *init, use_global_new); @@ -3280,6 +3303,7 @@ build_vec_init (tree base, tree maxindex, tree init, tree obase = base; bool xvalue = false; bool errors = false; + tree length_check = NULL_TREE; if (TREE_CODE (atype) == ARRAY_TYPE && TYPE_DOMAIN (atype)) maxindex = array_type_nelts (atype); @@ -3298,6 +3322,14 @@ build_vec_init (tree base, tree maxindex, tree init, && from_array != 2) init = TARGET_EXPR_INITIAL (init); + /* If we have a braced-init-list, make sure that the array + is big enough for all the initializers. */ + if (init && TREE_CODE (init) == CONSTRUCTOR + && CONSTRUCTOR_NELTS (init) > 0 + && !TREE_CONSTANT (maxindex)) + length_check = fold_build2 (LT_EXPR, boolean_type_node, maxindex, + size_int (CONSTRUCTOR_NELTS (init) - 1)); + if (init && TREE_CODE (atype) == ARRAY_TYPE && (from_array == 2 @@ -3316,6 +3348,10 @@ build_vec_init (tree base, tree maxindex, tree init, store_constructor will handle the semantics for us. */ stmt_expr = build2 (INIT_EXPR, atype, base, init); + if (length_check) + stmt_expr = build3 (COND_EXPR, atype, length_check, + throw_bad_array_length (), + stmt_expr); return stmt_expr; } @@ -3430,6 +3466,18 @@ build_vec_init (tree base, tree maxindex, tree init, vec<constructor_elt, va_gc> *new_vec; from_array = 0; + if (length_check) + { + tree throw_call; + if (array_of_runtime_bound_p (atype)) + throw_call = throw_bad_array_length (); + else + throw_call = throw_bad_array_new_length (); + length_check = build3 (COND_EXPR, void_type_node, length_check, + throw_call, void_zero_node); + finish_expr_stmt (length_check); + } + if (try_const) vec_alloc (new_vec, CONSTRUCTOR_NELTS (init)); else @@ -3742,7 +3790,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, addr = mark_rvalue_use (addr); - if (TREE_CODE (type) == POINTER_TYPE) + if (TYPE_PTR_P (type)) { bool complete_p = true; @@ -4045,7 +4093,7 @@ build_vec_delete (tree base, tree maxindex, type = TREE_TYPE (base); - if (TREE_CODE (type) == POINTER_TYPE) + if (TYPE_PTR_P (type)) { /* Step back one from start of vector, and read dimension. */ tree cookie_addr; diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index e00d25a2a85..d6ed809d61d 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -171,7 +171,7 @@ init_reswords (void) tree id; int mask = 0; - if (cxx_dialect < cxx0x) + if (cxx_dialect < cxx11) mask |= D_CXX0X; if (flag_no_asm) mask |= D_ASM | D_EXT; diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index a48d476856c..8da62b5e969 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -350,6 +350,7 @@ canonicalize_for_substitution (tree node) && TYPE_CANONICAL (node) != node && TYPE_MAIN_VARIANT (node) != node) { + tree orig = node; /* Here we want to strip the topmost typedef only. We need to do that so is_std_substitution can do proper name matching. */ @@ -361,6 +362,9 @@ canonicalize_for_substitution (tree node) else node = cp_build_qualified_type (TYPE_MAIN_VARIANT (node), cp_type_quals (node)); + if (TREE_CODE (node) == FUNCTION_TYPE + || TREE_CODE (node) == METHOD_TYPE) + node = build_ref_qualified_type (node, type_memfn_rqual (orig)); } return node; } @@ -663,7 +667,7 @@ write_mangled_name (const tree decl, bool top_level) write_source_name (DECL_NAME (decl)); } } - else if (TREE_CODE (decl) == VAR_DECL + else if (VAR_P (decl) /* The names of non-static global variables aren't mangled. */ && DECL_EXTERNAL_LINKAGE_P (decl) && (CP_DECL_CONTEXT (decl) == global_namespace @@ -904,9 +908,11 @@ write_unscoped_template_name (const tree decl) /* Write the nested name, including CV-qualifiers, of DECL. - <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E - ::= N [<CV-qualifiers>] <template-prefix> <template-args> E + <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E + ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E + <ref-qualifier> ::= R # & ref-qualifier + ::= O # && ref-qualifier <CV-qualifiers> ::= [r] [V] [K] */ static void @@ -926,6 +932,13 @@ write_nested_name (const tree decl) write_char ('V'); if (DECL_CONST_MEMFUNC_P (decl)) write_char ('K'); + if (FUNCTION_REF_QUALIFIED (TREE_TYPE (decl))) + { + if (FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (decl))) + write_char ('O'); + else + write_char ('R'); + } } /* Is this a template instance? */ @@ -1042,7 +1055,7 @@ write_prefix (const tree node) { write_prefix (decl_mangling_context (decl)); write_unqualified_name (decl); - if (TREE_CODE (decl) == VAR_DECL + if (VAR_P (decl) || TREE_CODE (decl) == FIELD_DECL) { /* <data-member-prefix> := <member source-name> M */ @@ -1189,7 +1202,7 @@ write_unqualified_name (const tree decl) { MANGLE_TRACE_TREE ("unqualified-name", decl); - if (TREE_CODE (decl) == IDENTIFIER_NODE) + if (identifier_p (decl)) { write_unqualified_id (decl); return; @@ -1880,7 +1893,21 @@ write_type (tree type) mangle the unqualified type. The recursive call is needed here since both the qualified and unqualified types are substitution candidates. */ - write_type (TYPE_MAIN_VARIANT (type)); + { + tree t = TYPE_MAIN_VARIANT (type); + if (TREE_CODE (t) == FUNCTION_TYPE + || TREE_CODE (t) == METHOD_TYPE) + { + t = build_ref_qualified_type (t, type_memfn_rqual (type)); + if (abi_version_at_least (8)) + /* Avoid adding the unqualified function type as a substitution. */ + write_function_type (t); + else + write_type (t); + } + else + write_type (t); + } else if (TREE_CODE (type) == ARRAY_TYPE) /* It is important not to use the TYPE_MAIN_VARIANT of TYPE here so that the cv-qualification of the element type is available @@ -1892,6 +1919,9 @@ write_type (tree type) /* See through any typedefs. */ type = TYPE_MAIN_VARIANT (type); + if (TREE_CODE (type) == FUNCTION_TYPE + || TREE_CODE (type) == METHOD_TYPE) + type = build_ref_qualified_type (type, type_memfn_rqual (type_orig)); /* According to the C++ ABI, some library classes are passed the same as the scalar type of their single member and use the same @@ -1912,7 +1942,7 @@ write_type (tree type) write_string (target_mangling); /* Add substitutions for types other than fundamental types. */ - if (TREE_CODE (type) != VOID_TYPE + if (!VOID_TYPE_P (type) && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE && TREE_CODE (type) != BOOLEAN_TYPE) @@ -1966,7 +1996,7 @@ write_type (tree type) case POINTER_TYPE: case REFERENCE_TYPE: - if (TREE_CODE (type) == POINTER_TYPE) + if (TYPE_PTR_P (type)) write_char ('P'); else if (TYPE_REF_IS_RVALUE (type)) write_char ('O'); @@ -1989,7 +2019,10 @@ write_type (tree type) case TEMPLATE_TYPE_PARM: if (is_auto (type)) { - write_identifier ("Da"); + if (AUTO_IS_DECLTYPE (type)) + write_identifier ("Dc"); + else + write_identifier ("Da"); ++is_builtin_type; break; } @@ -2327,7 +2360,7 @@ write_builtin_type (tree type) METHOD_TYPE. The return type is mangled before the parameter types. - <function-type> ::= F [Y] <bare-function-type> E */ + <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E */ static void write_function_type (const tree type) @@ -2360,6 +2393,13 @@ write_function_type (const tree type) See [dcl.link]. */ write_bare_function_type (type, /*include_return_type_p=*/1, /*decl=*/NULL); + if (FUNCTION_REF_QUALIFIED (type)) + { + if (FUNCTION_RVALUE_QUALIFIED (type)) + write_char ('O'); + else + write_char ('R'); + } write_char ('E'); } @@ -2519,7 +2559,7 @@ write_template_args (tree args) static void write_member_name (tree member) { - if (TREE_CODE (member) == IDENTIFIER_NODE) + if (identifier_p (member)) write_unqualified_id (member); else if (DECL_P (member)) write_unqualified_name (member); @@ -2555,6 +2595,8 @@ write_expression (tree expr) is converted (via qualification conversions) to another type. */ while (TREE_CODE (expr) == NOP_EXPR + /* Parentheses aren't mangled. */ + || code == PAREN_EXPR || TREE_CODE (expr) == NON_LVALUE_EXPR) { expr = TREE_OPERAND (expr, 0); @@ -2691,13 +2733,13 @@ write_expression (tree expr) write_member_name (member); } } - else if (TREE_CODE (expr) == INDIRECT_REF + else if (INDIRECT_REF_P (expr) && TREE_TYPE (TREE_OPERAND (expr, 0)) && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE) { write_expression (TREE_OPERAND (expr, 0)); } - else if (TREE_CODE (expr) == IDENTIFIER_NODE) + else if (identifier_p (expr)) { /* An operator name appearing as a dependent name needs to be specially marked to disambiguate between a use of the operator diff --git a/gcc/cp/method.c b/gcc/cp/method.c index ff29b596892..4ac533eacf7 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -755,7 +755,7 @@ synthesize_method (tree fndecl) tree stmt; location_t save_input_location = input_location; int error_count = errorcount; - int warning_count = warningcount; + int warning_count = warningcount + werrorcount; /* Reset the source location, we might have been previously deferred, and thus have saved where we were first needed. */ @@ -817,7 +817,7 @@ synthesize_method (tree fndecl) pop_deferring_access_checks (); - if (error_count != errorcount || warning_count != warningcount) + if (error_count != errorcount || warning_count != warningcount + werrorcount) inform (input_location, "synthesized method %qD first required here ", fndecl); } @@ -1115,6 +1115,19 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk, "initialize %q+#D", field); } } + else if (sfk == sfk_copy_constructor) + { + /* 12.8p11b5 */ + if (TREE_CODE (mem_type) == REFERENCE_TYPE + && TYPE_REF_IS_RVALUE (mem_type)) + { + if (diag) + error ("copying non-static data member %q#D of rvalue " + "reference type", field); + if (deleted_p) + *deleted_p = true; + } + } if (!CLASS_TYPE_P (mem_type)) continue; @@ -1166,7 +1179,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, bool ctor_p; if (spec_p) - *spec_p = (cxx_dialect >= cxx0x ? noexcept_true_spec : empty_except_spec); + *spec_p = (cxx_dialect >= cxx11 ? noexcept_true_spec : empty_except_spec); if (deleted_p) { @@ -1258,7 +1271,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, resolution, so a constructor can be trivial even if it would otherwise call a non-trivial constructor. */ if (expected_trivial - && (!copy_arg_p || cxx_dialect < cxx0x)) + && (!copy_arg_p || cxx_dialect < cxx11)) { if (constexpr_p && sfk == sfk_constructor) { @@ -1340,7 +1353,8 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, if (diag && assign_p && move_p && BINFO_VIRTUAL_P (base_binfo) && rval && TREE_CODE (rval) == FUNCTION_DECL - && move_fn_p (rval) && !trivial_fn_p (rval)) + && move_fn_p (rval) && !trivial_fn_p (rval) + && vbase_has_user_provided_move_assign (basetype)) warning (OPT_Wvirtual_move_assign, "defaulted move assignment for %qT calls a non-trivial " "move assignment operator for virtual base %qT", @@ -1618,7 +1632,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, if (deleted_p) constexpr_p = false; /* A trivial copy/move constructor is also a constexpr constructor. */ - else if (trivial_p && cxx_dialect >= cxx0x + else if (trivial_p && cxx_dialect >= cxx11 && (kind == sfk_copy_constructor || kind == sfk_move_constructor)) gcc_assert (constexpr_p); @@ -1699,7 +1713,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, DECL_IN_AGGR_P (fn) = 1; DECL_ARTIFICIAL (fn) = 1; DECL_DEFAULTED_FN (fn) = 1; - if (cxx_dialect >= cxx0x) + if (cxx_dialect >= cxx11) { DECL_DELETED_FN (fn) = deleted_p; DECL_DECLARED_CONSTEXPR_P (fn) = constexpr_p; @@ -1742,6 +1756,7 @@ defaulted_late_check (tree fn) bool fn_const_p = (copy_fn_p (fn) == 2); tree implicit_fn = implicitly_declare_fn (kind, ctx, fn_const_p, NULL, NULL); + tree eh_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (implicit_fn)); if (!same_type_p (TREE_TYPE (TREE_TYPE (fn)), TREE_TYPE (TREE_TYPE (implicit_fn))) @@ -1753,31 +1768,40 @@ defaulted_late_check (tree fn) "does not match expected signature %qD", implicit_fn); } - /* 8.4.2/2: If it is explicitly defaulted on its first declaration, it is + /* 8.4.2/2: An explicitly-defaulted function (...) may have an explicit + exception-specification only if it is compatible (15.4) with the + exception-specification on the implicit declaration. If a function + is explicitly defaulted on its first declaration, (...) it is implicitly considered to have the same exception-specification as if it had been implicitly declared. */ - if (DECL_DEFAULTED_IN_CLASS_P (fn)) + if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))) { - tree eh_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (implicit_fn)); - if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))) + maybe_instantiate_noexcept (fn); + if (!comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)), + eh_spec, ce_normal)) { - maybe_instantiate_noexcept (fn); - if (!comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)), - eh_spec, ce_normal)) + if (DECL_DEFAULTED_IN_CLASS_P (fn)) error ("function %q+D defaulted on its first declaration " "with an exception-specification that differs from " "the implicit declaration %q#D", fn, implicit_fn); + else + error ("function %q+D defaulted on its redeclaration " + "with an exception-specification that differs from " + "the implicit declaration %q#D", fn, implicit_fn); } - TREE_TYPE (fn) = build_exception_variant (TREE_TYPE (fn), eh_spec); - if (DECL_DECLARED_CONSTEXPR_P (implicit_fn)) - { - /* Hmm...should we do this for out-of-class too? Should it be OK to - add constexpr later like inline, rather than requiring - declarations to match? */ - DECL_DECLARED_CONSTEXPR_P (fn) = true; - if (kind == sfk_constructor) - TYPE_HAS_CONSTEXPR_CTOR (ctx) = true; - } + } + if (DECL_DEFAULTED_IN_CLASS_P (fn)) + TREE_TYPE (fn) = build_exception_variant (TREE_TYPE (fn), eh_spec); + + if (DECL_DEFAULTED_IN_CLASS_P (fn) + && DECL_DECLARED_CONSTEXPR_P (implicit_fn)) + { + /* Hmm...should we do this for out-of-class too? Should it be OK to + add constexpr later like inline, rather than requiring + declarations to match? */ + DECL_DECLARED_CONSTEXPR_P (fn) = true; + if (kind == sfk_constructor) + TYPE_HAS_CONSTEXPR_CTOR (ctx) = true; } if (!DECL_DECLARED_CONSTEXPR_P (implicit_fn) @@ -1840,13 +1864,19 @@ defaultable_fn_check (tree fn) } else { - tree t = FUNCTION_FIRST_USER_PARMTYPE (fn); - for (; t && t != void_list_node; t = TREE_CHAIN (t)) + for (tree t = FUNCTION_FIRST_USER_PARMTYPE (fn); + t && t != void_list_node; t = TREE_CHAIN (t)) if (TREE_PURPOSE (t)) { error ("defaulted function %q+D with default argument", fn); break; } + + /* Avoid do_warn_unused_parameter warnings. */ + for (tree p = FUNCTION_FIRST_USER_PARM (fn); p; p = DECL_CHAIN (p)) + if (DECL_NAME (p)) + TREE_NO_WARNING (p) = 1; + if (TYPE_BEING_DEFINED (DECL_CONTEXT (fn))) /* Defer checking. */; else if (!processing_template_decl) diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 2a47331ea73..2b1f9fbf318 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -69,14 +69,12 @@ get_anonymous_namespace_name (void) { if (!anonymous_namespace_name) { - /* The anonymous namespace has to have a unique name - if typeinfo objects are being compared by name. */ - if (! flag_weak || ! SUPPORTS_ONE_ONLY) - anonymous_namespace_name = get_file_function_name ("N"); - else - /* The demangler expects anonymous namespaces to be called - something starting with '_GLOBAL__N_'. */ - anonymous_namespace_name = get_identifier ("_GLOBAL__N_1"); + /* We used to use get_file_function_name here, but that isn't + necessary now that anonymous namespace typeinfos + are !TREE_PUBLIC, and thus compared by address. */ + /* The demangler expects anonymous namespaces to be called + something starting with '_GLOBAL__N_'. */ + anonymous_namespace_name = get_identifier ("_GLOBAL__N_1"); } return anonymous_namespace_name; } @@ -511,8 +509,8 @@ supplement_binding_1 (cxx_binding *binding, tree decl) A member shall not be declared twice in the member-specification. */ - else if (TREE_CODE (target_decl) == VAR_DECL - && TREE_CODE (target_bval) == VAR_DECL + else if (VAR_P (target_decl) + && VAR_P (target_bval) && DECL_EXTERNAL (target_decl) && DECL_EXTERNAL (target_bval) && !DECL_CLASS_SCOPE_P (target_decl)) { @@ -576,7 +574,7 @@ add_decl_to_level (tree decl, cp_binding_level *b) { /* We used to record virtual tables as if they were ordinary variables, but no longer do so. */ - gcc_assert (!(TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))); + gcc_assert (!(VAR_P (decl) && DECL_VIRTUAL_P (decl))); if (TREE_CODE (decl) == NAMESPACE_DECL && !DECL_NAMESPACE_ALIAS (decl)) @@ -596,10 +594,12 @@ add_decl_to_level (tree decl, cp_binding_level *b) static later. It's OK for this list to contain a few false positives. */ if (b->kind == sk_namespace) - if ((TREE_CODE (decl) == VAR_DECL + if ((VAR_P (decl) && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) || (TREE_CODE (decl) == FUNCTION_DECL - && (!TREE_PUBLIC (decl) || DECL_DECLARED_INLINE_P (decl)))) + && (!TREE_PUBLIC (decl) + || decl_anon_ns_mem_p (decl) + || DECL_DECLARED_INLINE_P (decl)))) vec_safe_push (b->static_decls, decl); } } @@ -638,7 +638,7 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) /* A local declaration for an `extern' variable is in the scope of the current namespace, not the current function. */ - && !(TREE_CODE (x) == VAR_DECL && DECL_EXTERNAL (x)) + && !(VAR_P (x) && DECL_EXTERNAL (x)) /* When parsing the parameter list of a function declarator, don't set DECL_CONTEXT to an enclosing function. When we push the PARM_DECLs in order to process the function body, @@ -680,7 +680,7 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) block scope declaration declares that same entity and receives the linkage of the previous declaration. */ if (! t && current_function_decl && x != current_function_decl - && (TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL) + && VAR_OR_FUNCTION_DECL_P (x) && DECL_EXTERNAL (x)) { /* Look in block scope. */ @@ -889,7 +889,7 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) add_decl_to_level (x, NAMESPACE_LEVEL (CP_DECL_CONTEXT (t))); } - if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t)) + if (DECL_DECLARES_FUNCTION_P (t)) check_default_args (t); if (t != x || DECL_FUNCTION_TEMPLATE_P (t)) @@ -945,8 +945,10 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) && TREE_CODE (decl) == TREE_CODE (x) && !same_type_p (TREE_TYPE (x), TREE_TYPE (decl))) { - permerror (input_location, "type mismatch with previous external decl of %q#D", x); - permerror (input_location, "previous external decl of %q+#D", decl); + if (permerror (input_location, "type mismatch with previous " + "external decl of %q#D", x)) + inform (input_location, "previous external decl of %q+#D", + decl); } } @@ -975,7 +977,7 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) if (!(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x) && t != NULL_TREE) && (TREE_CODE (x) == TYPE_DECL - || TREE_CODE (x) == VAR_DECL + || VAR_P (x) || TREE_CODE (x) == NAMESPACE_DECL || TREE_CODE (x) == CONST_DECL || TREE_CODE (x) == TEMPLATE_DECL)) @@ -1023,7 +1025,7 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) tree d = oldlocal; while (oldlocal - && TREE_CODE (oldlocal) == VAR_DECL + && VAR_P (oldlocal) && DECL_DEAD_FOR_LOCAL (oldlocal)) oldlocal = DECL_SHADOWED_FOR_VAR (oldlocal); @@ -1067,7 +1069,7 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) /* Inline decls shadow nothing. */ && !DECL_FROM_INLINE (x) && (TREE_CODE (oldlocal) == PARM_DECL - || TREE_CODE (oldlocal) == VAR_DECL + || VAR_P (oldlocal) /* If the old decl is a type decl, only warn if the old decl is an explicit typedef or if both the old and new decls are type decls. */ @@ -1127,30 +1129,59 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) outermost block of the controlled statement. Redeclaring a variable from a for or while condition is detected elsewhere. */ - else if (TREE_CODE (oldlocal) == VAR_DECL + else if (VAR_P (oldlocal) && oldscope == current_binding_level->level_chain && (oldscope->kind == sk_cond || oldscope->kind == sk_for)) { error ("redeclaration of %q#D", x); - error ("%q+#D previously declared here", oldlocal); + inform (input_location, "%q+#D previously declared here", + oldlocal); + nowarn = true; + } + /* C++11: + 3.3.3/3: The name declared in an exception-declaration (...) + shall not be redeclared in the outermost block of the handler. + 3.3.3/2: A parameter name shall not be redeclared (...) in + the outermost block of any handler associated with a + function-try-block. + 3.4.1/15: The function parameter names shall not be redeclared + in the exception-declaration nor in the outermost block of a + handler for the function-try-block. */ + else if ((VAR_P (oldlocal) + && oldscope == current_binding_level->level_chain + && oldscope->kind == sk_catch) + || (TREE_CODE (oldlocal) == PARM_DECL + && (current_binding_level->kind == sk_catch + || (current_binding_level->level_chain->kind + == sk_catch)) + && in_function_try_handler)) + { + if (permerror (input_location, "redeclaration of %q#D", x)) + inform (input_location, "%q+#D previously declared here", + oldlocal); + nowarn = true; } if (warn_shadow && !nowarn) { + bool warned; + if (TREE_CODE (oldlocal) == PARM_DECL) - warning_at (input_location, OPT_Wshadow, + warned = warning_at (input_location, OPT_Wshadow, "declaration of %q#D shadows a parameter", x); else if (is_capture_proxy (oldlocal)) - warning_at (input_location, OPT_Wshadow, + warned = warning_at (input_location, OPT_Wshadow, "declaration of %qD shadows a lambda capture", x); else - warning_at (input_location, OPT_Wshadow, + warned = warning_at (input_location, OPT_Wshadow, "declaration of %qD shadows a previous local", x); - warning_at (DECL_SOURCE_LOCATION (oldlocal), OPT_Wshadow, - "shadowed declaration is here"); + + if (warned) + inform (DECL_SOURCE_LOCATION (oldlocal), + "shadowed declaration is here"); } } @@ -1165,8 +1196,8 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) { tree member; - if (current_class_ptr) - member = lookup_member (current_class_type, + if (nonlambda_method_basetype ()) + member = lookup_member (current_nonlambda_class_type (), name, /*protect=*/0, /*want_type=*/false, @@ -1181,7 +1212,7 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) x); } else if (oldglobal != NULL_TREE - && (TREE_CODE (oldglobal) == VAR_DECL + && (VAR_P (oldglobal) /* If the old decl is a type decl, only warn if the old decl is an explicit typedef or if both the old and new decls are type decls. */ @@ -1190,15 +1221,16 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) || TREE_CODE (x) == TYPE_DECL)))) /* XXX shadow warnings in outer-more namespaces */ { - warning_at (input_location, OPT_Wshadow, - "declaration of %qD shadows a global declaration", x); - warning_at (DECL_SOURCE_LOCATION (oldglobal), OPT_Wshadow, - "shadowed declaration is here"); + if (warning_at (input_location, OPT_Wshadow, + "declaration of %qD shadows a " + "global declaration", x)) + inform (DECL_SOURCE_LOCATION (oldglobal), + "shadowed declaration is here"); } } } - if (TREE_CODE (x) == VAR_DECL) + if (VAR_P (x)) maybe_register_incomplete_var (x); } @@ -1311,12 +1343,12 @@ check_for_out_of_scope_variable (tree decl) tree shadowed; /* We only care about out of scope variables. */ - if (!(TREE_CODE (decl) == VAR_DECL && DECL_DEAD_FOR_LOCAL (decl))) + if (!(VAR_P (decl) && DECL_DEAD_FOR_LOCAL (decl))) return decl; shadowed = DECL_HAS_SHADOWED_FOR_VAR_P (decl) ? DECL_SHADOWED_FOR_VAR (decl) : NULL_TREE ; - while (shadowed != NULL_TREE && TREE_CODE (shadowed) == VAR_DECL + while (shadowed != NULL_TREE && VAR_P (shadowed) && DECL_DEAD_FOR_LOCAL (shadowed)) shadowed = DECL_HAS_SHADOWED_FOR_VAR_P (shadowed) ? DECL_SHADOWED_FOR_VAR (shadowed) : NULL_TREE; @@ -1802,6 +1834,22 @@ print_binding_level (cp_binding_level* lvl) } } +DEBUG_FUNCTION void +debug (cp_binding_level &ref) +{ + print_binding_level (&ref); +} + +DEBUG_FUNCTION void +debug (cp_binding_level *ptr) +{ + if (ptr) + debug (*ptr); + else + fprintf (stderr, "<nil>\n"); +} + + void print_other_binding_stack (cp_binding_level *stack) { @@ -1961,7 +2009,7 @@ constructor_name_p (tree name, tree type) if (!name) return false; - if (TREE_CODE (name) != IDENTIFIER_NODE) + if (!identifier_p (name)) return false; /* These don't have names. */ @@ -2075,7 +2123,7 @@ lookup_extern_c_fun_in_all_ns (tree function) gcc_assert (function && TREE_CODE (function) == FUNCTION_DECL); name = DECL_NAME (function); - gcc_assert (name && TREE_CODE (name) == IDENTIFIER_NODE); + gcc_assert (name && identifier_p (name)); for (iter = IDENTIFIER_NAMESPACE_BINDINGS (name); iter; @@ -2138,7 +2186,7 @@ push_using_decl_1 (tree scope, tree name) tree decl; gcc_assert (TREE_CODE (scope) == NAMESPACE_DECL); - gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); + gcc_assert (identifier_p (name)); for (decl = current_binding_level->usings; decl; decl = DECL_CHAIN (decl)) if (USING_DECL_SCOPE (decl) == scope && DECL_NAME (decl) == name) break; @@ -2421,7 +2469,7 @@ validate_nonmember_using_decl (tree decl, tree scope, tree name) if (using_decl == NULL_TREE && at_function_scope_p () - && TREE_CODE (decl) == VAR_DECL) + && VAR_P (decl)) /* C++11 7.3.3/10. */ error ("%qD is already declared in this scope", name); @@ -3047,7 +3095,7 @@ push_class_level_binding_1 (tree name, tree x) (Non-static data members were also forbidden to have the same name as T until TC1.) */ - if ((TREE_CODE (x) == VAR_DECL + if ((VAR_P (x) || TREE_CODE (x) == CONST_DECL || (TREE_CODE (x) == TYPE_DECL && !DECL_SELF_REFERENCE_P (x)) @@ -4941,7 +4989,7 @@ lookup_name_innermost_nonclass_level_1 (tree name) while (1) { if (binding->scope == b - && !(TREE_CODE (binding->value) == VAR_DECL + && !(VAR_P (binding->value) && DECL_DEAD_FOR_LOCAL (binding->value))) return binding->value; @@ -4980,7 +5028,7 @@ is_local_extern (tree decl) if (TREE_CODE (decl) == FUNCTION_DECL) return DECL_LOCAL_FUNCTION_P (decl); - if (TREE_CODE (decl) != VAR_DECL) + if (!VAR_P (decl)) return false; if (!current_function_decl) return false; @@ -5540,7 +5588,7 @@ lookup_arg_dependent_1 (tree name, tree fns, vec<tree, va_gc> *args, fns = k.functions; if (fns - && TREE_CODE (fns) != VAR_DECL + && !VAR_P (fns) && !is_overloaded_fn (fns)) { error ("argument dependent lookup finds %q+D", fns); @@ -5726,7 +5774,7 @@ pushtag_1 (tree name, tree type, tag_scope scope) || COMPLETE_TYPE_P (b->this_entity)))) b = b->level_chain; - gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); + gcc_assert (identifier_p (name)); /* Do C++ gratuitous typedefing. */ if (identifier_type_value_1 (name) != type) @@ -5809,8 +5857,7 @@ pushtag_1 (tree name, tree type, tag_scope scope) convenient way. (It's otherwise tricky to find a member function definition it's only pointed to from within a local class.) */ - if (TYPE_CONTEXT (type) - && TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL) + if (TYPE_FUNCTION_SCOPE_P (type)) { if (processing_template_decl) { diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index f9a0fbe4dcb..11cdd1f09e8 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -132,10 +132,11 @@ typedef enum tag_scope { ts_global = 1, /* All scopes. This is the 3.4.1 [basic.lookup.unqual] lookup mentioned in [basic.lookup.elab]/2. */ - ts_within_enclosing_non_class = 2 /* Search within enclosing non-class + ts_within_enclosing_non_class = 2, /* Search within enclosing non-class only, for friend class lookup according to [namespace.memdef]/3 and [class.friend]/9. */ + ts_lambda = 3 /* Declaring a lambda closure. */ } tag_scope; typedef struct GTY(()) cp_class_binding { @@ -346,7 +347,7 @@ extern void cp_emit_debug_info_for_using (tree, tree); /* Set *DECL to the (non-hidden) declaration for ID at global scope, if present and return true; otherwise return false. */ -static inline bool +inline bool get_global_value_if_present (tree id, tree *decl) { tree global_value = namespace_binding (id, global_namespace); @@ -357,7 +358,7 @@ get_global_value_if_present (tree id, tree *decl) /* True is the binding of IDENTIFIER at global scope names a type. */ -static inline bool +inline bool is_typename_at_global_scope (tree id) { tree global_value = namespace_binding (id, global_namespace); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index ff4faa32d3c..ec8ad46dd44 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -327,6 +327,21 @@ cp_lexer_debug_tokens (vec<cp_token, va_gc> *buffer) cp_lexer_dump_tokens (stderr, buffer, NULL, 0, NULL); } +DEBUG_FUNCTION void +debug (vec<cp_token, va_gc> &ref) +{ + cp_lexer_dump_tokens (stderr, &ref, NULL, 0, NULL); +} + +DEBUG_FUNCTION void +debug (vec<cp_token, va_gc> *ptr) +{ + if (ptr) + debug (*ptr); + else + fprintf (stderr, "<nil>\n"); +} + /* Dump the cp_parser tree field T to FILE if T is non-NULL. DESC is the description for T. */ @@ -545,6 +560,20 @@ cp_debug_parser (FILE *file, cp_parser *parser) fprintf (file, "\tColumn: %d\n", eloc.column); } +DEBUG_FUNCTION void +debug (cp_parser &ref) +{ + cp_debug_parser (stderr, &ref); +} + +DEBUG_FUNCTION void +debug (cp_parser *ptr) +{ + if (ptr) + debug (*ptr); + else + fprintf (stderr, "<nil>\n"); +} /* Allocate memory for a new lexer object and return it. */ @@ -837,6 +866,12 @@ cp_lexer_next_token_is_keyword (cp_lexer* lexer, enum rid keyword) return cp_lexer_peek_token (lexer)->keyword == keyword; } +static inline bool +cp_lexer_nth_token_is_keyword (cp_lexer* lexer, size_t n, enum rid keyword) +{ + return cp_lexer_peek_nth_token (lexer, n)->keyword == keyword; +} + /* Return true if the next token is not the indicated KEYWORD. */ static inline bool @@ -1110,7 +1145,7 @@ cp_lexer_print_token (FILE * stream, cp_token *token) case CPP_KEYWORD: /* Some keywords have a value that is not an IDENTIFIER_NODE. For example, `struct' is mapped to an INTEGER_CST. */ - if (TREE_CODE (token->u.value) != IDENTIFIER_NODE) + if (!identifier_p (token->u.value)) break; /* else fall through */ case CPP_NAME: @@ -1140,6 +1175,23 @@ cp_lexer_print_token (FILE * stream, cp_token *token) } } +DEBUG_FUNCTION void +debug (cp_token &ref) +{ + cp_lexer_print_token (stderr, &ref); + fprintf (stderr, "\n"); +} + +DEBUG_FUNCTION void +debug (cp_token *ptr) +{ + if (ptr) + debug (*ptr); + else + fprintf (stderr, "<nil>\n"); +} + + /* Start emitting debugging information. */ static void @@ -1188,7 +1240,7 @@ clear_decl_specs (cp_decl_specifier_seq *decl_specs) VAR_DECLs or FUNCTION_DECLs) should do that directly. */ static cp_declarator *make_call_declarator - (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, tree, tree); + (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, cp_ref_qualifier, tree, tree); static cp_declarator *make_array_declarator (cp_declarator *, tree); static cp_declarator *make_pointer_declarator @@ -1259,7 +1311,7 @@ make_id_declarator (tree qualifying_scope, tree unqualified_name, if (qualifying_scope && TYPE_P (qualifying_scope)) qualifying_scope = TYPE_MAIN_VARIANT (qualifying_scope); - gcc_assert (TREE_CODE (unqualified_name) == IDENTIFIER_NODE + gcc_assert (identifier_p (unqualified_name) || TREE_CODE (unqualified_name) == BIT_NOT_EXPR || TREE_CODE (unqualified_name) == TEMPLATE_ID_EXPR); @@ -1367,6 +1419,7 @@ make_call_declarator (cp_declarator *target, tree parms, cp_cv_quals cv_qualifiers, cp_virt_specifiers virt_specifiers, + cp_ref_qualifier ref_qualifier, tree exception_specification, tree late_return_type) { @@ -1377,6 +1430,7 @@ make_call_declarator (cp_declarator *target, declarator->u.function.parameters = parms; declarator->u.function.qualifiers = cv_qualifiers; declarator->u.function.virt_specifiers = virt_specifiers; + declarator->u.function.ref_qualifier = ref_qualifier; declarator->u.function.exception_specification = exception_specification; declarator->u.function.late_return_type = late_return_type; if (target) @@ -1802,9 +1856,9 @@ static tree cp_parser_nested_name_specifier static tree cp_parser_qualifying_entity (cp_parser *, bool, bool, bool, bool, bool); static tree cp_parser_postfix_expression - (cp_parser *, bool, bool, bool, cp_id_kind *); + (cp_parser *, bool, bool, bool, bool, cp_id_kind *); static tree cp_parser_postfix_open_square_expression - (cp_parser *, tree, bool); + (cp_parser *, tree, bool, bool); static tree cp_parser_postfix_dot_deref_expression (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t); static vec<tree, va_gc> *cp_parser_parenthesized_expression_list @@ -1812,7 +1866,7 @@ static vec<tree, va_gc> *cp_parser_parenthesized_expression_list /* Values for the second parameter of cp_parser_parenthesized_expression_list. */ enum { non_attr = 0, normal_attr = 1, id_attr = 2 }; static void cp_parser_pseudo_destructor_name - (cp_parser *, tree *, tree *); + (cp_parser *, tree, tree *, tree *); static tree cp_parser_unary_expression (cp_parser *, bool, bool, cp_id_kind *); static enum tree_code cp_parser_unary_operator @@ -1832,7 +1886,7 @@ static vec<tree, va_gc> *cp_parser_new_initializer static tree cp_parser_delete_expression (cp_parser *); static tree cp_parser_cast_expression - (cp_parser *, bool, bool, cp_id_kind *); + (cp_parser *, bool, bool, bool, cp_id_kind *); static tree cp_parser_binary_expression (cp_parser *, bool, bool, enum cp_parser_prec, cp_id_kind *); static tree cp_parser_question_colon_clause @@ -1843,6 +1897,8 @@ static enum tree_code cp_parser_assignment_operator_opt (cp_parser *); static tree cp_parser_expression (cp_parser *, bool, cp_id_kind *); +static tree cp_parser_expression + (cp_parser *, bool, bool, cp_id_kind *); static tree cp_parser_constant_expression (cp_parser *, bool, bool *); static tree cp_parser_builtin_offsetof @@ -1970,6 +2026,8 @@ static cp_cv_quals cp_parser_cv_qualifier_seq_opt (cp_parser *); static cp_virt_specifiers cp_parser_virt_specifier_seq_opt (cp_parser *); +static cp_ref_qualifier cp_parser_ref_qualifier_opt + (cp_parser *); static tree cp_parser_late_return_type_opt (cp_parser *, cp_cv_quals); static tree cp_parser_declarator_id @@ -2585,7 +2643,7 @@ cp_parser_check_for_invalid_template_id (cp_parser* parser, { if (TYPE_P (type)) error_at (location, "%qT is not a template", type); - else if (TREE_CODE (type) == IDENTIFIER_NODE) + else if (identifier_p (type)) { if (tag_type != none_type) error_at (location, "%qE is not a class template", type); @@ -2771,7 +2829,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, template <typename T> struct B : public A<T> { X x; }; The user should have said "typename A<T>::X". */ - if (cxx_dialect < cxx0x && id == ridpointers[(int)RID_CONSTEXPR]) + if (cxx_dialect < cxx11 && id == ridpointers[(int)RID_CONSTEXPR]) inform (location, "C++11 %<constexpr%> only available with " "-std=c++11 or -std=gnu++11"); else if (processing_template_decl && current_class_type @@ -2814,8 +2872,16 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, else if (parser->scope != error_mark_node) { if (TREE_CODE (parser->scope) == NAMESPACE_DECL) - error_at (location, "%qE in namespace %qE does not name a type", - id, parser->scope); + { + if (cp_lexer_next_token_is (parser->lexer, CPP_LESS)) + error_at (location_of (id), + "%qE in namespace %qE does not name a template type", + id, parser->scope); + else + error_at (location_of (id), + "%qE in namespace %qE does not name a type", + id, parser->scope); + } else if (CLASS_TYPE_P (parser->scope) && constructor_name_p (id, parser->scope)) { @@ -2832,8 +2898,16 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, "%qT is a dependent scope", parser->scope, id, parser->scope); else if (TYPE_P (parser->scope)) - error_at (location, "%qE in %q#T does not name a type", - id, parser->scope); + { + if (cp_lexer_next_token_is (parser->lexer, CPP_LESS)) + error_at (location_of (id), + "%qE in %q#T does not name a template type", + id, parser->scope); + else + error_at (location_of (id), + "%qE in %q#T does not name a type", + id, parser->scope); + } else gcc_unreachable (); } @@ -3191,7 +3265,7 @@ cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id, location_t id_location) { tree result; - if (TREE_CODE (id) == IDENTIFIER_NODE) + if (identifier_p (id)) { result = make_typename_type (scope, id, typename_type, /*complain=*/tf_none); @@ -3559,21 +3633,20 @@ lookup_literal_operator (tree name, vec<tree, va_gc> *args) unsigned int ix; bool found = true; tree fn = OVL_CURRENT (fns); - tree argtypes = NULL_TREE; - argtypes = TYPE_ARG_TYPES (TREE_TYPE (fn)); - if (argtypes != NULL_TREE) + tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (fn)); + if (parmtypes != NULL_TREE) { - for (ix = 0; ix < vec_safe_length (args) && argtypes != NULL_TREE; - ++ix, argtypes = TREE_CHAIN (argtypes)) + for (ix = 0; ix < vec_safe_length (args) && parmtypes != NULL_TREE; + ++ix, parmtypes = TREE_CHAIN (parmtypes)) { - tree targ = TREE_VALUE (argtypes); - tree tparm = TREE_TYPE ((*args)[ix]); - bool ptr = TREE_CODE (targ) == POINTER_TYPE; - bool arr = TREE_CODE (tparm) == ARRAY_TYPE; - if ((ptr || arr || !same_type_p (targ, tparm)) + tree tparm = TREE_VALUE (parmtypes); + tree targ = TREE_TYPE ((*args)[ix]); + bool ptr = TYPE_PTR_P (tparm); + bool arr = TREE_CODE (targ) == ARRAY_TYPE; + if ((ptr || arr || !same_type_p (tparm, targ)) && (!ptr || !arr - || !same_type_p (TREE_TYPE (targ), - TREE_TYPE (tparm)))) + || !same_type_p (TREE_TYPE (tparm), + TREE_TYPE (targ)))) found = false; } if (found @@ -3582,7 +3655,7 @@ lookup_literal_operator (tree name, vec<tree, va_gc> *args) depending on how exactly should user-defined literals work in presence of default arguments on the literal operator parameters. */ - && argtypes == void_list_node) + && parmtypes == void_list_node) return fn; } } @@ -3651,6 +3724,37 @@ make_char_string_pack (tree value) return argvec; } +/* A subroutine of cp_parser_userdef_numeric_literal to + create a char... template parameter pack from a string node. */ + +static tree +make_string_pack (tree value) +{ + tree charvec; + tree argpack = make_node (NONTYPE_ARGUMENT_PACK); + const char *str = TREE_STRING_POINTER (value); + int i, len = TREE_STRING_LENGTH (value) - 1; + tree argvec = make_tree_vec (2); + + tree string_char_type_node = TREE_TYPE (TREE_TYPE (value)); + + /* First template parm is character type. */ + TREE_VEC_ELT (argvec, 0) = string_char_type_node; + + /* Fill in CHARVEC with all of the parameters. */ + charvec = make_tree_vec (len); + for (i = 0; i < len; ++i) + TREE_VEC_ELT (charvec, i) = build_int_cst (string_char_type_node, str[i]); + + /* Build the argument packs. */ + SET_ARGUMENT_PACK_ARGS (argpack, charvec); + TREE_TYPE (argpack) = string_char_type_node; + + TREE_VEC_ELT (argvec, 1) = argpack; + + return argvec; +} + /* Parse a user-defined numeric constant. returns a call to a user-defined literal operator. */ @@ -3750,10 +3854,29 @@ cp_parser_userdef_string_literal (cp_token *token) int len = TREE_STRING_LENGTH (value) / TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (value)))) - 1; tree decl, result; + vec<tree, va_gc> *args; + + /* Look for a template function with typename parameter CharT + and parameter pack CharT... Call the function with + template parameter characters representing the string. */ + args = make_tree_vector (); + decl = lookup_literal_operator (name, args); + if (decl && decl != error_mark_node) + { + tree tmpl_args = make_string_pack (value); + decl = lookup_template_function (decl, tmpl_args); + result = finish_call_expr (decl, &args, false, true, tf_none); + if (result != error_mark_node) + { + release_tree_vector (args); + return result; + } + } + release_tree_vector (args); /* Build up a call to the user-defined operator */ /* Lookup the name we got back from the id-expression. */ - vec<tree, va_gc> *args = make_tree_vector (); + args = make_tree_vector (); vec_safe_push (args, value); vec_safe_push (args, build_int_cst (size_type_node, len)); decl = lookup_name (name); @@ -3840,6 +3963,18 @@ cp_parser_translation_unit (cp_parser* parser) return success; } +/* Return the appropriate tsubst flags for parsing, possibly in N3276 + decltype context. */ + +static inline tsubst_flags_t +complain_flags (bool decltype_p) +{ + tsubst_flags_t complain = tf_warning_or_error; + if (decltype_p) + complain |= tf_decltype; + return complain; +} + /* Expressions [gram.expr] */ /* Parse a primary-expression. @@ -3901,6 +4036,7 @@ cp_parser_primary_expression (cp_parser *parser, bool address_p, bool cast_p, bool template_arg_p, + bool decltype_p, cp_id_kind *idk) { cp_token *token = NULL; @@ -4052,13 +4188,13 @@ cp_parser_primary_expression (cp_parser *parser, else { /* Parse the parenthesized expression. */ - expr = cp_parser_expression (parser, cast_p, idk); + expr = cp_parser_expression (parser, cast_p, decltype_p, idk); /* Let the front end know that this expression was enclosed in parentheses. This matters in case, for example, the expression is of the form `A::B', since `&A::B' might be a pointer-to-member, but `&(A::B)' is not. */ - finish_parenthesized_expr (expr); + expr = finish_parenthesized_expr (expr); /* DR 705: Wrapping an unqualified name in parentheses suppresses arg-dependent lookup. We want to pass back CP_ID_KIND_QUALIFIED for suppressing vtable lookup @@ -4404,6 +4540,17 @@ cp_parser_primary_expression (cp_parser *parser, } } +static inline tree +cp_parser_primary_expression (cp_parser *parser, + bool address_p, + bool cast_p, + bool template_arg_p, + cp_id_kind *idk) +{ + return cp_parser_primary_expression (parser, address_p, cast_p, template_arg_p, + /*decltype*/false, idk); +} + /* Parse an id-expression. id-expression: @@ -4696,6 +4843,17 @@ cp_parser_unqualified_id (cp_parser* parser, return build_nt (BIT_NOT_EXPR, scope); } + /* ~auto means the destructor of whatever the object is. */ + if (cp_parser_is_keyword (token, RID_AUTO)) + { + if (cxx_dialect < cxx1y) + pedwarn (input_location, 0, + "%<~auto%> only available with " + "-std=c++1y or -std=gnu++1y"); + cp_lexer_consume_token (parser->lexer); + return build_nt (BIT_NOT_EXPR, make_auto ()); + } + /* If there was an explicit qualification (S::~T), first look in the scope given by the qualification (i.e., S). @@ -4842,7 +5000,7 @@ cp_parser_unqualified_id (cp_parser* parser, { /* 17.6.3.3.5 */ const char *name = UDLIT_OP_SUFFIX (id); - if (name[0] != '_' && !in_system_header) + if (name[0] != '_' && !in_system_header && declarator_p) warning (0, "literal operator suffixes not preceded by %<_%>" " are reserved for future standardization"); } @@ -5072,10 +5230,16 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, decl); else if (ambiguous_decls) { - error_at (token->location, - "reference to %qD is ambiguous", - token->u.value); - print_candidates (ambiguous_decls); + // cp_parser_lookup_name has the same diagnostic, + // thus make sure to emit it at most once. + if (cp_parser_uncommitted_to_tentative_parse_p + (parser)) + { + error_at (token->location, + "reference to %qD is ambiguous", + token->u.value); + print_candidates (ambiguous_decls); + } decl = error_mark_node; } else @@ -5365,7 +5529,7 @@ cp_parser_qualifying_entity (cp_parser *parser, static tree cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, - bool member_access_only_p, + bool member_access_only_p, bool decltype_p, cp_id_kind * pidk_return) { cp_token *token; @@ -5388,6 +5552,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, tree type; tree expression; const char *saved_message; + bool saved_in_type_id_in_expr_p; /* All of these can be handled in the same way from the point of view of parsing. Begin by consuming the token @@ -5402,7 +5567,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, /* Look for the opening `<'. */ cp_parser_require (parser, CPP_LESS, RT_LESS); /* Parse the type to which we are casting. */ + saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; + parser->in_type_id_in_expr_p = true; type = cp_parser_type_id (parser); + parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; /* Look for the closing `>'. */ cp_parser_require (parser, CPP_GREATER, RT_GREATER); /* Restore the old message. */ @@ -5561,7 +5729,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, if (cp_parser_allow_gnu_extensions_p (parser) && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { - vec<constructor_elt, va_gc> *initializer_list = NULL; + tree initializer = NULL_TREE; bool saved_in_type_id_in_expr_p; cp_parser_parse_tentatively (parser); @@ -5574,21 +5742,19 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; /* Look for the `)'. */ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); - /* Look for the `{'. */ - cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE); /* If things aren't going well, there's no need to keep going. */ if (!cp_parser_error_occurred (parser)) { - bool non_constant_p; - /* Parse the initializer-list. */ - initializer_list - = cp_parser_initializer_list (parser, &non_constant_p); - /* Allow a trailing `,'. */ - if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) - cp_lexer_consume_token (parser->lexer); - /* Look for the final `}'. */ - cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + { + bool non_constant_p; + /* Parse the brace-enclosed initializer list. */ + initializer = cp_parser_braced_list (parser, + &non_constant_p); + } + else + cp_parser_simulate_error (parser); } /* If that worked, we're definitely looking at a compound-literal expression. */ @@ -5596,7 +5762,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, { /* Warn the user that a compound literal is not allowed in standard C++. */ - pedwarn (input_location, OPT_Wpedantic, "ISO C++ forbids compound-literals"); + pedwarn (input_location, OPT_Wpedantic, + "ISO C++ forbids compound-literals"); /* For simplicity, we disallow compound literals in constant-expressions. We could allow compound literals of integer type, whose @@ -5614,10 +5781,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, } /* Form the representation of the compound-literal. */ postfix_expression - = (finish_compound_literal - (type, build_constructor (init_list_type_node, - initializer_list), - tf_warning_or_error)); + = finish_compound_literal (type, initializer, + tf_warning_or_error); break; } } @@ -5626,16 +5791,22 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, postfix_expression = cp_parser_primary_expression (parser, address_p, cast_p, /*template_arg_p=*/false, + decltype_p, &idk); } break; } + /* Note that we don't need to worry about calling build_cplus_new on a + class-valued CALL_EXPR in decltype when it isn't the end of the + postfix-expression; unary_complex_lvalue will take care of that for + all these cases. */ + /* Keep looping until the postfix-expression is complete. */ while (true) { if (idk == CP_ID_KIND_UNQUALIFIED - && TREE_CODE (postfix_expression) == IDENTIFIER_NODE + && identifier_p (postfix_expression) && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)) /* It is not a Koenig lookup function call. */ postfix_expression @@ -5657,7 +5828,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, postfix_expression = cp_parser_postfix_open_square_expression (parser, postfix_expression, - false); + false, + decltype_p); idk = CP_ID_KIND_NONE; is_member_access = false; break; @@ -5669,6 +5841,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, bool is_builtin_constant_p; bool saved_integral_constant_expression_p = false; bool saved_non_integral_constant_expression_p = false; + tsubst_flags_t complain = complain_flags (decltype_p); vec<tree, va_gc> *args; is_member_access = false; @@ -5718,7 +5891,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, if (idk == CP_ID_KIND_UNQUALIFIED || idk == CP_ID_KIND_TEMPLATE_ID) { - if (TREE_CODE (postfix_expression) == IDENTIFIER_NODE) + if (identifier_p (postfix_expression)) { if (!args->is_empty ()) { @@ -5727,7 +5900,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, postfix_expression = perform_koenig_lookup (postfix_expression, args, /*include_std=*/false, - tf_warning_or_error); + complain); } else postfix_expression @@ -5753,7 +5926,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, postfix_expression = perform_koenig_lookup (postfix_expression, args, /*include_std=*/false, - tf_warning_or_error); + complain); } } } @@ -5785,21 +5958,21 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, ? LOOKUP_NORMAL|LOOKUP_NONVIRTUAL : LOOKUP_NORMAL), /*fn_p=*/NULL, - tf_warning_or_error)); + complain)); } else postfix_expression = finish_call_expr (postfix_expression, &args, /*disallow_virtual=*/false, /*koenig_p=*/false, - tf_warning_or_error); + complain); } else if (TREE_CODE (postfix_expression) == OFFSET_REF || TREE_CODE (postfix_expression) == MEMBER_REF || TREE_CODE (postfix_expression) == DOTSTAR_EXPR) postfix_expression = (build_offset_ref_call_from_tree (postfix_expression, &args, - tf_warning_or_error)); + complain)); else if (idk == CP_ID_KIND_QUALIFIED) /* A call to a static class member, or a namespace-scope function. */ @@ -5807,14 +5980,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, = finish_call_expr (postfix_expression, &args, /*disallow_virtual=*/true, koenig_p, - tf_warning_or_error); + complain); else /* All other function calls. */ postfix_expression = finish_call_expr (postfix_expression, &args, /*disallow_virtual=*/false, koenig_p, - tf_warning_or_error); + complain); /* The POSTFIX_EXPRESSION is certainly no longer an id. */ idk = CP_ID_KIND_NONE; @@ -5887,6 +6060,170 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, return error_mark_node; } +/* This function parses Cilk Plus array notations. The starting index is + passed in INIT_INDEX and the array name is passed in ARRAY_VALUE. If the + INIT_INDEX is NULL, then we have special case were the entire array is + accessed (e.g. A[:]). The return value of this function is a tree node + called VALUE_TREE of type ARRAY_NOTATION_REF. If some error occurred it + returns error_mark_node. */ + +static tree +cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index, + tree array_value) +{ + cp_token *token = NULL; + tree start_index = NULL_TREE, length_index = NULL_TREE, stride = NULL_TREE; + tree value_tree, type, array_type, array_type_domain; + double_int x; + bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; + + if (!array_value || array_value == error_mark_node) + { + cp_parser_skip_to_end_of_statement (parser); + return error_mark_node; + } + + if (processing_template_decl) + { + array_type = TREE_TYPE (array_value); + type = TREE_TYPE (array_type); + } + else + { + array_type = TREE_TYPE (array_value); + gcc_assert (array_type); + type = array_type; + } + token = cp_lexer_peek_token (parser->lexer); + if (!token) + { + cp_parser_error (parser, "expected %<:%> or numeral"); + return error_mark_node; + } + else if (token->type == CPP_COLON) + { + if (!init_index) + { + /* If we are here, then we have a case like this A[:]. */ + cp_lexer_consume_token (parser->lexer); + + if (cp_lexer_peek_token (parser->lexer)->type != CPP_CLOSE_SQUARE) + { + cp_parser_error (parser, "expected %<]%>"); + cp_parser_skip_to_end_of_statement (parser); + return error_mark_node; + } + if (TREE_CODE (array_type) == RECORD_TYPE + || TREE_CODE (array_type) == POINTER_TYPE) + { + error_at (loc, "start-index and length fields necessary for " + "using array notations in pointers or records"); + cp_parser_skip_to_end_of_statement (parser); + return error_mark_node; + } + if (TREE_CODE (array_type) == ARRAY_TYPE) + { + tree subtype = TREE_TYPE (array_type); + while (subtype && TREE_CODE (subtype) == POINTER_TYPE) + { + /* This could be a function ptr. If so, then emit error. */ + subtype = TREE_TYPE (subtype); + if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE) + { + error_at (loc, "array notations cannot be used with" + " function pointer arrays"); + cp_parser_skip_to_end_of_statement (parser); + return error_mark_node; + } + } + } + array_type_domain = TYPE_DOMAIN (array_type); + if (!array_type_domain) + { + error_at (loc, "start-index and length fields necessary for " + "using array notations in dimensionless arrays"); + cp_parser_skip_to_end_of_statement (parser); + return error_mark_node; + } + start_index = TYPE_MINVAL (array_type_domain); + start_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, + start_index); + x = TREE_INT_CST (TYPE_MAXVAL (array_type_domain)); + x.low++; + length_index = double_int_to_tree (integer_type_node, x); + length_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, + length_index); + stride = build_int_cst (integer_type_node, 1); + stride = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, stride); + } + else if (init_index != error_mark_node) + { + /* If we hare here, then there are 2 possibilities: + 1. Array [ EXPR : EXPR ] + 2. Array [ EXPR : EXPR : EXPR ] + */ + start_index = init_index; + cp_lexer_consume_token (parser->lexer); + + saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; + /* The ':' is used in array notation. Thus compiler cannot do scope + correction automatically. */ + parser->colon_corrects_to_scope_p = false; + length_index = cp_parser_expression (parser, false, NULL); + parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; + if (!length_index || length_index == error_mark_node) + cp_parser_skip_to_end_of_statement (parser); + + if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON) + { + cp_lexer_consume_token (parser->lexer); + saved_colon_corrects_to_scope_p = + parser->colon_corrects_to_scope_p; + /* Disable correcting single colon correcting to scope. */ + parser->colon_corrects_to_scope_p = false; + stride = cp_parser_expression (parser, false, NULL); + parser->colon_corrects_to_scope_p = + saved_colon_corrects_to_scope_p; + if (!stride || stride == error_mark_node) + { + cp_parser_skip_to_end_of_statement (parser); + if (cp_lexer_peek_token (parser->lexer)->type + == CPP_CLOSE_SQUARE) + cp_lexer_consume_token (parser->lexer); + } + } + else + stride = build_one_cst (integer_type_node); + } + else + { + cp_parser_skip_to_end_of_statement (parser); + return error_mark_node; + } + } + + if (start_index == error_mark_node || length_index == error_mark_node + || stride == error_mark_node || !start_index || !length_index + || !stride) + { + if (cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_SQUARE) + cp_lexer_consume_token (parser->lexer); + return error_mark_node; + } + cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); + + /* We fold all 3 of the values to make things easier when we transform + them later. */ + start_index = fold (start_index); + length_index = fold (length_index); + stride = fold (stride); + + value_tree = build_array_notation_ref (input_location, array_value, + start_index, length_index, stride, + type); + return value_tree; +} + /* A subroutine of cp_parser_postfix_expression that also gets hijacked by cp_parser_builtin_offsetof. We're looking for @@ -5899,7 +6236,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, static tree cp_parser_postfix_open_square_expression (cp_parser *parser, tree postfix_expression, - bool for_offsetof) + bool for_offsetof, + bool decltype_p) { tree index; location_t loc = cp_lexer_peek_token (parser->lexer)->location; @@ -5907,40 +6245,78 @@ cp_parser_postfix_open_square_expression (cp_parser *parser, /* Consume the `[' token. */ cp_lexer_consume_token (parser->lexer); - /* Parse the index expression. */ - /* ??? For offsetof, there is a question of what to allow here. If - offsetof is not being used in an integral constant expression context, - then we *could* get the right answer by computing the value at runtime. - If we are in an integral constant expression context, then we might - could accept any constant expression; hard to say without analysis. - Rather than open the barn door too wide right away, allow only integer - constant expressions here. */ - if (for_offsetof) - index = cp_parser_constant_expression (parser, false, NULL); + if (flag_enable_cilkplus + && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON) + /* If we are here, then we have something like this: + ARRAY[:] + */ + postfix_expression = cp_parser_array_notation (loc, parser, NULL_TREE, + postfix_expression); else { - if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + /* Here are have these options: + 1. ARRAY[EXPR] -- This is the normal array call. + 2. ARRAY[EXPR : EXPR] -- Array notation expr with default stride + of 1. + 3. ARRAY[EXPR : EXPR : EXPR] -- Array Notation with userdefined stride. + 4. Array[Braced List] -- This is handled by braced list. + */ + + /* Parse the index expression. */ + /* ??? For offsetof, there is a question of what to allow here. If + offsetof is not being used in an integral constant expression context, + then we *could* get the right answer by computing the value at runtime. + If we are in an integral constant expression context, then we might + could accept any constant expression; hard to say without analysis. + Rather than open the barn door too wide right away, allow only integer + constant expressions here. */ + if (for_offsetof) + index = cp_parser_constant_expression (parser, false, NULL); + else { - bool expr_nonconst_p; - maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS); - index = cp_parser_braced_list (parser, &expr_nonconst_p); + bool saved_colon_corrects_to_scope_p = + parser->colon_corrects_to_scope_p; + if (flag_enable_cilkplus) + parser->colon_corrects_to_scope_p = false; + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + { + bool expr_nonconst_p; + maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS); + index = cp_parser_braced_list (parser, &expr_nonconst_p); + if (flag_enable_cilkplus + && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON) + { + error_at (cp_lexer_peek_token (parser->lexer)->location, + "braced list index is not allowed with array " + "notations"); + index = error_mark_node; + } + } + else + index = cp_parser_expression (parser, /*cast_p=*/false, NULL); + parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; } + if (flag_enable_cilkplus + && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON) + postfix_expression = cp_parser_array_notation (loc, parser, index, + postfix_expression); else - index = cp_parser_expression (parser, /*cast_p=*/false, NULL); - } - - /* Look for the closing `]'. */ - cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); - - /* Build the ARRAY_REF. */ - postfix_expression = grok_array_decl (loc, postfix_expression, index); + { + /* Look for the closing `]'. */ + cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); - /* When not doing offsetof, array references are not permitted in - constant-expressions. */ - if (!for_offsetof - && (cp_parser_non_integral_constant_expression (parser, NIC_ARRAY_REF))) - postfix_expression = error_mark_node; + /* Build the ARRAY_REF. */ + postfix_expression = grok_array_decl (loc, postfix_expression, + index, decltype_p); + /* When not doing offsetof, array references are not permitted in + constant-expressions. */ + if (!for_offsetof + && (cp_parser_non_integral_constant_expression (parser, + NIC_ARRAY_REF))) + postfix_expression = error_mark_node; + } + } return postfix_expression; } @@ -6003,7 +6379,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, /* Unlike the object expression in other contexts, *this is not required to be of complete type for purposes of class member access (5.2.5) outside the member function body. */ - else if (scope != current_class_ref + else if (postfix_expression != current_class_ref && !(processing_template_decl && scope == current_class_type)) scope = complete_type_or_else (scope, NULL_TREE); /* Let the name lookup machinery know that we are processing a @@ -6036,18 +6412,18 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, cp_parser_parse_tentatively (parser); /* Parse the pseudo-destructor-name. */ s = NULL_TREE; - cp_parser_pseudo_destructor_name (parser, &s, &type); + cp_parser_pseudo_destructor_name (parser, postfix_expression, + &s, &type); if (dependent_p && (cp_parser_error_occurred (parser) - || TREE_CODE (type) != TYPE_DECL - || !SCALAR_TYPE_P (TREE_TYPE (type)))) + || !SCALAR_TYPE_P (type))) cp_parser_abort_tentative_parse (parser); else if (cp_parser_parse_definitely (parser)) { pseudo_destructor_p = true; postfix_expression = finish_pseudo_destructor_expr (postfix_expression, - s, TREE_TYPE (type)); + s, type); } } @@ -6308,11 +6684,28 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, static void cp_parser_pseudo_destructor_name (cp_parser* parser, + tree object, tree* scope, tree* type) { bool nested_name_specifier_p; + /* Handle ~auto. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_COMPL) + && cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_AUTO) + && !type_dependent_expression_p (object)) + { + if (cxx_dialect < cxx1y) + pedwarn (input_location, 0, + "%<~auto%> only available with " + "-std=c++1y or -std=gnu++1y"); + cp_lexer_consume_token (parser->lexer); + cp_lexer_consume_token (parser->lexer); + *scope = NULL_TREE; + *type = TREE_TYPE (object); + return; + } + /* Assume that things will not work out. */ *type = error_mark_node; @@ -6380,7 +6773,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser, /* Look for the type-name again. We are not responsible for checking that it matches the first type-name. */ - *type = cp_parser_nonclass_name (parser); + *type = TREE_TYPE (cp_parser_nonclass_name (parser)); } /* Parse a unary-expression. @@ -6406,6 +6799,9 @@ cp_parser_pseudo_destructor_name (cp_parser* parser, __real__ cast-expression __imag__ cast-expression && identifier + sizeof ( type-id ) { initializer-list , [opt] } + alignof ( type-id ) { initializer-list , [opt] } [C++0x] + __alignof__ ( type-id ) { initializer-list , [opt] } ADDRESS_P is true iff the unary-expression is appearing as the operand of the `&' operator. CAST_P is true if this expression is @@ -6415,7 +6811,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser, static tree cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p, - cp_id_kind * pidk) + bool decltype_p, cp_id_kind * pidk) { cp_token *token; enum tree_code unary_operator; @@ -6629,6 +7025,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p, tree expression = error_mark_node; non_integral_constant non_constant_p = NIC_NONE; location_t loc = token->location; + tsubst_flags_t complain = complain_flags (decltype_p); /* Consume the operator token. */ token = cp_lexer_consume_token (parser->lexer); @@ -6636,7 +7033,9 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p, cast_expression = cp_parser_cast_expression (parser, unary_operator == ADDR_EXPR, - /*cast_p=*/false, pidk); + /*cast_p=*/false, + /*decltype*/false, + pidk); /* Now, build an appropriate representation. */ switch (unary_operator) { @@ -6644,7 +7043,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p, non_constant_p = NIC_STAR; expression = build_x_indirect_ref (loc, cast_expression, RO_UNARY_STAR, - tf_warning_or_error); + complain); break; case ADDR_EXPR: @@ -6653,7 +7052,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p, case BIT_NOT_EXPR: expression = build_x_unary_op (loc, unary_operator, cast_expression, - tf_warning_or_error); + complain); break; case PREINCREMENT_EXPR: @@ -6665,7 +7064,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p, case NEGATE_EXPR: case TRUTH_NOT_EXPR: expression = finish_unary_op_expr (loc, unary_operator, - cast_expression); + cast_expression, complain); break; default: @@ -6682,9 +7081,18 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p, return cp_parser_postfix_expression (parser, address_p, cast_p, /*member_access_only_p=*/false, + decltype_p, pidk); } +static inline tree +cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p, + cp_id_kind * pidk) +{ + return cp_parser_unary_expression (parser, address_p, cast_p, + /*decltype*/false, pidk); +} + /* Returns ERROR_MARK if TOKEN is not a unary-operator. If TOKEN is a unary-operator, the corresponding tree code is returned. */ @@ -7163,7 +7571,7 @@ cp_parser_tokens_start_cast_expression (cp_parser *parser) static tree cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, - cp_id_kind * pidk) + bool decltype_p, cp_id_kind * pidk) { /* If it's a `(', then we might be looking at a cast. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) @@ -7237,7 +7645,9 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, cp_parser_parse_definitely (parser); expr = cp_parser_cast_expression (parser, /*address_p=*/false, - /*cast_p=*/true, pidk); + /*cast_p=*/true, + /*decltype_p=*/false, + pidk); /* Warn about old-style casts, if so requested. */ if (warn_old_style_cast @@ -7263,7 +7673,8 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, /* If we get here, then it's not a cast, so it must be a unary-expression. */ - return cp_parser_unary_expression (parser, address_p, cast_p, pidk); + return cp_parser_unary_expression (parser, address_p, cast_p, + decltype_p, pidk); } /* Parse a binary expression of the general form: @@ -7348,6 +7759,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, static tree cp_parser_binary_expression (cp_parser* parser, bool cast_p, bool no_toplevel_fold_p, + bool decltype_p, enum cp_parser_prec prec, cp_id_kind * pidk) { @@ -7362,7 +7774,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, /* Parse the first expression. */ current.lhs = cp_parser_cast_expression (parser, /*address_p=*/false, - cast_p, pidk); + cast_p, decltype_p, pidk); current.lhs_type = ERROR_MARK; current.prec = prec; @@ -7479,7 +7891,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, current.lhs = build_x_binary_op (current.loc, current.tree_type, current.lhs, current.lhs_type, rhs, rhs_type, &overload, - tf_warning_or_error); + complain_flags (decltype_p)); current.lhs_type = current.tree_type; if (EXPR_P (current.lhs)) SET_EXPR_LOCATION (current.lhs, current.loc); @@ -7499,6 +7911,15 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, return current.lhs; } +static tree +cp_parser_binary_expression (cp_parser* parser, bool cast_p, + bool no_toplevel_fold_p, + enum cp_parser_prec prec, + cp_id_kind * pidk) +{ + return cp_parser_binary_expression (parser, cast_p, no_toplevel_fold_p, + /*decltype*/false, prec, pidk); +} /* Parse the `? expression : assignment-expression' part of a conditional-expression. The LOGICAL_OR_EXPR is the @@ -7568,12 +7989,13 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr) throw-expression CAST_P is true if this expression is the target of a cast. + DECLTYPE_P is true if this expression is the operand of decltype. Returns a representation for the expression. */ static tree cp_parser_assignment_expression (cp_parser* parser, bool cast_p, - cp_id_kind * pidk) + bool decltype_p, cp_id_kind * pidk) { tree expr; @@ -7587,6 +8009,7 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p, { /* Parse the binary expressions (logical-or-expression). */ expr = cp_parser_binary_expression (parser, cast_p, false, + decltype_p, PREC_NOT_OPERATOR, pidk); /* If the next token is a `?' then we're actually looking at a conditional-expression. */ @@ -7623,7 +8046,7 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p, expr = build_x_modify_expr (loc, expr, assignment_operator, rhs, - tf_warning_or_error); + complain_flags (decltype_p)); input_location = saved_input_location; } } @@ -7632,6 +8055,14 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p, return expr; } +static tree +cp_parser_assignment_expression (cp_parser* parser, bool cast_p, + cp_id_kind * pidk) +{ + return cp_parser_assignment_expression (parser, cast_p, + /*decltype*/false, pidk); +} + /* Parse an (optional) assignment-operator. assignment-operator: one of @@ -7723,11 +8154,14 @@ cp_parser_assignment_operator_opt (cp_parser* parser) expression , assignment-expression CAST_P is true if this expression is the target of a cast. + DECLTYPE_P is true if this expression is the immediate operand of decltype, + except possibly parenthesized or on the RHS of a comma (N3276). Returns a representation of the expression. */ static tree -cp_parser_expression (cp_parser* parser, bool cast_p, cp_id_kind * pidk) +cp_parser_expression (cp_parser* parser, bool cast_p, bool decltype_p, + cp_id_kind * pidk) { tree expression = NULL_TREE; location_t loc = UNKNOWN_LOCATION; @@ -7738,7 +8172,19 @@ cp_parser_expression (cp_parser* parser, bool cast_p, cp_id_kind * pidk) /* Parse the next assignment-expression. */ assignment_expression - = cp_parser_assignment_expression (parser, cast_p, pidk); + = cp_parser_assignment_expression (parser, cast_p, decltype_p, pidk); + + /* We don't create a temporary for a call that is the immediate operand + of decltype or on the RHS of a comma. But when we see a comma, we + need to create a temporary for a call on the LHS. */ + if (decltype_p && !processing_template_decl + && TREE_CODE (assignment_expression) == CALL_EXPR + && CLASS_TYPE_P (TREE_TYPE (assignment_expression)) + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + assignment_expression + = build_cplus_new (TREE_TYPE (assignment_expression), + assignment_expression, tf_warning_or_error); + /* If this is the first assignment-expression, we can just save it away. */ if (!expression) @@ -7746,7 +8192,7 @@ cp_parser_expression (cp_parser* parser, bool cast_p, cp_id_kind * pidk) else expression = build_x_compound_expr (loc, expression, assignment_expression, - tf_warning_or_error); + complain_flags (decltype_p)); /* If the next token is not a comma, then we are done with the expression. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) @@ -7762,6 +8208,12 @@ cp_parser_expression (cp_parser* parser, bool cast_p, cp_id_kind * pidk) return expression; } +static inline tree +cp_parser_expression (cp_parser* parser, bool cast_p, cp_id_kind * pidk) +{ + return cp_parser_expression (parser, cast_p, /*decltype*/false, pidk); +} + /* Parse a constant-expression. constant-expression: @@ -7807,7 +8259,7 @@ cp_parser_constant_expression (cp_parser* parser, /* We are now parsing a constant-expression. */ parser->integral_constant_expression_p = true; parser->allow_non_integral_constant_expression_p - = (allow_non_constant_p || cxx_dialect >= cxx0x); + = (allow_non_constant_p || cxx_dialect >= cxx11); parser->non_integral_constant_expression_p = false; /* Although the grammar says "conditional-expression", we parse an "assignment-expression", which also permits "throw-expression" @@ -7824,7 +8276,7 @@ cp_parser_constant_expression (cp_parser* parser, = saved_integral_constant_expression_p; parser->allow_non_integral_constant_expression_p = saved_allow_non_integral_constant_expression_p; - if (cxx_dialect >= cxx0x) + if (cxx_dialect >= cxx11) { /* Require an rvalue constant expression here; that's what our callers expect. Reference constant expressions are handled @@ -7891,12 +8343,14 @@ cp_parser_builtin_offsetof (cp_parser *parser) { case CPP_OPEN_SQUARE: /* offsetof-member-designator "[" expression "]" */ - expr = cp_parser_postfix_open_square_expression (parser, expr, true); + expr = cp_parser_postfix_open_square_expression (parser, expr, + true, false); break; case CPP_DEREF: /* offsetof-member-designator "->" identifier */ - expr = grok_array_decl (token->location, expr, integer_zero_node); + expr = grok_array_decl (token->location, expr, + integer_zero_node, false); /* FALLTHRU */ case CPP_DOT: @@ -8196,19 +8650,8 @@ cp_parser_lambda_expression (cp_parser* parser) cp_parser_skip_to_end_of_block_or_statement (parser); /* The capture list was built up in reverse order; fix that now. */ - { - tree newlist = NULL_TREE; - tree elt, next; - - for (elt = LAMBDA_EXPR_CAPTURE_LIST (lambda_expr); - elt; elt = next) - { - next = TREE_CHAIN (elt); - TREE_CHAIN (elt) = newlist; - newlist = elt; - } - LAMBDA_EXPR_CAPTURE_LIST (lambda_expr) = newlist; - } + LAMBDA_EXPR_CAPTURE_LIST (lambda_expr) + = nreverse (LAMBDA_EXPR_CAPTURE_LIST (lambda_expr)); if (ok) maybe_add_lambda_conv_op (type); @@ -8332,16 +8775,18 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) } /* Find the initializer for this capture. */ - if (cp_lexer_next_token_is (parser->lexer, CPP_EQ)) + if (cp_lexer_next_token_is (parser->lexer, CPP_EQ) + || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN) + || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) { - /* An explicit expression exists. */ - cp_lexer_consume_token (parser->lexer); - pedwarn (input_location, OPT_Wpedantic, - "ISO C++ does not allow initializers " - "in lambda expression capture lists"); - capture_init_expr = cp_parser_assignment_expression (parser, - /*cast_p=*/true, - &idk); + bool direct, non_constant; + /* An explicit initializer exists. */ + if (cxx_dialect < cxx1y) + pedwarn (input_location, 0, + "lambda capture initializers " + "only available with -std=c++1y or -std=gnu++1y"); + capture_init_expr = cp_parser_initializer (parser, &direct, + &non_constant); explicit_init_p = true; } else @@ -8366,7 +8811,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) continue; } else if (DECL_P (capture_init_expr) - && (TREE_CODE (capture_init_expr) != VAR_DECL + && (!VAR_P (capture_init_expr) && TREE_CODE (capture_init_expr) != PARM_DECL)) { error_at (capture_token->location, @@ -8375,7 +8820,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) inform (0, "%q+#D declared here", capture_init_expr); continue; } - if (TREE_CODE (capture_init_expr) == VAR_DECL + if (VAR_P (capture_init_expr) && decl_storage_duration (capture_init_expr) != dk_auto) { pedwarn (capture_token->location, 0, "capture of variable " @@ -8487,7 +8932,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) if (cp_lexer_next_token_is (parser->lexer, CPP_DEREF)) { cp_lexer_consume_token (parser->lexer); - LAMBDA_EXPR_RETURN_TYPE (lambda_expr) = cp_parser_type_id (parser); + LAMBDA_EXPR_RETURN_TYPE (lambda_expr) + = cp_parser_trailing_type_id (parser); } /* The function parameters must be in scope all the way until after the @@ -8526,6 +8972,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) ? TYPE_UNQUALIFIED : TYPE_QUAL_CONST); declarator = make_call_declarator (declarator, param_list, quals, VIRT_SPEC_UNSPECIFIED, + REF_QUAL_NONE, exception_spec, /*late_return_type=*/NULL_TREE); declarator->id_loc = LAMBDA_EXPR_LOCATION (lambda_expr); @@ -9018,7 +9465,15 @@ cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr) /* If the next token is a ';', then there is no expression statement. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) - statement = cp_parser_expression (parser, /*cast_p=*/false, NULL); + { + statement = cp_parser_expression (parser, /*cast_p=*/false, NULL); + if (statement == error_mark_node + && !cp_parser_uncommitted_to_tentative_parse_p (parser)) + { + cp_parser_skip_to_end_of_block_or_statement (parser); + return error_mark_node; + } + } /* Give a helpful message for "A<T>::type t;" and the like. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON) @@ -9096,6 +9551,8 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr, /* Consume the `}'. */ cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); + if (flag_enable_cilkplus && contains_array_notation_expr (compound_stmt)) + compound_stmt = expand_array_notation_exprs (compound_stmt); return compound_stmt; } @@ -9288,6 +9745,14 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p) /* Now we're all done with the switch-statement. */ finish_switch_stmt (statement); + if (flag_enable_cilkplus + && contains_array_notation_expr (condition)) + { + error_at (EXPR_LOCATION (condition), + "array notations cannot be used as a condition for " + "switch statement"); + statement = error_mark_node; + } } return statement; @@ -9603,13 +10068,21 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr) begin_expr = end_expr = iter_type = error_mark_node; else { - tree range_temp = build_range_temp (range_expr); - pushdecl (range_temp); - cp_finish_decl (range_temp, range_expr, - /*is_constant_init*/false, NULL_TREE, - LOOKUP_ONLYCONVERTING); + tree range_temp; - range_temp = convert_from_reference (range_temp); + if (TREE_CODE (range_expr) == VAR_DECL + && array_of_runtime_bound_p (TREE_TYPE (range_expr))) + /* Can't bind a reference to an array of runtime bound. */ + range_temp = range_expr; + else + { + range_temp = build_range_temp (range_expr); + pushdecl (range_temp); + cp_finish_decl (range_temp, range_expr, + /*is_constant_init*/false, NULL_TREE, + LOOKUP_ONLYCONVERTING); + range_temp = convert_from_reference (range_temp); + } iter_type = cp_parser_perform_range_for_lookup (range_temp, &begin_expr, &end_expr); } @@ -9644,7 +10117,8 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr) /* The new increment expression. */ expression = finish_unary_op_expr (input_location, - PREINCREMENT_EXPR, begin); + PREINCREMENT_EXPR, begin, + tf_warning_or_error); finish_for_expr (expression, statement); /* The declaration is initialized with *__begin inside the loop body. */ @@ -9836,6 +10310,12 @@ cp_parser_iteration_statement (cp_parser* parser) parser->in_statement = in_statement; /* We're done with the while-statement. */ finish_while_stmt (statement); + if (flag_enable_cilkplus && contains_array_notation_expr (condition)) + { + error_at (EXPR_LOCATION (condition), "array notations cannot be " + "used as a condition for while statement"); + statement = error_mark_node; + } } break; @@ -9862,6 +10342,15 @@ cp_parser_iteration_statement (cp_parser* parser) cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); /* Look for the `;'. */ cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); + if (flag_enable_cilkplus + && contains_array_notation_expr (DO_COND (statement))) + { + error_at (EXPR_LOCATION (DO_COND (statement)), + "array notations cannot be used as a condition for a " + "do-while statement"); + statement = error_mark_node; + } + } break; @@ -9880,8 +10369,17 @@ cp_parser_iteration_statement (cp_parser* parser) cp_parser_already_scoped_statement (parser); parser->in_statement = in_statement; - /* We're done with the for-statement. */ - finish_for_stmt (statement); + if (flag_enable_cilkplus + && contains_array_notation_expr (FOR_COND (statement))) + { + error_at (EXPR_LOCATION (FOR_COND (statement)), + "array notations cannot be used in a condition for a " + "for-loop"); + statement = error_mark_node; + } + else + /* We're done with the for-statement. */ + finish_for_stmt (statement); } break; @@ -9930,7 +10428,7 @@ cp_parser_for_init_statement (cp_parser* parser, tree *decl) /* It is a range-for, consume the ':' */ cp_lexer_consume_token (parser->lexer); is_range_for = true; - if (cxx_dialect < cxx0x) + if (cxx_dialect < cxx11) { error_at (cp_lexer_peek_token (parser->lexer)->location, "range-based %<for%> loops are not allowed " @@ -10418,7 +10916,7 @@ cp_parser_block_declaration (cp_parser *parser, cp_parser_using_directive (parser); /* If the second token after 'using' is '=', then we have an alias-declaration. */ - else if (cxx_dialect >= cxx0x + else if (cxx_dialect >= cxx11 && token2->type == CPP_NAME && ((cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_EQ) || (cp_nth_tokens_can_be_attribute_p (parser, 3)))) @@ -11172,59 +11670,15 @@ cp_parser_static_assert(cp_parser *parser, bool member_p) finish_static_assert (condition, message, saved_loc, member_p); } -/* Parse a `decltype' type. Returns the type. - - simple-type-specifier: - decltype ( expression ) */ +/* Parse the expression in decltype ( expression ). */ static tree -cp_parser_decltype (cp_parser *parser) +cp_parser_decltype_expr (cp_parser *parser, + bool &id_expression_or_member_access_p) { - tree expr; - bool id_expression_or_member_access_p = false; - const char *saved_message; - bool saved_integral_constant_expression_p; - bool saved_non_integral_constant_expression_p; cp_token *id_expr_start_token; - cp_token *start_token = cp_lexer_peek_token (parser->lexer); - - if (start_token->type == CPP_DECLTYPE) - { - /* Already parsed. */ - cp_lexer_consume_token (parser->lexer); - return start_token->u.value; - } - - /* Look for the `decltype' token. */ - if (!cp_parser_require_keyword (parser, RID_DECLTYPE, RT_DECLTYPE)) - return error_mark_node; - - /* Types cannot be defined in a `decltype' expression. Save away the - old message. */ - saved_message = parser->type_definition_forbidden_message; - - /* And create the new one. */ - parser->type_definition_forbidden_message - = G_("types may not be defined in %<decltype%> expressions"); - - /* The restrictions on constant-expressions do not apply inside - decltype expressions. */ - saved_integral_constant_expression_p - = parser->integral_constant_expression_p; - saved_non_integral_constant_expression_p - = parser->non_integral_constant_expression_p; - parser->integral_constant_expression_p = false; - - /* Do not actually evaluate the expression. */ - ++cp_unevaluated_operand; - - /* Do not warn about problems with the expression. */ - ++c_inhibit_evaluation_warnings; + tree expr; - /* Parse the opening `('. */ - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) - return error_mark_node; - /* First, try parsing an id-expression. */ id_expr_start_token = cp_lexer_peek_token (parser->lexer); cp_parser_parse_tentatively (parser); @@ -11242,7 +11696,7 @@ cp_parser_decltype (cp_parser *parser) cp_id_kind idk; const char *error_msg; - if (TREE_CODE (expr) == IDENTIFIER_NODE) + if (identifier_p (expr)) /* Lookup the name we got back from the id-expression. */ expr = cp_parser_lookup_name (parser, expr, none_type, @@ -11299,7 +11753,7 @@ cp_parser_decltype (cp_parser *parser) /* Parse a class member access. */ expr = cp_parser_postfix_expression (parser, /*address_p=*/false, - /*cast_p=*/false, + /*cast_p=*/false, /*decltype*/true, /*member_access_only_p=*/true, NULL); if (expr @@ -11314,31 +11768,102 @@ cp_parser_decltype (cp_parser *parser) cp_parser_parse_definitely (parser); else { - bool saved_greater_than_is_operator_p; - /* Abort our attempt to parse an id-expression or member access expression. */ cp_parser_abort_tentative_parse (parser); - /* Within a parenthesized expression, a `>' token is always - the greater-than operator. */ - saved_greater_than_is_operator_p - = parser->greater_than_is_operator_p; - parser->greater_than_is_operator_p = true; - /* Parse a full expression. */ - expr = cp_parser_expression (parser, /*cast_p=*/false, NULL); + expr = cp_parser_expression (parser, /*cast_p=*/false, + /*decltype*/true, NULL); + } + + return expr; +} + +/* Parse a `decltype' type. Returns the type. + + simple-type-specifier: + decltype ( expression ) + C++14 proposal: + decltype ( auto ) */ + +static tree +cp_parser_decltype (cp_parser *parser) +{ + tree expr; + bool id_expression_or_member_access_p = false; + const char *saved_message; + bool saved_integral_constant_expression_p; + bool saved_non_integral_constant_expression_p; + bool saved_greater_than_is_operator_p; + cp_token *start_token = cp_lexer_peek_token (parser->lexer); - /* The `>' token might be the end of a template-id or - template-parameter-list now. */ - parser->greater_than_is_operator_p - = saved_greater_than_is_operator_p; + if (start_token->type == CPP_DECLTYPE) + { + /* Already parsed. */ + cp_lexer_consume_token (parser->lexer); + return start_token->u.value; } + /* Look for the `decltype' token. */ + if (!cp_parser_require_keyword (parser, RID_DECLTYPE, RT_DECLTYPE)) + return error_mark_node; + + /* Parse the opening `('. */ + if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + return error_mark_node; + + /* decltype (auto) */ + if (cxx_dialect >= cxx1y + && cp_lexer_next_token_is_keyword (parser->lexer, RID_AUTO)) + { + cp_lexer_consume_token (parser->lexer); + if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + return error_mark_node; + expr = make_decltype_auto (); + AUTO_IS_DECLTYPE (expr) = true; + goto rewrite; + } + + /* Types cannot be defined in a `decltype' expression. Save away the + old message. */ + saved_message = parser->type_definition_forbidden_message; + + /* And create the new one. */ + parser->type_definition_forbidden_message + = G_("types may not be defined in %<decltype%> expressions"); + + /* The restrictions on constant-expressions do not apply inside + decltype expressions. */ + saved_integral_constant_expression_p + = parser->integral_constant_expression_p; + saved_non_integral_constant_expression_p + = parser->non_integral_constant_expression_p; + parser->integral_constant_expression_p = false; + + /* Within a parenthesized expression, a `>' token is always + the greater-than operator. */ + saved_greater_than_is_operator_p + = parser->greater_than_is_operator_p; + parser->greater_than_is_operator_p = true; + + /* Do not actually evaluate the expression. */ + ++cp_unevaluated_operand; + + /* Do not warn about problems with the expression. */ + ++c_inhibit_evaluation_warnings; + + expr = cp_parser_decltype_expr (parser, id_expression_or_member_access_p); + /* Go back to evaluating expressions. */ --cp_unevaluated_operand; --c_inhibit_evaluation_warnings; + /* The `>' token might be the end of a template-id or + template-parameter-list now. */ + parser->greater_than_is_operator_p + = saved_greater_than_is_operator_p; + /* Restore the old message and the integral constant expression flags. */ parser->type_definition_forbidden_message = saved_message; @@ -11358,6 +11883,7 @@ cp_parser_decltype (cp_parser *parser) expr = finish_decltype_type (expr, id_expression_or_member_access_p, tf_warning_or_error); + rewrite: /* Replace the decltype with a CPP_DECLTYPE so we don't need to parse it again. */ start_token->type = CPP_DECLTYPE; @@ -11439,13 +11965,22 @@ cp_parser_conversion_type_id (cp_parser* parser) cp_decl_specifier_seq type_specifiers; cp_declarator *declarator; tree type_specified; + const char *saved_message; /* Parse the attributes. */ attributes = cp_parser_attributes_opt (parser); + + saved_message = parser->type_definition_forbidden_message; + parser->type_definition_forbidden_message + = G_("types may not be defined in a conversion-type-id"); + /* Parse the type-specifiers. */ cp_parser_type_specifier_seq (parser, /*is_declaration=*/false, /*is_trailing_return=*/false, &type_specifiers); + + parser->type_definition_forbidden_message = saved_message; + /* If that didn't work, stop. */ if (type_specifiers.type == error_mark_node) return error_mark_node; @@ -11811,7 +12346,6 @@ cp_literal_operator_id (const char* name) + strlen (name) + 10); sprintf (buffer, UDLIT_OP_ANSI_FORMAT, name); identifier = get_identifier (buffer); - /*IDENTIFIER_UDLIT_OPNAME_P (identifier) = 1; If we get a flag someday. */ return identifier; } @@ -12690,7 +13224,7 @@ cp_parser_template_id (cp_parser *parser, } /* Build a representation of the specialization. */ - if (TREE_CODE (templ) == IDENTIFIER_NODE) + if (identifier_p (templ)) template_id = build_min_nt_loc (next_token->location, TEMPLATE_ID_EXPR, templ, arguments); @@ -12750,7 +13284,7 @@ cp_parser_template_id (cp_parser *parser, error_at (token->location, "parse error in template argument list"); } - pop_deferring_access_checks (); + pop_to_parent_deferring_access_checks (); return template_id; } @@ -13205,7 +13739,7 @@ cp_parser_template_argument (cp_parser* parser) { tree probe; - if (TREE_CODE (argument) == INDIRECT_REF) + if (INDIRECT_REF_P (argument)) { gcc_assert (REFERENCE_REF_P (argument)); argument = TREE_OPERAND (argument, 0); @@ -13217,7 +13751,7 @@ cp_parser_template_argument (cp_parser* parser) probe = argument; if (TREE_CODE (probe) == SCOPE_REF) probe = TREE_OPERAND (probe, 1); - if (TREE_CODE (probe) == VAR_DECL) + if (VAR_P (probe)) { /* A variable without external linkage might still be a valid constant-expression, so no error is issued here @@ -13266,7 +13800,6 @@ cp_parser_template_argument (cp_parser* parser) argument = cp_parser_constant_expression (parser, /*allow_non_constant_p=*/false, /*non_constant_p=*/NULL); - argument = fold_non_dependent_expr (argument); if (!maybe_type_id) return argument; if (!cp_parser_next_token_ends_template_argument_p (parser)) @@ -13693,6 +14226,7 @@ cp_parser_type_specifier (cp_parser* parser, __int128 __typeof__ unary-expression __typeof__ ( type-id ) + __typeof__ ( type-id ) { initializer-list , [opt] } Returns the indicated TYPE_DECL. If DECL_SPECS is not NULL, it is appropriately updated. */ @@ -13912,7 +14446,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, && !global_p && !qualified_p && TREE_CODE (type) == TYPE_DECL - && TREE_CODE (DECL_NAME (type)) == IDENTIFIER_NODE) + && identifier_p (DECL_NAME (type))) maybe_note_name_used_in_class (DECL_NAME (type), type); /* If it didn't work out, we don't have a TYPE. */ if ((flags & CP_PARSER_FLAGS_OPTIONAL) @@ -13998,7 +14532,7 @@ cp_parser_type_name (cp_parser* parser) /* If it's not a class-name, keep looking. */ if (!cp_parser_parse_definitely (parser)) { - if (cxx_dialect < cxx0x) + if (cxx_dialect < cxx11) /* It must be a typedef-name or an enum-name. */ return cp_parser_nonclass_name (parser); @@ -14534,7 +15068,7 @@ cp_parser_enum_specifier (cp_parser* parser) if (cp_lexer_next_token_is_keyword (parser->lexer, RID_CLASS) || cp_lexer_next_token_is_keyword (parser->lexer, RID_STRUCT)) { - if (cxx_dialect < cxx0x) + if (cxx_dialect < cxx11) maybe_warn_cpp0x (CPP0X_SCOPED_ENUMS); /* Consume the `struct' or `class' token. */ @@ -14589,6 +15123,8 @@ cp_parser_enum_specifier (cp_parser* parser) type = NULL_TREE; } } + else if (nested_name_specifier == error_mark_node) + /* We already issued an error. */; else error_at (type_start_token->location, "%qD is not an enumerator-name", identifier); @@ -14601,6 +15137,9 @@ cp_parser_enum_specifier (cp_parser* parser) { identifier = make_anon_name (); is_anonymous = true; + if (scoped_enum_p) + error_at (type_start_token->location, + "anonymous scoped enum is not allowed"); } } pop_deferring_access_checks (); @@ -14623,7 +15162,7 @@ cp_parser_enum_specifier (cp_parser* parser) if (!cp_parser_parse_definitely (parser)) return NULL_TREE; - if (cxx_dialect < cxx0x) + if (cxx_dialect < cxx11) maybe_warn_cpp0x (CPP0X_SCOPED_ENUMS); has_underlying_type = true; @@ -14641,7 +15180,7 @@ cp_parser_enum_specifier (cp_parser* parser) /* Look for the `{' but don't consume it yet. */ if (!cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) { - if (cxx_dialect < cxx0x || (!scoped_enum_p && !underlying_type)) + if (cxx_dialect < cxx11 || (!scoped_enum_p && !underlying_type)) { cp_parser_error (parser, "expected %<{%>"); if (has_underlying_type) @@ -14695,7 +15234,8 @@ cp_parser_enum_specifier (cp_parser* parser) if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) { timevar_push (TV_PARSE_ENUM); - if (nested_name_specifier) + if (nested_name_specifier + && nested_name_specifier != error_mark_node) { /* The following catches invalid code such as: enum class S<int>::E { A, B, C }; */ @@ -14748,7 +15288,13 @@ cp_parser_enum_specifier (cp_parser* parser) if (type == error_mark_node) cp_parser_skip_to_end_of_block_or_statement (parser); /* If the next token is not '}', then there are some enumerators. */ - else if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE)) + else if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)) + { + if (is_anonymous && !scoped_enum_p) + pedwarn (type_start_token->location, OPT_Wpedantic, + "ISO C++ forbids empty anonymous enum"); + } + else cp_parser_enumerator_list (parser, type); /* Consume the final '}'. */ @@ -14834,7 +15380,7 @@ cp_parser_enumerator_list (cp_parser* parser, tree type) /* If the next token is a `}', there is a trailing comma. */ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)) { - if (cxx_dialect < cxx0x && !in_system_header) + if (cxx_dialect < cxx11 && !in_system_header) pedwarn (input_location, OPT_Wpedantic, "comma at end of enumerator list"); break; @@ -15211,7 +15757,7 @@ cp_parser_using_declaration (cp_parser* parser, depending on what scope we are in. */ if (qscope == error_mark_node || identifier == error_mark_node) ; - else if (TREE_CODE (identifier) != IDENTIFIER_NODE + else if (!identifier_p (identifier) && TREE_CODE (identifier) != BIT_NOT_EXPR) /* [namespace.udecl] @@ -16168,6 +16714,7 @@ cp_parser_declarator (cp_parser* parser, declarator-id direct-declarator ( parameter-declaration-clause ) cv-qualifier-seq [opt] + ref-qualifier [opt] exception-specification [opt] direct-declarator [ constant-expression [opt] ] ( declarator ) @@ -16176,6 +16723,7 @@ cp_parser_declarator (cp_parser* parser, direct-abstract-declarator [opt] ( parameter-declaration-clause ) cv-qualifier-seq [opt] + ref-qualifier [opt] exception-specification [opt] direct-abstract-declarator [opt] [ constant-expression [opt] ] ( abstract-declarator ) @@ -16290,15 +16838,18 @@ cp_parser_direct_declarator (cp_parser* parser, /* Consume the `)'. */ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); - /* If all went well, parse the cv-qualifier-seq and the - exception-specification. */ + /* If all went well, parse the cv-qualifier-seq, + ref-qualifier and the exception-specification. */ if (member_p || cp_parser_parse_definitely (parser)) { cp_cv_quals cv_quals; cp_virt_specifiers virt_specifiers; + cp_ref_qualifier ref_qual; tree exception_specification; tree late_return; tree attrs; + bool memfn = (member_p || (pushed_scope + && CLASS_TYPE_P (pushed_scope))); is_declarator = true; @@ -16308,6 +16859,8 @@ cp_parser_direct_declarator (cp_parser* parser, /* Parse the cv-qualifier-seq. */ cv_quals = cp_parser_cv_qualifier_seq_opt (parser); + /* Parse the ref-qualifier. */ + ref_qual = cp_parser_ref_qualifier_opt (parser); /* And the exception-specification. */ exception_specification = cp_parser_exception_specification_opt (parser); @@ -16315,7 +16868,7 @@ cp_parser_direct_declarator (cp_parser* parser, attrs = cp_parser_std_attribute_spec_seq (parser); late_return = (cp_parser_late_return_type_opt - (parser, member_p ? cv_quals : -1)); + (parser, memfn ? cv_quals : -1)); /* Parse the virt-specifier-seq. */ virt_specifiers = cp_parser_virt_specifier_seq_opt (parser); @@ -16325,6 +16878,7 @@ cp_parser_direct_declarator (cp_parser* parser, params, cv_quals, virt_specifiers, + ref_qual, exception_specification, late_return); declarator->std_attributes = attrs; @@ -16399,30 +16953,53 @@ cp_parser_direct_declarator (cp_parser* parser, { bool non_constant_p; - bounds - = cp_parser_constant_expression (parser, - /*allow_non_constant=*/true, - &non_constant_p); - if (!non_constant_p) - /* OK */; - else if (error_operand_p (bounds)) - /* Already gave an error. */; - else if (!parser->in_function_body - || current_binding_level->kind == sk_function_parms) + if (flag_enable_cilkplus + && cp_lexer_next_token_is (parser->lexer, CPP_COLON)) { - /* Normally, the array bound must be an integral constant - expression. However, as an extension, we allow VLAs - in function scopes as long as they aren't part of a - parameter declaration. */ - cp_parser_error (parser, - "array bound is not an integer constant"); bounds = error_mark_node; + error_at (cp_lexer_peek_token (parser->lexer)->location, + "array notations cannot be used in declaration"); + cp_lexer_consume_token (parser->lexer); } - else if (processing_template_decl) + else { - /* Remember this wasn't a constant-expression. */ - bounds = build_nop (TREE_TYPE (bounds), bounds); - TREE_SIDE_EFFECTS (bounds) = 1; + bounds + = cp_parser_constant_expression (parser, + /*allow_non_constant=*/true, + &non_constant_p); + if (!non_constant_p) + /* OK */; + else if (error_operand_p (bounds)) + /* Already gave an error. */; + else if (!parser->in_function_body + || current_binding_level->kind == sk_function_parms) + { + /* Normally, the array bound must be an integral constant + expression. However, as an extension, we allow VLAs + in function scopes as long as they aren't part of a + parameter declaration. */ + cp_parser_error (parser, + "array bound is not an integer constant"); + bounds = error_mark_node; + } + else if (processing_template_decl) + { + /* Remember this wasn't a constant-expression. */ + bounds = build_nop (TREE_TYPE (bounds), bounds); + TREE_SIDE_EFFECTS (bounds) = 1; + } + if (flag_enable_cilkplus + && cp_lexer_next_token_is (parser->lexer, CPP_COLON)) + { + location_t loc = + cp_lexer_peek_token (parser->lexer)->location; + while (cp_lexer_next_token_is_not (parser->lexer, + CPP_CLOSE_SQUARE)) + cp_lexer_consume_token (parser->lexer); + error_at (loc, "array notations cannot be used in " + "declaration"); + bounds = error_mark_node; + } } } else @@ -16492,8 +17069,7 @@ cp_parser_direct_declarator (cp_parser* parser, unqualified_name = error_mark_node; else if (unqualified_name && (qualifying_scope - || (TREE_CODE (unqualified_name) - != IDENTIFIER_NODE))) + || (!identifier_p (unqualified_name)))) { cp_parser_error (parser, "expected unqualified-id"); unqualified_name = error_mark_node; @@ -16637,9 +17213,18 @@ cp_parser_direct_declarator (cp_parser* parser, handle_declarator:; scope = get_scope_of_declarator (declarator); if (scope) - /* Any names that appear after the declarator-id for a - member are looked up in the containing scope. */ - pushed_scope = push_scope (scope); + { + /* Any names that appear after the declarator-id for a + member are looked up in the containing scope. */ + if (at_function_scope_p ()) + { + /* But declarations with qualified-ids can't appear in a + function. */ + cp_parser_error (parser, "qualified-id in declaration"); + break; + } + pushed_scope = push_scope (scope); + } parser->in_declarator_p = true; if ((ctor_dtor_or_conv_p && *ctor_dtor_or_conv_p) || (declarator && declarator->kind == cdk_id)) @@ -16857,6 +17442,56 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser) return cv_quals; } +/* Parse an (optional) ref-qualifier + + ref-qualifier: + & + && + + Returns cp_ref_qualifier representing ref-qualifier. */ + +static cp_ref_qualifier +cp_parser_ref_qualifier_opt (cp_parser* parser) +{ + cp_ref_qualifier ref_qual = REF_QUAL_NONE; + + while (true) + { + cp_ref_qualifier curr_ref_qual = REF_QUAL_NONE; + cp_token *token = cp_lexer_peek_token (parser->lexer); + + switch (token->type) + { + case CPP_AND: + curr_ref_qual = REF_QUAL_LVALUE; + break; + + case CPP_AND_AND: + curr_ref_qual = REF_QUAL_RVALUE; + break; + + default: + curr_ref_qual = REF_QUAL_NONE; + break; + } + + if (!curr_ref_qual) + break; + else if (ref_qual) + { + error_at (token->location, "multiple ref-qualifiers"); + cp_lexer_purge_token (parser->lexer); + } + else + { + ref_qual = curr_ref_qual; + cp_lexer_consume_token (parser->lexer); + } + } + + return ref_qual; +} + /* Parse an (optional) virt-specifier-seq. virt-specifier-seq: @@ -16939,6 +17574,19 @@ inject_this_parameter (tree ctype, cp_cv_quals quals) current_class_ptr = this_parm; } +/* Return true iff our current scope is a non-static data member + initializer. */ + +bool +parsing_nsdmi (void) +{ + /* We recognize NSDMI context by the context-less 'this' pointer set up + by the function above. */ + if (current_class_ptr && DECL_CONTEXT (current_class_ptr) == NULL_TREE) + return true; + return false; +} + /* Parse a late-specified return type, if any. This is not a separate non-terminal, but part of a function declarator, which looks like @@ -16964,17 +17612,21 @@ cp_parser_late_return_type_opt (cp_parser* parser, cp_cv_quals quals) /* Consume the ->. */ cp_lexer_consume_token (parser->lexer); + tree save_ccp = current_class_ptr; + tree save_ccr = current_class_ref; if (quals >= 0) { /* DR 1207: 'this' is in scope in the trailing return type. */ - gcc_assert (current_class_ptr == NULL_TREE); inject_this_parameter (current_class_type, quals); } type = cp_parser_trailing_type_id (parser); if (quals >= 0) - current_class_ptr = current_class_ref = NULL_TREE; + { + current_class_ptr = save_ccp; + current_class_ref = save_ccr; + } return type; } @@ -17054,6 +17706,7 @@ cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg, abstract_declarator = NULL; if (type_specifier_seq.type + && cxx_dialect < cxx1y && type_uses_auto (type_specifier_seq.type)) { /* A type-id with type 'auto' is only ok if the abstract declarator @@ -17398,7 +18051,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) && !parser->in_type_id_in_expr_p && cp_parser_uncommitted_to_tentative_parse_p (parser) /* However, a parameter-declaration of the form - "foat(f)" (which is a valid declaration of a + "float(f)" (which is a valid declaration of a parameter "f") can also be interpreted as an expression (the conversion of "f" to "float"). */ && !parenthesized_p) @@ -17472,8 +18125,9 @@ cp_parser_parameter_declaration (cp_parser *parser, &declares_class_or_enum); /* Complain about missing 'typename' or other invalid type names. */ - if (!decl_specifiers.any_type_specifiers_p) - cp_parser_parse_and_diagnose_invalid_type_name (parser); + if (!decl_specifiers.any_type_specifiers_p + && cp_parser_parse_and_diagnose_invalid_type_name (parser)) + decl_specifiers.type = error_mark_node; /* If an error occurred, there's no reason to attempt to parse the rest of the declaration. */ @@ -17716,6 +18370,11 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser, cp_parser_function_body (parser, in_function_try_block); if (check_body_p) check_constexpr_ctor_body (last, list); + + /* Transform all array notations to the equivalent array refs and loop. */ + if (flag_enable_cilkplus && contains_array_notation_expr (body)) + body = expand_array_notation_exprs (body); + /* Finish the function body. */ finish_function_body (body); @@ -18130,7 +18789,7 @@ cp_parser_class_name (cp_parser *parser, /* Check to see that it is really the name of a class. */ if (TREE_CODE (decl) == TEMPLATE_ID_EXPR - && TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE + && identifier_p (TREE_OPERAND (decl, 0)) && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE)) /* Situations like this: @@ -18604,9 +19263,7 @@ cp_parser_class_head (cp_parser* parser, for (scope = TREE_TYPE (type); scope && TREE_CODE (scope) != NAMESPACE_DECL; - scope = (TYPE_P (scope) - ? TYPE_CONTEXT (scope) - : DECL_CONTEXT (scope))) + scope = get_containing_scope (scope)) if (TYPE_P (scope) && CLASS_TYPE_P (scope) && CLASSTYPE_TEMPLATE_INFO (scope) @@ -19072,7 +19729,7 @@ cp_parser_member_declaration (cp_parser* parser) /* Check for a using-declaration. */ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_USING)) { - if (cxx_dialect < cxx0x) + if (cxx_dialect < cxx11) { /* Parse the using-declaration. */ cp_parser_using_declaration (parser, @@ -19176,7 +19833,7 @@ cp_parser_member_declaration (cp_parser* parser) { /* If the `friend' keyword was present, the friend must be introduced with a class-key. */ - if (!declares_class_or_enum && cxx_dialect < cxx0x) + if (!declares_class_or_enum && cxx_dialect < cxx11) pedwarn (decl_spec_token_start->location, OPT_Wpedantic, "in C++03 a class-key must be used " "when declaring a friend"); @@ -19376,7 +20033,7 @@ cp_parser_member_declaration (cp_parser* parser) initializer = cp_parser_pure_specifier (parser); else if (decl_specifiers.storage_class != sc_static) initializer = cp_parser_save_nsdmi (parser); - else if (cxx_dialect >= cxx0x) + else if (cxx_dialect >= cxx11) { bool nonconst; /* Don't require a constant rvalue in C++11, since we @@ -19915,7 +20572,7 @@ cp_parser_exception_specification_opt (cp_parser* parser) #if 0 /* Enable this once a lot of code has transitioned to noexcept? */ - if (cxx_dialect >= cxx0x && !in_system_header) + if (cxx_dialect >= cxx11 && !in_system_header) warning (OPT_Wdeprecated, "dynamic exception specifications are " "deprecated in C++0x; use %<noexcept%> instead"); #endif @@ -20383,7 +21040,7 @@ cp_nth_tokens_can_be_std_attribute_p (cp_parser *parser, size_t n) { cp_token *token = cp_lexer_peek_nth_token (parser->lexer, n); - return (cxx_dialect >= cxx0x + return (cxx_dialect >= cxx11 && ((token->type == CPP_KEYWORD && token->keyword == RID_ALIGNAS) || (token->type == CPP_OPEN_SQUARE && (token = cp_lexer_peek_nth_token (parser->lexer, n + 1)) @@ -20674,8 +21331,13 @@ cp_parser_std_attribute (cp_parser *parser) token = cp_lexer_peek_token (parser->lexer); } else - attribute = build_tree_list (build_tree_list (NULL_TREE, attr_id), - NULL_TREE); + { + attribute = build_tree_list (build_tree_list (NULL_TREE, attr_id), + NULL_TREE); + /* C++11 noreturn attribute is equivalent to GNU's. */ + if (is_attribute_p ("noreturn", attr_id)) + TREE_PURPOSE (TREE_PURPOSE (attribute)) = get_identifier ("gnu"); + } /* Now parse the optional argument clause of the attribute. */ @@ -21024,7 +21686,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name, /* By this point, the NAME should be an ordinary identifier. If the id-expression was a qualified name, the qualifying scope is stored in PARSER->SCOPE at this point. */ - gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); + gcc_assert (identifier_p (name)); /* Perform the lookup. */ if (parser->scope) @@ -21692,6 +22354,12 @@ cp_parser_function_definition_after_declarator (cp_parser* parser, finish_lambda_scope (); + /* Expand all array notation expressions here. */ + if (flag_enable_cilkplus && current_function_decl + && contains_array_notation_expr (DECL_SAVED_TREE (current_function_decl))) + DECL_SAVED_TREE (current_function_decl) = + expand_array_notation_exprs (DECL_SAVED_TREE (current_function_decl)); + /* Finish the function. */ fn = finish_function ((ctor_initializer_p ? 1 : 0) | (inline_p ? 2 : 0)); @@ -21788,7 +22456,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE)) cp_parser_template_declaration_after_export (parser, member_p); - else if (cxx_dialect >= cxx0x + else if (cxx_dialect >= cxx11 && cp_lexer_next_token_is_keyword (parser->lexer, RID_USING)) decl = cp_parser_alias_declaration (parser); else @@ -21814,8 +22482,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) decl = finish_member_template_decl (decl); } else if (friend_p && decl - && (TREE_CODE (decl) == TYPE_DECL - || DECL_TYPE_TEMPLATE_P (decl))) + && DECL_DECLARES_TYPE_P (decl)) make_friend_class (current_class_type, TREE_TYPE (decl), /*complain=*/true); } @@ -21829,7 +22496,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) /* Check the template arguments for a literal operator template. */ if (decl - && (TREE_CODE (decl) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (decl)) + && DECL_DECLARES_FUNCTION_P (decl) && UDLIT_OPER_P (DECL_NAME (decl))) { bool ok = true; @@ -21838,9 +22505,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) else { int num_parms = TREE_VEC_LENGTH (parameter_list); - if (num_parms != 1) - ok = false; - else + if (num_parms == 1) { tree parm_list = TREE_VEC_ELT (parameter_list, 0); tree parm = INNERMOST_TEMPLATE_PARMS (parm_list); @@ -21848,10 +22513,23 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))) ok = false; } + else if (num_parms == 2 && cxx_dialect >= cxx1y) + { + tree parm_type = TREE_VEC_ELT (parameter_list, 0); + tree type = INNERMOST_TEMPLATE_PARMS (parm_type); + tree parm_list = TREE_VEC_ELT (parameter_list, 1); + tree parm = INNERMOST_TEMPLATE_PARMS (parm_list); + if (TREE_TYPE (parm) != TREE_TYPE (type) + || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))) + ok = false; + } + else + ok = false; } if (!ok) error ("literal operator template %qD has invalid parameter list." - " Expected non-type template argument pack <char...>", + " Expected non-type template argument pack <char...>" + " or <typename CharT, CharT...>", decl); } /* Register member declarations. */ @@ -21865,8 +22543,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) (Even though there is no definition, there might be default arguments that need handling.) */ if (member_p && decl - && (TREE_CODE (decl) == FUNCTION_DECL - || DECL_FUNCTION_TEMPLATE_P (decl))) + && DECL_DECLARES_FUNCTION_P (decl)) vec_safe_push (unparsed_funs_with_definitions, decl); } @@ -22005,7 +22682,7 @@ cp_parser_single_declaration (cp_parser* parser, decl = error_mark_node; } - if (decl && TREE_CODE (decl) == VAR_DECL) + if (decl && VAR_P (decl)) check_template_variable (decl); } @@ -22033,7 +22710,7 @@ static tree cp_parser_simple_cast_expression (cp_parser *parser) { return cp_parser_cast_expression (parser, /*address_p=*/false, - /*cast_p=*/false, NULL); + /*cast_p=*/false, /*decltype*/false, NULL); } /* Parse a functional cast to TYPE. Returns an expression @@ -22523,6 +23200,44 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn) pop_unparsed_function_queues (parser); } +/* Subroutine of cp_parser_sizeof_operand, for handling C++11 + + sizeof ... ( identifier ) + + where the 'sizeof' token has already been consumed. */ + +static tree +cp_parser_sizeof_pack (cp_parser *parser) +{ + /* Consume the `...'. */ + cp_lexer_consume_token (parser->lexer); + maybe_warn_variadic_templates (); + + bool paren = cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN); + if (paren) + cp_lexer_consume_token (parser->lexer); + else + permerror (cp_lexer_peek_token (parser->lexer)->location, + "%<sizeof...%> argument must be surrounded by parentheses"); + + cp_token *token = cp_lexer_peek_token (parser->lexer); + tree name = cp_parser_identifier (parser); + tree expr = cp_parser_lookup_name_simple (parser, name, token->location); + if (expr == error_mark_node) + cp_parser_name_lookup_error (parser, name, expr, NLE_NULL, + token->location); + if (TREE_CODE (expr) == TYPE_DECL) + expr = TREE_TYPE (expr); + else if (TREE_CODE (expr) == CONST_DECL) + expr = DECL_INITIAL (expr); + expr = make_pack_expansion (expr); + + if (paren) + cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + + return expr; +} + /* Parse the operand of `sizeof' (or a similar operator). Returns either a TYPE or an expression, depending on the form of the input. The KEYWORD indicates which kind of expression we have @@ -22536,7 +23251,12 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword) char *tmp; bool saved_integral_constant_expression_p; bool saved_non_integral_constant_expression_p; - bool pack_expansion_p = false; + + /* If it's a `...', then we are computing the length of a parameter + pack. */ + if (keyword == RID_SIZEOF + && cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) + return cp_parser_sizeof_pack (parser); /* Types cannot be defined in a `sizeof' expression. Save away the old message. */ @@ -22555,19 +23275,6 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword) = parser->non_integral_constant_expression_p; parser->integral_constant_expression_p = false; - /* If it's a `...', then we are computing the length of a parameter - pack. */ - if (keyword == RID_SIZEOF - && cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) - { - /* Consume the `...'. */ - cp_lexer_consume_token (parser->lexer); - maybe_warn_variadic_templates (); - - /* Note that this is an expansion. */ - pack_expansion_p = true; - } - /* Do not actually evaluate the expression. */ ++cp_unevaluated_operand; ++c_inhibit_evaluation_warnings; @@ -22575,21 +23282,44 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword) construction. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { - tree type; - bool saved_in_type_id_in_expr_p; + tree type = NULL_TREE; + bool compound_literal_p; /* We can't be sure yet whether we're looking at a type-id or an expression. */ cp_parser_parse_tentatively (parser); /* Consume the `('. */ cp_lexer_consume_token (parser->lexer); - /* Parse the type-id. */ - saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; - parser->in_type_id_in_expr_p = true; - type = cp_parser_type_id (parser); - parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; - /* Now, look for the trailing `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + /* Note: as a GNU Extension, compound literals are considered + postfix-expressions as they are in C99, so they are valid + arguments to sizeof. See comment in cp_parser_cast_expression + for details. */ + cp_lexer_save_tokens (parser->lexer); + /* Skip tokens until the next token is a closing parenthesis. + If we find the closing `)', and the next token is a `{', then + we are looking at a compound-literal. */ + compound_literal_p + = (cp_parser_skip_to_closing_parenthesis (parser, false, false, + /*consume_paren=*/true) + && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)); + /* Roll back the tokens we skipped. */ + cp_lexer_rollback_tokens (parser->lexer); + /* If we were looking at a compound-literal, simulate an error + so that the call to cp_parser_parse_definitely below will + fail. */ + if (compound_literal_p) + cp_parser_simulate_error (parser); + else + { + bool saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; + parser->in_type_id_in_expr_p = true; + /* Look for the type-id. */ + type = cp_parser_type_id (parser); + /* Look for the closing `)'. */ + cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; + } + /* If all went well, then we're done. */ if (cp_parser_parse_definitely (parser)) { @@ -22607,9 +23337,6 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword) /*attrlist=*/NULL); } } - else if (pack_expansion_p) - permerror (cp_lexer_peek_token (parser->lexer)->location, - "%<sizeof...%> argument must be surrounded by parentheses"); /* If the type-id production did not work out, then we must be looking at the unary-expression production. */ @@ -22617,10 +23344,6 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword) expr = cp_parser_unary_expression (parser, /*address_p=*/false, /*cast_p=*/false, NULL); - if (pack_expansion_p) - /* Build a pack expansion. */ - expr = make_pack_expansion (expr); - /* Go back to evaluating expressions. */ --cp_unevaluated_operand; --c_inhibit_evaluation_warnings; @@ -23268,12 +23991,12 @@ cp_parser_check_class_key (enum tag_types class_key, tree type) return; if ((TREE_CODE (type) == UNION_TYPE) != (class_key == union_type)) { - permerror (input_location, "%qs tag used in naming %q#T", - class_key == union_type ? "union" - : class_key == record_type ? "struct" : "class", - type); - inform (DECL_SOURCE_LOCATION (TYPE_NAME (type)), - "%q#T was previously declared here", type); + if (permerror (input_location, "%qs tag used in naming %q#T", + class_key == union_type ? "union" + : class_key == record_type ? "struct" : "class", + type)) + inform (DECL_SOURCE_LOCATION (TYPE_NAME (type)), + "%q#T was previously declared here", type); } } @@ -24194,7 +24917,7 @@ cp_parser_objc_protocol_qualifiers (cp_parser* parser) node = token->u.value; - while (node && TREE_CODE (node) == IDENTIFIER_NODE + while (node && identifier_p (node) && (node == ridpointers [(int) RID_IN] || node == ridpointers [(int) RID_OUT] || node == ridpointers [(int) RID_INOUT] @@ -26830,7 +27553,7 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl) op = (token->type == CPP_PLUS_PLUS ? PREINCREMENT_EXPR : PREDECREMENT_EXPR); cp_lexer_consume_token (parser->lexer); - lhs = cp_parser_cast_expression (parser, false, false, NULL); + lhs = cp_parser_simple_cast_expression (parser); if (lhs != decl) return error_mark_node; return build2 (op, TREE_TYPE (decl), decl, NULL_TREE); @@ -27827,7 +28550,7 @@ cp_parser_transaction_expression (cp_parser *parser, enum rid keyword) cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); expr = cp_parser_expression (parser, /*cast_p=*/false, NULL); - finish_parenthesized_expr (expr); + expr = finish_parenthesized_expr (expr); cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); } diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h index fe787e4c858..3d8bb742d22 100644 --- a/gcc/cp/parser.h +++ b/gcc/cp/parser.h @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #define GCC_CP_PARSER_H #include "tree.h" +#include "cp/cp-tree.h" #include "c-family/c-pragma.h" /* A token's value and its associated deferred access checks and @@ -343,7 +344,13 @@ typedef struct GTY(()) cp_parser { } cp_parser; /* In parser.c */ +extern void debug (cp_token &ref); +extern void debug (cp_token *ptr); extern void cp_lexer_debug_tokens (vec<cp_token, va_gc> *); +extern void debug (vec<cp_token, va_gc> &ref); +extern void debug (vec<cp_token, va_gc> *ptr); extern void cp_debug_parser (FILE *, cp_parser *); +extern void debug (cp_parser &ref); +extern void debug (cp_parser *ptr); #endif /* GCC_CP_PARSER_H */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index eb9fc7f94c7..667e37f2ec9 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -213,9 +213,8 @@ static tree instantiate_alias_template (tree, tree, tsubst_flags_t); static void push_access_scope (tree t) { - gcc_assert (TREE_CODE (t) == FUNCTION_DECL - || TREE_CODE (t) == TYPE_DECL - || TREE_CODE (t) == VAR_DECL); + gcc_assert (VAR_OR_FUNCTION_DECL_P (t) + || TREE_CODE (t) == TYPE_DECL); if (DECL_FRIEND_CONTEXT (t)) push_nested_class (DECL_FRIEND_CONTEXT (t)); @@ -325,7 +324,7 @@ get_template_info (const_tree t) if (!tinfo && DECL_IMPLICIT_TYPEDEF_P (t)) t = TREE_TYPE (t); - if (TAGGED_TYPE_P (t)) + if (OVERLOAD_TYPE_P (t)) tinfo = TYPE_TEMPLATE_INFO (t); else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM) tinfo = TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t); @@ -1009,6 +1008,9 @@ optimize_specialization_lookup_p (tree tmpl) static tree retrieve_specialization (tree tmpl, tree args, hashval_t hash) { + if (tmpl == NULL_TREE) + return NULL_TREE; + if (args == error_mark_node) return NULL_TREE; @@ -2464,7 +2466,7 @@ check_explicit_specialization (tree declarator, { tree fns; - gcc_assert (TREE_CODE (declarator) == IDENTIFIER_NODE); + gcc_assert (identifier_p (declarator)); if (ctype) fns = dname; else @@ -2525,8 +2527,7 @@ check_explicit_specialization (tree declarator, return decl; } else if (ctype != NULL_TREE - && (TREE_CODE (TREE_OPERAND (declarator, 0)) == - IDENTIFIER_NODE)) + && (identifier_p (TREE_OPERAND (declarator, 0)))) { /* Find the list of functions in ctype that have the same name as the declared function. */ @@ -3057,10 +3058,7 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data) bool parameter_pack_p = false; /* Handle type aliases/typedefs. */ - if (TYPE_P (t) - && TYPE_NAME (t) - && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL - && TYPE_DECL_ALIAS_P (TYPE_NAME (t))) + if (TYPE_ALIAS_P (t)) { if (TYPE_TEMPLATE_INFO (t)) cp_walk_tree (&TYPE_TI_ARGS (t), @@ -3145,7 +3143,7 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data) case UNION_TYPE: case ENUMERAL_TYPE: if (TYPE_TEMPLATE_INFO (t)) - cp_walk_tree (&TI_ARGS (TYPE_TEMPLATE_INFO (t)), + cp_walk_tree (&TYPE_TI_ARGS (t), &find_parameter_packs_r, ppd, ppd->visited); *walk_subtrees = 0; @@ -3873,10 +3871,10 @@ template_parms_to_args (tree parms) Consider the level of the parms of TT; T and U both have level 2; TT has no template parm of level 1. So in this case the first element of full_template_args is NULL_TREE. If we - leave it like this TMPL_ARG_DEPTH on args returns 1 instead + leave it like this TMPL_ARGS_DEPTH on args returns 1 instead of 2. This will make tsubst wrongly consider that T and U have level 1. Instead, let's create a dummy vector as the - first element of full_template_args so that TMPL_ARG_DEPTH + first element of full_template_args so that TMPL_ARGS_DEPTH returns the correct depth for args. */ TREE_VEC_ELT (args, 0) = make_tree_vec (1); return args; @@ -4248,8 +4246,16 @@ process_partial_specialization (tree decl) /* We should only get here once. */ gcc_assert (!COMPLETE_TYPE_P (type)); + tree tmpl = build_template_decl (decl, current_template_parms, + DECL_MEMBER_TEMPLATE_P (maintmpl)); + TREE_TYPE (tmpl) = type; + DECL_TEMPLATE_RESULT (tmpl) = decl; + SET_DECL_TEMPLATE_SPECIALIZATION (tmpl); + DECL_TEMPLATE_INFO (tmpl) = build_template_info (maintmpl, specargs); + DECL_PRIMARY_TEMPLATE (tmpl) = maintmpl; + DECL_TEMPLATE_SPECIALIZATIONS (maintmpl) - = tree_cons (specargs, inner_parms, + = tree_cons (specargs, tmpl, DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)); TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type; @@ -4306,6 +4312,13 @@ check_default_tmpl_args (tree decl, tree parms, bool is_primary, local scope. */ return true; + if (TREE_CODE (decl) == TYPE_DECL + && TREE_TYPE (decl) + && LAMBDA_TYPE_P (TREE_TYPE (decl))) + /* A lambda doesn't have an explicit declaration; don't complain + about the parms of the enclosing class. */ + return true; + if (current_class_type && !TYPE_BEING_DEFINED (current_class_type) && DECL_LANG_SPECIFIC (decl) @@ -4674,6 +4687,8 @@ push_template_decl_real (tree decl, bool is_friend) if (!ctx || TREE_CODE (ctx) == FUNCTION_DECL || (CLASS_TYPE_P (ctx) && TYPE_BEING_DEFINED (ctx)) + || (TREE_CODE (decl) == TYPE_DECL + && LAMBDA_TYPE_P (TREE_TYPE (decl))) || (is_friend && !DECL_TEMPLATE_INFO (decl))) { if (DECL_LANG_SPECIFIC (decl) @@ -4793,9 +4808,7 @@ push_template_decl_real (tree decl, bool is_friend) /* Can happen in erroneous input. */ break; else - current = (TYPE_P (current) - ? TYPE_CONTEXT (current) - : DECL_CONTEXT (current)); + current = get_containing_scope (current); } /* Check that the parms are used in the appropriate qualifying scopes @@ -5044,9 +5057,8 @@ fold_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain) as two declarations of the same function, for example. */ if (processing_template_decl - && !type_dependent_expression_p (expr) - && potential_constant_expression (expr) - && !value_dependent_expression_p (expr)) + && !instantiation_dependent_expression_p (expr) + && potential_constant_expression (expr)) { HOST_WIDE_INT saved_processing_template_decl; @@ -5131,7 +5143,7 @@ convert_nontype_argument_function (tree type, tree expr) if (TREE_CODE (fn_no_ptr) != FUNCTION_DECL) { error ("%qE is not a valid template argument for type %qT", expr, type); - if (TREE_CODE (type) == POINTER_TYPE) + if (TYPE_PTR_P (type)) error ("it must be the address of a function with external linkage"); else error ("it must be the name of a function with external linkage"); @@ -5139,9 +5151,9 @@ convert_nontype_argument_function (tree type, tree expr) } linkage = decl_linkage (fn_no_ptr); - if (cxx_dialect >= cxx0x ? linkage == lk_none : linkage != lk_external) + if (cxx_dialect >= cxx11 ? linkage == lk_none : linkage != lk_external) { - if (cxx_dialect >= cxx0x) + if (cxx_dialect >= cxx11) error ("%qE is not a valid template argument for type %qT " "because %qD has no linkage", expr, type, fn_no_ptr); @@ -5166,7 +5178,7 @@ check_valid_ptrmem_cst_expr (tree type, tree expr, STRIP_NOPS (expr); if (expr && (null_ptr_cst_p (expr) || TREE_CODE (expr) == PTRMEM_CST)) return true; - if (cxx_dialect >= cxx0x && null_member_pointer_value_p (expr)) + if (cxx_dialect >= cxx11 && null_member_pointer_value_p (expr)) return true; if (complain & tf_error) { @@ -5371,7 +5383,7 @@ unify_no_common_base (bool explain_p, enum template_base_result r, { case tbr_ambiguous_baseclass: inform (input_location, " %qT is an ambiguous base class of %qT", - arg, parm); + parm, arg); break; default: inform (input_location, " %qT is not derived from %qT", arg, parm); @@ -5498,7 +5510,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) arbitrary constant expressions. Pointer and pointer to member arguments can be general constant expressions that evaluate to a null value, but otherwise still need to be of a specific form. */ - if (cxx_dialect >= cxx0x) + if (cxx_dialect >= cxx11) { if (TREE_CODE (expr) == PTRMEM_CST) /* A PTRMEM_CST is already constant, and a valid template @@ -5538,7 +5550,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) tree addr = TREE_OPERAND (probe, 0); if (TREE_CODE (probe_type) == REFERENCE_TYPE && TREE_CODE (addr) == ADDR_EXPR - && TREE_CODE (TREE_TYPE (addr)) == POINTER_TYPE + && TYPE_PTR_P (TREE_TYPE (addr)) && (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (probe_type), TREE_TYPE (TREE_TYPE (addr))))) @@ -5554,15 +5566,19 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) qualification conversion. Let's strip everything. */ else if (TREE_CODE (expr) == NOP_EXPR && TYPE_PTROBV_P (type)) { - STRIP_NOPS (expr); - gcc_assert (TREE_CODE (expr) == ADDR_EXPR); - gcc_assert (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE); - /* Skip the ADDR_EXPR only if it is part of the decay for - an array. Otherwise, it is part of the original argument - in the source code. */ - if (TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == ARRAY_TYPE) - expr = TREE_OPERAND (expr, 0); - expr_type = TREE_TYPE (expr); + tree probe = expr; + STRIP_NOPS (probe); + if (TREE_CODE (probe) == ADDR_EXPR + && TYPE_PTR_P (TREE_TYPE (probe))) + { + /* Skip the ADDR_EXPR only if it is part of the decay for + an array. Otherwise, it is part of the original argument + in the source code. */ + if (TREE_CODE (TREE_TYPE (TREE_OPERAND (probe, 0))) == ARRAY_TYPE) + probe = TREE_OPERAND (probe, 0); + expr = probe; + expr_type = TREE_TYPE (expr); + } } /* [temp.arg.nontype]/5, bullet 1 @@ -5586,12 +5602,12 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) { if (complain & tf_error) { - int errs = errorcount, warns = warningcount; + int errs = errorcount, warns = warningcount + werrorcount; if (processing_template_decl && !require_potential_constant_expression (expr)) return NULL_TREE; expr = cxx_constant_value (expr); - if (errorcount > errs || warningcount > warns) + if (errorcount > errs || warningcount + werrorcount > warns) inform (EXPR_LOC_OR_HERE (expr), "in template argument for type %qT ", type); if (expr == error_mark_node) @@ -5628,12 +5644,12 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) if (DECL_P (expr) && DECL_TEMPLATE_PARM_P (expr)) /* Non-type template parameters are OK. */ ; - else if (cxx_dialect >= cxx0x && integer_zerop (expr)) + else if (cxx_dialect >= cxx11 && integer_zerop (expr)) /* Null pointer values are OK in C++11. */; else if (TREE_CODE (expr) != ADDR_EXPR && TREE_CODE (expr_type) != ARRAY_TYPE) { - if (TREE_CODE (expr) == VAR_DECL) + if (VAR_P (expr)) { error ("%qD is not a valid template argument " "because %qD is a variable, not the address of " @@ -5641,6 +5657,13 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) expr, expr); return NULL_TREE; } + if (POINTER_TYPE_P (expr_type)) + { + error ("%qE is not a valid template argument for %qT " + "because it is not the address of a variable", + expr, type); + return NULL_TREE; + } /* Other values, like integer constants, might be valid non-type arguments of some other type. */ return error_mark_node; @@ -5651,21 +5674,21 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) decl = ((TREE_CODE (expr) == ADDR_EXPR) ? TREE_OPERAND (expr, 0) : expr); - if (TREE_CODE (decl) != VAR_DECL) + if (!VAR_P (decl)) { error ("%qE is not a valid template argument of type %qT " "because %qE is not a variable", expr, type, decl); return NULL_TREE; } - else if (cxx_dialect < cxx0x && !DECL_EXTERNAL_LINKAGE_P (decl)) + else if (cxx_dialect < cxx11 && !DECL_EXTERNAL_LINKAGE_P (decl)) { error ("%qE is not a valid template argument of type %qT " "because %qD does not have external linkage", expr, type, decl); return NULL_TREE; } - else if (cxx_dialect >= cxx0x && decl_linkage (decl) == lk_none) + else if (cxx_dialect >= cxx11 && decl_linkage (decl) == lk_none) { error ("%qE is not a valid template argument of type %qT " "because %qD has no linkage", @@ -5715,7 +5738,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) shall be one of: [...] -- the address of an object or function with external linkage. */ - if (TREE_CODE (expr) == INDIRECT_REF + if (INDIRECT_REF_P (expr) && TYPE_REF_OBJ_P (TREE_TYPE (TREE_OPERAND (expr, 0)))) { expr = TREE_OPERAND (expr, 0); @@ -5764,7 +5787,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) return error_mark_node; } - if (cxx_dialect >= cxx0x && integer_zerop (expr)) + if (cxx_dialect >= cxx11 && integer_zerop (expr)) /* Null pointer values are OK in C++11. */ return perform_qualification_conversions (type, expr); @@ -5788,7 +5811,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) return NULL_TREE; } - expr = convert_nontype_argument_function (TREE_TYPE (type), expr); + expr = convert_nontype_argument_function (type, expr); if (!expr || expr == error_mark_node) return expr; @@ -6193,7 +6216,7 @@ convert_template_argument (tree parm, tree t = maybe_get_template_decl_from_type_decl (TYPE_NAME (arg)); if (TREE_CODE (t) == TEMPLATE_DECL) { - if (cxx_dialect >= cxx0x) + if (cxx_dialect >= cxx11) /* OK under DR 1004. */; else if (complain & tf_warning_or_error) pedwarn (input_location, OPT_Wpedantic, "injected-class-name %qD" @@ -6353,7 +6376,8 @@ convert_template_argument (tree parm, val = error_mark_node; } } - else if (!uses_template_parms (orig_arg) && !uses_template_parms (t)) + else if (!dependent_template_arg_p (orig_arg) + && !uses_template_parms (t)) /* We used to call digest_init here. However, digest_init will report errors, which we don't want when complain is zero. More importantly, digest_init will try too @@ -6933,7 +6957,7 @@ lookup_template_function (tree fns, tree arglist) gcc_assert (!arglist || TREE_CODE (arglist) == TREE_VEC); - if (!is_overloaded_fn (fns) && TREE_CODE (fns) != IDENTIFIER_NODE) + if (!is_overloaded_fn (fns) && !identifier_p (fns)) { error ("%q#D is not a function template", fns); return error_mark_node; @@ -7001,7 +7025,7 @@ maybe_get_template_decl_from_type_decl (tree decl) ? CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl)) : decl; } -/* Given an IDENTIFIER_NODE (type TEMPLATE_DECL) and a chain of +/* Given an IDENTIFIER_NODE (or type TEMPLATE_DECL) and a chain of parameters, find the desired type. D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments. @@ -7036,7 +7060,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, spec_entry elt; hashval_t hash; - if (TREE_CODE (d1) == IDENTIFIER_NODE) + if (identifier_p (d1)) { tree value = innermost_non_namespace_value (d1); if (value && DECL_TEMPLATE_TEMPLATE_PARM_P (value)) @@ -7082,6 +7106,11 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, d1 = DECL_NAME (templ); context = DECL_CONTEXT (templ); } + else if (DECL_TEMPLATE_TEMPLATE_PARM_P (d1)) + { + templ = d1; + d1 = DECL_NAME (templ); + } /* Issue an error message if we didn't find a template. */ if (! templ) @@ -7540,7 +7569,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, if (CLASS_TYPE_P (template_type) && is_dependent_type) /* If the type makes use of template parameters, the code that generates debugging information will crash. */ - DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1; + DECL_IGNORED_P (TYPE_MAIN_DECL (t)) = 1; /* Possibly limit visibility based on template args. */ TREE_PUBLIC (type_decl) = 1; @@ -7601,7 +7630,7 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d) case ENUMERAL_TYPE: if (!TYPE_TEMPLATE_INFO (t)) *walk_subtrees = 0; - else if (for_each_template_parm (TI_ARGS (TYPE_TEMPLATE_INFO (t)), + else if (for_each_template_parm (TYPE_TI_ARGS (t), fn, data, pfd->visited, pfd->include_nondeduced_p)) return error_mark_node; @@ -7831,7 +7860,7 @@ uses_template_parms (tree t) || TREE_CODE (t) == TEMPLATE_PARM_INDEX || TREE_CODE (t) == OVERLOAD || BASELINK_P (t) - || TREE_CODE (t) == IDENTIFIER_NODE + || identifier_p (t) || TREE_CODE (t) == TRAIT_EXPR || TREE_CODE (t) == CONSTRUCTOR || CONSTANT_CLASS_P (t)) @@ -8460,8 +8489,7 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags, if (TREE_VALUE (t) && TREE_CODE (TREE_VALUE (t)) == TREE_LIST && TREE_VALUE (TREE_VALUE (t)) - && (TREE_CODE (TREE_VALUE (TREE_VALUE (t))) - == IDENTIFIER_NODE)) + && (identifier_p (TREE_VALUE (TREE_VALUE (t))))) { tree chain = tsubst_expr (TREE_CHAIN (TREE_VALUE (t)), args, complain, @@ -8767,8 +8795,7 @@ instantiate_class_template_1 (tree type) pushtag (name, newtag, /*tag_scope=*/ts_current); } } - else if (TREE_CODE (t) == FUNCTION_DECL - || DECL_FUNCTION_TEMPLATE_P (t)) + else if (DECL_DECLARES_FUNCTION_P (t)) { /* Build new TYPE_METHODS. */ tree r; @@ -8818,7 +8845,7 @@ instantiate_class_template_1 (tree type) r = tsubst (t, args, tf_warning_or_error, NULL_TREE); if (TREE_CODE (t) == TEMPLATE_DECL) --processing_template_decl; - if (TREE_CODE (r) == VAR_DECL) + if (VAR_P (r)) { /* In [temp.inst]: @@ -8844,9 +8871,8 @@ instantiate_class_template_1 (tree type) else if (TREE_CODE (r) == FIELD_DECL) { /* Determine whether R has a valid type and can be - completed later. If R is invalid, then it is - replaced by error_mark_node so that it will not be - added to TYPE_FIELDS. */ + completed later. If R is invalid, then its type is + replaced by error_mark_node. */ tree rtype = TREE_TYPE (r); if (can_complete_type_without_circularity (rtype)) complete_type (rtype); @@ -8854,7 +8880,7 @@ instantiate_class_template_1 (tree type) if (!COMPLETE_TYPE_P (rtype)) { cxx_incomplete_type_error (r, rtype); - r = error_mark_node; + TREE_TYPE (r) = error_mark_node; } } @@ -8992,12 +9018,26 @@ instantiate_class_template_1 (tree type) } } - if (CLASSTYPE_LAMBDA_EXPR (type)) + if (tree expr = CLASSTYPE_LAMBDA_EXPR (type)) { tree decl = lambda_function (type); if (decl) { instantiate_decl (decl, false, false); + + /* We need to instantiate the capture list from the template + after we've instantiated the closure members, but before we + consider adding the conversion op. Also keep any captures + that may have been added during instantiation of the op(). */ + tree tmpl_expr = CLASSTYPE_LAMBDA_EXPR (pattern); + tree tmpl_cap + = tsubst_copy_and_build (LAMBDA_EXPR_CAPTURE_LIST (tmpl_expr), + args, tf_warning_or_error, NULL_TREE, + false, false); + + LAMBDA_EXPR_CAPTURE_LIST (expr) + = chainon (tmpl_cap, nreverse (LAMBDA_EXPR_CAPTURE_LIST (expr))); + maybe_add_lambda_conv_op (type); } else @@ -9169,8 +9209,15 @@ use_pack_expansion_extra_args_p (tree parm_packs, int arg_pack_len, bool has_empty_arg) { + /* If one pack has an expansion and another pack has a normal + argument or if one pack has an empty argument and an another + one hasn't then tsubst_pack_expansion cannot perform the + substitution and need to fall back on the + PACK_EXPANSION_EXTRA mechanism. */ if (parm_packs == NULL_TREE) return false; + else if (has_empty_arg) + return true; bool has_expansion_arg = false; for (int i = 0 ; i < arg_pack_len; ++i) @@ -9188,13 +9235,7 @@ use_pack_expansion_extra_args_p (tree parm_packs, has_non_expansion_arg = true; } - /* If one pack has an expansion and another pack has a normal - argument or if one pack has an empty argument another one - hasn't then tsubst_pack_expansion cannot perform the - substitution and need to fall back on the - PACK_EXPANSION_EXTRA mechanism. */ - if ((has_expansion_arg && has_non_expansion_arg) - || (has_empty_arg && (has_expansion_arg || has_non_expansion_arg))) + if (has_expansion_arg && has_non_expansion_arg) return true; } return false; @@ -10025,7 +10066,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) RETURN (error_mark_node); TREE_TYPE (r) = new_type; - CLASSTYPE_TI_TEMPLATE (new_type) = r; + /* For a partial specialization, we need to keep pointing to + the primary template. */ + if (!DECL_TEMPLATE_SPECIALIZATION (t)) + CLASSTYPE_TI_TEMPLATE (new_type) = r; DECL_TEMPLATE_RESULT (r) = TYPE_MAIN_DECL (new_type); DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (new_type); DECL_CONTEXT (r) = TYPE_CONTEXT (new_type); @@ -10252,7 +10296,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) DECL_TEMPLATE_INFO (r) = build_template_info (gen_tmpl, argvec); SET_DECL_IMPLICIT_INSTANTIATION (r); - register_specialization (r, gen_tmpl, argvec, false, hash); + + tree new_r + = register_specialization (r, gen_tmpl, argvec, false, hash); + if (new_r != r) + /* We instantiated this while substituting into + the type earlier (template/friend54.C). */ + RETURN (new_r); /* We're not supposed to instantiate default arguments until they are called, for a template. But, for a @@ -10474,8 +10524,6 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) /* We don't have to set DECL_CONTEXT here; it is set by finish_member_declaration. */ DECL_CHAIN (r) = NULL_TREE; - if (VOID_TYPE_P (type)) - error ("instantiation of %q+D as type %qT", r, type); apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0, args, complain, in_decl); @@ -10600,16 +10648,6 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) break; } - if (TREE_CODE (t) == VAR_DECL && DECL_ANON_UNION_VAR_P (t)) - { - /* Just use name lookup to find a member alias for an anonymous - union, but then add it to the hash table. */ - r = lookup_name (DECL_NAME (t)); - gcc_assert (DECL_ANON_UNION_VAR_P (r)); - register_local_specialization (r, t); - break; - } - /* Create a new node for the specialization we need. */ r = copy_decl (t); if (type == NULL_TREE) @@ -10618,13 +10656,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) type = DECL_ORIGINAL_TYPE (t); else type = TREE_TYPE (t); - if (TREE_CODE (t) == VAR_DECL + if (VAR_P (t) && VAR_HAD_UNKNOWN_BOUND (t) && type != error_mark_node) type = strip_array_domain (type); type = tsubst (type, args, complain, in_decl); } - if (TREE_CODE (r) == VAR_DECL) + if (VAR_P (r)) { /* Even if the original location is out of scope, the newly substituted one is not. */ @@ -10688,7 +10726,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_WRTL)) SET_DECL_RTL (r, NULL); DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0; - if (TREE_CODE (r) == VAR_DECL) + if (VAR_P (r)) { /* Possibly limit visibility based on template args. */ DECL_VISIBILITY (r) = VISIBILITY_DEFAULT; @@ -10714,21 +10752,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) SET_DECL_IMPLICIT_INSTANTIATION (r); } else if (cp_unevaluated_operand) - { - /* We're substituting this var in a decltype outside of its - scope, such as for a lambda return type. Don't add it to - local_specializations, do perform auto deduction. */ - tree auto_node = type_uses_auto (type); - if (auto_node) - { - tree init - = tsubst_expr (DECL_INITIAL (t), args, complain, in_decl, - /*constant_expression_p=*/false); - init = resolve_nondeduced_context (init); - TREE_TYPE (r) = type - = do_auto_deduction (type, init, auto_node); - } - } + gcc_unreachable (); else register_local_specialization (r, t); @@ -10826,6 +10850,9 @@ tsubst_arg_types (tree arg_types, } return error_mark_node; } + /* DR 657. */ + if (abstract_virtuals_error_sfinae (ACU_PARM, type, complain)) + return error_mark_node; /* Do array-to-pointer, function-to-pointer conversion, and ignore top-level qualifiers as required. */ @@ -10888,10 +10915,8 @@ tsubst_function_type (tree t, return_type = tsubst (TREE_TYPE (t), args, complain, in_decl); if (return_type == error_mark_node) return error_mark_node; - /* The standard does not presently indicate that creation of a - function type with an invalid return type is a deduction failure. - However, that is clearly analogous to creating an array of "void" - or a reference to a reference. This is core issue #486. */ + /* DR 486 clarifies that creation of a function type with an + invalid return type is a deduction failure. */ if (TREE_CODE (return_type) == ARRAY_TYPE || TREE_CODE (return_type) == FUNCTION_TYPE) { @@ -10904,6 +10929,9 @@ tsubst_function_type (tree t, } return error_mark_node; } + /* And DR 657. */ + if (abstract_virtuals_error_sfinae (ACU_RETURN, return_type, complain)) + return error_mark_node; /* Substitute the argument types. */ arg_types = tsubst_arg_types (TYPE_ARG_TYPES (t), args, NULL_TREE, @@ -10915,7 +10943,9 @@ tsubst_function_type (tree t, if (TREE_CODE (t) == FUNCTION_TYPE) { fntype = build_function_type (return_type, arg_types); - fntype = apply_memfn_quals (fntype, type_memfn_quals (t)); + fntype = apply_memfn_quals (fntype, + type_memfn_quals (t), + type_memfn_rqual (t)); } else { @@ -10937,6 +10967,7 @@ tsubst_function_type (tree t, fntype = build_method_type_directly (r, return_type, TREE_CHAIN (arg_types)); + fntype = build_ref_qualified_type (fntype, type_memfn_rqual (t)); } fntype = cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t)); @@ -11484,7 +11515,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) only enforce this check in strict C++98 mode. */ if ((TREE_CODE (type) == REFERENCE_TYPE && (((cxx_dialect == cxx98) && flag_iso) || code != REFERENCE_TYPE)) - || (code == REFERENCE_TYPE && TREE_CODE (type) == VOID_TYPE)) + || (code == REFERENCE_TYPE && VOID_TYPE_P (type))) { static location_t last_loc; @@ -11494,7 +11525,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (complain & tf_error && last_loc != input_location) { - if (TREE_CODE (type) == VOID_TYPE) + if (VOID_TYPE_P (type)) error ("forming reference to void"); else if (code == POINTER_TYPE) error ("forming pointer to reference type %qT", type); @@ -11505,6 +11536,21 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) return error_mark_node; } + else if (TREE_CODE (type) == FUNCTION_TYPE + && (type_memfn_quals (type) != TYPE_UNQUALIFIED + || type_memfn_rqual (type) != REF_QUAL_NONE)) + { + if (complain & tf_error) + { + if (code == POINTER_TYPE) + error ("forming pointer to qualified function type %qT", + type); + else + error ("forming reference to qualified function type %qT", + type); + } + return error_mark_node; + } else if (code == POINTER_TYPE) { r = build_pointer_type (type); @@ -11529,6 +11575,20 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) r = cp_build_reference_type (type, TYPE_REF_IS_RVALUE (t)); r = cp_build_qualified_type_real (r, cp_type_quals (t), complain); + if (cxx_dialect >= cxx1y + && !(TREE_CODE (t) == REFERENCE_TYPE && REFERENCE_VLA_OK (t)) + && array_of_runtime_bound_p (type)) + { + if (complain & tf_warning_or_error) + pedwarn + (input_location, OPT_Wvla, + code == REFERENCE_TYPE + ? G_("cannot declare reference to array of runtime bound") + : G_("cannot declare pointer to array of runtime bound")); + else + r = error_mark_node; + } + if (r != error_mark_node) /* Will this ever be needed for TYPE_..._TO values? */ layout_type (r); @@ -11557,7 +11617,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) error ("creating pointer to member reference type %qT", type); return error_mark_node; } - if (TREE_CODE (type) == VOID_TYPE) + if (VOID_TYPE_P (type)) { if (complain & tf_error) error ("creating pointer to member of type void"); @@ -11569,7 +11629,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) /* The type of the implicit object parameter gets its cv-qualifiers from the FUNCTION_TYPE. */ tree memptr; - tree method_type = build_memfn_type (type, r, type_memfn_quals (type)); + tree method_type + = build_memfn_type (type, r, type_memfn_quals (type), + type_memfn_rqual (type)); memptr = build_ptrmemfunc_type (build_pointer_type (method_type)); return cp_build_qualified_type_real (memptr, cp_type_quals (t), complain); @@ -11617,7 +11679,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) -- Attempting to create an array with an element type that is void, a function type, or a reference type, or [DR337] an abstract class type. */ - if (TREE_CODE (type) == VOID_TYPE + if (VOID_TYPE_P (type) || TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == REFERENCE_TYPE) { @@ -11625,13 +11687,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) error ("creating array of %qT", type); return error_mark_node; } - if (ABSTRACT_CLASS_TYPE_P (type)) - { - if (complain & tf_error) - error ("creating array of %qT, which is an abstract class type", - type); - return error_mark_node; - } + + if (abstract_virtuals_error_sfinae (ACU_ARRAY, type, complain)) + return error_mark_node; r = build_cplus_array_type (type, domain); @@ -11756,20 +11814,31 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) ++cp_unevaluated_operand; ++c_inhibit_evaluation_warnings; - type = tsubst_expr (DECLTYPE_TYPE_EXPR (t), args, - complain, in_decl, - /*integral_constant_expression_p=*/false); + type = tsubst_copy_and_build (DECLTYPE_TYPE_EXPR (t), args, + complain|tf_decltype, in_decl, + /*function_p*/false, + /*integral_constant_expression*/false); --cp_unevaluated_operand; --c_inhibit_evaluation_warnings; if (DECLTYPE_FOR_LAMBDA_CAPTURE (t)) - type = lambda_capture_field_type (type); + type = lambda_capture_field_type (type, + DECLTYPE_FOR_INIT_CAPTURE (t)); else if (DECLTYPE_FOR_LAMBDA_PROXY (t)) type = lambda_proxy_type (type); else - type = finish_decltype_type - (type, DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t), complain); + { + bool id = DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t); + if (id && TREE_CODE (DECLTYPE_TYPE_EXPR (t)) == BIT_NOT_EXPR + && EXPR_P (type)) + /* In a template ~id could be either a complement expression + or an unqualified-id naming a destructor; if instantiating + it produces an expression, it's not an id-expression or + member access. */ + id = false; + type = finish_decltype_type (type, id, complain); + } return cp_build_qualified_type_real (type, cp_type_quals (t) | cp_type_quals (type), @@ -12010,11 +12079,11 @@ tsubst_qualified_id (tree qualified_id, tree args, else if (TYPE_P (scope)) { expr = (adjust_result_of_qualified_name_lookup - (expr, scope, current_class_type)); + (expr, scope, current_nonlambda_class_type ())); expr = (finish_qualified_id_expr (scope, expr, done, address_p && PTRMEM_OK_P (qualified_id), QUALIFIED_NAME_IS_TEMPLATE (qualified_id), - /*template_arg_p=*/false)); + /*template_arg_p=*/false, complain)); } /* Expressions do not generally have reference type. */ @@ -12137,11 +12206,32 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) case VAR_DECL: case FUNCTION_DECL: - if ((DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)) - || local_variable_p (t)) - t = tsubst (t, args, complain, in_decl); - mark_used (t); - return t; + if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)) + r = tsubst (t, args, complain, in_decl); + else if (local_variable_p (t)) + { + r = retrieve_local_specialization (t); + if (r == NULL_TREE) + { + if (DECL_ANON_UNION_VAR_P (t)) + { + /* Just use name lookup to find a member alias for an + anonymous union, but then add it to the hash table. */ + r = lookup_name (DECL_NAME (t)); + gcc_assert (DECL_ANON_UNION_VAR_P (r)); + register_local_specialization (r, t); + } + else + { + gcc_assert (errorcount || sorrycount); + return error_mark_node; + } + } + } + else + r = t; + mark_used (r); + return r; case NAMESPACE_DECL: return t; @@ -12264,6 +12354,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) case TYPEID_EXPR: case REALPART_EXPR: case IMAGPART_EXPR: + case PAREN_EXPR: return build1 (code, tsubst (TREE_TYPE (t), args, complain, in_decl), tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl)); @@ -12858,9 +12949,9 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, handle local variables, and since we've already done all that needs to be done, that's the right thing to do. */ - if (TREE_CODE (decl) == VAR_DECL) + if (VAR_P (decl)) DECL_TEMPLATE_INSTANTIATED (decl) = 1; - if (TREE_CODE (decl) == VAR_DECL + if (VAR_P (decl) && ANON_AGGR_TYPE_P (TREE_TYPE (decl))) /* Anonymous aggregates are a special case. */ finish_anon_union (decl); @@ -12881,7 +12972,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, { int const_init = false; maybe_push_decl (decl); - if (TREE_CODE (decl) == VAR_DECL + if (VAR_P (decl) && DECL_PRETTY_FUNCTION_P (decl)) { /* For __PRETTY_FUNCTION__ we have to adjust the @@ -12912,7 +13003,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, init = t; } - if (TREE_CODE (decl) == VAR_DECL) + if (VAR_P (decl)) const_init = (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (pattern_decl)); cp_finish_decl (decl, init, const_init, NULL_TREE, 0); @@ -13179,15 +13270,15 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, stmt = begin_omp_structured_block (); + pre_body = push_stmt_list (); + RECUR (OMP_FOR_PRE_BODY (t)); + pre_body = pop_stmt_list (pre_body); + for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++) tsubst_omp_for_iterator (t, i, declv, initv, condv, incrv, &clauses, args, complain, in_decl, integral_constant_expression_p); - pre_body = push_stmt_list (); - RECUR (OMP_FOR_PRE_BODY (t)); - pre_body = pop_stmt_list (pre_body); - body = push_stmt_list (); RECUR (OMP_FOR_BODY (t)); body = pop_stmt_list (body); @@ -13393,6 +13484,11 @@ tsubst_copy_and_build (tree t, if (EXPR_HAS_LOCATION (t)) input_location = EXPR_LOCATION (t); + /* N3276 decltype magic only applies to calls at the top level or on the + right side of a comma. */ + tsubst_flags_t decltype_flag = (complain & tf_decltype); + complain &= ~tf_decltype; + switch (TREE_CODE (t)) { case USING_DECL: @@ -13422,7 +13518,7 @@ tsubst_copy_and_build (tree t, decl = finish_id_expression (t, decl, NULL_TREE, &idk, integral_constant_expression_p, - /*allow_non_integral_constant_expression_p=*/(cxx_dialect >= cxx0x), + /*allow_non_integral_constant_expression_p=*/(cxx_dialect >= cxx11), &non_integral_constant_expression_p, /*template_p=*/false, /*done=*/true, @@ -13432,7 +13528,7 @@ tsubst_copy_and_build (tree t, input_location); if (error_msg) error (error_msg); - if (!function_p && TREE_CODE (decl) == IDENTIFIER_NODE) + if (!function_p && identifier_p (decl)) { if (complain & tf_error) unqualified_name_lookup_error (decl); @@ -13479,7 +13575,8 @@ tsubst_copy_and_build (tree t, r = convert_from_reference (r); } else - r = build_x_indirect_ref (input_location, r, RO_UNARY_STAR, complain); + r = build_x_indirect_ref (input_location, r, RO_UNARY_STAR, + complain|decltype_flag); RETURN (r); } @@ -13556,7 +13653,8 @@ tsubst_copy_and_build (tree t, case POSTINCREMENT_EXPR: op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0), args, complain, in_decl); - RETURN (build_x_unary_op (input_location, TREE_CODE (t), op1, complain)); + RETURN (build_x_unary_op (input_location, TREE_CODE (t), op1, + complain|decltype_flag)); case PREDECREMENT_EXPR: case PREINCREMENT_EXPR: @@ -13568,7 +13666,8 @@ tsubst_copy_and_build (tree t, case REALPART_EXPR: case IMAGPART_EXPR: RETURN (build_x_unary_op (input_location, TREE_CODE (t), - RECUR (TREE_OPERAND (t, 0)), complain)); + RECUR (TREE_OPERAND (t, 0)), + complain|decltype_flag)); case FIX_TRUNC_EXPR: RETURN (cp_build_unary_op (FIX_TRUNC_EXPR, RECUR (TREE_OPERAND (t, 0)), @@ -13585,7 +13684,8 @@ tsubst_copy_and_build (tree t, else op1 = tsubst_non_call_postfix_expression (op1, args, complain, in_decl); - RETURN (build_x_unary_op (input_location, ADDR_EXPR, op1, complain)); + RETURN (build_x_unary_op (input_location, ADDR_EXPR, op1, + complain|decltype_flag)); case PLUS_EXPR: case MINUS_EXPR: @@ -13634,7 +13734,7 @@ tsubst_copy_and_build (tree t, ? ERROR_MARK : TREE_CODE (TREE_OPERAND (t, 1))), /*overload=*/NULL, - complain); + complain|decltype_flag); if (EXPR_P (r) && TREE_NO_WARNING (t)) TREE_NO_WARNING (r) = TREE_NO_WARNING (t); @@ -13650,8 +13750,23 @@ tsubst_copy_and_build (tree t, op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0), args, complain, in_decl); RETURN (build_x_array_ref (EXPR_LOCATION (t), op1, - RECUR (TREE_OPERAND (t, 1)), complain)); + RECUR (TREE_OPERAND (t, 1)), + complain|decltype_flag)); + case ARRAY_NOTATION_REF: + { + tree start_index, length, stride; + op1 = tsubst_non_call_postfix_expression (ARRAY_NOTATION_ARRAY (t), + args, complain, in_decl); + start_index = RECUR (ARRAY_NOTATION_START (t)); + length = RECUR (ARRAY_NOTATION_LENGTH (t)); + stride = RECUR (ARRAY_NOTATION_STRIDE (t)); + if (!cilkplus_an_triplet_types_ok_p (loc, start_index, length, stride, + TREE_TYPE (op1))) + RETURN (error_mark_node); + RETURN (build_array_notation_ref (EXPR_LOCATION (t), op1, start_index, + length, stride, TREE_TYPE (op1))); + } case SIZEOF_EXPR: if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))) RETURN (tsubst_copy (t, args, complain, in_decl)); @@ -13738,12 +13853,16 @@ tsubst_copy_and_build (tree t, case MODOP_EXPR: { - tree r = build_x_modify_expr + tree r; + + ++c_inhibit_evaluation_warnings; + + r = build_x_modify_expr (EXPR_LOCATION (t), RECUR (TREE_OPERAND (t, 0)), TREE_CODE (TREE_OPERAND (t, 1)), RECUR (TREE_OPERAND (t, 2)), - complain); + complain|decltype_flag); /* TREE_NO_WARNING must be set if either the expression was parenthesized or it uses an operator such as >>= rather than plain assignment. In the former case, it was already @@ -13752,6 +13871,9 @@ tsubst_copy_and_build (tree t, here. */ if (TREE_NO_WARNING (t)) TREE_NO_WARNING (r) = TREE_NO_WARNING (t); + + --c_inhibit_evaluation_warnings; + RETURN (r); } @@ -13824,10 +13946,16 @@ tsubst_copy_and_build (tree t, complain)); case COMPOUND_EXPR: - RETURN (build_x_compound_expr (EXPR_LOCATION (t), - RECUR (TREE_OPERAND (t, 0)), - RECUR (TREE_OPERAND (t, 1)), - complain)); + { + tree op0 = tsubst_copy_and_build (TREE_OPERAND (t, 0), args, + complain & ~tf_decltype, in_decl, + /*function_p=*/false, + integral_constant_expression_p); + RETURN (build_x_compound_expr (EXPR_LOCATION (t), + op0, + RECUR (TREE_OPERAND (t, 1)), + complain|decltype_flag)); + } case CALL_EXPR: { @@ -13849,7 +13977,7 @@ tsubst_copy_and_build (tree t, /*done=*/false, /*address_p=*/false); } - else if (koenig_p && TREE_CODE (function) == IDENTIFIER_NODE) + else if (koenig_p && identifier_p (function)) { /* Do nothing; calling tsubst_copy_and_build on an identifier would incorrectly perform unqualified lookup again. @@ -13933,7 +14061,7 @@ tsubst_copy_and_build (tree t, not appropriate, even if an unqualified-name was used to denote the function. */ && !DECL_FUNCTION_MEMBER_P (get_first_fn (function))) - || TREE_CODE (function) == IDENTIFIER_NODE) + || identifier_p (function)) /* Only do this when substitution turns a dependent call into a non-dependent call. */ && type_dependent_expression_p_push (t) @@ -13941,7 +14069,7 @@ tsubst_copy_and_build (tree t, function = perform_koenig_lookup (function, call_args, false, tf_none); - if (TREE_CODE (function) == IDENTIFIER_NODE + if (identifier_p (function) && !any_type_dependent_arguments_p (call_args)) { if (koenig_p && (complain & tf_warning_or_error)) @@ -13958,40 +14086,42 @@ tsubst_copy_and_build (tree t, if (unq != function) { tree fn = unq; - if (TREE_CODE (fn) == INDIRECT_REF) + if (INDIRECT_REF_P (fn)) fn = TREE_OPERAND (fn, 0); if (TREE_CODE (fn) == COMPONENT_REF) fn = TREE_OPERAND (fn, 1); if (is_overloaded_fn (fn)) fn = get_first_fn (fn); - permerror (EXPR_LOC_OR_HERE (t), - "%qD was not declared in this scope, " - "and no declarations were found by " - "argument-dependent lookup at the point " - "of instantiation", function); - if (!DECL_P (fn)) - /* Can't say anything more. */; - else if (DECL_CLASS_SCOPE_P (fn)) + if (permerror (EXPR_LOC_OR_HERE (t), + "%qD was not declared in this scope, " + "and no declarations were found by " + "argument-dependent lookup at the point " + "of instantiation", function)) { - inform (EXPR_LOC_OR_HERE (t), - "declarations in dependent base %qT are " - "not found by unqualified lookup", - DECL_CLASS_CONTEXT (fn)); - if (current_class_ptr) - inform (EXPR_LOC_OR_HERE (t), - "use %<this->%D%> instead", function); + if (!DECL_P (fn)) + /* Can't say anything more. */; + else if (DECL_CLASS_SCOPE_P (fn)) + { + inform (EXPR_LOC_OR_HERE (t), + "declarations in dependent base %qT are " + "not found by unqualified lookup", + DECL_CLASS_CONTEXT (fn)); + if (current_class_ptr) + inform (EXPR_LOC_OR_HERE (t), + "use %<this->%D%> instead", function); + else + inform (EXPR_LOC_OR_HERE (t), + "use %<%T::%D%> instead", + current_class_name, function); + } else - inform (EXPR_LOC_OR_HERE (t), - "use %<%T::%D%> instead", - current_class_name, function); + inform (0, "%q+D declared here, later in the " + "translation unit", fn); } - else - inform (0, "%q+D declared here, later in the " - "translation unit", fn); function = unq; } } - if (TREE_CODE (function) == IDENTIFIER_NODE) + if (identifier_p (function)) { if (complain & tf_error) unqualified_name_lookup_error (function); @@ -14004,6 +14134,9 @@ tsubst_copy_and_build (tree t, if (DECL_P (function)) mark_used (function); + /* Put back tf_decltype for the actual call. */ + complain |= decltype_flag; + if (TREE_CODE (function) == OFFSET_REF) ret = build_offset_ref_call_from_tree (function, &call_args, complain); @@ -14293,7 +14426,10 @@ tsubst_copy_and_build (tree t, newlen = vec_safe_length (n); FOR_EACH_VEC_SAFE_ELT (n, idx, ce) { - if (ce->index && process_index_p) + if (ce->index && process_index_p + /* An identifier index is looked up in the type + being initialized, not the current scope. */ + && TREE_CODE (ce->index) != IDENTIFIER_NODE) ce->index = RECUR (ce->index); if (PACK_EXPANSION_P (ce->value)) @@ -14471,12 +14607,6 @@ tsubst_copy_and_build (tree t, declaration of the op() for later calls to lambda_function. */ complete_type (type); - /* The capture list refers to closure members, so this needs to - wait until after we finish instantiating the type. Also keep - any captures that may have been added during instantiation. */ - LAMBDA_EXPR_CAPTURE_LIST (r) - = chainon (RECUR (LAMBDA_EXPR_CAPTURE_LIST (t)), - LAMBDA_EXPR_CAPTURE_LIST (r)); LAMBDA_EXPR_THIS_CAPTURE (r) = NULL_TREE; RETURN (build_lambda_object (r)); @@ -14495,6 +14625,9 @@ tsubst_copy_and_build (tree t, RETURN (tsubst_expr(t, args, complain, in_decl, integral_constant_expression_p)); + case PAREN_EXPR: + RETURN (finish_parenthesized_expr (RECUR (TREE_OPERAND (t, 0)))); + default: /* Handle Objective-C++ constructs, if appropriate. */ { @@ -14881,7 +15014,8 @@ fn_type_unification (tree fn, tree return_type, unification_kind_t strict, int flags, - bool explain_p) + bool explain_p, + bool decltype_p) { tree parms; tree fntype; @@ -14895,6 +15029,9 @@ fn_type_unification (tree fn, tree tinst; tree r = error_mark_node; + if (decltype_p) + complain |= tf_decltype; + /* In C++0x, it's possible to have a function template whose type depends on itself recursively. This is most obvious with decltype, but can also occur with enumeration scope (c++/48969). So we need to catch infinite @@ -15042,9 +15179,21 @@ fn_type_unification (tree fn, callers must be ready to deal with unification failures in any event. */ + TREE_VALUE (tinst) = targs; + /* If we aren't explaining yet, push tinst context so we can see where + any errors (e.g. from class instantiations triggered by instantiation + of default template arguments) come from. If we are explaining, this + context is redundant. */ + if (!explain_p && !push_tinst_level (tinst)) + { + excessive_deduction_depth = true; + goto fail; + } ok = !type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn), targs, parms, args, nargs, /*subr=*/0, strict, flags, explain_p); + if (!explain_p) + pop_tinst_level (); if (!ok) goto fail; @@ -15296,6 +15445,135 @@ check_non_deducible_conversion (tree parm, tree arg, int strict, return unify_arg_conversion (explain_p, parm, type, arg); } +static bool uses_deducible_template_parms (tree type); + +/* Returns true iff the expression EXPR is one from which a template + argument can be deduced. In other words, if it's an undecorated + use of a template non-type parameter. */ + +static bool +deducible_expression (tree expr) +{ + return (TREE_CODE (expr) == TEMPLATE_PARM_INDEX); +} + +/* Returns true iff the array domain DOMAIN uses a template parameter in a + deducible way; that is, if it has a max value of <PARM> - 1. */ + +static bool +deducible_array_bound (tree domain) +{ + if (domain == NULL_TREE) + return false; + + tree max = TYPE_MAX_VALUE (domain); + if (TREE_CODE (max) != MINUS_EXPR) + return false; + + return deducible_expression (TREE_OPERAND (max, 0)); +} + +/* Returns true iff the template arguments ARGS use a template parameter + in a deducible way. */ + +static bool +deducible_template_args (tree args) +{ + for (int i = 0; i < TREE_VEC_LENGTH (args); ++i) + { + bool deducible; + tree elt = TREE_VEC_ELT (args, i); + if (ARGUMENT_PACK_P (elt)) + deducible = deducible_template_args (ARGUMENT_PACK_ARGS (elt)); + else + { + if (PACK_EXPANSION_P (elt)) + elt = PACK_EXPANSION_PATTERN (elt); + if (TREE_CODE (elt) == TEMPLATE_TEMPLATE_PARM) + deducible = true; + else if (TYPE_P (elt)) + deducible = uses_deducible_template_parms (elt); + else + deducible = deducible_expression (elt); + } + if (deducible) + return true; + } + return false; +} + +/* Returns true iff TYPE contains any deducible references to template + parameters, as per 14.8.2.5. */ + +static bool +uses_deducible_template_parms (tree type) +{ + if (PACK_EXPANSION_P (type)) + type = PACK_EXPANSION_PATTERN (type); + + /* T + cv-list T + TT<T> + TT<i> + TT<> */ + if (TREE_CODE (type) == TEMPLATE_TYPE_PARM + || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM) + return true; + + /* T* + T& + T&& */ + if (POINTER_TYPE_P (type)) + return uses_deducible_template_parms (TREE_TYPE (type)); + + /* T[integer-constant ] + type [i] */ + if (TREE_CODE (type) == ARRAY_TYPE) + return (uses_deducible_template_parms (TREE_TYPE (type)) + || deducible_array_bound (TYPE_DOMAIN (type))); + + /* T type ::* + type T::* + T T::* + T (type ::*)() + type (T::*)() + type (type ::*)(T) + type (T::*)(T) + T (type ::*)(T) + T (T::*)() + T (T::*)(T) */ + if (TYPE_PTRMEM_P (type)) + return (uses_deducible_template_parms (TYPE_PTRMEM_CLASS_TYPE (type)) + || (uses_deducible_template_parms + (TYPE_PTRMEM_POINTED_TO_TYPE (type)))); + + /* template-name <T> (where template-name refers to a class template) + template-name <i> (where template-name refers to a class template) */ + if (CLASS_TYPE_P (type) + && CLASSTYPE_TEMPLATE_INFO (type) + && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))) + return deducible_template_args (INNERMOST_TEMPLATE_ARGS + (CLASSTYPE_TI_ARGS (type))); + + /* type (T) + T() + T(T) */ + if (TREE_CODE (type) == FUNCTION_TYPE + || TREE_CODE (type) == METHOD_TYPE) + { + if (uses_deducible_template_parms (TREE_TYPE (type))) + return true; + tree parm = TYPE_ARG_TYPES (type); + if (TREE_CODE (type) == METHOD_TYPE) + parm = TREE_CHAIN (parm); + for (; parm; parm = TREE_CHAIN (parm)) + if (uses_deducible_template_parms (TREE_VALUE (parm))) + return true; + } + + return false; +} + /* Subroutine of type_unification_real and unify_pack_expansion to handle unification of a single P/A pair. Parameters are as for those functions. */ @@ -15315,10 +15593,21 @@ unify_one_argument (tree tparms, tree targs, tree parm, tree arg, template args from other function args. */ return unify_success (explain_p); - /* FIXME uses_deducible_template_parms */ + /* Implicit conversions (Clause 4) will be performed on a function + argument to convert it to the type of the corresponding function + parameter if the parameter type contains no template-parameters that + participate in template argument deduction. */ if (TYPE_P (parm) && !uses_template_parms (parm)) + /* For function parameters that contain no template-parameters at all, + we have historically checked for convertibility in order to shortcut + consideration of this candidate. */ return check_non_deducible_conversion (parm, arg, strict, flags, explain_p); + else if (strict == DEDUCE_CALL + && TYPE_P (parm) && !uses_deducible_template_parms (parm)) + /* For function parameters with only non-deducible template parameters, + just return. */ + return unify_success (explain_p); switch (strict) { @@ -15450,6 +15739,9 @@ type_unification_real (tree tparms, arg = args[ia]; ++ia; + if (flag_enable_cilkplus && TREE_CODE (arg) == ARRAY_NOTATION_REF) + return 1; + if (unify_one_argument (tparms, targs, parm, arg, subr, strict, flags, explain_p)) return 1; @@ -15805,7 +16097,7 @@ resolve_nondeduced_context (tree orig_expr) { tree base = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (offset, 0))); - expr = build_offset_ref (base, expr, addr); + expr = build_offset_ref (base, expr, addr, tf_warning_or_error); } if (addr) expr = cp_build_addr_expr (expr, tf_warning_or_error); @@ -16155,10 +16447,10 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms, arg = NULL_TREE; if (TREE_VALUE (pack) && (pargs = ARGUMENT_PACK_EXPLICIT_ARGS (TREE_VALUE (pack))) - && (i < TREE_VEC_LENGTH (pargs))) + && (i - start < TREE_VEC_LENGTH (pargs))) { any_explicit = true; - arg = TREE_VEC_ELT (pargs, i); + arg = TREE_VEC_ELT (pargs, i - start); } TMPL_ARG (targs, level, idx) = arg; } @@ -16689,8 +16981,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, else if (same_type_p (TREE_TYPE (arg), tparm)) /* OK */; else if ((strict & UNIFY_ALLOW_INTEGER) - && (TREE_CODE (tparm) == INTEGER_TYPE - || TREE_CODE (tparm) == BOOLEAN_TYPE)) + && CP_INTEGRAL_TYPE_P (tparm)) /* Convert the ARG to the type of PARM; the deduced non-type template argument must exactly match the types of the corresponding parameter. */ @@ -16700,7 +16991,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, later. */ return unify_success (explain_p); else - return unify_type_mismatch (explain_p, tparm, arg); + return unify_type_mismatch (explain_p, tparm, TREE_TYPE (arg)); /* If ARG is a parameter pack or an expansion, we cannot unify against it unless PARM is also a parameter pack. */ @@ -16735,7 +17026,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, case POINTER_TYPE: { - if (TREE_CODE (arg) != POINTER_TYPE) + if (!TYPE_PTR_P (arg)) return unify_type_mismatch (explain_p, parm, arg); /* [temp.deduct.call] @@ -17022,9 +17313,6 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, deduces the type of the member as a function type. */ if (TYPE_PTRMEMFUNC_P (arg)) { - tree method_type; - tree fntype; - /* Check top-level cv qualifiers */ if (!check_cv_quals_for_unify (UNIFY_ALLOW_NONE, arg, parm)) return unify_cv_qual_mismatch (explain_p, parm, arg); @@ -17034,15 +17322,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, UNIFY_ALLOW_NONE, explain_p); /* Determine the type of the function we are unifying against. */ - method_type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (arg)); - fntype = - build_function_type (TREE_TYPE (method_type), - TREE_CHAIN (TYPE_ARG_TYPES (method_type))); - - /* Extract the cv-qualifiers of the member function from the - implicit object parameter and place them on the function - type to be restored later. */ - fntype = apply_memfn_quals (fntype, type_memfn_quals (method_type)); + tree fntype = static_fn_type (arg); + return unify (tparms, targs, TREE_TYPE (parm), fntype, strict, explain_p); } @@ -17148,6 +17429,13 @@ mark_decl_instantiated (tree result, int extern_p) if (TREE_ASM_WRITTEN (result)) return; + /* For anonymous namespace we don't need to do anything. */ + if (decl_anon_ns_mem_p (result)) + { + gcc_assert (!TREE_PUBLIC (result)); + return; + } + if (TREE_CODE (result) != FUNCTION_DECL) /* The TREE_PUBLIC flag for function declarations will have been set correctly by tsubst. */ @@ -17572,7 +17860,8 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype) args, ix, (check_rettype || DECL_CONV_FN_P (fn) ? TREE_TYPE (decl_type) : NULL_TREE), - DEDUCE_EXACT, LOOKUP_NORMAL, /*explain_p=*/false) + DEDUCE_EXACT, LOOKUP_NORMAL, /*explain_p=*/false, + /*decltype*/false) == error_mark_node) return NULL_TREE; @@ -17821,7 +18110,8 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain) { tree partial_spec_args; tree spec_args; - tree parms = TREE_VALUE (t); + tree spec_tmpl = TREE_VALUE (t); + tree orig_parms = DECL_INNERMOST_TEMPLATE_PARMS (spec_tmpl); partial_spec_args = CLASSTYPE_TI_ARGS (TREE_TYPE (t)); @@ -17829,24 +18119,14 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain) if (outer_args) { - int i; - /* Discard the outer levels of args, and then substitute in the template args from the enclosing class. */ partial_spec_args = INNERMOST_TEMPLATE_ARGS (partial_spec_args); partial_spec_args = tsubst_template_args (partial_spec_args, outer_args, tf_none, NULL_TREE); - /* PARMS already refers to just the innermost parms, but the - template parms in partial_spec_args had their levels lowered - by tsubst, so we need to do the same for the parm list. We - can't just tsubst the TREE_VEC itself, as tsubst wants to - treat a TREE_VEC as an argument vector. */ - parms = copy_node (parms); - for (i = TREE_VEC_LENGTH (parms) - 1; i >= 0; --i) - TREE_VEC_ELT (parms, i) = - tsubst (TREE_VEC_ELT (parms, i), outer_args, tf_none, NULL_TREE); - + /* And the same for the partial specialization TEMPLATE_DECL. */ + spec_tmpl = tsubst (spec_tmpl, outer_args, tf_none, NULL_TREE); } partial_spec_args = @@ -17861,7 +18141,10 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain) if (partial_spec_args == error_mark_node) return error_mark_node; + if (spec_tmpl == error_mark_node) + return error_mark_node; + tree parms = DECL_INNERMOST_TEMPLATE_PARMS (spec_tmpl); spec_args = get_class_bindings (tmpl, parms, partial_spec_args, args); @@ -17869,7 +18152,7 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain) { if (outer_args) spec_args = add_to_template_args (outer_args, spec_args); - list = tree_cons (spec_args, TREE_VALUE (t), list); + list = tree_cons (spec_args, orig_parms, list); TREE_TYPE (list) = TREE_TYPE (t); } } @@ -17949,7 +18232,7 @@ do_decl_instantiation (tree decl, tree storage) error ("explicit instantiation of non-template %q#D", decl); return; } - else if (TREE_CODE (decl) == VAR_DECL) + else if (VAR_P (decl)) { /* There is an asymmetry here in the way VAR_DECLs and FUNCTION_DECLs are handled by grokdeclarator. In the case of @@ -17965,7 +18248,7 @@ do_decl_instantiation (tree decl, tree storage) return; } result = lookup_field (DECL_CONTEXT (decl), DECL_NAME (decl), 0, false); - if (!result || TREE_CODE (result) != VAR_DECL) + if (!result || !VAR_P (result)) { error ("no matching template for %qD found", decl); return; @@ -18227,7 +18510,7 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain) instantiate_class_member (tmp, extern_p); for (tmp = TYPE_FIELDS (t); tmp; tmp = DECL_CHAIN (tmp)) - if (TREE_CODE (tmp) == VAR_DECL && DECL_TEMPLATE_INSTANTIATION (tmp)) + if (VAR_P (tmp) && DECL_TEMPLATE_INSTANTIATION (tmp)) instantiate_class_member (tmp, extern_p); if (CLASSTYPE_NESTED_UTDS (t)) @@ -18356,7 +18639,7 @@ regenerate_decl_from_template (tree decl, tree tmpl) && !DECL_DECLARED_INLINE_P (decl)) DECL_DECLARED_INLINE_P (decl) = 1; } - else if (TREE_CODE (decl) == VAR_DECL) + else if (VAR_P (decl)) { DECL_INITIAL (decl) = tsubst_expr (DECL_INITIAL (code_pattern), args, @@ -18420,7 +18703,7 @@ template_for_substitution (tree decl) cannot restructure the loop to just keep going until we find a template with a definition, since that might go too far if a specialization was declared, but not defined. */ - gcc_assert (TREE_CODE (decl) != VAR_DECL + gcc_assert (!VAR_P (decl) || DECL_IN_AGGR_P (DECL_TEMPLATE_RESULT (tmpl))); /* Fetch the more general template. */ @@ -18448,7 +18731,7 @@ always_instantiate_p (tree decl) /* And we need to instantiate static data members so that their initializers are available in integral constant expressions. */ - || (TREE_CODE (decl) == VAR_DECL + || (VAR_P (decl) && decl_maybe_constant_var_p (decl))); } @@ -18545,15 +18828,14 @@ instantiate_decl (tree d, int defer_ok, /* This function should only be used to instantiate templates for functions and static member variables. */ - gcc_assert (TREE_CODE (d) == FUNCTION_DECL - || TREE_CODE (d) == VAR_DECL); + gcc_assert (VAR_OR_FUNCTION_DECL_P (d)); /* Variables are never deferred; if instantiation is required, they are instantiated right away. That allows for better code in the case that an expression refers to the value of the variable -- if the variable has a constant value the referring expression can take advantage of that fact. */ - if (TREE_CODE (d) == VAR_DECL + if (VAR_P (d) || DECL_DECLARED_CONSTEXPR_P (d)) defer_ok = 0; @@ -18672,11 +18954,11 @@ instantiate_decl (tree d, int defer_ok, elsewhere, we don't want to instantiate the entire data member, but we do want to instantiate the initializer so that we can substitute that elsewhere. */ - || (external_p && TREE_CODE (d) == VAR_DECL)) + || (external_p && VAR_P (d))) { /* The definition of the static data member is now required so we must substitute the initializer. */ - if (TREE_CODE (d) == VAR_DECL + if (VAR_P (d) && !DECL_INITIAL (d) && DECL_INITIAL (code_pattern)) { @@ -18726,7 +19008,7 @@ instantiate_decl (tree d, int defer_ok, goto out; /* ??? Historically, we have instantiated inline functions, even when marked as "extern template". */ - if (!(external_p && TREE_CODE (d) == VAR_DECL)) + if (!(external_p && VAR_P (d))) add_pending_template (d); goto out; } @@ -18766,7 +19048,7 @@ instantiate_decl (tree d, int defer_ok, they changed as a result of calling regenerate_decl_from_template. */ input_location = DECL_SOURCE_LOCATION (d); - if (TREE_CODE (d) == VAR_DECL) + if (VAR_P (d)) { tree init; bool const_init = false; @@ -18861,6 +19143,11 @@ instantiate_decl (tree d, int defer_ok, pointer_map_destroy (local_specializations); local_specializations = saved_local_specializations; + /* We expand all the array notation expressions here. */ + if (flag_enable_cilkplus + && contains_array_notation_expr (DECL_SAVED_TREE (d))) + DECL_SAVED_TREE (d) = expand_array_notation_exprs (DECL_SAVED_TREE (d)); + /* Finish the function. */ d = finish_function (0); expand_or_defer_fn (d); @@ -19320,7 +19607,7 @@ dependent_type_p_r (tree type) return (dependent_type_p (TYPE_PTRMEM_CLASS_TYPE (type)) || dependent_type_p (TYPE_PTRMEM_POINTED_TO_TYPE (type))); - else if (TREE_CODE (type) == POINTER_TYPE + else if (TYPE_PTR_P (type) || TREE_CODE (type) == REFERENCE_TYPE) return dependent_type_p (TREE_TYPE (type)); else if (TREE_CODE (type) == FUNCTION_TYPE @@ -19547,7 +19834,7 @@ value_dependent_expression_p (tree expression) /* If there are no operands, it must be an expression such as "int()". This should not happen for aggregate types because it would form non-constant expressions. */ - gcc_assert (cxx_dialect >= cxx0x + gcc_assert (cxx_dialect >= cxx11 || INTEGRAL_OR_ENUMERATION_TYPE_P (type)); return false; @@ -19726,8 +20013,7 @@ type_dependent_expression_p (tree expression) return false; /* An unresolved name is always dependent. */ - if (TREE_CODE (expression) == IDENTIFIER_NODE - || TREE_CODE (expression) == USING_DECL) + if (identifier_p (expression) || TREE_CODE (expression) == USING_DECL) return true; /* Some expression forms are never type-dependent. */ @@ -19816,12 +20102,35 @@ type_dependent_expression_p (tree expression) /* A static data member of the current instantiation with incomplete array type is type-dependent, as the definition and specializations can have different bounds. */ - if (TREE_CODE (expression) == VAR_DECL + if (VAR_P (expression) && DECL_CLASS_SCOPE_P (expression) && dependent_type_p (DECL_CONTEXT (expression)) && VAR_HAD_UNKNOWN_BOUND (expression)) return true; + /* An array of unknown bound depending on a variadic parameter, eg: + + template<typename... Args> + void foo (Args... args) + { + int arr[] = { args... }; + } + + template<int... vals> + void bar () + { + int arr[] = { vals... }; + } + + If the array has no length and has an initializer, it must be that + we couldn't determine its length in cp_complete_array_type because + it is dependent. */ + if (VAR_P (expression) + && TREE_CODE (TREE_TYPE (expression)) == ARRAY_TYPE + && !TYPE_DOMAIN (TREE_TYPE (expression)) + && DECL_INITIAL (expression)) + return true; + if (TREE_TYPE (expression) == unknown_type_node) { if (TREE_CODE (expression) == ADDR_EXPR) @@ -19832,7 +20141,7 @@ type_dependent_expression_p (tree expression) if (type_dependent_expression_p (TREE_OPERAND (expression, 0))) return true; expression = TREE_OPERAND (expression, 1); - if (TREE_CODE (expression) == IDENTIFIER_NODE) + if (identifier_p (expression)) return false; } /* SCOPE_REF with non-null TREE_TYPE is always non-dependent. */ @@ -19890,6 +20199,13 @@ instantiation_dependent_r (tree *tp, int *walk_subtrees, case TREE_VEC: return NULL_TREE; + case VAR_DECL: + case CONST_DECL: + /* A constant with a dependent initializer is dependent. */ + if (value_dependent_expression_p (*tp)) + return *tp; + break; + case TEMPLATE_PARM_INDEX: return *tp; @@ -19917,13 +20233,14 @@ instantiation_dependent_r (tree *tp, int *walk_subtrees, case TRAIT_EXPR: if (dependent_type_p (TRAIT_EXPR_TYPE1 (*tp)) - || dependent_type_p (TRAIT_EXPR_TYPE2 (*tp))) + || (TRAIT_EXPR_TYPE2 (*tp) + && dependent_type_p (TRAIT_EXPR_TYPE2 (*tp)))) return *tp; *walk_subtrees = false; return NULL_TREE; case COMPONENT_REF: - if (TREE_CODE (TREE_OPERAND (*tp, 1)) == IDENTIFIER_NODE) + if (identifier_p (TREE_OPERAND (*tp, 1))) /* In a template, finish_class_member_access_expr creates a COMPONENT_REF with an IDENTIFIER_NODE for op1 even if it isn't type-dependent, so that we can check access control at @@ -20106,8 +20423,7 @@ any_template_arguments_need_structural_equality_p (tree args) if (error_operand_p (arg)) return true; - else if (TREE_CODE (arg) == TEMPLATE_DECL - || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM) + else if (TREE_CODE (arg) == TEMPLATE_DECL) continue; else if (TYPE_P (arg) && TYPE_STRUCTURAL_EQUALITY_P (arg)) return true; @@ -20167,8 +20483,7 @@ dependent_template_p (tree tmpl) || TREE_CODE (tmpl) == TEMPLATE_TEMPLATE_PARM) return true; /* So are names that have not been looked up. */ - if (TREE_CODE (tmpl) == SCOPE_REF - || TREE_CODE (tmpl) == IDENTIFIER_NODE) + if (TREE_CODE (tmpl) == SCOPE_REF || identifier_p (tmpl)) return true; /* So are member templates of dependent classes. */ if (TYPE_P (CP_DECL_CONTEXT (tmpl))) @@ -20325,7 +20640,7 @@ resolve_typename_type (tree type, bool only_current_p) find a TEMPLATE_DECL. Otherwise, we want to find a TYPE_DECL. */ if (!decl) /*nop*/; - else if (TREE_CODE (TYPENAME_TYPE_FULLNAME (type)) == IDENTIFIER_NODE + else if (identifier_p (TYPENAME_TYPE_FULLNAME (type)) && TREE_CODE (decl) == TYPE_DECL) { result = TREE_TYPE (decl); @@ -20386,8 +20701,7 @@ build_non_dependent_expr (tree expr) #ifdef ENABLE_CHECKING /* Try to get a constant value for all non-dependent expressions in order to expose bugs in *_dependent_expression_p and constexpr. */ - if (cxx_dialect >= cxx0x - && !instantiation_dependent_expression_p (expr)) + if (cxx_dialect >= cxx11) maybe_constant_value (fold_non_dependent_expr_sfinae (expr, tf_none)); #endif @@ -20404,7 +20718,7 @@ build_non_dependent_expr (tree expr) || TREE_CODE (inner_expr) == OFFSET_REF) return expr; /* There is no need to return a proxy for a variable. */ - if (TREE_CODE (expr) == VAR_DECL) + if (VAR_P (expr)) return expr; /* Preserve string constants; conversions from string constants to "char *" are allowed, even though normally a "const char *" @@ -20471,15 +20785,16 @@ make_args_non_dependent (vec<tree, va_gc> *args) } } -/* Returns a type which represents 'auto'. We use a TEMPLATE_TYPE_PARM - with a level one deeper than the actual template parms. */ +/* Returns a type which represents 'auto' or 'decltype(auto)'. We use a + TEMPLATE_TYPE_PARM with a level one deeper than the actual template + parms. */ -tree -make_auto (void) +static tree +make_auto_1 (tree name) { tree au = cxx_make_type (TEMPLATE_TYPE_PARM); TYPE_NAME (au) = build_decl (BUILTINS_LOCATION, - TYPE_DECL, get_identifier ("auto"), au); + TYPE_DECL, name, au); TYPE_STUB_DECL (au) = TYPE_NAME (au); TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index (0, processing_template_decl + 1, processing_template_decl + 1, @@ -20491,6 +20806,18 @@ make_auto (void) return au; } +tree +make_decltype_auto (void) +{ + return make_auto_1 (get_identifier ("decltype(auto)")); +} + +tree +make_auto (void) +{ + return make_auto_1 (get_identifier ("auto")); +} + /* Given type ARG, return std::initializer_list<ARG>. */ static tree @@ -20530,9 +20857,7 @@ listify_autos (tree type, tree auto_node) tree do_auto_deduction (tree type, tree init, tree auto_node) { - tree parms, tparms, targs; - tree args[1]; - int val; + tree targs; if (init == error_mark_node) return error_mark_node; @@ -20551,32 +20876,47 @@ do_auto_deduction (tree type, tree init, tree auto_node) init = resolve_nondeduced_context (init); - parms = build_tree_list (NULL_TREE, type); - args[0] = init; - tparms = make_tree_vec (1); targs = make_tree_vec (1); - TREE_VEC_ELT (tparms, 0) - = build_tree_list (NULL_TREE, TYPE_NAME (auto_node)); - val = type_unification_real (tparms, targs, parms, args, 1, 0, - DEDUCE_CALL, LOOKUP_NORMAL, - /*explain_p=*/false); - if (val > 0) - { - if (processing_template_decl) - /* Try again at instantiation time. */ - return type; - if (type && type != error_mark_node) - /* If type is error_mark_node a diagnostic must have been - emitted by now. Also, having a mention to '<type error>' - in the diagnostic is not really useful to the user. */ + if (AUTO_IS_DECLTYPE (auto_node)) + { + bool id = (DECL_P (init) || TREE_CODE (init) == COMPONENT_REF); + TREE_VEC_ELT (targs, 0) + = finish_decltype_type (init, id, tf_warning_or_error); + if (type != auto_node) { - if (cfun && auto_node == current_function_auto_return_pattern - && LAMBDA_FUNCTION_P (current_function_decl)) - error ("unable to deduce lambda return type from %qE", init); - else - error ("unable to deduce %qT from %qE", type, init); + error ("%qT as type rather than plain %<decltype(auto)%>", type); + return error_mark_node; + } + } + else + { + tree parms = build_tree_list (NULL_TREE, type); + tree tparms = make_tree_vec (1); + int val; + + TREE_VEC_ELT (tparms, 0) + = build_tree_list (NULL_TREE, TYPE_NAME (auto_node)); + val = type_unification_real (tparms, targs, parms, &init, 1, 0, + DEDUCE_CALL, LOOKUP_NORMAL, + /*explain_p=*/false); + if (val > 0) + { + if (processing_template_decl) + /* Try again at instantiation time. */ + return type; + if (type && type != error_mark_node) + /* If type is error_mark_node a diagnostic must have been + emitted by now. Also, having a mention to '<type error>' + in the diagnostic is not really useful to the user. */ + { + if (cfun && auto_node == current_function_auto_return_pattern + && LAMBDA_FUNCTION_P (current_function_decl)) + error ("unable to deduce lambda return type from %qE", init); + else + error ("unable to deduce %qT from %qE", type, init); + } + return error_mark_node; } - return error_mark_node; } /* If the list of declarators contains more than one declarator, the type @@ -20625,13 +20965,15 @@ splice_late_return_type (tree type, tree late_return_type) return tsubst (type, argvec, tf_warning_or_error, NULL_TREE); } -/* Returns true iff TYPE is a TEMPLATE_TYPE_PARM representing 'auto'. */ +/* Returns true iff TYPE is a TEMPLATE_TYPE_PARM representing 'auto' or + 'decltype(auto)'. */ bool is_auto (const_tree type) { if (TREE_CODE (type) == TEMPLATE_TYPE_PARM - && TYPE_IDENTIFIER (type) == get_identifier ("auto")) + && (TYPE_IDENTIFIER (type) == get_identifier ("auto") + || TYPE_IDENTIFIER (type) == get_identifier ("decltype(auto)"))) return true; else return false; diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c index deba90fd488..f4ca003be98 100644 --- a/gcc/cp/ptree.c +++ b/gcc/cp/ptree.c @@ -63,7 +63,7 @@ cxx_print_decl (FILE *file, tree node, int indent) && DECL_PENDING_INLINE_INFO (node)) fprintf (file, " pending-inline-info %p", (void *) DECL_PENDING_INLINE_INFO (node)); - if ((TREE_CODE (node) == FUNCTION_DECL || TREE_CODE (node) == VAR_DECL) + if (VAR_OR_FUNCTION_DECL_P (node) && DECL_TEMPLATE_INFO (node)) fprintf (file, " template-info %p", (void *) DECL_TEMPLATE_INFO (node)); diff --git a/gcc/cp/repo.c b/gcc/cp/repo.c index 8b9f73f223a..7b6f7b8ce1b 100644 --- a/gcc/cp/repo.c +++ b/gcc/cp/repo.c @@ -291,8 +291,7 @@ repo_emit_p (tree decl) { int ret = 0; gcc_assert (TREE_PUBLIC (decl)); - gcc_assert (TREE_CODE (decl) == FUNCTION_DECL - || TREE_CODE (decl) == VAR_DECL); + gcc_assert (VAR_OR_FUNCTION_DECL_P (decl)); gcc_assert (!DECL_REALLY_EXTERN (decl)); /* When not using the repository, emit everything. */ @@ -303,7 +302,7 @@ repo_emit_p (tree decl) is an artificial restriction; the code in the prelinker and here will work fine if all entities with vague linkage are managed by the repository. */ - if (TREE_CODE (decl) == VAR_DECL) + if (VAR_P (decl)) { tree type = NULL_TREE; if (DECL_VTABLE_OR_VTT_P (decl)) diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 6c02c1cf0da..f3094981dfb 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -173,7 +173,7 @@ build_headof (tree exp) tree offset; tree index; - gcc_assert (TREE_CODE (type) == POINTER_TYPE); + gcc_assert (TYPE_PTR_P (type)); type = TREE_TYPE (type); if (!TYPE_POLYMORPHIC_P (type)) @@ -326,18 +326,16 @@ build_typeid (tree exp, tsubst_flags_t complain) /* FIXME when integrating with c_fully_fold, mark resolves_to_fixed_type_p case as a non-constant expression. */ - if (TREE_CODE (exp) == INDIRECT_REF - && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE - && TYPE_POLYMORPHIC_P (TREE_TYPE (exp)) + if (TYPE_POLYMORPHIC_P (TREE_TYPE (exp)) && ! resolves_to_fixed_type_p (exp, &nonnull) && ! nonnull) { /* So we need to look into the vtable of the type of exp. - This is an lvalue use of expr then. */ - exp = mark_lvalue_use (exp); + Make sure it isn't a null lvalue. */ + exp = cp_build_addr_expr (exp, complain); exp = stabilize_reference (exp); - cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0), - complain); + cond = cp_convert (boolean_type_node, exp, complain); + exp = cp_build_indirect_ref (exp, RO_NULL, complain); } exp = get_tinfo_decl_dynamic (exp, complain); @@ -395,9 +393,12 @@ get_tinfo_decl (tree type) if (variably_modified_type_p (type, /*fn=*/NULL_TREE)) { - error ("cannot create type information for type %qT because " - "it involves types of variable size", - type); + if (array_of_runtime_bound_p (type)) + error ("typeid of array of runtime bound"); + else + error ("cannot create type information for type %qT because " + "it involves types of variable size", + type); return error_mark_node; } @@ -479,6 +480,16 @@ get_typeid (tree type, tsubst_flags_t complain) referenced type. */ type = non_reference (type); + /* This is not one of the uses of a qualified function type in 8.3.5. */ + if (TREE_CODE (type) == FUNCTION_TYPE + && (type_memfn_quals (type) != TYPE_UNQUALIFIED + || type_memfn_rqual (type) != REF_QUAL_NONE)) + { + if (complain & tf_error) + error ("typeid of qualified function type %qT", type); + return error_mark_node; + } + /* The top-level cv-qualifiers of the lvalue expression or the type-id that is the operand of typeid are always ignored. */ type = TYPE_MAIN_VARIANT (type); @@ -528,7 +539,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain) switch (tc) { case POINTER_TYPE: - if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE) + if (VOID_TYPE_P (TREE_TYPE (type))) break; /* Fall through. */ case REFERENCE_TYPE: @@ -559,7 +570,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain) expr = mark_rvalue_use (expr); - if (TREE_CODE (exprtype) != POINTER_TYPE) + if (!TYPE_PTR_P (exprtype)) { errstr = _("source is not a pointer"); goto fail; @@ -611,19 +622,10 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain) /* If *type is an unambiguous accessible base class of *exprtype, convert statically. */ { - tree binfo; - - binfo = lookup_base (TREE_TYPE (exprtype), TREE_TYPE (type), - ba_check, NULL, complain); - + tree binfo = lookup_base (TREE_TYPE (exprtype), TREE_TYPE (type), + ba_check, NULL, complain); if (binfo) - { - expr = build_base_path (PLUS_EXPR, convert_from_reference (expr), - binfo, 0, complain); - if (TREE_CODE (exprtype) == POINTER_TYPE) - expr = rvalue (expr); - return expr; - } + return build_static_cast (type, expr, complain); } /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */ @@ -635,7 +637,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain) { /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */ if (TREE_CODE (expr) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL + && VAR_P (TREE_OPERAND (expr, 0)) && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE) return build1 (NOP_EXPR, type, expr); @@ -658,7 +660,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain) dynamic_cast<D&>(b) (b an object) cannot succeed. */ if (tc == REFERENCE_TYPE) { - if (TREE_CODE (old_expr) == VAR_DECL + if (VAR_P (old_expr) && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE) { tree expr = throw_bad_cast (); @@ -674,7 +676,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain) else if (TREE_CODE (expr) == ADDR_EXPR) { tree op = TREE_OPERAND (expr, 0); - if (TREE_CODE (op) == VAR_DECL + if (VAR_P (op) && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE) { if (complain & tf_warning) @@ -822,7 +824,7 @@ target_incomplete_p (tree type) return true; type = TYPE_PTRMEM_POINTED_TO_TYPE (type); } - else if (TREE_CODE (type) == POINTER_TYPE) + else if (TYPE_PTR_P (type)) type = TREE_TYPE (type); else return !COMPLETE_OR_VOID_TYPE_P (type); @@ -1053,7 +1055,7 @@ typeinfo_in_lib_p (tree type) { /* The typeinfo objects for `T*' and `const T*' are in the runtime library for simple types T. */ - if (TREE_CODE (type) == POINTER_TYPE + if (TYPE_PTR_P (type) && (cp_type_quals (TREE_TYPE (type)) == TYPE_QUAL_CONST || cp_type_quals (TREE_TYPE (type)) == TYPE_UNQUALIFIED)) type = TREE_TYPE (type); diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 4cc02ba7dfc..b113477d088 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -188,6 +188,14 @@ lookup_base (tree t, tree base, base_access access, tree t_binfo; base_kind bk; + /* "Nothing" is definitely not derived from Base. */ + if (t == NULL_TREE) + { + if (kind_ptr) + *kind_ptr = bk_not_base; + return NULL_TREE; + } + if (t == error_mark_node || base == error_mark_node) { if (kind_ptr) @@ -373,7 +381,7 @@ lookup_field_1 (tree type, tree name, bool want_type) { tree field; - gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); + gcc_assert (identifier_p (name)); if (TREE_CODE (type) == TEMPLATE_TYPE_PARM || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM @@ -416,8 +424,7 @@ lookup_field_1 (tree type, tree name, bool want_type) do field = fields[i--]; while (i >= lo && DECL_NAME (fields[i]) == name); - if (TREE_CODE (field) != TYPE_DECL - && !DECL_TYPE_TEMPLATE_P (field)) + if (!DECL_DECLARES_TYPE_P (field)) field = NULL_TREE; } else @@ -470,9 +477,7 @@ lookup_field_1 (tree type, tree name, bool want_type) } if (DECL_NAME (decl) == name - && (!want_type - || TREE_CODE (decl) == TYPE_DECL - || DECL_TYPE_TEMPLATE_P (decl))) + && (!want_type || DECL_DECLARES_TYPE_P (decl))) return decl; } /* Not found. */ @@ -769,8 +774,7 @@ friend_accessible_p (tree scope, tree decl, tree binfo) if (!scope) return 0; - if (TREE_CODE (scope) == FUNCTION_DECL - || DECL_FUNCTION_TEMPLATE_P (scope)) + if (DECL_DECLARES_FUNCTION_P (scope)) befriending_classes = DECL_BEFRIENDING_CLASSES (scope); else if (TYPE_P (scope)) befriending_classes = CLASSTYPE_BEFRIENDING_CLASSES (scope); @@ -788,8 +792,7 @@ friend_accessible_p (tree scope, tree decl, tree binfo) if (protected_accessible_p (decl, t, binfo)) return 1; - if (TREE_CODE (scope) == FUNCTION_DECL - || DECL_FUNCTION_TEMPLATE_P (scope)) + if (DECL_DECLARES_FUNCTION_P (scope)) { /* Perhaps this SCOPE is a member of a class which is a friend. */ @@ -975,7 +978,7 @@ struct lookup_field_info { int shared_member_p (tree t) { - if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == TYPE_DECL \ + if (VAR_P (t) || TREE_CODE (t) == TYPE_DECL \ || TREE_CODE (t) == CONST_DECL) return 1; if (is_overloaded_fn (t)) @@ -1051,8 +1054,7 @@ lookup_field_r (tree binfo, void *data) /* If we're looking up a type (as with an elaborated type specifier) we ignore all non-types we find. */ - if (lfi->want_type && TREE_CODE (nval) != TYPE_DECL - && !DECL_TYPE_TEMPLATE_P (nval)) + if (lfi->want_type && !DECL_DECLARES_TYPE_P (nval)) { if (lfi->name == TYPE_IDENTIFIER (type)) { @@ -1182,7 +1184,7 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type, || xbasetype == error_mark_node) return NULL_TREE; - gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); + gcc_assert (identifier_p (name)); if (TREE_CODE (xbasetype) == TREE_BINFO) { @@ -1501,8 +1503,7 @@ lookup_fnfields_slot_nolazy (tree type, tree name) int class_method_index_for_fn (tree class_type, tree function) { - gcc_assert (TREE_CODE (function) == FUNCTION_DECL - || DECL_FUNCTION_TEMPLATE_P (function)); + gcc_assert (DECL_DECLARES_FUNCTION_P (function)); return lookup_fnfields_1 (class_type, DECL_CONSTRUCTOR_P (function) ? ctor_identifier : @@ -1841,8 +1842,8 @@ check_final_overrider (tree overrider, tree basefn) { tree over_type = TREE_TYPE (overrider); tree base_type = TREE_TYPE (basefn); - tree over_return = TREE_TYPE (over_type); - tree base_return = TREE_TYPE (base_type); + tree over_return = fndecl_declared_return_type (overrider); + tree base_return = fndecl_declared_return_type (basefn); tree over_throw, base_throw; int fail = 0; @@ -1896,8 +1897,7 @@ check_final_overrider (tree overrider, tree basefn) { /* can_convert will permit user defined conversion from a (reference to) class type. We must reject them. */ - over_return = non_reference (TREE_TYPE (over_type)); - if (CLASS_TYPE_P (over_return)) + if (CLASS_TYPE_P (non_reference (over_return))) fail = 2; else { diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index e909b984681..0a460a42544 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -536,7 +536,7 @@ simplify_loop_decl_cond (tree *cond_p, tree body) tree finish_goto_stmt (tree destination) { - if (TREE_CODE (destination) == IDENTIFIER_NODE) + if (identifier_p (destination)) destination = lookup_label (destination); /* We warn about unused labels with -Wunused. That means we have to @@ -779,6 +779,22 @@ finish_return_stmt (tree expr) tree r; bool no_warning; + if (flag_enable_cilkplus && contains_array_notation_expr (expr)) + { + size_t rank = 0; + + if (!find_rank (input_location, expr, expr, false, &rank)) + return error_mark_node; + + /* If the return expression contains array notations, then flag it as + error. */ + if (rank >= 1) + { + error_at (input_location, "array notation expression cannot be " + "used as a return value"); + return error_mark_node; + } + } expr = check_return_expr (expr, &no_warning); if (flag_openmp && !check_omp_return ()) @@ -1199,8 +1215,6 @@ finish_handler_parms (tree decl, tree handler) else type = expand_start_catch_block (decl); HANDLER_TYPE (handler) = type; - if (!processing_template_decl && type) - mark_used (eh_type_info (type)); } /* Finish a handler, which may be given by HANDLER. The BLOCKs are @@ -1507,6 +1521,38 @@ finish_mem_initializers (tree mem_inits) emit_mem_initializers (mem_inits); } +/* Obfuscate EXPR if it looks like an id-expression or member access so + that the call to finish_decltype in do_auto_deduction will give the + right result. */ + +tree +force_paren_expr (tree expr) +{ + /* This is only needed for decltype(auto) in C++14. */ + if (cxx_dialect < cxx1y) + return expr; + + if (!DECL_P (expr) && TREE_CODE (expr) != COMPONENT_REF + && TREE_CODE (expr) != SCOPE_REF) + return expr; + + if (processing_template_decl) + expr = build1 (PAREN_EXPR, TREE_TYPE (expr), expr); + else + { + cp_lvalue_kind kind = lvalue_kind (expr); + if ((kind & ~clk_class) != clk_none) + { + tree type = unlowered_expr_type (expr); + bool rval = !!(kind & clk_rvalueref); + type = cp_build_reference_type (type, rval); + expr = build_static_cast (type, expr, tf_warning_or_error); + } + } + + return expr; +} + /* Finish a parenthesized expression EXPR. */ tree @@ -1525,6 +1571,8 @@ finish_parenthesized_expr (tree expr) if (TREE_CODE (expr) == STRING_CST) PAREN_STRING_LITERAL_P (expr) = 1; + expr = force_paren_expr (expr); + return expr; } @@ -1574,9 +1622,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) else { /* Set the cv qualifiers. */ - int quals = (current_class_ref - ? cp_type_quals (TREE_TYPE (current_class_ref)) - : TYPE_UNQUALIFIED); + int quals = cp_type_quals (TREE_TYPE (object)); if (DECL_MUTABLE_P (decl)) quals &= ~TYPE_QUAL_CONST; @@ -1740,15 +1786,17 @@ finish_qualified_id_expr (tree qualifying_class, bool done, bool address_p, bool template_p, - bool template_arg_p) + bool template_arg_p, + tsubst_flags_t complain) { gcc_assert (TYPE_P (qualifying_class)); if (error_operand_p (expr)) return error_mark_node; - if (DECL_P (expr) || BASELINK_P (expr)) - mark_used (expr); + if ((DECL_P (expr) || BASELINK_P (expr)) + && !mark_used (expr, complain)) + return error_mark_node; if (template_p) check_template_keyword (expr); @@ -1760,10 +1808,14 @@ finish_qualified_id_expr (tree qualifying_class, if (TREE_CODE (expr) == SCOPE_REF) expr = TREE_OPERAND (expr, 1); expr = build_offset_ref (qualifying_class, expr, - /*address_p=*/true); + /*address_p=*/true, complain); return expr; } + /* No need to check access within an enum. */ + if (TREE_CODE (qualifying_class) == ENUMERAL_TYPE) + return expr; + /* Within the scope of a class, turn references to non-static members into expression of the form "this->...". */ if (template_arg_p) @@ -1790,11 +1842,12 @@ finish_qualified_id_expr (tree qualifying_class, expr, BASELINK_ACCESS_BINFO (expr), /*preserve_reference=*/false, - tf_warning_or_error)); + complain)); else if (done) /* The expression is a qualified name whose address is not being taken. */ - expr = build_offset_ref (qualifying_class, expr, /*address_p=*/false); + expr = build_offset_ref (qualifying_class, expr, /*address_p=*/false, + complain); } else if (BASELINK_P (expr)) ; @@ -2001,7 +2054,7 @@ perform_koenig_lookup (tree fn, vec<tree, va_gc> *args, bool include_std, } /* Find the name of the overloaded function. */ - if (TREE_CODE (fn) == IDENTIFIER_NODE) + if (identifier_p (fn)) identifier = fn; else if (is_overloaded_fn (fn)) { @@ -2238,7 +2291,7 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual, if (processing_template_decl && result != error_mark_node) { - if (TREE_CODE (result) == INDIRECT_REF) + if (INDIRECT_REF_P (result)) result = TREE_OPERAND (result, 0); result = build_call_vec (TREE_TYPE (result), orig_fn, orig_args); SET_EXPR_LOCATION (result, input_location); @@ -2295,7 +2348,6 @@ finish_this_expr (void) result = lambda_expr_this_capture (CLASSTYPE_LAMBDA_EXPR (type)); else result = current_class_ptr; - } else if (current_function_decl && DECL_STATIC_FUNCTION_P (current_function_decl)) @@ -2312,6 +2364,9 @@ finish_this_expr (void) result = error_mark_node; } + /* The keyword 'this' is a prvalue expression. */ + result = rvalue (result); + return result; } @@ -2335,6 +2390,8 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor) error ("invalid qualifying scope in pseudo-destructor name"); return error_mark_node; } + if (is_auto (destructor)) + destructor = TREE_TYPE (object); if (scope && TYPE_P (scope) && !check_dtor_name (scope, destructor)) { error ("qualified type %qT does not match destructor name ~%qT", @@ -2370,10 +2427,12 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor) /* Finish an expression of the form CODE EXPR. */ tree -finish_unary_op_expr (location_t loc, enum tree_code code, tree expr) +finish_unary_op_expr (location_t loc, enum tree_code code, tree expr, + tsubst_flags_t complain) { - tree result = build_x_unary_op (loc, code, expr, tf_warning_or_error); - if (TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (expr)) + tree result = build_x_unary_op (loc, code, expr, complain); + if ((complain & tf_warning) + && TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (expr)) overflow_warning (input_location, result); return result; @@ -2703,8 +2762,7 @@ finish_member_declaration (tree decl) /* Put functions on the TYPE_METHODS list and everything else on the TYPE_FIELDS list. Note that these are built up in reverse order. We reverse them (to obtain declaration order) in finish_struct. */ - if (TREE_CODE (decl) == FUNCTION_DECL - || DECL_FUNCTION_TEMPLATE_P (decl)) + if (DECL_DECLARES_FUNCTION_P (decl)) { /* We also need to add this function to the CLASSTYPE_METHOD_VEC. */ @@ -2717,8 +2775,10 @@ finish_member_declaration (tree decl) /*friend_p=*/0); } } - /* Enter the DECL into the scope of the class. */ - else if (pushdecl_class_level (decl)) + /* Enter the DECL into the scope of the class, if the class + isn't a closure (whose fields are supposed to be unnamed). */ + else if (CLASSTYPE_LAMBDA_EXPR (current_class_type) + || pushdecl_class_level (decl)) { if (TREE_CODE (decl) == USING_DECL) { @@ -2773,8 +2833,7 @@ note_decl_for_pch (tree decl) /* There's a good chance that we'll have to mangle names at some point, even if only for emission in debugging information. */ - if ((TREE_CODE (decl) == VAR_DECL - || TREE_CODE (decl) == FUNCTION_DECL) + if (VAR_OR_FUNCTION_DECL_P (decl) && !processing_template_decl) mangle_decl (decl); } @@ -2882,9 +2941,10 @@ baselink_for_fns (tree fns) static bool outer_var_p (tree decl) { - return ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL) + return ((VAR_P (decl) || TREE_CODE (decl) == PARM_DECL) && DECL_FUNCTION_SCOPE_P (decl) - && DECL_CONTEXT (decl) != current_function_decl); + && (DECL_CONTEXT (decl) != current_function_decl + || parsing_nsdmi ())); } /* As above, but also checks that DECL is automatic. */ @@ -2967,7 +3027,7 @@ finish_id_expression (tree id_expression, if (scope && (!TYPE_P (scope) || (!dependent_type_p (scope) - && !(TREE_CODE (id_expression) == IDENTIFIER_NODE + && !(identifier_p (id_expression) && IDENTIFIER_TYPENAME_P (id_expression) && dependent_type_p (TREE_TYPE (id_expression)))))) { @@ -2996,8 +3056,7 @@ finish_id_expression (tree id_expression, the current class so that we can check later to see if the meaning would have been different after the class was entirely defined. */ - if (!scope && decl != error_mark_node - && TREE_CODE (id_expression) == IDENTIFIER_NODE) + if (!scope && decl != error_mark_node && identifier_p (id_expression)) maybe_note_name_used_in_class (id_expression, decl); /* Disallow uses of local variables from containing functions, except @@ -3041,12 +3100,14 @@ finish_id_expression (tree id_expression, return integral_constant_value (decl); } + if (parsing_nsdmi ()) + containing_function = NULL_TREE; /* If we are in a lambda function, we can move out until we hit 1. the context, 2. a non-lambda function, or 3. a non-default capturing lambda function. */ - while (context != containing_function - && LAMBDA_FUNCTION_P (containing_function)) + else while (context != containing_function + && LAMBDA_FUNCTION_P (containing_function)) { lambda_expr = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (containing_function)); @@ -3063,6 +3124,12 @@ finish_id_expression (tree id_expression, = decl_function_context (containing_function); } + if (lambda_expr && TREE_CODE (decl) == VAR_DECL + && DECL_ANON_UNION_VAR_P (decl)) + { + error ("cannot capture member %qD of anonymous union", decl); + return error_mark_node; + } if (context == containing_function) { decl = add_default_capture (lambda_stack, @@ -3076,7 +3143,7 @@ finish_id_expression (tree id_expression, } else { - error (TREE_CODE (decl) == VAR_DECL + error (VAR_P (decl) ? G_("use of local variable with automatic storage from containing function") : G_("use of parameter from containing function")); error (" %q+#D declared here", decl); @@ -3168,8 +3235,7 @@ finish_id_expression (tree id_expression, /* A template-id where the name of the template was not resolved is definitely dependent. */ else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR - && (TREE_CODE (TREE_OPERAND (decl, 0)) - == IDENTIFIER_NODE)) + && (identifier_p (TREE_OPERAND (decl, 0)))) dependent_p = true; /* For anything except an overloaded function, just check its type. */ @@ -3229,7 +3295,8 @@ finish_id_expression (tree id_expression, decl = finish_qualified_id_expr (scope, decl, done, address_p, template_p, - template_arg_p); + template_arg_p, + tf_warning_or_error); else { tree type = NULL_TREE; @@ -3253,7 +3320,7 @@ finish_id_expression (tree id_expression, /* If we found a variable, then name lookup during the instantiation will always resolve to the same VAR_DECL (or an instantiation thereof). */ - if (TREE_CODE (decl) == VAR_DECL + if (VAR_P (decl) || TREE_CODE (decl) == PARM_DECL) { mark_used (decl); @@ -3297,7 +3364,7 @@ finish_id_expression (tree id_expression, /* Mark variable-like entities as used. Functions are similarly marked either below or after overload resolution. */ - if ((TREE_CODE (decl) == VAR_DECL + if ((VAR_P (decl) || TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == CONST_DECL || TREE_CODE (decl) == RESULT_DECL) @@ -3322,7 +3389,7 @@ finish_id_expression (tree id_expression, } tree wrap; - if (TREE_CODE (decl) == VAR_DECL + if (VAR_P (decl) && !cp_unevaluated_operand && DECL_THREAD_LOCAL_P (decl) && (wrap = get_tls_wrapper_fn (decl))) @@ -3345,7 +3412,8 @@ finish_id_expression (tree id_expression, done, address_p, template_p, - template_arg_p); + template_arg_p, + tf_warning_or_error); else decl = convert_from_reference (decl); } @@ -3638,10 +3706,17 @@ finish_offsetof (tree expr) || TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE || TREE_TYPE (expr) == unknown_type_node) { - if (TREE_CODE (expr) == COMPONENT_REF - || TREE_CODE (expr) == COMPOUND_EXPR) - expr = TREE_OPERAND (expr, 1); - error ("cannot apply %<offsetof%> to member function %qD", expr); + if (TREE_CODE (expr) == INDIRECT_REF) + error ("second operand of %<offsetof%> is neither a single " + "identifier nor a sequence of member accesses and " + "array references"); + else + { + if (TREE_CODE (expr) == COMPONENT_REF + || TREE_CODE (expr) == COMPOUND_EXPR) + expr = TREE_OPERAND (expr, 1); + error ("cannot apply %<offsetof%> to member function %qD", expr); + } return error_mark_node; } if (REFERENCE_REF_P (expr)) @@ -4055,7 +4130,7 @@ finish_omp_clauses (tree clauses) goto check_dup_generic; check_dup_generic: t = OMP_CLAUSE_DECL (c); - if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL) + if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) { if (processing_template_decl) break; @@ -4078,7 +4153,7 @@ finish_omp_clauses (tree clauses) case OMP_CLAUSE_FIRSTPRIVATE: t = OMP_CLAUSE_DECL (c); - if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL) + if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) { if (processing_template_decl) break; @@ -4100,7 +4175,7 @@ finish_omp_clauses (tree clauses) case OMP_CLAUSE_LASTPRIVATE: t = OMP_CLAUSE_DECL (c); - if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL) + if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) { if (processing_template_decl) break; @@ -4252,7 +4327,7 @@ finish_omp_clauses (tree clauses) t = OMP_CLAUSE_DECL (c); if (processing_template_decl - && TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL) + && !VAR_P (t) && TREE_CODE (t) != PARM_DECL) { pc = &OMP_CLAUSE_CHAIN (c); continue; @@ -4292,7 +4367,7 @@ finish_omp_clauses (tree clauses) break; case OMP_CLAUSE_COPYIN: - if (TREE_CODE (t) != VAR_DECL || !DECL_THREAD_LOCAL_P (t)) + if (!VAR_P (t) || !DECL_THREAD_LOCAL_P (t)) { error ("%qE must be %<threadprivate%> for %<copyin%>", t); remove = true; @@ -4319,7 +4394,7 @@ finish_omp_clauses (tree clauses) { const char *share_name = NULL; - if (TREE_CODE (t) == VAR_DECL && DECL_THREAD_LOCAL_P (t)) + if (VAR_P (t) && DECL_THREAD_LOCAL_P (t)) share_name = "threadprivate"; else switch (cxx_omp_predetermined_sharing (t)) { @@ -4386,7 +4461,7 @@ finish_omp_threadprivate (tree vars) if (error_operand_p (v)) ; - else if (TREE_CODE (v) != VAR_DECL) + else if (!VAR_P (v)) error ("%<threadprivate%> %qD is not file, namespace " "or block scope variable", v); /* If V had already been marked threadprivate, it doesn't matter @@ -4875,7 +4950,7 @@ finish_omp_for (location_t locus, tree declv, tree initv, tree condv, } if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)) - && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE) + && !TYPE_PTR_P (TREE_TYPE (decl))) { error_at (elocus, "invalid type for iteration variable %qE", decl); return NULL; @@ -5277,6 +5352,9 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, expr = resolve_nondeduced_context (expr); + if (invalid_nonstatic_memfn_p (expr, complain)) + return error_mark_node; + if (type_unknown_p (expr)) { if (complain & tf_error) @@ -5284,12 +5362,9 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, return error_mark_node; } - if (invalid_nonstatic_memfn_p (expr, complain)) - return error_mark_node; - /* To get the size of a static data member declared as an array of unknown bound, we need to instantiate it. */ - if (TREE_CODE (expr) == VAR_DECL + if (VAR_P (expr) && VAR_HAD_UNKNOWN_BOUND (expr) && DECL_TEMPLATE_INSTANTIATION (expr)) instantiate_decl (expr, /*defer_ok*/true, /*expl_inst_mem*/false); @@ -5300,10 +5375,10 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, [expr.ref]), decltype(e) is defined as the type of the entity named by e. If there is no such entity, or e names a set of overloaded functions, the program is ill-formed. */ - if (TREE_CODE (expr) == IDENTIFIER_NODE) + if (identifier_p (expr)) expr = lookup_name (expr); - if (TREE_CODE (expr) == INDIRECT_REF) + if (INDIRECT_REF_P (expr)) /* This can happen when the expression is, e.g., "a.b". Just look at the underlying operand. */ expr = TREE_OPERAND (expr, 0); @@ -5345,6 +5420,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, break; case COMPONENT_REF: + case COMPOUND_EXPR: mark_type_use (expr); type = is_bitfield_expr_with_lowered_type (expr); if (!type) @@ -5362,8 +5438,9 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, break; default: - gcc_unreachable (); - return error_mark_node; + /* Handle instantiated template non-type arguments. */ + type = TREE_TYPE (expr); + break; } } else @@ -5403,6 +5480,15 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, } } + if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type)) + { + if (complain & tf_warning_or_error) + pedwarn (input_location, OPT_Wvla, + "taking decltype of array of runtime bound"); + else + return error_mark_node; + } + return type; } @@ -5721,7 +5807,7 @@ tree ensure_literal_type_for_constexpr_object (tree decl) { tree type = TREE_TYPE (decl); - if (TREE_CODE (decl) == VAR_DECL && DECL_DECLARED_CONSTEXPR_P (decl) + if (VAR_P (decl) && DECL_DECLARED_CONSTEXPR_P (decl) && !processing_template_decl) { if (CLASS_TYPE_P (type) && !COMPLETE_TYPE_P (complete_type (type))) @@ -5950,7 +6036,7 @@ build_data_member_initialization (tree t, vec<constructor_elt, va_gc> **vec) return true; else gcc_unreachable (); - if (TREE_CODE (member) == INDIRECT_REF) + if (INDIRECT_REF_P (member)) member = TREE_OPERAND (member, 0); if (TREE_CODE (member) == NOP_EXPR) { @@ -6819,7 +6905,7 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t, { tree ob_arg = get_nth_callarg (t, 0); STRIP_NOPS (ob_arg); - gcc_assert (TREE_CODE (TREE_TYPE (ob_arg)) == POINTER_TYPE + gcc_assert (TYPE_PTR_P (TREE_TYPE (ob_arg)) && CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (ob_arg)))); result = adjust_temp_type (TREE_TYPE (TREE_TYPE (ob_arg)), result); @@ -6837,6 +6923,9 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t, bool reduced_constant_expression_p (tree t) { + if (TREE_CODE (t) == PTRMEM_CST) + /* Even if we can't lower this yet, it's constant. */ + return true; /* FIXME are we calling this too much? */ return initializer_constant_valid_p (t, TREE_TYPE (t)) != NULL_TREE; } @@ -7007,6 +7096,13 @@ cxx_eval_array_reference (const constexpr_call *call, tree t, *non_constant_p = true; return t; } + else if (tree_int_cst_lt (index, integer_zero_node)) + { + if (!allow_non_constant) + error ("negative array subscript"); + *non_constant_p = true; + return t; + } i = tree_low_cst (index, 0); if (TREE_CODE (ary) == CONSTRUCTOR) return (*CONSTRUCTOR_ELTS (ary))[i].value; @@ -7571,15 +7667,17 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) } } } - /* *(foo *)fooarrptreturn> (*fooarrptr)[0] */ + /* *(foo *)fooarrptr => (*fooarrptr)[0] */ else if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE && (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (TREE_TYPE (subtype))))) { tree type_domain; tree min_val = size_zero_node; - sub = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL); - if (!sub) + tree newsub = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL); + if (newsub) + sub = newsub; + else sub = build1_loc (loc, INDIRECT_REF, TREE_TYPE (subtype), sub); type_domain = TYPE_DOMAIN (TREE_TYPE (sub)); if (type_domain && TYPE_MIN_VALUE (type_domain)) @@ -7649,6 +7747,8 @@ cxx_eval_indirect_ref (const constexpr_call *call, tree t, if (r == NULL_TREE) { + if (addr && op0 != orig_op0) + return build1 (INDIRECT_REF, TREE_TYPE (t), op0); if (!addr) VERIFY_CONSTANT (t); return t; @@ -7690,7 +7790,7 @@ non_const_var_error (tree r) } else { - if (cxx_dialect >= cxx0x && !DECL_DECLARED_CONSTEXPR_P (r)) + if (cxx_dialect >= cxx11 && !DECL_DECLARED_CONSTEXPR_P (r)) inform (DECL_SOURCE_LOCATION (r), "%qD was not declared %<constexpr%>", r); else @@ -7700,37 +7800,32 @@ non_const_var_error (tree r) } } -/* Evaluate VEC_PERM_EXPR (v1, v2, mask). */ +/* Subroutine of cxx_eval_constant_expression. + Like cxx_eval_unary_expression, except for trinary expressions. */ + static tree -cxx_eval_vec_perm_expr (const constexpr_call *call, tree t, - bool allow_non_constant, bool addr, - bool *non_constant_p, bool *overflow_p) +cxx_eval_trinary_expression (const constexpr_call *call, tree t, + bool allow_non_constant, bool addr, + bool *non_constant_p, bool *overflow_p) { int i; tree args[3]; tree val; - tree elttype = TREE_TYPE (t); for (i = 0; i < 3; i++) { args[i] = cxx_eval_constant_expression (call, TREE_OPERAND (t, i), allow_non_constant, addr, non_constant_p, overflow_p); - if (*non_constant_p) - goto fail; + VERIFY_CONSTANT (args[i]); } - gcc_assert (TREE_CODE (TREE_TYPE (args[0])) == VECTOR_TYPE); - gcc_assert (TREE_CODE (TREE_TYPE (args[1])) == VECTOR_TYPE); - gcc_assert (TREE_CODE (TREE_TYPE (args[2])) == VECTOR_TYPE); - - val = fold_ternary_loc (EXPR_LOCATION (t), VEC_PERM_EXPR, elttype, + val = fold_ternary_loc (EXPR_LOCATION (t), TREE_CODE (t), TREE_TYPE (t), args[0], args[1], args[2]); - if (val != NULL_TREE) - return val; - - fail: - return t; + if (val == NULL_TREE) + return t; + VERIFY_CONSTANT (val); + return val; } /* Attempt to reduce the expression T to a constant value. @@ -7969,6 +8064,7 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t, case UNGT_EXPR: case UNGE_EXPR: case UNEQ_EXPR: + case LTGT_EXPR: case RANGE_EXPR: case COMPLEX_EXPR: r = cxx_eval_binary_expression (call, t, allow_non_constant, addr, @@ -7993,6 +8089,7 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t, non_constant_p, overflow_p); break; + case ARRAY_NOTATION_REF: case ARRAY_REF: r = cxx_eval_array_reference (call, t, allow_non_constant, addr, non_constant_p, overflow_p); @@ -8029,9 +8126,10 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t, non_constant_p, overflow_p); break; + case FMA_EXPR: case VEC_PERM_EXPR: - r = cxx_eval_vec_perm_expr (call, t, allow_non_constant, addr, - non_constant_p, overflow_p); + r = cxx_eval_trinary_expression (call, t, allow_non_constant, addr, + non_constant_p, overflow_p); break; case CONVERT_EXPR: @@ -8044,6 +8142,16 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t, non_constant_p, overflow_p); if (*non_constant_p) return t; + if (POINTER_TYPE_P (TREE_TYPE (t)) + && TREE_CODE (op) == INTEGER_CST + && !integer_zerop (op)) + { + if (!allow_non_constant) + error_at (EXPR_LOC_OR_HERE (t), + "reinterpret_cast from integer to pointer"); + *non_constant_p = true; + return t; + } if (op == oldop) /* We didn't fold at the top so we could check for ptr-int conversion. */ @@ -8209,11 +8317,10 @@ maybe_constant_value (tree t) { tree r; - if (type_dependent_expression_p (t) + if (instantiation_dependent_expression_p (t) || type_unknown_p (t) || BRACE_ENCLOSED_INITIALIZER_P (t) - || !potential_constant_expression (t) - || value_dependent_expression_p (t)) + || !potential_constant_expression (t)) { if (TREE_OVERFLOW_P (t)) { @@ -8374,7 +8481,8 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) tree x = get_nth_callarg (t, 0); if (is_this_parameter (x)) { - if (DECL_CONSTRUCTOR_P (DECL_CONTEXT (x))) + if (DECL_CONTEXT (x) == NULL_TREE + || DECL_CONSTRUCTOR_P (DECL_CONTEXT (x))) { if (flags & tf_error) sorry ("calling a member function of the " @@ -8390,7 +8498,11 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) } } else - fun = get_first_fn (fun); + { + if (!potential_constant_expression_1 (fun, true, flags)) + return false; + fun = get_first_fn (fun); + } /* Skip initial arguments to base constructors. */ if (DECL_BASE_CONSTRUCTOR_P (fun)) i = num_artificial_parms_for (fun); @@ -8440,6 +8552,15 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) may change to something more specific to type-punning (DR 1312). */ { tree from = TREE_OPERAND (t, 0); + if (POINTER_TYPE_P (TREE_TYPE (t)) + && TREE_CODE (from) == INTEGER_CST + && !integer_zerop (from)) + { + if (flags & tf_error) + error_at (EXPR_LOC_OR_HERE (t), + "reinterpret_cast from integer to pointer"); + return false; + } return (potential_constant_expression_1 (from, TREE_CODE (t) != VIEW_CONVERT_EXPR, flags)); } @@ -8487,6 +8608,13 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) STRIP_NOPS (x); if (is_this_parameter (x)) { + if (DECL_CONTEXT (x) + && !DECL_DECLARED_CONSTEXPR_P (DECL_CONTEXT (x))) + { + if (flags & tf_error) + error ("use of %<this%> in a constant expression"); + return false; + } if (want_rval && DECL_CONTEXT (x) && DECL_CONSTRUCTOR_P (DECL_CONTEXT (x))) { @@ -8514,6 +8642,10 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) case THROW_EXPR: case MODIFY_EXPR: case MODOP_EXPR: + case OMP_ATOMIC: + case OMP_ATOMIC_READ: + case OMP_ATOMIC_CAPTURE_OLD: + case OMP_ATOMIC_CAPTURE_NEW: /* GCC internal stuff. */ case VA_ARG_EXPR: case OBJ_TYPE_REF: @@ -8609,7 +8741,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) case STATIC_CAST_EXPR: case REINTERPRET_CAST_EXPR: case IMPLICIT_CONV_EXPR: - if (cxx_dialect < cxx0x + if (cxx_dialect < cxx11 && !dependent_type_p (TREE_TYPE (t)) && !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t))) /* In C++98, a conversion to non-integral type can't be part of a @@ -8769,6 +8901,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) want_rval = true; /* Fall through. */ case ARRAY_REF: + case ARRAY_NOTATION_REF: case ARRAY_RANGE_REF: case MEMBER_REF: case DOTSTAR_EXPR: @@ -8918,6 +9051,7 @@ build_lambda_object (tree lambda_expr) if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE) val = build_array_copy (val); else if (DECL_NORMAL_CAPTURE_P (field) + && !DECL_VLA_CAPTURE_P (field) && TREE_CODE (TREE_TYPE (field)) != REFERENCE_TYPE) { /* "the entities that are captured by copy are used to @@ -8967,7 +9101,7 @@ begin_lambda_type (tree lambda) /* Create the new RECORD_TYPE for this lambda. */ type = xref_tag (/*tag_code=*/record_type, name, - /*scope=*/ts_within_enclosing_non_class, + /*scope=*/ts_lambda, /*template_header_p=*/false); } @@ -9036,18 +9170,24 @@ lambda_function (tree lambda) The caller should add REFERENCE_TYPE for capture by reference. */ tree -lambda_capture_field_type (tree expr) +lambda_capture_field_type (tree expr, bool explicit_init_p) { tree type; - if (type_dependent_expression_p (expr)) + if (explicit_init_p) + { + type = make_auto (); + type = do_auto_deduction (type, expr, type); + } + else + type = non_reference (unlowered_expr_type (expr)); + if (!type || WILDCARD_TYPE_P (type)) { type = cxx_make_type (DECLTYPE_TYPE); DECLTYPE_TYPE_EXPR (type) = expr; DECLTYPE_FOR_LAMBDA_CAPTURE (type) = true; + DECLTYPE_FOR_INIT_CAPTURE (type) = explicit_init_p; SET_TYPE_STRUCTURAL_EQUALITY (type); } - else - type = non_reference (unlowered_expr_type (expr)); return type; } @@ -9156,7 +9296,7 @@ capture_decltype (tree decl) bool is_capture_proxy (tree decl) { - return (TREE_CODE (decl) == VAR_DECL + return (VAR_P (decl) && DECL_HAS_VALUE_EXPR_P (decl) && !DECL_ANON_UNION_VAR_P (decl) && LAMBDA_FUNCTION_P (DECL_CONTEXT (decl))); @@ -9189,13 +9329,12 @@ void insert_capture_proxy (tree var) { cp_binding_level *b; - int skip; tree stmt_list; /* Put the capture proxy in the extra body block so that it won't clash with a later local variable. */ b = current_binding_level; - for (skip = 0; ; ++skip) + for (;;) { cp_binding_level *n = b->level_chain; if (n->kind == sk_function_parms) @@ -9206,7 +9345,7 @@ insert_capture_proxy (tree var) /* And put a DECL_EXPR in the STATEMENT_LIST for the same block. */ var = build_stmt (DECL_SOURCE_LOCATION (var), DECL_EXPR, var); - stmt_list = (*stmt_list_stack)[stmt_list_stack->length () - 1 - skip]; + stmt_list = (*stmt_list_stack)[1]; gcc_assert (stmt_list); append_to_statement_list_force (var, &stmt_list); } @@ -9248,7 +9387,7 @@ lambda_proxy_type (tree ref) if (REFERENCE_REF_P (ref)) ref = TREE_OPERAND (ref, 0); type = TREE_TYPE (ref); - if (!dependent_type_p (type)) + if (type && !WILDCARD_TYPE_P (non_reference (type))) return type; type = cxx_make_type (DECLTYPE_TYPE); DECLTYPE_TYPE_EXPR (type) = ref; @@ -9277,9 +9416,27 @@ build_capture_proxy (tree member) object = TREE_OPERAND (object, 0); /* Remove the __ inserted by add_capture. */ - name = get_identifier (IDENTIFIER_POINTER (DECL_NAME (member)) + 2); + if (DECL_NORMAL_CAPTURE_P (member)) + name = get_identifier (IDENTIFIER_POINTER (DECL_NAME (member)) + 2); + else + name = DECL_NAME (member); type = lambda_proxy_type (object); + + if (DECL_VLA_CAPTURE_P (member)) + { + /* Rebuild the VLA type from the pointer and maxindex. */ + tree field = next_initializable_field (TYPE_FIELDS (type)); + tree ptr = build_simple_component_ref (object, field); + field = next_initializable_field (DECL_CHAIN (field)); + tree max = build_simple_component_ref (object, field); + type = build_array_type (TREE_TYPE (TREE_TYPE (ptr)), + build_index_type (max)); + type = build_reference_type (type); + REFERENCE_VLA_OK (type) = true; + object = convert (type, ptr); + } + var = build_decl (input_location, VAR_DECL, name, type); SET_DECL_VALUE_EXPR (var, object); DECL_HAS_VALUE_EXPR_P (var) = 1; @@ -9301,6 +9458,29 @@ build_capture_proxy (tree member) return var; } +/* Return a struct containing a pointer and a length for lambda capture of + an array of runtime length. */ + +static tree +vla_capture_type (tree array_type) +{ + static tree ptr_id, max_id; + tree type = xref_tag (record_type, make_anon_name (), ts_current, false); + xref_basetypes (type, NULL_TREE); + type = begin_class_definition (type); + if (!ptr_id) + { + ptr_id = get_identifier ("ptr"); + max_id = get_identifier ("max"); + } + tree ptrtype = build_pointer_type (TREE_TYPE (array_type)); + tree field = build_decl (input_location, FIELD_DECL, ptr_id, ptrtype); + finish_member_declaration (field); + field = build_decl (input_location, FIELD_DECL, max_id, sizetype); + finish_member_declaration (field); + return finish_struct (type, NULL_TREE); +} + /* From an ID and INITIALIZER, create a capture (by reference if BY_REFERENCE_P is true), add it to the capture-list for LAMBDA, and return it. */ @@ -9311,9 +9491,38 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p, { char *buf; tree type, member, name; + bool vla = false; - type = lambda_capture_field_type (initializer); - if (by_reference_p) + if (TREE_CODE (initializer) == TREE_LIST) + initializer = build_x_compound_expr_from_list (initializer, ELK_INIT, + tf_warning_or_error); + type = lambda_capture_field_type (initializer, explicit_init_p); + if (array_of_runtime_bound_p (type)) + { + vla = true; + if (!by_reference_p) + error ("array of runtime bound cannot be captured by copy, " + "only by reference"); + + /* For a VLA, we capture the address of the first element and the + maximum index, and then reconstruct the VLA for the proxy. */ + tree elt = cp_build_array_ref (input_location, initializer, + integer_zero_node, tf_warning_or_error); + initializer = build_constructor_va (init_list_type_node, 2, + NULL_TREE, build_address (elt), + NULL_TREE, array_type_nelts (type)); + type = vla_capture_type (type); + } + else if (variably_modified_type_p (type, NULL_TREE)) + { + error ("capture of variable-size type %qT that is not a C++1y array " + "of runtime bound", type); + if (TREE_CODE (type) == ARRAY_TYPE + && variably_modified_type_p (TREE_TYPE (type), NULL_TREE)) + inform (input_location, "because the array element type %qT has " + "variable size", TREE_TYPE (type)); + } + else if (by_reference_p) { type = build_reference_type (type); if (!real_lvalue_p (initializer)) @@ -9327,11 +9536,17 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p, won't find the field with name lookup. We can't just leave the name unset because template instantiation uses the name to find instantiated fields. */ - buf = (char *) alloca (IDENTIFIER_LENGTH (id) + 3); - buf[1] = buf[0] = '_'; - memcpy (buf + 2, IDENTIFIER_POINTER (id), - IDENTIFIER_LENGTH (id) + 1); - name = get_identifier (buf); + if (!explicit_init_p) + { + buf = (char *) alloca (IDENTIFIER_LENGTH (id) + 3); + buf[1] = buf[0] = '_'; + memcpy (buf + 2, IDENTIFIER_POINTER (id), + IDENTIFIER_LENGTH (id) + 1); + name = get_identifier (buf); + } + else + /* But captures with explicit initializers are named. */ + name = id; /* If TREE_TYPE isn't set, we're still in the introducer, so check for duplicates. */ @@ -9348,6 +9563,7 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p, /* Make member variable. */ member = build_lang_decl (FIELD_DECL, name, type); + DECL_VLA_CAPTURE_P (member) = vla; if (!explicit_init_p) /* Normal captures are invisible to name lookup but uses are replaced @@ -9438,6 +9654,11 @@ lambda_expr_this_capture (tree lambda) tree this_capture = LAMBDA_EXPR_THIS_CAPTURE (lambda); + /* In unevaluated context this isn't an odr-use, so just return the + nearest 'this'. */ + if (cp_unevaluated_operand) + return lookup_name (this_identifier); + /* Try to default capture 'this' if we can. */ if (!this_capture && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE) @@ -9507,11 +9728,6 @@ lambda_expr_this_capture (tree lambda) if (!this_capture) { - /* In unevaluated context this isn't an odr-use, so just return the - nearest 'this'. */ - if (cp_unevaluated_operand) - return lookup_name (this_identifier); - error ("%<this%> was not captured for this lambda function"); result = error_mark_node; } @@ -9545,11 +9761,12 @@ maybe_resolve_dummy (tree object) return object; tree type = TYPE_MAIN_VARIANT (TREE_TYPE (object)); - gcc_assert (TREE_CODE (type) != POINTER_TYPE); + gcc_assert (!TYPE_PTR_P (type)); if (type != current_class_type && current_class_type - && LAMBDA_TYPE_P (current_class_type)) + && LAMBDA_TYPE_P (current_class_type) + && DERIVED_FROM_P (type, current_nonlambda_class_type ())) { /* In a lambda, need to go through 'this' capture. */ tree lam = CLASSTYPE_LAMBDA_EXPR (current_class_type); @@ -9605,6 +9822,13 @@ maybe_add_lambda_conv_op (tree type) if (processing_template_decl) return; + if (DECL_INITIAL (callop) == NULL_TREE) + { + /* If the op() wasn't instantiated due to errors, give up. */ + gcc_assert (errorcount || sorrycount); + return; + } + stattype = build_function_type (TREE_TYPE (TREE_TYPE (callop)), FUNCTION_ARG_CHAIN (callop)); @@ -9661,7 +9885,11 @@ maybe_add_lambda_conv_op (tree type) DECL_STATIC_FUNCTION_P (fn) = 1; DECL_ARGUMENTS (fn) = copy_list (DECL_CHAIN (DECL_ARGUMENTS (callop))); for (arg = DECL_ARGUMENTS (fn); arg; arg = DECL_CHAIN (arg)) - DECL_CONTEXT (arg) = fn; + { + /* Avoid duplicate -Wshadow warnings. */ + DECL_NAME (arg) = NULL_TREE; + DECL_CONTEXT (arg) = fn; + } if (nested) DECL_INTERFACE_KNOWN (fn) = 1; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 178b80aa24f..f8b4bbce822 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -70,7 +70,7 @@ lvalue_kind (const_tree ref) /* unnamed rvalue references are rvalues */ if (TYPE_REF_IS_RVALUE (TREE_TYPE (ref)) && TREE_CODE (ref) != PARM_DECL - && TREE_CODE (ref) != VAR_DECL + && !VAR_P (ref) && TREE_CODE (ref) != COMPONENT_REF /* Functions are always lvalues. */ && TREE_CODE (TREE_TYPE (TREE_TYPE (ref))) != FUNCTION_TYPE) @@ -141,6 +141,7 @@ lvalue_kind (const_tree ref) case INDIRECT_REF: case ARROW_EXPR: case ARRAY_REF: + case ARRAY_NOTATION_REF: case PARM_DECL: case RESULT_DECL: return clk_ordinary; @@ -210,7 +211,7 @@ lvalue_kind (const_tree ref) /* We just return clk_ordinary for NON_DEPENDENT_EXPR in C++98, but in C++11 lvalues don't bind to rvalue references, so we need to work harder to avoid bogus errors (c++/44870). */ - if (cxx_dialect < cxx0x) + if (cxx_dialect < cxx11) return clk_ordinary; else return lvalue_kind (TREE_OPERAND (ref, 0)); @@ -309,7 +310,7 @@ build_target_expr (tree decl, tree value, tsubst_flags_t complain) gcc_assert (VOID_TYPE_P (TREE_TYPE (value)) || TREE_TYPE (decl) == TREE_TYPE (value) /* On ARM ctors return 'this'. */ - || (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE + || (TYPE_PTR_P (TREE_TYPE (value)) && TREE_CODE (value) == CALL_EXPR) || useless_type_conversion_p (TREE_TYPE (decl), TREE_TYPE (value))); @@ -469,6 +470,9 @@ build_cplus_new (tree type, tree init, tsubst_flags_t complain) tree rval = build_aggr_init_expr (type, init); tree slot; + if (!complete_type_or_maybe_complain (type, init, complain)) + return error_mark_node; + /* Make sure that we're not trying to create an instance of an abstract class. */ if (abstract_virtuals_error_sfinae (NULL_TREE, type, complain)) @@ -562,7 +566,7 @@ build_vec_init_expr (tree type, tree init, tsubst_flags_t complain) TREE_SIDE_EFFECTS (init) = true; SET_EXPR_LOCATION (init, input_location); - if (cxx_dialect >= cxx0x + if (cxx_dialect >= cxx11 && potential_constant_expression (elt_init)) VEC_INIT_EXPR_IS_CONSTEXPR (init) = true; VEC_INIT_EXPR_VALUE_INIT (init) = value_init; @@ -826,10 +830,12 @@ build_cplus_array_type (tree elt_type, tree index_type) if (TYPE_MAIN_VARIANT (t) != m) { - if (COMPLETE_TYPE_P (t) && !COMPLETE_TYPE_P (m)) + if (COMPLETE_TYPE_P (TREE_TYPE (t)) && !COMPLETE_TYPE_P (m)) { /* m was built before the element type was complete, so we - also need to copy the layout info from t. */ + also need to copy the layout info from t. We might + end up doing this multiple times if t is an array of + unknown bound. */ tree size = TYPE_SIZE (t); tree size_unit = TYPE_SIZE_UNIT (t); unsigned int align = TYPE_ALIGN (t); @@ -868,6 +874,21 @@ build_array_of_n_type (tree elt, int n) return build_cplus_array_type (elt, build_index_type (size_int (n - 1))); } +/* True iff T is a C++1y array of runtime bound (VLA). */ + +bool +array_of_runtime_bound_p (tree t) +{ + if (!t || TREE_CODE (t) != ARRAY_TYPE) + return false; + tree dom = TYPE_DOMAIN (t); + if (!dom) + return false; + tree max = TYPE_MAX_VALUE (dom); + return (!potential_rvalue_constant_expression (max) + || (!value_dependent_expression_p (max) && !TREE_CONSTANT (max))); +} + /* Return a reference type node referring to TO_TYPE. If RVAL is true, return an rvalue reference type, otherwise return an lvalue reference type. If a type node exists, reuse it, otherwise create @@ -1078,12 +1099,21 @@ cp_build_qualified_type_real (tree type, /* Retrieve (or create) the appropriately qualified variant. */ result = build_qualified_type (type, type_quals); + /* Preserve exception specs and ref-qualifier since build_qualified_type + doesn't know about them. */ + if (TREE_CODE (result) == FUNCTION_TYPE + || TREE_CODE (result) == METHOD_TYPE) + { + result = build_exception_variant (result, TYPE_RAISES_EXCEPTIONS (type)); + result = build_ref_qualified_type (result, type_memfn_rqual (type)); + } + /* If this was a pointer-to-method type, and we just made a copy, then we need to unshare the record that holds the cached pointer-to-member-function type, because these will be distinct between the unqualified and qualified types. */ if (result != type - && TREE_CODE (type) == POINTER_TYPE + && TYPE_PTR_P (type) && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE && TYPE_LANG_SPECIFIC (result) == TYPE_LANG_SPECIFIC (type)) TYPE_LANG_SPECIFIC (result) = NULL; @@ -1092,7 +1122,7 @@ cp_build_qualified_type_real (tree type, type of a pointer-to-method type, which could have the same sharing problem described above. */ if (TYPE_CANONICAL (result) != TYPE_CANONICAL (type) - && TREE_CODE (type) == POINTER_TYPE + && TYPE_PTR_P (type) && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE && (TYPE_LANG_SPECIFIC (TYPE_CANONICAL (result)) == TYPE_LANG_SPECIFIC (TYPE_CANONICAL (type)))) @@ -1211,7 +1241,9 @@ strip_typedefs (tree t) { result = build_function_type (type, arg_types); - result = apply_memfn_quals (result, type_memfn_quals (t)); + result = apply_memfn_quals (result, + type_memfn_quals (t), + type_memfn_rqual (t)); } if (TYPE_RAISES_EXCEPTIONS (t)) @@ -1241,8 +1273,13 @@ strip_typedefs (tree t) changed = true; } if (changed) - fullname = lookup_template_function (TREE_OPERAND (fullname, 0), - new_args); + { + NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_args) + = NON_DEFAULT_TEMPLATE_ARGS_COUNT (args); + fullname + = lookup_template_function (TREE_OPERAND (fullname, 0), + new_args); + } else ggc_free (new_args); } @@ -1375,8 +1412,8 @@ strip_typedefs_expr (tree t) r = copy_node (t); for (i = 0; i < n; ++i) TREE_VEC_ELT (r, i) = (*vec)[i]; - SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT - (r, GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (t)); + NON_DEFAULT_TEMPLATE_ARGS_COUNT (r) + = NON_DEFAULT_TEMPLATE_ARGS_COUNT (t); } else r = t; @@ -1418,7 +1455,8 @@ strip_typedefs_expr (tree t) } case LAMBDA_EXPR: - gcc_unreachable (); + error ("lambda-expression in a constant expression"); + return error_mark_node; default: break; @@ -1698,6 +1736,66 @@ build_qualified_name (tree type, tree scope, tree name, bool template_p) return t; } +/* Like check_qualified_type, but also check ref-qualifier and exception + specification. */ + +static bool +cp_check_qualified_type (const_tree cand, const_tree base, int type_quals, + cp_ref_qualifier rqual, tree raises) +{ + return (check_qualified_type (cand, base, type_quals) + && comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (cand), + ce_exact) + && type_memfn_rqual (cand) == rqual); +} + +/* Build the FUNCTION_TYPE or METHOD_TYPE with the ref-qualifier RQUAL. */ + +tree +build_ref_qualified_type (tree type, cp_ref_qualifier rqual) +{ + tree t; + + if (rqual == type_memfn_rqual (type)) + return type; + + int type_quals = TYPE_QUALS (type); + tree raises = TYPE_RAISES_EXCEPTIONS (type); + for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) + if (cp_check_qualified_type (t, type, type_quals, rqual, raises)) + return t; + + t = build_variant_type_copy (type); + switch (rqual) + { + case REF_QUAL_RVALUE: + FUNCTION_RVALUE_QUALIFIED (t) = 1; + FUNCTION_REF_QUALIFIED (t) = 1; + break; + case REF_QUAL_LVALUE: + FUNCTION_RVALUE_QUALIFIED (t) = 0; + FUNCTION_REF_QUALIFIED (t) = 1; + break; + default: + FUNCTION_REF_QUALIFIED (t) = 0; + break; + } + + if (TYPE_STRUCTURAL_EQUALITY_P (type)) + /* Propagate structural equality. */ + SET_TYPE_STRUCTURAL_EQUALITY (t); + else if (TYPE_CANONICAL (type) != type) + /* Build the underlying canonical type, since it is different + from TYPE. */ + TYPE_CANONICAL (t) = build_ref_qualified_type (TYPE_CANONICAL (type), + rqual); + else + /* T is its own canonical type. */ + TYPE_CANONICAL (t) = t; + + return t; +} + /* Returns nonzero if X is an expression for a (possibly overloaded) function. If "f" is a function or function template, "f", "c->f", "c.f", "C::f", and "f<int>" will all be considered possibly @@ -1730,7 +1828,7 @@ is_overloaded_fn (tree x) tree dependent_name (tree x) { - if (TREE_CODE (x) == IDENTIFIER_NODE) + if (identifier_p (x)) return x; if (TREE_CODE (x) != COMPONENT_REF && TREE_CODE (x) != OFFSET_REF @@ -1903,9 +2001,9 @@ build_exception_variant (tree type, tree raises) return type; type_quals = TYPE_QUALS (type); + cp_ref_qualifier rqual = type_memfn_rqual (type); for (v = TYPE_MAIN_VARIANT (type); v; v = TYPE_NEXT_VARIANT (v)) - if (check_qualified_type (v, type, type_quals) - && comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (v), ce_exact)) + if (cp_check_qualified_type (v, type, type_quals, rqual, raises)) return v; /* Need to build a new variant. */ @@ -2024,11 +2122,12 @@ no_linkage_check (tree t, bool relaxed_p) if (TYPE_PTRMEMFUNC_P (t)) goto ptrmem; /* Lambda types that don't have mangling scope have no linkage. We - check CLASSTYPE_LAMBDA_EXPR here rather than LAMBDA_TYPE_P because + check CLASSTYPE_LAMBDA_EXPR for error_mark_node because when we get here from pushtag none of the lambda information is set up yet, so we want to assume that the lambda has linkage and fix it up later if not. */ if (CLASSTYPE_LAMBDA_EXPR (t) + && CLASSTYPE_LAMBDA_EXPR (t) != error_mark_node && LAMBDA_TYPE_EXTRA_SCOPE (t) == NULL_TREE) return t; /* Fall through. */ @@ -2214,7 +2313,7 @@ bot_replace (tree* t, int* /*walk_subtrees*/, void* data) { splay_tree target_remap = ((splay_tree) data); - if (TREE_CODE (*t) == VAR_DECL) + if (VAR_P (*t)) { splay_tree_node n = splay_tree_lookup (target_remap, (splay_tree_key) *t); @@ -2486,7 +2585,7 @@ cp_tree_equal (tree t1, tree t2) t1 = TREE_OPERAND (t1, 0); for (code2 = TREE_CODE (t2); CONVERT_EXPR_CODE_P (code2) - || code1 == NON_LVALUE_EXPR; + || code2 == NON_LVALUE_EXPR; code2 = TREE_CODE (t2)) t2 = TREE_OPERAND (t2, 0); @@ -2579,10 +2678,10 @@ cp_tree_equal (tree t1, tree t2) it means that it's going to be unified with whatever the TARGET_EXPR is really supposed to initialize, so treat it as being equivalent to anything. */ - if (TREE_CODE (o1) == VAR_DECL && DECL_NAME (o1) == NULL_TREE + if (VAR_P (o1) && DECL_NAME (o1) == NULL_TREE && !DECL_RTL_SET_P (o1)) /*Nop*/; - else if (TREE_CODE (o2) == VAR_DECL && DECL_NAME (o2) == NULL_TREE + else if (VAR_P (o2) && DECL_NAME (o2) == NULL_TREE && !DECL_RTL_SET_P (o2)) /*Nop*/; else if (!cp_tree_equal (o1, o2)) @@ -2874,7 +2973,7 @@ maybe_dummy_object (tree type, tree* binfop) int is_dummy_object (const_tree ob) { - if (TREE_CODE (ob) == INDIRECT_REF) + if (INDIRECT_REF_P (ob)) ob = TREE_OPERAND (ob, 0); return (TREE_CODE (ob) == NOP_EXPR && TREE_OPERAND (ob, 0) == void_zero_node); @@ -3144,7 +3243,7 @@ handle_init_priority_attribute (tree* node, type = strip_array_types (type); if (decl == NULL_TREE - || TREE_CODE (decl) != VAR_DECL + || !VAR_P (decl) || !TREE_STATIC (decl) || DECL_EXTERNAL (decl) || (TREE_CODE (type) != RECORD_TYPE @@ -3232,7 +3331,7 @@ handle_abi_tag_attribute (tree* node, tree name, tree args, { if (TYPE_P (*node)) { - if (!TAGGED_TYPE_P (*node)) + if (!OVERLOAD_TYPE_P (*node)) { error ("%qE attribute applied to non-class, non-enum type %qT", name, *node); @@ -3303,8 +3402,12 @@ cp_build_type_attribute_variant (tree type, tree attributes) new_type = build_type_attribute_variant (type, attributes); if (TREE_CODE (new_type) == FUNCTION_TYPE || TREE_CODE (new_type) == METHOD_TYPE) - new_type = build_exception_variant (new_type, - TYPE_RAISES_EXCEPTIONS (type)); + { + new_type = build_exception_variant (new_type, + TYPE_RAISES_EXCEPTIONS (type)); + new_type = build_ref_qualified_type (new_type, + type_memfn_rqual (type)); + } /* Making a new main variant of a class type is broken. */ gcc_assert (!CLASS_TYPE_P (type) || new_type == type); @@ -3574,8 +3677,7 @@ decl_linkage (tree decl) template instantiations have internal linkage (in the object file), but the symbols should still be treated as having external linkage from the point of view of the language. */ - if ((TREE_CODE (decl) == FUNCTION_DECL - || TREE_CODE (decl) == VAR_DECL) + if (VAR_OR_FUNCTION_DECL_P (decl) && DECL_COMDAT (decl)) return lk_external; @@ -3589,7 +3691,7 @@ decl_linkage (tree decl) really meant to have internal linkage have DECL_THIS_STATIC set. */ if (TREE_CODE (decl) == TYPE_DECL) return lk_external; - if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL) + if (VAR_OR_FUNCTION_DECL_P (decl)) { if (!DECL_THIS_STATIC (decl)) return lk_external; @@ -3614,7 +3716,7 @@ decl_storage_duration (tree decl) return dk_auto; if (TREE_CODE (decl) == FUNCTION_DECL) return dk_static; - gcc_assert (TREE_CODE (decl) == VAR_DECL); + gcc_assert (VAR_P (decl)); if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl)) return dk_auto; @@ -3854,7 +3956,7 @@ bool cast_valid_in_integral_constant_expression_p (tree type) { return (INTEGRAL_OR_ENUMERATION_TYPE_P (type) - || cxx_dialect >= cxx0x + || cxx_dialect >= cxx11 || dependent_type_p (type) || type == error_mark_node); } @@ -3879,7 +3981,7 @@ cp_fix_function_decl_p (tree decl) /* Don't fix same_body aliases. Although they don't have their own CFG, they share it with what they alias to. */ - if (!node || !node->alias + if (!node || !node->symbol.alias || !vec_safe_length (node->symbol.ref_list.references)) return true; } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 58ebcc0ab2d..5b321ce5a7f 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -54,7 +54,7 @@ static tree get_delta_difference (tree, tree, bool, bool, tsubst_flags_t); static void casts_away_constness_r (tree *, tree *, tsubst_flags_t); static bool casts_away_constness (tree, tree, tsubst_flags_t); static void maybe_warn_about_returning_address_of_local (tree); -static tree lookup_destructor (tree, tree, tree); +static tree lookup_destructor (tree, tree, tree, tsubst_flags_t); static void warn_args_num (location_t, tree, bool); static int convert_arguments (tree, vec<tree, va_gc> **, tree, int, tsubst_flags_t); @@ -483,7 +483,7 @@ composite_pointer_type_r (tree t1, tree t2, tree attributes; /* Determine the types pointed to by T1 and T2. */ - if (TREE_CODE (t1) == POINTER_TYPE) + if (TYPE_PTR_P (t1)) { pointee1 = TREE_TYPE (t1); pointee2 = TREE_TYPE (t2); @@ -503,8 +503,7 @@ composite_pointer_type_r (tree t1, tree t2, types. */ if (same_type_ignoring_top_level_qualifiers_p (pointee1, pointee2)) result_type = pointee1; - else if ((TREE_CODE (pointee1) == POINTER_TYPE - && TREE_CODE (pointee2) == POINTER_TYPE) + else if ((TYPE_PTR_P (pointee1) && TYPE_PTR_P (pointee2)) || (TYPE_PTRMEM_P (pointee1) && TYPE_PTRMEM_P (pointee2))) { result_type = composite_pointer_type_r (pointee1, pointee2, operation, @@ -581,7 +580,7 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2, and cv2. If either type is a pointer to void, make sure it is T1. */ - if (TREE_CODE (t2) == POINTER_TYPE && VOID_TYPE_P (TREE_TYPE (t2))) + if (TYPE_PTR_P (t2) && VOID_TYPE_P (TREE_TYPE (t2))) { tree t; t = t1; @@ -590,7 +589,7 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2, } /* Now, if T1 is a pointer to void, merge the qualifiers. */ - if (TREE_CODE (t1) == POINTER_TYPE && VOID_TYPE_P (TREE_TYPE (t1))) + if (TYPE_PTR_P (t1) && VOID_TYPE_P (TREE_TYPE (t1))) { tree attributes; tree result_type; @@ -628,8 +627,8 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2, return build_type_attribute_variant (result_type, attributes); } - if (c_dialect_objc () && TREE_CODE (t1) == POINTER_TYPE - && TREE_CODE (t2) == POINTER_TYPE) + if (c_dialect_objc () && TYPE_PTR_P (t1) + && TYPE_PTR_P (t2)) { if (objc_have_common_type (t1, t2, -3, NULL_TREE)) return objc_common_type (t1, t2); @@ -637,7 +636,7 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2, /* [expr.eq] permits the application of a pointer conversion to bring the pointers to a common type. */ - if (TREE_CODE (t1) == POINTER_TYPE && TREE_CODE (t2) == POINTER_TYPE + if (TYPE_PTR_P (t1) && TYPE_PTR_P (t2) && CLASS_TYPE_P (TREE_TYPE (t1)) && CLASS_TYPE_P (TREE_TYPE (t2)) && !same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (t1), @@ -833,7 +832,10 @@ merge_types (tree t1, tree t2) rval = build_function_type (valtype, parms); gcc_assert (type_memfn_quals (t1) == type_memfn_quals (t2)); - rval = apply_memfn_quals (rval, type_memfn_quals (t1)); + gcc_assert (type_memfn_rqual (t1) == type_memfn_rqual (t2)); + rval = apply_memfn_quals (rval, + type_memfn_quals (t1), + type_memfn_rqual (t1)); raises = merge_exception_specifiers (TYPE_RAISES_EXCEPTIONS (t1), TYPE_RAISES_EXCEPTIONS (t2), NULL_TREE); @@ -849,6 +851,7 @@ merge_types (tree t1, tree t2) tree raises = merge_exception_specifiers (TYPE_RAISES_EXCEPTIONS (t1), TYPE_RAISES_EXCEPTIONS (t2), NULL_TREE); + cp_ref_qualifier rqual = type_memfn_rqual (t1); tree t3; /* If this was a member function type, get back to the @@ -862,6 +865,7 @@ merge_types (tree t1, tree t2) t3 = build_method_type_directly (basetype, TREE_TYPE (t3), TYPE_ARG_TYPES (t3)); t1 = build_exception_variant (t3, raises); + t1 = build_ref_qualified_type (t1, rqual); break; } @@ -959,8 +963,7 @@ comp_except_types (tree a, tree b, bool exact) if (cp_type_quals (a) || cp_type_quals (b)) return false; - if (TREE_CODE (a) == POINTER_TYPE - && TREE_CODE (b) == POINTER_TYPE) + if (TYPE_PTR_P (a) && TYPE_PTR_P (b)) { a = TREE_TYPE (a); b = TREE_TYPE (b); @@ -1186,6 +1189,12 @@ structural_comptypes (tree t1, tree t2, int strict) if (TREE_CODE (t1) == FUNCTION_TYPE && type_memfn_quals (t1) != type_memfn_quals (t2)) return false; + /* Need to check this before TYPE_MAIN_VARIANT. + FIXME function qualifiers should really change the main variant. */ + if ((TREE_CODE (t1) == FUNCTION_TYPE + || TREE_CODE (t1) == METHOD_TYPE) + && type_memfn_rqual (t1) != type_memfn_rqual (t2)) + return false; if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2)) return false; @@ -1515,7 +1524,7 @@ cxx_sizeof_or_alignof_type (tree type, enum tree_code op, bool complain) if (TREE_CODE (type) == METHOD_TYPE) { if (complain) - pedwarn (input_location, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith, + pedwarn (input_location, OPT_Wpointer_arith, "invalid application of %qs to a member function", operator_name_info[(int) op].name); value = size_one_node; @@ -1540,6 +1549,15 @@ cxx_sizeof_or_alignof_type (tree type, enum tree_code op, bool complain) return value; } + if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type)) + { + if (complain & tf_warning_or_error) + pedwarn (input_location, OPT_Wvla, + "taking sizeof array of runtime bound"); + else + return error_mark_node; + } + return c_sizeof_or_alignof_type (input_location, complete_type (type), op == SIZEOF_EXPR, complain); @@ -1553,7 +1571,7 @@ tree cxx_sizeof_nowarn (tree type) { if (TREE_CODE (type) == FUNCTION_TYPE - || TREE_CODE (type) == VOID_TYPE + || VOID_TYPE_P (type) || TREE_CODE (type) == ERROR_MARK) return size_one_node; else if (!COMPLETE_TYPE_P (type)) @@ -1581,7 +1599,7 @@ cxx_sizeof_expr (tree e, tsubst_flags_t complain) /* To get the size of a static data member declared as an array of unknown bound, we need to instantiate it. */ - if (TREE_CODE (e) == VAR_DECL + if (VAR_P (e) && VAR_HAD_UNKNOWN_BOUND (e) && DECL_TEMPLATE_INSTANTIATION (e)) instantiate_decl (e, /*defer_ok*/true, /*expl_inst_mem*/false); @@ -1645,7 +1663,7 @@ cxx_alignof_expr (tree e, tsubst_flags_t complain) e = mark_type_use (e); - if (TREE_CODE (e) == VAR_DECL) + if (VAR_P (e)) t = size_int (DECL_ALIGN_UNIT (e)); else if (TREE_CODE (e) == COMPONENT_REF && TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL @@ -1718,15 +1736,19 @@ cxx_alignas_expr (tree e) When the alignment-specifier is of the form alignas(type-id ), it shall have the same effect as - alignas( alignof(type-id )). */ + alignas(alignof(type-id )). */ return cxx_sizeof_or_alignof_type (e, ALIGNOF_EXPR, false); - /* If we reach this point, it means the alignas expression if of the form "alignas(assignment-expression)", so we should follow what is stated by [dcl.align]/2. */ + if (value_dependent_expression_p (e)) + /* Leave value-dependent expression alone for now. */ + return e; + + e = fold_non_dependent_expr (e); e = mark_rvalue_use (e); /* [dcl.align]/2 says: @@ -1734,18 +1756,7 @@ cxx_alignas_expr (tree e) the assignment-expression shall be an integral constant expression. */ - e = fold_non_dependent_expr (e); - if (value_dependent_expression_p (e)) - /* Leave value-dependent expression alone for now. */; - else - e = cxx_constant_value (e); - - if (e == NULL_TREE - || e == error_mark_node - || TREE_CODE (e) != INTEGER_CST) - return error_mark_node; - - return e; + return cxx_constant_value (e); } @@ -1766,9 +1777,16 @@ cxx_alignas_expr (tree e) violates these rules. */ bool -invalid_nonstatic_memfn_p (const_tree expr, tsubst_flags_t complain) +invalid_nonstatic_memfn_p (tree expr, tsubst_flags_t complain) { - if (expr && DECL_NONSTATIC_MEMBER_FUNCTION_P (expr)) + 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) error ("invalid use of non-static member function"); @@ -1911,7 +1929,7 @@ decay_conversion (tree exp, tsubst_flags_t complain) tree adr; tree ptrtype; - if (TREE_CODE (exp) == INDIRECT_REF) + if (INDIRECT_REF_P (exp)) return build_nop (build_pointer_type (TREE_TYPE (type)), TREE_OPERAND (exp, 0)); @@ -1943,7 +1961,7 @@ decay_conversion (tree exp, tsubst_flags_t complain) ptrtype = build_pointer_type (TREE_TYPE (type)); - if (TREE_CODE (exp) == VAR_DECL) + if (VAR_P (exp)) { if (!cxx_mark_addressable (exp)) return error_mark_node; @@ -2062,7 +2080,7 @@ string_conv_p (const_tree totype, const_tree exp, int warn) { tree t; - if (TREE_CODE (totype) != POINTER_TYPE) + if (!TYPE_PTR_P (totype)) return 0; t = TREE_TYPE (totype); @@ -2123,7 +2141,8 @@ rationalize_conditional_expr (enum tree_code code, tree t, gcc_assert (!TREE_SIDE_EFFECTS (op0) && !TREE_SIDE_EFFECTS (op1)); return - build_conditional_expr (build_x_binary_op (input_location, + build_conditional_expr (EXPR_LOC_OR_HERE (t), + build_x_binary_op (EXPR_LOC_OR_HERE (t), (TREE_CODE (t) == MIN_EXPR ? LE_EXPR : GE_EXPR), op0, TREE_CODE (op0), @@ -2136,7 +2155,7 @@ rationalize_conditional_expr (enum tree_code code, tree t, } return - build_conditional_expr (TREE_OPERAND (t, 0), + build_conditional_expr (EXPR_LOC_OR_HERE (t), TREE_OPERAND (t, 0), cp_build_unary_op (code, TREE_OPERAND (t, 1), 0, complain), cp_build_unary_op (code, TREE_OPERAND (t, 2), 0, @@ -2273,7 +2292,7 @@ build_class_member_access_expr (tree object, tree member, /* In [expr.ref], there is an explicit list of the valid choices for MEMBER. We check for each of those cases here. */ - if (TREE_CODE (member) == VAR_DECL) + if (VAR_P (member)) { /* A static data member. */ result = member; @@ -2289,7 +2308,7 @@ build_class_member_access_expr (tree object, tree member, int type_quals; tree member_type; - null_object_p = (TREE_CODE (object) == INDIRECT_REF + null_object_p = (INDIRECT_REF_P (object) && integer_zerop (TREE_OPERAND (object, 0))); /* Convert OBJECT to the type of MEMBER. */ @@ -2455,7 +2474,8 @@ build_class_member_access_expr (tree object, tree member, SCOPE is NULL, by OBJECT.DTOR_NAME, where DTOR_NAME is ~type. */ static tree -lookup_destructor (tree object, tree scope, tree dtor_name) +lookup_destructor (tree object, tree scope, tree dtor_name, + tsubst_flags_t complain) { tree object_type = TREE_TYPE (object); tree dtor_type = TREE_OPERAND (dtor_name, 0); @@ -2463,11 +2483,14 @@ lookup_destructor (tree object, tree scope, tree dtor_name) if (scope && !check_dtor_name (scope, dtor_type)) { - error ("qualified type %qT does not match destructor name ~%qT", - scope, dtor_type); + if (complain & tf_error) + error ("qualified type %qT does not match destructor name ~%qT", + scope, dtor_type); return error_mark_node; } - if (TREE_CODE (dtor_type) == IDENTIFIER_NODE) + if (is_auto (dtor_type)) + dtor_type = object_type; + else if (identifier_p (dtor_type)) { /* In a template, names we can't find a match for are still accepted destructor names, and we check them here. */ @@ -2475,16 +2498,18 @@ lookup_destructor (tree object, tree scope, tree dtor_name) dtor_type = object_type; else { - error ("object type %qT does not match destructor name ~%qT", - object_type, dtor_type); + if (complain & tf_error) + error ("object type %qT does not match destructor name ~%qT", + object_type, dtor_type); return error_mark_node; } } else if (!DERIVED_FROM_P (dtor_type, TYPE_MAIN_VARIANT (object_type))) { - error ("the type being destroyed is %qT, but the destructor refers to %qT", - TYPE_MAIN_VARIANT (object_type), dtor_type); + if (complain & tf_error) + error ("the type being destroyed is %qT, but the destructor " + "refers to %qT", TYPE_MAIN_VARIANT (object_type), dtor_type); return error_mark_node; } expr = lookup_member (dtor_type, complete_dtor_identifier, @@ -2588,7 +2613,7 @@ finish_class_member_access_expr (tree object, tree name, bool template_p, dependent_type_p (object_type) /* If NAME is just an IDENTIFIER_NODE, then the expression is dependent. */ - || TREE_CODE (object) == IDENTIFIER_NODE + || identifier_p (object) /* If NAME is "f<args>", where either 'f' or 'args' is dependent, then the expression is dependent. */ || (TREE_CODE (name) == TEMPLATE_ID_EXPR @@ -2604,7 +2629,7 @@ finish_class_member_access_expr (tree object, tree name, bool template_p, object = build_non_dependent_expr (object); } else if (c_dialect_objc () - && TREE_CODE (name) == IDENTIFIER_NODE + && identifier_p (name) && (expr = objc_maybe_build_component_ref (object, name))) return expr; @@ -2670,9 +2695,25 @@ finish_class_member_access_expr (tree object, tree name, bool template_p, return error_mark_node; } + if (TREE_CODE (scope) == ENUMERAL_TYPE) + { + /* Looking up a member enumerator (c++/56793). */ + if (!TYPE_CLASS_SCOPE_P (scope) + || !DERIVED_FROM_P (TYPE_CONTEXT (scope), object_type)) + { + if (complain & tf_error) + error ("%<%D::%D%> is not a member of %qT", + scope, name, object_type); + return error_mark_node; + } + tree val = lookup_enumerator (scope, name); + if (TREE_SIDE_EFFECTS (object)) + val = build2 (COMPOUND_EXPR, TREE_TYPE (val), object, val); + return val; + } + gcc_assert (CLASS_TYPE_P (scope)); - gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE - || TREE_CODE (name) == BIT_NOT_EXPR); + gcc_assert (identifier_p (name) || TREE_CODE (name) == BIT_NOT_EXPR); if (constructor_name_p (name, scope)) { @@ -2701,7 +2742,7 @@ finish_class_member_access_expr (tree object, tree name, bool template_p, } if (TREE_CODE (name) == BIT_NOT_EXPR) - member = lookup_destructor (object, scope, name); + member = lookup_destructor (object, scope, name, complain); else { /* Look up the member. */ @@ -2759,6 +2800,19 @@ finish_class_member_access_expr (tree object, tree name, bool template_p, return expr; } +/* Build a COMPONENT_REF of OBJECT and MEMBER with the appropriate + type. */ + +tree +build_simple_component_ref (tree object, tree member) +{ + tree type = cp_build_qualified_type (TREE_TYPE (member), + cp_type_quals (TREE_TYPE (object))); + return fold_build3_loc (input_location, + COMPONENT_REF, type, + object, member, NULL_TREE); +} + /* Return an expression for the MEMBER_NAME field in the internal representation of PTRMEM, a pointer-to-member function. (Each pointer-to-member function type gets its own RECORD_TYPE so it is @@ -2771,7 +2825,6 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name) { tree ptrmem_type; tree member; - tree member_type; /* This code is a stripped down version of build_class_member_access_expr. It does not work to use that @@ -2781,11 +2834,7 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name) gcc_assert (TYPE_PTRMEMFUNC_P (ptrmem_type)); member = lookup_member (ptrmem_type, member_name, /*protect=*/0, /*want_type=*/false, tf_warning_or_error); - member_type = cp_build_qualified_type (TREE_TYPE (member), - cp_type_quals (ptrmem_type)); - return fold_build3_loc (input_location, - COMPONENT_REF, member_type, - ptrmem, member, NULL_TREE); + return build_simple_component_ref (ptrmem, member); } /* Given an expression PTR for a pointer, return an expression @@ -2837,7 +2886,11 @@ cp_build_indirect_ref (tree ptr, ref_operator errorstring, { tree pointer, type; - if (ptr == current_class_ptr) + if (ptr == current_class_ptr + || (TREE_CODE (ptr) == NOP_EXPR + && TREE_OPERAND (ptr, 0) == current_class_ptr + && (same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (ptr), TREE_TYPE (current_class_ptr))))) return current_class_ref; pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE @@ -2952,6 +3005,22 @@ cp_build_array_ref (location_t loc, tree array, tree idx, return error_mark_node; } + /* If an array's index is an array notation, then its rank cannot be + greater than one. */ + if (flag_enable_cilkplus && contains_array_notation_expr (idx)) + { + size_t rank = 0; + + /* If find_rank returns false, then it should have reported an error, + thus it is unnecessary for repetition. */ + if (!find_rank (loc, idx, idx, true, &rank)) + return error_mark_node; + if (rank > 1) + { + error_at (loc, "rank of the array%'s index is greater than 1"); + return error_mark_node; + } + } if (TREE_TYPE (array) == error_mark_node || TREE_TYPE (idx) == error_mark_node) return error_mark_node; @@ -2972,7 +3041,7 @@ cp_build_array_ref (location_t loc, tree array, tree idx, case COND_EXPR: ret = build_conditional_expr - (TREE_OPERAND (array, 0), + (loc, TREE_OPERAND (array, 0), cp_build_array_ref (loc, TREE_OPERAND (array, 1), idx, complain), cp_build_array_ref (loc, TREE_OPERAND (array, 2), idx, @@ -3044,7 +3113,7 @@ cp_build_array_ref (location_t loc, tree array, tree idx, tree foo = array; while (TREE_CODE (foo) == COMPONENT_REF) foo = TREE_OPERAND (foo, 0); - if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo) + if (VAR_P (foo) && DECL_REGISTER (foo) && (complain & tf_warning)) warning_at (loc, OPT_Wextra, "subscripting array declared %<register%>"); @@ -3081,7 +3150,7 @@ cp_build_array_ref (location_t loc, tree array, tree idx, if (ar == error_mark_node || ind == error_mark_node) return error_mark_node; - if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE) + if (!TYPE_PTR_P (TREE_TYPE (ar))) { if (complain & tf_error) error_at (loc, "subscripted value is neither array nor pointer"); @@ -3254,7 +3323,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function, cp_build_addr_expr (e2, complain)); e2 = fold_convert (TREE_TYPE (e3), e2); - e1 = build_conditional_expr (e1, e2, e3, complain); + e1 = build_conditional_expr (input_location, e1, e2, e3, complain); if (e1 == error_mark_node) return error_mark_node; @@ -3391,11 +3460,10 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params, return error_mark_node; } - is_method = (TREE_CODE (fntype) == POINTER_TYPE + is_method = (TYPE_PTR_P (fntype) && TREE_CODE (TREE_TYPE (fntype)) == METHOD_TYPE); - if (!((TREE_CODE (fntype) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE) + if (!(TYPE_PTRFN_P (fntype) || is_method || TREE_CODE (function) == TEMPLATE_ID_EXPR)) { @@ -3425,8 +3493,12 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params, params = &allocated; } - nargs = convert_arguments (parm_types, params, fndecl, LOOKUP_NORMAL, - complain); + if (flag_enable_cilkplus + && is_cilkplus_reduce_builtin (fndecl) != BUILT_IN_NONE) + nargs = (*params)->length (); + else + nargs = convert_arguments (parm_types, params, fndecl, LOOKUP_NORMAL, + complain); if (nargs < 0) return error_mark_node; @@ -3884,8 +3956,15 @@ cp_build_binary_op (location_t location, } } - type0 = TREE_TYPE (op0); - type1 = TREE_TYPE (op1); + if (flag_enable_cilkplus && contains_array_notation_expr (op0)) + type0 = find_correct_array_notation_type (op0); + else + type0 = TREE_TYPE (op0); + + if (flag_enable_cilkplus && contains_array_notation_expr (op1)) + type1 = find_correct_array_notation_type (op1); + else + type1 = TREE_TYPE (op1); /* The expression codes of the data types of the arguments tell us whether the arguments are integers, floating, pointers, etc. */ @@ -3900,7 +3979,8 @@ cp_build_binary_op (location_t location, if ((invalid_op_diag = targetm.invalid_binary_op (code, type0, type1))) { - error (invalid_op_diag); + if (complain & tf_error) + error (invalid_op_diag); return error_mark_node; } @@ -3939,6 +4019,7 @@ cp_build_binary_op (location_t location, return error_mark_node; case stv_firstarg: { + op0 = save_expr (op0); op0 = convert (TREE_TYPE (type1), op0); op0 = build_vector_from_val (type1, op0); type0 = TREE_TYPE (op0); @@ -3948,6 +4029,7 @@ cp_build_binary_op (location_t location, } case stv_secondarg: { + op1 = save_expr (op1); op1 = convert (TREE_TYPE (type0), op1); op1 = build_vector_from_val (type0, op1); type1 = TREE_TYPE (op1); @@ -4014,8 +4096,9 @@ cp_build_binary_op (location_t location, || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)) { enum tree_code tcode0 = code0, tcode1 = code1; + tree cop1 = fold_non_dependent_expr_sfinae (op1, tf_none); - warn_for_div_by_zero (location, op1); + warn_for_div_by_zero (location, maybe_constant_value (cop1)); if (tcode0 == COMPLEX_TYPE || tcode0 == VECTOR_TYPE) tcode0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0))); @@ -4051,7 +4134,11 @@ cp_build_binary_op (location_t location, case TRUNC_MOD_EXPR: case FLOOR_MOD_EXPR: - warn_for_div_by_zero (location, op1); + { + tree cop1 = fold_non_dependent_expr_sfinae (op1, tf_none); + + warn_for_div_by_zero (location, maybe_constant_value (cop1)); + } if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE @@ -4099,7 +4186,8 @@ cp_build_binary_op (location_t location, } else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { - tree const_op1 = maybe_constant_value (op1); + tree const_op1 = fold_non_dependent_expr_sfinae (op1, tf_none); + const_op1 = maybe_constant_value (const_op1); if (TREE_CODE (const_op1) != INTEGER_CST) const_op1 = op1; result_type = type0; @@ -4145,7 +4233,8 @@ cp_build_binary_op (location_t location, } else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { - tree const_op1 = maybe_constant_value (op1); + tree const_op1 = fold_non_dependent_expr_sfinae (op1, tf_none); + const_op1 = maybe_constant_value (const_op1); if (TREE_CODE (const_op1) != INTEGER_CST) const_op1 = op1; result_type = type0; @@ -4560,7 +4649,8 @@ cp_build_binary_op (location_t location, || !same_scalar_type_ignoring_signedness (TREE_TYPE (type0), TREE_TYPE (type1))) { - binary_op_error (location, code, type0, type1); + if (complain & tf_error) + binary_op_error (location, code, type0, type1); return error_mark_node; } arithmetic_types_p = 1; @@ -4572,11 +4662,12 @@ cp_build_binary_op (location_t location, && (shorten || common || short_compare)) { result_type = cp_common_type (type0, type1); - do_warn_double_promotion (result_type, type0, type1, - "implicit conversion from %qT to %qT " - "to match other operand of binary " - "expression", - location); + if (complain & tf_warning) + do_warn_double_promotion (result_type, type0, type1, + "implicit conversion from %qT to %qT " + "to match other operand of binary " + "expression", + location); } if (!result_type) @@ -4813,7 +4904,7 @@ pointer_diff (tree op0, tree op1, tree ptrtype, tsubst_flags_t complain) if (!complete_type_or_else (target_type, NULL_TREE)) return error_mark_node; - if (TREE_CODE (target_type) == VOID_TYPE) + if (VOID_TYPE_P (target_type)) { if (complain & tf_error) permerror (input_location, "ISO C++ forbids using pointer of " @@ -4914,10 +5005,11 @@ build_x_unary_op (location_t loc, enum tree_code code, tree xarg, tree fn = get_first_fn (xarg); if (DECL_CONSTRUCTOR_P (fn) || DECL_DESTRUCTOR_P (fn)) { - error (DECL_CONSTRUCTOR_P (fn) - ? G_("taking address of constructor %qE") - : G_("taking address of destructor %qE"), - xarg); + if (complain & tf_error) + error (DECL_CONSTRUCTOR_P (fn) + ? G_("taking address of constructor %qE") + : G_("taking address of destructor %qE"), + xarg); return error_mark_node; } } @@ -4930,17 +5022,23 @@ build_x_unary_op (location_t loc, enum tree_code code, tree xarg, if (TREE_CODE (xarg) != OFFSET_REF || !TYPE_P (TREE_OPERAND (xarg, 0))) { - error ("invalid use of %qE to form a pointer-to-member-function", - xarg); - if (TREE_CODE (xarg) != OFFSET_REF) - inform (input_location, " a qualified-id is required"); + if (complain & tf_error) + { + error ("invalid use of %qE to form a " + "pointer-to-member-function", xarg); + if (TREE_CODE (xarg) != OFFSET_REF) + inform (input_location, " a qualified-id is required"); + } return error_mark_node; } else { - error ("parentheses around %qE cannot be used to form a" - " pointer-to-member-function", - xarg); + if (complain & tf_error) + error ("parentheses around %qE cannot be used to form a" + " pointer-to-member-function", + xarg); + else + return error_mark_node; PTRMEM_OK_P (xarg) = 1; } } @@ -5067,9 +5165,15 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) arg = mark_lvalue_use (arg); argtype = lvalue_type (arg); - gcc_assert (TREE_CODE (arg) != IDENTIFIER_NODE - || !IDENTIFIER_OPNAME_P (arg)); + gcc_assert (!identifier_p (arg) || !IDENTIFIER_OPNAME_P (arg)); + if (flag_enable_cilkplus && TREE_CODE (arg) == ARRAY_NOTATION_REF) + { + val = build_address (arg); + if (TREE_CODE (arg) == OFFSET_REF) + PTRMEM_OK_P (val) = PTRMEM_OK_P (arg); + return val; + } if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg) && !really_overloaded_fn (TREE_OPERAND (arg, 1))) { @@ -5109,7 +5213,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) " Say %<&%T::%D%>", base, name); } - arg = build_offset_ref (base, fn, /*address_p=*/true); + arg = build_offset_ref (base, fn, /*address_p=*/true, complain); } /* Uninstantiated types are all functions. Taking the @@ -5166,7 +5270,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) } /* Let &* cancel out to simplify resulting code. */ - if (TREE_CODE (arg) == INDIRECT_REF) + if (INDIRECT_REF_P (arg)) { /* We don't need to have `current_class_ptr' wrapped in a NON_LVALUE_EXPR node. */ @@ -5191,7 +5295,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) && argtype != unknown_type_node && (val = get_base_address (arg)) && COMPLETE_TYPE_P (TREE_TYPE (val)) - && TREE_CODE (val) == INDIRECT_REF + && INDIRECT_REF_P (val) && TREE_CONSTANT (TREE_OPERAND (val, 0))) { tree type = build_pointer_type (argtype); @@ -5258,7 +5362,17 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) } if (argtype != error_mark_node) - argtype = build_pointer_type (argtype); + { + if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (argtype)) + { + if (complain & tf_warning_or_error) + pedwarn (input_location, OPT_Wvla, + "taking address of array of runtime bound"); + else + return error_mark_node; + } + argtype = build_pointer_type (argtype); + } /* In a template, we are processing a non-dependent expression so we can just form an ADDR_EXPR with the correct type. */ @@ -5299,7 +5413,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) val = build_address (arg); } - if (TREE_CODE (argtype) == POINTER_TYPE + if (TYPE_PTR_P (argtype) && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE) { build_ptrmemfunc_type (argtype); @@ -5356,7 +5470,8 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert, : code), TREE_TYPE (xarg)))) { - error (invalid_op_diag); + if (complain & tf_error) + error (invalid_op_diag); return error_mark_node; } @@ -5527,7 +5642,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert, /* Compute the increment. */ - if (TREE_CODE (argtype) == POINTER_TYPE) + if (TYPE_PTR_P (argtype)) { tree type = complete_type (TREE_TYPE (argtype)); @@ -5542,15 +5657,15 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert, else return error_mark_node; } - else if ((pedantic || warn_pointer_arith) - && !TYPE_PTROB_P (argtype)) + else if (!TYPE_PTROB_P (argtype)) { if (complain & tf_error) - permerror (input_location, (code == PREINCREMENT_EXPR + pedwarn (input_location, OPT_Wpointer_arith, + (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) - ? G_("ISO C++ forbids incrementing a pointer of type %qT") - : G_("ISO C++ forbids decrementing a pointer of type %qT"), - argtype); + ? G_("ISO C++ forbids incrementing a pointer of type %qT") + : G_("ISO C++ forbids decrementing a pointer of type %qT"), + argtype); else return error_mark_node; } @@ -5710,7 +5825,7 @@ unary_complex_lvalue (enum tree_code code, tree arg) return build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg)), targ); } - if (TREE_CODE (arg) == SAVE_EXPR && TREE_CODE (targ) == INDIRECT_REF) + if (TREE_CODE (arg) == SAVE_EXPR && INDIRECT_REF_P (targ)) return build3 (SAVE_EXPR, build_pointer_type (TREE_TYPE (arg)), TREE_OPERAND (targ, 0), current_function_decl, NULL); } @@ -5763,7 +5878,7 @@ cxx_mark_addressable (tree exp) if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x) && !DECL_ARTIFICIAL (x)) { - if (TREE_CODE (x) == VAR_DECL && DECL_HARD_REGISTER (x)) + if (VAR_P (x) && DECL_HARD_REGISTER (x)) { error ("address of explicit register variable %qD requested", x); @@ -5822,7 +5937,7 @@ build_x_conditional_expr (location_t loc, tree ifexp, tree op1, tree op2, op2 = build_non_dependent_expr (op2); } - expr = build_conditional_expr (ifexp, op1, op2, complain); + expr = build_conditional_expr (loc, ifexp, op1, op2, complain); if (processing_template_decl && expr != error_mark_node && TREE_CODE (expr) != VEC_COND_EXPR) { @@ -5830,7 +5945,7 @@ build_x_conditional_expr (location_t loc, tree ifexp, tree op1, tree op2, orig_ifexp, orig_op1, orig_op2); /* In C++11, remember that the result is an lvalue or xvalue. In C++98, lvalue_kind can just assume lvalue in a template. */ - if (cxx_dialect >= cxx0x + if (cxx_dialect >= cxx11 && lvalue_or_rvalue_with_address_p (expr) && !lvalue_or_rvalue_with_address_p (min)) TREE_TYPE (min) = cp_build_reference_type (TREE_TYPE (min), @@ -5988,7 +6103,8 @@ cp_build_compound_expr (tree lhs, tree rhs, tsubst_flags_t complain) if (type_unknown_p (rhs)) { - error ("no context to resolve type of %qE", rhs); + if (complain & tf_error) + error ("no context to resolve type of %qE", rhs); return error_mark_node; } @@ -6235,9 +6351,15 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, /* [expr.static.cast] Any expression can be explicitly converted to type cv void. */ - if (TREE_CODE (type) == VOID_TYPE) + if (VOID_TYPE_P (type)) return convert_to_void (expr, ICV_CAST, complain); + /* [class.abstract] + An abstract class shall not be used ... as the type of an explicit + conversion. */ + if (abstract_virtuals_error_sfinae (ACU_CAST, type, complain)) + return error_mark_node; + /* [expr.static.cast] An expression e can be explicitly converted to a type T using a @@ -6351,7 +6473,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, converted to a pointer to object type. A value of type pointer to object converted to "pointer to cv void" and back to the original pointer type will have its original value. */ - if (TREE_CODE (intype) == POINTER_TYPE + if (TYPE_PTR_P (intype) && VOID_TYPE_P (TREE_TYPE (intype)) && TYPE_PTROB_P (type)) { @@ -6871,7 +6993,7 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain) { /* Allow casting from T1* to T2[] because Cfront allows it. NIHCL uses it. It is not valid ISO C++ however. */ - if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) + if (TYPE_PTR_P (TREE_TYPE (expr))) { if (complain & tf_error) permerror (input_location, "ISO C++ forbids casting to an array type %qT", type); @@ -6895,7 +7017,7 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain) return error_mark_node; } - if (TREE_CODE (type) == POINTER_TYPE + if (TYPE_PTR_P (type) && TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE /* Casting to an integer of smaller size is an error detected elsewhere. */ && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (value)) @@ -7065,7 +7187,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, return error_mark_node; cond = build_conditional_expr - (TREE_OPERAND (lhs, 0), + (input_location, TREE_OPERAND (lhs, 0), cp_build_modify_expr (TREE_OPERAND (lhs, 1), modifycode, rhs, complain), cp_build_modify_expr (TREE_OPERAND (lhs, 2), @@ -7531,8 +7653,13 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p, if (!force && !can_convert_arg (to_type, TREE_TYPE (pfn), pfn, LOOKUP_NORMAL, complain)) - error ("invalid conversion to type %qT from type %qT", - to_type, pfn_type); + { + if (complain & tf_error) + error ("invalid conversion to type %qT from type %qT", + to_type, pfn_type); + else + return error_mark_node; + } n = get_delta_difference (TYPE_PTRMEMFUNC_OBJECT_TYPE (pfn_type), TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type), @@ -7725,6 +7852,13 @@ convert_for_assignment (tree type, tree rhs, tree rhstype; enum tree_code coder; + /* If we are dealing with built-in array notation function then we don't need + to convert them. They will be broken up into modify exprs in future, + during which all these checks will be done. */ + if (flag_enable_cilkplus + && is_cilkplus_reduce_builtin (fndecl) != BUILT_IN_NONE) + return rhs; + /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ if (TREE_CODE (rhs) == NON_LVALUE_EXPR) rhs = TREE_OPERAND (rhs, 0); @@ -7951,8 +8085,7 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags, && (TREE_CODE (type) != REFERENCE_TYPE || TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE)) || (TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE - && (TREE_CODE (type) != REFERENCE_TYPE - || TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)) + && !TYPE_REFFN_P (type)) || TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE) rhs = decay_conversion (rhs, complain); @@ -7971,15 +8104,14 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags, int savew = 0, savee = 0; if (fndecl) - savew = warningcount, savee = errorcount; + savew = warningcount + werrorcount, savee = errorcount; rhs = initialize_reference (type, rhs, flags, complain); - if (fndecl) - { - if (warningcount > savew) - warning (0, "in passing argument %P of %q+D", parmnum, fndecl); - else if (errorcount > savee) - error ("in passing argument %P of %q+D", parmnum, fndecl); - } + + if (fndecl + && (warningcount + werrorcount > savew || errorcount > savee)) + inform (input_location, + "in passing argument %P of %q+D", parmnum, fndecl); + return rhs; } @@ -8036,7 +8168,7 @@ maybe_warn_about_returning_address_of_local (tree retval) warning (OPT_Wreturn_local_addr, "returning reference to temporary"); return; } - if (TREE_CODE (whats_returned) == VAR_DECL + if (VAR_P (whats_returned) && DECL_NAME (whats_returned) && TEMP_NAME_P (DECL_NAME (whats_returned))) { @@ -8052,6 +8184,7 @@ maybe_warn_about_returning_address_of_local (tree retval) if (DECL_P (whats_returned) && DECL_NAME (whats_returned) && DECL_FUNCTION_SCOPE_P (whats_returned) + && !is_capture_proxy (whats_returned) && !(TREE_STATIC (whats_returned) || TREE_PUBLIC (whats_returned))) { @@ -8243,7 +8376,7 @@ check_return_expr (tree retval, bool *no_warning) warn = false; /* If we are calling a function whose return type is the same of the current class reference, it is ok. */ - else if (TREE_CODE (retval) == INDIRECT_REF + else if (INDIRECT_REF_P (retval) && TREE_CODE (TREE_OPERAND (retval, 0)) == CALL_EXPR) warn = false; } @@ -8274,11 +8407,11 @@ check_return_expr (tree retval, bool *no_warning) named_return_value_okay_p = (retval != NULL_TREE /* Must be a local, automatic variable. */ - && TREE_CODE (retval) == VAR_DECL + && VAR_P (retval) && DECL_CONTEXT (retval) == current_function_decl && ! TREE_STATIC (retval) && ! DECL_ANON_UNION_VAR_P (retval) - && (DECL_ALIGN (retval) >= DECL_ALIGN (result)) + && (DECL_ALIGN (retval) <= DECL_ALIGN (result)) /* The cv-unqualified type of the returned value must be the same as the cv-unqualified return type of the function. */ @@ -8322,7 +8455,7 @@ check_return_expr (tree retval, bool *no_warning) Note that these conditions are similar to, but not as strict as, the conditions for the named return value optimization. */ if ((cxx_dialect != cxx98) - && (TREE_CODE (retval) == VAR_DECL + && (VAR_P (retval) || TREE_CODE (retval) == PARM_DECL) && DECL_CONTEXT (retval) == current_function_decl && !TREE_STATIC (retval) @@ -8406,7 +8539,7 @@ comp_ptr_ttypes_real (tree to, tree from, int constp) if (TREE_CODE (to) == VECTOR_TYPE) is_opaque_pointer = vector_targets_convertible_p (to, from); - if (TREE_CODE (to) != POINTER_TYPE && !TYPE_PTRDATAMEM_P (to)) + if (!TYPE_PTR_P (to) && !TYPE_PTRDATAMEM_P (to)) return ((constp >= 0 || to_more_cv_qualified) && (is_opaque_pointer || same_type_ignoring_top_level_qualifiers_p (to, from))); @@ -8470,9 +8603,9 @@ ptr_reasonably_similar (const_tree to, const_tree from) for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from)) { /* Any target type is similar enough to void. */ - if (TREE_CODE (to) == VOID_TYPE) + if (VOID_TYPE_P (to)) return !error_type_p (from); - if (TREE_CODE (from) == VOID_TYPE) + if (VOID_TYPE_P (from)) return !error_type_p (to); if (TREE_CODE (to) != TREE_CODE (from)) @@ -8495,7 +8628,7 @@ ptr_reasonably_similar (const_tree to, const_tree from) if (TREE_CODE (to) == FUNCTION_TYPE) return !error_type_p (to) && !error_type_p (from); - if (TREE_CODE (to) != POINTER_TYPE) + if (!TYPE_PTR_P (to)) return comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), COMPARE_BASE | COMPARE_DERIVED); @@ -8524,7 +8657,7 @@ comp_ptr_ttypes_const (tree to, tree from) if (TREE_CODE (to) == VECTOR_TYPE) is_opaque_pointer = vector_targets_convertible_p (to, from); - if (TREE_CODE (to) != POINTER_TYPE) + if (!TYPE_PTR_P (to)) return (is_opaque_pointer || same_type_ignoring_top_level_qualifiers_p (to, from)); } @@ -8553,6 +8686,22 @@ cp_type_quals (const_tree type) return quals; } +/* Returns the function-ref-qualifier for TYPE */ + +cp_ref_qualifier +type_memfn_rqual (const_tree type) +{ + gcc_assert (TREE_CODE (type) == FUNCTION_TYPE + || TREE_CODE (type) == METHOD_TYPE); + + if (!FUNCTION_REF_QUALIFIED (type)) + return REF_QUAL_NONE; + else if (FUNCTION_RVALUE_QUALIFIED (type)) + return REF_QUAL_RVALUE; + else + return REF_QUAL_LVALUE; +} + /* Returns the function-cv-quals for TYPE, which must be a FUNCTION_TYPE or METHOD_TYPE. */ @@ -8568,18 +8717,22 @@ type_memfn_quals (const_tree type) } /* Returns the FUNCTION_TYPE TYPE with its function-cv-quals changed to - MEMFN_QUALS. */ + MEMFN_QUALS and its ref-qualifier to RQUAL. */ tree -apply_memfn_quals (tree type, cp_cv_quals memfn_quals) +apply_memfn_quals (tree type, cp_cv_quals memfn_quals, cp_ref_qualifier rqual) { /* Could handle METHOD_TYPE here if necessary. */ gcc_assert (TREE_CODE (type) == FUNCTION_TYPE); - if (TYPE_QUALS (type) == memfn_quals) + if (TYPE_QUALS (type) == memfn_quals + && type_memfn_rqual (type) == rqual) return type; + /* This should really have a different TYPE_MAIN_VARIANT, but that gets complex. */ - return build_qualified_type (type, memfn_quals); + tree result = build_qualified_type (type, memfn_quals); + result = build_exception_variant (result, TYPE_RAISES_EXCEPTIONS (type)); + return build_ref_qualified_type (result, rqual); } /* Returns nonzero if TYPE is const or volatile. */ @@ -8744,8 +8897,7 @@ casts_away_constness (tree t1, tree t2, tsubst_flags_t complain) /* Casting away constness is only something that makes sense for pointer or reference types. */ - if (TREE_CODE (t1) != POINTER_TYPE - || TREE_CODE (t2) != POINTER_TYPE) + if (!TYPE_PTR_P (t1) || !TYPE_PTR_P (t2)) return false; /* Top-level qualifiers don't matter. */ @@ -8855,7 +9007,7 @@ check_literal_operator_args (const_tree decl, tree t = TREE_VALUE (argtype); ++arity; - if (TREE_CODE (t) == POINTER_TYPE) + if (TYPE_PTR_P (t)) { bool maybe_raw_p = false; t = TREE_TYPE (t); diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index d227a821d43..a44789362e3 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -98,7 +98,7 @@ cxx_readonly_error (tree arg, enum lvalue_use errstring) /* Handle C++-specific things first. */ - if (TREE_CODE (arg) == VAR_DECL + if (VAR_P (arg) && DECL_LANG_SPECIFIC (arg) && DECL_IN_AGGR_P (arg) && !TREE_STATIC (arg)) @@ -111,9 +111,9 @@ cxx_readonly_error (tree arg, enum lvalue_use errstring) G_("decrement of " "constant field %qD"), arg); - else if (TREE_CODE (arg) == INDIRECT_REF + else if (INDIRECT_REF_P (arg) && TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))) == REFERENCE_TYPE - && (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL + && (VAR_P (TREE_OPERAND (arg, 0)) || TREE_CODE (TREE_OPERAND (arg, 0)) == PARM_DECL)) ERROR_FOR_ASSIGNMENT (G_("assignment of " "read-only reference %qD"), @@ -141,6 +141,9 @@ struct GTY((chain_next ("%h.next"))) pending_abstract_type { /* Type which will be checked for abstractness. */ tree type; + /* Kind of use in an unnamed declarator. */ + abstract_class_use use; + /* Position of the declaration. This is only needed for IDENTIFIER_NODEs, because DECLs already carry locus information. */ location_t locus; @@ -181,6 +184,7 @@ pat_compare (const void* val1, const void* val2) static GTY ((param_is (struct pending_abstract_type))) htab_t abstract_pending_vars = NULL; +static int abstract_virtuals_error_sfinae (tree, tree, abstract_class_use, tsubst_flags_t); /* This function is called after TYPE is completed, and will check if there are pending declarations for which we still need to verify the abstractness @@ -231,7 +235,8 @@ complete_type_check_abstract (tree type) location. Notice that this is only needed if the decl is an IDENTIFIER_NODE. */ input_location = pat->locus; - abstract_virtuals_error (pat->decl, pat->type); + abstract_virtuals_error_sfinae (pat->decl, pat->type, pat->use, + tf_warning_or_error); pat = pat->next; } } @@ -244,11 +249,13 @@ complete_type_check_abstract (tree type) /* If TYPE has abstract virtual functions, issue an error about trying to create an object of that type. DECL is the object declared, or - NULL_TREE if the declaration is unavailable. Returns 1 if an error - occurred; zero if all was well. */ + NULL_TREE if the declaration is unavailable, in which case USE specifies + the kind of invalid use. Returns 1 if an error occurred; zero if + all was well. */ -int -abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain) +static int +abstract_virtuals_error_sfinae (tree decl, tree type, abstract_class_use use, + tsubst_flags_t complain) { vec<tree, va_gc> *pure; @@ -258,17 +265,24 @@ abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain) return 0; type = TYPE_MAIN_VARIANT (type); +#if 0 + /* Instantiation here seems to be required by the standard, + but breaks e.g. boost::bind. FIXME! */ + /* In SFINAE, non-N3276 context, force instantiation. */ + if (!(complain & (tf_error|tf_decltype))) + complete_type (type); +#endif + /* If the type is incomplete, we register it within a hash table, so that we can check again once it is completed. This makes sense only for objects for which we have a declaration or at least a name. */ - if (!COMPLETE_TYPE_P (type)) + if (!COMPLETE_TYPE_P (type) && (complain & tf_error)) { void **slot; struct pending_abstract_type *pat; - gcc_assert (!decl || DECL_P (decl) - || TREE_CODE (decl) == IDENTIFIER_NODE); + gcc_assert (!decl || DECL_P (decl) || identifier_p (decl)); if (!abstract_pending_vars) abstract_pending_vars = htab_create_ggc (31, &pat_calc_hash, @@ -280,6 +294,7 @@ abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain) pat = ggc_alloc_pending_abstract_type (); pat->type = type; pat->decl = decl; + pat->use = use; pat->locus = ((decl && DECL_P (decl)) ? DECL_SOURCE_LOCATION (decl) : input_location); @@ -304,12 +319,18 @@ abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain) if (decl) { - if (TREE_CODE (decl) == VAR_DECL) + if (VAR_P (decl)) error ("cannot declare variable %q+D to be of abstract " "type %qT", decl, type); else if (TREE_CODE (decl) == PARM_DECL) - error ("cannot declare parameter %q+D to be of abstract type %qT", - decl, type); + { + if (DECL_NAME (decl)) + error ("cannot declare parameter %q+D to be of abstract type %qT", + decl, type); + else + error ("cannot declare parameter to be of abstract type %qT", + type); + } else if (TREE_CODE (decl) == FIELD_DECL) error ("cannot declare field %q+D to be of abstract type %qT", decl, type); @@ -318,14 +339,40 @@ abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain) error ("invalid abstract return type for member function %q+#D", decl); else if (TREE_CODE (decl) == FUNCTION_DECL) error ("invalid abstract return type for function %q+#D", decl); - else if (TREE_CODE (decl) == IDENTIFIER_NODE) + else if (identifier_p (decl)) /* Here we do not have location information. */ error ("invalid abstract type %qT for %qE", type, decl); else error ("invalid abstract type for %q+D", decl); } - else - error ("cannot allocate an object of abstract type %qT", type); + else switch (use) + { + case ACU_ARRAY: + error ("creating array of %qT, which is an abstract class type", type); + break; + case ACU_CAST: + error ("invalid cast to abstract class type %qT", type); + break; + case ACU_NEW: + error ("invalid new-expression of abstract class type %qT", type); + break; + case ACU_RETURN: + error ("invalid abstract return type %qT", type); + break; + case ACU_PARM: + error ("invalid abstract parameter type %qT", type); + break; + case ACU_THROW: + error ("expression of abstract class type %qT cannot " + "be used in throw-expression", type); + break; + case ACU_CATCH: + error ("cannot declare catch parameter to be of abstract " + "class type %qT", type); + break; + default: + error ("cannot allocate an object of abstract type %qT", type); + } /* Only go through this once. */ if (pure->length ()) @@ -347,14 +394,24 @@ abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain) again. */ pure->truncate (0); } - else - inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)), - " since type %qT has pure virtual functions", - type); return 1; } +int +abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain) +{ + return abstract_virtuals_error_sfinae (decl, type, ACU_UNKNOWN, complain); +} + +int +abstract_virtuals_error_sfinae (abstract_class_use use, tree type, + tsubst_flags_t complain) +{ + return abstract_virtuals_error_sfinae (NULL_TREE, type, use, complain); +} + + /* Wrapper for the above function in the common case of wanting errors. */ int @@ -363,6 +420,12 @@ abstract_virtuals_error (tree decl, tree type) return abstract_virtuals_error_sfinae (decl, type, tf_warning_or_error); } +int +abstract_virtuals_error (abstract_class_use use, tree type) +{ + return abstract_virtuals_error_sfinae (use, type, tf_warning_or_error); +} + /* 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 @@ -382,7 +445,7 @@ cxx_incomplete_type_diagnostic (const_tree value, const_tree type, if (TREE_CODE (type) == ERROR_MARK) return; - if (value != 0 && (TREE_CODE (value) == VAR_DECL + if (value != 0 && (VAR_P (value) || TREE_CODE (value) == PARM_DECL || TREE_CODE (value) == FIELD_DECL)) { @@ -732,10 +795,12 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags) will perform the dynamic initialization. */ if (value != error_mark_node && (TREE_SIDE_EFFECTS (value) - || ! initializer_constant_valid_p (value, TREE_TYPE (value)))) + || array_of_runtime_bound_p (type) + || ! reduced_constant_expression_p (value))) { if (TREE_CODE (type) == ARRAY_TYPE - && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (type))) + && (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (type)) + || array_of_runtime_bound_p (type))) /* For an array, we only need/want a single cleanup region rather than one per element. */ return build_vec_init (decl, NULL_TREE, value, false, 1, @@ -825,7 +890,7 @@ check_narrowing (tree type, tree init) if (!ok) { - if (cxx_dialect >= cxx0x) + if (cxx_dialect >= cxx11) pedwarn (EXPR_LOC_OR_HERE (init), OPT_Wnarrowing, "narrowing conversion of %qE from %qT to %qT inside { }", init, ftype, type); @@ -1051,7 +1116,7 @@ process_init_constructor_array (tree type, tree init, if (TREE_CODE (type) == ARRAY_TYPE) { tree domain = TYPE_DOMAIN (type); - if (domain) + if (domain && TREE_CONSTANT (TYPE_MAX_VALUE (domain))) len = (tree_to_double_int (TYPE_MAX_VALUE (domain)) - tree_to_double_int (TYPE_MIN_VALUE (domain)) + double_int_one) @@ -1171,6 +1236,8 @@ process_init_constructor_record (tree type, tree init, type = TREE_TYPE (field); if (DECL_BIT_FIELD_TYPE (field)) type = DECL_BIT_FIELD_TYPE (field); + if (type == error_mark_node) + return PICFLAG_ERRONEOUS; if (idx < vec_safe_length (CONSTRUCTOR_ELTS (init))) { @@ -1181,7 +1248,7 @@ process_init_constructor_record (tree type, tree init, latter case can happen in templates where lookup has to be deferred. */ gcc_assert (TREE_CODE (ce->index) == FIELD_DECL - || TREE_CODE (ce->index) == IDENTIFIER_NODE); + || identifier_p (ce->index)); if (ce->index != field && ce->index != DECL_NAME (field)) { @@ -1307,7 +1374,7 @@ process_init_constructor_union (tree type, tree init, { if (TREE_CODE (ce->index) == FIELD_DECL) ; - else if (TREE_CODE (ce->index) == IDENTIFIER_NODE) + else if (identifier_p (ce->index)) { /* This can happen within a cast, see g++.dg/opt/cse2.C. */ tree name = ce->index; @@ -1526,7 +1593,7 @@ build_x_arrow (location_t loc, tree expr, tsubst_flags_t complain) else last_rval = decay_conversion (expr, complain); - if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE) + if (TYPE_PTR_P (TREE_TYPE (last_rval))) { if (processing_template_decl) { @@ -1612,7 +1679,7 @@ build_m_component_ref (tree datum, tree component, tsubst_flags_t complain) if (TYPE_PTRDATAMEM_P (ptrmem_type)) { - bool is_lval = real_lvalue_p (datum); + cp_lvalue_kind kind = lvalue_kind (datum); tree ptype; /* Compute the type of the field, as described in [expr.ref]. @@ -1642,12 +1709,39 @@ build_m_component_ref (tree datum, tree component, tsubst_flags_t complain) return error_mark_node; /* If the object expression was an rvalue, return an rvalue. */ - if (!is_lval) + if (kind & clk_class) + datum = rvalue (datum); + else if (kind & clk_rvalueref) datum = move (datum); return datum; } else - return build2 (OFFSET_REF, type, datum, component); + { + /* 5.5/6: In a .* expression whose object expression is an rvalue, the + program is ill-formed if the second operand is a pointer to member + function with ref-qualifier &. In a .* expression whose object + expression is an lvalue, the program is ill-formed if the second + operand is a pointer to member function with ref-qualifier &&. */ + if (FUNCTION_REF_QUALIFIED (type)) + { + bool lval = real_lvalue_p (datum); + if (lval && FUNCTION_RVALUE_QUALIFIED (type)) + { + if (complain & tf_error) + error ("pointer-to-member-function type %qT requires an rvalue", + ptrmem_type); + return error_mark_node; + } + else if (!lval && !FUNCTION_RVALUE_QUALIFIED (type)) + { + if (complain & tf_error) + error ("pointer-to-member-function type %qT requires an lvalue", + ptrmem_type); + return error_mark_node; + } + } + return build2 (OFFSET_REF, type, datum, component); + } } /* Return a tree node for the expression TYPENAME '(' PARMS ')'. */ @@ -1729,7 +1823,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain) if (!complete_type_or_maybe_complain (type, NULL_TREE, complain)) return error_mark_node; - if (abstract_virtuals_error_sfinae (NULL_TREE, type, complain)) + if (abstract_virtuals_error_sfinae (ACU_CAST, type, complain)) return error_mark_node; /* [expr.type.conv] @@ -1790,7 +1884,7 @@ add_exception_specifier (tree list, tree spec, int complain) /* [except.spec] 1, type in an exception specifier shall not be incomplete, or pointer or ref to incomplete other than pointer to cv void. */ - is_ptr = TREE_CODE (core) == POINTER_TYPE; + is_ptr = TYPE_PTR_P (core); if (is_ptr || TREE_CODE (core) == REFERENCE_TYPE) core = TREE_TYPE (core); if (complain < 0) |