Validate a list of storage class specifiers.
(valid-stor-spec-list storspecs ident type fundefp table) → (mv erp typedefp linkage lifetime?)
This function is called on the sub-list of storage class specifiers of a list of declaration specifiers, after determining the identifier being declared and its type, which are both passed as input to this function, along with the current validation table.
Only a few sequences of storage class specifiers are allowed [C17:6.7.1/2],
also depending on whether the declaration is in a block or file scope
[C17:6.7.1/3],
which we can see from the validation table.
Each allowed sequence of storage class specifiers may determine
that a
If the storage class specifier sequence is
If the storage class specifier sequence is
If the storage class specifier sequence is
If the storage class specifier sequence is
If the storage class specifier sequence is
If the storage class specifier sequence is
If the storage class specifier sequence is
If there are no storage class specifiers (i.e. the sequence is empty),
things differ based on
whether the identifier declares an object or a function,
and whether we are in the file scope or a block scope.
If the type is that of a function,
linkage is determined as if it had the
We prove that if
The
Function:
(defun valid-stor-spec-list (storspecs ident type fundefp table) (declare (xargs :guard (and (stor-spec-listp storspecs) (identp ident) (typep type) (booleanp fundefp) (valid-tablep table)))) (b* (((reterr) nil (irr-linkage) nil)) (cond ((stor-spec-list-typedef-p storspecs) (retok t (linkage-none) nil)) ((stor-spec-list-extern-p storspecs) (b* ((linkage (b* (((mv info? &) (valid-lookup-ord ident table)) ((unless info?) (linkage-external)) ((unless (valid-ord-info-case info? :objfun)) (linkage-external)) (previous-linkage (valid-ord-info-objfun->linkage info?))) (if (linkage-case previous-linkage :none) (linkage-external) previous-linkage))) (lifetime? (if (type-case type :function) nil (lifetime-static)))) (retok nil linkage lifetime?))) ((stor-spec-list-extern-thread-p storspecs) (b* (((when (type-case type :function)) (retmsg$ "The storage class specifier '_Thread_local' ~ cannot be used in the declaration of the function ~x0." (ident-fix ident))) (linkage (b* (((mv info? &) (valid-lookup-ord ident table)) ((unless info?) (linkage-external)) ((unless (valid-ord-info-case info? :objfun)) (linkage-external)) (previous-linkage (valid-ord-info-objfun->linkage info?))) (if (linkage-case previous-linkage :none) (linkage-external) previous-linkage)))) (retok nil linkage (lifetime-thread)))) ((stor-spec-list-static-p storspecs) (b* ((block-scope-p (and (> (valid-table-num-scopes table) 1) (not fundefp))) ((when (and block-scope-p (type-case type :function))) (retmsg$ "The storage class specifier 'static' ~ cannot be used in the declaration of the function ~x0." (ident-fix ident))) (linkage (if block-scope-p (linkage-none) (linkage-internal))) (lifetime? (if (type-case type :function) nil (lifetime-static)))) (retok nil linkage lifetime?))) ((stor-spec-list-static-thread-p storspecs) (b* (((when (type-case type :function)) (retmsg$ "The storage class specifier '_Thread_local' ~ cannot be used in the declaration of the function ~x0." (ident-fix ident))) (block-scope-p (and (> (valid-table-num-scopes table) 1) (not fundefp))) (linkage (if block-scope-p (linkage-none) (linkage-internal))) (lifetime? (lifetime-thread))) (retok nil linkage lifetime?))) ((stor-spec-list-thread-p storspecs) (b* (((when (type-case type :function)) (retmsg$ "The storage class specifier '_Thread_local' ~ cannot be used in the declaration of the function ~x0." (ident-fix ident))) ((when (and (> (valid-table-num-scopes table) 1) (not fundefp))) (retmsg$ "The storage class specifier '_Thread_local' ~ cannot be used in a block scope ~ without 'extern' or 'static', ~ for the declaration of the object ~x0." (ident-fix ident)))) (retok nil (linkage-external) (lifetime-thread)))) ((or (stor-spec-list-auto-p storspecs) (stor-spec-list-register-p storspecs)) (b* (((when (type-case type :function)) (retmsg$ "The storage class specifier '~s0' ~ cannot be used in the declaration of the function ~x1." (if (stor-spec-list-auto-p storspecs) "auto" "register") (ident-fix ident))) ((unless (and (> (valid-table-num-scopes table) 1) (not fundefp))) (retmsg$ "The storage class specifier '~s0' ~ cannot be used in the file scope, for identifier ~x1." (if (stor-spec-list-auto-p storspecs) "auto" "register") (ident-fix ident)))) (retok nil (linkage-none) (lifetime-auto)))) ((endp storspecs) (if (type-case type :function) (b* (((mv info? &) (valid-lookup-ord ident table)) ((unless info?) (retok nil (linkage-external) nil)) ((unless (valid-ord-info-case info? :objfun)) (retok nil (linkage-external) nil)) (previous-linkage (valid-ord-info-objfun->linkage info?))) (if (linkage-case previous-linkage :none) (retok nil (linkage-external) nil) (retok nil previous-linkage nil))) (if (and (> (valid-table-num-scopes table) 1) (not fundefp)) (retok nil (linkage-none) (lifetime-auto)) (retok nil (linkage-external) (lifetime-static))))) (t (retmsg$ "The storage class specifier sequence ~x0 is invalid." (stor-spec-list-fix storspecs))))))
Theorem:
(defthm maybe-msgp-of-valid-stor-spec-list.erp (b* (((mv acl2::?erp ?typedefp ?linkage ?lifetime?) (valid-stor-spec-list storspecs ident type fundefp table))) (maybe-msgp erp)) :rule-classes :rewrite)
Theorem:
(defthm booleanp-of-valid-stor-spec-list.typedefp (b* (((mv acl2::?erp ?typedefp ?linkage ?lifetime?) (valid-stor-spec-list storspecs ident type fundefp table))) (booleanp typedefp)) :rule-classes :rewrite)
Theorem:
(defthm linkagep-of-valid-stor-spec-list.linkage (b* (((mv acl2::?erp ?typedefp ?linkage ?lifetime?) (valid-stor-spec-list storspecs ident type fundefp table))) (linkagep linkage)) :rule-classes :rewrite)
Theorem:
(defthm lifetime-optionp-of-valid-stor-spec-list.lifetime? (b* (((mv acl2::?erp ?typedefp ?linkage ?lifetime?) (valid-stor-spec-list storspecs ident type fundefp table))) (lifetime-optionp lifetime?)) :rule-classes :rewrite)
Theorem:
(defthm no-lifetime-of-valid-stor-spec-list-when-typedef (b* (((mv acl2::?erp ?typedefp ?linkage ?lifetime?) (valid-stor-spec-list storspecs ident type fundefp table))) (implies typedefp (not lifetime?))))
Theorem:
(defthm no-linkage-of-valid-stor-spec-list-when-typedef (b* (((mv acl2::?erp ?typedefp ?linkage ?lifetime?) (valid-stor-spec-list storspecs ident type fundefp table))) (implies typedefp (equal (linkage-kind linkage) :none))))
Theorem:
(defthm ext/int-linkage-of-valid-stor-spec-when-function (b* (((mv acl2::?erp ?typedefp ?linkage ?lifetime?) (valid-stor-spec-list storspecs ident type fundefp table))) (implies (and (not erp) (not typedefp) (type-case type :function)) (not (equal (linkage-kind linkage) :none)))))
Theorem:
(defthm ext/int-linkage-of-valid-stor-spec-list-when-file-object (b* (((mv acl2::?erp ?typedefp ?linkage ?lifetime?) (valid-stor-spec-list storspecs ident type fundefp table))) (implies (and (not erp) (not typedefp) (not (type-case type :function)) (equal (valid-table-num-scopes table) 1)) (not (equal (linkage-kind linkage) :none)))))
Theorem:
(defthm lifetime-of-valid-stor-spec-when-object (b* (((mv acl2::?erp ?typedefp ?linkage ?lifetime?) (valid-stor-spec-list storspecs ident type fundefp table))) (implies (and (not erp) (not typedefp) (not (type-case type :function))) lifetime?)))
Theorem:
(defthm extern/static/none-when-valid-stor-spec-list-function (b* (((mv acl2::?erp ?typedefp ?linkage ?lifetime?) (valid-stor-spec-list storspecs ident type fundefp table))) (implies (and (not erp) (not typedefp) (type-case type :function)) (or (stor-spec-list-extern-p storspecs) (stor-spec-list-static-p storspecs) (endp storspecs)))))
Theorem:
(defthm valid-stor-spec-list-of-stor-spec-list-fix-storspecs (equal (valid-stor-spec-list (stor-spec-list-fix storspecs) ident type fundefp table) (valid-stor-spec-list storspecs ident type fundefp table)))
Theorem:
(defthm valid-stor-spec-list-stor-spec-list-equiv-congruence-on-storspecs (implies (stor-spec-list-equiv storspecs storspecs-equiv) (equal (valid-stor-spec-list storspecs ident type fundefp table) (valid-stor-spec-list storspecs-equiv ident type fundefp table))) :rule-classes :congruence)
Theorem:
(defthm valid-stor-spec-list-of-ident-fix-ident (equal (valid-stor-spec-list storspecs (ident-fix ident) type fundefp table) (valid-stor-spec-list storspecs ident type fundefp table)))
Theorem:
(defthm valid-stor-spec-list-ident-equiv-congruence-on-ident (implies (ident-equiv ident ident-equiv) (equal (valid-stor-spec-list storspecs ident type fundefp table) (valid-stor-spec-list storspecs ident-equiv type fundefp table))) :rule-classes :congruence)
Theorem:
(defthm valid-stor-spec-list-of-type-fix-type (equal (valid-stor-spec-list storspecs ident (type-fix type) fundefp table) (valid-stor-spec-list storspecs ident type fundefp table)))
Theorem:
(defthm valid-stor-spec-list-type-equiv-congruence-on-type (implies (type-equiv type type-equiv) (equal (valid-stor-spec-list storspecs ident type fundefp table) (valid-stor-spec-list storspecs ident type-equiv fundefp table))) :rule-classes :congruence)
Theorem:
(defthm valid-stor-spec-list-of-bool-fix-fundefp (equal (valid-stor-spec-list storspecs ident type (bool-fix fundefp) table) (valid-stor-spec-list storspecs ident type fundefp table)))
Theorem:
(defthm valid-stor-spec-list-iff-congruence-on-fundefp (implies (iff fundefp fundefp-equiv) (equal (valid-stor-spec-list storspecs ident type fundefp table) (valid-stor-spec-list storspecs ident type fundefp-equiv table))) :rule-classes :congruence)
Theorem:
(defthm valid-stor-spec-list-of-valid-table-fix-table (equal (valid-stor-spec-list storspecs ident type fundefp (valid-table-fix table)) (valid-stor-spec-list storspecs ident type fundefp table)))
Theorem:
(defthm valid-stor-spec-list-valid-table-equiv-congruence-on-table (implies (valid-table-equiv table table-equiv) (equal (valid-stor-spec-list storspecs ident type fundefp table) (valid-stor-spec-list storspecs ident type fundefp table-equiv))) :rule-classes :congruence)