chiark / gitweb /
src/c-types-{impl,parse}.lisp: Support C11 `_Atomic'.
authorMark Wooding <mdw@distorted.org.uk>
Thu, 26 May 2016 08:26:09 +0000 (09:26 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 29 May 2016 14:25:52 +0000 (15:25 +0100)
This change adds support for both the `_Atomic' type qualifier and the
`_Atomic(...)' type specifier.

doc/SYMBOLS
doc/clang.tex
doc/syntax.tex
src/c-types-impl.lisp
src/c-types-parse.lisp
src/sod-module.5

index ced5f77fe7b4c8ab1ac93778e06399fb1d1f3e81..8395db37a0d4e4fe1b1257f04762e821855caf31 100644 (file)
@@ -17,9 +17,11 @@ c-types-class-impl.lisp
 c-types-impl.lisp
   cl:*                                          variable function c-type
   cl:array                                      class c-type
+  atomic                                        c-type
   bool                                          c-type
   c-array-dimensions                            generic
   c-array-type                                  class
+  c-atomic-type                                 class
   c-enum-type                                   class
   c-function-arguments                          generic
   c-function-type                               class
@@ -82,6 +84,7 @@ c-types-impl.lisp
   long-long                                     c-type
   long-long-int                                 c-type
   make-array-type                               function
+  make-atomic-type                              function
   make-c-tagged-type                            function
   make-enum-type                                function
   make-function-type                            function
@@ -586,6 +589,7 @@ cl:t
         c-array-type
         c-function-type
         qualifiable-c-type
+          c-atomic-type
           c-pointer-type
           simple-c-type
             c-class-type
@@ -685,6 +689,7 @@ c-fragment-text
 c-function-arguments
   c-function-type
 c-qualifier-keyword
+  (eql :atomic)
   cl:symbol
 c-tagged-type-kind
   c-enum-type
@@ -697,6 +702,7 @@ c-type-class
 c-type-equal-p
   t t
   c-array-type c-array-type
+  c-atomic-type c-atomic-type
   c-class-type c-class-type
   c-function-type c-function-type
   c-pointer-type c-pointer-type
@@ -709,6 +715,7 @@ c-type-qualifiers
   qualifiable-c-type
 c-type-subtype
   c-array-type
+  c-atomic-type
   c-function-type
   c-pointer-type
 c-type-tag
@@ -876,6 +883,7 @@ expand-c-type-form
   (eql cl:function) t
   (eql cl:nil) t
   (eql cl:union) t
+  (eql atomic) t
   (eql bool) t
   (eql double) t
   (eql double-complex) t
@@ -1171,6 +1179,7 @@ module-pset
 pprint-c-type
   t t t
   c-array-type t t
+  c-atomic-type t t
   c-function-type t t
   c-pointer-type t t
   simple-c-type t t
@@ -1180,6 +1189,7 @@ primary-method-class
   standard-message
 print-c-type
   t c-array-type
+  t c-atomic-type
   t c-class-type
   t c-function-type
   t c-pointer-type
index 700033fe5e6976c7dc57f0e8cf6e8124d03c6f47..348c5b634d827510edbba760982ad982b43e3fd0 100644 (file)
@@ -46,6 +46,7 @@ The class hierarchy is shown in~\xref{fig:codegen.c-types.classes}.
           @|c-struct-type| \\
           @|c-union-type| \\
           @|c-enum-type| \- \\
+        @|c-atomic-type| \\
         @|c-pointer-type| \- \\
       @|c-array-type| \\
       @|c-function-type|
@@ -306,6 +307,29 @@ argument lists for methods.  This is done by @|c-type-equal-p|.
 \subsection{Type qualifiers and qualifiable types}
 \label{sec:clang.ctypes.qual}
 
+Qualifiers -- @|const|, @|volatile|, and so on -- are represented as lists of
+keywords attached to types.  Not all C types can carry qualifiers: notably,
+function and array types cannot be qualified.
+
+For the most part, the C qualifier keywords correspond to like-named Lisp
+keywords, only the Lisp keyword names are in uppercase.  The correspondence
+is shown in \xref{tab:clang.ctypes.qual}.
+
+\begin{table}
+  \begin{tabular}[C]{*2{>{\codeface}l}l}                           \hlx*{hv}
+    \thd{\textbf{C name}}       & \thd{\textbf{Lisp name}}      \\ \hlx{vhv}
+    _Atomic                     & :atomic                       \\
+    const                       & :const                        \\
+    restrict                    & :restrict                     \\
+    volatile                    & :volatile                     \\ \hlx*{vh}
+  \end{tabular}
+  \caption{C and Lisp qualifier names} \label{tab:clang.ctypes.qual}
+\end{table}
+
+The default behaviour, on output, is to convert keywords to lowercase and
+hope for the best: special cases can be dealt with by adding appropriate
+methods to \descref{c-qualifier-keyword}{gf}.
+
 \begin{describe}{cls}{qualifiable-c-type (c-type) \&key :qualifiers}
   The class @|qualifiable-c-type| describes C types which can bear
   `qualifiers' (\Cplusplus\ calls them `cv-qualifiers'): @|const|,
