clang-format pada chapter sebelumnya hanya menata karakter — ia berhenti sebelum menilai apa arti baris tersebut. clang-tidy melangkah lebih jauh: alat ini membaca kode sebagai pohon sintaks (AST) hasil frontend Clang, lalu menjalankan ratusan check bernama yang masing-masing mengenali satu pola kode dan menawarkan perbaikannya. Hasilnya bukan sekadar “ada masalah di baris ini”, melainkan “masalah apa, dari kategori apa, dan biasanya diperbaiki seperti apa” — laporan yang bisa langsung dieksekusi. clang-tidy tidak terinstal di sandbox penulis, sehingga laporan yang Anda lihat di chapter ini adalah ilustrasi formatnya; tetapi kode yang menjadi targetnya kita kompilasi dan jalankan sungguhan, karena seleranya persis itu: kode yang berjalan baik di mata compiler, tetapi menyimpan beberapa kebiasaan yang layak diperbaiki.

Empat Kategori Check yang Paling Sering Dipakai #

Check clang-tidy dikelompokkan dengan awalan nama, dan hampir seluruh kerja sehari-hari berada di empat kategori ini:

KategoriFokusContoh check
bugprone-*pola yang hampir pasti menyimpan bugbugprone-undefined-memory-manipulation, bugprone-narrowing-conversions
performance-*pemborosan yang tak disadari penulisnyaperformance-unnecessary-value-param, performance-for-range-copy
modernize-*gaya lama yang punya pengganti modernmodernize-use-nullptr, modernize-make-unique, modernize-loop-convert
readability-*kejelasan tanpa mengubah perilakureadability-identifier-naming, readability-const-return-type

Di luar itu, clang-tidy juga menjalankan diagnostic compiler Clang pada baris yang dipindai — jadi sebagian warning yang sudah kita pelajari pada chapter Compiler Warnings muncul kembali di sini. Konsep lain yang membuat clang-tidy praktis adalah fix otomatis: banyak check menyertakan perbaikan siap terapkan, dan flag -fix membuat clang-tidy menulisnya langsung ke berkas — perbaikan pada kategori modernize biasanya aman untuk diterapkan massal.

Studi Kasus: Kode yang Berjalan Baik, Menurut clang-tidy Belum #

Target kita berjalan mulus, lolos -Wall -Wextra tanpa satu pun peringatan, dan menghasilkan output yang benar:

cpp
// kandidat-tidy.cpp — berjalan dengan benar, tetapi clang-tidy punya
// beberapa saran perbaikan untuk kode ini (modernize-* dan performance-*).

#include <iostream>
#include <memory>
#include <string>
#include <vector>

struct Profil {
    std::string nama;
    int level;
};

void tampilkan(Profil profil) {
    std::cout << profil.nama << " level " << profil.level << "\n";
}

int main() {
    std::vector<int> nilai = {4, 8, 15};
    int total = 0;
    for (std::size_t i = 0; i < nilai.size(); ++i) {
        total += nilai[i];
    }

    std::unique_ptr<Profil> pemilik(new Profil{"Budi", 3});
    int* petunjuk = 0;
    if (petunjuk == nullptr) {
        std::cout << "petunjuk belum menunjuk apa-apa\n";
    }

    tampilkan(*pemilik);
    std::cout << "total: " << total << "\n";
    return 0;
}

Output yang Dihasilkan:

text
petunjuk belum menunjuk apa-apa
Budi level 3
total: 27

Sekarang jalankan clang-tidy dengan perintah berikut — perhatikan tanda -- yang memisahkan argumen clang-tidy dari flag compiler:

bash
clang-tidy -checks='-*,performance-*,modernize-*' kandidat-tidy.cpp -- -std=c++23

Format laporannya (ilustrasi — clang-tidy tidak terinstal di sandbox; teks pesan bisa sedikit berbeda antar versi):

