Defect Report #445
Previous Defect Report < - > Next Defect Report
  
  Submitter: Joseph Myers
  Submission Date: 2013-07-23
  
   Source: WG 14
  Reference Document:
   N1731
  Version: 1.1
  Date: April 2014
  Subject: Issues with alignment in C11, part 2
  Summary
There are various deficiencies in the C11 text about alignment
requirements.
  
  Issue 2: Contexts in which alignments are supported
  
6.2.8#2 defines "fundamental alignment": "A fundamental alignment is
represented by an alignment less than or equal to the greatest
alignment supported by the implementation in all contexts, which is
equal to _Alignof (max_align_t)."
  
6.2.8#3 defines "extended alignment": "An extended alignment is
represented by an alignment greater than _Alignof (max_align_t). It is
implementation-defined whether any extended alignments are supported
and the contexts in which they are supported. A type having an
extended alignment requirement is an over-aligned type."
  
6.2.8#4 defines "valid alignment", saying "Alignments are represented
as values of the type size_t. Valid alignments include only those
values returned by an _Alignof expression for fundamental types, plus
an additional implementation-defined set of values, which may be
empty. Every valid alignment value shall be a nonnegative integral
power of two.".
  
max_align_t is specified in 7.19#2 as "an object type whose alignment
is as great as is supported by the implementation in all contexts".
  