@@ -559,6 +583,38 @@ protocol.
 \end{describe}
 
 
+\subsection{Atomic types} \label{sec:clang.c-types.atomic}
+
+Atomic types are compound types.  The subtype of an atomic type is simply the
+underlying type of the object.  Note that, as far as Sod is concerned, atomic
+types are not the same as atomic-qualified types: you must be consistent
+about which you use.
+
+\begin{describe}{cls}
+    {c-atomic-type (qualifiable-c-type) \&key :qualifiers :subtype}
+  Represents an atomic type.  An instance denotes the C type
+  @|_Atomic(@<subtype>)|.
+
+  The @<subtype> may be any C type.\footnote{%
+    C does not permit atomic function or array types.} %
+  Two atomic types are equal if and only if their subtypes are equal and they
+  have matching qualifiers.  It is possible, though probably not useful, to
+  have an atomic-qualified atomic type.
+
+  The type specifier @|(atomic @<type-spec> @<qualifier>^*)| returns a type
+  qualified atomic @<subtype>, where @<subtype> is the type specified by
+  @<type-spec> and the @<qualifier>s are qualifier keywords (which are
+  evaluated).
+\end{describe}
+
+\begin{describe}{fun}
+    {make-atomic-type @<c-type> \&optional @<qualifiers> @> @<c-atomic-type>}
+  Return an object describing the type qualified atomic @<subtype>.  If
+  @<subtype> is interned, then the returned atomic type object is interned
+  also.
+\end{describe}
+
+
 \subsection{Pointer types} \label{sec:clang.c-types.pointer}
 
 Pointers are compound types.  The subtype of a pointer type is the type it
index 5f8c89eddc280908dd07eb4a0a1925f5fd26d410..560dc47334a417ece602f842aff8f147a623384b 100644 (file)
@@ -451,8 +451,14 @@ recognized.
 \alt "bool" | "_Bool"
 \alt "imaginary" | "_Imaginary" | "complex" | "_Complex"
 \alt <qualifier>
+\alt <atomic-type>
 
-<qualifier> ::= "const" | "volatile" | "restrict"
+<qualifier> ::= <atomic> | "const" | "volatile" | "restrict"
+
+<atomic-type> ::=
+  <atomic> "(" @<declaration-specifier>^+ <abstract-declarator> ")"
+
+<atomic> ::= "atomic" | "_Atomic"
 
 <type-name> ::= <identifier>
 \end{grammar}
@@ -472,6 +478,7 @@ combinations are permitted.  A declaration specifier must consist of zero or
 more @<qualifier>s, and one of the following, up to reordering.
 \begin{itemize}
 \item @<type-name>
+\item @<atomic-type>
 \item @"struct" @<identifier>, @"union" @<identifier>, @"enum" @<identifier>
 \item @"void"
 \item @"_Bool", @"bool"
@@ -509,6 +516,8 @@ All of these have their usual C meanings.
 
 <argument> ::= @<declaration-specifier>^+ <argument-declarator>
 
+<abstract-declarator> ::= <declarator>$[\epsilon]$
+
 <argument-declarator> ::= <declarator>$[\mbox{@<identifier> @! $\epsilon$}]$
 
 <simple-declarator> ::= <declarator>$[\mbox{@<identifier>}]$
index be679a0b4e77f4de3ed30c0ffe42d72cfef35b89..d0d4a74a43b65f28baf9d6ef4defb5fab37d54af 100644 (file)
@@ -282,6 +282,55 @@ (defmethod print-c-type (stream (type tagged-c-type) &optional colon atsign)
          (c-type-tag type)
          (c-type-qualifiers type)))
 
