return r;
const bool type_p = SPLICE_SCOPE_TYPE_P (t);
if (dependent_splice_p (r))
- return make_splice_scope (r, type_p);
- if (type_p && ctad_template_p (r))
+ r = make_splice_scope (r, type_p);
+ else if (type_p && ctad_template_p (r))
r = make_template_placeholder (r);
if (type_p
? !valid_splice_type_p (r)
return error_mark_node;
}
+ if (type_p)
+ r = cp_build_qualified_type (r, cp_type_quals (t) | cp_type_quals (r),
+ complain | tf_ignore_bad_quals);
+
return r;
}
{
return (CLASS_TYPE_P (t)
|| TREE_CODE (t) == ENUMERAL_TYPE
- || TREE_CODE (t) == NAMESPACE_DECL);
+ || TREE_CODE (t) == NAMESPACE_DECL
+ || TREE_CODE (t) == SPLICE_SCOPE);
}
/* Return true if T is a valid result of the splice in a class member access,
--- /dev/null
+// PR c++/125096
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+#include <meta>
+#include <vector>
+
+namespace ctp {
+ template <class T> struct Reflect;
+
+ namespace impl {
+ template <class T> using custom_target = Reflect<T>::target_type;
+ }
+
+ template <class T>
+ using target = [: is_scalar_type(^^T) ? ^^T : substitute(^^impl::custom_target, {^^T}) :];
+
+ template <class T>
+ struct Reflect<std::vector<T>> {
+ using underlying = target<T> const;
+ using target_type = std::span<const target<T>>;
+ };
+}
+
+static_assert(dealias(^^ctp::target<int>) == ^^int);
+static_assert(dealias(^^ctp::target<std::vector<int>>) == ^^std::span<int const>);
+static_assert(dealias(^^ctp::Reflect<std::vector<int>>::underlying) == ^^int const);
+static_assert(dealias(^^ctp::Reflect<std::vector<int>>::target_type) == ^^std::span<int const>);
}
int main() {
- // ??? It's not clear which of these should error.
- std::default_accessor<int> _ = std::iterator_accessor<int*>();
- std::default_accessor<const int> _ = std::iterator_accessor<int*>(); // { dg-error "conversion" }
+ std::default_accessor<int> _ = std::iterator_accessor<int*>(); // { dg-error "conversion" }
+ std::default_accessor<const int> _ = std::iterator_accessor<int*>();
}