Guidelines for the use of the C++14 language in critical and
safety-related systems Sample code compile list(31)
https://www.autosar.org/fileadmin/user_upload/standards/adaptive/17-03/AUTOSAR_RS_CPP14Guidelines.pdf
Autosar Guidelines C++14 example code compile list
https://qiita.com/kaizen_nagoya/items/8ccbf6675c3494d57a76
目的(purpose)
AutosarのC++ GuidelineをOS, 制御のプログラムで利用するにあたって、(1)hosted, freestandingのどちらを基本にすべきか。(2)C++2014,C++2017, C++202aのどれを用いると良いか, (3)どの処理系を併用すると良いかを検討するため、-std=c++14, -std=c++17, -std=c++2aの3種類で、複数のコンパイラでコンパイルすることにより、誤(error)、警告(warning)、関数・変数連携(link)、出力(output)、にどのような影響があるかを確認する。
成果(outcome)
複数の処理系の特徴が明確になるとともに、各標準段階, hosted, freestandingの特徴と課題を明確にする。
A5-0-1.cpp
算譜(source code)
//Guidelines for the use of the C++14 language in critical and safety-related systems
const char* msg="Rule A5-0-1 (required, implementation, automated) The value of an expression shall be the same under any order of evaluation that the standard permits.(31)A5-0-1.cpp";
//https://www.autosar.org/fileadmin/user_upload/standards/adaptive/17-03/AUTOSAR_RS_CPP14Guidelines.pdf
// There is no description about Autosar declear hosted or freestanding.
// If the Autosar intended both depending on the cases, autosar.h can choose one.
// Compile with -DHOSTED work as hosted environment, -DFREESTANDING work as freestanding.
#include "autosar.h"/// @line add header file https://qiita.com/kaizen_nagoya/items/4bde8f21ab059b96cf2a
#include <cstdint>
using namespace std;/// @line add using
///start AUTOSAR: From here to the "///end AUTOSAR" is from AUTOSAR without code having /// comment in line.
// $Id: A5-0-1.cpp 271927 2017-03-24 12:01:35Z piotr.tanski $
#include <cstdint>
#include <stack>
// The following notes give some guidance on how dependence on order of
// evaluation may occur, and therefore may assist in adopting the rule.
// 1) Increment or decrement operators
// As an example of what can go wrong, consider
void f1(std::uint8_t (&arr)[10], std::uint8_t idx) noexcept(false)
{
std::uint16_t x = arr[idx] + idx++;
cout <<"f1:idx="<<idx<<" x="<<x<<endl;/// @ line for output
}
// This will give different results depending on whether arr[idx] is evaluated
// before idx++ or vice versa. The problem could be avoided by putting the
// increment operation in a separate statement. For example:
void f2(std::uint8_t (&arr)[10], std::uint8_t idx) noexcept(false)
{
std::uint8_t x = arr[idx] + idx;
idx++;
cout <<"f2:idx="<<idx<<endl;/// @ line for output
}
// 2) Function arguments
// The order of evaluation of function arguments is unspecified.
extern std::uint8_t func(std::uint8_t x, std::uint8_t y);
void f3() noexcept(false)
{
std::uint8_t i = 0;
std::uint8_t x = func(i++, i);
cout <<"f3:x="<<x<<endl;/// @ line for output
}
// This will give different results depending on which of the functions two
// parameters is evaluated first.
// 3) Function pointers
// If a function is called via a function pointer there shall be no
// dependence
// on the order in which function-designator and function arguments are
// evaluated.
struct S
{
void taskStartFn(S* obj) noexcept(false) {
cout<< "taskStartFn:*obj="<<obj<<endl;
}
};
void f4(S* p) noexcept(false)
{
p->taskStartFn(p++);
cout <<"f4"<<endl;/// @ line for output
}
// 4) Function calls
// Functions may have additional effects when they are called (e.g. modifying
// some global data). Dependence on order of evaluation could be avoided by
// invoking the function prior to the expression that uses it, making use of a
// temporary variable for the value. For example:
extern std::uint16_t g(std::uint8_t) noexcept(false);
extern std::uint16_t z(std::uint8_t) noexcept(false);
void f5(std::uint8_t a) noexcept(false)
{
std::uint16_t x = g(a) + z(a);
cout <<"f5:x="<<x<<endl;/// @ line for output
}
// could be written as
void f6(std::uint8_t a) noexcept(false)
{
std::uint16_t x = g(a);
x += z(a);
cout <<"f6:x="<<x<<endl;/// @ line for output
}
// As an example of what can go wrong, consider an expression to take two values
// off a stack, subtract the second from the first, and push the result back on
// the stack:
std::int32_t pop(std::stack<std::int32_t>& s)
{
std::int32_t ret = s.top();
s.pop();
return ret;
}
void f7(std::stack<std::int32_t>& s)
{
s.push(pop(s) - pop(s));
cout <<"s.top()="<<s.top()<<endl;/// @ line for output
}
// This will give different results depending on which of the pop() function
// calls is evaluated first (because pop() has side effects).
// 5) Nested assignment statements
// Assignments nested within expressions cause additional side effects. The best
// way to avoid any possibility of this leading to a dependence on order of
// evaluation is not to embed assignments within expressions. For example, the
// following is not recommended:
void f8(std::int32_t& x) noexcept(false)
{
std::int32_t y = 4;
x = y = y++; // It is undefined whether the final value of y is 4 or 5
cout <<"y="<<y<<endl;/// @ line for output
}
// 6) Accessing a volatile
// The volatile type qualifier is provided in C++ to denote objects whose value
// can change independently of the execution of the program (for example an
// input register). If an object of volatile qualified type is accessed this may
// change its value. C++ compilers will not optimize out reads of a volatile. In
// addition, as far as a C++ program is concerned, a read of a volatile has a
// side effect (changing the value of the volatile). It will usually be
// necessary to access volatile data as part of an expression, which then means
// there may be dependence on order of evaluation. Where possible, though, it is
// recommended that volatiles only be accessed in simple assignment statements,
// such as the following:
void f9(std::uint16_t& x) noexcept(false)
{
volatile std::uint16_t v=2048; /// @ add value for warning
// ...
x = v;
cout <<"v="<<v<<endl;/// @ line for output
}
// The rule addresses the order of evaluation problem with side effects. Note
// that there may also be an issue with the number of times a sub-expression is
// evaluated, which is not covered by this rule. This can be a problem with
// function invocations where the function is implemented as a macro. For
// example, consider the following function-like macro and its invocation:
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
// ...
void f10(std::uint32_t& i, std::uint32_t j)
{
std::uint32_t z = MAX(i++, j);
cout <<"f10:z="<< z<<endl; /// @ line add output for warning
}
// The definition evaluates the first parameter twice if a > b but only once if
// a = b. The macro invocation may thus increment i either once or twice,
// depending on the values of i and j.
// It should be noted that magnitude-dependent effects, such as those due to
// floating-point rounding, are also not addressed by this rule. Although
// the
// order in which side effects occur is undefined, the result of an operation is
// otherwise well-defined and is controlled by the structure of the expression.
// In the following example, f1 and f2 are floating-point variables; F3, F4
// and
// F5 denote expressions with floating-point types.
// f1 = F3 + ( F4 + F5 );
// f2 = ( F3 + F4 ) + F5;
// The addition operations are, or at least appear to be, performed in the order
// determined by the position of the parentheses, i.e. firstly F4 is added to F5
// then secondly F3 is added to give the value of f1. Provided that F3, F4 and
// F5 contain no side effects, their values are independent of the order in
// which they are evaluated. However, the values assigned to f1 and f2 are not
// guaranteed to be the same because floating-point rounding following the
// addition operations are dependent on the values being added.
///end AUTOSAR
int start() { /// @{} for start
uint32_t ui;
uint32_t& i=ui;
uint32_t uj=1023;
uint8_t ar[10];
uint8_t (&arr)[10]=ar;
uint8_t idx=1;
S s;
S * p = &s;
stack<int32_t> st;
stack<int32_t> & str=st;
int32_t i32;
int32_t & ir=i32;
uint16_t ui16;
uint16_t & uir=ui16;
f1( (&arr)[10], idx) ;
f2((&arr)[10], idx) ;
f3();
f4(p);
f5(idx) ;
f6(idx);
f7(str);
f8(ir);
f9(uir);
f10(i,uj);
cout<< msg << endl;
ShutdownOS() EXIT_SUCCESS;
/// Autosar OS 3.1.1, 2009: 7.1.2.2 Undefined Behaviour in OSEK OS
/// OS425 If ShutdownOS is called and ShutdownHook() returns then the operating system shall disable all interrupts and enter an endless loop.
}
#include "autosar.h"/// @line add header file https://qiita.com/kaizen_nagoya/items/4bde8f21ab059b96cf2a
using namespace std;
uint16_t g(uint8_t ui8) noexcept(false) {
uint16_t ui16 = ui8*ui8;
cout << "ui8="<<ui8<<" ui16="<<ui16<<endl;
return ui16;
}
uint16_t z(uint8_t ui8) noexcept(false) {
uint16_t ui16 = ui8+ui8;
cout << "ui8="<<ui8<<" ui16="<<ui16<<endl;
return ui16;
}
uint8_t func(uint8_t x, uint8_t y) {
cout << "x="<<x<<" y="<<y<<endl;
return x+y;
}
編纂・実行結果(compile and go)
$ ../cpa2.sh a5-0-1 a5-0-1a
$ clang++ a5-0-1.cpp a5-0-1a.cpp -std=c++14 -Wall
a5-0-1.cpp:25:35: warning: unsequenced modification and access to 'idx' [-Wunsequenced]
std::uint16_t x = arr[idx] + idx++;
~~~ ^
a5-0-1.cpp:34:16: warning: unused variable 'x' [-Wunused-variable]
std::uint8_t x = arr[idx] + idx;
^
a5-0-1.cpp:46:26: warning: unsequenced modification and access to 'i' [-Wunsequenced]
std::uint8_t x = func(i++, i);
^ ~
a5-0-1.cpp:65:19: warning: unsequenced modification and access to 'p' [-Wunsequenced]
p->taskStartFn(p++);
~ ^
a5-0-1.cpp:115:12: warning: multiple unsequenced modifications to 'y' [-Wunsequenced]
x = y = y++; // It is undefined whether the final value of y is 4 or 5
~ ^
5 warnings generated.
f1:idx= x=225
f2:idx=
x= y=
f3:x=
taskStartFn:*obj=0x7ffee02375f8
f4
ui8= ui16=1
ui8= ui16=2
f5:x=3
ui8= ui16=1
ui8= ui16=2
f6:x=3
../cpa2.sh: line 7: 40060 Segmentation fault: 11 ./$1l14 $2
rm: a5-0-1l13: No such file or directory
$ clang++ a5-0-1.cpp a5-0-1a.cpp -std=c++17 -Wall
a5-0-1.cpp:25:35: warning: unsequenced modification and access to 'idx' [-Wunsequenced]
std::uint16_t x = arr[idx] + idx++;
~~~ ^
a5-0-1.cpp:34:16: warning: unused variable 'x' [-Wunused-variable]
std::uint8_t x = arr[idx] + idx;
^
a5-0-1.cpp:46:26: warning: unsequenced modification and access to 'i' [-Wunsequenced]
std::uint8_t x = func(i++, i);
^ ~
a5-0-1.cpp:65:19: warning: unsequenced modification and access to 'p' [-Wunsequenced]
p->taskStartFn(p++);
~ ^
a5-0-1.cpp:115:12: warning: multiple unsequenced modifications to 'y' [-Wunsequenced]
x = y = y++; // It is undefined whether the final value of y is 4 or 5
~ ^
5 warnings generated.
f1:idx= x=239
f2:idx=
x= y=
f3:x=
taskStartFn:*obj=0x7ffeee7785f8
f4
ui8= ui16=1
ui8= ui16=2
f5:x=3
ui8= ui16=1
ui8= ui16=2
f6:x=3
../cpa2.sh: line 13: 40067 Segmentation fault: 11 ./$1l17 $2
$ clang++ a5-0-1.cpp a5-0-1a.cpp -std=c++2a -Wall
a5-0-1.cpp:25:35: warning: unsequenced modification and access to 'idx' [-Wunsequenced]
std::uint16_t x = arr[idx] + idx++;
~~~ ^
a5-0-1.cpp:34:16: warning: unused variable 'x' [-Wunused-variable]
std::uint8_t x = arr[idx] + idx;
^
a5-0-1.cpp:46:26: warning: unsequenced modification and access to 'i' [-Wunsequenced]
std::uint8_t x = func(i++, i);
^ ~
a5-0-1.cpp:65:19: warning: unsequenced modification and access to 'p' [-Wunsequenced]
p->taskStartFn(p++);
~ ^
a5-0-1.cpp:115:12: warning: multiple unsequenced modifications to 'y' [-Wunsequenced]
x = y = y++; // It is undefined whether the final value of y is 4 or 5
~ ^
5 warnings generated.
f1:idx= x=235
f2:idx=
x= y=
f3:x=
taskStartFn:*obj=0x7ffeea40d5f8
f4
ui8= ui16=1
ui8= ui16=2
f5:x=3
ui8= ui16=1
ui8= ui16=2
f6:x=3
../cpa2.sh: line 19: 40073 Segmentation fault: 11 ./$1l2a $2
$ g++-8 a5-0-1.cpp a5-0-1a.cpp -std=c++14 -Wall
a5-0-1.cpp: In function 'void f1(uint8_t (&)[10], uint8_t)':
a5-0-1.cpp:25:35: warning: operation on 'idx' may be undefined [-Wsequence-point]
std::uint16_t x = arr[idx] + idx++;
~~~^~
a5-0-1.cpp: In function 'void f2(uint8_t (&)[10], uint8_t)':
a5-0-1.cpp:34:16: warning: unused variable 'x' [-Wunused-variable]
std::uint8_t x = arr[idx] + idx;
^
a5-0-1.cpp: In function 'void f3()':
a5-0-1.cpp:46:26: warning: operation on 'i' may be undefined [-Wsequence-point]
std::uint8_t x = func(i++, i);
~^~
a5-0-1.cpp: In function 'void f4(S*)':
a5-0-1.cpp:65:19: warning: operation on 'p' may be undefined [-Wsequence-point]
p->taskStartFn(p++);
~^~
a5-0-1.cpp: In function 'void f8(int32_t&)':
a5-0-1.cpp:115:9: warning: operation on 'y' may be undefined [-Wsequence-point]
x = y = y++; // It is undefined whether the final value of y is 4 or 5
~~^~~~~
f1:idx= x=1
f2:idx=
x= y=
f3:x=
taskStartFn:*obj=0x7ffeeed556e1
f4
ui8= ui16=1
ui8= ui16=2
f5:x=3
ui8= ui16=1
ui8= ui16=2
f6:x=3
s.top()=-1346830414
y=4
v=2048
f10:z=32767
Rule A5-0-1 (required, implementation, automated) The value of an expression shall be the same under any order of evaluation that the standard permits.(31)A5-0-1.cpp
$ g++-8 a5-0-1.cpp a5-0-1a.cppp -std=c++17 -Wall
a5-0-1.cpp: In function 'void f1(uint8_t (&)[10], uint8_t)':
a5-0-1.cpp:25:35: warning: operation on 'idx' may be undefined [-Wsequence-point]
std::uint16_t x = arr[idx] + idx++;
~~~^~
a5-0-1.cpp: In function 'void f2(uint8_t (&)[10], uint8_t)':
a5-0-1.cpp:34:16: warning: unused variable 'x' [-Wunused-variable]
std::uint8_t x = arr[idx] + idx;
^
a5-0-1.cpp: In function 'void f3()':
a5-0-1.cpp:46:26: warning: operation on 'i' may be undefined [-Wsequence-point]
std::uint8_t x = func(i++, i);
~^~
a5-0-1.cpp: In function 'void f4(S*)':
a5-0-1.cpp:65:19: warning: operation on 'p' may be undefined [-Wsequence-point]
p->taskStartFn(p++);
~^~
a5-0-1.cpp: In function 'void f8(int32_t&)':
a5-0-1.cpp:115:9: warning: operation on 'y' may be undefined [-Wsequence-point]
x = y = y++; // It is undefined whether the final value of y is 4 or 5
~~^~~~~
f1:idx= x=1
f2:idx=
x= y=
f3:x=
taskStartFn:*obj=0x7ffee71e86e1
f4
ui8= ui16=1
ui8= ui16=2
f5:x=3
ui8= ui16=1
ui8= ui16=2
f6:x=3
s.top()=-1346830414
y=4
v=2048
f10:z=32767
Rule A5-0-1 (required, implementation, automated) The value of an expression shall be the same under any order of evaluation that the standard permits.(31)A5-0-1.cpp
$ g++-8 a5-0-1.cpp a5-0-1a.cppp -std=c++2a -Wall
a5-0-1.cpp: In function 'void f1(uint8_t (&)[10], uint8_t)':
a5-0-1.cpp:25:35: warning: operation on 'idx' may be undefined [-Wsequence-point]
std::uint16_t x = arr[idx] + idx++;
~~~^~
a5-0-1.cpp: In function 'void f2(uint8_t (&)[10], uint8_t)':
a5-0-1.cpp:34:16: warning: unused variable 'x' [-Wunused-variable]
std::uint8_t x = arr[idx] + idx;
^
a5-0-1.cpp: In function 'void f3()':
a5-0-1.cpp:46:26: warning: operation on 'i' may be undefined [-Wsequence-point]
std::uint8_t x = func(i++, i);
~^~
a5-0-1.cpp: In function 'void f4(S*)':
a5-0-1.cpp:65:19: warning: operation on 'p' may be undefined [-Wsequence-point]
p->taskStartFn(p++);
~^~
a5-0-1.cpp: In function 'void f8(int32_t&)':
a5-0-1.cpp:115:9: warning: operation on 'y' may be undefined [-Wsequence-point]
x = y = y++; // It is undefined whether the final value of y is 4 or 5
~~^~~~~
f1:idx= x=1
f2:idx=
x= y=
f3:x=
taskStartFn:*obj=0x7ffee0f186e1
f4
ui8= ui16=1
ui8= ui16=2
f5:x=3
ui8= ui16=1
ui8= ui16=2
f6:x=3
s.top()=-1346830414
y=4
v=2048
f10:z=32767
Rule A5-0-1 (required, implementation, automated) The value of an expression shall be the same under any order of evaluation that the standard permits.(31)A5-0-1.cpp
検討事項(agenda)
1. 自律(freestanding)環境. 接待(hosted)環境
C++N4606 1.4 Implementation compliance p.4
2. 対応OSの水準、対応通信規約、応用機能による分類
freestanding用の関数、ライブラリ等
3. C++2014, C++2017, C++202aの比較項目
本件なし
4. clang++, g++の比較検討項目
本件なし
5 実行時エラーを取る
6 役立つまたは意味のある出力
参考文献(reference)
プログラミング言語教育のXYZ
https://qiita.com/kaizen_nagoya/items/1950c5810fb5c0b07be4
プログラミング言語教育のXYZ(youtube)
https://www.youtube.com/watch?v=He1_tg4px-w&t=486s
C++N4741 2018
Working Draft, Standard for Programming Language C++
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4741.pdf
C++N4741, 2018 Standard Working Draft on ISO/IEC 14882 sample code compile list
https://qiita.com/kaizen_nagoya/items/3294c014044550896010
C++N4606 2016
Working Draft, Standard for Programming Language C++
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4606.pdf
C++N4606, 2016符号断片編纂一覧(example code compile list)
Working Draft 2016, ISO/IEC 14882(1)
https://qiita.com/kaizen_nagoya/items/df5d62c35bd6ed1c3d43/
CEDD(Compile Error Driven Design)
初めての CEDD(Compile Error Driven Design) 8回直してコンパイル。
https://qiita.com/kaizen_nagoya/items/9494236aa1753f3fd1e1
コンパイルエラーを記録するとよい理由7つ
https://qiita.com/kaizen_nagoya/items/85c0e92b206883140e89
C Puzzle Bookの有り難み5つ、C言語規格及びCコンパイラの特性を認識
https://qiita.com/kaizen_nagoya/items/d89a48c1536a02ecdec9
C言語(C++)に対する誤解、曲解、無理解、爽快。
https://qiita.com/kaizen_nagoya/items/3f3992c9722c1cee2e3a
Qiitaに投稿するCのStyle例(暫定)
https://qiita.com/kaizen_nagoya/items/946df1528a6a1ef2bc0d
C++N4606 Working Draft 2016, ISO/IEC 14882, C++ standardのコード断片をコンパイルするためにしていること
https://qiita.com/kaizen_nagoya/items/a8d7ee2f2e29e76c19c1
コンパイル用shell script C版(clangとgcc)とC++版(clang++とg++)
https://qiita.com/kaizen_nagoya/items/74220c0577a512c2d7da
[C][C++]の国際規格案の例題をコンパイルするときの課題7つ。
https://qiita.com/kaizen_nagoya/items/5f4b155030259497c4de
docker gnu(gcc/g++) and llvm(clang/clang++)
https://qiita.com/drafts/059874ea39c4de64c0f7
文書履歴(document history)
ver 0.10 初稿 20180610
ver 0.11 一覧追記 参考文献欄追記 20180616