LoginSignup
4
1

目的

複数の処理系(compiler)でコンパイルすることにより、それぞれの処理系の特徴を確認する。

成果

複数の処理系の特徴が把握できる。

複数の処理系の特徴を利用し、コードチェッカを利用しなくても検査できる項目を洗い出す。

本文

Cコンパイラで、警告を出す出さないは、それぞれのコンパイラでもスイッチによって異なる。

ここでは、スイッチなし状態で比較する。

-std=C++03

#include <cstdlib>

がないと、g++でEXIT_SUCCESSなどの定数定義でコンパイルエラーが出る。
-std=C++11, -std=C++17では出ない。理由未調査。

-std=c++17

C++は -std=C++17で比較する(今、C++2017を追っかけ中)

accfree-old.c
//EXAMPLE 1 In this noncompliant example, a diagnostic is required because head->next is accessed after head has been freed.

#include <stdio.h>/// for printf
#include <stdlib.h>/// for EXIT_SUCCESS

struct List { struct List *next; /* ... */ };
void free_list(struct List *head) {
  for (; head != NULL; head = head->next) { // diagnostic required
  printf("%d %d \n",(int)head, (int)head->next);
  free(head);
  }
}
int main(int argc, char** argv){///
  struct List lista;///
  free_list(&lista);///
  return EXIT_SUCCESS;///
}///

編纂

shell
./gcc7ts.sh accfree-old
$ clang accfree-old.c
-524404904 0 
accfree-oldl(87331,0x7fffa098d340) malloc: *** error for object 0x7ffee0be3758: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
./gcc7ts.sh: line 4: 87331 Abort trap: 6           ./$1l $2

$ gcc-7 accfree-old.c
accfree-old.c: In function 'free_list':
accfree-old.c:9:21: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
   printf("%d %d \n",(int)head, (int)head->next);
                     ^
accfree-old.c:9:32: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
   printf("%d %d \n",(int)head, (int)head->next);
                                ^
-327620760 241340882 
accfree-oldg(87340,0x7fffa098d340) malloc: *** error for object 0x7ffeec78e768: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
./gcc7ts.sh: line 8: 87340 Abort trap: 6           ./$1g $2

考察案

intはレジスタの幅、

accfree2-old.c
// ISO/IEC JTC 1/SC 22/WG 14 N 1624 Date: 2012-06-26 ISO/IEC TS 17961, p.8
/// lines are added by Dr. Kiyoshi Ogawa, 2018
/// Compiled on Clang(LLVM) and GCC(GNU)
// EXAMPLE 2 In this noncompliant example, a diagnostic is required because buf is written to after it has been freed.

#include <stdio.h> // for printf
#include <stdlib.h> // for EXIT_SUCCESS
#include <string.h> // for strlen

int main(int argc, char *argv[]) {///
  if (argc < 2) {
    printf("argc:%d\n",argc);
    /* ... */
    return EXIT_FAILURE;
  }
  char *return_val = 0;
  const size_t bufsize = strlen(argv[1]) + 1;
  char *buf = (char *)malloc(bufsize);
  if (!buf) {
    /* ... */
    printf("!buf\n");
    return EXIT_FAILURE;
  }
  /* ... */
  printf("buf:%d\n",(int)buf);
  free(buf);
  /* ... */
  return_val = strncpy(buf, argv[1], bufsize); // diagnostic required
  if (return_val) {
    printf("*return_val:%d\n",(int)*return_val);
    /* ... */
  }
  return EXIT_SUCCESS;
}

編纂

shell
./gcc7ts.sh accfree2
$ clang accfree2.c
argc:1
./gcc7ts.sh: line 4: 87661 Segmentation fault: 11  ./$1l $2

$ gcc-7 accfree2.c
accfree2.c: In function 'main':
accfree2.c:19:21: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
   printf("buf:%d\n",(int)buf);
                     ^
argc:1
./gcc7ts.sh: line 8: 87670 Segmentation fault: 11  ./$1g $2
C89(C1990), C1999, C2011対応スイッチの比較は、順次追記する。

Preprocessing tokens

N4604 Working Draft 2016, ISO/IEC 14882, C++ standard(5) 2.4 Preprocessing tokens
https://qiita.com/kaizen_nagoya/items/0ff84fbd4581a600df21

p20.cpp
// N4606 Working Draft, Standard for Programming Language C++
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4606.pdf 

#include <iostream>

// from here p.20
#define R "x"
const char* s = R"y"; // ill-formed raw string, not "x" "y"
/// to here p.20

int main(int argc, char *argv[], char *envp[]){
  std::cout << "s" <<s<<"R"<<R<< std::endl;
  return EXIT_SUCCESS;
}

編纂

shell
./cppgl.sh p20
$ clang++ p20.cpp
p20.cpp:8:34: error: invalid character ' ' character in raw string delimiter; use
      PREFIX( )PREFIX to delimit raw string
const char* s = R"y";//ill-formed raw string, not "x" "y"
                                 ^
p20.cpp:8:17: error: expected expression
const char* s = R"y";//ill-formed raw string, not "x" "y"
                ^
2 errors generated.

$ g++-7 p20.cpp
p20.cpp:8:35: error: invalid character ' ' in raw string delimiter
 const char* s = R"y";//ill-formed raw string, not "x" "y"
                 ^               
p20.cpp:8:17: error: stray 'R' in program

実行結果の値の違い(1)

cpp2011 2 Lexical conventions 2.4Trigraph sequences
https://researchmap.jp/jo1l2qlb5-1797580/#_1797580
clang++: 0
g++:1

実行結果の値の違い(2)

C++N4741(31)7.5 Qualification conversions [conv.qual]p77
https://qiita.com/kaizen_nagoya/items/75e6d7cd28f73ff01882

clang++ 文字'C'出力, g++ ??出力

リンクエラーとエラーなし

C++N4606(210)15.2 Constructors and destructors [except.ctor]p430
https://qiita.com/kaizen_nagoya/items/f828978910659ef7c1db

clang++リンクエラー、g++エラーなし

コンパイルエラーと警告(1)

C++N4606 (65)7.1 Specifiers [dcl.spec] p155
https://qiita.com/kaizen_nagoya/items/a3918fe2e9d8245ebbd2

clang++: warning
g++: error

コンパイルエラーと警告(2)

C++N4741(10)6.3.7 Class scope [basic.scope.class]p33
https://qiita.com/kaizen_nagoya/items/2b2962a6a4c00ab88167

g++はコンパイルエラー、clang++は別の警告

コンパイルエラーと警告(3)

C++N4741 (37)8.4.4.1 Unqualified names [expr.prim.id.unqual] p86
https://qiita.com/kaizen_nagoya/items/2d3373b2ea194da27c9c

g++コンパイルエラー:binding reference of type 'float&' to 'const float' discards qualifiers clang++はunused警告

コンパイルエラーと警告(4)

C++N4741(38)8.4.5 Lambda expressions [expr.prim.lambda]p87
https://qiita.com/kaizen_nagoya/items/4532b5c023d55bba6466

clang++コンパイルエラー、g++unused警告

コンパイルエラーと警告なし(1)

C++N4606 (85)7.6.5 Fallthrough attribute [dcl.attr.fallthrough] p198
https://qiita.com/kaizen_nagoya/items/ec93d4f379077832ac53

コンパイルエラーと警告なし(2)cstringをincludeするとgccのエラーがなくなる。

C++N4606 (112) 9.2.2 Non-static member functions [class.mfct.non-static] p246
https://qiita.com/kaizen_nagoya/items/45a4749ebe5f31ea5214

cstringをincludeするとgccのエラーがなくなる。

コンパイルエラーと警告なし(3)g++がエラー, clang++は実行。cassert をincludeでエラーがなくなる

C++N4606(222)17.6.3.2 Swappable requirements [swappable.requirements] p468
https://qiita.com/kaizen_nagoya/items/b18a777cbef93f99772a

g++がエラー, clang++は実行。
cassert をinclude

コンパイルエラーと警告なし(4)

C++N4606 (227)18.3.2.2 Header synopsis [limits.syn]p486
https://qiita.com/kaizen_nagoya/items/e108b62f810e0ce0e050

g++ -std=c++17だけエラーなし, -std=c++11, -std=++03, clang++コンパイルエラー

コンパイルエラーと警告なし(5)

cpprefjpのdecltypeをコンパイル試験
https://qiita.com/kaizen_nagoya/items/090909af702f0d5d8a67

clang++ -std=c++17はエラーなし。-std=c++11, -std=++03, g++コンパイルエラー

コンパイルエラーと警告なし(6) std::bitset<8>() と include bitset

C++N4741(8)6.3.2 Point of declaration [basic.scope.pdecl]p30
https://qiita.com/kaizen_nagoya/items/cdb289c5d998013f09f5

g++はstd::bitset<8>() でコンパイルエラー、bitsetをincludeするとエラーなし。clang++はエラーなし

コンパイルエラーの個数(1)

C++N4606 (90)8.1 Type names [dcl.name] p201
https://qiita.com/kaizen_nagoya/items/81f8d75425dc376cd72b
clang++とg++でエラーの個数が違う
 clang++:2
g++:1

コンパイルエラーの個数(2)

C++N4606(212)16 Preprocessing directives [cpp]p441
https://qiita.com/kaizen_nagoya/items/2670d244c3345bfb3b04

clang++1エラー、g++2エラー

コンパイルエラーの個数(3)

C++N4606 (226)17.7 Header synopsis [cstdlib.syn]p483
https://qiita.com/kaizen_nagoya/items/7fbfb3e99d6f2ebd8736
clang++エラー2つ、g++エラーたくさん

警告の有無(1)

C++ N4606(145)12.7 Construction and destruction [class.cdtor]p301
https://qiita.com/kaizen_nagoya/items/7692db7e25150a404852

clang++警告3
g++警告なし
両方リンクエラー

警告の有無(2)

C++N4741(17)6.4.4 Elaborated type specifiers [basic.lookup.elab]p44
https://qiita.com/kaizen_nagoya/items/3e3cddbe6ac0f39bdddc

g++警告なし, clang++警告2
意味のある出力未完成

警告の有無と実行時の値の違い

C++N4606(94)8.3.2 References [dcl.ref]p205
https://qiita.com/kaizen_nagoya/items/ba8b77d3142cd23440fa

g++とclang++の警告の有無の背景
  clang++ 警告有
  g++ 警告無
g++とclang++の実行結果の違いの背景

_Complex

C++ N4606 (51) 5.18 Assignment and compound assignment operators [expr.ass] p137
https://qiita.com/kaizen_nagoya/items/4f4b1e6073b33c534d85

comma operator

C++ N4606 (52) 5.19 Comma operator [expr.comma]
https://qiita.com/kaizen_nagoya/items/3111b2885f820b59ebd5

clang++ warninig
g++ no warning

エラーの内容の違い(1) clang++:noexcept, g++/bits/exception_ptr.h

C++ N4606(140)12.4 Destructors [class.dtor]p290
https://qiita.com/kaizen_nagoya/items/db277f41068cb722a9cb
clang++ 'noexcept'
g++ /bits/exception_ptr.h

エラーの内容の違い(2) clang++:int_type, g++:bitmask

C++N4606 (219)17.5.2.1.3 Bitmask types [bitmask.types]p461
https://qiita.com/kaizen_nagoya/items/d859e9702a2c04f8c9df

clang++はint_type, g++はbitmaskでエラー

エラーの内容の違い(3)

C++N4606 (220)17.5.2.3 Private members [objects.within.classes]p462
https://qiita.com/kaizen_nagoya/items/609c531d3f8c548fb18c

clang++: std::が要るというエラー
g++: streambufは知らんというエラー
using namespace std;を入れると両方消えた。

エラーの出し方の違い

clang++, g++コンパイルエラー方針の違いの例
https://qiita.com/kaizen_nagoya/items/ea6e5009fe126d270a82

clang++ 致命的なエラーはそれ以降出さないか20個まで。
g++ いっぱいエラー出す。

実行中断と無限ループ?

C++ N4606 Working Draft 2016, ISO/IEC 14882, C++ standard(62) 6.7 Declaration statement [stmt.dcl] p150
https://qiita.com/kaizen_nagoya/items/270ac1a6bbcc82b4bfed

clang++とg++の実行時エラーの有無の背景。
clang++ 実行中断(libc++abi.dylib: __cxa_guard_acquire detected deadlock, Abort trap: 6)
g++ 無限ループ?(^Cで手動終了)

警告の有無と実行時エラーの有無

C++ N4606(151)13.3.1.1.2 Call to object of class type [over.call.object]p319
https://qiita.com/kaizen_nagoya/items/1cfd10e65cd1c6b1e723

clang++警告有り、実行時エラー
g++警告なし、実行時エラーなし

実行時エラーと実行時エラーなし

N4606 Working Draft 2016, ISO/IEC 14882, C++ standard(87)7.6.7 Nodiscard attribute [dcl.attr.nodiscard] p199
https://qiita.com/kaizen_nagoya/items/55113745d005a1dd1745

参考資料

コンパイル用shell script C版(clangとgcc)とC++版(clang++とg++)
https://qiita.com/kaizen_nagoya/items/74220c0577a512c2d7da

Qiitaに投稿するCのStyle例(暫定)
https://qiita.com/kaizen_nagoya/items/946df1528a6a1ef2bc0d

文書履歴

ver. 0.10 初稿 20180408
ver. 0.11 C++追記 20180409
ver. 0.12 _Complex, comma operator 追記 20180416
ver. 0.13 「実行中断と無限ループ?」、「コンパイルエラーと警告」20180417
ver. 0.14「C++は -std=C++17で比較する(今、C++2017を追っかけ中)」 「警告の有無と実行時の値の違い追記」 20180417
ver. 0.15 「エラーの理由」「エラーの出し方の違い」「警告の有無」「警告の有無と実行時エラーの有無」追記 20180420
ver. 0.16 「clang++リンクエラー、g++エラーなし」「コンパイルエラーの個数(2)」「エラーの内容の違いint_type, bitmask」「コンパイルエラーと警告なし(3)g++がエラー, clang++は実行。cassert をincludeでエラーがなくなる」追記
ver. 0.17 20180422 ver 0.16 #実行結果の値の違い clang++: 0 g++:1追記
ver. 0.18 20180427 -std=C++03 でgccだと#include がないとEXIT_SUCCESSなどの定数でコンパイルエラー -std=C++11, -std=C++17ではエラにならない。clang++ではいずれもエラー出ない。
ver. 0.19 20180430 「コンパイルエラーと警告なし(5) cpprefjpのdecltypeをコンパイル試験」追記
ver. 0.20 20180504 「コンパイルエラーと警告なし(6)std::bitset<8>() と include bitset」追記
ver. 0.21 20180505 「コンパイルエラーと警告(2)g++はコンパイルエラー、clang++は別の警告」追記
ver. 0.22 20180505 「警告の有無(2) g++警告なし, clang++警告2」追記
ver. 0.23 20180507 「#実行結果の値の違い(2) C++N4741(31) clang++ 文字'C'出力, g++ ??出力」「コンパイルエラーと警告(4) clang++コンパイルエラー、g++unused警告」追記
ver. 0.24 ありがとう追記 20230413

最後までおよみいただきありがとうございました。

いいね 💚、フォローをお願いします。

Thank you very much for reading to the last sentence.

Please press the like icon 💚 and follow me for your happy life.

4
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
4
1