text Contoh laporan clang-tidy pada kandidat-tidy.cpp
kandidat-tidy.cpp:14:23: warning: the parameter 'profil' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
void tampilkan(Profil profil) {
               ^
               const      &
kandidat-tidy.cpp:21:22: warning: use range-based for loop instead [modernize-loop-convert]
    for (std::size_t i = 0; i < nilai.size(); ++i) {
                         ^
kandidat-tidy.cpp:25:37: warning: use std::make_unique instead [modernize-make-unique]
    std::unique_ptr<Profil> pemilik(new Profil{"Budi", 3});
                                    ^
                                    std::make_unique<Profil>(
kandidat-tidy.cpp:26:22: warning: use nullptr instead of 0 [modernize-use-nullptr]
    int* petunjuk = 0;
                     ^
4 warnings generated.

Empat temuan, dan masing-masing layak kita bedah:

  1. performance-unnecessary-value-param (baris 14) — parameter Profil profil disalin utuh pada setiap pemanggilan tampilkan, padahal function hanya membaca. Laporan bahkan menampilkan bentuk perbaikannya di bawah caret: ubah menjadi const Profil& — salinan hilang, perilaku identik. Pada struct yang berisi std::string, biaya salinan ini bukan main-main di program yang memanggilnya ribuan kali.
  2. modernize-loop-convert (baris 21) — loop indeks manual bisa ditulis sebagai range-based for. Selain lebih pendek, versi range-based menghapus seluruh kelas bug tipe indeks (std::size_t versus int) yang sudah kita bahas pada chapter Compiler Warnings.
  3. modernize-make-unique (baris 25) — std::unique_ptr<Profil> pemilik(new Profil{...}) memisahkan alokasi dan kepemilikan dalam dua langkah; std::make_unique<Profil>(...) menggabungkannya jadi satu ungkapan yang aman terhadap exception dan lebih singkat.
  4. modernize-use-nullptr (baris 26) — int* petunjuk = 0; sah, tetapi 0 juga nilai bilangan bulat sehingga bermakna ganda; nullptr hanya pointer dan membuat niat penulisnya tak terbantahkan.

Yang menarik dari kasus ini: tidak ada satu pun temuan yang membuat program salah hari ini. Itu justru karakter linting yang sehat — temuan-temuannya kecil secara individual, tetapi menumpuk menjadi perbedaan besar antara kode yang “berjalan” dan kode yang mudah dirawat.

Konfigurasi Proyek: Berkas .clang-tidy #

Mengetik -checks=... di setiap panggilan tidak mungkin bertahan lama. Seperti clang-format, clang-tidy membaca konfigurasi proyek dari satu berkas:

yaml Contoh .clang-tidy untuk proyek course
Checks: >
  -*,
  bugprone-*,
  performance-*,
  modernize-*,
  readability-*,
  -modernize-use-trailing-return-type
WarningsAsErrors: 'performance-*,bugprone-*'
FormatStyle: file

Pola bacanya: -* mematikan semua check bawaan lebih dulu, baris berikutnya menyalakan empat kategori pilihan kita, dan satu check dikecualikan (bentuk return auto yang disarankan check itu belum kita ajarkan di course ini — dan inilah pola yang benar untuk check yang tidak relevan bagi proyek: kecualikan secara spesifik, jangan matikan semuanya). WarningsAsErrors menaikkan dua kategori paling berbahaya menjadi error sehingga build gagal bila muncul, dan FormatStyle: file membuat perbaikan otomatis mengikuti .clang-format yang sama.

clang-tidy dalam Pipeline CI #

Di mesin lokal, clang-tidy paling cocok dijalankan pada berkas yang baru saja Anda ubah — laporannya langsung bisa ditindaklanjuti. Di CI, ia menjadi gerbang kolektif: satu job yang menjalankan clang-tidy atas seluruh proyek, dan pipeline gagal bila ada temuan yang dikonfigurasi sebagai error. Karena clang-tidy perlu tahu flag kompilasi yang dipakai proyek, proyek berbasis CMake menyediakannya lewat berkas compile_commands.json yang dirujuk dengan flag -p — jangan khawatir jika istilah itu belum familiar, kita akan mengujinya pada Section Build System dan Project Structure. Pola job CI-nya sendiri sederhana:

yaml Konsep job clang-tidy di CI (GitHub Actions)
jobs:
  tidy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Konfigurasi CMake untuk compile_commands.json
        run: cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
      - name: clang-tidy
        run: clang-tidy -p build $(git ls-files '*.cpp')

Kombinasi inilah yang membuat kebiasaan ini bertahan: clang-format menjaga bentuk tetap seragam tanpa campur tangan manusia, clang-tidy menjaga pola-pola makna kecil tetap sehat, dan keduanya berjalan otomatis setiap ada perubahan. Namun ada satu kelas pertanyaan yang tidak bisa dijawab alat manapun sampai hari ini: apakah function konversiCelsiusKeFahrenheit benar-benar mengembalikan 212 saat menerima 100? Itu pertanyaan tentang perilaku, dan jawabannya hanya bisa datang dari kode yang menguji kode — unit testing, yang kita bangun pada chapter berikutnya.

Referensi: Clang — clang-tidy , Clang — Daftar check clang-tidy .