はじめに(Introduction)
N3054 Working Draft, Standard for Programming Language C
http://www.open-std.org/jtc1/sc22/wg14/docs/papers/2022/n3054.pdf
C++ nは、ISO/IEC JTC1 SC22 WG14の作業原案(Working Draft)です。
公式のISO/IEC 9899原本ではありません。
ISO/IEC JTC1 SC22 のWG14を含むいくつかのWGでは、可能な限り作業文書を公開し、幅広い意見を求めています。
ISO/IEC JTC1 SC7からISO/IEC JTC1 SC22リエゾンとして、2000年頃、C/C++の品質向上に貢献しようとした活動をしていたことがあります。その頃は、まだISO/IEC TS 17961の原案が出る前です。Cの精神が優勢で、セキュリティ対策は補助的な位置付けでした。ISO/IEC TS 17961の制定と、C/C++のライブラリ類の見直しと、C++の進化はどんどん進んでいきます。
進化の具合が、どちらに行こうとしているかは、コンパイルて実行させてみないとわかりません。C/C++の規格案の電子ファイルは、そのままコンパイルできる形式であるとよいと主張してきました。MISRA-C/C++, CERTC/C++でも同様です。MISRA-C/C++は、Example Suiteという形で、コード断片をコンパイルできる形で提供するようになりました。
一連の記事はコード断片をコンパイルできる形にする方法を検討してコンパイル、リンク、実行して、規格案の原文と処理系(gcc, clang)との違いを確認し、技術内容を検討し、ISO/IEC JTC1 SC22 WG21にフィードバックするために用います。
また、CERT C/C++, MISRA C/C++等のコーディング標準のコード断片をコンパイルする際の参考にさせていただこうと考えています。CERT C++, MISRA C++が標準化の動きとの時間的なずれがあれば確認できれば幸いです。また、boostライブラリとの関連、Linux OS, 箱庭プロジェクト、g++(GCC), clang++(LLVM)との関係も調査中です。
何か、抜け漏れ、耳より情報がありましたらおしらせくださると幸いです。
<この項は書きかけです。順次追記します。>
背景(back ground)
C/C++でコンパイルエラーが出ると、途方にくれることがしばしばあります。
何回かに1回は、該当するエラーが検索できます。
ただ、条件が違っていて、そこでの修正方法では目的を達成しないこともしばしばです。いろいろな条件のコンパイルエラーとその対応方法について、広く記録することによって、いつか同じエラーに遭遇した時にやくに立つことを目指しています。
過去に何度か、自分のネットでの記録に助けられたことがあります。
また
https://researchmap.jp/joub9b3my-1797580/#_1797580
に記載したサイトのお世話になっています。
作業方針(sequence)
clangでは--std=c11, -std=C17 -std=c2xの3種類
gccでは-std=c11, -std=C17 -std=c2xの3種類
でコンパイルし、
1)コンパイルエラーを収集する。
2)コンパイルエラーをなくす方法を検討する。
コンパイルエラーになる例を示すだけが目的のコードは、コンパイルエラーをなくすのではなく、コンパイルエラーの種類を収集するだけにする。
文法を示すのが目的のコード場合に、コンパイルエラーをなくすのに手間がかかる場合は、順次作業します。
3)リンクエラーをなくす方法を検討する。
文法を示すのが目的のコード場合に、リンクエラーをなくすのに手間がかかる場合は、順次作業します。
4)意味のある出力を作る。
コンパイル、リンクが通っても、意味のある出力を示そうとすると、コンパイル・リンクエラーが出て収拾できそうにない場合がある。順次作業します。
1)だけのものから4)まで進んだものと色々ある状態です。一歩でも前に進むご助言をお待ちしています。「検討事項」の欄に現状を記録するようにしています。
$ docker run -v /Users/ogawakiyoshi/n4910/n3540:/Users/ogawakiyoshi/n4910/n3540 -it kaizenjapan/n3540 /bin/bash
読書感想文
CコンパイラによるC言語規格の読書感想文として掲載しています。
コンパイル実験が、CN3242に対する、gccとclangによる感想文だということご理解いただけると幸いです。
読書感想文は人間かAIだけが作るものとは限りません。
本(電子書籍を含む)を入力として、その内容に対する文字列を読書感想文として受け止めましょう。
元の文章をあり方、コンパイルできるように電子化しておくこと、コンパイラが解釈可能な断片の作り方など。
個人開発
Cコンパイラの試験を一人でもくもくとやっているのは個人開発の一つの姿です。
<この項は書きかけです。順次追記します。>
編纂器(Compiler)
clang --version
Debian clang version 14.0.6-++20220622053050+f28c006a5895-1~exp1~20220622173135.152
Target: x86_64-pc-linux-gnu Thread model: posix InstalledDir: /usr/bin
gcc --version
gcc (GCC) 12.1.0 Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7. Library 7.1 Introduction, CN3054:2022 (12) p193.c
算譜(source code)
// CN3054 Committee Draft, Standard for Programming Language C
// http://www.open-std.org/jtc1/sc22/wg14/docs/papers/2022/n3054.pdf
const char * n3054 = "7. Library 7.1 Introduction, CN3054:2022 (12) p193.c";
// Debian clang version 14.0.5-++20220610033153+c12386ae247c-
// g++ (GCC) 12.1.0 Copyright (C) 2022 Free Software Foundation, Inc.
// Edited by Dr. OGAWA Kiyoshi. Compile procedure and results record.
// C++N3054:2022 Standard Working Draft on ISO/IEC 14882(0) sample code compile list
#include "N3054.h"
// 7.1.4 Use of library functions
// Each of the following statements applies unless explicitly stated otherwise in the detailed descrip- tions that follow:
// — If an argument to a function has an invalid value (such as a value outside the domain of the function, or a pointer outside the address space of the program, or a null pointer, or a pointer to non-modifiable storage when the corresponding parameter is not const-qualified) or a type (after default argument promotion) not expected by a function with a variable number of arguments, the behavior is undefined.
// — If a function argument is described as being an array, the pointer passed to the function shall have a value such that all address computations and accesses to objects (that would be valid if the pointer did point to the first element of such an array) are valid.234)
// — Any function declared in a header may be additionally implemented as a function-like macro defined in the header, so if a library function is declared explicitly when its header is included, one of the techniques shown below can be used to ensure the declaration is not affected by such a macro. Any macro definition of a function can be suppressed locally by enclosing the name of the function in parentheses, because the name is then not followed by the left parenthesis that indicates expansion of a macro function name. For the same syntactic reason, it is permitted to take the address of a library function even if it is also defined as a macro.235) The use of #undef to remove any macro definition will also ensure that an actual function is referred to.
// — Any invocation of a library function that is implemented as a macro shall expand to code that evaluates each of its arguments exactly once, fully protected by parentheses where necessary, so it is generally safe to use arbitrary expressions as arguments.236)
// — Likewise, those function-like macros described in the following subclauses may be invoked in an expression anywhere a function with a compatible return type could be called. 237)
// — All object-like macros listed as expanding to integer constant expressions shall additionally be suitable for use in conditional expression inclusion preprocessing directives.
// Provided that a library function can be declared without reference to any type defined in a header, it is also permissible to declare the function and use it without including its associated header.
// There is a sequence point immediately before a library function returns.
// 234)This includes, for example, passing a valid pointer that points one-past-the-end of an array along with a size of 0, or using any valid pointer with a size of 0.
// 235)This means that an implementation is required to provide an actual function for each library function, even if it also provides a macro for that function.
// 236)Such macros might not contain the sequence points that the corresponding function calls do.
// 237)Because external identifiers and some macro names beginning with an underscore are reserved, implementations can provide special semantics for such names. For example, the identifier _BUILTIN_abs could be used to indicate generation of in-line code for the abs function. Thus, the appropriate header could specify
#define abs(x) _BUILTIN_abs(x)
// for a compiler whose code generator will accept it. In this manner, a user desiring to guarantee that a given library function such as abs will be a genuine function can write
#undef abs
// whether the implementation’s header provides a macro implementation of abs or a built-in implementation. The prototype for the function, which precedes and is hidden by any macro definition, is thereby revealed also.
// The functions in the standard library are not guaranteed to be reentrant and may modify objects with static or thread storage duration. 238)
// Unless explicitly stated otherwise in the detailed descriptions that follow, library functions shall prevent data races as follows: A library function shall not directly or indirectly access objects accessible by threads other than the current thread unless the objects are accessed directly or indirectly via the function’s arguments. A library function shall not directly or indirectly modify objects accessible by threads other than the current thread unless the objects are accessed directly or indirectly via the function’s non-const arguments. 239) Implementations may share their own internal objects between threads if the objects are not visible to users and are protected against data races.
// Unless otherwise specified, library functions shall perform all operations solely within the current thread if those operations have effects that are visible to users.240)
// EXAMPLE The function atoi can be used in any of several ways:
// — by use of its associated header (possibly generating a macro expansion)
// — by use of its associated header (assuredly generating a true function reference) or
// — by explicit declaration
#include <stdlib.h>
const char *str;
/* ... */
i = atoi(str);
#include <stdlib.h>
#undef atoi
const char *str;
/* ... */
i = atoi(str);
#include <stdlib.h>
const char *str;
/* ... */
i = (atoi)(str);
extern int atoi(const char *);
const char *str;
/* ... */
i = atoi(str);
// 238)Thus, a signal handler cannot, in general, call standard library functions.
// 239)This means, for example, that an implementation is not permitted to use a static object for internal purposes without synchronization because it could cause a data race even in programs that do not explicitly share objects between threads. Similarly, an implementation of memcpy is not permitted to copy bytes beyond the specified length of the destination object and then restore the original values because it could cause a data race if the program shared those bytes between threads.
// 240)This allows implementations to parallelize operations if there are no visible side effects.
int main() {
// PR3(st.a,st.b,st.c,d);
printf("%s\n", n3054);
return EXIT_SUCCESS;
}
編纂・実行結果(compile and go)
$ clang p193.c -std=11 -o p193l -I. -Wall
p193.c:39:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
i = atoi(str);
^
p193.c:39:5: error: initializer element is not a compile-time constant
i = atoi(str);
^~~~~~~~~
p193.c:44:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
i = atoi(str);
^
p193.c:44:1: error: redefinition of 'i'
p193.c:39:1: note: previous definition is here
i = atoi(str);
^
p193.c:48:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
i = (atoi)(str);
^
p193.c:48:1: error: redefinition of 'i'
p193.c:39:1: note: previous definition is here
i = atoi(str);
^
p193.c:52:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
i = atoi(str);
^
p193.c:52:1: error: redefinition of 'i'
p193.c:39:1: note: previous definition is here
i = atoi(str);
^
4 warnings and 4 errors generated.
$ clang p193.c -std=17 -o p193l -I. -Wall
p193.c:39:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
i = atoi(str);
^
p193.c:39:5: error: initializer element is not a compile-time constant
i = atoi(str);
^~~~~~~~~
p193.c:44:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
i = atoi(str);
^
p193.c:44:1: error: redefinition of 'i'
p193.c:39:1: note: previous definition is here
i = atoi(str);
^
p193.c:48:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
i = (atoi)(str);
^
p193.c:48:1: error: redefinition of 'i'
p193.c:39:1: note: previous definition is here
i = atoi(str);
^
p193.c:52:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
i = atoi(str);
^
p193.c:52:1: error: redefinition of 'i'
p193.c:39:1: note: previous definition is here
i = atoi(str);
^
4 warnings and 4 errors generated.
$ clang p193.c -std=2x -o p193l -I. -Wall
p193.c:39:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
i = atoi(str);
^
p193.c:39:5: error: initializer element is not a compile-time constant
i = atoi(str);
^~~~~~~~~
p193.c:44:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
i = atoi(str);
^
p193.c:44:1: error: redefinition of 'i'
p193.c:39:1: note: previous definition is here
i = atoi(str);
^
p193.c:48:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
i = (atoi)(str);
^
p193.c:48:1: error: redefinition of 'i'
p193.c:39:1: note: previous definition is here
i = atoi(str);
^
p193.c:52:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
i = atoi(str);
^
p193.c:52:1: error: redefinition of 'i'
p193.c:39:1: note: previous definition is here
i = atoi(str);
^
4 warnings and 4 errors generated.
$ gcc p193.c -std=11 -o p193g -I. -Wall
p193.c:39:1: warning: data definition has no type or storage class
39 | i = atoi(str);
| ^
p193.c:39:1: warning: type defaults to 'int' in declaration of 'i' [-Wimplicit-int]
p193.c:39:5: error: initializer element is not constant
39 | i = atoi(str);
| ^~~~
p193.c:44:1: warning: data definition has no type or storage class
44 | i = atoi(str);
| ^
p193.c:44:1: warning: type defaults to 'int' in declaration of 'i' [-Wimplicit-int]
p193.c:44:1: error: redefinition of 'i'
p193.c:39:1: note: previous definition of 'i' with type 'int'
39 | i = atoi(str);
| ^
p193.c:44:5: error: initializer element is not constant
44 | i = atoi(str);
| ^~~~
p193.c:48:1: warning: data definition has no type or storage class
48 | i = (atoi)(str);
| ^
p193.c:48:1: warning: type defaults to 'int' in declaration of 'i' [-Wimplicit-int]
p193.c:48:1: error: redefinition of 'i'
p193.c:39:1: note: previous definition of 'i' with type 'int'
39 | i = atoi(str);
| ^
p193.c:48:5: error: initializer element is not constant
48 | i = (atoi)(str);
| ^
p193.c:52:1: warning: data definition has no type or storage class
52 | i = atoi(str);
| ^
p193.c:52:1: warning: type defaults to 'int' in declaration of 'i' [-Wimplicit-int]
p193.c:52:1: error: redefinition of 'i'
p193.c:39:1: note: previous definition of 'i' with type 'int'
39 | i = atoi(str);
| ^
p193.c:52:5: error: initializer element is not constant
52 | i = atoi(str);
| ^~~~
$ gcc p193.c -std=c17 -o p193g -I. -Wall
p193.c:39:1: warning: data definition has no type or storage class
39 | i = atoi(str);
| ^
p193.c:39:1: warning: type defaults to 'int' in declaration of 'i' [-Wimplicit-int]
p193.c:39:5: error: initializer element is not constant
39 | i = atoi(str);
| ^~~~
p193.c:44:1: warning: data definition has no type or storage class
44 | i = atoi(str);
| ^
p193.c:44:1: warning: type defaults to 'int' in declaration of 'i' [-Wimplicit-int]
p193.c:44:1: error: redefinition of 'i'
p193.c:39:1: note: previous definition of 'i' with type 'int'
39 | i = atoi(str);
| ^
p193.c:44:5: error: initializer element is not constant
44 | i = atoi(str);
| ^~~~
p193.c:48:1: warning: data definition has no type or storage class
48 | i = (atoi)(str);
| ^
p193.c:48:1: warning: type defaults to 'int' in declaration of 'i' [-Wimplicit-int]
p193.c:48:1: error: redefinition of 'i'
p193.c:39:1: note: previous definition of 'i' with type 'int'
39 | i = atoi(str);
| ^
p193.c:48:5: error: initializer element is not constant
48 | i = (atoi)(str);
| ^
p193.c:52:1: warning: data definition has no type or storage class
52 | i = atoi(str);
| ^
p193.c:52:1: warning: type defaults to 'int' in declaration of 'i' [-Wimplicit-int]
p193.c:52:1: error: redefinition of 'i'
p193.c:39:1: note: previous definition of 'i' with type 'int'
39 | i = atoi(str);
| ^
p193.c:52:5: error: initializer element is not constant
52 | i = atoi(str);
| ^~~~
$ gcc p193.c -std=c2x -o p193g -I. -Wall
p193.c:39:1: warning: data definition has no type or storage class
39 | i = atoi(str);
| ^
p193.c:39:1: warning: type defaults to 'int' in declaration of 'i' [-Wimplicit-int]
p193.c:39:5: error: initializer element is not constant
39 | i = atoi(str);
| ^~~~
p193.c:44:1: warning: data definition has no type or storage class
44 | i = atoi(str);
| ^
p193.c:44:1: warning: type defaults to 'int' in declaration of 'i' [-Wimplicit-int]
p193.c:44:1: error: redefinition of 'i'
p193.c:39:1: note: previous definition of 'i' with type 'int'
39 | i = atoi(str);
| ^
p193.c:44:5: error: initializer element is not constant
44 | i = atoi(str);
| ^~~~
p193.c:48:1: warning: data definition has no type or storage class
48 | i = (atoi)(str);
| ^
p193.c:48:1: warning: type defaults to 'int' in declaration of 'i' [-Wimplicit-int]
p193.c:48:1: error: redefinition of 'i'
p193.c:39:1: note: previous definition of 'i' with type 'int'
39 | i = atoi(str);
| ^
p193.c:48:5: error: initializer element is not constant
48 | i = (atoi)(str);
| ^
p193.c:52:1: warning: data definition has no type or storage class
52 | i = atoi(str);
| ^
p193.c:52:1: warning: type defaults to 'int' in declaration of 'i' [-Wimplicit-int]
p193.c:52:1: error: redefinition of 'i'
p193.c:39:1: note: previous definition of 'i' with type 'int'
39 | i = atoi(str);
| ^
p193.c:52:5: error: initializer element is not constant
52 | i = atoi(str);
| ^~~~
検討事項(agenda)
コンパイルエラーを取るか、コンパイルエラーの理由を解説する。
応用例1 MISRA C/C++
MISRA C まとめ #include
https://qiita.com/kaizen_nagoya/items/f1a79a7cbd281607c7c9
MISRA C++ 5-0-16
https://qiita.com/kaizen_nagoya/items/7df2d4e05db724752a74
応用例2 CERT C/C++
SEI CERT C++ Coding Standard AA. Bibliography 確認中。
https://qiita.com/kaizen_nagoya/items/fe06719aef10f3f985ae
MISRA C/C++, AUTOSAR C++, CERT C/C++とC/C++工業標準をコンパイルする
https://qiita.com/kaizen_nagoya/items/8dff19511e42b2593db1
自己参考資料(self reference)
関連する自己参照以外は、こちらの先頭に移転。
C言語(C++)に対する誤解、曲解、無理解、爽快。
https://qiita.com/kaizen_nagoya/items/3f3992c9722c1cee2e3a
C2011コンパイル一覧@researchmap
https://researchmap.jp/jownvh0ye-1797580/#_1797580
[C][C++]の国際規格案の例題をコンパイルするときの課題7つ。
https://qiita.com/kaizen_nagoya/items/5f4b155030259497c4de
C Puzzle Bookの有り難み5つ、C言語規格及びCコンパイラの特性を認識
https://qiita.com/kaizen_nagoya/items/d89a48c1536a02ecdec9
dockerにclang
https://qiita.com/kaizen_nagoya/items/8829ffeee397eda50e80
docker gnu(gcc/g++) and llvm(clang/clang++)
https://qiita.com/kaizen_nagoya/items/059874ea39c4de64c0f7
コンパイル用shell script C版(clangとgcc)とC++版(clang++とg++)
https://qiita.com/kaizen_nagoya/items/74220c0577a512c2d7da
astyle 使ってみた
https://qiita.com/kaizen_nagoya/items/3c9a87a781d53a1a23f3
<この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。>
文書履歴(document history)
ver. 0.01 初稿 20221120
最後までおよみいただきありがとうございました。
いいね 💚、フォローをお願いします。
Thank you very much for reading to the last sentence.
Please press the like icon 💚 and follow me for your happy life.