Name
	alx-0004r10 - adopt qualifier conversion rules from C++98

Principles
	-  Codify existing practice to address evident deficiencies.
	-  Do not leave features in an underdeveloped state.
	-  Enable secure programming.
	-  Facilitate interoperability.

Category
	Language; conversions; pointers.

Author
	Alejandro Colomar <alx@kernel.org>

	Cc: Christopher Bazley <chris.bazley.wg14@gmail.com>
	Cc: Philipp Klaus Krause <philipp@informatik.uni-frankfurt.de>
	Cc: Aaron Ballman <aaron@aaronballman.com>
	Cc: Joseph Myers <josmyers@redhat.com>
	Cc: Jonathan Wakely <jwakely@redhat.com>
	Cc: наб <nabijaczleweli@nabijaczleweli.xyz>
	Cc: Halalaluyafail3 <luigighiron@gmail.com>
	Cc: Keith Thompson <keith.s.thompson@gmail.com>
	Cc: Thiago Adams <thiago.adams@gmail.com>

History
	<https://www.alejandro-colomar.es/src/alx/alx/wg14/alx-0004.git/>

	r0 (2025-03-15):
	-  Initial draft.

	r1 (2025-03-17):
	-  Fix recursive wording.  The types in tN might be qualified at
	   any level as long as the corresponding uN is qualified,
	   regardless of the qualification of t(N-1).  At least that's
	   what g++(1) seems to accept.

	r2 (2025-05-04):
	-  Fix typos.
	-  Remove bogus link from 'See also'.
	-  Add links to 'See also'.
	-  Mention n3510 in 'See also'.
	-  Use the wording in C++11.  The wording I had was bogus; and
	   the wording in the current versions of C++ is too complex for
	   me to understand it.  The wording of C++11 is slightly less
	   powerful than the current one, but on the other hand it's not
	   a bad idea to fall short on allowed conversions, just in
	   case.  If we want to lift more restrictions, we're always in
	   time.

	r3 (2025-06-29; n3629):
	-  Complete reword, using wording from
	   n3510 (Bazley; "Enhanced type variance (v2)").  This is even
	   simpler than the wording from C++11 I had picked earlier, and
	   works much better (I don't need to add extra wording to make
	   it work with the existing standard).

	Brno (2025-08):
	-  Joseph: Needs some wording fixes mentioned in the reflector.
	-  Along the lines support: 23y/0n/6a

	r4 (2025-12-01; n3749):
	-  tfix, pfix
	-  Add example.
	-  Add footnote.
	-  Add requirement that RHS is a pointer.
	-  Expand a bit on the Description and See also sections.

	r5 (2026-02-03):
	-  Rebase on n3783.
	-  Specify comparable types.  [taken from n3674]
	-  Specify representation and alignment of comparable types.
	-  Remove some text from 6.2.5p32, which is now redundant.
	-  Update 6.2.6.3p1 about representation of comparable types.
	-  Update 6.5.1p9 about substitutable types and lvalues.
	-  ffix

	r6 (2026-04-17):
	-  Rebase on n3854 + alx-0086 + alx-0091.
	-  Update with wording from n3674

	r7 (2026-08-22):
	-  Remove redundant sentence.
	-  Update old reference to n3510 with reference to n3674.
	-  Rebase after n3886, alx-0086r8, and alx-0091r2.

	r8 (2026-08-22):
	-  Rebase after alx-0091r3.
	-  Fix typo.  [Halalaluyafail3]
	-  Move 'Otherwise' bullet to all types.  [Halalaluyafail3]
	-  Suggest that a future proposal might adopt C++14 rules.

	r9 (2026-08-24):
	-  Add footnote YYY.
	-  Add CCs.

	r10 (2026-10-11; n3987):
	-  Rebase.

Description
	C is too strict regarding qualifiers, and requires the
	programmer to do casts or have functions with unnecessarily
	unqualified APIs.  C++ has shown that certain assignments can be
	done safely.  The following is forbidden by C, but allowed by
	C++:

		char               *p;
		const char *const  *pp = &p;

	I haven't added examples of invalid coversions, because we
	already have the widely known one in the standard.

