diff options
author | Erik Desjardins <erikdesjardinspublic@gmail.com> | 2023-02-01 13:46:59 -0800 |
---|---|---|
committer | Jan Svoboda <jan_svoboda@apple.com> | 2023-02-01 13:54:09 -0800 |
commit | 06be346311b9341d3d11120a631263de863f937c (patch) | |
tree | c62b2b546ca9080ac70cc44bf87ef83f046c7724 /clang/lib/Frontend/CompilerInvocation.cpp | |
parent | aa2943502cf2986948af69681d9b833614645cd0 (diff) | |
download | llvm-06be346311b9341d3d11120a631263de863f937c.zip llvm-06be346311b9341d3d11120a631263de863f937c.tar.gz llvm-06be346311b9341d3d11120a631263de863f937c.tar.bz2 |
[Clang] avoid relying on StringMap iteration order when roundtripping -analyzer-config
I am working on another patch that changes StringMap's hash function,
which changes the iteration order here, and breaks some tests,
specifically:
clang/test/Analysis/NSString.m
clang/test/Analysis/shallow-mode.m
with errors like:
generated arguments do not match in round-trip
generated arguments #1 in round-trip: <...> "-analyzer-config" "ipa=inlining" "-analyzer-config" "max-nodes=75000" <...>
generated arguments #2 in round-trip: <...> "-analyzer-config" "max-nodes=75000" "-analyzer-config" "ipa=inlining" <...>
To avoid this, sort the options by key, instead of using the default map
iteration order.
Reviewed By: jansvoboda11, MaskRay
Differential Revision: https://reviews.llvm.org/D142861
Diffstat (limited to 'clang/lib/Frontend/CompilerInvocation.cpp')
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index ed483d2..1911c5d 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -877,14 +877,20 @@ static void GenerateAnalyzerArgs(AnalyzerOptions &Opts, AnalyzerOptions ConfigOpts; parseAnalyzerConfigs(ConfigOpts, nullptr); - for (const auto &C : Opts.Config) { + // Sort options by key to avoid relying on StringMap iteration order. + SmallVector<std::pair<StringRef, StringRef>, 4> SortedConfigOpts; + for (const auto &C : Opts.Config) + SortedConfigOpts.emplace_back(C.getKey(), C.getValue()); + llvm::sort(SortedConfigOpts, llvm::less_first()); + + for (const auto &[Key, Value] : SortedConfigOpts) { // Don't generate anything that came from parseAnalyzerConfigs. It would be // redundant and may not be valid on the command line. - auto Entry = ConfigOpts.Config.find(C.getKey()); - if (Entry != ConfigOpts.Config.end() && Entry->getValue() == C.getValue()) + auto Entry = ConfigOpts.Config.find(Key); + if (Entry != ConfigOpts.Config.end() && Entry->getValue() == Value) continue; - GenerateArg(Args, OPT_analyzer_config, C.getKey() + "=" + C.getValue(), SA); + GenerateArg(Args, OPT_analyzer_config, Key + "=" + Value, SA); } // Nothing to generate for FullCompilerInvocation. |