From: Mark Wooding Date: Thu, 26 May 2016 08:26:09 +0000 (+0100) Subject: src/c-types-{impl,parse}.lisp: Support C11 `_Atomic'. X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/sod/commitdiff_plain/ae0f15ee8427fa91cfd1945bfded847032cb8a25 src/c-types-{impl,parse}.lisp: Support C11 `_Atomic'. This change adds support for both the `_Atomic' type qualifier and the `_Atomic(...)' type specifier. --- diff --git a/doc/SYMBOLS b/doc/SYMBOLS index ced5f77..8395db3 100644 --- a/doc/SYMBOLS +++ b/doc/SYMBOLS @@ -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 diff --git a/doc/clang.tex b/doc/clang.tex index 700033f..348c5b6 100644 --- a/doc/clang.tex +++ b/doc/clang.tex @@ -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(@)|. + + The @ 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 @ @^*)| returns a type + qualified atomic @, where @ is the type specified by + @ and the @s are qualifier keywords (which are + evaluated). +\end{describe} + +\begin{describe}{fun} + {make-atomic-type @ \&optional @ @> @} + Return an object describing the type qualified atomic @. If + @ 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 diff --git a/doc/syntax.tex b/doc/syntax.tex index 5f8c89e..560dc47 100644 --- a/doc/syntax.tex +++ b/doc/syntax.tex @@ -451,8 +451,14 @@ recognized. \alt "bool" | "_Bool" \alt "imaginary" | "_Imaginary" | "complex" | "_Complex" \alt +\alt - ::= "const" | "volatile" | "restrict" + ::= | "const" | "volatile" | "restrict" + + ::= + "(" @^+ ")" + + ::= "atomic" | "_Atomic" ::= \end{grammar} @@ -472,6 +478,7 @@ combinations are permitted. A declaration specifier must consist of zero or more @s, and one of the following, up to reordering. \begin{itemize} \item @ +\item @ \item @"struct" @, @"union" @, @"enum" @ \item @"void" \item @"_Bool", @"bool" @@ -509,6 +516,8 @@ All of these have their usual C meanings. ::= @^+ + ::= $[\epsilon]$ + ::= $[\mbox{@ @! $\epsilon$}]$ ::= $[\mbox{@}]$ diff --git a/src/c-types-impl.lisp b/src/c-types-impl.lisp index be679a0..d0d4a74 100644 --- a/src/c-types-impl.lisp +++ b/src/c-types-impl.lisp @@ -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 "~:@" + (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. diff --git a/src/c-types-parse.lisp b/src/c-types-parse.lisp index 4244d3e..92f999a 100644 --- a/src/c-types-parse.lisp +++ b/src/c-types-parse.lisp @@ -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. diff --git a/src/sod-module.5 b/src/sod-module.5 index 21a9fee..86b124d 100644 --- a/src/sod-module.5 +++ b/src/sod-module.5 @@ -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]"