Commit ff603745 by Jakub Jelinek Committed by Jakub Jelinek

cp-tree.h (enum cp_tree_index): Add CPTI_SOURCE_LOCATION_IMPL.

	* cp-tree.h (enum cp_tree_index): Add CPTI_SOURCE_LOCATION_IMPL.
	(source_location_impl): Define.
	(enum cp_built_in_function): Add CP_BUILT_IN_SOURCE_LOCATION.
	(fold_builtin_source_location): Declare.
	* cp-gimplify.c: Include output.h, file-prefix-map.h and cgraph.h.
	(cp_gimplify_expr, cp_fold): Handle CP_BUILT_IN_SOURCE_LOCATION.
	Formatting fix.
	(get_source_location_impl_type): New function.
	(struct source_location_table_entry,
	struct source_location_table_entry_hash): New types.
	(source_location_table, source_location_id): New variables.
	(fold_builtin_source_location): New function.
	* constexpr.c (cxx_eval_builtin_function_call): Handle
	CP_BUILT_IN_SOURCE_LOCATION.
	* tree.c (builtin_valid_in_constant_expr_p): Likewise.  Formatting
	fix.
	* decl.c (cxx_init_decl_processing): Register
	__builtin_source_location.
	* name-lookup.c (get_std_name_hint): Add source_location entry.

	* g++.dg/cpp2a/srcloc1.C: New test.
	* g++.dg/cpp2a/srcloc2.C: New test.
	* g++.dg/cpp2a/srcloc3.C: New test.
	* g++.dg/cpp2a/srcloc4.C: New test.
	* g++.dg/cpp2a/srcloc5.C: New test.
	* g++.dg/cpp2a/srcloc6.C: New test.
	* g++.dg/cpp2a/srcloc7.C: New test.
	* g++.dg/cpp2a/srcloc8.C: New test.
	* g++.dg/cpp2a/srcloc9.C: New test.
	* g++.dg/cpp2a/srcloc10.C: New test.
	* g++.dg/cpp2a/srcloc11.C: New test.
	* g++.dg/cpp2a/srcloc12.C: New test.
	* g++.dg/cpp2a/srcloc13.C: New test.
	* g++.dg/cpp2a/srcloc14.C: New test.

