@@ -445,7 +445,9 @@ builtin_valid_in_constant_expr_p (const_
if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL)
{
if (fndecl_built_in_p (decl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
- BUILT_IN_FRONTEND))
+ BUILT_IN_FRONTEND)
+ || fndecl_built_in_p (decl, CP_BUILT_IN_SOURCE_LOCATION,
+ BUILT_IN_FRONTEND))
return true;
/* Not a built-in. */
return false;
@@ -1238,6 +1238,9 @@ cxx_eval_builtin_function_call (const co
return boolean_true_node;
}
+ if (fndecl_built_in_p (fun, CP_BUILT_IN_SOURCE_LOCATION, BUILT_IN_FRONTEND))
+ return fold_builtin_source_location (EXPR_LOCATION (t));
+
/* Be permissive for arguments to built-ins; __builtin_constant_p should
return constant false for a non-constant argument. */
constexpr_ctx new_ctx = *ctx;
@@ -5747,6 +5747,8 @@ get_std_name_hint (const char *name)
{"shared_lock", "<shared_mutex>", cxx14},
{"shared_mutex", "<shared_mutex>", cxx17},
{"shared_timed_mutex", "<shared_mutex>", cxx14},
+ /* <source_location>. */
+ {"source_location", "<source_location>", cxx2a},
/* <sstream>. */
{"basic_stringbuf", "<sstream>", cxx98},
{"basic_istringstream", "<sstream>", cxx98},
@@ -35,6 +35,9 @@ along with GCC; see the file COPYING3.
#include "attribs.h"
#include "asan.h"
#include "gcc-rich-location.h"
+#include "output.h"
+#include "file-prefix-map.h"
+#include "cgraph.h"
/* Forward declarations. */
@@ -896,8 +899,12 @@ cp_gimplify_expr (tree *expr_p, gimple_s
tree decl = cp_get_callee_fndecl_nofold (*expr_p);
if (decl
&& fndecl_built_in_p (decl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
- BUILT_IN_FRONTEND))
+ BUILT_IN_FRONTEND))
*expr_p = boolean_false_node;
+ else if (decl
+ && fndecl_built_in_p (decl, CP_BUILT_IN_SOURCE_LOCATION,
+ BUILT_IN_FRONTEND))
+ *expr_p = fold_builtin_source_location (EXPR_LOCATION (*expr_p));
}
break;
@@ -2641,9 +2648,17 @@ cp_fold (tree x)
/* Defer folding __builtin_is_constant_evaluated. */
if (callee
&& fndecl_built_in_p (callee, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
- BUILT_IN_FRONTEND))
+ BUILT_IN_FRONTEND))
break;
+ if (callee
+ && fndecl_built_in_p (callee, CP_BUILT_IN_SOURCE_LOCATION,
+ BUILT_IN_FRONTEND))
+ {
+ x = fold_builtin_source_location (EXPR_LOCATION (x));
+ break;
+ }
+
x = copy_node (x);
m = call_expr_nargs (x);
@@ -2868,4 +2883,172 @@ process_stmt_hotness_attribute (tree std
return std_attrs;
}
+/* Helper of fold_builtin_source_location, return the
+ std::source_location::__impl type after performing verification
+ on it. */
+
+static tree
+get_source_location_impl (location_t loc)
+{
+ tree name = get_identifier ("source_location");
+ tree decl = lookup_qualified_name (std_node, name);
+ if (TREE_CODE (decl) != TYPE_DECL)
+ {
+ auto_diagnostic_group d;
+ if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
+ qualified_name_lookup_error (std_node, name, decl, loc);
+ else
+ error ("%<std::%D%> is not a type", decl);
+ return error_mark_node;
+ }
+ name = get_identifier ("__impl");
+ tree type = TREE_TYPE (decl);
+ decl = lookup_qualified_name (type, name);
+ if (TREE_CODE (decl) != TYPE_DECL)
+ {
+ auto_diagnostic_group d;
+ if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
+ qualified_name_lookup_error (type, name, decl, loc);
+ else
+ error ("%<std::source_location::%D%> is not a type", decl);
+ return error_mark_node;
+ }
+ type = TREE_TYPE (decl);
+ if (TREE_CODE (type) != RECORD_TYPE)
+ {
+ error ("%<std::source_location::%D%> is not a class type", decl);
+ return error_mark_node;
+ }
+
+ int cnt = 0;
+ for (tree field = TYPE_FIELDS (type);
+ (field = next_initializable_field (field)) != NULL_TREE;
+ field = DECL_CHAIN (field))
+ {
+ if (DECL_NAME (field) != NULL_TREE)
+ {
+ const char *n = IDENTIFIER_POINTER (DECL_NAME (field));
+ if (strcmp (n, "__file") == 0 || strcmp (n, "__function") == 0)
+ {
+ if (TREE_TYPE (field) != const_string_type_node)
+ {
+ error ("%<std::source_location::__impl::%D%> does not "
+ "have %<const char *%> type", field);
+ return error_mark_node;
+ }
+ cnt++;
+ continue;
+ }
+ else if (strcmp (n, "__line") == 0 || strcmp (n, "__column") == 0)
+ {
+ if (TREE_CODE (TREE_TYPE (field)) != INTEGER_TYPE)
+ {
+ error ("%<std::source_location::__impl::%D%> does not "
+ "have integral type", field);
+ return error_mark_node;
+ }
+ cnt++;
+ continue;
+ }
+ }
+ cnt = 0;
+ break;
+ }
+ if (cnt != 4)
+ {
+ error ("%<std::source_location::__impl%> does not contain only "
+ "non-static data members %<__file%>, %<__function%>, "
+ "%<__line%> and %<__column%>");
+ return error_mark_node;
+ }
+ return build_qualified_type (type, TYPE_QUAL_CONST);
+}
+
+/* static GTY(()) hash_map <location_hash, tree> *source_location_table; */
+static GTY(()) unsigned int source_location_id;
+
+/* Fold __builtin_source_location () call. LOC is the location
+ of the call. */
+
+tree
+fold_builtin_source_location (location_t loc)
+{
+ if (source_location_impl == NULL_TREE)
+ {
+ auto_diagnostic_group d;
+ source_location_impl = get_source_location_impl (loc);
+ if (source_location_impl == error_mark_node)
+ inform (loc, "evaluating %qs", "__builtin_source_location");
+ }
+ if (source_location_impl == error_mark_node)
+ return build_zero_cst (const_ptr_type_node);
+// if (source_location_table)
+// hash_map <location_hash, tree>::create_ggc (64);
+ loc = LOCATION_LOCUS (loc);
+// tree *varp = source_location_table->get (loc);
+ tree var;
+// if (*varp)
+// var = *varp;
+// else
+ {
+ char tmp_name[32];
+ ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lsrc_loc", source_location_id++);
+ var = build_decl (loc, VAR_DECL, get_identifier (tmp_name),
+ source_location_impl);
+ TREE_STATIC (var) = 1;
+ TREE_PUBLIC (var) = 0;
+ DECL_ARTIFICIAL (var) = 1;
+ DECL_IGNORED_P (var) = 1;
+ DECL_EXTERNAL (var) = 0;
+ DECL_DECLARED_CONSTEXPR_P (var) = 1;
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (var) = 1;
+ layout_decl (var, 0);
+
+ vec<constructor_elt, va_gc> *v = NULL;
+ vec_alloc (v, 4);
+ for (tree field = TYPE_FIELDS (source_location_impl);
+ (field = next_initializable_field (field)) != NULL_TREE;
+ field = DECL_CHAIN (field))
+ {
+ const char *n = IDENTIFIER_POINTER (DECL_NAME (field));
+ tree val = NULL_TREE;
+ if (strcmp (n, "__file") == 0)
+ {
+ if (const char *fname = LOCATION_FILE (loc))
+ {
+ fname = remap_macro_filename (fname);
+ val = build_string_literal (strlen (fname) + 1, fname);
+ }
+ else
+ val = build_string_literal (1, "");
+ }
+ else if (strcmp (n, "__function") == 0)
+ {
+ const char *name = "";
+
+ if (current_function_decl)
+ name = cxx_printable_name (current_function_decl, 0);
+
+ val = build_string_literal (strlen (name) + 1, name);
+ }
+ else if (strcmp (n, "__line") == 0)
+ val = build_int_cst (TREE_TYPE (field), LOCATION_LINE (loc));
+ else if (strcmp (n, "__column") == 0)
+ val = build_int_cst (TREE_TYPE (field), LOCATION_COLUMN (loc));
+ else
+ gcc_unreachable ();
+ CONSTRUCTOR_APPEND_ELT (v, field, val);
+ }
+
+ tree ctor = build_constructor (source_location_impl, v);
+ TREE_CONSTANT (ctor) = 1;
+ TREE_STATIC (ctor) = 1;
+ DECL_INITIAL (var) = ctor;
+ varpool_node::finalize_decl (var);
+// source_location_table->put (loc, var);
+ }
+
+ return build_fold_addr_expr_with_type_loc (loc, var, const_ptr_type_node);
+}
+
#include "gt-cp-cp-gimplify.h"
@@ -204,6 +204,8 @@ enum cp_tree_index
CPTI_ANY_TARG,
+ CPTI_SOURCE_LOCATION_IMPL,
+
CPTI_MAX
};
@@ -356,6 +358,9 @@ extern GTY(()) tree cp_global_trees[CPTI
/* A node which matches any template argument. */
#define any_targ_node cp_global_trees[CPTI_ANY_TARG]
+/* std::source_location::__impl class. */
+#define source_location_impl cp_global_trees[CPTI_SOURCE_LOCATION_IMPL]
+
/* Node to indicate default access. This must be distinct from the
access nodes in tree.h. */
@@ -6175,6 +6180,7 @@ struct GTY((chain_next ("%h.next"))) tin
enum cp_built_in_function {
CP_BUILT_IN_IS_CONSTANT_EVALUATED,
CP_BUILT_IN_INTEGER_PACK,
+ CP_BUILT_IN_SOURCE_LOCATION,
CP_BUILT_IN_LAST
};
@@ -7723,6 +7729,7 @@ extern void clear_fold_cache (void);
extern tree lookup_hotness_attribute (tree);
extern tree process_stmt_hotness_attribute (tree, location_t);
extern bool simple_empty_class_p (tree, tree, tree_code);
+extern tree fold_builtin_source_location (location_t);
/* in name-lookup.c */
extern tree strip_using_decl (tree);
@@ -4290,6 +4290,12 @@ cxx_init_decl_processing (void)
BUILT_IN_FRONTEND, NULL, NULL_TREE);
set_call_expr_flags (decl, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
+ tree cptr_ftype = build_function_type_list (const_ptr_type_node, NULL_TREE);
+ decl = add_builtin_function ("__builtin_source_location",
+ cptr_ftype, CP_BUILT_IN_SOURCE_LOCATION,
+ BUILT_IN_FRONTEND, NULL, NULL_TREE);
+ set_call_expr_flags (decl, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
+
integer_two_node = build_int_cst (NULL_TREE, 2);
/* Guess at the initial static decls size. */