+;;;--------------------------------------------------------------------------
+;;; Atomic types.
+
+;; Class definition.
+
+(export 'c-atomic-type)
+(defclass c-atomic-type (qualifiable-c-type)
+  ((subtype :initarg :subtype :type c-type :reader c-type-subtype))
+  (:documentation "C atomic types."))
+
+;; Constructor function.
+
+(export 'make-atomic-type)
+(defun make-atomic-type (subtype &optional qualifiers)
+  "Return a (maybe distinguished) atomic type."
+  (make-or-intern-c-type 'c-atomic-type subtype
+                        :subtype subtype
+                        :qualifiers (canonify-qualifiers qualifiers)))
+
+;; Comparison protocol.
+
+(defmethod c-type-equal-p and ((type-a c-atomic-type) (type-b c-atomic-type))
+  (c-type-equal-p (c-type-subtype type-a) (c-type-subtype type-b)))
+
+;; C-syntax output protocol.
+
+(defmethod pprint-c-type ((type c-atomic-type) stream kernel)
+  (pprint-logical-block (stream nil)
+    (format stream "~{~A ~@_~}" (c-type-qualifier-keywords type))
+    (write-string "_Atomic(" stream)
+    (pprint-indent :current 0 stream)
+    (pprint-c-type (c-type-subtype type) stream
+                  (lambda (stream prio spacep)
+                    (declare (ignore stream prio spacep))))
+    (write-char #\) stream)))
+
+;; S-expression notation protocol.
+
+(defmethod print-c-type (stream (type c-atomic-type) &optional colon atsign)
+  (declare (ignore colon atsign))
+  (format stream "~:@<ATOMIC ~@_~/sod:print-c-type/~{ ~_~S~}~:>"
+         (c-type-subtype type)
+         (c-type-qualifiers type)))
+
+(export 'atomic)
+(define-c-type-syntax atomic (sub &rest quals)
+  "Return the type of atomic SUB."
+  `(make-atomic-type ,(expand-c-type-spec sub) (list ,@quals)))
+
 ;;;--------------------------------------------------------------------------
 ;;; Pointer types.
 
index 4244d3e5a3b23a5beafd6ea63ca4d6c0074a4525..92f999aaf2c451fee56b6f5b9acc542943750588 100644 (file)
@@ -262,6 +262,19 @@ (defun scan-simple-declspec
           (scanner-step scanner)
           (values ds t t)))))
 
+(define-pluggable-parser complex-declspec atomic-typepsec (scanner)
+  ;; `atomic' `(' type-name `)'
+  ;; `_Atomic' `(' type-name `)'
+  (with-parser-context (token-scanner-context :scanner scanner)
+    (parse (peek (seq ((nil (or "atomic" "_Atomic"))
+                      #\(
+                      (decls (parse-c-type scanner))
+                      (subtype (parse-declarator scanner decls
+                                                 :kernel (parse-empty)
+                                                 :abstractp t))
+                      #\))
+                  (make-atomic-type (car subtype)))))))
+
 (defun scan-and-merge-declspec (scanner specs)
   "Scan a declaration specifier and merge it with SPECS.
 
index 21a9feeeae0e621d5203bfb05d62e93655f44ad2..86b124d864908aa470aafb28ba1a72053784cc67 100644 (file)
@@ -712,15 +712,34 @@ class-definition
 .B _Complex
 .|
 .I qualifier
+.|
+.I atomic-type
 .br
 .I qualifier
 ::=
+.I atomic
+|
 .B const
 |
 .B volatile
 |
 .B restrict
 .br
+.I atomic-type
+::=
+.I
+atomic
+.B (
+.IR declaration-specifier \*+
+.I abstract-declarator
+.B )
+.br
+.I atomic
+::=
+.B atomic
+|
+.B _Atomic
+.br
 .I type-name
 ::=
 .I identifier
@@ -854,6 +873,10 @@ and one of the following, up to reordering.
 .IR declaration-specifier \*+
 .I argument-declarator
 .br
+.I abstract-declarator
+::=
+.IR declarator [\*e]
+.br
 .I argument-declarator
 ::=
 .IR declarator [ identifier " | \*e]"