Index: clang-tidy/ClangTidy.cpp =================================================================== --- clang-tidy/ClangTidy.cpp +++ clang-tidy/ClangTidy.cpp @@ -36,6 +36,7 @@ #include "clang/Tooling/Refactoring.h" #include "clang/Tooling/ReplacementsYaml.h" #include "clang/Tooling/Tooling.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/Signals.h" @@ -376,6 +377,19 @@ std::vector *Errors, ProfileData *Profile) { ClangTool Tool(Compilations, InputFiles); clang::tidy::ClangTidyContext Context(std::move(OptionsProvider)); + ArgumentsAdjuster PerFileExtraArgumentsInserter = [&Context]( + const CommandLineArguments &Args, StringRef Filename) { + ClangTidyOptions Opts = Context.getOptionsForFile(Filename); + CommandLineArguments AdjustedArgs; + if (Opts.ExtraArgsBefore) + AdjustedArgs = *Opts.ExtraArgsBefore; + AdjustedArgs.insert(AdjustedArgs.begin(), Args.begin(), Args.end()); + if (Opts.ExtraArgs) + AdjustedArgs.insert(AdjustedArgs.end(), Opts.ExtraArgs->begin(), + Opts.ExtraArgs->end()); + return AdjustedArgs; + }; + Tool.appendArgumentsAdjuster(PerFileExtraArgumentsInserter); if (Profile) Context.setCheckProfileData(Profile); Index: clang-tidy/ClangTidyDiagnosticConsumer.h =================================================================== --- clang-tidy/ClangTidyDiagnosticConsumer.h +++ clang-tidy/ClangTidyDiagnosticConsumer.h @@ -165,6 +165,8 @@ /// \brief Returns options for \c CurrentFile. const ClangTidyOptions &getOptions() const; + ClangTidyOptions getOptionsForFile(StringRef File) const; + /// \brief Returns \c ClangTidyStats containing issued and ignored diagnostic /// counters. const ClangTidyStats &getStats() const { return Stats; } Index: clang-tidy/ClangTidyDiagnosticConsumer.cpp =================================================================== --- clang-tidy/ClangTidyDiagnosticConsumer.cpp +++ clang-tidy/ClangTidyDiagnosticConsumer.cpp @@ -202,9 +202,7 @@ void ClangTidyContext::setCurrentFile(StringRef File) { CurrentFile = File; - // Safeguard against options with unset values. - CurrentOptions = ClangTidyOptions::getDefaults().mergeWith( - OptionsProvider->getOptions(CurrentFile)); + CurrentOptions = getOptionsForFile(CurrentFile); CheckFilter.reset(new GlobList(*getOptions().Checks)); } @@ -221,6 +219,13 @@ return CurrentOptions; } +ClangTidyOptions ClangTidyContext::getOptionsForFile(StringRef File) const { + // Merge options on top of getDefaults() as a safeguard against options with + // unset values. + return ClangTidyOptions::getDefaults().mergeWith( + OptionsProvider->getOptions(CurrentFile)); +} + void ClangTidyContext::setCheckProfileData(ProfileData *P) { Profile = P; } GlobList &ClangTidyContext::getChecksFilter() { Index: clang-tidy/ClangTidyOptions.h =================================================================== --- clang-tidy/ClangTidyOptions.h +++ clang-tidy/ClangTidyOptions.h @@ -83,6 +83,14 @@ /// \brief Key-value mapping used to store check-specific options. OptionMap CheckOptions; + + typedef std::vector ArgList; + + /// \brief Add extra compilation arguments to the end of the list. + llvm::Optional ExtraArgs; + + /// \brief Add extra compilation arguments to the start of the list. + llvm::Optional ExtraArgsBefore; }; /// \brief Abstract interface for retrieving various ClangTidy options. Index: clang-tidy/ClangTidyOptions.cpp =================================================================== --- clang-tidy/ClangTidyOptions.cpp +++ clang-tidy/ClangTidyOptions.cpp @@ -27,6 +27,7 @@ LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter) LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter::LineRange) LLVM_YAML_IS_SEQUENCE_VECTOR(ClangTidyOptions::StringPair) +LLVM_YAML_IS_SEQUENCE_VECTOR(std::string) namespace llvm { namespace yaml { @@ -88,6 +89,8 @@ IO.mapOptional("AnalyzeTemporaryDtors", Options.AnalyzeTemporaryDtors); IO.mapOptional("User", Options.User); IO.mapOptional("CheckOptions", NOpts->Options); + IO.mapOptional("ExtraArgs", Options.ExtraArgs); + IO.mapOptional("ExtraArgsBefore", Options.ExtraArgsBefore); } }; @@ -129,6 +132,10 @@ Result.AnalyzeTemporaryDtors = Other.AnalyzeTemporaryDtors; if (Other.User) Result.User = Other.User; + if (Other.ExtraArgs) + Result.ExtraArgs = Other.ExtraArgs; + if (Other.ExtraArgsBefore) + Result.ExtraArgsBefore = Other.ExtraArgsBefore; for (const auto &KeyValue : Other.CheckOptions) Result.CheckOptions[KeyValue.first] = KeyValue.second; Index: test/clang-tidy/custom-diagnostics.cpp =================================================================== --- /dev/null +++ test/clang-tidy/custom-diagnostics.cpp @@ -0,0 +1,12 @@ +// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-shadow,clang-diagnostic-float-conversion' %s -- | count 0 +// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-shadow,clang-diagnostic-float-conversion' \ +// RUN: -config='{ExtraArgs: ["-Wshadow","-Wno-unused-variable"], ExtraArgsBefore: ["-Wno-shadow","-Wfloat-conversion","-Wunused-variable"]}' %s -- \ +// RUN: | FileCheck -implicit-check-not='{{warning:|error:}}' %s + +void f(float x) { + int a; + { int a; } + // CHECK: :[[@LINE-1]]:9: warning: declaration shadows a local variable [clang-diagnostic-shadow] + int b = x; + // CHECK: :[[@LINE-1]]:11: warning: implicit conversion turns floating-point number into integer: 'float' to 'int' [clang-diagnostic-float-conversion] +}