See also
	<https://stackoverflow.com/a/8909208/6872717>
	<https://github.com/llvm/llvm-project/issues/129260>
	<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=17654#c11>
	<https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4261.html>
	<https://c-faq.com/ansi/constmismatch.html>
	<https://isocpp.org/wiki/faq/const-correctness#constptrptr-conversion>
	<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3674.pdf>

Future directions
	This proposal would interact with n3674 (see link above).  Both
	proposals intend to reduce the use of casts for converting
	pointers, in order to have stronger type safety.  n3674 also
	covers function pointers, while this proposal focuses on
	pointers to pointers.  Both proposals are compatible (and this
	one will reduce the diff of n3674), although care should be
	taken to make sure there are no merge conflicts.  This proposal
	is simpler than n3674, since we have prior art in C++, where it
	has been tested for a long time.  My intention for having this
	as a separate proposal is precisely that n3674 already has the
	essential wording in the standard, so that it becomes a simpler
	proposal.

	Another shorter step might be to take the rules from C++14,
	which are a bit more permissive than the current proposal, but
	not as permissive as n3674.

Proposed wording
	Based on N3886 + alx-0086r11 + alx-0091r4.
	
    6.2.6.3  Pointer types and nullptr_t
	@@ p1
	 A pointer to void
	 shall have the same representation and alignment requirements
	 as a pointer to a character type.
	 31)
	-Similarly,
	-pointers to
	-similar types
	-shall have the same representation and alignment requirements.
	 All pointers to structure types
	 shall have the same representation and alignment requirements
	 as each other.
	 All pointers to union types
	 shall have the same representation and alignment requirements
	 as each other.
	 Pointers to other types
	 may not have the same representation or alignment requirements.
	
	## The sentence being removed is now redundant, since qualified
	## or unqualified pointers to similar types are themselves
	## similar types (because of the added recursion in
	## similar types; see below in 6.2.7+1).
	
	## BTW, the standard had been incorrect (contrary to existing
	## practice, and to common sense), as only (access-)qualified or
	## unqualified versions of pointers to similar types should
	## have same representation and alignment requirements.
	## 'int *' and 'int *_Atomic' don't have the same requirements.
	
    6.2.7+1  Similar types
	@@ p1
	 Two types are similar types
	 if they would be compatible types
	 if all access qualifiers
	 were removed from both types,
	+including recursively from
	+every referenced type of a pointer type.
	-XXX)
	
	-XXX)
	-Only top-level qualifiers.
	
    6.2.7+2  Substitutable type
	@@ p2
	 A type, <tt>T</tt>,
	 is substitutable for another type, <tt>S</tt>,
	 if the following conditions are satisfied:
	
	  --	<tt>T</tt> and <tt>S</tt>
		are similar types;
		and
	  --	<tt>S</tt> has
		all the qualifiers of <tt>T</tt>.
	+	YYY)
	+ --	If both types are pointer types:
	+	--
	+		the referenced type of <tt>T</tt>
	+		is substitutable for
	+		the referenced type of <tt>S</tt>;
	+		and,
	+	--
	+		<tt>S</tt> is const-qualified if
	+		the referenced type of <tt>T</tt>
	+		is not compatible with
	+		the referenced type of <tt>S</tt>.
	+
	+YYY)
	+Only top-level qualifiers.
	
	@@ p2+1
	+2+1
	+	EXAMPLE
	+		#include <stddef.h>
	+
	+		volatile char *const *vpcp = NULL;
	+		volatile char *      *vpp = NULL;
	+		char          *const *pcp = NULL;
	+		char          *      *pp = NULL;
	+
	+		vpcp = vpp;
	+		vpcp = pcp;
	+		vpcp = pp;
	+		pcp = pp;
	+
	+	In this example,
	+	the types of
	+	all of <tt>*vpp</tt>, <tt>*pcp</tt>, and <tt>*pp</tt>
	+	are substitutable for
	+	the type of <tt>*vpcp</tt>,
	+	and the type of <tt>*pp</tt>
	+	is substitutable for the type of <tt>*pcp</tt>.