aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-12-03 12:12:10 -0800
committerIan Lance Taylor <iant@golang.org>2020-12-03 12:12:10 -0800
commitf012991e2db06cc95f7aac8ecb74a1ac5f51f3d2 (patch)
tree582e5d7b377b6e973666a71960b28a7d11d72b07 /gcc/cp
parent8d703821c69062c0cd255787d793e44f1a95d463 (diff)
parent3089f5feef36810c625b5813370a97b4ecc841f8 (diff)
downloadgcc-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/ChangeLog470
-rw-r--r--gcc/cp/Make-lang.in10
-rw-r--r--gcc/cp/call.c94
-rw-r--r--gcc/cp/class.c17
-rw-r--r--gcc/cp/constexpr.c416
-rw-r--r--gcc/cp/constraint.cc4
-rw-r--r--gcc/cp/coroutines.cc2
-rw-r--r--gcc/cp/cp-gimplify.c13
-rw-r--r--gcc/cp/cp-objcp-common.c2
-rw-r--r--gcc/cp/cp-tree.def6
-rw-r--r--gcc/cp/cp-tree.h170
-rw-r--r--gcc/cp/cxx-pretty-print.c15
-rw-r--r--gcc/cp/decl.c110
-rw-r--r--gcc/cp/error.c19
-rw-r--r--gcc/cp/g++spec.c33
-rw-r--r--gcc/cp/init.c6
-rw-r--r--gcc/cp/lang-specs.h57
-rw-r--r--gcc/cp/lex.c15
-rw-r--r--gcc/cp/logic.cc5
-rw-r--r--gcc/cp/mangle.c27
-rw-r--r--gcc/cp/method.c2
-rw-r--r--gcc/cp/module.cc21
-rw-r--r--gcc/cp/name-lookup.c264
-rw-r--r--gcc/cp/name-lookup.h119
-rw-r--r--gcc/cp/optimize.c2
-rw-r--r--gcc/cp/parser.c375
-rw-r--r--gcc/cp/pt.c184
-rw-r--r--gcc/cp/ptree.c38
-rw-r--r--gcc/cp/rtti.c34
-rw-r--r--gcc/cp/semantics.c165
-rw-r--r--gcc/cp/tree.c85
-rw-r--r--gcc/cp/typeck.c38
-rw-r--r--gcc/cp/typeck2.c168
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"