Skip to content

Commit

Permalink
例に main 関数をつけ wandbox でコンパイル可能にした (#473)
Browse files Browse the repository at this point in the history
  • Loading branch information
e-kwsm committed Nov 4, 2017
1 parent 1359d48 commit e66760f
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 71 deletions.
64 changes: 20 additions & 44 deletions lang/cpp17/fallthrough.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,64 +15,40 @@ switch-case文において意図しないフォールスルーによってバグ

##
```cpp
void f(int n) {
void g(), h(), i();
#include <iostream>

int main() {
int n = 3;
switch (n) {
case 1:
case 2: //caseの間に1つも文がなければフォールスルーは警告されない
g();
std::cout << "case 2\n";
[[fallthrough]];
case 3: //[[fallthrough]]属性の記述によりフォールスルー警告は無効化される
h();
std::cout << "case 3\n";
case 4: //コンパイラがフォールスルーを警告する
i();
[[fallthrough]]; //最後のcaseには記述できない、コンパイルエラーになる
std::cout << "case 4\n";
//[[fallthrough]]; //最後のcaseには記述できない、コンパイルエラーになる
}
}
```

### 出力
clang++ 5.0.0 にてコンパイルした場合。
```
fallthrough.cpp:12:5: error: fallthrough annotation does not directly precede switch label
[[fallthrough]]; //最後のcaseには記述できない、コンパイルエラーになる
^
1 error generated.
case 3
case 4
```

## 検討されたほかの選択肢
* キーワードではなく属性である理由
`fallthrough`をキーワードとして定義した場合、他の制御構文キーワード`continue`や`break`と揃う利点があるが、`fallthrough`を関数名、変数名に使用しているプログラムがあった場合、過去との互換性を壊す可能性がある。
* caseラベルに属性を指定せず、単独で記述する理由
下記のように`case`内に分岐があって分岐の中で`break`を記述している場合に、バグを見逃してしまう場合がある。
```cpp
switch (n) {
case 2:
if (c1) {
f();
break;
} else if (c2) {
g(); // 警告、case 3にフォールスルーするがバグではないか?
} else if (c3) {
h();
break;
} else if (c4) {
g();
h();
[[fallthrough]]; // case 3にフォールスルーするのは意図的である
}
case 3:
  // もしcaseに属性を指定する仕様だったら、
// if (c2) のフォールスルーは正しいことになり、バグだった場合に見逃す
h();
}
### 警告例
g++ 7.1.0、`-Wextra` オプションでコンパイルした場合:
```
fallthrough.cpp: In function ‘int main()’:
fallthrough.cpp:11:15: warning: this statement may fall through [-Wimplicit-fallthrough=]
std::cout << "case 3\n";
~~~~~~~~~~^~~~~~~~~~~~~
fallthrough.cpp:12:3: note: here
case 4: //コンパイラがフォールスルーを警告する
^~~~
```

## 関連項目
Expand Down
25 changes: 15 additions & 10 deletions lang/cpp17/maybe_unused.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,27 +76,32 @@ enum class [[maybe_unused]] E {
```cpp
#include <cassert>

//警告が発生しない
[[maybe_unused]] void f([[maybe_unused]] bool thing1,
[[maybe_unused]] bool thing2) {
[[maybe_unused]] bool b = thing1 && thing2;
//警告は発生しない
[[maybe_unused]] void f([[maybe_unused]] bool flag1,
[[maybe_unused]] bool flag2) {
[[maybe_unused]] bool b = flag1 && flag2;
assert(b);
}

//警告が発生する場合がある
void g(bool thing3, bool thing4) {
bool b2 = thing3 && thing4;
void g(bool flag3, bool flag4) {
bool b2 = flag3 && flag4;
assert(b2);
}

int main() {
f(true, true);
g(true, true);
}
```
### 出力
clang++ 5.0.0 にてコンパイルした場合。
```
$ clang++ -std=c++1z -Wall -DNDEBUG maybe_unused.cpp -c
```
### 警告例
clang++ 5.0.0、`-Wall -DNDEBUG` オプションでコンパイルした場合:
```
maybe_unused.cpp:12:8: warning: unused variable 'b2' [-Wunused-variable]
bool b2 = thing3 && thing4;
^
Expand Down
33 changes: 16 additions & 17 deletions lang/cpp17/nodiscard.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,32 @@
##
```cpp
//無視してはいけないデータ型
struct [[nodiscard]] error_info { /*...*/ };
struct [[nodiscard]] error_info {};

error_info safety_mode();
void launch();
error_info f() { return error_info{}; }

//関数の戻り値を必ず使用すること
[[nodiscard]] int check_mode();
[[nodiscard]] int g() { return 0; }

void test_missiles() {
safety_mode(); //無視してはいけない型を無視したため、警告が発生するだろう
launch();

check_mode(); //戻り値を無視しているため、警告が発生するだろう
int main() {
f(); //無視してはいけない型を無視したため、警告が発生するだろう
g(); //戻り値を無視したため、警告が発生するだろう
}
```

### 出力
```
```

clang++ 5.0.0 にてコンパイルした場合。

### 警告例
clang++ 5.0.0 でコンパイルした場合:
```
nodiscard.cpp:12:3: warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
safety_mode(); //無視してはいけない型を無視したため、警告が発生するだろう
^~~~~~~~~~~
nodiscard.cpp:15:3: warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
check_mode(); //戻り値を無視しているため、警告が発生するだろう
^~~~~~~~~~
nodiscard.cpp:10:3: warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
f(); //無視してはいけない型を無視したため、警告が発生するだろう
^
nodiscard.cpp:11:3: warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
g(); //戻り値を無視しているため、警告が発生するだろう
^
2 warnings generated.
```

Expand Down

1 comment on commit e66760f

@saki7
Copy link
Contributor

@saki7 saki7 commented on e66760f Nov 4, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

助かります! 🎨

Please sign in to comment.