The memory management functions in 7.22.3 are defined to return a
pointer "suitably aligned so that it may be assigned to a pointer to
any type of object with a fundamental alignment requirement and then
used to access such an object or an array of such objects in the space
allocated".  In the case of aligned_alloc, there may be a stricter
requirement given by the alignment passed to the function, but the
alignment passed to the function can't result in memory any
less-aligned than a fundamental alignment requirement.  The alignment
requirement still applies even if the size is too small for any object
requiring the given alignment (see the response to C90 DR#075).
  
There are various problems with the above:
  
- 
  The term "fundamental type" is not defined in C11.  
  
 - 
There is also no definition of what a "context" is in which an
  alignment might or might not be supported.  In common implementation
  practice, separate contexts might be by the storage duration of the
  object (static, thread, automatic, allocated, with the last
  referring to the alignments guaranteed by calloc, malloc and
  realloc).
  
 - 
A "valid alignment" may not be a "fundamental alignment".  Thus,
  whatever interpretation is adopted for "fundamental type", nothing
  in the standard requires the alignment of a "fundamental type" to be
  a "fundamental alignment".  For example, say "long double" is a
  "fundamental type"; it would seem nonsensical if declaring "long
  double" objects (in any context) failed to work, but nothing seems
  to require malloc to return objects sufficiently aligned for long
  double.
  
 - 
Given these gaps in the definition, nothing in the normative text
  appears to imply footnote 57 "Every over-aligned type is, or
  contains, a structure or union type with a member to which an
  extended alignment has been applied.", although no doubt it reflects
  the intent.
  
 - 
If "fundamental type" is interpreted to mean "basic type", that is
  not sufficient to resolve these lacunae.  For example, if
  
  struct s { long double ld; }
  
has an alignment requirement bigger than long double, it should
  still be possible to allocate memory for it with malloc, and the
  same applies to any typedef from a standard header that might also
  have a bigger alignment requirement than any basic type.
  
 
  
The following principles seem natural for any fix for this issue:
  
- 
C99 referred to "any type of object" in the alignment requirements
  for calloc, malloc and realloc.  As a matter of compatibility, this
  means that any type that could be constructed within C99 (including
  one using types from standard headers) should have an alignment
  required by C11 to be supported in all contexts, and the same
  applies to types from C extensions originally specified as
  extensions to C99.  Most of the following principles follow to a
  greater or lesser extent from this compatibility principle.
  
 - 
All basic types have alignments supported in all contexts.  
  
 - 
  All enumerated types have alignments supported in all contexts.
  
 - 
  All pointer types have alignments supported in all contexts (even if
  the type pointed to does not).
  
 - 
  All types from standard headers specified as complete object types
  in the definitions of those headers have alignments supported in all
  contexts.  (This includes both types specified as typedefs and types
specified as structs or unions with a given tag.)
  
 - 
  If a type has an alignment supported in all contexts, so do arrays
  of that type, qualified versions of that type, and atomic versions
  of that type.
  
 - 
  If all the members of a structure or union have types with
  alignments supported in all contexts, and none of them use an
  _Alignas specifier specifying an alignment bigger than supported in
  all contexts, then that structure or union has an alignment
  supported in all contexts.
  
 - 
  Where C extensions such as TS 18661-2 and 18661-3 are proposed that
  define new types, or existing such extensions such as TR 18037 are
  revised and updated for C11, care should be taken that the new types
  are covered under the above, whether through being basic types or
  through being defined in standard headers.  (If SIMD vector types,
  as mentioned at
  http://www.open-std.org/pipermail/cplex/2013-June/000010.html,
  were to end up in any such extension, it would probably be
  appropriate to define them in a way that does *not* require calloc,
  malloc and realloc to return memory suitably aligned for them; such
  types often require alignments bigger than needed for any other
  type, so imposing such requirements on memory allocation functions
  would result in undue inefficiency.)  
  
 
  
  
  Oct 2013 meeting
  Committee Discussion
  - 
  It is indeed the case that 6.2.8p3 "fundamental type" is not defined. The intention
  is that it be "basic type", such that "fundamental alignment" is well defined, and yet this is not the case, and "fundamental alignment" also needs a definition.  It is likely that the definition of fundamental type can be made editorially, but that when and where fundamental alignment is required is substantive.
  
 - 
  It is also the case that 6.2.8p3 "contexts" is not defined.  It is intended to mean the full set of storage durations.  Perhaps we should say "storage duration contexts".
  
 - 
  It is also the case that "valid alignment" may not be a "fundamental alignment".
  
 - It was the case in C99 that malloc was required to return memory appropriate for "any type", and this should not be lost in the new wording regarding types that are not over-aligned.  All other C99 behaviors must also be preserved as he describes as guidance.
  
 - 
  All types declared without the _Alignas directive are intended to have fundamental alignment, which must be tied somehow to basic type.  A consequence is that the only manner in which one can produce an over-aligned type is through _Alignas.  malloc has been defined in terms of fundamental alignment, yet we do not anywhere strongly state that, say, int has such fundamental alignment.
  
 - 
  These are several interwoven definitions and missing definitions that need a comprehensive review for adequate correction.  We solicit the author for a suggested technical corrigendum. A copy of the audio discussion can be provided.
  
 
  Apr 2014 meeting
  Committee Discussion
  - 
  The author provided input to
   N1804 as a proposed technical corrigendum:
  
 - 
Change 6.2.8#2 to:
A fundamental alignment is a valid alignment less than or equal to 
_Alignof (max_align_t).  Fundamental alignments shall be supported by the 
implementation for objects of all storage durations.  The alignment 
requirements of the following types shall be fundamental alignments:
- 
all atomic, qualified or unqualified basic types;
 - 
all atomic, qualified or unqualified enumerated types;
 - 
all atomic, qualified or unqualified pointer types;
 - 
all array types whose element type has a fundamental alignment 
requirement;
 - 
all types specified in clause 7 as complete object types;
 - 
all structure or union types all of whose elements have types with 
fundamental alignment requirements and none of whose elements have an 
alignment specifier specifying an alignment that is not a fundamental 
alignment.
 
In 6.2.8#3, change "the contexts in" to "the storage durations of objects 
for which".
In 6.2.8#4, change "those values returned by an _Alignof expression for 
fundamental types" to "fundamental alignments".
(Note that the above admits the possibility that e.g. 1 and 4 are 
fundamental alignments, but 2 isn't, in which case it can't be an extended 
alignment either.  If we want to ensure that 2 isn't a valid alignment at 
all in that case, rather than possibly having valid alignments that are 
neither fundamental nor extended, also change "additional 
implementation-defined set of values" to "additional 
implementation-defined set of extended alignments" in 6.2.8#4.)
In 6.7.5#3, change "in the context in which it appears" to "for an object 
of the storage duration, if any, being declared".  Add a new constraint at 
the end of 6.7.5#3: "An object shall not be declared with an over-aligned 
type with an extended alignment requirement not supported by the 
implementation for an object of that storage duration.".
(This deals with the point that if an over-aligned struct is defined, then 
objects with that type may be supported with some storage durations but 
not others, so it is the declaration of an object with that type that can 
violate a constraint rather than the declaration of the struct.)
In 7.19#2, change "whose alignment is as great as is supported by the 
implementation in all contexts" to "whose alignment is the greatest 
fundamental alignment".
(I'm trying to avoid an undesirable implication that if an alignment of 
e.g. 1MB is supported in all contexts - and it's quite plausible that an 
implementation can support more or less arbitrary alignments - then 
max_align_t must have such an alignment and so such an alignment must 
count as fundamental and so malloc must return memory suitable aligned for 
it.)
  
 - 
  This is a difficult area and further study is required.
  
 
  
  Previous Defect Report < - >
  Next Defect Report