1// Copyright 2016 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package config 16 17import ( 18 "android/soong/android" 19 "strings" 20) 21 22var ( 23 // Some clang-tidy checks have bugs or don't work for Android. 24 // They are disabled here, overriding any locally selected checks. 25 globalNoCheckList = []string{ 26 // https://b.corp.google.com/issues/153464409 27 // many local projects enable cert-* checks, which 28 // trigger bugprone-reserved-identifier. 29 "-bugprone-reserved-identifier*,-cert-dcl51-cpp,-cert-dcl37-c", 30 // http://b/153757728 31 "-readability-qualified-auto", 32 // http://b/193716442 33 "-bugprone-implicit-widening-of-multiplication-result", 34 // Too many existing functions trigger this rule, and fixing it requires large code 35 // refactoring. The cost of maintaining this tidy rule outweighs the benefit it brings. 36 "-bugprone-easily-swappable-parameters", 37 // http://b/216364337 - TODO: Follow-up after compiler update to 38 // disable or fix individual instances. 39 "-cert-err33-c", 40 // http://b/241125373 41 "-bugprone-unchecked-optional-access", 42 // http://b/265438407 43 "-misc-use-anonymous-namespace", 44 // http://b/285005947 45 "-performance-avoid-endl", 46 } 47 48 // Some clang-tidy checks are included in some tidy_checks_as_errors lists, 49 // but not all warnings are fixed/suppressed yet. These checks are not 50 // disabled in the TidyGlobalNoChecks list, so we can see them and fix/suppress them. 51 globalNoErrorCheckList = []string{ 52 // http://b/241997913 53 "-bugprone-assignment-in-if-condition", 54 // http://b/155034972 55 "-bugprone-branch-clone", 56 // http://b/155034563 57 "-bugprone-signed-char-misuse", 58 // http://b/241819232 59 "-misc-const-correctness", 60 // http://b/285356805 61 "-bugprone-unsafe-functions", 62 "-cert-msc24-c", 63 "-cert-msc33-c", 64 // http://b/285356799 65 "-modernize-type-traits", 66 // http://b/285361108 67 "-readability-avoid-unconditional-preprocessor-if", 68 } 69 70 extraArgFlags = []string{ 71 // We might be using the static analyzer through clang tidy. 72 // https://bugs.llvm.org/show_bug.cgi?id=32914 73 "-D__clang_analyzer__", 74 75 // A recent change in clang-tidy (r328258) enabled destructor inlining, which 76 // appears to cause a number of false positives. Until that's resolved, this turns 77 // off the effects of r328258. 78 // https://bugs.llvm.org/show_bug.cgi?id=37459 79 "-Xclang", 80 "-analyzer-config", 81 "-Xclang", 82 "c++-temp-dtor-inlining=false", 83 } 84) 85 86func init() { 87 // The global default tidy checks should include clang-tidy 88 // default checks and tested groups, but exclude known noisy checks. 89 // See https://clang.llvm.org/extra/clang-tidy/checks/list.html 90 pctx.VariableConfigMethod("TidyDefaultGlobalChecks", func(config android.Config) string { 91 if override := config.Getenv("DEFAULT_GLOBAL_TIDY_CHECKS"); override != "" { 92 return override 93 } 94 checks := strings.Join([]string{ 95 "android-*", 96 "bugprone-*", 97 "cert-*", 98 "clang-diagnostic-unused-command-line-argument", 99 // Select only google-* checks that do not have thousands of warnings. 100 // Add more such checks when we clean up source code. 101 // "google-build-using-namespace", 102 // "google-default-arguments", 103 // "google-explicit-constructor", 104 // "google-global-names-in-headers", 105 // "google-runtime-int", 106 "google-build-explicit-make-pair", 107 "google-build-namespaces", 108 "google-runtime-operator", 109 "google-upgrade-*", 110 "misc-*", 111 "performance-*", 112 "portability-*", 113 "-bugprone-assignment-in-if-condition", 114 "-bugprone-easily-swappable-parameters", 115 "-bugprone-narrowing-conversions", 116 "-misc-const-correctness", 117 "-misc-no-recursion", 118 "-misc-non-private-member-variables-in-classes", 119 "-misc-unused-parameters", 120 "-performance-no-int-to-ptr", 121 // the following groups are not in clang-tidy default checks. 122 // -altera-* 123 // -cppcoreguidelines-* 124 // -darwin-* 125 // -fuchsia-* 126 // -hicpp-* 127 // -llvm-* 128 // -llvmlibc-* 129 // -modernize-* 130 // -mpi-* 131 // -objc-* 132 // -readability-* 133 // -zircon-* 134 }, ",") 135 // clang-analyzer-* checks are slow for large files, but we have TIDY_TIMEOUT to 136 // limit clang-tidy runtime. We allow clang-tidy default clang-analyzer-* checks, 137 // and add it explicitly when CLANG_ANALYZER_CHECKS is set. 138 // The insecureAPI.DeprecatedOrUnsafeBufferHandling warning does not apply to Android. 139 if config.IsEnvTrue("CLANG_ANALYZER_CHECKS") { 140 checks += ",clang-analyzer-*,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling" 141 } else { 142 checks += ",-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling" 143 } 144 return checks 145 }) 146 147 // The external and vendor projects do not run clang-tidy unless TIDY_EXTERNAL_VENDOR is set. 148 // We do not add "-*" to the check list to avoid suppressing the check list in .clang-tidy config files. 149 // There are too many clang-tidy warnings in external and vendor projects, so we only 150 // enable some google checks for these projects. Users can add more checks locally with the 151 // "tidy_checks" list in .bp files, or the "Checks" list in .clang-tidy config files. 152 pctx.VariableConfigMethod("TidyExternalVendorChecks", func(config android.Config) string { 153 if override := config.Getenv("DEFAULT_EXTERNAL_VENDOR_TIDY_CHECKS"); override != "" { 154 return override 155 } 156 return strings.Join([]string{ 157 "clang-diagnostic-unused-command-line-argument", 158 "google-build-explicit-make-pair", 159 "google-build-namespaces", 160 "google-runtime-operator", 161 "google-upgrade-*", 162 "-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling", 163 }, ",") 164 }) 165 166 pctx.StaticVariable("TidyGlobalNoChecks", strings.Join(globalNoCheckList, ",")) 167 168 pctx.StaticVariable("TidyGlobalNoErrorChecks", strings.Join(globalNoErrorCheckList, ",")) 169 170 pctx.StaticVariable("TidyExtraArgFlags", strings.Join(extraArgFlags, " ")) 171 172 // To reduce duplicate warnings from the same header files, 173 // header-filter will contain only the module directory and 174 // those specified by DEFAULT_TIDY_HEADER_DIRS. 175 pctx.VariableConfigMethod("TidyDefaultHeaderDirs", func(config android.Config) string { 176 return config.Getenv("DEFAULT_TIDY_HEADER_DIRS") 177 }) 178 179 // Use WTIH_TIDY_FLAGS to pass extra global default clang-tidy flags. 180 pctx.VariableConfigMethod("TidyWithTidyFlags", func(config android.Config) string { 181 return config.Getenv("WITH_TIDY_FLAGS") 182 }) 183} 184 185type PathBasedTidyCheck struct { 186 PathPrefix string 187 Checks string 188} 189 190const tidyDefault = "${config.TidyDefaultGlobalChecks}" 191const tidyExternalVendor = "${config.TidyExternalVendorChecks}" 192const tidyDefaultNoAnalyzer = "${config.TidyDefaultGlobalChecks},-clang-analyzer-*" 193 194// This is a map of local path prefixes to the set of default clang-tidy checks 195// to be used. This is like android.IsThirdPartyPath, but with more patterns. 196// The last matched local_path_prefix should be the most specific to be used. 197var DefaultLocalTidyChecks = []PathBasedTidyCheck{ 198 {"external/", tidyExternalVendor}, 199 {"frameworks/compile/mclinker/", tidyExternalVendor}, 200 {"hardware/", tidyExternalVendor}, 201 {"hardware/google/", tidyDefault}, 202 {"hardware/interfaces/", tidyDefault}, 203 {"hardware/ril/", tidyDefault}, 204 {"hardware/libhardware", tidyDefault}, // all 'hardware/libhardware*' 205 {"vendor/", tidyExternalVendor}, 206 {"vendor/google", tidyDefault}, // all 'vendor/google*' 207 {"vendor/google/external/", tidyExternalVendor}, 208 {"vendor/google_arc/libs/org.chromium.arc.mojom", tidyExternalVendor}, 209 {"vendor/google_devices/", tidyExternalVendor}, // many have vendor code 210} 211 212var reversedDefaultLocalTidyChecks = reverseTidyChecks(DefaultLocalTidyChecks) 213 214func reverseTidyChecks(in []PathBasedTidyCheck) []PathBasedTidyCheck { 215 ret := make([]PathBasedTidyCheck, len(in)) 216 for i, check := range in { 217 ret[len(in)-i-1] = check 218 } 219 return ret 220} 221 222func TidyChecksForDir(dir string) string { 223 dir = dir + "/" 224 for _, pathCheck := range reversedDefaultLocalTidyChecks { 225 if strings.HasPrefix(dir, pathCheck.PathPrefix) { 226 return pathCheck.Checks 227 } 228 } 229 return tidyDefault 230} 231 232func neverTidyForDir(dir string) bool { 233 // This function can be extended if tidy needs to be disabled for more directories. 234 return strings.HasPrefix(dir, "external/grpc-grpc") 235} 236 237func NoClangTidyForDir(allowExternalVendor bool, dir string) bool { 238 // Tidy can be disable for a module in dir, if the dir is "neverTidyForDir", 239 // or if it belongs to external|vendor and !allowExternalVendor. 240 // This function depends on TidyChecksForDir, which selects tidyExternalVendor 241 // checks for external/vendor projects. 242 return neverTidyForDir(dir) || 243 (!allowExternalVendor && TidyChecksForDir(dir) == tidyExternalVendor) 244} 245 246// Returns a globally disabled tidy checks, overriding locally selected checks. 247func TidyGlobalNoChecks() string { 248 if len(globalNoCheckList) > 0 { 249 return ",${config.TidyGlobalNoChecks}" 250 } 251 return "" 252} 253 254// Returns a globally allowed/no-error tidy checks, appended to -warnings-as-errors. 255func TidyGlobalNoErrorChecks() string { 256 if len(globalNoErrorCheckList) > 0 { 257 return ",${config.TidyGlobalNoErrorChecks}" 258 } 259 return "" 260} 261 262func TidyExtraArgFlags() []string { 263 return extraArgFlags 264} 265 266func TidyFlagsForSrcFile(srcFile android.Path, flags string) string { 267 // Disable clang-analyzer-* checks globally for generated source files 268 // because some of them are too huge. Local .bp files can add wanted 269 // clang-analyzer checks through the tidy_checks property. 270 // Need to do this patch per source file, because some modules 271 // have both generated and organic source files. 272 if _, ok := srcFile.(android.WritablePath); ok { 273 if strings.Contains(flags, tidyDefault) { 274 return strings.ReplaceAll(flags, tidyDefault, tidyDefaultNoAnalyzer) 275 } 276 } 277 return flags 278} 279