สำหรับบริบทฉันเป็นนักพัฒนาเสียงดังกราวทำงานที่ Google ที่ Google เราได้นำการวินิจฉัยของ Clang ออกมาให้กับนักพัฒนา C ++ ทุกคนและเราปฏิบัติต่อคำเตือนของ Clang ว่าเป็นข้อผิดพลาดเช่นกัน ในฐานะที่เป็นทั้งผู้พัฒนา Clang และหนึ่งในผู้ใช้ที่ใหญ่กว่าของ Clang Diagnostics ฉันจะพยายามทำให้กระจ่างในธงเหล่านี้และวิธีการใช้ โปรดทราบว่าทุกสิ่งที่ฉันอธิบายนั้นสามารถใช้กับเสียงดังกราวทั่วไปและไม่เฉพาะเจาะจงกับ C, C ++ หรือ Objective-C
TL; DR เวอร์ชัน: โปรดใช้-Wall
และ-Werror
อย่างน้อยกับรหัสใหม่ใด ๆ ที่คุณกำลังพัฒนา เรา (ผู้พัฒนาคอมไพเลอร์) เพิ่มคำเตือนที่นี่ด้วยเหตุผลที่ดี: พวกเขาพบข้อบกพร่อง หากคุณพบคำเตือนที่จับข้อบกพร่องให้คุณเปิดเช่นกัน ลอง-Wextra
หากลุ่มผู้สมัครที่ดีที่นี่ หากหนึ่งในนั้นคือมีเสียงดังมากเกินไปสำหรับคุณที่จะใช้กำไรยื่นข้อผิดพลาด หากคุณเขียนรหัสที่มีข้อผิดพลาด "ชัดเจน" แต่คอมไพเลอร์ไม่ได้เตือนเกี่ยวกับมันให้ยื่นข้อผิดพลาด
ตอนนี้สำหรับรุ่นยาว พื้นหลังแรกในการจัดกลุ่มธงเตือน คำเตือนใน Clang มี "กลุ่ม" จำนวนมาก (และในขอบเขตที่ จำกัด ใน GCC) บางส่วนที่เกี่ยวข้องกับการสนทนานี้:
- โดยค่าเริ่มต้น: คำเตือนเหล่านี้จะเปิดอยู่เสมอเว้นแต่คุณจะปิดการใช้งานอย่างชัดเจน
-Wall
: สิ่งเหล่านี้เป็นการเตือนว่าผู้พัฒนามีความมั่นใจสูงทั้งในด้านมูลค่าและอัตราการบวกลบที่ต่ำ
-Wextra
: สิ่งเหล่านี้เป็นคำเตือนที่เชื่อว่ามีคุณค่าและเสียง (กล่าวคือพวกเขาไม่ได้บั๊ก) แต่พวกเขาอาจมีอัตราการบวกเท็จสูงหรือการคัดค้านทางปรัชญาที่พบบ่อย
-Weverything
: นี่เป็นกลุ่มวิกลจริตที่เปิดใช้งานการ
เตือนทุกครั้งใน Clang อย่าใช้สิ่งนี้กับรหัสของคุณ มันมีจุดมุ่งหมายอย่างเคร่งครัดสำหรับนักพัฒนาเสียงดังกราวหรือสำหรับการสำรวจสิ่งที่อยู่คำเตือน
มีเกณฑ์หลักสองข้อที่กล่าวถึงข้างต้นซึ่งเป็นแนวทางในการเตือนไปที่เสียงดังกังวานและให้ความกระจ่างแก่สิ่งเหล่านี้ ประการแรกคือ
ค่าที่เป็นไปได้ของการเกิดขึ้นโดยเฉพาะของคำเตือน นี่คือประโยชน์ที่คาดว่าจะเกิดขึ้นกับผู้ใช้ (นักพัฒนา) เมื่อคำเตือนเริ่มทำงานและ
ระบุปัญหาด้วยรหัสได้อย่างถูกต้อง
เกณฑ์ที่สองคือแนวคิดของรายงานที่ผิดพลาด เหล่านี้เป็นสถานการณ์ที่คำเตือนใช้รหัส แต่ปัญหาที่อาจเกิดขึ้นที่อ้างถึงนั้นไม่ได้เกิดขึ้นจริงเนื่องจากบริบทหรือข้อ จำกัด อื่น ๆ ของโปรแกรม รหัสเตือนเกี่ยวกับการทำงานจริงอย่างถูกต้อง สิ่งเหล่านี้เป็นสิ่งที่ไม่ดีโดยเฉพาะอย่างยิ่งเมื่อคำเตือนไม่เคยตั้งใจจะใช้รูปแบบรหัสนั้น แต่มันเป็นข้อบกพร่องในการใช้งานคำเตือนที่ทำให้เกิดไฟไหม้ที่นั่น
สำหรับคำเตือนแบบเสียงดังกังวานค่านั้นจำเป็นต้องอยู่ในรูปแบบของความถูกต้องไม่ใช่แบบแผนการลิ้มรสหรือแบบแผนการเข้ารหัส สิ่งนี้ จำกัด ชุดของการเตือนที่มีอยู่ซึ่งจะแยกการเตือนของการร้องขอที่ร้องขอเช่นคำเตือนเมื่อใดก็ตาม{}
ที่ไม่ได้ใช้ s รอบ ๆ เนื้อความของif
คำสั่ง เสียงดังกราวยังเป็นสิ่งที่ทนต่อความผิดพลาดได้เป็นอย่างมาก แตกต่างจากคอมไพเลอร์อื่น ๆ โดยส่วนใหญ่จะใช้แหล่งข้อมูลที่หลากหลายอย่างไม่น่าเชื่อในการตัดผลบวกปลอมรวมถึงการสะกดคำที่แน่นอนของสิ่งก่อสร้างการมีอยู่หรือไม่มีส่วนเสริม '()' การปลดเปลื้องหรือแม้แต่มาโครตัวประมวลผลล่วงหน้า!
ทีนี้ลองมาดูตัวอย่างคำเตือนในโลกแห่งความจริงจาก Clang แล้วดูว่าพวกมันถูกจัดหมวดหมู่อย่างไร ก่อนคำเตือนเริ่มต้น:
% nl x.cc
1 class C { const int x; };
% clang -fsyntax-only x.cc
x.cc:1:7: warning: class 'C' does not declare any constructor to initialize its non-modifiable members
class C { const int x; };
^
x.cc:1:21: note: const member 'x' will never be initialized
class C { const int x; };
^
1 warning generated.
ที่นี่ไม่จำเป็นต้องตั้งค่าสถานะเพื่อรับคำเตือนนี้ เหตุผลก็คือว่านี่เป็นรหัสที่ไม่ถูกต้องจริง ๆ ให้มูลค่าสูงเตือนและคำเตือนเพียงยิงบนรหัสที่เสียงดังกราวสามารถพิสูจน์ได้ตกอยู่ในถังนี้ทำให้มันเป็นศูนย์อัตราบวกเท็จ
% nl x2.cc
1 int f(int x_) {
2 int x = x;
3 return x;
4 }
% clang -fsyntax-only -Wall x2.cc
x2.cc:2:11: warning: variable 'x' is uninitialized when used within its own initialization [-Wuninitialized]
int x = x;
~ ^
1 warning generated.
เสียงดังกราวต้องการ-Wall
แฟล็กสำหรับคำเตือนนี้ เหตุผลก็คือมีรหัสที่ไม่สำคัญซึ่งมีการใช้รูปแบบโค้ดที่ดี (หรือไม่ดี) ที่เราได้รับคำเตือนเกี่ยวกับการสร้างมูลค่าที่ไม่ได้เตรียมไว้โดยเจตนา ในทางปรัชญาแล้วฉันไม่เห็นประเด็นใดในเรื่องนี้ แต่คนอื่น ๆ ไม่เห็นด้วยและความเป็นจริงของความแตกต่างในความเห็นนี้คือสิ่งที่ขับเคลื่อนการเตือนภายใต้
-Wall
ธง มันยังคงมีมูลค่าสูงมากและมีอัตราการบวกเป็นเท็จที่ต่ำมาก
แต่สำหรับบางโค้ดมันเป็น non-starter
% nl x3.cc
1 void g(int x);
2 void f(int arr[], unsigned int size) {
3 for (int i = 0; i < size; ++i)
4 g(arr[i]);
5 }
% clang -fsyntax-only -Wextra x3.cc
x3.cc:3:21: warning: comparison of integers of different signs: 'int' and 'unsigned int' [-Wsign-compare]
for (int i = 0; i < size; ++i)
~ ^ ~~~~
1 warning generated.
คำเตือนนี้ต้องใช้-Wextra
ธง เหตุผลก็คือมี
ฐานรหัสขนาดใหญ่มากซึ่งสัญญาณที่จับคู่ผิดในการเปรียบเทียบนั้นเป็นเรื่องธรรมดามาก ในขณะที่คำเตือนนี้พบข้อบกพร่องบางอย่างน่าจะเป็นของรหัสที่เป็นข้อผิดพลาดเมื่อผู้ใช้เขียนมันค่อนข้างต่ำโดยเฉลี่ย ผลที่ได้คืออัตราบวกเท็จที่สูงมาก แต่เมื่อมีข้อผิดพลาดในโปรแกรมเนื่องจากกฎโปรโมชั่นที่แปลกก็มักจะบอบบางมากทำให้คำเตือนนี้
เมื่อมันธงข้อผิดพลาดที่มีค่อนข้างสูงค่า เป็นผลให้เสียงดังกราวให้มันและเปิดเผยภายใต้ธง
โดยทั่วไปแล้วคำเตือนจะมีชีวิตอยู่ไม่นานนอก-Wextra
ธง เสียงดังกราวพยายามอย่างหนักที่จะไม่ใช้คำเตือนที่ไม่เห็นการใช้งานปกติและการทดสอบ คำเตือนเพิ่มเติมที่เปิดใช้โดย-Weverything
ปกติแล้วคำเตือนภายใต้การพัฒนาที่ใช้งานอยู่หรือมีข้อบกพร่องที่ใช้งานอยู่ อาจจะได้รับการแก้ไขและวางไว้ภายใต้ธงที่เหมาะสมหรือควรลบออก
ตอนนี้เรามีความเข้าใจในการทำงานของสิ่งเหล่านี้กับ Clang แล้วลองกลับไปที่คำถามเดิม: คุณควรเปิดคำเตือนอะไรไว้สำหรับการพัฒนาของคุณ คำตอบคือน่าเสียดายที่มันขึ้นอยู่กับ ลองพิจารณาคำถามต่อไปนี้เพื่อช่วยพิจารณาว่าคำเตือนใดทำงานได้ดีที่สุดสำหรับสถานการณ์ของคุณ
- คุณสามารถควบคุมรหัสทั้งหมดของคุณหรือเป็นบางส่วนภายนอกได้หรือไม่
- เป้าหมายของคุณคืออะไร จับข้อบกพร่องหรือเขียนรหัสที่ดีกว่า
- การยอมรับผิดพลาดของคุณคืออะไร คุณยินดีที่จะเขียนรหัสพิเศษเพื่อเงียบเตือนเป็นประจำหรือไม่
ก่อนอื่นถ้าคุณไม่ควบคุมรหัสอย่าพยายามเปิดคำเตือนเพิ่มเติมที่นั่น เตรียมพร้อมที่จะปิดบางอย่าง มีโค้ดที่ไม่ดีมากมายในโลกและคุณอาจไม่สามารถแก้ไขได้ทั้งหมด ไม่เป็นไร พยายามหาวิธีที่จะมุ่งเน้นความพยายามของคุณในรหัสที่คุณควบคุม
จากนั้นให้หาสิ่งที่คุณต้องการจากคำเตือนของคุณ สิ่งนี้แตกต่างกันไปสำหรับคนอื่น เสียงดังกราวจะพยายามเตือนโดยไม่มีตัวเลือกใด ๆ เกี่ยวกับข้อผิดพลาดร้ายแรงหรือรูปแบบรหัสที่เรามีมาก่อนหน้าประวัติศาสตร์ที่ยาวนานระบุอัตราข้อผิดพลาดที่สูงมาก เมื่อเปิดใช้งาน-Wall
คุณจะได้รับชุดคำเตือนที่ก้าวร้าวมากขึ้นโดยมุ่งเน้นที่การจับข้อผิดพลาดที่พบบ่อยที่สุดซึ่งนักพัฒนาเสียงดังดังได้สังเกตเห็นในรหัส C ++ แต่ด้วยอัตราทั้ง
บวกและลบควรมีอัตราที่ค่อนข้างต่ำ
สุดท้ายหากคุณยินดีที่จะเงียบ * เท็จบวก s * -Wextra
ทุกครั้งที่เลี้ยวไปสำหรับ ไฟล์บั๊กหากคุณสังเกตเห็นคำเตือนที่จับข้อผิดพลาดจริงจำนวนมาก แต่ที่มีข้อผิดพลาดที่โง่หรือไร้จุดหมาย เรากำลังทำงานอย่างต่อเนื่องเพื่อหาวิธีการที่จะนำมากขึ้นของตรรกะข้อผิดพลาดการค้นพบที่นำเสนอในการ-Wextra
เข้าไปใน-Wall
ที่ที่เราสามารถหลีกเลี่ยงเท็จบวก
หลายคนจะพบว่าไม่มีตัวเลือกเหล่านี้ที่เหมาะสมสำหรับพวกเขา ที่ Google เราได้ปิดคำเตือน-Wall
เนื่องจากรหัสที่มีอยู่จำนวนมากซึ่งละเมิดคำเตือน เราได้เปิดการเตือนบางอย่างอย่างชัดเจนแม้ว่าพวกเขาจะไม่ได้เปิดใช้งาน-Wall
เพราะพวกเขามีค่าสูงเป็นพิเศษสำหรับเรา ระยะของคุณจะแตกต่างกัน แต่มีแนวโน้มที่จะแตกต่างกันไปในทำนองเดียวกัน -Wextra
มันมักจะดีกว่าที่จะเปิดใช้งานคำเตือนที่สำคัญบางมากกว่าทั้งหมดของ
ฉันขอแนะนำให้ทุกคนเปิด-Wall
ใช้รหัสที่ไม่ได้รับมรดก สำหรับรหัสใหม่คำเตือนที่นี่มีค่าเกือบตลอดเวลาและทำให้การพัฒนาโค้ดดีขึ้น ตรงกันข้ามผมจะสนับสนุนให้ทุกคน
ไม่ได้-Wextra
เปิดใช้งานธงเกิน หากคุณพบว่าคำเตือนเสียงดังกราวที่-Wextra
ไม่ได้รวมถึง แต่ที่พิสูจน์ที่ทุกคน-Wextra
มีคุณค่าให้กับคุณเพียงแค่ยื่นข้อผิดพลาดและเราจะสามารถวางไว้ใต้ ไม่ว่าคุณจะเปิดใช้งานอย่างชัดเจนส่วนย่อยบางส่วนของคำเตือนในการจะขึ้นอยู่อย่างหนักในรหัสของคุณรูปแบบการเข้ารหัสของคุณและไม่ว่าจะรักษารายการที่ง่ายกว่าเครื่องประกอบทุกอย่างที่ค้นพบโดย-Wextra
-Wextra
จากรายการคำเตือนของ OP (ซึ่งรวมทั้ง-Wall
และ-Wextra
) เฉพาะคำเตือนต่อไปนี้เท่านั้นที่ไม่ครอบคลุมโดยทั้งสองกลุ่ม (หรือเปิดตามค่าเริ่มต้น) กลุ่มแรกเน้นเหตุผลมากกว่าการพึ่งพาธงเตือนอย่างชัดเจนจะไม่ดี: ไม่มีของเหล่านี้จะได้ดำเนินการในเสียงดังกราว! พวกเขาได้รับการยอมรับในบรรทัดคำสั่งเฉพาะสำหรับความเข้ากันได้ของ GCC
-Wbad-function-cast
-Wdeclaration-after-statement
-Wmissing-format-attribute
-Wmissing-noreturn
-Wnested-externs
-Wnewline-eof
-Wold-style-definition
-Wredundant-decls
-Wsequence-point
-Wstrict-prototypes
-Wswitch-default
ที่เก็บข้อมูลชุดถัดไปของคำเตือนที่ไม่จำเป็นในรายการต้นฉบับคือคำเตือนที่ซ้ำซ้อนกับผู้อื่นในรายการนั้น:
-Wformat-nonliteral
- ชุดย่อยของ -Wformat=2
-Wshorten-64-to-32
- ชุดย่อยของ -Wconversion
-Wsign-conversion
- ชุดย่อยของ -Wconversion
นอกจากนี้ยังมีการเลือกคำเตือนที่แตกต่างกันอย่างมีนัยสำคัญ การจัดการกับตัวแปรภาษาถิ่นเหล่านี้แทนด้วยรหัส buggy หรือ non-buggy ด้วยข้อยกเว้น-Wwrite-strings
สิ่งเหล่านี้ล้วนเป็นคำเตือนสำหรับส่วนขยายภาษาที่จัดทำโดย Clang ว่าเสียงดังกราวเตือนเกี่ยวกับการใช้งานของพวกเขาขึ้นอยู่กับความชุกของส่วนขยาย เสียงดังกราวมีจุดประสงค์เพื่อความเข้ากันได้ของ GCC และในหลายกรณีมันช่วยลดความยุ่งยากในการใช้งานส่วนขยายภาษาโดยนัย -Wwrite-strings
ตามความเห็นใน OP คือการตั้งค่าความเข้ากันได้จาก GCC ที่เปลี่ยนความหมายของโปรแกรม ฉันเสียใจอย่างสุดซึ้งกับธงนี้ แต่เราต้องสนับสนุนมันเนื่องจากมรดกที่มีอยู่ตอนนี้
-Wfour-char-constants
-Wpointer-arith
-Wwrite-strings
ตัวเลือกที่เหลือซึ่งเปิดใช้งานการเตือนที่น่าสนใจจริง ๆ คือ:
-Wcast-align
-Wconversion
-Wfloat-equal
-Wformat=2
-Wimplicit-atomic-properties
-Wmissing-declarations
-Wmissing-prototypes
-Woverlength-strings
-Wshadow
-Wstrict-selector-match
-Wundeclared-selector
-Wunreachable-code
เหตุผลที่สิ่งเหล่านี้ไม่ได้อยู่ใน-Wall
หรือ-Wextra
ไม่ชัดเจนเสมอไป สำหรับหลาย ๆ คนเหล่านี้พวกเขาจะจริงตามคำเตือน GCC ( -Wconversion
,
-Wshadow
ฯลฯ ) และเป็นเสียงดังกราวดังกล่าวพยายามที่จะเลียนแบบพฤติกรรมของ GCC เราค่อยๆแบ่งสิ่งเหล่านี้ออกเป็นคำเตือนที่เป็นประโยชน์และมีประโยชน์มากขึ้น สิ่งเหล่านั้นมีโอกาสสูงที่จะทำให้มันเป็นหนึ่งในกลุ่มเตือนระดับบนสุด ที่กล่าวว่าจะรับในหนึ่งเตือน-Wconversion
เป็นดังนั้นในวงกว้างว่ามันมีแนวโน้มที่จะยังคงอยู่ในตัวเอง "ระดับบน" หมวดหมู่ของมันในอนาคตอันใกล้ คำเตือนอื่น ๆ ที่ GCC มี แต่ที่มีค่าต่ำและอัตราการบวกเท็จที่สูงอาจถูกผลักไสให้ไปที่ไม่มีที่ดินของมนุษย์ที่คล้ายกัน
เหตุผลอื่น ๆ ที่ว่าทำไมสิ่งเหล่านี้ไม่ได้อยู่ในหนึ่งในถังที่ใหญ่กว่านั้นรวมถึงข้อบกพร่องอย่างง่ายปัญหาเชิงบวกที่ผิดพลาดที่สำคัญมากและคำเตือนระหว่างการพัฒนา ฉันจะดูข้อผิดพลาดในการยื่นสำหรับสิ่งที่ฉันสามารถระบุได้ ในที่สุดพวกเขาทั้งหมดควรโยกย้ายไปที่ธงถังขนาดใหญ่ที่เหมาะสมหรือถูกลบออกจากเสียงดังกราว
ฉันหวังว่าสิ่งนี้จะอธิบายสถานการณ์เตือนด้วย Clang และให้ข้อมูลเชิงลึกแก่ผู้ที่พยายามเลือกชุดคำเตือนสำหรับการใช้งานหรือการใช้งานของ บริษัท