diff options
author | Ian Lance Taylor <iant@golang.org> | 2020-12-03 12:12:10 -0800 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2020-12-03 12:12:10 -0800 |
commit | f012991e2db06cc95f7aac8ecb74a1ac5f51f3d2 (patch) | |
tree | 582e5d7b377b6e973666a71960b28a7d11d72b07 /gcc/cp | |
parent | 8d703821c69062c0cd255787d793e44f1a95d463 (diff) | |
parent | 3089f5feef36810c625b5813370a97b4ecc841f8 (diff) | |
download | gcc-f012991e2db06cc95f7aac8ecb74a1ac5f51f3d2.zip gcc-f012991e2db06cc95f7aac8ecb74a1ac5f51f3d2.tar.gz gcc-f012991e2db06cc95f7aac8ecb74a1ac5f51f3d2.tar.bz2 |
Merge from trunk revision 3089f5feef36810c625b5813370a97b4ecc841f8
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 470 | ||||
-rw-r--r-- | gcc/cp/Make-lang.in | 10 | ||||
-rw-r--r-- | gcc/cp/call.c | 94 | ||||
-rw-r--r-- | gcc/cp/class.c | 17 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 416 | ||||
-rw-r--r-- | gcc/cp/constraint.cc | 4 | ||||
-rw-r--r-- | gcc/cp/coroutines.cc | 2 | ||||
-rw-r--r-- | gcc/cp/cp-gimplify.c | 13 | ||||
-rw-r--r-- | gcc/cp/cp-objcp-common.c | 2 | ||||
-rw-r--r-- | gcc/cp/cp-tree.def | 6 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 170 | ||||
-rw-r--r-- | gcc/cp/cxx-pretty-print.c | 15 | ||||
-rw-r--r-- | gcc/cp/decl.c | 110 | ||||
-rw-r--r-- | gcc/cp/error.c | 19 | ||||
-rw-r--r-- | gcc/cp/g++spec.c | 33 | ||||
-rw-r--r-- | gcc/cp/init.c | 6 | ||||
-rw-r--r-- | gcc/cp/lang-specs.h | 57 | ||||
-rw-r--r-- | gcc/cp/lex.c | 15 | ||||
-rw-r--r-- | gcc/cp/logic.cc | 5 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 27 | ||||
-rw-r--r-- | gcc/cp/method.c | 2 | ||||
-rw-r--r-- | gcc/cp/module.cc | 21 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 264 | ||||
-rw-r--r-- | gcc/cp/name-lookup.h | 119 | ||||
-rw-r--r-- | gcc/cp/optimize.c | 2 | ||||
-rw-r--r-- | gcc/cp/parser.c | 375 | ||||
-rw-r--r-- | gcc/cp/pt.c | 184 | ||||
-rw-r--r-- | gcc/cp/ptree.c | 38 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 34 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 165 | ||||
-rw-r--r-- | gcc/cp/tree.c | 85 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 38 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 168 |
33 files changed, 2332 insertions, 654 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9c36b80..6728ea1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,473 @@ +2020-12-03 Peter Bergner <bergner@linux.ibm.com> + + PR c++/97947 + * typeck2.c (digest_init_r): Handle OPAQUE_TYPE as an aggregate type. + +2020-12-02 Jakub Jelinek <jakub@redhat.com> + + PR c++/80780 + PR c++/93093 + * cp-tree.h (source_location_current_p): Declare. + * tree.c (source_location_current_p): New function. + * call.c (immediate_invocation_p): New function. + (build_over_call): Use it to resolve LWG3396. + * constexpr.c (cxx_eval_builtin_function_call): Temporarily set + current_function_decl from ctx->call->fundef->decl if any. + * cp-gimplify.c (cp_genericize_r) <case CALL_EXPR>: Fold calls + to immediate function std::source_location::current (). + +2020-12-02 Jason Merrill <jason@redhat.com> + + * decl.c (grokdeclarator): Improve diagnostic for + disallowed CTAD placeholder. + +2020-12-02 Jason Merrill <jason@redhat.com> + + * decl.c (check_initializer): Also look through STMT_EXPR + and BIND_EXPR. + +2020-12-02 Nathan Sidwell <nathan@acm.org> + + * cp-tree.h (comparing_typenames): Declare. + * pt.c (comparing_typenames): Define. + (spec_hasher::equal): Increment it around comparisons. + * typeck.c (structural_comptypes): Adjust TYPENAME resolution + check. + +2020-12-02 Marek Polacek <polacek@redhat.com> + + PR c++/97975 + * constexpr.c (fold_non_dependent_init): Add a tree parameter. + Use it. + * cp-tree.h (fold_non_dependent_init): Add a tree parameter with + a default value. + * typeck2.c (store_init_value): Call fold_non_dependent_expr + only when checking the initializer for constexpr variables. + Call fold_non_dependent_init instead of maybe_constant_init. + +2020-12-02 Marek Polacek <polacek@redhat.com> + + PR c++/97187 + PR c++/97993 + * pt.c (tsubst_copy_and_build) <case NEW_EXPR>: Return error_mark_node + if init is erroneous. + +2020-12-02 Nathan Sidwell <nathan@acm.org> + + * cp-tree.h (DECL_MODULE_PURVIEW_P, DECL_MODULE_IMPORT_P) + (DECL_MODULE_ENTITY_P): New. + (DECL_MODULE_PENDING_SPECIALIZATIONS_P): New. + (DECL_MODULE_PENDING_MEMBERS_P): New. + (DECL_MODULE_ATTACHMENTS_P): New. + (DECL_MODULE_EXPORT_P): New. + (struct lang_decl_base): Shrink sel field. Add new + module-specific fields. + +2020-12-02 Nathan Sidwell <nathan@acm.org> + + * cp-tree.h (DECL_TINFO_P): Also for TYPE_DECLs. + (get_tinfo_decl_direct): Declare. + (get_pseudo_tinfo_index, get_pseudo_tinfo_type): Declare. + * rtti.c (get_tinfo_decl_direct): Externalize. + (get_tinfo_desc): Set DECL_TINFO_P on the typedef. + (get_pseudo_tinfo_index, get_pseudo_tinfo_type): New. + +2020-12-02 Nathan Sidwell <nathan@acm.org> + + * cp-tree.h (maybe_add_lang_decl_raw, maybe_add_lang_type_raw): + Declare. + * lex.c (maybe_add_lang_decl_raw, maybe_add_lang_type_raw): + Externalize, reformat. + +2020-12-02 Nathan Sidwell <nathan@acm.org> + + * cp-tree.h (build_cplus_array_type): Add defaulted DEP parm. + * tree.c (set_array_type_common): Add DEP parm. + (build_cplus_array_type): Add DEP parm, determine dependency if + needed. + (cp_build_qualified_type_real): Adjust array-building call. + (strip_typedefs): Likewise. + +2020-12-02 Nathan Sidwell <nathan@acm.org> + + * ptree.c (cxx_print_xnode): Increase binding-vector prefix size. + +2020-12-02 Nathan Sidwell <nathan@acm.org> + + * cp-tree.def (BINDING_VECTOR): New. + * name-lookup.h (struct binding_slot): New. + (BINDING_VECTOR_SLOTS_PER_CLUSTER): New. + (struct binding_index, struct binding_cluster): New. + (BINDING_VECTOR_ALLOC_CLUSTERS, BINDING_VECTOR_CLUSTER_BASE) + (BINDING_VECTOR_CLUSTER): New. + (struct tree_binding_vec): New. + (BINDING_VECTOR_NAME, BINDING_VECTOR_GLOBAL_DUPS_P) + (BINDING_VECTOR_PARTITION_DUPS_P): New. + (BINDING_BINDING_GLOBAL_P, BINDING_BINDING_PARTITION_P): New. + (BINDING_VECTOR_PENDING_SPECIALIZATIONS) + (BINDING_VECTOR_PENDING_IS_HEADER_P) + (BINDING_VECTOR_PENDING_IS_PARTITION_P): New. + * cp-tree.h (enum cp_tree_node_structure_enum): Add + TS_CP_BINDING_VECTOR. + (union lang_tree_node): Add binding_vec field. + (make_binding_vec): Declare. + (named_decl_hash::hash, named_decl_hash::equal): Check for binding + vector. + * decl.c (cp_tree_node_structure): Add BINDING_VECTOR case. + * ptree.c (cxx_print_xnode): Add BINDING_VECTOR case. + * tree.c (make_binding_vec): New. + +2020-12-01 Ville Voutilainen <ville.voutilainen@gmail.com> + + PR c++/98054 + * cxx-pretty-print.c (pp_cxx_trait_expression): + Add support for __is_nothrow_{assignable,constructible}. + +2020-12-01 Jakub Jelinek <jakub@redhat.com> + + PR c++/98072 + * parser.c (cp_parser_omp_depobj): Suppress location wrappers when + parsing depend clause. + +2020-12-01 Nathan Sidwell <nathan@acm.org> + + * lex.c (init_reswords): Maybe enable module keywords. + +2020-12-01 Nathan Sidwell <nathan@acm.org> + + * lang-specs.h: Add module-related options. + +2020-12-01 Iain Sandoe <iain@sandoe.co.uk> + + * parser.c (cp_parser_declaration): Add a not about where + attributes may be placed. + +2020-11-27 Martin Sebor <msebor@redhat.com> + + * error.c (add_quotes): Revert previous change and use pragma to + suppress -Wformat-diag. + +2020-11-26 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * g++spec.c (TIMELIB, TIME_LIBRARY): Remove. + (lang_specific_driver): Remove TIME_LIBRARY handling. + +2020-11-26 Thomas Schwinge <thomas@codesourcery.com> + + * parser.c (cp_parser_omp_var_list_no_open): Assert that array + section's 'low_bound', 'length' are not location wrapper nodes. + (cp_parser_oacc_all_clauses, cp_parser_oacc_cache): Instantiate + 'auto_suppress_location_wrappers'. + +2020-11-25 Martin Sebor <msebor@redhat.com> + + PR bootstrap/94982 + * constraint.cc (debug_argument_list): Avoid -Wformat-diag. + * error.c (function_category): Same. + (print_template_differences): Same. + * logic.cc (debug): Same. + * name-lookup.c (lookup_using_decl): Same. + * parser.c (maybe_add_cast_fixit): Same. + (cp_parser_template_introduction): Same. + * typeck.c (access_failure_info::add_fixit_hint): Same. + +2020-11-25 Thomas Schwinge <thomas@codesourcery.com> + + * pt.c (tsubst_omp_clauses): Handle 'OMP_CLAUSE__CACHE_'. + (tsubst_expr): Handle 'OACC_CACHE'. + +2020-11-24 Jason Merrill <jason@redhat.com> + + PR c++/97899 + * typeck2.c (store_init_value): Don't split_nonconstant_init in a + template. + +2020-11-24 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/96929 + * constexpr.c (cxx_eval_binary_expression): For shifts by constant + with MSB set, emulate older wide_int_binop behavior to preserve + diagnostics and -fpermissive behavior. + +2020-11-23 Nathan Sidwell <nathan@acm.org> + + * module.cc: New dummy file. + * Make-lang.in: Add rules to build module.o + +2020-11-23 Jozef Lawrynowicz <jozef.l@mittosystems.com> + + * decl.c (start_decl): Set DECL_INITIAL for initialized decls + before attribute processing. + +2020-11-23 Richard Sandiford <richard.sandiford@arm.com> + + PR c++/97904 + * pt.c (tsubst): Use verify_type_context to check the type + of an array element. + +2020-11-21 Marek Polacek <polacek@redhat.com> + + PR c++/94695 + * parser.c (warn_for_range_copy): Warn when the loop variable is + initialized with a value of a different type resulting in a copy. + +2020-11-21 Marek Polacek <polacek@redhat.com> + + PR c++/97846 + * constexpr.c (potential_constant_expression_1): Reject + LABEL_EXPRs that use non-artifical LABEL_DECLs. + +2020-11-21 Marek Polacek <polacek@redhat.com> + + PR c++/97881 + * parser.c (warn_about_ambiguous_parse): Only assume "int" if we + actually saw any type-specifiers. + +2020-11-21 Marek Polacek <polacek@redhat.com> + + PR c++/97839 + * parser.c (cp_parser_lambda_declarator_opt): Don't require (). + +2020-11-21 Marek Polacek <polacek@redhat.com> + + PR c++/97427 + * constexpr.c (cxx_set_object_constness): New function. + (cxx_eval_call_expression): Set new_obj for destructors too. + Call cxx_set_object_constness to set/unset TREE_READONLY of + the object under construction/destruction. + +2020-11-21 Aaron Sawdey <acsawdey@linux.ibm.com> + + * error.c (dump_type): Handle opaque types. + (dump_type_prefix): Handle opaque types. + (dump_type_suffix): Handle opaque types. + (dump_expr): Handle opaque types. + * pt.c (tsubst): Allow opaque types in templates. + (unify): Allow opaque types in templates. + * typeck.c (structural_comptypes): Handle comparison + of opaque types. + +2020-11-20 Jakub Jelinek <jakub@redhat.com> + + PR other/97911 + * Make-lang.in (c++.serial): Change from goal to a variable. + (.PHONY): Drop c++.serial and c++.prev. + (cc1plus$(exeext)): Depend on $(c++.serial) rather than c++.serial. + +2020-11-19 Nathan Sidwell <nathan@acm.org> + + * cp-tree.h (struct spec_entry): Moved from pt.c. + (walk_specializations, match_mergeable_specialization) + (get_mergeable_specialization_flags) + (add_mergeable_specialization): Declare. + * pt.c (struct spec_entry): Moved to cp-tree.h. + (walk_specializations, match_mergeable_specialization) + (get_mergeable_specialization_flags) + (add_mergeable_specialization): New. + +2020-11-19 Nathan Sidwell <nathan@acm.org> + + * cp-tree.h (struct constexpr_fundef): Moved from constexpr.c. + (maybe_save_constexpr_fundef): Declare. + (register_constexpr_fundef): Take constexpr_fundef object, return + void. + * decl.c (mabe_save_function_definition): Delete, functionality + moved to maybe_save_constexpr_fundef. + (emit_coro_helper, finish_function): Adjust. + * constexpr.c (struct constexpr_fundef): Moved to cp-tree.h. + (constexpr_fundef_hasher::equal): Constify. + (constexpr_fundef_hasher::hash): Constify. + (retrieve_constexpr_fundef): Make non-static. + (maybe_save_constexpr_fundef): Break out checking and duplication + from ... + (register_constexpr_fundef): ... here. Just register the constexpr. + +2020-11-19 Marek Polacek <polacek@redhat.com> + + PR c++/97523 + * init.c (build_new): When value-initializing an array new, + leave the INIT as an empty vector. + +2020-11-19 Marek Polacek <polacek@redhat.com> + + PR c++/97895 + * pt.c (do_auto_deduction): Don't crash when the constructor has + zero elements. + +2020-11-19 Nathan Sidwell <nathan@acm.org> + + PR c++/97905 + * decl.c (duplicate_decls): Relax new assert. + +2020-11-18 Iain Sandoe <iain@sandoe.co.uk> + + * parser.c (cp_parser_objc_valid_prefix_attributes): Check + for empty attributes. + +2020-11-18 Jakub Jelinek <jakub@redhat.com> + + * Make-lang.in (c++.serial): New goal. + (.PHONY): Add c++.serial c++.prev. + (cc1plus$(exeext)): Depend on c++.prev. Call LINK_PROGRESS. + +2020-11-17 Nathan Sidwell <nathan@acm.org> + + PR c++/97877 + * decl.c (duplicate_decls): Deal with duplicated DECL_LOCAL_DECL_P + decls. Extend decl_lang_specific checking assert. + +2020-11-17 Nathan Sidwell <nathan@acm.org> + + * cp-tree.h (enum cp_tree_index): Reorder to place lazy fields + after newly-added CPTI_MODULE_HWM. + +2020-11-17 Iain Sandoe <iain@sandoe.co.uk> + + PR c++/97871 + * parser.c (cp_parser_declaration): Remove checking assert. + +2020-11-15 Jason Merrill <jason@redhat.com> + + * decl.c (cp_finish_decl): Only check abstractness on definition. + (require_complete_types_for_parms): Check abstractness here. + (create_array_type_for_decl): Not here. + (grokdeclarator, grokparms, complete_vars): Not here. + * pt.c (tsubst, tsubst_arg_types, tsubst_function_type): Not here. + * typeck2.c (struct pending_abstract_type): Remove. + (struct abstract_type_hasher): Remove. + (abstract_pending_vars, complete_type_check_abstract): Remove. + (abstract_virtuals_error_sfinae): Handle arrays. + * call.c (conv_is_prvalue): Split out from... + (conv_binds_ref_to_prvalue): ...here. + (implicit_conversion_1): Rename from implicit_conversion. + (implicit_conversion): An abstract prvalue is bad. + (convert_like_internal): Don't complain if expr is already + error_mark_node. + +2020-11-13 Jason Merrill <jason@redhat.com> + + * cp-tree.h (USING_DECL_UNRELATED_P): New. + (CONST_DECL_USING_P): New. + * class.c (handle_using_decl): If USING_DECL_UNRELATED_P, + clone the CONST_DECL. + * name-lookup.c (supplement_binding_1): A clone hides its + using-declaration. + (lookup_using_decl): Rewrite to separate lookup and validation. + (do_class_using_decl): Adjust. + (finish_nonmember_using_decl): Adjust. + * parser.c (make_location): Add cp_token overload. + (finish_using_decl): Split out from... + (cp_parser_using_declaration): ...here. Don't look through enums. + (cp_parser_using_enum): New. + (cp_parser_block_declaration): Call it. + (cp_parser_member_declaration): Call it. + * semantics.c (finish_id_expression_1): Handle enumerator + used from class scope. + +2020-11-13 Vladimir N. Makarov <vmakarov@redhat.com> + + * parser.c (cp_parser_asm_definition): Parse outputs for asm + goto too. + +2020-11-13 Iain Sandoe <iain@sandoe.co.uk> + + PR objc/77404 + * parser.c (cp_parser_objc_class_interface): Pass the + location of the class name to the interface declaration. + +2020-11-13 Patrick Palka <ppalka@redhat.com> + + * semantics.c (finish_compound_literal): Don't wrap the original + compound literal in a TARGET_EXPR when inside a template. + +2020-11-12 Jakub Jelinek <jakub@redhat.com> + + PR c++/97790 + * constexpr.c (cxx_eval_constant_expression) <case CLEANUP_POINT_EXPR, + case TRY_FINALLY_EXPR, case CLEANUP_STMT>: Don't pass jump_target to + cxx_eval_constant_expression when evaluating the cleanups. + +2020-11-11 Iain Sandoe <iain@sandoe.co.uk> + + * parser.c (cp_parser_declaration): Unless we are compiling for + Ojective-C++, warn about and discard any attributes that prefix + a linkage specification. + +2020-11-11 Patrick Palka <ppalka@redhat.com> + + PR c++/88115 + * mangle.c (write_expression): Mangle __alignof_ differently + from alignof when the ABI version is at least 15. + +2020-11-11 Patrick Palka <ppalka@redhat.com> + + PR c++/88115 + * cp-tree.h (cxx_sizeof_or_alignof_expr): Add bool parameter. + * decl.c (fold_sizeof_expr): Pass false to + cxx_sizeof_or_alignof_expr. + * parser.c (cp_parser_unary_expression): Pass std_alignof to + cxx_sizeof_or_alignof_expr. + * pt.c (tsubst_copy): Pass false to cxx_sizeof_or_alignof_expr. + (tsubst_copy_and_build): Pass std_alignof to + cxx_sizeof_or_alignof_expr. + * typeck.c (cxx_alignof_expr): Add std_alignof bool parameter + and pass it to cxx_sizeof_or_alignof_type. Set ALIGNOF_EXPR_STD_P + appropriately. + (cxx_sizeof_or_alignof_expr): Add std_alignof bool parameter + and pass it to cxx_alignof_expr. Assert op is either + SIZEOF_EXPR or ALIGNOF_EXPR. + +2020-11-11 Marek Polacek <polacek@redhat.com> + + PR c++/97518 + * pt.c (tsubst_qualified_id): Use EXPR_LOCATION of the qualified-id. + Use it to maybe_wrap_with_location the final expression. + +2020-11-10 Marek Polacek <polacek@redhat.com> + + PR c++/97518 + * cp-tree.h (finish_static_assert): Adjust declaration. + * parser.c (cp_parser_static_assert): Pass false to + finish_static_assert. + * pt.c (tsubst_expr): Pass true to finish_static_assert. + * semantics.c (find_failing_clause_r): New function. + (find_failing_clause): New function. + (finish_static_assert): Add a bool parameter. Use + iloc_sentinel. Call contextual_conv_bool instead of + perform_implicit_conversion_flags. Don't check for INTEGER_CST before + calling integer_zerop. Call find_failing_clause and maybe use its + location. Print the original condition or the failing clause if + SHOW_EXPR_P. + +2020-11-10 Strager Neds <strager.nds@gmail.com> + + * decl.c (duplicate_decls): Use new overload of + set_decl_section_name. + * method.c (use_thunk): Same. + * optimize.c (maybe_clone_body): Same. + * coroutines.cc (act_des_fn): Same. + +2020-11-10 Jakub Jelinek <jakub@redhat.com> + + PR c/97748 + * cvt.c (convert_to_void): Check (complain & tf_warning) in the outer + if rather than twice times in the inner one. Use warn_if_unused_value. + Formatting fix. + +2020-11-10 Chung-Lin Tang <cltang@codesourcery.com> + + * parser.c (cp_parser_omp_target_data): Add use of + new c_omp_adjust_map_clauses function. Add GOMP_MAP_ATTACH_DETACH as + handled map clause kind. + (cp_parser_omp_target_enter_data): Likewise. + (cp_parser_omp_target_exit_data): Likewise. + (cp_parser_omp_target): Likewise. + * semantics.c (handle_omp_array_sections): Adjust COMPONENT_REF case to + use GOMP_MAP_ATTACH_DETACH map kind for C_ORT_OMP region type. Fix + interaction between reference case and attach/detach. + (finish_omp_clauses): Adjust bitmap checks to allow struct decl and + same struct field access to co-exist on OpenMP construct. + 2020-11-09 Marek Polacek <polacek@redhat.com> DR 1914 diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index 6ee4e41..ebfdc90 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -47,12 +47,16 @@ CP_PLUGIN_HEADERS := cp-tree.h cxx-pretty-print.h name-lookup.h type-utils.h ope # into the C++ rule, but that needs a little bit of work # to do the right thing within all.cross. c++: cc1plus$(exeext) +c++.serial = cc1plus$(exeext) # Tell GNU make to ignore these if they exist. .PHONY: c++ CFLAGS-cp/g++spec.o += $(DRIVER_DEFINES) +CFLAGS-cp/module.o += -DHOST_MACHINE=\"$(host)\" \ + -DTARGET_MACHINE=\"$(target)\" + # Create the compiler driver for g++. GXX_OBJS = $(GCC_OBJS) cp/g++spec.o xg++$(exeext): $(GXX_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS) @@ -80,7 +84,7 @@ CXX_AND_OBJCXX_OBJS = \ cp/error.o cp/except.o cp/expr.o \ cp/friend.o cp/init.o \ cp/lambda.o cp/lex.o cp/logic.o \ - cp/mangle.o cp/method.o \ + cp/mangle.o cp/method.o cp/module.o \ cp/name-lookup.o cp/optimize.o \ cp/parser.o cp/pt.o cp/ptree.o \ cp/rtti.o \ @@ -116,9 +120,11 @@ cc1plus-checksum.c : build/genchecksum$(build_exeext) checksum-options \ $(srcdir)/../move-if-change cc1plus-checksum.c.tmp cc1plus-checksum.c; \ fi -cc1plus$(exeext): $(CXX_OBJS) cc1plus-checksum.o $(BACKEND) $(LIBDEPS) +cc1plus$(exeext): $(CXX_OBJS) cc1plus-checksum.o $(BACKEND) $(LIBDEPS) $(c++.prev) + @$(call LINK_PROGRESS,$(INDEX.c++),start) +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ $(CXX_OBJS) cc1plus-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS) + @$(call LINK_PROGRESS,$(INDEX.c++),end) ifeq ($(ENABLE_MAINTAINER_RULES), true) # Special build rule. This is a maintainer rule, that is only diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 9861be1..f1e0bcb 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -213,6 +213,7 @@ static conversion *merge_conversion_sequences (conversion *, conversion *); static tree build_temp (tree, tree, int, diagnostic_t *, tsubst_flags_t); static conversion *build_identity_conv (tree, tree); static inline bool conv_binds_to_array_of_unknown_bound (conversion *); +static bool conv_is_prvalue (conversion *); static tree prevent_lifetime_extension (tree); /* Returns nonzero iff the destructor name specified in NAME matches BASETYPE. @@ -1963,14 +1964,12 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, return conv; } -/* Returns the implicit conversion sequence (see [over.ics]) from type - FROM to type TO. The optional expression EXPR may affect the - conversion. FLAGS are the usual overloading flags. If C_CAST_P is - true, this conversion is coming from a C-style cast. */ +/* Most of the implementation of implicit_conversion, with the same + parameters. */ static conversion * -implicit_conversion (tree to, tree from, tree expr, bool c_cast_p, - int flags, tsubst_flags_t complain) +implicit_conversion_1 (tree to, tree from, tree expr, bool c_cast_p, + int flags, tsubst_flags_t complain) { conversion *conv; @@ -2096,6 +2095,26 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p, return NULL; } +/* Returns the implicit conversion sequence (see [over.ics]) from type + FROM to type TO. The optional expression EXPR may affect the + conversion. FLAGS are the usual overloading flags. If C_CAST_P is + true, this conversion is coming from a C-style cast. */ + +static conversion * +implicit_conversion (tree to, tree from, tree expr, bool c_cast_p, + int flags, tsubst_flags_t complain) +{ + conversion *conv = implicit_conversion_1 (to, from, expr, c_cast_p, + flags, complain); + if (!conv || conv->bad_p) + return conv; + if (conv_is_prvalue (conv) + && CLASS_TYPE_P (conv->type) + && CLASSTYPE_PURE_VIRTUALS (conv->type)) + conv->bad_p = true; + return conv; +} + /* Like implicit_conversion, but return NULL if the conversion is bad. This is not static so that check_non_deducible_conversion can call it within @@ -7407,7 +7426,7 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, else if (t->kind == ck_identity) break; } - if (!complained) + if (!complained && expr != error_mark_node) { range_label_for_type_mismatch label (TREE_TYPE (expr), totype); gcc_rich_location richloc (loc, &label); @@ -8438,20 +8457,15 @@ unsafe_copy_elision_p (tree target, tree exp) && !AGGR_INIT_VIA_CTOR_P (init)); } -/* True iff C is a conversion that binds a reference to a prvalue. */ +/* True IFF the result of the conversion C is a prvalue. */ static bool -conv_binds_ref_to_prvalue (conversion *c) +conv_is_prvalue (conversion *c) { - if (c->kind != ck_ref_bind) - return false; - if (c->need_temporary_p) - return true; - - c = next_conversion (c); - if (c->kind == ck_rvalue) return true; + if (c->kind == ck_base && c->need_temporary_p) + return true; if (c->kind == ck_user && !TYPE_REF_P (c->type)) return true; if (c->kind == ck_identity && c->u.expr @@ -8461,6 +8475,19 @@ conv_binds_ref_to_prvalue (conversion *c) return false; } +/* True iff C is a conversion that binds a reference to a prvalue. */ + +static bool +conv_binds_ref_to_prvalue (conversion *c) +{ + if (c->kind != ck_ref_bind) + return false; + if (c->need_temporary_p) + return true; + + return conv_is_prvalue (next_conversion (c)); +} + /* True iff converting EXPR to a reference type TYPE does not involve creating a temporary. */ @@ -8513,6 +8540,25 @@ build_trivial_dtor_call (tree instance, bool no_ptr_deref) instance, clobber); } +/* Return true if a call to FN with number of arguments NARGS + is an immediate invocation. */ + +static bool +immediate_invocation_p (tree fn, int nargs) +{ + return (TREE_CODE (fn) == FUNCTION_DECL + && DECL_IMMEDIATE_FUNCTION_P (fn) + && cp_unevaluated_operand == 0 + && (current_function_decl == NULL_TREE + || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl)) + && (current_binding_level->kind != sk_function_parms + || !current_binding_level->immediate_fn_ctx_p) + /* As an exception, we defer std::source_location::current () + invocations until genericization because LWG3396 mandates + special behavior for it. */ + && (nargs > 1 || !source_location_current_p (fn))); +} + /* Subroutine of the various build_*_call functions. Overload resolution has chosen a winning candidate CAND; build up a CALL_EXPR accordingly. ARGS is a TREE_LIST of the unconverted arguments to the call. FLAGS is a @@ -8580,13 +8626,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) addr, nargs, argarray); if (TREE_THIS_VOLATILE (fn) && cfun) current_function_returns_abnormally = 1; - if (TREE_CODE (fn) == FUNCTION_DECL - && DECL_IMMEDIATE_FUNCTION_P (fn) - && cp_unevaluated_operand == 0 - && (current_function_decl == NULL_TREE - || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl)) - && (current_binding_level->kind != sk_function_parms - || !current_binding_level->immediate_fn_ctx_p)) + if (immediate_invocation_p (fn, nargs)) { tree obj_arg = NULL_TREE, exprimm = expr; if (DECL_CONSTRUCTOR_P (fn)) @@ -9224,13 +9264,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) if (TREE_CODE (fn) == ADDR_EXPR) { tree fndecl = STRIP_TEMPLATE (TREE_OPERAND (fn, 0)); - if (TREE_CODE (fndecl) == FUNCTION_DECL - && DECL_IMMEDIATE_FUNCTION_P (fndecl) - && cp_unevaluated_operand == 0 - && (current_function_decl == NULL_TREE - || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl)) - && (current_binding_level->kind != sk_function_parms - || !current_binding_level->immediate_fn_ctx_p)) + if (immediate_invocation_p (fndecl, nargs)) { tree obj_arg = NULL_TREE; if (DECL_CONSTRUCTOR_P (fndecl)) diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 7c34d94..ec47b06 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1331,6 +1331,23 @@ handle_using_decl (tree using_decl, tree t) add_method (t, *iter, true); alter_access (t, *iter, access); } + else if (USING_DECL_UNRELATED_P (using_decl)) + { + /* C++20 using enum can import non-inherited enumerators into class + scope. We implement that by making a copy of the CONST_DECL for which + CONST_DECL_USING_P is true. */ + gcc_assert (TREE_CODE (decl) == CONST_DECL); + + tree copy = copy_decl (decl); + DECL_CONTEXT (copy) = t; + DECL_ARTIFICIAL (copy) = true; + /* We emitted debug info for the USING_DECL above; make sure we don't + also emit anything for this clone. */ + DECL_IGNORED_P (copy) = true; + DECL_SOURCE_LOCATION (copy) = DECL_SOURCE_LOCATION (using_decl); + finish_member_declaration (copy); + DECL_ABSTRACT_ORIGIN (copy) = decl; + } else alter_access (t, decl, access); } diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index b6f9c43..e0d3580 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -133,19 +133,10 @@ ensure_literal_type_for_constexpr_object (tree decl) return decl; } -/* Representation of entries in the constexpr function definition table. */ - -struct GTY((for_user)) constexpr_fundef { - tree decl; - tree body; - tree parms; - tree result; -}; - struct constexpr_fundef_hasher : ggc_ptr_hash<constexpr_fundef> { - static hashval_t hash (constexpr_fundef *); - static bool equal (constexpr_fundef *, constexpr_fundef *); + static hashval_t hash (const constexpr_fundef *); + static bool equal (const constexpr_fundef *, const constexpr_fundef *); }; /* This table holds all constexpr function definitions seen in @@ -158,7 +149,8 @@ static GTY (()) hash_table<constexpr_fundef_hasher> *constexpr_fundef_table; same constexpr function. */ inline bool -constexpr_fundef_hasher::equal (constexpr_fundef *lhs, constexpr_fundef *rhs) +constexpr_fundef_hasher::equal (const constexpr_fundef *lhs, + const constexpr_fundef *rhs) { return lhs->decl == rhs->decl; } @@ -167,20 +159,20 @@ constexpr_fundef_hasher::equal (constexpr_fundef *lhs, constexpr_fundef *rhs) Return a hash value for the entry pointed to by Q. */ inline hashval_t -constexpr_fundef_hasher::hash (constexpr_fundef *fundef) +constexpr_fundef_hasher::hash (const constexpr_fundef *fundef) { return DECL_UID (fundef->decl); } /* Return a previously saved definition of function FUN. */ -static constexpr_fundef * +constexpr_fundef * retrieve_constexpr_fundef (tree fun) { if (constexpr_fundef_table == NULL) return NULL; - constexpr_fundef fundef = { fun, NULL, NULL, NULL }; + constexpr_fundef fundef = { fun, NULL_TREE, NULL_TREE, NULL_TREE }; return constexpr_fundef_table->find (&fundef); } @@ -669,7 +661,7 @@ get_function_named_in_call (tree t) return fun; } -/* Subroutine of register_constexpr_fundef. BODY is the body of a function +/* Subroutine of check_constexpr_fundef. BODY is the body of a function declared to be constexpr, or a sub-statement thereof. Returns the return value if suitable, error_mark_node for a statement not allowed in a constexpr function, or NULL_TREE if no return value was found. */ @@ -738,7 +730,7 @@ constexpr_fn_retval (tree body) } } -/* Subroutine of register_constexpr_fundef. BODY is the DECL_SAVED_TREE of +/* Subroutine of check_constexpr_fundef. BODY is the DECL_SAVED_TREE of FUN; do the necessary transformations to turn it into a single expression that we can store in the hash table. */ @@ -868,27 +860,28 @@ cx_check_missing_mem_inits (tree ctype, tree body, bool complain) } /* We are processing the definition of the constexpr function FUN. - Check that its BODY fulfills the propriate requirements and - enter it in the constexpr function definition table. - For constructor BODY is actually the TREE_LIST of the - member-initializer list. */ + Check that its body fulfills the apropriate requirements and + enter it in the constexpr function definition table. */ -tree -register_constexpr_fundef (tree fun, tree body) +void +maybe_save_constexpr_fundef (tree fun) { - constexpr_fundef entry; - constexpr_fundef **slot; + if (processing_template_decl + || !DECL_DECLARED_CONSTEXPR_P (fun) + || cp_function_chain->invalid_constexpr + || DECL_CLONED_FUNCTION_P (fun)) + return; if (!is_valid_constexpr_fn (fun, !DECL_GENERATED_P (fun))) - return NULL; + return; - tree massaged = massage_constexpr_body (fun, body); + tree massaged = massage_constexpr_body (fun, DECL_SAVED_TREE (fun)); if (massaged == NULL_TREE || massaged == error_mark_node) { if (!DECL_CONSTRUCTOR_P (fun)) error ("body of %<constexpr%> function %qD not a return-statement", fun); - return NULL; + return; } bool potential = potential_rvalue_constant_expression (massaged); @@ -901,39 +894,47 @@ register_constexpr_fundef (tree fun, tree body) potential = false; if (!potential && !DECL_GENERATED_P (fun)) - return NULL; - - /* Create the constexpr function table if necessary. */ - if (constexpr_fundef_table == NULL) - constexpr_fundef_table - = hash_table<constexpr_fundef_hasher>::create_ggc (101); + return; - entry.decl = fun; - tree saved_fn = current_function_decl; + constexpr_fundef entry = {fun, NULL_TREE, NULL_TREE, NULL_TREE}; bool clear_ctx = false; - current_function_decl = fun; if (DECL_RESULT (fun) && DECL_CONTEXT (DECL_RESULT (fun)) == NULL_TREE) { clear_ctx = true; DECL_CONTEXT (DECL_RESULT (fun)) = fun; } - entry.body = copy_fn (fun, entry.parms, entry.result); + tree saved_fn = current_function_decl; + current_function_decl = fun; + entry.body = copy_fn (entry.decl, entry.parms, entry.result); current_function_decl = saved_fn; - slot = constexpr_fundef_table->find_slot (&entry, INSERT); if (clear_ctx) - DECL_CONTEXT (DECL_RESULT (fun)) = NULL_TREE; - + DECL_CONTEXT (DECL_RESULT (entry.decl)) = NULL_TREE; if (!potential) /* For a template instantiation, we want to remember the pre-generic body for explain_invalid_constexpr_fn, but do tell cxx_eval_call_expression that it doesn't need to bother trying to expand the function. */ entry.result = error_mark_node; + register_constexpr_fundef (entry); +} + +/* BODY is a validated and massaged definition of a constexpr + function. Register it in the hash table. */ + +void +register_constexpr_fundef (const constexpr_fundef &value) +{ + /* Create the constexpr function table if necessary. */ + if (constexpr_fundef_table == NULL) + constexpr_fundef_table + = hash_table<constexpr_fundef_hasher>::create_ggc (101); + + constexpr_fundef **slot = constexpr_fundef_table->find_slot + (const_cast<constexpr_fundef *> (&value), INSERT); + gcc_assert (*slot == NULL); *slot = ggc_alloc<constexpr_fundef> (); - **slot = entry; - - return fun; + **slot = value; } /* FUN is a non-constexpr function called in a context that requires a @@ -1331,7 +1332,12 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, } if (fndecl_built_in_p (fun, CP_BUILT_IN_SOURCE_LOCATION, BUILT_IN_FRONTEND)) - return fold_builtin_source_location (EXPR_LOCATION (t)); + { + temp_override<tree> ovr (current_function_decl); + if (ctx->call && ctx->call->fundef) + current_function_decl = ctx->call->fundef->decl; + return fold_builtin_source_location (EXPR_LOCATION (t)); + } int strops = 0; int strret = 0; @@ -2186,6 +2192,27 @@ cxx_eval_thunk_call (const constexpr_ctx *ctx, tree t, tree thunk_fndecl, non_constant_p, overflow_p); } +/* If OBJECT is of const class type, evaluate it to a CONSTRUCTOR and set + its TREE_READONLY flag according to READONLY_P. Used for constexpr + 'tors to detect modifying const objects in a constexpr context. */ + +static void +cxx_set_object_constness (const constexpr_ctx *ctx, tree object, + bool readonly_p, bool *non_constant_p, + bool *overflow_p) +{ + if (CLASS_TYPE_P (TREE_TYPE (object)) + && CP_TYPE_CONST_P (TREE_TYPE (object))) + { + /* Subobjects might not be stored in ctx->global->values but we + can get its CONSTRUCTOR by evaluating *this. */ + tree e = cxx_eval_constant_expression (ctx, object, /*lval*/false, + non_constant_p, overflow_p); + if (TREE_CODE (e) == CONSTRUCTOR && !*non_constant_p) + TREE_READONLY (e) = readonly_p; + } +} + /* Subroutine of cxx_eval_constant_expression. Evaluate the call expression tree T in the context of OLD_CALL expression evaluation. */ @@ -2514,11 +2541,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, depth_ok = push_cx_call_context (t); - /* Remember the object we are constructing. */ + /* Remember the object we are constructing or destructing. */ tree new_obj = NULL_TREE; - if (DECL_CONSTRUCTOR_P (fun)) + if (DECL_CONSTRUCTOR_P (fun) || DECL_DESTRUCTOR_P (fun)) { - /* In a constructor, it should be the first `this' argument. + /* In a cdtor, it should be the first `this' argument. At this point it has already been evaluated in the call to cxx_bind_parameters_in_call. */ new_obj = TREE_VEC_ELT (new_call.bindings, 0); @@ -2655,6 +2682,12 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, unsigned save_heap_alloc_count = ctx->global->heap_vars.length (); unsigned save_heap_dealloc_count = ctx->global->heap_dealloc_count; + /* If this is a constexpr destructor, the object's const and volatile + semantics are no longer in effect; see [class.dtor]p5. */ + if (new_obj && DECL_DESTRUCTOR_P (fun)) + cxx_set_object_constness (ctx, new_obj, /*readonly_p=*/false, + non_constant_p, overflow_p); + tree jump_target = NULL_TREE; cxx_eval_constant_expression (&ctx_with_save_exprs, body, lval, non_constant_p, overflow_p, @@ -2685,19 +2718,9 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, the object is no longer under construction, and its possible 'const' semantics now apply. Make a note of this fact by marking the CONSTRUCTOR TREE_READONLY. */ - if (new_obj - && CLASS_TYPE_P (TREE_TYPE (new_obj)) - && CP_TYPE_CONST_P (TREE_TYPE (new_obj))) - { - /* Subobjects might not be stored in ctx->global->values but we - can get its CONSTRUCTOR by evaluating *this. */ - tree e = cxx_eval_constant_expression (ctx, new_obj, - /*lval*/false, - non_constant_p, - overflow_p); - if (TREE_CODE (e) == CONSTRUCTOR && !*non_constant_p) - TREE_READONLY (e) = true; - } + if (new_obj && DECL_CONSTRUCTOR_P (fun)) + cxx_set_object_constness (ctx, new_obj, /*readonly_p=*/true, + non_constant_p, overflow_p); /* Forget the saved values of the callee's SAVE_EXPRs and TARGET_EXPRs. */ @@ -3144,6 +3167,21 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t, if (r == NULL_TREE) r = fold_binary_loc (loc, code, type, lhs, rhs); + if (r == NULL_TREE + && (code == LSHIFT_EXPR || code == RSHIFT_EXPR) + && TREE_CODE (lhs) == INTEGER_CST + && TREE_CODE (rhs) == INTEGER_CST + && wi::neg_p (wi::to_wide (rhs))) + { + /* For diagnostics and -fpermissive emulate previous behavior of + handling shifts by negative amount. */ + tree nrhs = const_unop (NEGATE_EXPR, TREE_TYPE (rhs), rhs); + if (nrhs) + r = fold_binary_loc (loc, + code == LSHIFT_EXPR ? RSHIFT_EXPR : LSHIFT_EXPR, + type, lhs, nrhs); + } + if (r == NULL_TREE) { if (lhs == orig_lhs && rhs == orig_rhs) @@ -3912,6 +3950,205 @@ cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t, return error_mark_node; } +/* Helper for cxx_eval_bit_cast. + Check [bit.cast]/3 rules, bit_cast is constexpr only if the To and From + types and types of all subobjects have is_union_v<T>, is_pointer_v<T>, + is_member_pointer_v<T>, is_volatile_v<T> false and has no non-static + data members of reference type. */ + +static bool +check_bit_cast_type (const constexpr_ctx *ctx, location_t loc, tree type, + tree orig_type) +{ + if (TREE_CODE (type) == UNION_TYPE) + { + if (!ctx->quiet) + { + if (type == orig_type) + error_at (loc, "%qs is not a constant expression because %qT is " + "a union type", "__builtin_bit_cast", type); + else + error_at (loc, "%qs is not a constant expression because %qT " + "contains a union type", "__builtin_bit_cast", + orig_type); + } + return true; + } + if (TREE_CODE (type) == POINTER_TYPE) + { + if (!ctx->quiet) + { + if (type == orig_type) + error_at (loc, "%qs is not a constant expression because %qT is " + "a pointer type", "__builtin_bit_cast", type); + else + error_at (loc, "%qs is not a constant expression because %qT " + "contains a pointer type", "__builtin_bit_cast", + orig_type); + } + return true; + } + if (TREE_CODE (type) == REFERENCE_TYPE) + { + if (!ctx->quiet) + { + if (type == orig_type) + error_at (loc, "%qs is not a constant expression because %qT is " + "a reference type", "__builtin_bit_cast", type); + else + error_at (loc, "%qs is not a constant expression because %qT " + "contains a reference type", "__builtin_bit_cast", + orig_type); + } + return true; + } + if (TYPE_PTRMEM_P (type)) + { + if (!ctx->quiet) + { + if (type == orig_type) + error_at (loc, "%qs is not a constant expression because %qT is " + "a pointer to member type", "__builtin_bit_cast", + type); + else + error_at (loc, "%qs is not a constant expression because %qT " + "contains a pointer to member type", + "__builtin_bit_cast", orig_type); + } + return true; + } + if (TYPE_VOLATILE (type)) + { + if (!ctx->quiet) + { + if (type == orig_type) + error_at (loc, "%qs is not a constant expression because %qT is " + "volatile", "__builtin_bit_cast", type); + else + error_at (loc, "%qs is not a constant expression because %qT " + "contains a volatile subobject", + "__builtin_bit_cast", orig_type); + } + return true; + } + if (TREE_CODE (type) == RECORD_TYPE) + for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + if (TREE_CODE (field) == FIELD_DECL + && check_bit_cast_type (ctx, loc, TREE_TYPE (field), orig_type)) + return true; + return false; +} + +/* Subroutine of cxx_eval_constant_expression. + Attempt to evaluate a BIT_CAST_EXPR. */ + +static tree +cxx_eval_bit_cast (const constexpr_ctx *ctx, tree t, bool *non_constant_p, + bool *overflow_p) +{ + if (check_bit_cast_type (ctx, EXPR_LOCATION (t), TREE_TYPE (t), + TREE_TYPE (t)) + || check_bit_cast_type (ctx, cp_expr_loc_or_loc (TREE_OPERAND (t, 0), + EXPR_LOCATION (t)), + TREE_TYPE (TREE_OPERAND (t, 0)), + TREE_TYPE (TREE_OPERAND (t, 0)))) + { + *non_constant_p = true; + return t; + } + + tree op = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), false, + non_constant_p, overflow_p); + if (*non_constant_p) + return t; + + location_t loc = EXPR_LOCATION (t); + if (BITS_PER_UNIT != 8 || CHAR_BIT != 8) + { + if (!ctx->quiet) + sorry_at (loc, "%qs cannot be constant evaluated on the target", + "__builtin_bit_cast"); + *non_constant_p = true; + return t; + } + + if (!tree_fits_shwi_p (TYPE_SIZE_UNIT (TREE_TYPE (t)))) + { + if (!ctx->quiet) + sorry_at (loc, "%qs cannot be constant evaluated because the " + "type is too large", "__builtin_bit_cast"); + *non_constant_p = true; + return t; + } + + HOST_WIDE_INT len = tree_to_shwi (TYPE_SIZE_UNIT (TREE_TYPE (t))); + if (len < 0 || (int) len != len) + { + if (!ctx->quiet) + sorry_at (loc, "%qs cannot be constant evaluated because the " + "type is too large", "__builtin_bit_cast"); + *non_constant_p = true; + return t; + } + + unsigned char buf[64]; + unsigned char *ptr, *mask; + size_t alen = (size_t) len * 2; + if (alen <= sizeof (buf)) + ptr = buf; + else + ptr = XNEWVEC (unsigned char, alen); + mask = ptr + (size_t) len; + /* At the beginning consider everything indeterminate. */ + memset (mask, ~0, (size_t) len); + + if (native_encode_initializer (op, ptr, len, 0, mask) != len) + { + if (!ctx->quiet) + sorry_at (loc, "%qs cannot be constant evaluated because the " + "argument cannot be encoded", "__builtin_bit_cast"); + *non_constant_p = true; + if (ptr != buf) + XDELETE (ptr); + return t; + } + + tree r = NULL_TREE; + if (can_native_interpret_type_p (TREE_TYPE (t))) + r = native_interpret_expr (TREE_TYPE (t), ptr, len); + else if (TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE) + { + r = native_interpret_aggregate (TREE_TYPE (t), ptr, 0, len); + if (r != NULL_TREE) + clear_type_padding_in_mask (TREE_TYPE (t), mask); + } + + if (r != NULL_TREE) + { + for (int i = 0; i < len; i++) + if (mask[i]) + { + if (!ctx->quiet) + error_at (loc, "%qs accessing uninitialized byte at offset %d", + "__builtin_bit_cast", i); + *non_constant_p = true; + r = t; + break; + } + if (ptr != buf) + XDELETE (ptr); + return r; + } + + if (!ctx->quiet) + sorry_at (loc, "%qs cannot be constant evaluated because the " + "argument cannot be interpreted", "__builtin_bit_cast"); + *non_constant_p = true; + if (ptr != buf) + XDELETE (ptr); + return t; +} + /* Subroutine of cxx_eval_constant_expression. Evaluate a short-circuited logical expression T in the context of a given constexpr CALL. BAILOUT_VALUE is the value for @@ -6018,8 +6255,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, /* Evaluate the cleanups. */ FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup) cxx_eval_constant_expression (ctx, cleanup, false, - non_constant_p, overflow_p, - jump_target); + non_constant_p, overflow_p); } break; @@ -6030,29 +6266,20 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (!*non_constant_p) /* Also evaluate the cleanup. */ cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), true, - non_constant_p, overflow_p, - jump_target); + non_constant_p, overflow_p); break; case CLEANUP_STMT: - { - tree initial_jump_target = jump_target ? *jump_target : NULL_TREE; - r = cxx_eval_constant_expression (ctx, CLEANUP_BODY (t), lval, - non_constant_p, overflow_p, - jump_target); - if (!CLEANUP_EH_ONLY (t) && !*non_constant_p) - { - iloc_sentinel ils (loc); - /* Also evaluate the cleanup. If we weren't skipping at the - start of the CLEANUP_BODY, change jump_target temporarily - to &initial_jump_target, so that even a return or break or - continue in the body doesn't skip the cleanup. */ - cxx_eval_constant_expression (ctx, CLEANUP_EXPR (t), true, - non_constant_p, overflow_p, - jump_target ? &initial_jump_target - : NULL); - } - } + r = cxx_eval_constant_expression (ctx, CLEANUP_BODY (t), lval, + non_constant_p, overflow_p, + jump_target); + if (!CLEANUP_EH_ONLY (t) && !*non_constant_p) + { + iloc_sentinel ils (loc); + /* Also evaluate the cleanup. */ + cxx_eval_constant_expression (ctx, CLEANUP_EXPR (t), true, + non_constant_p, overflow_p); + } break; /* These differ from cxx_eval_unary_expression in that this doesn't @@ -6625,6 +6852,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, *non_constant_p = true; return t; + case BIT_CAST_EXPR: + r = cxx_eval_bit_cast (ctx, t, non_constant_p, overflow_p); + break; + default: if (STATEMENT_CODE_P (TREE_CODE (t))) { @@ -7248,7 +7479,8 @@ maybe_fold_non_dependent_expr (tree expr, tree fold_non_dependent_init (tree t, tsubst_flags_t complain /*=tf_warning_or_error*/, - bool manifestly_const_eval /*=false*/) + bool manifestly_const_eval /*=false*/, + tree object /* = NULL_TREE */) { if (t == NULL_TREE) return NULL_TREE; @@ -7256,7 +7488,7 @@ fold_non_dependent_init (tree t, if (processing_template_decl) { t = fold_non_dependent_expr_template (t, complain, - manifestly_const_eval, NULL_TREE); + manifestly_const_eval, object); /* maybe_constant_init does this stripping, so do it here too. */ if (TREE_CODE (t) == TARGET_EXPR) { @@ -7267,7 +7499,7 @@ fold_non_dependent_init (tree t, return t; } - return maybe_constant_init (t, NULL_TREE, manifestly_const_eval); + return maybe_constant_init (t, object, manifestly_const_eval); } /* Like maybe_constant_value, but returns a CONSTRUCTOR directly, rather @@ -7494,7 +7726,6 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case OVERLOAD: case TEMPLATE_ID_EXPR: case LABEL_DECL: - case LABEL_EXPR: case CASE_LABEL_EXPR: case PREDICT_EXPR: case CONST_DECL: @@ -8403,9 +8634,20 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, return false; } + case LABEL_EXPR: + t = LABEL_EXPR_LABEL (t); + if (DECL_ARTIFICIAL (t)) + return true; + else if (flags & tf_error) + error_at (loc, "label definition is not a constant expression"); + return false; + case ANNOTATE_EXPR: return RECUR (TREE_OPERAND (t, 0), rval); + case BIT_CAST_EXPR: + return RECUR (TREE_OPERAND (t, 0), rval); + /* Coroutine await, yield and return expressions are not. */ case CO_AWAIT_EXPR: case CO_YIELD_EXPR: diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 8691281..00d2f2e 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -533,9 +533,9 @@ debug_argument_list (tree args) { tree arg = TREE_VEC_ELT (args, i); if (TYPE_P (arg)) - verbatim ("ARG %qT", arg); + verbatim ("argument %qT", arg); else - verbatim ("ARG %qE", arg); + verbatim ("argument %qE", arg); } } diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index 9b9141e..fd6cda4 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -3756,7 +3756,7 @@ act_des_fn (tree orig, tree fn_type, tree coro_frame_ptr, const char* name) /* Copy selected attributes from the original function. */ TREE_USED (fn) = TREE_USED (orig); if (DECL_SECTION_NAME (orig)) - set_decl_section_name (fn, DECL_SECTION_NAME (orig)); + set_decl_section_name (fn, orig); /* Copy any alignment that the FE added. */ if (DECL_ALIGN (orig)) SET_DECL_ALIGN (fn, DECL_ALIGN (orig)); diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 064a44c..bafcaf5 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -1374,6 +1374,14 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) break; } + if (tree fndecl = cp_get_callee_fndecl (stmt)) + if (DECL_IMMEDIATE_FUNCTION_P (fndecl)) + { + gcc_assert (source_location_current_p (fndecl)); + *stmt_p = cxx_constant_value (stmt); + break; + } + if (!wtd->no_sanitize_p && sanitize_flags_p ((SANITIZE_NULL | SANITIZE_ALIGNMENT | SANITIZE_VPTR))) @@ -1552,6 +1560,11 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) cp_genericize_r, cp_walk_subtrees); break; + case BIT_CAST_EXPR: + *stmt_p = build1_loc (EXPR_LOCATION (stmt), VIEW_CONVERT_EXPR, + TREE_TYPE (stmt), TREE_OPERAND (stmt, 0)); + break; + default: if (IS_TYPE_OR_DECL_P (stmt)) *walk_subtrees = 0; diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c index a38bb0a..7ff4d39 100644 --- a/gcc/cp/cp-objcp-common.c +++ b/gcc/cp/cp-objcp-common.c @@ -391,6 +391,7 @@ names_builtin_p (const char *name) case RID_BUILTIN_HAS_ATTRIBUTE: case RID_BUILTIN_SHUFFLE: case RID_BUILTIN_LAUNDER: + case RID_BUILTIN_BIT_CAST: case RID_OFFSETOF: case RID_HAS_NOTHROW_ASSIGN: case RID_HAS_NOTHROW_CONSTRUCTOR: @@ -489,6 +490,7 @@ cp_common_init_ts (void) MARK_TS_EXP (ALIGNOF_EXPR); MARK_TS_EXP (ARROW_EXPR); MARK_TS_EXP (AT_ENCODE_EXPR); + MARK_TS_EXP (BIT_CAST_EXPR); MARK_TS_EXP (CAST_EXPR); MARK_TS_EXP (CONST_CAST_EXPR); MARK_TS_EXP (CTOR_INITIALIZER); diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index a188576..c58b233 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -233,6 +233,9 @@ DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", tcc_expression, 2) /* One of a set of overloaded functions. */ DEFTREECODE (OVERLOAD, "overload", tcc_exceptional, 0) +/* A vector of binding slots. */ +DEFTREECODE (BINDING_VECTOR, "binding_vector", tcc_exceptional, 0) + /* A pseudo-destructor, of the form "OBJECT.~DESTRUCTOR" or "OBJECT.SCOPE::~DESTRUCTOR. The first operand is the OBJECT. The second operand (if non-NULL) is the SCOPE. The third operand is @@ -437,6 +440,9 @@ DEFTREECODE (UNARY_RIGHT_FOLD_EXPR, "unary_right_fold_expr", tcc_expression, 2) DEFTREECODE (BINARY_LEFT_FOLD_EXPR, "binary_left_fold_expr", tcc_expression, 3) DEFTREECODE (BINARY_RIGHT_FOLD_EXPR, "binary_right_fold_expr", tcc_expression, 3) +/* Represents the __builtin_bit_cast (type, expr) expression. + The type is in TREE_TYPE, expression in TREE_OPERAND (bitcast, 0). */ +DEFTREECODE (BIT_CAST_EXPR, "bit_cast_expr", tcc_expression, 1) /** C++ extensions. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b98d47a..69f8ed5 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -128,12 +128,8 @@ enum cp_tree_index CPTI_EXPLICIT_VOID_LIST, CPTI_VTBL_TYPE, CPTI_VTBL_PTR_TYPE, - CPTI_STD, - CPTI_ABI, CPTI_GLOBAL, CPTI_GLOBAL_TYPE, - CPTI_CONST_TYPE_INFO_TYPE, - CPTI_TYPE_INFO_PTR_TYPE, CPTI_ABORT_FNDECL, CPTI_AGGR_TAG, CPTI_CONV_OP_MARKER, @@ -190,8 +186,28 @@ enum cp_tree_index CPTI_NOEXCEPT_FALSE_SPEC, CPTI_NOEXCEPT_DEFERRED_SPEC, + CPTI_NULLPTR, + CPTI_NULLPTR_TYPE, + + CPTI_ANY_TARG, + + CPTI_MODULE_HWM, + /* Nodes after here change during compilation, or should not be in + the module's global tree table. */ + + /* We must find these via the global namespace. */ + CPTI_STD, + CPTI_ABI, + + /* These are created at init time, but the library/headers provide + definitions. */ + CPTI_ALIGN_TYPE, + CPTI_CONST_TYPE_INFO_TYPE, + CPTI_TYPE_INFO_PTR_TYPE, CPTI_TERMINATE_FN, CPTI_CALL_UNEXPECTED_FN, + + /* These are lazily inited. */ CPTI_GET_EXCEPTION_PTR_FN, CPTI_BEGIN_CATCH_FN, CPTI_END_CATCH_FN, @@ -204,13 +220,6 @@ enum cp_tree_index CPTI_DSO_HANDLE, CPTI_DCAST, - CPTI_NULLPTR, - CPTI_NULLPTR_TYPE, - - CPTI_ALIGN_TYPE, - - CPTI_ANY_TARG, - CPTI_SOURCE_LOCATION_IMPL, CPTI_FALLBACK_DFLOAT32_TYPE, @@ -479,13 +488,14 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; CALL_EXPR_ORDERED_ARGS (in CALL_EXPR, AGGR_INIT_EXPR) DECLTYPE_FOR_REF_CAPTURE (in DECLTYPE_TYPE) CONSTRUCTOR_C99_COMPOUND_LITERAL (in CONSTRUCTOR) + DECL_MODULE_EXPORT_P (in _DECL) OVL_NESTED_P (in OVERLOAD) LAMBDA_EXPR_INSTANTIATED (in LAMBDA_EXPR) Reserved for DECL_MODULE_EXPORT (in DECL_) 4: IDENTIFIER_MARKED (IDENTIFIER_NODEs) TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, CALL_EXPR, or FIELD_DECL). - DECL_TINFO_P (in VAR_DECL) + DECL_TINFO_P (in VAR_DECL, TYPE_DECL) FUNCTION_REF_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE) OVL_LOOKUP_P (in OVERLOAD) LOOKUP_FOUND_P (in RECORD_TYPE, UNION_TYPE, ENUMERAL_TYPE, NAMESPACE_DECL) @@ -529,6 +539,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; TEMPLATE_DECL_COMPLEX_ALIAS_P (in TEMPLATE_DECL) DECL_INSTANTIATING_NSDMI_P (in a FIELD_DECL) LABEL_DECL_CDTOR (in LABEL_DECL) + USING_DECL_UNRELATED_P (in USING_DECL) 3: DECL_IN_AGGR_P. 4: DECL_C_BIT_FIELD (in a FIELD_DECL) DECL_ANON_UNION_VAR_P (in a VAR_DECL) @@ -1634,6 +1645,46 @@ check_constraint_info (tree t) #define CONSTRAINED_PARM_PROTOTYPE(NODE) \ DECL_INITIAL (TYPE_DECL_CHECK (NODE)) +/* Module defines. */ +// Too many _DECLS: FUNCTION,VAR,TYPE,TEMPLATE,CONCEPT or NAMESPACE +#define DECL_MODULE_CHECK(NODE) (NODE) + +/* In the purview of a module (including header unit). */ +#define DECL_MODULE_PURVIEW_P(N) \ + (DECL_LANG_SPECIFIC (DECL_MODULE_CHECK (N))->u.base.module_purview_p) + +/* True if the live version of the decl was imported. */ +#define DECL_MODULE_IMPORT_P(NODE) \ + (DECL_LANG_SPECIFIC (DECL_MODULE_CHECK (NODE))->u.base.module_import_p) + +/* True if this decl is in the entity hash & array. This means that + some variant was imported, even if DECL_MODULE_IMPORT_P is false. */ +#define DECL_MODULE_ENTITY_P(NODE) \ + (DECL_LANG_SPECIFIC (DECL_MODULE_CHECK (NODE))->u.base.module_entity_p) + +/* True if there are unloaded specializations keyed to this template. */ +#define DECL_MODULE_PENDING_SPECIALIZATIONS_P(NODE) \ + (DECL_LANG_SPECIFIC (TEMPLATE_DECL_CHECK (NODE)) \ + ->u.base.module_pending_p) + +/* True if this class has unloaded members. These should be loaded + before we do member lookups. */ +#define DECL_MODULE_PENDING_MEMBERS_P(NODE) \ + (DECL_LANG_SPECIFIC (TYPE_DECL_CHECK (NODE)) \ + ->u.base.module_pending_p) + +/* DECL that has attached decls for ODR-relatedness. */ +#define DECL_MODULE_ATTACHMENTS_P(NODE) \ + (DECL_LANG_SPECIFIC (TREE_CHECK2(NODE,FUNCTION_DECL,VAR_DECL))\ + ->u.base.module_pending_p) + +/* Whether this is an exported DECL. Held on any decl that can appear + at namespace scope (function, var, type, template, const or + namespace). templates copy from their template_result, consts have + it for unscoped enums. */ +#define DECL_MODULE_EXPORT_P(NODE) TREE_LANG_FLAG_3 (NODE) + + /* The list of local parameters introduced by this requires-expression, in the form of a chain of PARM_DECLs. */ #define REQUIRES_EXPR_PARMS(NODE) \ @@ -1655,6 +1706,7 @@ enum cp_tree_node_structure_enum { TS_CP_TPI, TS_CP_PTRMEM, TS_CP_OVERLOAD, + TS_CP_BINDING_VECTOR, TS_CP_BASELINK, TS_CP_TEMPLATE_DECL, TS_CP_DEFERRED_PARSE, @@ -1676,6 +1728,7 @@ union GTY((desc ("cp_tree_node_structure (&%h)"), struct template_parm_index GTY ((tag ("TS_CP_TPI"))) tpi; struct ptrmem_cst GTY ((tag ("TS_CP_PTRMEM"))) ptrmem; struct tree_overload GTY ((tag ("TS_CP_OVERLOAD"))) overload; + struct tree_binding_vec GTY ((tag ("TS_CP_BINDING_VECTOR"))) binding_vec; struct tree_baselink GTY ((tag ("TS_CP_BASELINK"))) baselink; struct tree_template_decl GTY ((tag ("TS_CP_TEMPLATE_DECL"))) template_decl; struct tree_deferred_parse GTY ((tag ("TS_CP_DEFERRED_PARSE"))) deferred_parse; @@ -2643,15 +2696,15 @@ enum lang_decl_selector /* Flags shared by all forms of DECL_LANG_SPECIFIC. Some of the flags live here only to make lang_decl_min/fn smaller. Do - not make this struct larger than 32 bits; instead, make sel smaller. */ + not make this struct larger than 32 bits. */ struct GTY(()) lang_decl_base { - /* Larger than necessary for faster access. */ - ENUM_BITFIELD(lang_decl_selector) selector : 16; + ENUM_BITFIELD(lang_decl_selector) selector : 3; ENUM_BITFIELD(languages) language : 1; unsigned use_template : 2; unsigned not_really_extern : 1; /* var or fn */ unsigned initialized_in_class : 1; /* var or fn */ + unsigned threadprivate_or_deleted_p : 1; /* var or fn */ /* anticipated_p is no longer used for anticipated_decls (fn, type or template). It is used as DECL_OMP_PRIVATIZED_MEMBER in @@ -2660,11 +2713,22 @@ struct GTY(()) lang_decl_base { unsigned friend_or_tls : 1; /* var, fn, type or template */ unsigned unknown_bound_p : 1; /* var */ unsigned odr_used : 1; /* var or fn */ - unsigned spare : 1; unsigned concept_p : 1; /* applies to vars and functions */ unsigned var_declared_inline_p : 1; /* var */ unsigned dependent_init_p : 1; /* var */ - /* 2 spare bits */ + + /* The following apply to VAR, FUNCTION, TYPE, CONCEPT, TEMPLATE, + NAMESPACE decls. */ + unsigned module_purview_p : 1; /* in module purview (not GMF) */ + unsigned module_import_p : 1; /* from an import */ + unsigned module_entity_p : 1; /* is in the entitity ary & + hash. */ + /* TEMPLATE_DECL has specializations or, + TYPE_DECL has class members yet to load, or + VAR_DECL or FUNCTION_DECL has attached decls. */ + unsigned module_pending_p : 1; + + /* 12 spare bits. */ }; /* True for DECL codes which have template info and access. */ @@ -3338,7 +3402,8 @@ struct GTY(()) lang_decl { /* 1 iff VAR_DECL node NODE is a type-info decl. This flag is set for both the primary typeinfo object and the associated NTBS name. */ -#define DECL_TINFO_P(NODE) TREE_LANG_FLAG_4 (VAR_DECL_CHECK (NODE)) +#define DECL_TINFO_P(NODE) \ + TREE_LANG_FLAG_4 (TREE_CHECK2 (NODE,VAR_DECL,TYPE_DECL)) /* 1 iff VAR_DECL node NODE is virtual table or VTT. We forward to DECL_VIRTUAL_P from the common code, as that has the semantics we @@ -3409,6 +3474,16 @@ struct GTY(()) lang_decl { /* Non zero if the using decl refers to a dependent type. */ #define USING_DECL_TYPENAME_P(NODE) DECL_LANG_FLAG_1 (USING_DECL_CHECK (NODE)) +/* True if member using decl NODE refers to a non-inherited NODE. */ +#define USING_DECL_UNRELATED_P(NODE) DECL_LANG_FLAG_2 (USING_DECL_CHECK (NODE)) + +/* True iff the CONST_DECL is a class-scope clone from C++20 using enum, + created by handle_using_decl. */ +#define CONST_DECL_USING_P(NODE) \ + (TREE_CODE (NODE) == CONST_DECL \ + && TREE_CODE (TREE_TYPE (NODE)) == ENUMERAL_TYPE \ + && DECL_CONTEXT (NODE) != TREE_TYPE (NODE)) + /* In a FUNCTION_DECL, this is nonzero if this function was defined in the class definition. We have saved away the text of the function, but have not yet processed it. */ @@ -5324,6 +5399,10 @@ extern int function_depth; in structrual_comptypes. */ extern int comparing_specializations; +/* Nonzero if we are inside eq_specializations, which affects + resolving of typenames in structural_comptypes. */ +extern int comparing_typenames; + /* In parser.c. */ /* Nonzero if we are parsing an unevaluated operand: an operand to @@ -5383,6 +5462,14 @@ public: hash_map<tree, tree> *saved; }; +/* Entry in the specialization hash table. */ +struct GTY((for_user)) spec_entry +{ + tree tmpl; /* The general template this is a specialization of. */ + tree args; /* The args for this (maybe-partial) specialization. */ + tree spec; /* The specialization itself. */ +}; + /* in class.c */ extern int current_class_depth; @@ -6455,6 +6542,7 @@ extern bool check_omp_return (void); extern tree make_typename_type (tree, tree, enum tag_types, tsubst_flags_t); extern tree build_typename_type (tree, tree, tree, tag_types); extern tree make_unbound_class_template (tree, tree, tree, tsubst_flags_t); +extern tree make_unbound_class_template_raw (tree, tree, tree); extern tree build_library_fn_ptr (const char *, tree, int); extern tree build_cp_library_fn_ptr (const char *, tree, int); extern tree push_library_fn (tree, tree, tree, int); @@ -6729,6 +6817,8 @@ extern tree unqualified_fn_lookup_error (cp_expr); extern tree make_conv_op_name (tree); extern tree build_lang_decl (enum tree_code, tree, tree); extern tree build_lang_decl_loc (location_t, enum tree_code, tree, tree); +extern bool maybe_add_lang_decl_raw (tree, bool decomp_p); +extern bool maybe_add_lang_type_raw (tree); extern void retrofit_lang_decl (tree); extern void fit_decomposition_lang_decl (tree, tree); extern tree copy_decl (tree CXX_MEM_STAT_INFO); @@ -6791,6 +6881,7 @@ extern void maybe_show_extern_c_location (void); extern bool literal_integer_zerop (const_tree); /* in pt.c */ +extern tree canonical_type_parameter (tree); extern void push_access_scope (tree); extern void pop_access_scope (tree); extern bool check_template_shadow (tree); @@ -6974,6 +7065,15 @@ extern bool copy_guide_p (const_tree); extern bool template_guide_p (const_tree); extern bool builtin_guide_p (const_tree); extern void store_explicit_specifier (tree, tree); +extern void walk_specializations (bool, + void (*)(bool, spec_entry *, + void *), + void *); +extern tree match_mergeable_specialization (bool is_decl, tree tmpl, + tree args, tree spec); +extern unsigned get_mergeable_specialization_flags (tree tmpl, tree spec); +extern void add_mergeable_specialization (tree tmpl, tree args, + tree spec, unsigned); extern tree add_outermost_template_args (tree, tree); extern tree add_extra_args (tree, tree); extern tree build_extra_args (tree, tree, tsubst_flags_t); @@ -6984,6 +7084,7 @@ extern GTY(()) vec<tree, va_gc> *unemitted_tinfo_decls; extern void init_rtti_processing (void); extern tree build_typeid (tree, tsubst_flags_t); +extern tree get_tinfo_decl_direct (tree, tree, int); extern tree get_tinfo_decl (tree); extern tree get_typeid (tree, tsubst_flags_t); extern tree build_headof (tree); @@ -6991,6 +7092,8 @@ extern tree build_dynamic_cast (location_t, tree, tree, tsubst_flags_t); extern void emit_support_tinfos (void); extern bool emit_tinfo_decl (tree); +extern unsigned get_pseudo_tinfo_index (tree); +extern tree get_pseudo_tinfo_type (unsigned); /* in search.c */ extern bool accessible_base_p (tree, tree, bool); @@ -7234,7 +7337,7 @@ extern bool cxx_omp_create_clause_info (tree, tree, bool, bool, bool, bool); extern tree baselink_for_fns (tree); extern void finish_static_assert (tree, tree, location_t, - bool); + bool, bool); extern tree finish_decltype_type (tree, bool, tsubst_flags_t); extern tree finish_trait_expr (location_t, enum cp_trait_kind, tree, tree); extern tree build_lambda_expr (void); @@ -7271,6 +7374,8 @@ extern tree finish_builtin_launder (location_t, tree, tsubst_flags_t); extern tree cp_build_vec_convert (tree, location_t, tree, tsubst_flags_t); +extern tree cp_build_bit_cast (location_t, tree, tree, + tsubst_flags_t); extern void start_lambda_scope (tree); extern void record_lambda_scope (tree); extern void record_null_lambda_scope (tree); @@ -7338,7 +7443,7 @@ extern bool is_local_temp (tree); extern tree build_aggr_init_expr (tree, tree); 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_cplus_array_type (tree, tree, int is_dep = -1); extern tree build_array_of_n_type (tree, int); extern bool array_of_runtime_bound_p (tree); extern bool vla_type_p (tree); @@ -7349,6 +7454,7 @@ 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 tree make_binding_vec (tree, unsigned clusters); inline tree ovl_first (tree) ATTRIBUTE_PURE; extern tree ovl_make (tree fn, tree next = NULL_TREE); @@ -7376,6 +7482,7 @@ extern tree bind_template_template_parm (tree, tree); extern tree array_type_nelts_total (tree); extern tree array_type_nelts_top (tree); extern bool array_of_unknown_bound_p (const_tree); +extern bool source_location_current_p (tree); extern tree break_out_target_exprs (tree, bool = false); extern tree build_ctor_subob_ref (tree, tree, tree); extern tree replace_placeholders (tree, tree, bool * = NULL); @@ -7461,7 +7568,7 @@ extern int comp_cv_qualification (const_tree, const_tree); extern int comp_cv_qualification (int, int); extern int comp_cv_qual_signature (tree, tree); extern tree cxx_sizeof_or_alignof_expr (location_t, tree, - enum tree_code, bool); + enum tree_code, bool, bool); extern tree cxx_sizeof_or_alignof_type (location_t, tree, enum tree_code, bool, bool); extern tree cxx_alignas_expr (tree); @@ -7875,9 +7982,20 @@ extern void vtv_recover_class_info (void); extern void vtv_build_vtable_verify_fndecl (void); /* In constexpr.c */ +/* Representation of entries in the constexpr function definition table. */ + +struct GTY((for_user)) constexpr_fundef { + tree decl; + tree body; + tree parms; + tree result; +}; + extern void fini_constexpr (void); extern bool literal_type_p (tree); -extern tree register_constexpr_fundef (tree, tree); +extern void maybe_save_constexpr_fundef (tree); +extern void register_constexpr_fundef (const constexpr_fundef &); +extern constexpr_fundef *retrieve_constexpr_fundef (tree); extern bool is_valid_constexpr_fn (tree, bool); extern bool check_constexpr_ctor_body (tree, tree, bool); extern tree constexpr_fn_retval (tree); @@ -7905,7 +8023,7 @@ extern tree maybe_fold_non_dependent_expr (tree, tsubst_flags_t = tf_warning_or_error); extern tree fold_non_dependent_init (tree, tsubst_flags_t = tf_warning_or_error, - bool = false); + bool = false, tree = NULL_TREE); extern tree fold_simple (tree); extern bool reduced_constant_expression_p (tree); extern bool is_instantiation_of_constexpr (tree); @@ -7972,14 +8090,16 @@ type_unknown_p (const_tree expr) inline hashval_t named_decl_hash::hash (const value_type decl) { - tree name = OVL_NAME (decl); + tree name = (TREE_CODE (decl) == BINDING_VECTOR + ? BINDING_VECTOR_NAME (decl) : OVL_NAME (decl)); return name ? IDENTIFIER_HASH_VALUE (name) : 0; } inline bool named_decl_hash::equal (const value_type existing, compare_type candidate) { - tree name = OVL_NAME (existing); + tree name = (TREE_CODE (existing) == BINDING_VECTOR + ? BINDING_VECTOR_NAME (existing) : OVL_NAME (existing)); return candidate == name; } diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c index 058b9c2..b97f70e 100644 --- a/gcc/cp/cxx-pretty-print.c +++ b/gcc/cp/cxx-pretty-print.c @@ -655,6 +655,15 @@ cxx_pretty_printer::postfix_expression (tree t) pp_right_paren (this); break; + case BIT_CAST_EXPR: + pp_cxx_ws_string (this, "__builtin_bit_cast"); + pp_left_paren (this); + type_id (TREE_TYPE (t)); + pp_comma (this); + expression (TREE_OPERAND (t, 0)); + pp_right_paren (this); + break; + case EMPTY_CLASS_EXPR: type_id (TREE_TYPE (t)); pp_left_paren (this); @@ -2666,6 +2675,12 @@ pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t) case CPTK_IS_CONSTRUCTIBLE: pp_cxx_ws_string (pp, "__is_constructible"); break; + case CPTK_IS_NOTHROW_ASSIGNABLE: + pp_cxx_ws_string (pp, "__is_nothrow_assignable"); + break; + case CPTK_IS_NOTHROW_CONSTRUCTIBLE: + pp_cxx_ws_string (pp, "__is_nothrow_constructible"); + break; default: gcc_unreachable (); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 6264884..a28e792 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2452,6 +2452,20 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) if (! DECL_COMDAT (olddecl)) DECL_COMDAT (newdecl) = 0; + if (VAR_OR_FUNCTION_DECL_P (newdecl) && DECL_LOCAL_DECL_P (newdecl)) + { + if (!DECL_LOCAL_DECL_P (olddecl)) + /* This can happen if olddecl was brought in from the + enclosing namespace via a using-decl. The new decl is + then not a block-scope extern at all. */ + DECL_LOCAL_DECL_P (newdecl) = false; + else + { + retrofit_lang_decl (newdecl); + DECL_LOCAL_DECL_ALIAS (newdecl) = DECL_LOCAL_DECL_ALIAS (olddecl); + } + } + new_template_info = NULL_TREE; if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl)) { @@ -2735,8 +2749,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) with that from NEWDECL below. */ if (DECL_LANG_SPECIFIC (olddecl)) { - gcc_assert (DECL_LANG_SPECIFIC (olddecl) - != DECL_LANG_SPECIFIC (newdecl)); + gcc_checking_assert (DECL_LANG_SPECIFIC (olddecl) + != DECL_LANG_SPECIFIC (newdecl)); ggc_free (DECL_LANG_SPECIFIC (olddecl)); } @@ -2866,7 +2880,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) done later in decl_attributes since we are called before attributes are assigned. */ if (DECL_SECTION_NAME (newdecl) != NULL) - set_decl_section_name (olddecl, DECL_SECTION_NAME (newdecl)); + set_decl_section_name (olddecl, newdecl); if (DECL_ONE_ONLY (newdecl)) { @@ -4118,6 +4132,14 @@ make_unbound_class_template (tree context, tree name, tree parm_list, return tmpl; } + return make_unbound_class_template_raw (context, name, parm_list); +} + +/* Build an UNBOUND_CLASS_TEMPLATE. */ + +tree +make_unbound_class_template_raw (tree context, tree name, tree parm_list) +{ /* Build the UNBOUND_CLASS_TEMPLATE. */ tree t = cxx_make_type (UNBOUND_CLASS_TEMPLATE); TYPE_CONTEXT (t) = FROB_CONTEXT (context); @@ -5234,6 +5256,7 @@ start_decl (const cp_declarator *declarator, bool was_public; int flags; bool alias; + tree initial; *pushed_scope_p = NULL_TREE; @@ -5258,6 +5281,10 @@ start_decl (const cp_declarator *declarator, return error_mark_node; } + /* Save the DECL_INITIAL value in case it gets clobbered to assist + with attribute validation. */ + initial = DECL_INITIAL (decl); + if (initialized) { if (! toplevel_bindings_p () @@ -5267,6 +5294,10 @@ start_decl (const cp_declarator *declarator, DECL_EXTERNAL (decl) = 0; if (toplevel_bindings_p ()) TREE_STATIC (decl) = 1; + /* Tell 'cplus_decl_attributes' this is an initialized decl, + even though we might not yet have the initializer expression. */ + if (!DECL_INITIAL (decl)) + DECL_INITIAL (decl) = error_mark_node; } alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl)) != 0; @@ -5285,6 +5316,10 @@ start_decl (const cp_declarator *declarator, /* Set attributes here so if duplicate decl, will have proper attributes. */ cplus_decl_attributes (&decl, attributes, flags); + /* Restore the original DECL_INITIAL that we may have clobbered earlier to + assist with attribute validation. */ + DECL_INITIAL (decl) = initial; + /* Dllimported symbols cannot be defined. Static data members (which can be initialized in-class and dllimported) go through grokfield, not here, so we don't need to exclude those decls when checking for @@ -6865,9 +6900,17 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups) have returned an INIT_EXPR rather than a CALL_EXPR. In that case, pull the initializer back out and pass it down into store_init_value. */ - while (TREE_CODE (init_code) == EXPR_STMT - || TREE_CODE (init_code) == CONVERT_EXPR) - init_code = TREE_OPERAND (init_code, 0); + while (true) + { + if (TREE_CODE (init_code) == EXPR_STMT + || TREE_CODE (init_code) == STMT_EXPR + || TREE_CODE (init_code) == CONVERT_EXPR) + init_code = TREE_OPERAND (init_code, 0); + else if (TREE_CODE (init_code) == BIND_EXPR) + init_code = BIND_EXPR_BODY (init_code); + else + break; + } if (TREE_CODE (init_code) == INIT_EXPR) { /* In C++20, the call to build_aggr_init could have created @@ -7926,10 +7969,9 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, make_rtl_for_nonlocal_decl (decl, init, asmspec); - /* 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. */ - abstract_virtuals_error (decl, type); + /* Check for abstractness of the type. */ + if (var_definition_p) + abstract_virtuals_error (decl, type); if (TREE_TYPE (decl) == error_mark_node) /* No initialization required. */ @@ -10335,7 +10377,7 @@ fold_sizeof_expr (tree t) else r = cxx_sizeof_or_alignof_expr (EXPR_LOCATION (t), TREE_OPERAND (t, 0), SIZEOF_EXPR, - false); + false, false); if (r == error_mark_node) r = size_one_node; return r; @@ -10701,11 +10743,6 @@ create_array_type_for_decl (tree name, tree type, tree size, location_t loc) itype = compute_array_index_type_loc (loc, name, size, tf_warning_or_error); - /* [dcl.array] - T is called the array element type; this type shall not be [...] an - abstract class type. */ - abstract_virtuals_error (name, type); - return build_cplus_array_type (type, itype); } @@ -12097,11 +12134,6 @@ grokdeclarator (const cp_declarator *declarator, /* Declaring a function type. */ - { - iloc_sentinel ils (declspecs->locations[ds_type_spec]); - abstract_virtuals_error (ACU_RETURN, type); - } - /* Pick up type qualifiers which should be applied to `this'. */ memfn_quals = declarator->u.function.qualifiers; /* Pick up virt-specifiers. */ @@ -13121,6 +13153,16 @@ grokdeclarator (const cp_declarator *declarator, if (decl_context == PARM && AUTO_IS_DECLTYPE (auto_node)) error_at (typespec_loc, "cannot declare a parameter with %<decltype(auto)%>"); + else if (tree c = CLASS_PLACEHOLDER_TEMPLATE (auto_node)) + { + auto_diagnostic_group g; + error_at (typespec_loc, + "class template placeholder %qE not permitted " + "in this context", c); + if (decl_context == PARM && cxx_dialect >= cxx20) + inform (typespec_loc, "use %<auto%> for an " + "abbreviated function template"); + } else error_at (typespec_loc, "%<auto%> parameter not permitted in this context"); @@ -13872,6 +13914,7 @@ require_complete_types_for_parms (tree parms) relayout_decl (parms); DECL_ARG_TYPE (parms) = type_passed_as (TREE_TYPE (parms)); + abstract_virtuals_error (parms, TREE_TYPE (parms)); maybe_warn_parm_abi (TREE_TYPE (parms), DECL_SOURCE_LOCATION (parms)); } @@ -14109,9 +14152,6 @@ grokparms (tree parmlist, tree *parms) type = build_pointer_type (type); TREE_TYPE (decl) = type; } - else if (abstract_virtuals_error (decl, type)) - /* Ignore any default argument. */ - init = NULL_TREE; else if (cxx_dialect < cxx17 && INDIRECT_TYPE_P (type)) { /* Before C++17 DR 393: @@ -16871,20 +16911,6 @@ record_key_method_defined (tree fndecl) } } -/* Subroutine of finish_function. - Save the body of constexpr functions for possible - future compile time evaluation. */ - -static void -maybe_save_function_definition (tree fun) -{ - if (!processing_template_decl - && DECL_DECLARED_CONSTEXPR_P (fun) - && !cp_function_chain->invalid_constexpr - && !DECL_CLONED_FUNCTION_P (fun)) - register_constexpr_fundef (fun, DECL_SAVED_TREE (fun)); -} - /* Attempt to add a fix-it hint to RICHLOC suggesting the insertion of "return *this;" immediately before its location, using FNDECL's first statement (if any) to give the indentation, if appropriate. */ @@ -16918,7 +16944,7 @@ emit_coro_helper (tree helper) allocate_struct_function (helper, false); cfun->language = ggc_cleared_alloc<language_function> (); poplevel (1, 0, 1); - maybe_save_function_definition (helper); + maybe_save_constexpr_fundef (helper); /* We must start each function with a clear fold cache. */ clear_fold_cache (); cp_fold_function (helper); @@ -17152,7 +17178,7 @@ finish_function (bool inline_p) /* Save constexpr function body before it gets munged by the NRV transformation. */ - maybe_save_function_definition (fndecl); + maybe_save_constexpr_fundef (fndecl); /* Invoke the pre-genericize plugin before we start munging things. */ if (!processing_template_decl) @@ -17427,9 +17453,6 @@ complete_vars (tree type) else ix++; } - - /* Check for pending declarations which may have abstract type. */ - complete_type_check_abstract (type); } /* If DECL is of a type which needs a cleanup, build and return an @@ -17597,6 +17620,7 @@ cp_tree_node_structure (union lang_tree_node * t) case DEFERRED_PARSE: return TS_CP_DEFERRED_PARSE; case IDENTIFIER_NODE: return TS_CP_IDENTIFIER; case LAMBDA_EXPR: return TS_CP_LAMBDA_EXPR; + case BINDING_VECTOR: return TS_CP_BINDING_VECTOR; case OVERLOAD: return TS_CP_OVERLOAD; case PTRMEM_CST: return TS_CP_PTRMEM; case STATIC_ASSERT: return TS_CP_STATIC_ASSERT; diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 396558b..d11591d 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -529,6 +529,7 @@ dump_type (cxx_pretty_printer *pp, tree t, int flags) case INTEGER_TYPE: case REAL_TYPE: case VOID_TYPE: + case OPAQUE_TYPE: case BOOLEAN_TYPE: case COMPLEX_TYPE: case VECTOR_TYPE: @@ -874,6 +875,7 @@ dump_type_prefix (cxx_pretty_printer *pp, tree t, int flags) case UNION_TYPE: case LANG_TYPE: case VOID_TYPE: + case OPAQUE_TYPE: case TYPENAME_TYPE: case COMPLEX_TYPE: case VECTOR_TYPE: @@ -997,6 +999,7 @@ dump_type_suffix (cxx_pretty_printer *pp, tree t, int flags) case UNION_TYPE: case LANG_TYPE: case VOID_TYPE: + case OPAQUE_TYPE: case TYPENAME_TYPE: case COMPLEX_TYPE: case VECTOR_TYPE: @@ -2810,6 +2813,7 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags) case ENUMERAL_TYPE: case REAL_TYPE: case VOID_TYPE: + case OPAQUE_TYPE: case BOOLEAN_TYPE: case INTEGER_TYPE: case COMPLEX_TYPE: @@ -3549,6 +3553,14 @@ function_category (tree fn) return _("In function %qs"); } +/* Disable warnings about missing quoting in GCC diagnostics for + the pp_verbatim calls. Their format strings deliberately don't + follow GCC diagnostic conventions. */ +#if __GNUC__ >= 10 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wformat-diag" +#endif + /* Report the full context of a current template instantiation, onto BUFFER. */ static void @@ -4149,12 +4161,17 @@ add_quotes (const char *content, bool show_color) pp_show_color (&tmp_pp) = show_color; /* We have to use "%<%s%>" rather than "%qs" here in order to avoid - quoting colorization bytes within the results. */ + quoting colorization bytes within the results and using either + pp_quote or pp_begin_quote doesn't work the same. */ pp_printf (&tmp_pp, "%<%s%>", content); return pp_ggc_formatted_text (&tmp_pp); } +#if __GNUC__ >= 10 +# pragma GCC diagnostic pop +#endif + /* If we had %H and %I, and hence deferred printing them, print them now, storing the result into the chunk_info for pp_format. Quote them if 'q' was provided. diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c index 0ab63bc..0f17148 100644 --- a/gcc/cp/g++spec.c +++ b/gcc/cp/g++spec.c @@ -27,12 +27,10 @@ along with GCC; see the file COPYING3. If not see #define LANGSPEC (1<<1) /* This bit is set if they did `-lm' or `-lmath'. */ #define MATHLIB (1<<2) -/* This bit is set if they did `-lrt' or equivalent. */ -#define TIMELIB (1<<3) /* This bit is set if they did `-lc'. */ -#define WITHLIBC (1<<4) +#define WITHLIBC (1<<3) /* Skip this option. */ -#define SKIPOPT (1<<5) +#define SKIPOPT (1<<4) #ifndef MATH_LIBRARY #define MATH_LIBRARY "m" @@ -41,10 +39,6 @@ along with GCC; see the file COPYING3. If not see #define MATH_LIBRARY_PROFILE MATH_LIBRARY #endif -#ifndef TIME_LIBRARY -#define TIME_LIBRARY "" -#endif - #ifndef LIBSTDCXX #define LIBSTDCXX "stdc++" #endif @@ -95,15 +89,12 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, const struct cl_decoded_option *saw_libc = NULL; /* An array used to flag each argument that needs a bit set for - LANGSPEC, MATHLIB, TIMELIB, or WITHLIBC. */ + LANGSPEC, MATHLIB, or WITHLIBC. */ int *args; /* By default, we throw on the math library if we have one. */ int need_math = (MATH_LIBRARY[0] != '\0'); - /* By default, we throw on the time library if we have one. */ - int need_time = (TIME_LIBRARY[0] != '\0'); - /* True if we saw -static. */ int static_link = 0; @@ -147,11 +138,6 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, args[i] |= MATHLIB; need_math = 0; } - else if (strcmp (arg, TIME_LIBRARY) == 0) - { - args[i] |= TIMELIB; - need_time = 0; - } else if (strcmp (arg, "c") == 0) args[i] |= WITHLIBC; else @@ -285,12 +271,6 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, saw_math = &decoded_options[i]; } - if (!saw_time && (args[i] & TIMELIB) && library > 0) - { - --j; - saw_time = &decoded_options[i]; - } - if (!saw_libc && (args[i] & WITHLIBC) && library > 0) { --j; @@ -377,13 +357,6 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, } if (saw_time) new_decoded_options[j++] = *saw_time; - else if (library > 0 && need_time) - { - generate_option (OPT_l, TIME_LIBRARY, 1, CL_DRIVER, - &new_decoded_options[j]); - added_libraries++; - j++; - } if (saw_libc) new_decoded_options[j++] = *saw_libc; if (shared_libgcc && !static_link) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index ffb84ea..0b98f33 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -3766,7 +3766,11 @@ build_new (location_t loc, vec<tree, va_gc> **placement, tree type, /* P1009: Array size deduction in new-expressions. */ const bool array_p = TREE_CODE (type) == ARRAY_TYPE; - if (*init && (array_p || (nelts && cxx_dialect >= cxx20))) + if (*init + /* If ARRAY_P, we have to deduce the array bound. For C++20 paren-init, + we have to process the parenthesized-list. But don't do it for (), + which is value-initialization, and INIT should stay empty. */ + && (array_p || (cxx_dialect >= cxx20 && nelts && !(*init)->is_empty ()))) { /* This means we have 'new T[]()'. */ if ((*init)->is_empty ()) diff --git a/gcc/cp/lang-specs.h b/gcc/cp/lang-specs.h index 0ad4a33..1388aae 100644 --- a/gcc/cp/lang-specs.h +++ b/gcc/cp/lang-specs.h @@ -40,17 +40,57 @@ along with GCC; see the file COPYING3. If not see {".tcc", "@c++-header", 0, 0, 0}, {".hh", "@c++-header", 0, 0, 0}, {"@c++-header", - "%{E|M|MM:cc1plus -E %(cpp_options) %2 %(cpp_debug_options)}" + "%{E|M|MM:cc1plus -E %{fmodules-ts:-fdirectives-only -fmodule-header}" + " %(cpp_options) %2 %(cpp_debug_options)}" + "%{!E:%{!M:%{!MM:" + " %{save-temps*|no-integrated-cpp:cc1plus -E" + " %{fmodules-ts:-fdirectives-only -fmodule-header}" + " %(cpp_options) %2 -o %{save-temps*:%b.ii} %{!save-temps*:%g.ii} \n}" + " cc1plus %{save-temps*|no-integrated-cpp:-fpreprocessed" + " %{fmodules-ts:-fdirectives-only}" + " %{save-temps*:%b.ii} %{!save-temps*:%g.ii}}" + " %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}" + " %{fmodules-ts:-fmodule-header %{fpreprocessed:-fdirectives-only}}" + " %(cc1_options) %2" + " %{!S:-o %g.s%V}" + " %{!fsyntax-only:%{!fmodule-*:%{!fmodules-*:%{!fdump-ada-spec*:" + " %{!o*:--output-pch=%i.gch}%W{o*:--output-pch=%*}}}}}}}}", + CPLUSPLUS_CPP_SPEC, 0, 0}, + {"@c++-system-header", + "%{E|M|MM:cc1plus -E" + " %{fmodules-ts:-fdirectives-only -fmodule-header=system}" + " %(cpp_options) %2 %(cpp_debug_options)}" "%{!E:%{!M:%{!MM:" " %{save-temps*|no-integrated-cpp:cc1plus -E" + " %{fmodules-ts:-fdirectives-only -fmodule-header=system}" " %(cpp_options) %2 -o %{save-temps*:%b.ii} %{!save-temps*:%g.ii} \n}" " cc1plus %{save-temps*|no-integrated-cpp:-fpreprocessed" + " %{fmodules-ts:-fdirectives-only}" " %{save-temps*:%b.ii} %{!save-temps*:%g.ii}}" " %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}" + " %{fmodules-ts:-fmodule-header=system %{fpreprocessed:-fdirectives-only}}" " %(cc1_options) %2" - " %{!fsyntax-only:%{!S:-o %g.s}" - " %{!fdump-ada-spec*:%{!o*:--output-pch=%i.gch}" - " %W{o*:--output-pch=%*}}%V}}}}", + " %{!S:-o %g.s%V}" + " %{!fsyntax-only:%{!fmodule-*:%{!fmodules-*:%{!fdump-ada-spec*:" + " %{!o*:--output-pch=%i.gch}%W{o*:--output-pch=%*}}}}}}}}", + CPLUSPLUS_CPP_SPEC, 0, 0}, + {"@c++-user-header", + "%{E|M|MM:cc1plus -E" + " %{fmodules-ts:-fdirectives-only -fmodule-header=user}" + " %(cpp_options) %2 %(cpp_debug_options)}" + "%{!E:%{!M:%{!MM:" + " %{save-temps*|no-integrated-cpp:cc1plus -E" + " %{fmodules-ts:-fdirectives-only -fmodule-header=user}" + " %(cpp_options) %2 -o %{save-temps*:%b.ii} %{!save-temps*:%g.ii} \n}" + " cc1plus %{save-temps*|no-integrated-cpp:-fpreprocessed" + " %{fmodules-ts:-fdirectives-only}" + " %{save-temps*:%b.ii} %{!save-temps*:%g.ii}}" + " %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}" + " %{fmodules-ts:-fmodule-header=user %{fpreprocessed:-fdirectives-only}}" + " %(cc1_options) %2" + " %{!S:-o %g.s%V}" + " %{!fsyntax-only:%{!fmodule-*:%{!fmodules-*:%{!fdump-ada-spec*:" + " %{!o*:--output-pch=%i.gch}%W{o*:--output-pch=%*}}}}}}}}", CPLUSPLUS_CPP_SPEC, 0, 0}, {"@c++", "%{E|M|MM:cc1plus -E %(cpp_options) %2 %(cpp_debug_options)}" @@ -60,11 +100,14 @@ along with GCC; see the file COPYING3. If not see " cc1plus %{save-temps*|no-integrated-cpp:-fpreprocessed" " %{save-temps*:%b.ii} %{!save-temps*:%g.ii}}" " %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}" - " %(cc1_options) %2" - " %{!fsyntax-only:%(invoke_as)}}}}", + " %(cc1_options) %2" + " %{fmodule-only:%{!S:-o %g.s%V}}" + " %{!fsyntax-only:%{!fmodule-only:%(invoke_as)}}}}}", CPLUSPLUS_CPP_SPEC, 0, 0}, {".ii", "@c++-cpp-output", 0, 0, 0}, {"@c++-cpp-output", "%{!E:%{!M:%{!MM:" " cc1plus -fpreprocessed %i %(cc1_options) %2" - " %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0}, + " %{fmodule-only:%{!S:-o %g.s%V}}" + " %{!fsyntax-only:%{!fmodule-only:%{!fmodule-header*:" + " %(invoke_as)}}}}}}", 0, 0, 0}, diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 8a69bc4..795f571 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -235,6 +235,8 @@ init_reswords (void) mask |= D_CXX_CONCEPTS; if (!flag_coroutines) mask |= D_CXX_COROUTINES; + if (!flag_modules) + mask |= D_CXX_MODULES; if (!flag_tm) mask |= D_TRANSMEM; if (!flag_char8_t) @@ -678,7 +680,7 @@ build_lang_decl_loc (location_t loc, enum tree_code code, tree name, tree type) /* Maybe add a raw lang_decl to T, a decl. Return true if it needed one. */ -static bool +bool maybe_add_lang_decl_raw (tree t, bool decomp_p) { size_t size; @@ -831,8 +833,7 @@ copy_lang_type (tree node) if (! TYPE_LANG_SPECIFIC (node)) return; - struct lang_type *lt - = (struct lang_type *) ggc_internal_alloc (sizeof (struct lang_type)); + auto *lt = (struct lang_type *) ggc_internal_alloc (sizeof (struct lang_type)); memcpy (lt, TYPE_LANG_SPECIFIC (node), (sizeof (struct lang_type))); TYPE_LANG_SPECIFIC (node) = lt; @@ -858,15 +859,15 @@ copy_type (tree type MEM_STAT_DECL) /* Add a raw lang_type to T, a type, should it need one. */ -static bool +bool maybe_add_lang_type_raw (tree t) { if (!RECORD_OR_UNION_CODE_P (TREE_CODE (t))) return false; - TYPE_LANG_SPECIFIC (t) - = (struct lang_type *) (ggc_internal_cleared_alloc - (sizeof (struct lang_type))); + auto *lt = (struct lang_type *) (ggc_internal_cleared_alloc + (sizeof (struct lang_type))); + TYPE_LANG_SPECIFIC (t) = lt; if (GATHER_STATISTICS) { diff --git a/gcc/cp/logic.cc b/gcc/cp/logic.cc index 6701488..5592680 100644 --- a/gcc/cp/logic.cc +++ b/gcc/cp/logic.cc @@ -303,9 +303,10 @@ debug (formula& f) { for (formula::iterator i = f.begin(); i != f.end(); ++i) { - verbatim ("((("); + /* Format punctuators via %s to avoid -Wformat-diag. */ + verbatim ("%s", "((("); debug (*i); - verbatim (")))"); + verbatim ("%s", ")))"); } } diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 9fd3001..5548e51 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -3049,11 +3049,30 @@ write_expression (tree expr) else goto normal_expr; } - else if (TREE_CODE (expr) == ALIGNOF_EXPR - && TYPE_P (TREE_OPERAND (expr, 0))) + else if (TREE_CODE (expr) == ALIGNOF_EXPR) { - write_string ("at"); - write_type (TREE_OPERAND (expr, 0)); + if (!ALIGNOF_EXPR_STD_P (expr)) + { + if (abi_warn_or_compat_version_crosses (15)) + G.need_abi_warning = true; + if (abi_version_at_least (15)) + { + /* We used to mangle __alignof__ like alignof. */ + write_string ("v111__alignof__"); + if (TYPE_P (TREE_OPERAND (expr, 0))) + write_type (TREE_OPERAND (expr, 0)); + else + write_expression (TREE_OPERAND (expr, 0)); + return; + } + } + if (TYPE_P (TREE_OPERAND (expr, 0))) + { + write_string ("at"); + write_type (TREE_OPERAND (expr, 0)); + } + else + goto normal_expr; } else if (code == SCOPE_REF || code == BASELINK) diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 16e7635..4de192f 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -351,7 +351,7 @@ use_thunk (tree thunk_fndecl, bool emit_p) resolve_unique_section (thunk_fndecl, 0, flag_function_sections); /* Output the thunk into the same section as function. */ - set_decl_section_name (thunk_fndecl, DECL_SECTION_NAME (fn)); + set_decl_section_name (thunk_fndecl, fn); symtab_node::get (thunk_fndecl)->implicit_section = symtab_node::get (fn)->implicit_section; } diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc new file mode 100644 index 0000000..596061b --- /dev/null +++ b/gcc/cp/module.cc @@ -0,0 +1,21 @@ +/* C++ modules. Experimental! + Copyright (C) 2017-2020 Free Software Foundation, Inc. + Written by Nathan Sidwell <nathan@acm.org> while at FaceBook + + 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/>. */ + +/* This file intentionally left empty. */ diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 410ec59..c87d151 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -2125,6 +2125,10 @@ supplement_binding_1 (cxx_binding *binding, tree decl) region to refer only to the namespace to which it already refers. */ ok = false; + else if (TREE_CODE (bval) == USING_DECL + && CONST_DECL_USING_P (decl)) + /* Let the clone hide the using-decl that introduced it. */ + binding->value = decl; else { if (!error_operand_p (bval)) @@ -3287,12 +3291,17 @@ begin_scope (scope_kind kind, tree entity) case sk_cond: case sk_class: case sk_scoped_enum: - case sk_function_parms: case sk_transaction: case sk_omp: scope->keep = keep_next_level_flag; break; + case sk_function_parms: + scope->keep = keep_next_level_flag; + if (entity) + scope->immediate_fn_ctx_p = DECL_IMMEDIATE_FUNCTION_P (entity); + break; + case sk_namespace: NAMESPACE_LEVEL (entity) = scope; break; @@ -4540,43 +4549,66 @@ push_class_level_binding (tree name, tree x) /* Process and lookup a using decl SCOPE::lookup.name, filling in lookup.values & lookup.type. Return true if ok. */ -static bool +static tree lookup_using_decl (tree scope, name_lookup &lookup) { tree current = current_scope (); bool dependent_p = false; + tree binfo = NULL_TREE; + base_kind b_kind = bk_not_base; + + /* Because C++20 breaks the invariant that only member using-decls + refer to members and only non-member using-decls refer to + non-members, we first do the lookups, and then do validation that + what we found is ok. */ + + if (TREE_CODE (scope) == ENUMERAL_TYPE + && cxx_dialect < cxx20 + && UNSCOPED_ENUM_P (scope) + && !TYPE_FUNCTION_SCOPE_P (scope)) + { + /* PR c++/60265 argued that since C++11 added explicit enum scope, we + should allow it as meaning the enclosing scope. I don't see any + justification for this in C++11, but let's keep allowing it. */ + tree ctx = CP_TYPE_CONTEXT (scope); + if (CLASS_TYPE_P (ctx) == CLASS_TYPE_P (current)) + scope = ctx; + } if (TREE_CODE (scope) == NAMESPACE_DECL) { /* Naming a namespace member. */ - if (TYPE_P (current)) + qualified_namespace_lookup (scope, &lookup); + + if (TYPE_P (current) + && (!lookup.value + || lookup.type + || cxx_dialect < cxx20 + || TREE_CODE (lookup.value) != CONST_DECL)) { error ("using-declaration for non-member at class scope"); - return false; + return NULL_TREE; } - - qualified_namespace_lookup (scope, &lookup); } else if (TREE_CODE (scope) == ENUMERAL_TYPE) { - error ("using-declaration may not name enumerator %<%E::%D%>", - scope, lookup.name); - return false; + /* Naming an enumeration member. */ + if (cxx_dialect < cxx20) + error ("%<using%> with enumeration scope %q#T " + "only available with %<-std=c++20%> or %<-std=gnu++20%>", + scope); + lookup.value = lookup_enumerator (scope, lookup.name); } else { - /* Naming a class member. */ - if (!TYPE_P (current)) - { - error ("using-declaration for member at non-class scope"); - return false; - } + /* Naming a class member. This is awkward in C++20, because we + might be naming an enumerator of an unrelated class. */ - /* Make sure the name is not invalid */ + /* You cannot using-decl a destructor. */ if (TREE_CODE (lookup.name) == BIT_NOT_EXPR) { error ("%<%T::%D%> names destructor", scope, lookup.name); - return false; + return NULL_TREE; } /* Using T::T declares inheriting ctors, even if T is a typedef. */ @@ -4584,91 +4616,151 @@ lookup_using_decl (tree scope, name_lookup &lookup) && (lookup.name == TYPE_IDENTIFIER (scope) || constructor_name_p (lookup.name, scope))) { + if (!TYPE_P (current)) + { + error ("non-member using-declaration names constructor of %qT", + scope); + return NULL_TREE; + } maybe_warn_cpp0x (CPP0X_INHERITING_CTORS); lookup.name = ctor_identifier; CLASSTYPE_NON_AGGREGATE (current) = true; } - /* Cannot introduce a constructor name. */ - if (constructor_name_p (lookup.name, current)) + if (!MAYBE_CLASS_TYPE_P (scope)) + ; + else if (TYPE_P (current)) { - error ("%<%T::%D%> names constructor in %qT", - scope, lookup.name, current); - return false; - } - - /* Member using decls finish processing when completing the - class. */ - /* From [namespace.udecl]: - - A using-declaration used as a member-declaration shall refer - to a member of a base class of the class being defined. + dependent_p = dependent_scope_p (scope); + if (!dependent_p) + { + binfo = lookup_base (current, scope, ba_any, &b_kind, tf_none); + gcc_checking_assert (b_kind >= bk_not_base); - In general, we cannot check this constraint in a template - because we do not know the entire set of base classes of the - current class type. Morover, if SCOPE is dependent, it might - match a non-dependent base. */ + if (lookup.name == ctor_identifier) + { + /* Even if there are dependent bases, SCOPE will not + be direct base, no matter. */ + if (b_kind < bk_proper_base || !binfo_direct_p (binfo)) + { + error ("%qT is not a direct base of %qT", scope, current); + return NULL_TREE; + } + } + else if (b_kind < bk_proper_base) + binfo = TYPE_BINFO (scope); + else if (IDENTIFIER_CONV_OP_P (lookup.name) + && dependent_type_p (TREE_TYPE (lookup.name))) + dependent_p = true; + } + } + else + binfo = TYPE_BINFO (scope); - dependent_p = dependent_scope_p (scope); if (!dependent_p) { - base_kind b_kind; - tree binfo = lookup_base (current, scope, ba_any, &b_kind, - tf_warning_or_error); - if (b_kind < bk_proper_base) + if (binfo) + lookup.value = lookup_member (binfo, lookup.name, /*protect=*/2, + /*want_type=*/false, tf_none); + + tree saved_value = lookup.value; + if (lookup.value + && b_kind < bk_proper_base) { - /* If there are dependent bases, scope might resolve at - instantiation time, even if it isn't exactly one of - the dependent bases. */ - if (b_kind == bk_same_type || !any_dependent_bases_p ()) + if (cxx_dialect >= cxx20 + && TREE_CODE (lookup.value) == CONST_DECL) { - error_not_base_type (scope, current); - return false; + /* Using an unrelated enum; check access here rather + than separately for class and non-class using. */ + perform_or_defer_access_check + (binfo, lookup.value, lookup.value, tf_warning_or_error); + /* And then if this is a copy from handle_using_decl, look + through to the original enumerator. */ + if (CONST_DECL_USING_P (lookup.value)) + lookup.value = DECL_ABSTRACT_ORIGIN (lookup.value); } - /* Treat as-if dependent. */ - dependent_p = true; + else + lookup.value = NULL_TREE; } - else if (lookup.name == ctor_identifier && !binfo_direct_p (binfo)) + + if (!lookup.value) { - error ("cannot inherit constructors from indirect base %qT", - scope); - return false; + if (!TYPE_P (current)) + { + error ("using-declaration for member at non-class scope"); + return NULL_TREE; + } + + if (b_kind < bk_proper_base) + { + if (b_kind == bk_not_base && any_dependent_bases_p ()) + /* Treat as-if dependent. */ + dependent_p = true; + else + { + auto_diagnostic_group g; + error_not_base_type (scope, current); + if (saved_value && DECL_IMPLICIT_TYPEDEF_P (saved_value) + && (TREE_CODE (TREE_TYPE (saved_value)) + == ENUMERAL_TYPE)) + inform (input_location, + "did you mean %<using enum %T::%D%>?", + scope, lookup.name); + return NULL_TREE; + } + } } - else if (IDENTIFIER_CONV_OP_P (lookup.name) - && dependent_type_p (TREE_TYPE (lookup.name))) - dependent_p = true; - else - lookup.value = lookup_member (binfo, lookup.name, 0, - false, tf_warning_or_error); } } - if (!dependent_p) + /* Did we find anything sane? */ + if (dependent_p) + ; + else if (!lookup.value) { - if (!lookup.value) - { - error ("%qD has not been declared in %qE", lookup.name, scope); - return false; - } + error ("%qD has not been declared in %qD", lookup.name, scope); + return NULL_TREE; + } + else if (TREE_CODE (lookup.value) == TREE_LIST + /* We can (independently) have ambiguous implicit typedefs. */ + || (lookup.type && TREE_CODE (lookup.type) == TREE_LIST)) + { + error ("reference to %qD is ambiguous", lookup.name); + print_candidates (TREE_CODE (lookup.value) == TREE_LIST + ? lookup.value : lookup.type); + return NULL_TREE; + } + else if (TREE_CODE (lookup.value) == NAMESPACE_DECL) + { + error ("using-declaration may not name namespace %qD", lookup.value); + return NULL_TREE; + } - if (TREE_CODE (lookup.value) == TREE_LIST - /* We can (independently) have ambiguous implicit typedefs. */ - || (lookup.type && TREE_CODE (lookup.type) == TREE_LIST)) - { - error ("reference to %qD is ambiguous", lookup.name); - print_candidates (TREE_CODE (lookup.value) == TREE_LIST - ? lookup.value : lookup.type); - return false; - } + if (TYPE_P (current)) + { + /* In class scope. */ - if (TREE_CODE (lookup.value) == NAMESPACE_DECL) + /* Cannot introduce a constructor name. */ + if (constructor_name_p (lookup.name, current)) { - error ("using-declaration may not name namespace %qD", lookup.value); - return false; + error ("%<%T::%D%> names constructor in %qT", + scope, lookup.name, current); + return NULL_TREE; } + + if (lookup.value && BASELINK_P (lookup.value)) + /* The binfo from which the functions came does not matter. */ + lookup.value = BASELINK_FUNCTIONS (lookup.value); } - return true; + tree using_decl = build_lang_decl (USING_DECL, lookup.name, NULL_TREE); + USING_DECL_SCOPE (using_decl) = scope; + USING_DECL_DECLS (using_decl) = lookup.value; + DECL_DEPENDENT_P (using_decl) = dependent_p; + if (TYPE_P (current) && b_kind == bk_not_base) + USING_DECL_UNRELATED_P (using_decl) = true; + + return using_decl; } /* Process "using SCOPE::NAME" in a class scope. Return the @@ -4682,20 +4774,7 @@ do_class_using_decl (tree scope, tree name) return NULL_TREE; name_lookup lookup (name); - if (!lookup_using_decl (scope, lookup)) - return NULL_TREE; - - tree found = lookup.value; - if (found && BASELINK_P (found)) - /* The binfo from which the functions came does not matter. */ - found = BASELINK_FUNCTIONS (found); - - tree using_decl = build_lang_decl (USING_DECL, lookup.name, NULL_TREE); - USING_DECL_SCOPE (using_decl) = scope; - USING_DECL_DECLS (using_decl) = found; - DECL_DEPENDENT_P (using_decl) = !found; - - return using_decl; + return lookup_using_decl (scope, lookup); } @@ -5076,7 +5155,8 @@ finish_nonmember_using_decl (tree scope, tree name) name_lookup lookup (name); - if (!lookup_using_decl (scope, lookup)) + tree using_decl = lookup_using_decl (scope, lookup); + if (!using_decl) return; /* Emit debug info. */ @@ -5105,8 +5185,6 @@ finish_nonmember_using_decl (tree scope, tree name) } else { - tree using_decl = build_lang_decl (USING_DECL, lookup.name, NULL_TREE); - USING_DECL_SCOPE (using_decl) = scope; add_decl_expr (using_decl); cxx_binding *binding = find_local_binding (current_binding_level, name); diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index 6d18539..9cc8a42 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -68,6 +68,125 @@ struct GTY(()) cxx_saved_binding { tree real_type_value; }; +/* To support lazy module loading, we squirrel away a section number + (and a couple of flags) in the binding slot of unloaded bindings. + We rely on pointers being aligned and setting the bottom bit to + mark a lazy value. GTY doesn't like an array of union, so we have + a containing struct. */ + +struct GTY(()) binding_slot { + union GTY((desc ("%1.is_lazy ()"))) binding_slot_lazy { + tree GTY((tag ("false"))) binding; + } u; + + operator tree & () + { + gcc_checking_assert (!is_lazy ()); + return u.binding; + } + binding_slot &operator= (tree t) + { + u.binding = t; + return *this; + } + bool is_lazy () const + { + return bool (uintptr_t (u.binding) & 1); + } + void set_lazy (unsigned snum) + { + gcc_checking_assert (!u.binding); + u.binding = tree (uintptr_t ((snum << 1) | 1)); + } + void or_lazy (unsigned snum) + { + gcc_checking_assert (is_lazy ()); + u.binding = tree (uintptr_t (u.binding) | (snum << 1)); + } + unsigned get_lazy () const + { + gcc_checking_assert (is_lazy ()); + return unsigned (uintptr_t (u.binding) >> 1); + } +}; + +/* Bindings for modules are held in a sparse array. There is always a + current TU slot, others are allocated as needed. By construction + of the importing mechanism we only ever need to append to the + array. Rather than have straight index/slot tuples, we bunch them + up for greater packing. + + The cluster representation packs well on a 64-bit system. */ + +#define BINDING_VECTOR_SLOTS_PER_CLUSTER 2 +struct binding_index { + unsigned short base; + unsigned short span; +}; + +struct GTY(()) binding_cluster +{ + binding_index GTY((skip)) indices[BINDING_VECTOR_SLOTS_PER_CLUSTER]; + binding_slot slots[BINDING_VECTOR_SLOTS_PER_CLUSTER]; +}; + +/* These two fields overlay lang flags. So don't use those. */ +#define BINDING_VECTOR_ALLOC_CLUSTERS(NODE) \ + (BINDING_VECTOR_CHECK (NODE)->base.u.dependence_info.clique) +#define BINDING_VECTOR_NUM_CLUSTERS(NODE) \ + (BINDING_VECTOR_CHECK (NODE)->base.u.dependence_info.base) +#define BINDING_VECTOR_CLUSTER_BASE(NODE) \ + (((tree_binding_vec *)BINDING_VECTOR_CHECK (NODE))->vec) +#define BINDING_VECTOR_CLUSTER_LAST(NODE) \ + (&BINDING_VECTOR_CLUSTER (NODE, BINDING_VECTOR_NUM_CLUSTERS (NODE) - 1)) +#define BINDING_VECTOR_CLUSTER(NODE,IX) \ + (((tree_binding_vec *)BINDING_VECTOR_CHECK (NODE))->vec[IX]) + +struct GTY(()) tree_binding_vec { + struct tree_base base; + tree name; + binding_cluster GTY((length ("%h.base.u.dependence_info.base"))) vec[1]; +}; + +/* The name of a module vector. */ +#define BINDING_VECTOR_NAME(NODE) \ + (((tree_binding_vec *)BINDING_VECTOR_CHECK (NODE))->name) + +/* tree_binding_vec does uses base.u.dependence_info.base field for + length. It does not have lang_flag etc available! */ + +/* These two flags note if a module-vector contains deduplicated + bindings (i.e. multiple declarations in different imports). */ +/* This binding contains duplicate references to a global module + entity. */ +#define BINDING_VECTOR_GLOBAL_DUPS_P(NODE) \ + (BINDING_VECTOR_CHECK (NODE)->base.static_flag) +/* This binding contains duplicate references to a partioned module + entity. */ +#define BINDING_VECTOR_PARTITION_DUPS_P(NODE) \ + (BINDING_VECTOR_CHECK (NODE)->base.volatile_flag) + +/* These two flags indicate the provenence of the bindings on this + particular vector slot. We can of course determine this from slot + number, but that's a relatively expensive lookup. This avoids + that when iterating. */ +/* This slot is part of the global module (a header unit). */ +#define MODULE_BINDING_GLOBAL_P(NODE) \ + (OVERLOAD_CHECK (NODE)->base.static_flag) +/* This slot is part of the current module (a partition or primary). */ +#define MODULE_BINDING_PARTITION_P(NODE) \ + (OVERLOAD_CHECK (NODE)->base.volatile_flag) + +/* There are specializations of a template keyed to this binding. */ +#define BINDING_VECTOR_PENDING_SPECIALIZATIONS_P(NODE) \ + (BINDING_VECTOR_CHECK (NODE)->base.public_flag) +/* The key is in a header unit (not a named module partition or + primary). */ +#define BINDING_VECTOR_PENDING_IS_HEADER_P(NODE) \ + (BINDING_VECTOR_CHECK (NODE)->base.protected_flag) +/* The key is in a named module (primary or partition). */ +#define BINDING_VECTOR_PENDING_IS_PARTITION_P(NODE) \ + (BINDING_VECTOR_CHECK (NODE)->base.private_flag) extern tree identifier_type_value (tree); extern void set_identifier_type_value (tree, tree); diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index 00621d6..127d7fa 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -512,7 +512,7 @@ maybe_clone_body (tree fn) DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn); DECL_ATTRIBUTES (clone) = copy_list (DECL_ATTRIBUTES (fn)); DECL_DISREGARD_INLINE_LIMITS (clone) = DECL_DISREGARD_INLINE_LIMITS (fn); - set_decl_section_name (clone, DECL_SECTION_NAME (fn)); + set_decl_section_name (clone, fn); /* Adjust the parameter names and locations. */ parm = DECL_ARGUMENTS (fn); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 9c08c0e..103567c 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -808,6 +808,14 @@ make_location (location_t caret, location_t start, cp_lexer *lexer) return make_location (caret, start, t->location); } +/* Overload for make_location taking tokens instead of locations. */ + +static inline location_t +make_location (cp_token *caret, cp_token *start, cp_token *end) +{ + return make_location (caret->location, start->location, end->location); +} + /* nonzero if we are presently saving tokens. */ static inline int @@ -2187,7 +2195,7 @@ static void cp_parser_already_scoped_statement static void cp_parser_declaration_seq_opt (cp_parser *); static void cp_parser_declaration - (cp_parser *); + (cp_parser *, tree); static void cp_parser_toplevel_declaration (cp_parser *); static void cp_parser_block_declaration @@ -2233,12 +2241,14 @@ static bool cp_parser_using_declaration (cp_parser *, bool); static void cp_parser_using_directive (cp_parser *); +static void cp_parser_using_enum + (cp_parser *); static tree cp_parser_alias_declaration (cp_parser *); static void cp_parser_asm_definition (cp_parser *); static void cp_parser_linkage_specification - (cp_parser *); + (cp_parser *, tree); static void cp_parser_static_assert (cp_parser *, bool); static tree cp_parser_decltype @@ -5804,8 +5814,11 @@ cp_parser_primary_expression (cp_parser *parser, if ((parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN) && local_variable_p (decl)) { - error_at (id_expression.get_location (), - "local variable %qD may not appear in this context", + const char *msg + = (TREE_CODE (decl) == PARM_DECL + ? _("parameter %qD may not appear in this context") + : _("local variable %qD may not appear in this context")); + error_at (id_expression.get_location (), msg, decl.get_value ()); return error_mark_node; } @@ -7237,6 +7250,32 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, tf_warning_or_error); } + case RID_BUILTIN_BIT_CAST: + { + tree expression; + tree type; + /* Consume the `__builtin_bit_cast' token. */ + cp_lexer_consume_token (parser->lexer); + /* Look for the opening `('. */ + matching_parens parens; + parens.require_open (parser); + location_t type_location + = cp_lexer_peek_token (parser->lexer)->location; + /* Parse the type-id. */ + { + type_id_in_expr_sentinel s (parser); + type = cp_parser_type_id (parser); + } + /* Look for the `,'. */ + cp_parser_require (parser, CPP_COMMA, RT_COMMA); + /* Now, parse the assignment-expression. */ + expression = cp_parser_assignment_expression (parser); + /* Look for the closing `)'. */ + parens.require_close (parser); + return cp_build_bit_cast (type_location, type, expression, + tf_warning_or_error); + } + default: { tree type; @@ -8335,8 +8374,8 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk, "ISO C++ does not allow %<alignof%> " "with a non-type"); - ret = cxx_sizeof_or_alignof_expr (compound_loc, - operand, op, true); + ret = cxx_sizeof_or_alignof_expr (compound_loc, operand, op, + std_alignof, true); } /* For SIZEOF_EXPR, just issue diagnostics, but keep SIZEOF_EXPR with the original operand. */ @@ -9372,7 +9411,8 @@ maybe_add_cast_fixit (rich_location *rich_loc, location_t open_paren_loc, /* Replace the open paren with "CAST_SUGGESTION<". */ pretty_printer pp; - pp_printf (&pp, "%s<", cast_suggestion); + pp_string (&pp, cast_suggestion); + pp_less (&pp); rich_loc->add_fixit_replace (open_paren_loc, pp_formatted_text (&pp)); /* Replace the close paren with "> (". */ @@ -10594,6 +10634,8 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword) lambda-expression: lambda-introducer lambda-declarator [opt] compound-statement + lambda-introducer < template-parameter-list > requires-clause [opt] + lambda-declarator [opt] compound-statement Returns a representation of the expression. */ @@ -11051,13 +11093,11 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) /* Parse the (optional) middle of a lambda expression. lambda-declarator: - < template-parameter-list [opt] > - requires-clause [opt] - ( parameter-declaration-clause [opt] ) - attribute-specifier [opt] + ( parameter-declaration-clause ) decl-specifier-seq [opt] - exception-specification [opt] - lambda-return-type-clause [opt] + noexcept-specifier [opt] + attribute-specifier-seq [opt] + trailing-return-type [opt] requires-clause [opt] LAMBDA_EXPR is the current representation of the lambda expression. */ @@ -11207,8 +11247,6 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) trailing-return-type in case of decltype. */ pop_bindings_and_leave_scope (); } - else if (template_param_list != NULL_TREE) // generate diagnostic - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); /* Create the function call operator. @@ -12671,8 +12709,15 @@ do_range_for_auto_deduction (tree decl, tree range_expr) for (const auto &x : range) - if this version doesn't make a copy. DECL is the RANGE_DECL; EXPR is the - *__for_begin expression. + if this version doesn't make a copy. + + This function also warns when the loop variable is initialized with + a value of a different type resulting in a copy: + + int arr[10]; + for (const double &x : arr) + + DECL is the RANGE_DECL; EXPR is the *__for_begin expression. This function is never called when processing_template_decl is on. */ static void @@ -12690,7 +12735,22 @@ warn_for_range_copy (tree decl, tree expr) if (TYPE_REF_P (type)) { - /* TODO: Implement reference warnings. */ + if (glvalue_p (expr) && !ref_conv_binds_directly_p (type, expr)) + { + auto_diagnostic_group d; + if (warning_at (loc, OPT_Wrange_loop_construct, + "loop variable %qD of type %qT binds to a temporary " + "constructed from type %qT", decl, type, + TREE_TYPE (expr))) + { + tree ref = cp_build_qualified_type (TREE_TYPE (expr), + TYPE_QUAL_CONST); + ref = cp_build_reference_type (ref, /*rval*/false); + inform (loc, "use non-reference type %qT to make the copy " + "explicit or %qT to prevent copying", + non_reference (type), ref); + } + } return; } else if (!CP_TYPE_CONST_P (type)) @@ -13496,7 +13556,7 @@ cp_parser_declaration_seq_opt (cp_parser* parser) __extension__ declaration */ static void -cp_parser_declaration (cp_parser* parser) +cp_parser_declaration (cp_parser* parser, tree prefix_attrs) { int saved_pedantic; @@ -13504,7 +13564,7 @@ cp_parser_declaration (cp_parser* parser) if (cp_parser_extension_opt (parser, &saved_pedantic)) { /* Parse the qualified declaration. */ - cp_parser_declaration (parser); + cp_parser_declaration (parser, prefix_attrs); /* Restore the PEDANTIC flag. */ pedantic = saved_pedantic; @@ -13521,11 +13581,52 @@ cp_parser_declaration (cp_parser* parser) tree attributes = NULL_TREE; + /* Conditionally, allow attributes to precede a linkage specification. */ + if (token1->keyword == RID_ATTRIBUTE) + { + cp_lexer_save_tokens (parser->lexer); + attributes = cp_parser_attributes_opt (parser); + cp_token *t1 = cp_lexer_peek_token (parser->lexer); + cp_token *t2 = (t1->type == CPP_EOF + ? t1 : cp_lexer_peek_nth_token (parser->lexer, 2)); + if (t1->keyword == RID_EXTERN + && cp_parser_is_pure_string_literal (t2)) + { + cp_lexer_commit_tokens (parser->lexer); + /* We might have already been here. */ + if (!c_dialect_objc ()) + { + location_t where = get_finish (t2->location); + warning_at (token1->location, OPT_Wattributes, "attributes are" + " not permitted in this position"); + where = linemap_position_for_loc_and_offset (line_table, + where, 1); + inform (where, "attributes may be inserted here"); + attributes = NULL_TREE; + } + token1 = t1; + token2 = t2; + } + else + { + cp_lexer_rollback_tokens (parser->lexer); + attributes = NULL_TREE; + } + } + /* If we already had some attributes, and we've added more, then prepend. + Otherwise attributes just contains any that we just read. */ + if (prefix_attrs) + { + if (attributes) + TREE_CHAIN (prefix_attrs) = attributes; + attributes = prefix_attrs; + } + /* If the next token is `extern' and the following token is a string literal, then we have a linkage specification. */ if (token1->keyword == RID_EXTERN && cp_parser_is_pure_string_literal (token2)) - cp_parser_linkage_specification (parser); + cp_parser_linkage_specification (parser, attributes); /* If the next token is `template', then we have either a template declaration, an explicit instantiation, or an explicit specialization. */ @@ -13575,7 +13676,7 @@ cp_parser_declaration (cp_parser* parser) cp_parser_namespace_definition (parser); /* Objective-C++ declaration/definition. */ else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1->keyword)) - cp_parser_objc_declaration (parser, NULL_TREE); + cp_parser_objc_declaration (parser, attributes); else if (c_dialect_objc () && token1->keyword == RID_ATTRIBUTE && cp_parser_objc_valid_prefix_attributes (parser, &attributes)) @@ -13617,7 +13718,7 @@ cp_parser_toplevel_declaration (cp_parser* parser) } else /* Parse the declaration itself. */ - cp_parser_declaration (parser); + cp_parser_declaration (parser, NULL_TREE); } /* Parse a block-declaration. @@ -13687,6 +13788,8 @@ cp_parser_block_declaration (cp_parser *parser, token2 = cp_lexer_peek_nth_token (parser->lexer, 2); if (token2->keyword == RID_NAMESPACE) cp_parser_using_directive (parser); + else if (token2->keyword == RID_ENUM) + cp_parser_using_enum (parser); /* If the second token after 'using' is '=', then we have an alias-declaration. */ else if (cxx_dialect >= cxx11 @@ -14726,7 +14829,7 @@ cp_parser_function_specifier_opt (cp_parser* parser, extern string-literal declaration */ static void -cp_parser_linkage_specification (cp_parser* parser) +cp_parser_linkage_specification (cp_parser* parser, tree prefix_attr) { tree linkage; @@ -14791,7 +14894,7 @@ cp_parser_linkage_specification (cp_parser* parser) saved_in_unbraced_linkage_specification_p = parser->in_unbraced_linkage_specification_p; parser->in_unbraced_linkage_specification_p = true; - cp_parser_declaration (parser); + cp_parser_declaration (parser, prefix_attr); parser->in_unbraced_linkage_specification_p = saved_in_unbraced_linkage_specification_p; } @@ -14886,7 +14989,8 @@ cp_parser_static_assert(cp_parser *parser, bool member_p) /* Complete the static assertion, which may mean either processing the static assert now or saving it for template instantiation. */ - finish_static_assert (condition, message, assert_loc, member_p); + finish_static_assert (condition, message, assert_loc, member_p, + /*show_expr_p=*/false); } /* Parse the expression in decltype ( expression ). */ @@ -19970,6 +20074,31 @@ cp_parser_qualified_namespace_specifier (cp_parser* parser) return cp_parser_namespace_name (parser); } +/* Subroutine of cp_parser_using_declaration. */ + +static tree +finish_using_decl (tree qscope, tree identifier, bool typename_p = false) +{ + tree decl = NULL_TREE; + if (at_class_scope_p ()) + { + /* Create the USING_DECL. */ + decl = do_class_using_decl (qscope, identifier); + + if (check_for_bare_parameter_packs (decl)) + return error_mark_node; + + if (decl && typename_p) + USING_DECL_TYPENAME_P (decl) = 1; + + /* Add it to the list of members in this class. */ + finish_member_declaration (decl); + } + else + finish_nonmember_using_decl (qscope, identifier); + return decl; +} + /* Parse a using-declaration, or, if ACCESS_DECLARATION_P is true, an access declaration. @@ -19989,7 +20118,6 @@ cp_parser_using_declaration (cp_parser* parser, cp_token *token; bool typename_p = false; bool global_scope_p; - tree decl; tree identifier; tree qscope; int oldcount = errorcount; @@ -20048,9 +20176,6 @@ cp_parser_using_declaration (cp_parser* parser, /*is_declaration=*/true); if (!qscope) qscope = global_namespace; - else if (UNSCOPED_ENUM_P (qscope) - && !TYPE_FUNCTION_SCOPE_P (qscope)) - qscope = CP_TYPE_CONTEXT (qscope); cp_warn_deprecated_use_scopes (qscope); @@ -20098,25 +20223,13 @@ cp_parser_using_declaration (cp_parser* parser, "a template-id may not appear in a using-declaration"); else { - if (at_class_scope_p ()) - { - /* Create the USING_DECL. */ - decl = do_class_using_decl (qscope, identifier); - - if (decl && typename_p) - USING_DECL_TYPENAME_P (decl) = 1; + tree decl = finish_using_decl (qscope, identifier, typename_p); - if (check_for_bare_parameter_packs (decl)) - { - cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); - return false; - } - else - /* Add it to the list of members in this class. */ - finish_member_declaration (decl); + if (decl == error_mark_node) + { + cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); + return false; } - else - finish_nonmember_using_decl (qscope, identifier); } if (!access_declaration_p @@ -20142,6 +20255,76 @@ cp_parser_using_declaration (cp_parser* parser, return true; } +/* C++20 using enum declaration. + + using-enum-declaration : + using elaborated-enum-specifier ; */ + +static void +cp_parser_using_enum (cp_parser *parser) +{ + cp_parser_require_keyword (parser, RID_USING, RT_USING); + + /* Using cp_parser_elaborated_type_specifier rejects typedef-names, which + breaks one of the motivating examples in using-enum-5.C. + cp_parser_simple_type_specifier seems to be closer to what we actually + want, though that hasn't been properly specified yet. */ + + /* Consume 'enum'. */ + gcc_checking_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_ENUM)); + cp_lexer_consume_token (parser->lexer); + + cp_token *start = cp_lexer_peek_token (parser->lexer); + + tree type = (cp_parser_simple_type_specifier + (parser, NULL, CP_PARSER_FLAGS_TYPENAME_OPTIONAL)); + + cp_token *end = cp_lexer_previous_token (parser->lexer); + + if (type == error_mark_node + || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)) + { + cp_parser_skip_to_end_of_block_or_statement (parser); + return; + } + if (TREE_CODE (type) == TYPE_DECL) + type = TREE_TYPE (type); + + /* The elaborated-enum-specifier shall not name a dependent type and the type + shall have a reachable enum-specifier. */ + const char *msg = nullptr; + if (cxx_dialect < cxx20) + msg = _("%<using enum%> " + "only available with %<-std=c++20%> or %<-std=gnu++20%>"); + else if (dependent_type_p (type)) + msg = _("%<using enum%> of dependent type %qT"); + else if (TREE_CODE (type) != ENUMERAL_TYPE) + msg = _("%<using enum%> of non-enumeration type %q#T"); + else if (!COMPLETE_TYPE_P (type)) + msg = _("%<using enum%> of incomplete type %qT"); + else if (OPAQUE_ENUM_P (type)) + msg = _("%<using enum%> of %qT before its enum-specifier"); + if (msg) + { + location_t loc = make_location (start, start, end); + auto_diagnostic_group g; + error_at (loc, msg, type); + loc = location_of (type); + if (cxx_dialect < cxx20 || loc == input_location) + ; + else if (OPAQUE_ENUM_P (type)) + inform (loc, "opaque-enum-declaration here"); + else + inform (loc, "declared here"); + } + + /* A using-enum-declaration introduces the enumerator names of the named + enumeration as if by a using-declaration for each enumerator. */ + if (TREE_CODE (type) == ENUMERAL_TYPE) + for (tree v = TYPE_VALUES (type); v; v = TREE_CHAIN (v)) + finish_using_decl (type, DECL_NAME (TREE_VALUE (v))); +} + /* Parse an alias-declaration. alias-declaration: @@ -20494,8 +20677,7 @@ cp_parser_asm_definition (cp_parser* parser) && cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE) && cp_lexer_next_token_is_not (parser->lexer, - CPP_CLOSE_PAREN) - && !goto_p) + CPP_CLOSE_PAREN)) { outputs = cp_parser_asm_operand_list (parser); if (outputs == error_mark_node) @@ -20663,13 +20845,12 @@ warn_about_ambiguous_parse (const cp_decl_specifier_seq *decl_specifiers, if (same_type_p (type, void_type_node)) return; } + else if (decl_specifiers->any_type_specifiers_p) + /* Code like long f(); will have null ->type. If we have any + type-specifiers, pretend we've seen int. */ + type = integer_type_node; else - { - /* Code like long f(); will have null ->type. If we have any - type-specifiers, pretend we've seen int. */ - gcc_checking_assert (decl_specifiers->any_type_specifiers_p); - type = integer_type_node; - } + return; auto_diagnostic_group d; location_t loc = declarator->u.function.parens_loc; @@ -25240,12 +25421,10 @@ cp_parser_member_declaration (cp_parser* parser) if (cp_lexer_next_token_is_keyword (parser->lexer, RID_USING)) { if (cxx_dialect < cxx11) - { - /* Parse the using-declaration. */ - cp_parser_using_declaration (parser, - /*access_declaration_p=*/false); - return; - } + /* Parse the using-declaration. */ + cp_parser_using_declaration (parser, /*access_declaration_p=*/false); + else if (cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_ENUM)) + cp_parser_using_enum (parser); else { tree decl; @@ -25266,8 +25445,8 @@ cp_parser_member_declaration (cp_parser* parser) else cp_parser_using_declaration (parser, /*access_declaration_p=*/false); - return; } + return; } /* Check for @defs. */ @@ -29604,7 +29783,8 @@ cp_parser_template_introduction (cp_parser* parser, bool member_p) { if (!flag_concepts_ts) pedwarn (introduction_loc, 0, "template-introductions" - " are not part of C++20 concepts [-fconcepts-ts]"); + " are not part of C++20 concepts; use %qs to enable", + "-fconcepts-ts"); cp_parser_template_declaration_after_parameters (parser, parms, member_p); @@ -30400,7 +30580,6 @@ static void cp_parser_late_parsing_default_args (cp_parser *parser, tree fn) { unsigned char saved_local_variables_forbidden_p; - tree parm, parmdecl; /* While we're parsing the default args, we might (due to the statement expression extension) encounter more classes. We want @@ -30415,11 +30594,20 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn) push_defarg_context (fn); - for (parm = TYPE_ARG_TYPES (TREE_TYPE (fn)), - parmdecl = DECL_ARGUMENTS (fn); + begin_scope (sk_function_parms, fn); + + /* Gather the PARM_DECLs into a vec so we can keep track of them when + pushdecl clears DECL_CHAIN. */ + releasing_vec parms; + for (tree parmdecl = DECL_ARGUMENTS (fn); parmdecl; + parmdecl = DECL_CHAIN (parmdecl)) + vec_safe_push (parms, parmdecl); + + tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn)); + for (int i = 0; parm && parm != void_list_node; parm = TREE_CHAIN (parm), - parmdecl = DECL_CHAIN (parmdecl)) + ++i) { tree default_arg = TREE_PURPOSE (parm); tree parsed_arg; @@ -30427,6 +30615,9 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn) tree copy; unsigned ix; + tree parmdecl = parms[i]; + pushdecl (parmdecl); + if (!default_arg) continue; @@ -30447,6 +30638,16 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn) TREE_PURPOSE (copy) = parsed_arg; } + pop_bindings_and_leave_scope (); + + /* Restore DECL_CHAINs after clobbering by pushdecl. */ + parm = NULL_TREE; + for (int i = parms->length () - 1; i >= 0; --i) + { + DECL_CHAIN (parms[i]) = parm; + parm = parms[i]; + } + pop_defarg_context (); /* Make sure no default arg is missing. */ @@ -33098,7 +33299,7 @@ cp_parser_objc_interstitial_code (cp_parser* parser) if (token->keyword == RID_EXTERN && cp_parser_is_pure_string_literal (cp_lexer_peek_nth_token (parser->lexer, 2))) - cp_parser_linkage_specification (parser); + cp_parser_linkage_specification (parser, NULL_TREE); /* Handle #pragma, if any. */ else if (token->type == CPP_PRAGMA) cp_parser_pragma (parser, pragma_objc_icode, NULL); @@ -33534,6 +33735,7 @@ cp_parser_objc_class_interface (cp_parser* parser, tree attributes) bool is_class_extension; cp_lexer_consume_token (parser->lexer); /* Eat '@interface'. */ + location_t nam_loc = cp_lexer_peek_token (parser->lexer)->location; name = cp_parser_identifier (parser); if (name == error_mark_node) { @@ -33553,7 +33755,7 @@ cp_parser_objc_class_interface (cp_parser* parser, tree attributes) objc_start_category_interface (name, categ, protos, attributes); else { - objc_start_class_interface (name, super, protos, attributes); + objc_start_class_interface (name, nam_loc, super, protos, attributes); /* Handle instance variable declarations, if any. */ cp_parser_objc_class_ivars (parser); objc_continue_interface (); @@ -33863,11 +34065,15 @@ static bool cp_parser_objc_valid_prefix_attributes (cp_parser* parser, tree *attrib) { cp_lexer_save_tokens (parser->lexer); - *attrib = cp_parser_attributes_opt (parser); - gcc_assert (*attrib); - if (OBJC_IS_AT_KEYWORD (cp_lexer_peek_token (parser->lexer)->keyword)) + tree addon = cp_parser_attributes_opt (parser); + if (addon + && OBJC_IS_AT_KEYWORD (cp_lexer_peek_token (parser->lexer)->keyword)) { cp_lexer_commit_tokens (parser->lexer); + if (*attrib) + TREE_CHAIN (*attrib) = addon; + else + *attrib = addon; return true; } cp_lexer_rollback_tokens (parser->lexer); @@ -34684,7 +34890,11 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, parser->colon_corrects_to_scope_p = false; cp_lexer_consume_token (parser->lexer); if (!cp_lexer_next_token_is (parser->lexer, CPP_COLON)) - low_bound = cp_parser_expression (parser); + { + low_bound = cp_parser_expression (parser); + /* Later handling is not prepared to see through these. */ + gcc_checking_assert (!location_wrapper_p (low_bound)); + } if (!colon) parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; @@ -34704,7 +34914,11 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, cp_parser_commit_to_tentative_parse (parser); if (!cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_SQUARE)) - length = cp_parser_expression (parser); + { + length = cp_parser_expression (parser); + /* Later handling is not prepared to see through these. */ + gcc_checking_assert (!location_wrapper_p (length)); + } } /* Look for the closing `]'. */ if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, @@ -37368,6 +37582,9 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask, tree clauses = NULL; bool first = true; + /* Don't create location wrapper nodes within OpenACC clauses. */ + auto_suppress_location_wrappers sentinel; + while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) { location_t here; @@ -38620,6 +38837,8 @@ cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok) cp_lexer_consume_token (parser->lexer); if (!strcmp ("depend", p)) { + /* Don't create location wrapper nodes within the depend clause. */ + auto_suppress_location_wrappers sentinel; clause = cp_parser_omp_clause_depend (parser, NULL_TREE, c_loc); if (clause) clause = finish_omp_clauses (clause, C_ORT_OMP); @@ -41291,6 +41510,10 @@ check_clauses: static tree cp_parser_oacc_cache (cp_parser *parser, cp_token *pragma_tok) { + /* Don't create location wrapper nodes within 'OMP_CLAUSE__CACHE_' + clauses. */ + auto_suppress_location_wrappers sentinel; + tree stmt, clauses; clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE__CACHE_, NULL_TREE); @@ -41891,7 +42114,7 @@ cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok, switch (context) { case pragma_external: - cp_parser_declaration (parser); + cp_parser_declaration (parser, NULL_TREE); break; case pragma_member: cp_parser_member_declaration (parser); @@ -43448,7 +43671,7 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token *pragma_tok, } /* We only have to consider the pragma_external case here. */ - cp_parser_declaration (parser); + cp_parser_declaration (parser, NULL_TREE); if (parser->oacc_routine && !parser->oacc_routine->fndecl_seen) cp_ensure_no_oacc_routine (parser); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index a2655a0..3ca2813 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -103,13 +103,6 @@ local_specialization_stack::~local_specialization_stack () /* True if we've recursed into fn_type_unification too many times. */ static bool excessive_deduction_depth; -struct GTY((for_user)) spec_entry -{ - tree tmpl; - tree args; - tree spec; -}; - struct spec_hasher : ggc_ptr_hash<spec_entry> { static hashval_t hash (spec_entry *); @@ -1709,9 +1702,11 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend, return spec; } -/* Returns true iff two spec_entry nodes are equivalent. */ - +/* Restricts tree and type comparisons. */ int comparing_specializations; +int comparing_typenames; + +/* Returns true iff two spec_entry nodes are equivalent. */ bool spec_hasher::equal (spec_entry *e1, spec_entry *e2) @@ -1719,6 +1714,7 @@ spec_hasher::equal (spec_entry *e1, spec_entry *e2) int equal; ++comparing_specializations; + ++comparing_typenames; equal = (e1->tmpl == e2->tmpl && comp_template_args (e1->args, e2->args)); if (equal && flag_concepts @@ -1734,6 +1730,7 @@ spec_hasher::equal (spec_entry *e1, spec_entry *e2) equal = equivalent_constraints (c1, c2); } --comparing_specializations; + --comparing_typenames; return equal; } @@ -4435,7 +4432,7 @@ build_template_parm_index (int index, parameter. Returns the canonical type parameter, which may be TYPE if no such parameter existed. */ -static tree +tree canonical_type_parameter (tree type) { int idx = TEMPLATE_TYPE_IDX (type); @@ -13215,19 +13212,24 @@ tsubst_argument_pack (tree orig_arg, tree args, tsubst_flags_t complain, tree in_decl) { /* Substitute into each of the arguments. */ - tree new_arg = TYPE_P (orig_arg) - ? cxx_make_type (TREE_CODE (orig_arg)) - : make_node (TREE_CODE (orig_arg)); - tree pack_args = tsubst_template_args (ARGUMENT_PACK_ARGS (orig_arg), args, complain, in_decl); - if (pack_args == error_mark_node) - new_arg = error_mark_node; - else - SET_ARGUMENT_PACK_ARGS (new_arg, pack_args); + tree new_arg = error_mark_node; + if (pack_args != error_mark_node) + { + if (TYPE_P (orig_arg)) + { + new_arg = cxx_make_type (TREE_CODE (orig_arg)); + SET_TYPE_STRUCTURAL_EQUALITY (new_arg); + } + else + { + new_arg = make_node (TREE_CODE (orig_arg)); + TREE_CONSTANT (new_arg) = TREE_CONSTANT (orig_arg); + } - if (TREE_CODE (new_arg) == NONTYPE_ARGUMENT_PACK) - TREE_CONSTANT (new_arg) = TREE_CONSTANT (orig_arg); + SET_ARGUMENT_PACK_ARGS (new_arg, pack_args); + } return new_arg; } @@ -14932,9 +14934,6 @@ 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. */ @@ -15052,9 +15051,6 @@ 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; if (!late_return_type_p) { @@ -15389,6 +15385,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) case ERROR_MARK: case IDENTIFIER_NODE: case VOID_TYPE: + case OPAQUE_TYPE: case REAL_TYPE: case COMPLEX_TYPE: case VECTOR_TYPE: @@ -15880,7 +15877,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) return error_mark_node; } - if (abstract_virtuals_error_sfinae (ACU_ARRAY, type, complain)) + if (!verify_type_context (input_location, TCTX_ARRAY_ELEMENT, type, + !(complain & tf_error))) return error_mark_node; r = build_cplus_array_type (type, domain); @@ -16214,7 +16212,7 @@ tsubst_qualified_id (tree qualified_id, tree args, tree name; bool is_template; tree template_args; - location_t loc = UNKNOWN_LOCATION; + location_t loc = EXPR_LOCATION (qualified_id); gcc_assert (TREE_CODE (qualified_id) == SCOPE_REF); @@ -16223,7 +16221,6 @@ tsubst_qualified_id (tree qualified_id, tree args, if (TREE_CODE (name) == TEMPLATE_ID_EXPR) { is_template = true; - loc = EXPR_LOCATION (name); template_args = TREE_OPERAND (name, 1); if (template_args) template_args = tsubst_template_args (template_args, args, @@ -16351,6 +16348,8 @@ tsubst_qualified_id (tree qualified_id, tree args, if (REF_PARENTHESIZED_P (qualified_id)) expr = force_paren_expr (expr); + expr = maybe_wrap_with_location (expr, loc); + return expr; } @@ -16737,6 +16736,13 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) return build1 (code, type, op0); } + case BIT_CAST_EXPR: + { + tree type = tsubst (TREE_TYPE (t), args, complain, in_decl); + tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl); + return cp_build_bit_cast (EXPR_LOCATION (t), type, op0, complain); + } + case SIZEOF_EXPR: if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)) || ARGUMENT_PACK_P (TREE_OPERAND (t, 0))) @@ -16789,6 +16795,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) else return cxx_sizeof_or_alignof_expr (input_location, expanded, SIZEOF_EXPR, + false, complain & tf_error); } else @@ -17254,6 +17261,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort, case OMP_CLAUSE_FROM: case OMP_CLAUSE_TO: case OMP_CLAUSE_MAP: + case OMP_CLAUSE__CACHE_: case OMP_CLAUSE_NONTEMPORAL: case OMP_CLAUSE_USE_DEVICE_PTR: case OMP_CLAUSE_USE_DEVICE_ADDR: @@ -18492,8 +18500,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, tree condition; ++c_inhibit_evaluation_warnings; - condition = - tsubst_expr (STATIC_ASSERT_CONDITION (t), + condition = + tsubst_expr (STATIC_ASSERT_CONDITION (t), args, complain, in_decl, /*integral_constant_expression_p=*/true); @@ -18502,7 +18510,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, finish_static_assert (condition, STATIC_ASSERT_MESSAGE (t), STATIC_ASSERT_SOURCE_LOCATION (t), - /*member_p=*/false); + /*member_p=*/false, /*show_expr_p=*/true); } break; @@ -18770,6 +18778,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, add_stmt (t); break; + case OACC_CACHE: case OACC_ENTER_DATA: case OACC_EXIT_DATA: case OACC_UPDATE: @@ -19731,7 +19740,7 @@ tsubst_copy_and_build (tree t, complain & tf_error); else r = cxx_sizeof_or_alignof_expr (input_location, - op1, TREE_CODE (t), + op1, TREE_CODE (t), std_alignof, complain & tf_error); if (TREE_CODE (t) == SIZEOF_EXPR && r != error_mark_node) { @@ -19836,6 +19845,8 @@ tsubst_copy_and_build (tree t, parameter packs are of length zero. */ if (init == NULL_TREE && TREE_OPERAND (t, 3) == NULL_TREE) init_vec = NULL; + else if (init == error_mark_node) + RETURN (error_mark_node); else { init_vec = make_tree_vector (); @@ -23602,6 +23613,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, case BOOLEAN_TYPE: case ENUMERAL_TYPE: case VOID_TYPE: + case OPAQUE_TYPE: case NULLPTR_TYPE: if (TREE_CODE (arg) != TREE_CODE (parm)) return unify_type_mismatch (explain_p, parm, arg); @@ -29257,10 +29269,13 @@ do_auto_deduction (tree type, tree init, tree auto_node, return error_mark_node; if (BRACE_ENCLOSED_INITIALIZER_P (init)) - /* We don't recurse here because we can't deduce from a nested - initializer_list. */ - for (constructor_elt &elt : *CONSTRUCTOR_ELTS (init)) - elt.value = resolve_nondeduced_context (elt.value, complain); + { + /* We don't recurse here because we can't deduce from a nested + initializer_list. */ + if (CONSTRUCTOR_ELTS (init)) + for (constructor_elt &elt : *CONSTRUCTOR_ELTS (init)) + elt.value = resolve_nondeduced_context (elt.value, complain); + } else init = resolve_nondeduced_context (init, complain); @@ -29629,6 +29644,101 @@ declare_integer_pack (void) CP_BUILT_IN_INTEGER_PACK); } +/* Walk the decl or type specialization table calling FN on each + entry. */ + +void +walk_specializations (bool decls_p, + void (*fn) (bool decls_p, spec_entry *entry, void *data), + void *data) +{ + spec_hash_table *table = decls_p ? decl_specializations + : type_specializations; + spec_hash_table::iterator end (table->end ()); + for (spec_hash_table::iterator iter (table->begin ()); iter != end; ++iter) + fn (decls_p, *iter, data); +} + +/* Lookup the specialization of TMPL, ARGS in the decl or type + specialization table. Return what's there, or if SPEC is non-null, + add it and return NULL. */ + +tree +match_mergeable_specialization (bool decl_p, tree tmpl, tree args, tree spec) +{ + spec_entry elt = {tmpl, args, spec}; + hash_table<spec_hasher> *specializations + = decl_p ? decl_specializations : type_specializations; + hashval_t hash = spec_hasher::hash (&elt); + spec_entry **slot + = specializations->find_slot_with_hash (&elt, hash, + spec ? INSERT : NO_INSERT); + spec_entry *entry = slot ? *slot: NULL; + + if (entry) + return entry->spec; + + if (spec) + { + entry = ggc_alloc<spec_entry> (); + *entry = elt; + *slot = entry; + } + + return NULL_TREE; +} + +/* Return flags encoding whether SPEC is on the instantiation and/or + specialization lists of TMPL. */ + +unsigned +get_mergeable_specialization_flags (tree tmpl, tree decl) +{ + unsigned flags = 0; + + for (tree inst = DECL_TEMPLATE_INSTANTIATIONS (tmpl); + inst; inst = TREE_CHAIN (inst)) + if (TREE_VALUE (inst) == decl) + { + flags |= 1; + break; + } + + if (CLASS_TYPE_P (TREE_TYPE (decl)) + && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (decl)) + && CLASSTYPE_USE_TEMPLATE (TREE_TYPE (decl)) == 2) + /* Only need to search if DECL is a partial specialization. */ + for (tree part = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); + part; part = TREE_CHAIN (part)) + if (TREE_VALUE (part) == decl) + { + flags |= 2; + break; + } + + return flags; +} + +/* Add a new specialization of TMPL. FLAGS is as returned from + get_mergeable_specialization_flags. */ + +void +add_mergeable_specialization (tree tmpl, tree args, tree decl, unsigned flags) +{ + if (flags & 1) + DECL_TEMPLATE_INSTANTIATIONS (tmpl) + = tree_cons (args, decl, DECL_TEMPLATE_INSTANTIATIONS (tmpl)); + + if (flags & 2) + { + /* A partial specialization. */ + DECL_TEMPLATE_SPECIALIZATIONS (tmpl) + = tree_cons (args, decl, DECL_TEMPLATE_SPECIALIZATIONS (tmpl)); + TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (tmpl)) + = TREE_TYPE (DECL_TEMPLATE_RESULT (decl)); + } +} + /* Set up the hash tables for template instantiations. */ void diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c index a28b722..f8d2208 100644 --- a/gcc/cp/ptree.c +++ b/gcc/cp/ptree.c @@ -250,6 +250,44 @@ cxx_print_xnode (FILE *file, tree node, int indent) print_node (file, "function", OVL_FUNCTION (node), indent + 4); print_node (file, "next", OVL_CHAIN (node), indent + 4); break; + case BINDING_VECTOR: + { + unsigned len = BINDING_VECTOR_NUM_CLUSTERS (node); + print_node (file, "name", BINDING_VECTOR_NAME (node), indent + 4); + fprintf (file, " clusters %u, alloc %u", len, + BINDING_VECTOR_ALLOC_CLUSTERS (node)); + for (unsigned ix = 0; ix != len; ix++) + { + binding_cluster *cluster = &BINDING_VECTOR_CLUSTER (node, ix); + char pfx[24]; + for (unsigned jx = 0; jx != BINDING_VECTOR_SLOTS_PER_CLUSTER; jx++) + if (cluster->indices[jx].span) + { + int len = sprintf (pfx, "module:%u", + cluster->indices[jx].base); + if (cluster->indices[jx].span > 1) + len += sprintf (&pfx[len], "(+%u)", + cluster->indices[jx].span); + len += sprintf (&pfx[len], " cluster:%u/%u", ix, jx); + binding_slot &slot = cluster->slots[jx]; + if (slot.is_lazy ()) + { + indent_to (file, indent + 4); + unsigned lazy = slot.get_lazy (); + fprintf (file, "%s snum:%u flags:%d", + pfx, lazy >> 2, lazy & 3); + } + else if (slot) + print_node (file, pfx, slot, indent + 4); + else + { + indent_to (file, indent + 4); + fprintf (file, "%s NULL", pfx); + } + } + } + } + break; case TEMPLATE_PARM_INDEX: print_node (file, "decl", TEMPLATE_PARM_DECL (node), indent+4); indent_to (file, indent + 3); diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 887aae3..d628862 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -123,7 +123,6 @@ static GTY (()) vec<tinfo_s, va_gc> *tinfo_descs; static tree ifnonnull (tree, tree, tsubst_flags_t); static tree tinfo_name (tree, bool); -static tree get_tinfo_decl_direct (tree type, tree name, int pseudo_ix); static tree build_dynamic_cast_1 (location_t, tree, tree, tsubst_flags_t); static tree throw_bad_cast (void); static tree throw_bad_typeid (void); @@ -431,7 +430,7 @@ get_tinfo_decl (tree type) /* Get or create a tinfo VAR_DECL directly from the provided information. The caller must have already checked it is valid to do so. */ -static tree +tree get_tinfo_decl_direct (tree type, tree name, int pseudo_ix) { /* For a class type, the variable is cached in the type node @@ -1479,6 +1478,7 @@ get_tinfo_desc (unsigned ix) finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE); CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type; DECL_CONTEXT (TYPE_NAME (pseudo_type)) = FROB_CONTEXT (global_namespace); + DECL_TINFO_P (TYPE_NAME (pseudo_type)) = true; xref_basetypes (pseudo_type, /*bases=*/NULL_TREE); res->type = cp_build_qualified_type (pseudo_type, TYPE_QUAL_CONST); @@ -1491,6 +1491,36 @@ get_tinfo_desc (unsigned ix) return res; } +/* Return an identifying index for the pseudo type_info TYPE. + We wrote the index at the end of the name, so just scan it from + there. This isn't critical, as it's only on the first use of this + type during module stream out. */ + +unsigned +get_pseudo_tinfo_index (tree type) +{ + tree name = DECL_NAME (TYPE_NAME (type)); + unsigned ix = 0, scale = 1; + size_t len = IDENTIFIER_LENGTH (name); + const char *ptr = IDENTIFIER_POINTER (name) + len; + + for (; *--ptr != '_'; scale *= 10) + { + len--; + gcc_checking_assert (len && ISDIGIT (*ptr)); + ix += (*ptr - '0') * scale; + } + + gcc_assert (len != IDENTIFIER_LENGTH (name)); + return ix; +} + +tree +get_pseudo_tinfo_type (unsigned ix) +{ + return get_tinfo_desc (ix)->type; +} + /* We lazily create the type info types. */ static void diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 33d715e..d33ef42 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3006,12 +3006,7 @@ finish_compound_literal (tree type, tree compound_literal, /* If we're in a template, return the original compound literal. */ if (orig_cl) - { - if (!VECTOR_TYPE_P (type)) - return get_target_expr_sfinae (orig_cl, complain); - else - return orig_cl; - } + return orig_cl; if (TREE_CODE (compound_literal) == CONSTRUCTOR) { @@ -4024,9 +4019,17 @@ finish_id_expression_1 (tree id_expression, if (context != current_class_type) { tree path = currently_open_derived_class (context); - perform_or_defer_access_check (TYPE_BINFO (path), - decl, decl, - tf_warning_or_error); + if (!path) + /* PATH can be null for using an enum of an unrelated + class; we checked its access in lookup_using_decl. + + ??? Should this case make a clone instead, like + handle_using_decl? */ + gcc_assert (TREE_CODE (decl) == CONST_DECL); + else + perform_or_defer_access_check (TYPE_BINFO (path), + decl, decl, + tf_warning_or_error); } } @@ -9827,13 +9830,53 @@ init_cp_semantics (void) { } + +/* If we have a condition in conjunctive normal form (CNF), find the first + failing clause. In other words, given an expression like + + true && true && false && true && false + + return the first 'false'. EXPR is the expression. */ + +static tree +find_failing_clause_r (tree expr) +{ + if (TREE_CODE (expr) == TRUTH_ANDIF_EXPR) + { + /* First check the left side... */ + tree e = find_failing_clause_r (TREE_OPERAND (expr, 0)); + if (e == NULL_TREE) + /* ...if we didn't find a false clause, check the right side. */ + e = find_failing_clause_r (TREE_OPERAND (expr, 1)); + return e; + } + tree e = contextual_conv_bool (expr, tf_none); + e = fold_non_dependent_expr (e, tf_none, /*manifestly_const_eval=*/true); + if (integer_zerop (e)) + /* This is the failing clause. */ + return expr; + return NULL_TREE; +} + +/* Wrapper for find_failing_clause_r. */ + +static tree +find_failing_clause (tree expr) +{ + if (TREE_CODE (expr) != TRUTH_ANDIF_EXPR) + return NULL_TREE; + return find_failing_clause_r (expr); +} + /* Build a STATIC_ASSERT for a static assertion with the condition CONDITION and the message text MESSAGE. LOCATION is the location of the static assertion in the source code. When MEMBER_P, this - static assertion is a member of a class. */ + static assertion is a member of a class. If SHOW_EXPR_P is true, + print the condition (because it was instantiation-dependent). */ + void finish_static_assert (tree condition, tree message, location_t location, - bool member_p) + bool member_p, bool show_expr_p) { tsubst_flags_t complain = tf_warning_or_error; @@ -9871,8 +9914,7 @@ finish_static_assert (tree condition, tree message, location_t location, tree orig_condition = condition; /* Fold the expression and convert it to a boolean value. */ - condition = perform_implicit_conversion_flags (boolean_type_node, condition, - complain, LOOKUP_NORMAL); + condition = contextual_conv_bool (condition, complain); condition = fold_non_dependent_expr (condition, complain, /*manifestly_const_eval=*/true); @@ -9881,21 +9923,32 @@ finish_static_assert (tree condition, tree message, location_t location, ; else { - location_t saved_loc = input_location; + iloc_sentinel ils (location); - input_location = location; - if (TREE_CODE (condition) == INTEGER_CST - && integer_zerop (condition)) + if (integer_zerop (condition)) { int sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (message)))); int len = TREE_STRING_LENGTH (message) / sz - 1; + + /* See if we can find which clause was failing (for logical AND). */ + tree bad = find_failing_clause (orig_condition); + /* If not, or its location is unusable, fall back to the previous + location. */ + location_t cloc = location; + if (cp_expr_location (bad) != UNKNOWN_LOCATION) + cloc = cp_expr_location (bad); + /* Report the error. */ if (len == 0) - error ("static assertion failed"); + error_at (cloc, "static assertion failed"); else - error ("static assertion failed: %s", - TREE_STRING_POINTER (message)); + error_at (cloc, "static assertion failed: %s", + TREE_STRING_POINTER (message)); + if (show_expr_p) + inform (cloc, "%qE evaluates to false", + /* Nobody wants to see the artificial (bool) cast. */ + (bad ? tree_strip_nop_conversions (bad) : orig_condition)); /* Actually explain the failure if this is a concept check or a requires-expression. */ @@ -9909,7 +9962,6 @@ finish_static_assert (tree condition, tree message, location_t location, if (require_rvalue_constant_expression (condition)) cxx_constant_value (condition); } - input_location = saved_loc; } } @@ -10627,4 +10679,75 @@ cp_build_vec_convert (tree arg, location_t loc, tree type, return build_call_expr_internal_loc (loc, IFN_VEC_CONVERT, type, 1, arg); } +/* Finish __builtin_bit_cast (type, arg). */ + +tree +cp_build_bit_cast (location_t loc, tree type, tree arg, + tsubst_flags_t complain) +{ + if (error_operand_p (type)) + return error_mark_node; + if (!dependent_type_p (type)) + { + if (!complete_type_or_maybe_complain (type, NULL_TREE, complain)) + return error_mark_node; + if (TREE_CODE (type) == ARRAY_TYPE) + { + /* std::bit_cast for destination ARRAY_TYPE is not possible, + as functions may not return an array, so don't bother trying + to support this (and then deal with VLAs etc.). */ + error_at (loc, "%<__builtin_bit_cast%> destination type %qT " + "is an array type", type); + return error_mark_node; + } + if (!trivially_copyable_p (type)) + { + error_at (loc, "%<__builtin_bit_cast%> destination type %qT " + "is not trivially copyable", type); + return error_mark_node; + } + } + + if (error_operand_p (arg)) + return error_mark_node; + + if (!type_dependent_expression_p (arg)) + { + if (TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE) + { + /* Don't perform array-to-pointer conversion. */ + arg = mark_rvalue_use (arg, loc, true); + if (!complete_type_or_maybe_complain (TREE_TYPE (arg), arg, complain)) + return error_mark_node; + } + else + arg = decay_conversion (arg, complain); + + if (error_operand_p (arg)) + return error_mark_node; + + if (!trivially_copyable_p (TREE_TYPE (arg))) + { + error_at (cp_expr_loc_or_loc (arg, loc), + "%<__builtin_bit_cast%> source type %qT " + "is not trivially copyable", TREE_TYPE (arg)); + return error_mark_node; + } + if (!dependent_type_p (type) + && !cp_tree_equal (TYPE_SIZE_UNIT (type), + TYPE_SIZE_UNIT (TREE_TYPE (arg)))) + { + error_at (loc, "%<__builtin_bit_cast%> source size %qE " + "not equal to destination type size %qE", + TYPE_SIZE_UNIT (TREE_TYPE (arg)), + TYPE_SIZE_UNIT (type)); + return error_mark_node; + } + } + + tree ret = build_min (BIT_CAST_EXPR, type, arg); + SET_EXPR_LOCATION (ret, loc); + return ret; +} + #include "gt-cp-semantics.h" diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 28e5910..8d7df60 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -998,7 +998,7 @@ build_min_array_type (tree elt_type, tree index_type) build_cplus_array_type. */ static void -set_array_type_canon (tree t, tree elt_type, tree index_type) +set_array_type_canon (tree t, tree elt_type, tree index_type, bool dep) { /* Set the canonical type for this new node. */ if (TYPE_STRUCTURAL_EQUALITY_P (elt_type) @@ -1009,30 +1009,33 @@ set_array_type_canon (tree t, tree elt_type, tree index_type) TYPE_CANONICAL (t) = build_cplus_array_type (TYPE_CANONICAL (elt_type), index_type - ? TYPE_CANONICAL (index_type) : index_type); + ? TYPE_CANONICAL (index_type) : index_type, + dep); else TYPE_CANONICAL (t) = t; } /* Like build_array_type, but handle special C++ semantics: an array of a variant element type is a variant of the array of the main variant of - the element type. */ + the element type. IS_DEPENDENT is -ve if we should determine the + dependency. Otherwise its bool value indicates dependency. */ tree -build_cplus_array_type (tree elt_type, tree index_type) +build_cplus_array_type (tree elt_type, tree index_type, int dependent) { tree t; if (elt_type == error_mark_node || index_type == error_mark_node) return error_mark_node; - bool dependent = (uses_template_parms (elt_type) - || (index_type && uses_template_parms (index_type))); + if (dependent < 0) + dependent = (uses_template_parms (elt_type) + || (index_type && uses_template_parms (index_type))); if (elt_type != TYPE_MAIN_VARIANT (elt_type)) /* Start with an array of the TYPE_MAIN_VARIANT. */ t = build_cplus_array_type (TYPE_MAIN_VARIANT (elt_type), - index_type); + index_type, dependent); else if (dependent) { /* Since type_hash_canon calls layout_type, we need to use our own @@ -1062,13 +1065,20 @@ build_cplus_array_type (tree elt_type, tree index_type) *e = t; /* Set the canonical type for this new node. */ - set_array_type_canon (t, elt_type, index_type); + set_array_type_canon (t, elt_type, index_type, dependent); + + /* Mark it as dependent now, this saves time later. */ + TYPE_DEPENDENT_P_VALID (t) = true; + TYPE_DEPENDENT_P (t) = true; } } else { bool typeless_storage = is_byte_access_type (elt_type); t = build_array_type (elt_type, index_type, typeless_storage); + + /* Mark as non-dependenty now, this will save time later. */ + TYPE_DEPENDENT_P_VALID (t) = true; } /* Now check whether we already have this array variant. */ @@ -1083,7 +1093,10 @@ build_cplus_array_type (tree elt_type, tree index_type) if (!t) { t = build_min_array_type (elt_type, index_type); - set_array_type_canon (t, elt_type, index_type); + /* Mark dependency now, this saves time later. */ + TYPE_DEPENDENT_P_VALID (t) = true; + TYPE_DEPENDENT_P (t) = dependent; + set_array_type_canon (t, elt_type, index_type, dependent); if (!dependent) { layout_type (t); @@ -1319,7 +1332,10 @@ cp_build_qualified_type_real (tree type, if (!t) { - t = build_cplus_array_type (element_type, TYPE_DOMAIN (type)); + gcc_checking_assert (TYPE_DEPENDENT_P_VALID (type) + || !dependent_type_p (type)); + t = build_cplus_array_type (element_type, TYPE_DOMAIN (type), + TYPE_DEPENDENT_P (type)); /* Keep the typedef name. */ if (TYPE_NAME (t) != TYPE_NAME (type)) @@ -1555,7 +1571,9 @@ strip_typedefs (tree t, bool *remove_attributes, unsigned int flags) case ARRAY_TYPE: type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags); t0 = strip_typedefs (TYPE_DOMAIN (t), remove_attributes, flags); - result = build_cplus_array_type (type, t0); + gcc_checking_assert (TYPE_DEPENDENT_P_VALID (t) + || !dependent_type_p (t)); + result = build_cplus_array_type (type, t0, TYPE_DEPENDENT_P (t)); break; case FUNCTION_TYPE: case METHOD_TYPE: @@ -2218,6 +2236,23 @@ build_ref_qualified_type (tree type, cp_ref_qualifier rqual) return build_cp_fntype_variant (type, rqual, raises, late); } +tree +make_binding_vec (tree name, unsigned clusters MEM_STAT_DECL) +{ + /* Stored in an unsigned short, but we're limited to the number of + modules anyway. */ + gcc_checking_assert (clusters <= (unsigned short)(~0)); + size_t length = (offsetof (tree_binding_vec, vec) + + clusters * sizeof (binding_cluster)); + tree vec = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT); + TREE_SET_CODE (vec, BINDING_VECTOR); + BINDING_VECTOR_NAME (vec) = name; + BINDING_VECTOR_ALLOC_CLUSTERS (vec) = clusters; + BINDING_VECTOR_NUM_CLUSTERS (vec) = 0; + + return vec; +} + /* Make a raw overload node containing FN. */ tree @@ -2968,6 +3003,32 @@ array_type_nelts_total (tree type) return sz; } +/* Return true if FNDECL is std::source_location::current () method. */ + +bool +source_location_current_p (tree fndecl) +{ + gcc_checking_assert (TREE_CODE (fndecl) == FUNCTION_DECL + && DECL_IMMEDIATE_FUNCTION_P (fndecl)); + if (DECL_NAME (fndecl) == NULL_TREE + || TREE_CODE (TREE_TYPE (fndecl)) != FUNCTION_TYPE + || TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != RECORD_TYPE + || DECL_CONTEXT (fndecl) != TREE_TYPE (TREE_TYPE (fndecl)) + || !id_equal (DECL_NAME (fndecl), "current")) + return false; + + tree source_location = DECL_CONTEXT (fndecl); + if (TYPE_NAME (source_location) == NULL_TREE + || TREE_CODE (TYPE_NAME (source_location)) != TYPE_DECL + || TYPE_IDENTIFIER (source_location) == NULL_TREE + || !id_equal (TYPE_IDENTIFIER (source_location), + "source_location") + || !decl_in_std_namespace_p (TYPE_NAME (source_location))) + return false; + + return true; +} + struct bot_data { splay_tree target_remap; @@ -3918,6 +3979,7 @@ cp_tree_equal (tree t1, tree t2) CASE_CONVERT: case NON_LVALUE_EXPR: case VIEW_CONVERT_EXPR: + case BIT_CAST_EXPR: if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))) return false; /* Now compare operands as usual. */ @@ -5163,6 +5225,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, case CONST_CAST_EXPR: case DYNAMIC_CAST_EXPR: case IMPLICIT_CONV_EXPR: + case BIT_CAST_EXPR: if (TREE_TYPE (*tp)) WALK_SUBTREE (TREE_TYPE (*tp)); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 08e0c80..6294a78 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1256,16 +1256,15 @@ structural_comptypes (tree t1, tree t2, int strict) gcc_assert (TYPE_P (t1) && TYPE_P (t2)); - if (!comparing_specializations) - { - /* TYPENAME_TYPEs should be resolved if the qualifying scope is the - current instantiation. */ - if (TREE_CODE (t1) == TYPENAME_TYPE) - t1 = resolve_typename_type (t1, /*only_current_p=*/true); + /* TYPENAME_TYPEs should be resolved if the qualifying scope is the + current instantiation, and we don't care about typename + structural equality. The comparing_typenames check is after the + code check, in order to early-out the common case. */ + if (TREE_CODE (t1) == TYPENAME_TYPE && !comparing_typenames) + t1 = resolve_typename_type (t1, /*only_current_p=*/true); - if (TREE_CODE (t2) == TYPENAME_TYPE) - t2 = resolve_typename_type (t2, /*only_current_p=*/true); - } + if (TREE_CODE (t2) == TYPENAME_TYPE && !comparing_typenames) + t2 = resolve_typename_type (t2, /*only_current_p=*/true); if (TYPE_PTRMEMFUNC_P (t1)) t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1); @@ -1314,6 +1313,7 @@ structural_comptypes (tree t1, tree t2, int strict) /* All void and bool types are the same. */ break; + case OPAQUE_TYPE: case INTEGER_TYPE: case FIXED_POINT_TYPE: case REAL_TYPE: @@ -1832,10 +1832,12 @@ cxx_sizeof_expr (location_t loc, tree e, tsubst_flags_t complain) /* Implement the __alignof keyword: Return the minimum required alignment of E, measured in bytes. For VAR_DECL's and FIELD_DECL's return DECL_ALIGN (which can be set from an - "aligned" __attribute__ specification). */ + "aligned" __attribute__ specification). STD_ALIGNOF acts + like in cxx_sizeof_or_alignof_type. */ static tree -cxx_alignof_expr (location_t loc, tree e, tsubst_flags_t complain) +cxx_alignof_expr (location_t loc, tree e, bool std_alignof, + tsubst_flags_t complain) { tree t; @@ -1848,6 +1850,7 @@ cxx_alignof_expr (location_t loc, tree e, tsubst_flags_t complain) TREE_SIDE_EFFECTS (e) = 0; TREE_READONLY (e) = 1; SET_EXPR_LOCATION (e, loc); + ALIGNOF_EXPR_STD_P (e) = std_alignof; return e; } @@ -1900,23 +1903,25 @@ cxx_alignof_expr (location_t loc, tree e, tsubst_flags_t complain) } else return cxx_sizeof_or_alignof_type (loc, TREE_TYPE (e), - ALIGNOF_EXPR, false, + ALIGNOF_EXPR, std_alignof, complain & tf_error); return fold_convert_loc (loc, size_type_node, t); } /* Process a sizeof or alignof expression E with code OP where the operand - is an expression. */ + is an expression. STD_ALIGNOF acts like in cxx_sizeof_or_alignof_type. */ tree cxx_sizeof_or_alignof_expr (location_t loc, tree e, enum tree_code op, - bool complain) + bool std_alignof, bool complain) { + gcc_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR); if (op == SIZEOF_EXPR) return cxx_sizeof_expr (loc, e, complain? tf_warning_or_error : tf_none); else - return cxx_alignof_expr (loc, e, complain? tf_warning_or_error : tf_none); + return cxx_alignof_expr (loc, e, std_alignof, + complain? tf_warning_or_error : tf_none); } /* Build a representation of an expression 'alignas(E).' Return the @@ -2895,7 +2900,8 @@ access_failure_info::add_fixit_hint (rich_location *richloc, tree accessor_decl) { pretty_printer pp; - pp_printf (&pp, "%s()", IDENTIFIER_POINTER (DECL_NAME (accessor_decl))); + pp_string (&pp, IDENTIFIER_POINTER (DECL_NAME (accessor_decl))); + pp_string (&pp, "()"); richloc->add_fixit_replace (pp_formatted_text (&pp)); } diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 445e2a2..3fd2b17 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -123,123 +123,6 @@ cxx_readonly_error (location_t loc, tree arg, enum lvalue_use errstring) readonly_error (loc, arg, errstring); } -/* Structure that holds information about declarations whose type was - incomplete and we could not check whether it was abstract or not. */ - -struct GTY((chain_next ("%h.next"), for_user)) pending_abstract_type { - /* Declaration which we are checking for abstractness. It is either - a DECL node, or an IDENTIFIER_NODE if we do not have a full - declaration available. */ - tree decl; - - /* Type which will be checked for abstractness. */ - tree type; - - /* Kind of use in an unnamed declarator. */ - enum abstract_class_use use; - - /* Position of the declaration. This is only needed for IDENTIFIER_NODEs, - because DECLs already carry locus information. */ - location_t locus; - - /* Link to the next element in list. */ - struct pending_abstract_type* next; -}; - -struct abstract_type_hasher : ggc_ptr_hash<pending_abstract_type> -{ - typedef tree compare_type; - static hashval_t hash (pending_abstract_type *); - static bool equal (pending_abstract_type *, tree); -}; - -/* Compute the hash value of the node VAL. This function is used by the - hash table abstract_pending_vars. */ - -hashval_t -abstract_type_hasher::hash (pending_abstract_type *pat) -{ - return (hashval_t) TYPE_UID (pat->type); -} - - -/* Compare node VAL1 with the type VAL2. This function is used by the - hash table abstract_pending_vars. */ - -bool -abstract_type_hasher::equal (pending_abstract_type *pat1, tree type2) -{ - return (pat1->type == type2); -} - -/* Hash table that maintains pending_abstract_type nodes, for which we still - need to check for type abstractness. The key of the table is the type - of the declaration. */ -static GTY (()) hash_table<abstract_type_hasher> *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 - of TYPE, and emit a diagnostic (through abstract_virtuals_error) if TYPE - turned out to be incomplete. */ - -void -complete_type_check_abstract (tree type) -{ - struct pending_abstract_type *pat; - location_t cur_loc = input_location; - - gcc_assert (COMPLETE_TYPE_P (type)); - - if (!abstract_pending_vars) - return; - - /* Retrieve the list of pending declarations for this type. */ - pending_abstract_type **slot - = abstract_pending_vars->find_slot_with_hash (type, TYPE_UID (type), - NO_INSERT); - if (!slot) - return; - pat = *slot; - gcc_assert (pat); - - /* If the type is not abstract, do not do anything. */ - if (CLASSTYPE_PURE_VIRTUALS (type)) - { - struct pending_abstract_type *prev = 0, *next; - - /* Reverse the list to emit the errors in top-down order. */ - for (; pat; pat = next) - { - next = pat->next; - pat->next = prev; - prev = pat; - } - pat = prev; - - /* Go through the list, and call abstract_virtuals_error for each - element: it will issue a diagnostic if the type is abstract. */ - while (pat) - { - gcc_assert (type == pat->type); - - /* Tweak input_location so that the diagnostic appears at the correct - location. Notice that this is only needed if the decl is an - IDENTIFIER_NODE. */ - input_location = pat->locus; - abstract_virtuals_error_sfinae (pat->decl, pat->type, pat->use, - tf_warning_or_error); - pat = pat->next; - } - } - - abstract_pending_vars->clear_slot (slot); - - input_location = cur_loc; -} - - /* 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, in which case USE specifies @@ -252,6 +135,13 @@ abstract_virtuals_error_sfinae (tree decl, tree type, abstract_class_use use, { vec<tree, va_gc> *pure; + if (TREE_CODE (type) == ARRAY_TYPE) + { + decl = NULL_TREE; + use = ACU_ARRAY; + type = strip_array_types (type); + } + /* This function applies only to classes. Any other entity can never be abstract. */ if (!CLASS_TYPE_P (type)) @@ -266,38 +156,6 @@ abstract_virtuals_error_sfinae (tree decl, tree type, abstract_class_use use, 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) && (complain & tf_error)) - { - struct pending_abstract_type *pat; - - gcc_assert (!decl || DECL_P (decl) || identifier_p (decl)); - - if (!abstract_pending_vars) - abstract_pending_vars - = hash_table<abstract_type_hasher>::create_ggc (31); - - pending_abstract_type **slot - = abstract_pending_vars->find_slot_with_hash (type, TYPE_UID (type), - INSERT); - - 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); - - pat->next = *slot; - *slot = pat; - - return 0; - } - if (!TYPE_SIZE (type)) /* TYPE is being defined, and during that time CLASSTYPE_PURE_VIRTUALS holds the inline friends. */ @@ -886,11 +744,13 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags) { bool const_init; tree oldval = value; - value = fold_non_dependent_expr (value, tf_warning_or_error, true, decl); if (DECL_DECLARED_CONSTEXPR_P (decl) || (DECL_IN_AGGR_P (decl) && DECL_INITIALIZED_IN_CLASS_P (decl))) { + value = fold_non_dependent_expr (value, tf_warning_or_error, + /*manifestly_const_eval=*/true, + decl); /* Diagnose a non-constant initializer for constexpr variable or non-inline in-class-initialized static data member. */ if (!require_constant_expression (value)) @@ -904,7 +764,8 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags) value = cxx_constant_init (value, decl); } else - value = maybe_constant_init (value, decl, true); + value = fold_non_dependent_init (value, tf_warning_or_error, + /*manifestly_const_eval=*/true, decl); if (TREE_CODE (value) == CONSTRUCTOR && cp_has_mutable_p (type)) /* Poison this CONSTRUCTOR so it can't be copied to another constexpr variable. */ @@ -948,6 +809,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags) the bits that are constant, and then return an expression that will perform the dynamic initialization. */ if (value != error_mark_node + && !processing_template_decl && (TREE_SIDE_EFFECTS (value) || vla_type_p (type) || ! reduced_constant_expression_p (value))) @@ -1288,6 +1150,7 @@ digest_init_r (tree type, tree init, int nested, int flags, || VECTOR_TYPE_P (type) || code == RECORD_TYPE || code == UNION_TYPE + || code == OPAQUE_TYPE || code == COMPLEX_TYPE); /* "If T is a class type and the initializer list has a single @@ -2594,6 +2457,3 @@ require_complete_eh_spec_types (tree fntype, tree decl) } } } - - -#include "gt-cp-typeck2.h" |