From-SVN: r278949
parent dd2a16c7
2019-12-03 Jakub Jelinek <jakub@redhat.com>
* cp-tree.h (enum cp_tree_index): Add CPTI_SOURCE_LOCATION_IMPL.
(source_location_impl): Define.
(enum cp_built_in_function): Add CP_BUILT_IN_SOURCE_LOCATION.
(fold_builtin_source_location): Declare.
* cp-gimplify.c: Include output.h, file-prefix-map.h and cgraph.h.
(cp_gimplify_expr, cp_fold): Handle CP_BUILT_IN_SOURCE_LOCATION.
Formatting fix.
(get_source_location_impl_type): New function.
(struct source_location_table_entry,
struct source_location_table_entry_hash): New types.
(source_location_table, source_location_id): New variables.
(fold_builtin_source_location): New function.
* constexpr.c (cxx_eval_builtin_function_call): Handle
CP_BUILT_IN_SOURCE_LOCATION.
* tree.c (builtin_valid_in_constant_expr_p): Likewise. Formatting
fix.
* decl.c (cxx_init_decl_processing): Register
__builtin_source_location.
* name-lookup.c (get_std_name_hint): Add source_location entry.
2019-12-03 Paolo Carlini <paolo.carlini@oracle.com> 2019-12-03 Paolo Carlini <paolo.carlini@oracle.com>
* typeck.c (cp_build_addr_expr_1): Use the cp_expr_loc_or_input_loc * typeck.c (cp_build_addr_expr_1): Use the cp_expr_loc_or_input_loc
......
...@@ -1240,6 +1240,9 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, ...@@ -1240,6 +1240,9 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
return boolean_true_node; 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 /* Be permissive for arguments to built-ins; __builtin_constant_p should
return constant false for a non-constant argument. */ return constant false for a non-constant argument. */
constexpr_ctx new_ctx = *ctx; constexpr_ctx new_ctx = *ctx;
......
...@@ -35,6 +35,9 @@ along with GCC; see the file COPYING3. If not see ...@@ -35,6 +35,9 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h" #include "attribs.h"
#include "asan.h" #include "asan.h"
#include "gcc-rich-location.h" #include "gcc-rich-location.h"
#include "output.h"
#include "file-prefix-map.h"
#include "cgraph.h"
/* Forward declarations. */ /* Forward declarations. */
...@@ -896,8 +899,12 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) ...@@ -896,8 +899,12 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
tree decl = cp_get_callee_fndecl_nofold (*expr_p); tree decl = cp_get_callee_fndecl_nofold (*expr_p);
if (decl if (decl
&& fndecl_built_in_p (decl, CP_BUILT_IN_IS_CONSTANT_EVALUATED, && fndecl_built_in_p (decl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
BUILT_IN_FRONTEND)) BUILT_IN_FRONTEND))
*expr_p = boolean_false_node; *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; break;
...@@ -2657,9 +2664,17 @@ cp_fold (tree x) ...@@ -2657,9 +2664,17 @@ cp_fold (tree x)
/* Defer folding __builtin_is_constant_evaluated. */ /* Defer folding __builtin_is_constant_evaluated. */
if (callee if (callee
&& fndecl_built_in_p (callee, CP_BUILT_IN_IS_CONSTANT_EVALUATED, && fndecl_built_in_p (callee, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
BUILT_IN_FRONTEND)) BUILT_IN_FRONTEND))
break; 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); x = copy_node (x);
m = call_expr_nargs (x); m = call_expr_nargs (x);
...@@ -2884,4 +2899,246 @@ process_stmt_hotness_attribute (tree std_attrs, location_t attrs_loc) ...@@ -2884,4 +2899,246 @@ process_stmt_hotness_attribute (tree std_attrs, location_t attrs_loc)
return std_attrs; return std_attrs;
} }
/* Helper of fold_builtin_source_location, return the
std::source_location::__impl type after performing verification
on it. LOC is used for reporting any errors. */
static tree
get_source_location_impl_type (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_at (loc, "%qD 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_at (loc, "%qD is not a type", decl);
return error_mark_node;
}
type = TREE_TYPE (decl);
if (TREE_CODE (type) != RECORD_TYPE)
{
error_at (loc, "%qD 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, "_M_file_name") == 0
|| strcmp (n, "_M_function_name") == 0)
{
if (TREE_TYPE (field) != const_string_type_node)
{
error_at (loc, "%qD does not have %<const char *%> type",
field);
return error_mark_node;
}
cnt++;
continue;
}
else if (strcmp (n, "_M_line") == 0 || strcmp (n, "_M_column") == 0)
{
if (TREE_CODE (TREE_TYPE (field)) != INTEGER_TYPE)
{
error_at (loc, "%qD does not have integral type", field);
return error_mark_node;
}
cnt++;
continue;
}
}
cnt = 0;
break;
}
if (cnt != 4)
{
error_at (loc, "%<std::source_location::__impl%> does not contain only "
"non-static data members %<_M_file_name%>, "
"%<_M_function_name%>, %<_M_line%> and %<_M_column%>");
return error_mark_node;
}
return build_qualified_type (type, TYPE_QUAL_CONST);
}
/* Type for source_location_table hash_set. */
struct GTY((for_user)) source_location_table_entry {
location_t loc;
unsigned uid;
tree var;
};
/* Traits class for function start hash maps below. */
struct source_location_table_entry_hash
: ggc_remove <source_location_table_entry>
{
typedef source_location_table_entry value_type;
typedef source_location_table_entry compare_type;
static hashval_t
hash (const source_location_table_entry &ref)
{
inchash::hash hstate (0);
hstate.add_int (ref.loc);
hstate.add_int (ref.uid);
return hstate.end ();
}
static bool
equal (const source_location_table_entry &ref1,
const source_location_table_entry &ref2)
{
return ref1.loc == ref2.loc && ref1.uid == ref2.uid;
}
static void
mark_deleted (source_location_table_entry &ref)
{
ref.loc = UNKNOWN_LOCATION;
ref.uid = -1U;
ref.var = NULL_TREE;
}
static void
mark_empty (source_location_table_entry &ref)
{
ref.loc = UNKNOWN_LOCATION;
ref.uid = 0;
ref.var = NULL_TREE;
}
static bool
is_deleted (const source_location_table_entry &ref)
{
return (ref.loc == UNKNOWN_LOCATION
&& ref.uid == -1U
&& ref.var == NULL_TREE);
}
static bool
is_empty (const source_location_table_entry &ref)
{
return (ref.loc == UNKNOWN_LOCATION
&& ref.uid == 0
&& ref.var == NULL_TREE);
}
};
static GTY(()) hash_table <source_location_table_entry_hash>
*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_type (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 == NULL)
source_location_table
= hash_table <source_location_table_entry_hash>::create_ggc (64);
const line_map_ordinary *map;
source_location_table_entry entry;
entry.loc
= linemap_resolve_location (line_table, loc, LRK_MACRO_EXPANSION_POINT,
&map);
entry.uid = current_function_decl ? DECL_UID (current_function_decl) : -1;
entry.var = error_mark_node;
source_location_table_entry *entryp
= source_location_table->find_slot (entry, INSERT);
tree var;
if (entryp->var)
var = entryp->var;
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, "_M_file_name") == 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, "_M_function_name") == 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, "_M_line") == 0)
val = build_int_cst (TREE_TYPE (field), LOCATION_LINE (loc));
else if (strcmp (n, "_M_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);
*entryp = entry;
entryp->var = var;
}
return build_fold_addr_expr_with_type_loc (loc, var, const_ptr_type_node);
}
#include "gt-cp-cp-gimplify.h" #include "gt-cp-cp-gimplify.h"
...@@ -204,6 +204,8 @@ enum cp_tree_index ...@@ -204,6 +204,8 @@ enum cp_tree_index
CPTI_ANY_TARG, CPTI_ANY_TARG,
CPTI_SOURCE_LOCATION_IMPL,
CPTI_MAX CPTI_MAX
}; };
...@@ -356,6 +358,9 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; ...@@ -356,6 +358,9 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
/* A node which matches any template argument. */ /* A node which matches any template argument. */
#define any_targ_node cp_global_trees[CPTI_ANY_TARG] #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 /* Node to indicate default access. This must be distinct from the
access nodes in tree.h. */ access nodes in tree.h. */
...@@ -6182,6 +6187,7 @@ struct GTY((chain_next ("%h.next"))) tinst_level { ...@@ -6182,6 +6187,7 @@ struct GTY((chain_next ("%h.next"))) tinst_level {
enum cp_built_in_function { enum cp_built_in_function {
CP_BUILT_IN_IS_CONSTANT_EVALUATED, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
CP_BUILT_IN_INTEGER_PACK, CP_BUILT_IN_INTEGER_PACK,
CP_BUILT_IN_SOURCE_LOCATION,
CP_BUILT_IN_LAST CP_BUILT_IN_LAST
}; };
...@@ -7735,6 +7741,7 @@ extern void clear_fold_cache (void); ...@@ -7735,6 +7741,7 @@ extern void clear_fold_cache (void);
extern tree lookup_hotness_attribute (tree); extern tree lookup_hotness_attribute (tree);
extern tree process_stmt_hotness_attribute (tree, location_t); extern tree process_stmt_hotness_attribute (tree, location_t);
extern bool simple_empty_class_p (tree, tree, tree_code); extern bool simple_empty_class_p (tree, tree, tree_code);
extern tree fold_builtin_source_location (location_t);
/* in name-lookup.c */ /* in name-lookup.c */
extern tree strip_using_decl (tree); extern tree strip_using_decl (tree);
......
...@@ -4290,6 +4290,12 @@ cxx_init_decl_processing (void) ...@@ -4290,6 +4290,12 @@ cxx_init_decl_processing (void)
BUILT_IN_FRONTEND, NULL, NULL_TREE); BUILT_IN_FRONTEND, NULL, NULL_TREE);
set_call_expr_flags (decl, ECF_CONST | ECF_NOTHROW | ECF_LEAF); 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); integer_two_node = build_int_cst (NULL_TREE, 2);
/* Guess at the initial static decls size. */ /* Guess at the initial static decls size. */
......
...@@ -5747,6 +5747,8 @@ get_std_name_hint (const char *name) ...@@ -5747,6 +5747,8 @@ get_std_name_hint (const char *name)
{"shared_lock", "<shared_mutex>", cxx14}, {"shared_lock", "<shared_mutex>", cxx14},
{"shared_mutex", "<shared_mutex>", cxx17}, {"shared_mutex", "<shared_mutex>", cxx17},
{"shared_timed_mutex", "<shared_mutex>", cxx14}, {"shared_timed_mutex", "<shared_mutex>", cxx14},
/* <source_location>. */
{"source_location", "<source_location>", cxx2a},
/* <sstream>. */ /* <sstream>. */
{"basic_stringbuf", "<sstream>", cxx98}, {"basic_stringbuf", "<sstream>", cxx98},
{"basic_istringstream", "<sstream>", cxx98}, {"basic_istringstream", "<sstream>", cxx98},
......
...@@ -445,7 +445,9 @@ builtin_valid_in_constant_expr_p (const_tree decl) ...@@ -445,7 +445,9 @@ builtin_valid_in_constant_expr_p (const_tree decl)
if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL) if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL)
{ {
if (fndecl_built_in_p (decl, CP_BUILT_IN_IS_CONSTANT_EVALUATED, 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; return true;
/* Not a built-in. */ /* Not a built-in. */
return false; return false;
......
2019-12-03 Jakub Jelinek <jakub@redhat.com>
* g++.dg/cpp2a/srcloc1.C: New test.
* g++.dg/cpp2a/srcloc2.C: New test.
* g++.dg/cpp2a/srcloc3.C: New test.
* g++.dg/cpp2a/srcloc4.C: New test.
* g++.dg/cpp2a/srcloc5.C: New test.
* g++.dg/cpp2a/srcloc6.C: New test.
* g++.dg/cpp2a/srcloc7.C: New test.
* g++.dg/cpp2a/srcloc8.C: New test.
* g++.dg/cpp2a/srcloc9.C: New test.
* g++.dg/cpp2a/srcloc10.C: New test.
* g++.dg/cpp2a/srcloc11.C: New test.
* g++.dg/cpp2a/srcloc12.C: New test.
* g++.dg/cpp2a/srcloc13.C: New test.
* g++.dg/cpp2a/srcloc14.C: New test.
2019-12-03 Paolo Carlini <paolo.carlini@oracle.com> 2019-12-03 Paolo Carlini <paolo.carlini@oracle.com>
* g++.dg/diagnostic/inconsistent-deduction-1.C: New. * g++.dg/diagnostic/inconsistent-deduction-1.C: New.
......
// { dg-do compile { target c++2a } }
namespace std {
struct source_location {
struct __impl {
const char *_M_file_name;
const char *_M_function_name;
unsigned int _M_line, _M_column;
};
const __impl *__ptr;
constexpr source_location () : __ptr (nullptr) {}
static consteval source_location
current (const void *__p = __builtin_source_location ()) {
source_location __ret;
__ret.__ptr = static_cast <const __impl *> (__p);
return __ret;
}
constexpr const char *file_name () const {
return __ptr ? __ptr->_M_file_name : "";
}
constexpr const char *function_name () const {
return __ptr ? __ptr->_M_function_name : "";
}
constexpr unsigned line () const {
return __ptr ? __ptr->_M_line : 0;
}
constexpr unsigned column () const {
return __ptr ? __ptr->_M_column : 0;
}
};
}
using namespace std;
consteval source_location
bar (const source_location x = source_location::current ())
{
return x;
}
void
foo (const char **p, unsigned *q)
{
constexpr source_location s = source_location::current ();
constexpr source_location t = bar ();
p[0] = s.file_name ();
p[1] = s.function_name ();
q[0] = s.line ();
q[1] = s.column ();
p[2] = t.file_name ();
p[3] = t.function_name ();
q[2] = t.line ();
q[3] = t.column ();
constexpr const char *r = s.file_name ();
}
source_location s3 = source_location::current ();
template <int N>
constexpr source_location
baz ()
{
return source_location::current ();
}
#define A \
source_location s[3] = { source_location::current (), \
source_location::current (), \
source_location::current () }
source_location *
boo ()
{
static A;
return &s[0];
}
constexpr source_location s1 = baz <0> ();
constexpr source_location s2 = baz <1> ();
const source_location *p1 = &s1;
const source_location *p2 = &s2;
static_assert (source_location::current ().line () == __LINE__);
static_assert (source_location::current ().column () == 42);
constexpr bool
quux ()
{
const char *file1 = source_location::current ().file_name ();
const char *file2 = __FILE__;
const char *function1 = source_location::current ().function_name ();
const char *function2 = __FUNCTION__;
int line1 = source_location::current ().line ();
int line2 = __LINE__ - 1;
int column
= source_location::current ().column ();
int i = 0;
for (; file1[i]; i++)
if (file1[i] != file2[i])
return false;
if (file2[i])
return false;
for (i = 0; function1[i]; i++)
if (function1[i] != function2[i])
return false;
if (function2[i])
return false;
if (line1 != line2)
return false;
if (column != 33)
return false;
return true;
}
static_assert (quux ());
// { dg-do compile { target c++2a } }
namespace std {
struct source_location {
struct __impl {
const char *_M_file_name, *_M_function_name;
int __foo, _M_line, _M_column;
};
};
}
auto x = __builtin_source_location (); // { dg-error "'std::source_location::__impl' does not contain only non-static data members '_M_file_name', '_M_function_name', '_M_line' and '_M_column'" }
// { dg-message "evaluating '__builtin_source_location'" "" { target *-*-* } .-1 }
// { dg-do compile { target c++2a } }
namespace std {
struct source_location {
struct __impl {
const char *_M_file_name, *_M_function_name;
int _M_line;
};
};
}
auto x = __builtin_source_location (); // { dg-error "'std::source_location::__impl' does not contain only non-static data members '_M_file_name', '_M_function_name', '_M_line' and '_M_column'" }
// { dg-message "evaluating '__builtin_source_location'" "" { target *-*-* } .-1 }
// { dg-do compile { target c++2a } }
namespace std {
struct source_location {
struct __impl {
const void *_M_file_name;
const char *_M_function_name;
int _M_line, _M_column;
};
};
}
auto x = __builtin_source_location (); // { dg-error "'std::source_location::__impl::_M_file_name' does not have 'const char \\*' type" }
// { dg-message "evaluating '__builtin_source_location'" "" { target *-*-* } .-1 }
// { dg-do compile { target c++2a } }
namespace std {
struct source_location {
struct __impl {
const char *_M_file_name;
const char *_M_function_name;
float _M_line;
int _M_column;
};
};
}
auto x = __builtin_source_location (); // { dg-error "'std::source_location::__impl::_M_line' does not have integral type" }
// { dg-message "evaluating '__builtin_source_location'" "" { target *-*-* } .-1 }
// { dg-do compile { target c++2a } }
namespace std {
struct source_location {
struct __impl {
// Test that ordering doesn't matter
long long _M_column;
const char *_M_file_name;
int _M_line;
const char *_M_function_name;
};
};
}
auto x = __builtin_source_location ();
// { dg-do compile { target c++2a } }
namespace std {
inline namespace _8 { }
namespace _8 {
struct source_location {
struct __impl {
const char *_M_file_name;
const char *_M_function_name;
unsigned int _M_line, _M_column;
};
const __impl *__ptr;
constexpr source_location () : __ptr (nullptr) {}
static consteval source_location
current (const void *__p = __builtin_source_location ()) {
source_location __ret;
__ret.__ptr = static_cast <const __impl *> (__p);
return __ret;
}
constexpr const char *file_name () const {
return __ptr ? __ptr->_M_file_name : "";
}
constexpr const char *function_name () const {
return __ptr ? __ptr->_M_function_name : "";
}
constexpr unsigned line () const {
return __ptr ? __ptr->_M_line : 0;
}
constexpr unsigned column () const {
return __ptr ? __ptr->_M_column : 0;
}
};
}
}
using namespace std;
consteval source_location
bar (const source_location x = source_location::current ())
{
return x;
}
void
foo (const char **p, unsigned *q)
{
constexpr source_location s = source_location::current ();
constexpr source_location t = bar ();
p[0] = s.file_name ();
p[1] = s.function_name ();
q[0] = s.line ();
q[1] = s.column ();
p[2] = t.file_name ();
p[3] = t.function_name ();
q[2] = t.line ();
q[3] = t.column ();
constexpr const char *r = s.file_name ();
}
source_location s3 = source_location::current ();
template <int N>
constexpr source_location
baz ()
{
return source_location::current ();
}
#define A \
source_location s[3] = { source_location::current (), \
source_location::current (), \
source_location::current () }
source_location *
boo ()
{
static A;
return &s[0];
}
constexpr source_location s1 = baz <0> ();
constexpr source_location s2 = baz <1> ();
const source_location *p1 = &s1;
const source_location *p2 = &s2;
static_assert (source_location::current ().line () == __LINE__);
static_assert (source_location::current ().column () == 42);
constexpr bool
quux ()
{
const char *file1 = source_location::current ().file_name ();
const char *file2 = __FILE__;
const char *function1 = source_location::current ().function_name ();
const char *function2 = __FUNCTION__;
int line1 = source_location::current ().line ();
int line2 = __LINE__ - 1;
int column
= source_location::current ().column ();
int i = 0;
for (; file1[i]; i++)
if (file1[i] != file2[i])
return false;
if (file2[i])
return false;
for (i = 0; function1[i]; i++)
if (function1[i] != function2[i])
return false;
if (function2[i])
return false;
if (line1 != line2)
return false;
if (column != 33)
return false;
return true;
}
static_assert (quux ());
// { dg-do compile { target c++2a } }
auto x = __builtin_source_location (); // { dg-error "'source_location' is not a member of 'std'" }
// { dg-message "std::source_location' is defined in header '<source_location>'; did you forget to '#include <source_location>'" "" { target *-*-* } .-1 }
// { dg-message "evaluating '__builtin_source_location'" "" { target *-*-* } .-2 }
// { dg-do compile { target c++2a } }
namespace std {
void source_location ();
}
auto x = __builtin_source_location (); // { dg-error "'void std::source_location\\(\\)' is not a type" }
// { dg-message "evaluating '__builtin_source_location'" "" { target *-*-* } .-1 }
// { dg-do compile { target c++2a } }
namespace std {
typedef int source_location;
}
auto x = __builtin_source_location (); // { dg-error "'std::source_location'\[^\n\r]*is not a class type" }
// { dg-error "'__impl' is not a member of 'std::source_location'" "" { target *-*-* } .-1 }
// { dg-message "evaluating '__builtin_source_location'" "" { target *-*-* } .-2 }
// { dg-do compile { target c++2a } }
namespace std {
struct source_location {
};
}
auto x = __builtin_source_location (); // { dg-error "'__impl' is not a member of 'std::source_location'" }
// { dg-message "evaluating '__builtin_source_location'" "" { target *-*-* } .-1 }
// { dg-do compile { target c++2a } }
namespace std {
struct source_location {
static void __impl ();
};
}
auto x = __builtin_source_location (); // { dg-error "'std::source_location::__impl\\(\\)' is not a type" }
// { dg-message "evaluating '__builtin_source_location'" "" { target *-*-* } .-1 }
// { dg-do compile { target c++2a } }
namespace std {
struct source_location {
typedef int __impl;
};
}
auto x = __builtin_source_location (); // { dg-error "'std::source_location::__impl()' is not a class type" }
// { dg-message "evaluating '__builtin_source_location'" "" { target *-*-* } .-1 }
// { dg-do compile { target c++2a } }
namespace std {
struct source_location {
struct __impl {
};
};
}
auto x = __builtin_source_location (); // { dg-error "'std::source_location::__impl' does not contain only non-static data members '_M_file_name', '_M_function_name', '_M_line' and '_M_column'" }
// { dg-message "evaluating '__builtin_source_location'" "" { target *-*-* } .-1 }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment