C
C++
GCC
clang

Clang/Clang++(LLVM) gcc/g++(GNU) コンパイラ警告等比較

目的

複数の処理系(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/drafts/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警告」追記