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));
+ return fold_builtin_source_location (t);
}
int strops = 0;
break;
case CP_BUILT_IN_SOURCE_LOCATION:
*expr_p
- = fold_builtin_source_location (EXPR_LOCATION (*expr_p));
+ = fold_builtin_source_location (*expr_p);
break;
case CP_BUILT_IN_IS_CORRESPONDING_MEMBER:
*expr_p
case CP_BUILT_IN_IS_CONSTANT_EVALUATED:
break;
case CP_BUILT_IN_SOURCE_LOCATION:
- x = fold_builtin_source_location (EXPR_LOCATION (x));
+ x = fold_builtin_source_location (x);
break;
case CP_BUILT_IN_IS_CORRESPONDING_MEMBER:
x = fold_builtin_is_corresponding_member
&& fndecl_built_in_p (callee, CP_BUILT_IN_SOURCE_LOCATION,
BUILT_IN_FRONTEND))
{
- x = fold_builtin_source_location (EXPR_LOCATION (x));
+ x = fold_builtin_source_location (x);
break;
}
return remove_attribute ("gnu", "assume", 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. */
+/* Return the type std::source_location::__impl after performing
+ verification on it. */
-static tree
-get_source_location_impl_type (location_t loc)
+tree
+get_source_location_impl_type ()
{
tree name = get_identifier ("source_location");
tree decl = lookup_qualified_name (std_node, name);
{
auto_diagnostic_group d;
if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
- qualified_name_lookup_error (std_node, name, decl, loc);
+ qualified_name_lookup_error (std_node, name, decl, input_location);
else
- error_at (loc, "%qD is not a type", decl);
+ error ("%qD is not a type", decl);
return error_mark_node;
}
name = get_identifier ("__impl");
{
auto_diagnostic_group d;
if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
- qualified_name_lookup_error (type, name, decl, loc);
+ qualified_name_lookup_error (type, name, decl, input_location);
else
- error_at (loc, "%qD is not a type", decl);
+ error ("%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);
+ error ("%qD is not a class type", decl);
return error_mark_node;
}
{
if (TREE_TYPE (field) != const_string_type_node)
{
- error_at (loc, "%qD does not have %<const char *%> type",
- field);
+ error ("%qD does not have %<const char *%> type", field);
return error_mark_node;
}
cnt++;
{
if (TREE_CODE (TREE_TYPE (field)) != INTEGER_TYPE)
{
- error_at (loc, "%qD does not have integral type", field);
+ error ("%qD does not have integral type", field);
return error_mark_node;
}
cnt++;
}
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%>");
+ error ("%<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);
*source_location_table;
static GTY(()) unsigned int source_location_id;
-/* Fold __builtin_source_location () call. LOC is the location
- of the call. */
+/* Fold the __builtin_source_location () call T. */
tree
-fold_builtin_source_location (location_t loc)
+fold_builtin_source_location (const_tree t)
{
- 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");
- }
+ gcc_assert (TREE_CODE (t) == CALL_EXPR);
+ /* TREE_TYPE (t) is const std::source_location::__impl* */
+ tree source_location_impl = TREE_TYPE (TREE_TYPE (t));
if (source_location_impl == error_mark_node)
return build_zero_cst (const_ptr_type_node);
+ gcc_assert (CLASS_TYPE_P (source_location_impl)
+ && id_equal (TYPE_IDENTIFIER (source_location_impl), "__impl"));
+
+ location_t loc = EXPR_LOCATION (t);
if (source_location_table == NULL)
source_location_table
= hash_table <source_location_table_entry_hash>::create_ggc (64);
entryp->var = var;
}
- return build_fold_addr_expr_with_type_loc (loc, var, const_ptr_type_node);
+ return build_fold_addr_expr_with_type_loc (loc, var, TREE_TYPE (t));
}
#include "gt-cp-cp-gimplify.h"
CPTI_PSEUDO_CONTRACT_VIOLATION,
- CPTI_SOURCE_LOCATION_IMPL,
-
CPTI_FALLBACK_DFLOAT32_TYPE,
CPTI_FALLBACK_DFLOAT64_TYPE,
CPTI_FALLBACK_DFLOAT128_TYPE,
/* 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. */
extern tree build_assume_call (location_t, tree);
extern tree process_stmt_assume_attribute (tree, tree, location_t);
extern bool simple_empty_class_p (tree, tree, tree_code);
-extern tree fold_builtin_source_location (location_t);
+extern tree fold_builtin_source_location (const_tree);
+extern tree get_source_location_impl_type ();
/* in name-lookup.cc */
extern tree strip_using_decl (tree);
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);
+ /* The concrete return type of __builtin_source_location is
+ const std::source_location::__impl*, but we can't form the type
+ at this point. So we initially declare it with an auto return
+ type which we then "deduce" from require_deduced_type upon first use. */
+ tree auto_ftype = build_function_type_list (make_auto (), NULL_TREE);
decl = add_builtin_function ("__builtin_source_location",
- cptr_ftype, CP_BUILT_IN_SOURCE_LOCATION,
+ auto_ftype, CP_BUILT_IN_SOURCE_LOCATION,
BUILT_IN_FRONTEND, NULL, NULL_TREE);
set_call_expr_flags (decl, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
{
if (undeduced_auto_decl (decl))
{
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && fndecl_built_in_p (decl, BUILT_IN_FRONTEND)
+ && DECL_FE_FUNCTION_CODE (decl) == CP_BUILT_IN_SOURCE_LOCATION)
+ {
+ /* Set the return type of __builtin_source_location. */
+ tree type = get_source_location_impl_type ();
+ if (type == error_mark_node)
+ {
+ inform (input_location, "using %qs", "__builtin_source_location");
+ return false;
+ }
+ type = cp_build_qualified_type (type, TYPE_QUAL_CONST);
+ type = build_pointer_type (type);
+ apply_deduced_return_type (decl, type);
+ return true;
+ }
+
if (warning_suppressed_p (decl) && seen_error ())
/* We probably already complained about deduction failure. */;
else if (complain & tf_error)
}
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-message "using '__builtin_source_location'" "" { target *-*-* } .-1 }
}
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-message "using '__builtin_source_location'" "" { target *-*-* } .-1 }
}
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-message "using '__builtin_source_location'" "" { target *-*-* } .-1 }
}
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-message "using '__builtin_source_location'" "" { target *-*-* } .-1 }
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-message "using '__builtin_source_location'" "" { target *-*-* } .-2 }
}
auto x = __builtin_source_location (); // { dg-error "'void std::source_location\\(\\)' is not a type" }
-// { dg-message "evaluating '__builtin_source_location'" "" { target *-*-* } .-1 }
+// { dg-message "using '__builtin_source_location'" "" { target *-*-* } .-1 }
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-message "using '__builtin_source_location'" "" { target *-*-* } .-2 }
}
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-message "using '__builtin_source_location'" "" { target *-*-* } .-1 }
}
auto x = __builtin_source_location (); // { dg-error "'std::source_location::__impl\\(\\)' is not a type" }
-// { dg-message "evaluating '__builtin_source_location'" "" { target *-*-* } .-1 }
+// { dg-message "using '__builtin_source_location'" "" { target *-*-* } .-1 }
}
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-message "using '__builtin_source_location'" "" { target *-*-* } .-1 }
}
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-message "using '__builtin_source_location'" "" { target *-*-* } .-1 }
--- /dev/null
+// PR c++/100881
+// { dg-additional-options "-std=c++20 -fmodules-ts" }
+// { dg-module-cmi pr100881 }
+module;
+#include <source_location>
+export module pr100881;
+
+export
+consteval int
+current_line_fn(const std::source_location& loc = std::source_location::current())
+{
+ return loc.line();
+}
+
+export
+struct current_line_cls
+{
+ int line = std::source_location::current().line();
+};
+
+export
+template<class T>
+consteval int
+current_line_fn_tmpl(const std::source_location& loc = std::source_location::current())
+{
+ return loc.line();
+}
+
+export
+template<class T>
+struct current_line_cls_tmpl
+{
+ int line = std::source_location::current().line();
+};
--- /dev/null
+// PR c++/100881
+// { dg-additional-options "-std=c++20 -fmodules-ts" }
+import pr100881;
+
+static_assert(current_line_fn() == 5);
+static_assert(current_line_cls{}.line == 6);
+static_assert(current_line_fn_tmpl<int>() == 7);
+static_assert(current_line_cls_tmpl<int>{}.line == 8);