[clang] 06be346 - [Clang] avoid relying on StringMap iteration order when roundtripping -analyzer-config

Jan Svoboda via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 1 13:54:15 PST 2023


Author: Erik Desjardins
Date: 2023-02-01T13:54:09-08:00
New Revision: 06be346311b9341d3d11120a631263de863f937c

URL: https://github.com/llvm/llvm-project/commit/06be346311b9341d3d11120a631263de863f937c
DIFF: https://github.com/llvm/llvm-project/commit/06be346311b9341d3d11120a631263de863f937c.diff

LOG: [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

Added: 
    

Modified: 
    clang/lib/Frontend/CompilerInvocation.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index ed483d22550b5..1911c5d0f7334 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.


        


More information about the cfe-commits mailing list