LoginSignup
1
1

More than 5 years have passed since last update.

Autosar Guidelines C++14, example code compile list(31)Rule A5-0-1 The value of an expression

Last updated at Posted at 2018-06-09

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)

A5-0-1.cpp
//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.
}
a5-0-1a.cpp
#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)

cpa.sh
$ ../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

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1