serge-sans-paille created this revision.
serge-sans-paille added a reviewer: nikic.
Herald added subscribers: steakhal, pmatos, asb, jhenderson, abrachet, ormris, 
martong, phosek, kadircet, arphaman, steven_wu, hiraditya, arichardson, sbc100, 
emaste.
Herald added a reviewer: JDevlieghere.
Herald added a reviewer: alexander-shaposhnikov.
Herald added a reviewer: jhenderson.
Herald added a reviewer: MaskRay.
Herald added a reviewer: NoQ.
Herald added projects: lld-macho, All.
Herald added a reviewer: lld-macho.
serge-sans-paille requested review of this revision.
Herald added subscribers: cfe-commits, llvm-commits, lldb-commits, StephenFan, 
aheejin.
Herald added projects: clang, LLDB, LLVM, clang-tools-extra.

This avoids recomputing string lentgh that is already known at compile
time.

It has a slight impact on preprocessing / compile time, see

https://llvm-compile-time-tracker.com/compare.php?from=3f36d2d579d8b0e8824d9dd99bfa79f456858f88&to=e49640c507ddc6615b5e503144301c8e41f8f434&stat=instructions:u


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D139881

Files:
  clang-tools-extra/clangd/CompileCommands.cpp
  clang/include/clang/Basic/Builtins.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Basic/Builtins.cpp
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Driver/DriverOptions.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
  clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
  clang/lib/StaticAnalyzer/Checkers/DebugContainerModeling.cpp
  clang/lib/StaticAnalyzer/Checkers/DebugIteratorModeling.cpp
  clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
  clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/MIGChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/cert/PutenvWithAutoChecker.cpp
  clang/lib/StaticAnalyzer/Core/CallDescription.cpp
  clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
  clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp
  clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
  clang/unittests/StaticAnalyzer/ConflictingEvalCallsTest.cpp
  clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp
  clang/unittests/StaticAnalyzer/NoStateChangeFuncVisitorTest.cpp
  lld/COFF/DriverUtils.cpp
  lld/ELF/DriverUtils.cpp
  lld/MachO/DriverUtils.cpp
  lld/MinGW/Driver.cpp
  lld/wasm/Driver.cpp
  lldb/tools/driver/Driver.cpp
  lldb/tools/lldb-server/lldb-gdbserver.cpp
  lldb/tools/lldb-vscode/lldb-vscode.cpp
  llvm/include/llvm/ADT/ArrayRef.h
  llvm/include/llvm/Option/OptTable.h
  llvm/include/llvm/Option/Option.h
  llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp
  llvm/lib/Option/OptTable.cpp
  llvm/lib/Option/Option.cpp
  llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
  llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
  llvm/tools/dsymutil/dsymutil.cpp
  llvm/tools/llvm-cvtres/llvm-cvtres.cpp
  llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
  llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
  llvm/tools/llvm-ifs/llvm-ifs.cpp
  llvm/tools/llvm-lipo/llvm-lipo.cpp
  llvm/tools/llvm-ml/llvm-ml.cpp
  llvm/tools/llvm-mt/llvm-mt.cpp
  llvm/tools/llvm-nm/llvm-nm.cpp
  llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
  llvm/tools/llvm-objdump/llvm-objdump.cpp
  llvm/tools/llvm-rc/llvm-rc.cpp
  llvm/tools/llvm-readobj/llvm-readobj.cpp
  llvm/tools/llvm-size/llvm-size.cpp
  llvm/tools/llvm-strings/llvm-strings.cpp
  llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
  llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp
  llvm/unittests/Option/OptionParsingTest.cpp
  llvm/utils/TableGen/OptParserEmitter.cpp

Index: llvm/utils/TableGen/OptParserEmitter.cpp
===================================================================
--- llvm/utils/TableGen/OptParserEmitter.cpp
+++ llvm/utils/TableGen/OptParserEmitter.cpp
@@ -251,8 +251,8 @@
     // Prefix values.
     OS << ", {";
     for (const auto &PrefixKey : Prefix.first)
-      OS << "\"" << PrefixKey << "\" COMMA ";
-    OS << "nullptr})\n";
+      OS << "llvm::StringLiteral(\"" << PrefixKey << "\") COMMA ";
+    OS << "llvm::StringLiteral(\"\")})\n";
   }
   OS << "#undef COMMA\n";
   OS << "#endif // PREFIX\n\n";
Index: llvm/unittests/Option/OptionParsingTest.cpp
===================================================================
--- llvm/unittests/Option/OptionParsingTest.cpp
+++ llvm/unittests/Option/OptionParsingTest.cpp
@@ -25,7 +25,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral NAME[] = VALUE;
 #include "Opts.inc"
 #undef PREFIX
 
Index: llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp
===================================================================
--- llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp
+++ llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp
@@ -35,7 +35,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral NAME[] = VALUE;
 #include "Opts.inc"
 #undef PREFIX
 
Index: llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
===================================================================
--- llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
+++ llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
@@ -56,7 +56,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral NAME[] = VALUE;
 #include "Opts.inc"
 #undef PREFIX
 
Index: llvm/tools/llvm-strings/llvm-strings.cpp
===================================================================
--- llvm/tools/llvm-strings/llvm-strings.cpp
+++ llvm/tools/llvm-strings/llvm-strings.cpp
@@ -39,7 +39,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral NAME[] = VALUE;
 #include "Opts.inc"
 #undef PREFIX
 
Index: llvm/tools/llvm-size/llvm-size.cpp
===================================================================
--- llvm/tools/llvm-size/llvm-size.cpp
+++ llvm/tools/llvm-size/llvm-size.cpp
@@ -47,7 +47,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral NAME[] = VALUE;
 #include "Opts.inc"
 #undef PREFIX
 
Index: llvm/tools/llvm-readobj/llvm-readobj.cpp
===================================================================
--- llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -62,7 +62,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral NAME[] = VALUE;
 #include "Opts.inc"
 #undef PREFIX
 
Index: llvm/tools/llvm-rc/llvm-rc.cpp
===================================================================
--- llvm/tools/llvm-rc/llvm-rc.cpp
+++ llvm/tools/llvm-rc/llvm-rc.cpp
@@ -55,7 +55,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral NAME[] = VALUE;
 #include "Opts.inc"
 #undef PREFIX
 
@@ -85,7 +85,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const WINDRES_##NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral WINDRES_##NAME[] = VALUE;
 #include "WindresOpts.inc"
 #undef PREFIX
 
Index: llvm/tools/llvm-objdump/llvm-objdump.cpp
===================================================================
--- llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -120,7 +120,8 @@
 
 // ObjdumpOptID is in ObjdumpOptID.h
 
-#define PREFIX(NAME, VALUE) const char *const OBJDUMP_##NAME[] = VALUE;
+#define PREFIX(NAME, VALUE)                                                    \
+  constexpr llvm::StringLiteral OBJDUMP_##NAME[] = VALUE;
 #include "ObjdumpOpts.inc"
 #undef PREFIX
 
@@ -153,7 +154,8 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const OTOOL_##NAME[] = VALUE;
+#define PREFIX(NAME, VALUE)                                                    \
+  constexpr llvm::StringLiteral OTOOL_##NAME[] = VALUE;
 #include "OtoolOpts.inc"
 #undef PREFIX
 
Index: llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
===================================================================
--- llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -36,7 +36,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const OBJCOPY_##NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral OBJCOPY_##NAME[] = VALUE;
 #include "ObjcopyOpts.inc"
 #undef PREFIX
 
@@ -76,7 +76,7 @@
 };
 
 #define PREFIX(NAME, VALUE)                                                    \
-  const char *const INSTALL_NAME_TOOL_##NAME[] = VALUE;
+  constexpr StringLiteral INSTALL_NAME_TOOL_##NAME[] = VALUE;
 #include "InstallNameToolOpts.inc"
 #undef PREFIX
 
@@ -113,7 +113,8 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const BITCODE_STRIP_##NAME[] = VALUE;
+#define PREFIX(NAME, VALUE)                                                    \
+  constexpr StringLiteral BITCODE_STRIP_##NAME[] = VALUE;
 #include "BitcodeStripOpts.inc"
 #undef PREFIX
 
@@ -150,7 +151,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const STRIP_##NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral STRIP_##NAME[] = VALUE;
 #include "StripOpts.inc"
 #undef PREFIX
 
Index: llvm/tools/llvm-nm/llvm-nm.cpp
===================================================================
--- llvm/tools/llvm-nm/llvm-nm.cpp
+++ llvm/tools/llvm-nm/llvm-nm.cpp
@@ -64,7 +64,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral NAME[] = VALUE;
 #include "Opts.inc"
 #undef PREFIX
 
Index: llvm/tools/llvm-mt/llvm-mt.cpp
===================================================================
--- llvm/tools/llvm-mt/llvm-mt.cpp
+++ llvm/tools/llvm-mt/llvm-mt.cpp
@@ -41,7 +41,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral NAME[] = VALUE;
 #include "Opts.inc"
 #undef PREFIX
 
Index: llvm/tools/llvm-ml/llvm-ml.cpp
===================================================================
--- llvm/tools/llvm-ml/llvm-ml.cpp
+++ llvm/tools/llvm-ml/llvm-ml.cpp
@@ -60,7 +60,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral NAME[] = VALUE;
 #include "Opts.inc"
 #undef PREFIX
 
Index: llvm/tools/llvm-lipo/llvm-lipo.cpp
===================================================================
--- llvm/tools/llvm-lipo/llvm-lipo.cpp
+++ llvm/tools/llvm-lipo/llvm-lipo.cpp
@@ -74,8 +74,8 @@
 };
 
 // LipoInfoTable below references LIPO_##PREFIX. OptionGroup has prefix nullptr.
-constexpr const char *const *LIPO_nullptr = nullptr;
-#define PREFIX(NAME, VALUE) const char *const LIPO_##NAME[] = VALUE;
+constexpr std::nullptr_t LIPO_nullptr = nullptr;
+#define PREFIX(NAME, VALUE) constexpr llvm::StringLiteral LIPO_##NAME[] = VALUE;
 #include "LipoOpts.inc"
 #undef PREFIX
 
Index: llvm/tools/llvm-ifs/llvm-ifs.cpp
===================================================================
--- llvm/tools/llvm-ifs/llvm-ifs.cpp
+++ llvm/tools/llvm-ifs/llvm-ifs.cpp
@@ -60,7 +60,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral NAME[] = VALUE;
 #include "Opts.inc"
 #undef PREFIX
 
Index: llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
===================================================================
--- llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
+++ llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
@@ -40,7 +40,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr llvm::StringLiteral NAME[] = VALUE;
 #include "Options.inc"
 #undef PREFIX
 
Index: llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
===================================================================
--- llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
+++ llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
@@ -32,7 +32,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr llvm::StringLiteral NAME[] = VALUE;
 #include "Opts.inc"
 #undef PREFIX
 
Index: llvm/tools/llvm-cvtres/llvm-cvtres.cpp
===================================================================
--- llvm/tools/llvm-cvtres/llvm-cvtres.cpp
+++ llvm/tools/llvm-cvtres/llvm-cvtres.cpp
@@ -44,7 +44,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral NAME[] = VALUE;
 #include "Opts.inc"
 #undef PREFIX
 
Index: llvm/tools/dsymutil/dsymutil.cpp
===================================================================
--- llvm/tools/dsymutil/dsymutil.cpp
+++ llvm/tools/dsymutil/dsymutil.cpp
@@ -63,7 +63,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr llvm::StringLiteral NAME[] = VALUE;
 #include "Options.inc"
 #undef PREFIX
 
Index: llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
===================================================================
--- llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
+++ llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
@@ -41,7 +41,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral NAME[] = VALUE;
 #include "Options.inc"
 #undef PREFIX
 
Index: llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
===================================================================
--- llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
+++ llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
@@ -37,7 +37,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral NAME[] = VALUE;
 #include "Options.inc"
 #undef PREFIX
 
Index: llvm/lib/Option/Option.cpp
===================================================================
--- llvm/lib/Option/Option.cpp
+++ llvm/lib/Option/Option.cpp
@@ -58,11 +58,10 @@
 #undef P
   }
 
-  if (Info->Prefixes) {
+  if (!Info->Prefixes.empty()) {
     O << " Prefixes:[";
-    for (const char *const *Pre = Info->Prefixes; *Pre != nullptr; ++Pre) {
-      O << '"' << *Pre << (*(Pre + 1) == nullptr ? "\"" : "\", ");
-    }
+    for (size_t I = 0, N = Info->Prefixes.size(); I != N; ++I)
+      O << '"' << Info->Prefixes[I] << (I == N - 1 ? "\"" : "\", ");
     O << ']';
   }
 
Index: llvm/lib/Option/OptTable.cpp
===================================================================
--- llvm/lib/Option/OptTable.cpp
+++ llvm/lib/Option/OptTable.cpp
@@ -62,12 +62,10 @@
   if (int N = StrCmpOptionName(A.Name, B.Name))
     return N < 0;
 
-  for (const char * const *APre = A.Prefixes,
-                  * const *BPre = B.Prefixes;
-                          *APre != nullptr && *BPre != nullptr; ++APre, ++BPre){
-    if (int N = StrCmpOptionName(*APre, *BPre))
+  for (size_t I = 0, K = std::min(A.Prefixes.size(), B.Prefixes.size()); I != K;
+       ++I)
+    if (int N = StrCmpOptionName(A.Prefixes[I], B.Prefixes[I]))
       return N < 0;
-  }
 
   // Names are the same, check that classes are in order; exactly one
   // should be joined, and it should succeed the other.
@@ -131,11 +129,8 @@
   // Build prefixes.
   for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions() + 1;
                 i != e; ++i) {
-    if (const char *const *P = getInfo(i).Prefixes) {
-      for (; *P != nullptr; ++P) {
-        PrefixesUnion.insert(*P);
-      }
-    }
+    const auto &P = getInfo(i).Prefixes;
+    PrefixesUnion.insert(P.begin(), P.end());
   }
 
   // Build prefix chars.
@@ -171,8 +166,7 @@
 /// \returns Matched size. 0 means no match.
 static unsigned matchOption(const OptTable::Info *I, StringRef Str,
                             bool IgnoreCase) {
-  for (const char * const *Pre = I->Prefixes; *Pre != nullptr; ++Pre) {
-    StringRef Prefix(*Pre);
+  for (auto Prefix : I->Prefixes) {
     if (Str.startswith(Prefix)) {
       StringRef Rest = Str.substr(Prefix.size());
       bool Matched = IgnoreCase ? Rest.startswith_insensitive(I->Name)
@@ -186,13 +180,10 @@
 
 // Returns true if one of the Prefixes + In.Names matches Option
 static bool optionMatches(const OptTable::Info &In, StringRef Option) {
-  if (In.Prefixes) {
-    StringRef InName(In.Name);
-    for (size_t I = 0; In.Prefixes[I]; I++)
-      if (Option.endswith(InName))
-        if (Option.slice(0, Option.size() - InName.size()) == In.Prefixes[I])
-          return true;
-  }
+  for (auto Prefix : In.Prefixes)
+    if (Option.endswith(In.Name))
+      if (Option.slice(0, Option.size() - In.Name.size()) == Prefix)
+        return true;
   return false;
 }
 
@@ -224,13 +215,13 @@
   std::vector<std::string> Ret;
   for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; I++) {
     const Info &In = OptionInfos[I];
-    if (!In.Prefixes || (!In.HelpText && !In.GroupID))
+    if (In.Prefixes.empty() || (!In.HelpText && !In.GroupID))
       continue;
     if (In.Flags & DisableFlags)
       continue;
 
-    for (int I = 0; In.Prefixes[I]; I++) {
-      std::string S = std::string(In.Prefixes[I]) + std::string(In.Name) + "\t";
+    for (auto Prefix : In.Prefixes) {
+      std::string S = (Prefix + In.Name + "\t").str();
       if (In.HelpText)
         S += In.HelpText;
       if (StringRef(S).startswith(Cur) && S != std::string(Cur) + "\t")
@@ -268,7 +259,7 @@
 
     // * Ignore positional argument option candidates (which do not
     //   have prefixes).
-    if (!CandidateInfo.Prefixes)
+    if (CandidateInfo.Prefixes.empty())
       continue;
 
     // Now check if the candidate ends with a character commonly used when
@@ -288,8 +279,7 @@
     // Consider each possible prefix for each candidate to find the most
     // appropriate one. For example, if a user asks for "--helm", suggest
     // "--help" over "-help".
-    for (int P = 0;
-         const char *const CandidatePrefix = CandidateInfo.Prefixes[P]; P++) {
+    for (auto CandidatePrefix : CandidateInfo.Prefixes) {
       std::string Candidate = (CandidatePrefix + CandidateName).str();
       StringRef CandidateRef = Candidate;
       unsigned Distance =
Index: llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp
===================================================================
--- llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp
+++ llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp
@@ -18,7 +18,7 @@
 #define DEBUG_TYPE "jitlink"
 
 // Create prefix string literals used in Options.td
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral NAME[] = VALUE;
 #include "COFFOptions.inc"
 #undef PREFIX
 
Index: llvm/include/llvm/Option/Option.h
===================================================================
--- llvm/include/llvm/Option/Option.h
+++ llvm/include/llvm/Option/Option.h
@@ -124,8 +124,7 @@
 
   /// Get the default prefix for this option.
   StringRef getPrefix() const {
-    const char *Prefix = *Info->Prefixes;
-    return Prefix ? Prefix : StringRef();
+    return Info->Prefixes.empty() ? StringRef() : Info->Prefixes[0];
   }
 
   /// Get the name of this option with the default prefix.
Index: llvm/include/llvm/Option/OptTable.h
===================================================================
--- llvm/include/llvm/Option/OptTable.h
+++ llvm/include/llvm/Option/OptTable.h
@@ -43,7 +43,7 @@
   struct Info {
     /// A null terminated array of prefix strings to apply to name while
     /// matching.
-    const char *const *Prefixes;
+    ArrayRef<StringRef> Prefixes;
     StringRef Name;
     const char *HelpText;
     const char *MetaVar;
@@ -55,6 +55,35 @@
     unsigned short AliasID;
     const char *AliasArgs;
     const char *Values;
+
+    constexpr Info(std::nullptr_t, StringRef Name, const char *HelpText,
+                   const char *MetaVar, unsigned ID, unsigned char Kind,
+                   unsigned char Param, unsigned int Flags,
+                   unsigned short GroupID, unsigned short AliasID,
+                   const char *AliasArgs, const char *Values)
+        : Prefixes(), Name(Name), HelpText(HelpText), MetaVar(MetaVar), ID(ID),
+          Kind(Kind), Param(Param), Flags(Flags), GroupID(GroupID),
+          AliasID(AliasID), AliasArgs(AliasArgs), Values(Values) {}
+
+    constexpr Info(StringLiteral const (&Prefixes)[1], StringRef Name,
+                   const char *HelpText, const char *MetaVar, unsigned ID,
+                   unsigned char Kind, unsigned char Param, unsigned int Flags,
+                   unsigned short GroupID, unsigned short AliasID,
+                   const char *AliasArgs, const char *Values)
+        : Prefixes(), Name(Name), HelpText(HelpText), MetaVar(MetaVar), ID(ID),
+          Kind(Kind), Param(Param), Flags(Flags), GroupID(GroupID),
+          AliasID(AliasID), AliasArgs(AliasArgs), Values(Values) {}
+
+    template <size_t N>
+    constexpr Info(StringLiteral const (&Prefixes)[N], StringRef Name,
+                   const char *HelpText, const char *MetaVar, unsigned ID,
+                   unsigned char Kind, unsigned char Param, unsigned int Flags,
+                   unsigned short GroupID, unsigned short AliasID,
+                   const char *AliasArgs, const char *Values)
+        : Prefixes(&Prefixes[0], N - 1), Name(Name), HelpText(HelpText),
+          MetaVar(MetaVar), ID(ID), Kind(Kind), Param(Param), Flags(Flags),
+          GroupID(GroupID), AliasID(AliasID), AliasArgs(AliasArgs),
+          Values(Values) {}
   };
 
 private:
Index: llvm/include/llvm/ADT/ArrayRef.h
===================================================================
--- llvm/include/llvm/ADT/ArrayRef.h
+++ llvm/include/llvm/ADT/ArrayRef.h
@@ -74,12 +74,12 @@
       : Data(&OneElt), Length(1) {}
 
     /// Construct an ArrayRef from a pointer and length.
-    /*implicit*/ ArrayRef(const T *data, size_t length)
-      : Data(data), Length(length) {}
+    constexpr /*implicit*/ ArrayRef(const T *data, size_t length)
+        : Data(data), Length(length) {}
 
     /// Construct an ArrayRef from a range.
-    ArrayRef(const T *begin, const T *end)
-      : Data(begin), Length(end - begin) {}
+    constexpr ArrayRef(const T *begin, const T *end)
+        : Data(begin), Length(end - begin) {}
 
     /// Construct an ArrayRef from a SmallVector. This is templated in order to
     /// avoid instantiating SmallVectorTemplateCommon<T> whenever we
Index: lldb/tools/lldb-vscode/lldb-vscode.cpp
===================================================================
--- lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -79,7 +79,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr llvm::StringLiteral NAME[] = VALUE;
 #include "Options.inc"
 #undef PREFIX
 
Index: lldb/tools/lldb-server/lldb-gdbserver.cpp
===================================================================
--- lldb/tools/lldb-server/lldb-gdbserver.cpp
+++ lldb/tools/lldb-server/lldb-gdbserver.cpp
@@ -278,7 +278,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr llvm::StringLiteral NAME[] = VALUE;
 #include "LLGSOptions.inc"
 #undef PREFIX
 
Index: lldb/tools/driver/Driver.cpp
===================================================================
--- lldb/tools/driver/Driver.cpp
+++ lldb/tools/driver/Driver.cpp
@@ -59,7 +59,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr llvm::StringLiteral NAME[] = VALUE;
 #include "Options.inc"
 #undef PREFIX
 
Index: lld/wasm/Driver.cpp
===================================================================
--- lld/wasm/Driver.cpp
+++ lld/wasm/Driver.cpp
@@ -101,7 +101,7 @@
 }
 
 // Create prefix string literals used in Options.td
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr llvm::StringLiteral NAME[] = VALUE;
 #include "Options.inc"
 #undef PREFIX
 
Index: lld/MinGW/Driver.cpp
===================================================================
--- lld/MinGW/Driver.cpp
+++ lld/MinGW/Driver.cpp
@@ -61,7 +61,7 @@
 };
 
 // Create prefix string literals used in Options.td
-#define PREFIX(NAME, VALUE) static const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) static constexpr llvm::StringLiteral NAME[] = VALUE;
 #include "Options.inc"
 #undef PREFIX
 
Index: lld/MachO/DriverUtils.cpp
===================================================================
--- lld/MachO/DriverUtils.cpp
+++ lld/MachO/DriverUtils.cpp
@@ -35,7 +35,7 @@
 using namespace lld::macho;
 
 // Create prefix string literals used in Options.td
-#define PREFIX(NAME, VALUE) const char *NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral NAME[] = VALUE;
 #include "Options.inc"
 #undef PREFIX
 
Index: lld/ELF/DriverUtils.cpp
===================================================================
--- lld/ELF/DriverUtils.cpp
+++ lld/ELF/DriverUtils.cpp
@@ -34,7 +34,7 @@
 // Create OptTable
 
 // Create prefix string literals used in Options.td
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral NAME[] = VALUE;
 #include "Options.inc"
 #undef PREFIX
 
Index: lld/COFF/DriverUtils.cpp
===================================================================
--- lld/COFF/DriverUtils.cpp
+++ lld/COFF/DriverUtils.cpp
@@ -772,7 +772,7 @@
 // Create OptTable
 
 // Create prefix string literals used in Options.td
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr llvm::StringLiteral NAME[] = VALUE;
 #include "Options.inc"
 #undef PREFIX
 
Index: clang/unittests/StaticAnalyzer/NoStateChangeFuncVisitorTest.cpp
===================================================================
--- clang/unittests/StaticAnalyzer/NoStateChangeFuncVisitorTest.cpp
+++ clang/unittests/StaticAnalyzer/NoStateChangeFuncVisitorTest.cpp
@@ -86,17 +86,17 @@
 
 public:
   void checkPreCall(const CallEvent &Call, CheckerContext &C) const {
-    if (CallDescription{"preventError", 0}.matches(Call)) {
+    if (CallDescription{{"preventError"}, 0}.matches(Call)) {
       C.addTransition(C.getState()->set<ErrorPrevented>(true));
       return;
     }
 
-    if (CallDescription{"allowError", 0}.matches(Call)) {
+    if (CallDescription{{"allowError"}, 0}.matches(Call)) {
       C.addTransition(C.getState()->set<ErrorPrevented>(false));
       return;
     }
 
-    if (CallDescription{"error", 0}.matches(Call)) {
+    if (CallDescription{{"error"}, 0}.matches(Call)) {
       if (C.getState()->get<ErrorPrevented>())
         return;
       const ExplodedNode *N = C.generateErrorNode();
Index: clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp
===================================================================
--- clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp
+++ clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp
@@ -30,9 +30,9 @@
   using HandlerFn = bool (Self::*)(const CallEvent &Call,
                                    CheckerContext &) const;
   CallDescriptionMap<HandlerFn> Callbacks = {
-      {{"reachedWithContradiction", 0}, &Self::reachedWithContradiction},
-      {{"reachedWithNoContradiction", 0}, &Self::reachedWithNoContradiction},
-      {{"reportIfCanBeTrue", 1}, &Self::reportIfCanBeTrue},
+      {{{"reachedWithContradiction"}, 0}, &Self::reachedWithContradiction},
+      {{{"reachedWithNoContradiction"}, 0}, &Self::reachedWithNoContradiction},
+      {{{"reportIfCanBeTrue"}, 1}, &Self::reportIfCanBeTrue},
   };
 
   bool report(CheckerContext &C, ProgramStateRef State,
Index: clang/unittests/StaticAnalyzer/ConflictingEvalCallsTest.cpp
===================================================================
--- clang/unittests/StaticAnalyzer/ConflictingEvalCallsTest.cpp
+++ clang/unittests/StaticAnalyzer/ConflictingEvalCallsTest.cpp
@@ -18,7 +18,7 @@
 
 namespace {
 class EvalCallBase : public Checker<eval::Call> {
-  const CallDescription Foo = {"foo", 0};
+  const CallDescription Foo = {{"foo"}, 0};
 
 public:
   bool evalCall(const CallEvent &Call, CheckerContext &C) const {
Index: clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
===================================================================
--- clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
+++ clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
@@ -135,8 +135,8 @@
 TEST(CallDescription, SimpleNameMatching) {
   EXPECT_TRUE(tooling::runToolOnCode(
       std::unique_ptr<FrontendAction>(new CallDescriptionAction<>({
-          {{"bar"}, false}, // false: there's no call to 'bar' in this code.
-          {{"foo"}, true},  // true: there's a call to 'foo' in this code.
+          {{{"bar"}}, false}, // false: there's no call to 'bar' in this code.
+          {{{"foo"}}, true},  // true: there's a call to 'foo' in this code.
       })),
       "void foo(); void bar() { foo(); }"));
 }
@@ -144,8 +144,8 @@
 TEST(CallDescription, RequiredArguments) {
   EXPECT_TRUE(tooling::runToolOnCode(
       std::unique_ptr<FrontendAction>(new CallDescriptionAction<>({
-          {{"foo", 1}, true},
-          {{"foo", 2}, false},
+          {{{"foo"}, 1}, true},
+          {{{"foo"}, 2}, false},
       })),
       "void foo(int); void foo(int, int); void bar() { foo(1); }"));
 }
@@ -153,8 +153,8 @@
 TEST(CallDescription, LackOfRequiredArguments) {
   EXPECT_TRUE(tooling::runToolOnCode(
       std::unique_ptr<FrontendAction>(new CallDescriptionAction<>({
-          {{"foo", std::nullopt}, true},
-          {{"foo", 2}, false},
+          {{{"foo"}, std::nullopt}, true},
+          {{{"foo"}, 2}, false},
       })),
       "void foo(int); void foo(int, int); void bar() { foo(1); }"));
 }
@@ -479,7 +479,7 @@
       std::unique_ptr<FrontendAction>(new CallDescriptionAction<>({
           {{{"foo", "bar"}}, false},
           {{{"bar", "foo"}}, false},
-          {{"foo"}, true},
+          {{{"foo"}}, true},
       })),
       "void foo(); struct bar { void foo(); }; void test() { foo(); }"));
 }
@@ -488,7 +488,8 @@
   // Test CDF_MaybeBuiltin - a flag that allows matching weird builtins.
   EXPECT_TRUE(tooling::runToolOnCode(
       std::unique_ptr<FrontendAction>(new CallDescriptionAction<>(
-          {{{"memset", 3}, false}, {{CDF_MaybeBuiltin, "memset", 3}, true}})),
+          {{{{"memset"}, 3}, false},
+           {{CDF_MaybeBuiltin, {"memset"}, 3}, true}})),
       "void foo() {"
       "  int x;"
       "  __builtin___memset_chk(&x, 0, sizeof(x),"
@@ -499,8 +500,8 @@
     SCOPED_TRACE("multiple similar builtins");
     EXPECT_TRUE(tooling::runToolOnCode(
         std::unique_ptr<FrontendAction>(new CallDescriptionAction<>(
-            {{{CDF_MaybeBuiltin, "memcpy", 3}, false},
-             {{CDF_MaybeBuiltin, "wmemcpy", 3}, true}})),
+            {{{CDF_MaybeBuiltin, {"memcpy"}, 3}, false},
+             {{CDF_MaybeBuiltin, {"wmemcpy"}, 3}, true}})),
         R"(void foo(wchar_t *x, wchar_t *y) {
             __builtin_wmemcpy(x, y, sizeof(wchar_t));
           })"));
@@ -509,8 +510,8 @@
     SCOPED_TRACE("multiple similar builtins reversed order");
     EXPECT_TRUE(tooling::runToolOnCode(
         std::unique_ptr<FrontendAction>(new CallDescriptionAction<>(
-            {{{CDF_MaybeBuiltin, "wmemcpy", 3}, true},
-             {{CDF_MaybeBuiltin, "memcpy", 3}, false}})),
+            {{{CDF_MaybeBuiltin, {"wmemcpy"}, 3}, true},
+             {{CDF_MaybeBuiltin, {"memcpy"}, 3}, false}})),
         R"(void foo(wchar_t *x, wchar_t *y) {
             __builtin_wmemcpy(x, y, sizeof(wchar_t));
           })"));
@@ -518,8 +519,8 @@
   {
     SCOPED_TRACE("lookbehind and lookahead mismatches");
     EXPECT_TRUE(tooling::runToolOnCode(
-        std::unique_ptr<FrontendAction>(
-            new CallDescriptionAction<>({{{CDF_MaybeBuiltin, "func"}, false}})),
+        std::unique_ptr<FrontendAction>(new CallDescriptionAction<>(
+            {{{CDF_MaybeBuiltin, {"func"}}, false}})),
         R"(
           void funcXXX();
           void XXXfunc();
@@ -533,8 +534,8 @@
   {
     SCOPED_TRACE("lookbehind and lookahead matches");
     EXPECT_TRUE(tooling::runToolOnCode(
-        std::unique_ptr<FrontendAction>(
-            new CallDescriptionAction<>({{{CDF_MaybeBuiltin, "func"}, true}})),
+        std::unique_ptr<FrontendAction>(new CallDescriptionAction<>(
+            {{{CDF_MaybeBuiltin, {"func"}}, true}})),
         R"(
           void func();
           void func_XXX();
@@ -561,7 +562,7 @@
 
 class CallDescChecker
     : public Checker<check::PreCall, check::PreStmt<CallExpr>> {
-  CallDescriptionSet Set = {{"bar", 0}};
+  CallDescriptionSet Set = {{{"bar"}, 0}};
 
 public:
   void checkPreCall(const CallEvent &Call, CheckerContext &C) const {
Index: clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp
===================================================================
--- clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp
+++ clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp
@@ -33,11 +33,11 @@
                                        const CallEvent &, CheckerContext &)>;
 
   CallDescriptionMap<HandlerFn> Handlers = {
-      {{"setInteresting", 1}, &InterestingnessTestChecker::handleInteresting},
-      {{"setNotInteresting", 1},
+      {{{"setInteresting"}, 1}, &InterestingnessTestChecker::handleInteresting},
+      {{{"setNotInteresting"}, 1},
        &InterestingnessTestChecker::handleNotInteresting},
-      {{"check", 1}, &InterestingnessTestChecker::handleCheck},
-      {{"bug", 1}, &InterestingnessTestChecker::handleBug},
+      {{{"check"}, 1}, &InterestingnessTestChecker::handleCheck},
+      {{{"bug"}, 1}, &InterestingnessTestChecker::handleBug},
   };
 
   void handleInteresting(const CallEvent &Call, CheckerContext &C) const;
Index: clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
===================================================================
--- clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -121,7 +121,7 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) constexpr StringLiteral NAME[] = VALUE;
 #include "LinkerWrapperOpts.inc"
 #undef PREFIX
 
Index: clang/lib/StaticAnalyzer/Core/CallDescription.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/CallDescription.cpp
+++ clang/lib/StaticAnalyzer/Core/CallDescription.cpp
@@ -36,7 +36,7 @@
 }
 
 ento::CallDescription::CallDescription(CallDescriptionFlags Flags,
-                                       ArrayRef<const char *> QualifiedName,
+                                       ArrayRef<StringRef> QualifiedName,
                                        MaybeCount RequiredArgs /*= None*/,
                                        MaybeCount RequiredParams /*= None*/)
     : RequiredArgs(RequiredArgs),
@@ -44,11 +44,12 @@
       Flags(Flags) {
   assert(!QualifiedName.empty());
   this->QualifiedName.reserve(QualifiedName.size());
-  llvm::copy(QualifiedName, std::back_inserter(this->QualifiedName));
+  llvm::transform(QualifiedName, std::back_inserter(this->QualifiedName),
+                  [](StringRef From) { return From.str(); });
 }
 
 /// Construct a CallDescription with default flags.
-ento::CallDescription::CallDescription(ArrayRef<const char *> QualifiedName,
+ento::CallDescription::CallDescription(ArrayRef<StringRef> QualifiedName,
                                        MaybeCount RequiredArgs /*= None*/,
                                        MaybeCount RequiredParams /*= None*/)
     : CallDescription(CDF_None, QualifiedName, RequiredArgs, RequiredParams) {}
Index: clang/lib/StaticAnalyzer/Checkers/cert/PutenvWithAutoChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/cert/PutenvWithAutoChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/cert/PutenvWithAutoChecker.cpp
@@ -30,7 +30,7 @@
 private:
   BugType BT{this, "'putenv' function should not be called with auto variables",
              categories::SecurityError};
-  const CallDescription Putenv{"putenv", 1};
+  const CallDescription Putenv{{"putenv"}, 1};
 
 public:
   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
Index: clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp
@@ -39,11 +39,11 @@
 
   // SEI CERT ENV31-C
   const CallDescriptionMap<HandlerFn> EnvpInvalidatingFunctions = {
-      {{"setenv", 3}, &InvalidPtrChecker::EnvpInvalidatingCall},
-      {{"unsetenv", 1}, &InvalidPtrChecker::EnvpInvalidatingCall},
-      {{"putenv", 1}, &InvalidPtrChecker::EnvpInvalidatingCall},
-      {{"_putenv_s", 2}, &InvalidPtrChecker::EnvpInvalidatingCall},
-      {{"_wputenv_s", 2}, &InvalidPtrChecker::EnvpInvalidatingCall},
+      {{{"setenv"}, 3}, &InvalidPtrChecker::EnvpInvalidatingCall},
+      {{{"unsetenv"}, 1}, &InvalidPtrChecker::EnvpInvalidatingCall},
+      {{{"putenv"}, 1}, &InvalidPtrChecker::EnvpInvalidatingCall},
+      {{{"_putenv_s"}, 2}, &InvalidPtrChecker::EnvpInvalidatingCall},
+      {{{"_wputenv_s"}, 2}, &InvalidPtrChecker::EnvpInvalidatingCall},
   };
 
   void postPreviousReturnInvalidatingCall(const CallEvent &Call,
@@ -51,13 +51,15 @@
 
   // SEI CERT ENV34-C
   const CallDescriptionMap<HandlerFn> PreviousCallInvalidatingFunctions = {
-      {{"getenv", 1}, &InvalidPtrChecker::postPreviousReturnInvalidatingCall},
-      {{"setlocale", 2},
+      {{{"getenv"}, 1}, &InvalidPtrChecker::postPreviousReturnInvalidatingCall},
+      {{{"setlocale"}, 2},
        &InvalidPtrChecker::postPreviousReturnInvalidatingCall},
-      {{"strerror", 1}, &InvalidPtrChecker::postPreviousReturnInvalidatingCall},
-      {{"localeconv", 0},
+      {{{"strerror"}, 1},
+       &InvalidPtrChecker::postPreviousReturnInvalidatingCall},
+      {{{"localeconv"}, 0},
+       &InvalidPtrChecker::postPreviousReturnInvalidatingCall},
+      {{{"asctime"}, 1},
        &InvalidPtrChecker::postPreviousReturnInvalidatingCall},
-      {{"asctime", 1}, &InvalidPtrChecker::postPreviousReturnInvalidatingCall},
   };
 
 public:
Index: clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
@@ -100,27 +100,26 @@
 };
 
 const SmallVector<ValistChecker::VAListAccepter, 15>
-    ValistChecker::VAListAccepters = {
-        {{"vfprintf", 3}, 2},
-        {{"vfscanf", 3}, 2},
-        {{"vprintf", 2}, 1},
-        {{"vscanf", 2}, 1},
-        {{"vsnprintf", 4}, 3},
-        {{"vsprintf", 3}, 2},
-        {{"vsscanf", 3}, 2},
-        {{"vfwprintf", 3}, 2},
-        {{"vfwscanf", 3}, 2},
-        {{"vwprintf", 2}, 1},
-        {{"vwscanf", 2}, 1},
-        {{"vswprintf", 4}, 3},
-        // vswprintf is the wide version of vsnprintf,
-        // vsprintf has no wide version
-        {{"vswscanf", 3}, 2}};
-
-const CallDescription
-    ValistChecker::VaStart("__builtin_va_start", /*Args=*/2, /*Params=*/1),
-    ValistChecker::VaCopy("__builtin_va_copy", 2),
-    ValistChecker::VaEnd("__builtin_va_end", 1);
+    ValistChecker::VAListAccepters = {{{{"vfprintf"}, 3}, 2},
+                                      {{{"vfscanf"}, 3}, 2},
+                                      {{{"vprintf"}, 2}, 1},
+                                      {{{"vscanf"}, 2}, 1},
+                                      {{{"vsnprintf"}, 4}, 3},
+                                      {{{"vsprintf"}, 3}, 2},
+                                      {{{"vsscanf"}, 3}, 2},
+                                      {{{"vfwprintf"}, 3}, 2},
+                                      {{{"vfwscanf"}, 3}, 2},
+                                      {{{"vwprintf"}, 2}, 1},
+                                      {{{"vwscanf"}, 2}, 1},
+                                      {{{"vswprintf"}, 4}, 3},
+                                      // vswprintf is the wide version of
+                                      // vsnprintf, vsprintf has no wide version
+                                      {{{"vswscanf"}, 3}, 2}};
+
+const CallDescription ValistChecker::VaStart({"__builtin_va_start"}, /*Args=*/2,
+                                             /*Params=*/1),
+    ValistChecker::VaCopy({"__builtin_va_copy"}, 2),
+    ValistChecker::VaEnd({"__builtin_va_end"}, 1);
 } // end anonymous namespace
 
 void ValistChecker::checkPreCall(const CallEvent &Call,
Index: clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -236,42 +236,43 @@
 
 private:
   CallDescriptionMap<FnDescription> FnDescriptions = {
-      {{"fopen"}, {nullptr, &StreamChecker::evalFopen, ArgNone}},
-      {{"freopen", 3},
+      {{{"fopen"}}, {nullptr, &StreamChecker::evalFopen, ArgNone}},
+      {{{"freopen"}, 3},
        {&StreamChecker::preFreopen, &StreamChecker::evalFreopen, 2}},
-      {{"tmpfile"}, {nullptr, &StreamChecker::evalFopen, ArgNone}},
-      {{"fclose", 1},
+      {{{"tmpfile"}}, {nullptr, &StreamChecker::evalFopen, ArgNone}},
+      {{{"fclose"}, 1},
        {&StreamChecker::preDefault, &StreamChecker::evalFclose, 0}},
-      {{"fread", 4},
+      {{{"fread"}, 4},
        {&StreamChecker::preFread,
         std::bind(&StreamChecker::evalFreadFwrite, _1, _2, _3, _4, true), 3}},
-      {{"fwrite", 4},
+      {{{"fwrite"}, 4},
        {&StreamChecker::preFwrite,
         std::bind(&StreamChecker::evalFreadFwrite, _1, _2, _3, _4, false), 3}},
-      {{"fseek", 3}, {&StreamChecker::preFseek, &StreamChecker::evalFseek, 0}},
-      {{"ftell", 1}, {&StreamChecker::preDefault, nullptr, 0}},
-      {{"rewind", 1}, {&StreamChecker::preDefault, nullptr, 0}},
-      {{"fgetpos", 2}, {&StreamChecker::preDefault, nullptr, 0}},
-      {{"fsetpos", 2}, {&StreamChecker::preDefault, nullptr, 0}},
-      {{"clearerr", 1},
+      {{{"fseek"}, 3},
+       {&StreamChecker::preFseek, &StreamChecker::evalFseek, 0}},
+      {{{"ftell"}, 1}, {&StreamChecker::preDefault, nullptr, 0}},
+      {{{"rewind"}, 1}, {&StreamChecker::preDefault, nullptr, 0}},
+      {{{"fgetpos"}, 2}, {&StreamChecker::preDefault, nullptr, 0}},
+      {{{"fsetpos"}, 2}, {&StreamChecker::preDefault, nullptr, 0}},
+      {{{"clearerr"}, 1},
        {&StreamChecker::preDefault, &StreamChecker::evalClearerr, 0}},
-      {{"feof", 1},
+      {{{"feof"}, 1},
        {&StreamChecker::preDefault,
         std::bind(&StreamChecker::evalFeofFerror, _1, _2, _3, _4, ErrorFEof),
         0}},
-      {{"ferror", 1},
+      {{{"ferror"}, 1},
        {&StreamChecker::preDefault,
         std::bind(&StreamChecker::evalFeofFerror, _1, _2, _3, _4, ErrorFError),
         0}},
-      {{"fileno", 1}, {&StreamChecker::preDefault, nullptr, 0}},
+      {{{"fileno"}, 1}, {&StreamChecker::preDefault, nullptr, 0}},
   };
 
   CallDescriptionMap<FnDescription> FnTestDescriptions = {
-      {{"StreamTesterChecker_make_feof_stream", 1},
+      {{{"StreamTesterChecker_make_feof_stream"}, 1},
        {nullptr,
         std::bind(&StreamChecker::evalSetFeofFerror, _1, _2, _3, _4, ErrorFEof),
         0}},
-      {{"StreamTesterChecker_make_ferror_stream", 1},
+      {{{"StreamTesterChecker_make_ferror_stream"}, 1},
        {nullptr,
         std::bind(&StreamChecker::evalSetFeofFerror, _1, _2, _3, _4,
                   ErrorFError),
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -85,10 +85,10 @@
   using SmartPtrMethodHandlerFn =
       void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
   CallDescriptionMap<SmartPtrMethodHandlerFn> SmartPtrMethodHandlers{
-      {{"reset"}, &SmartPtrModeling::handleReset},
-      {{"release"}, &SmartPtrModeling::handleRelease},
-      {{"swap", 1}, &SmartPtrModeling::handleSwapMethod},
-      {{"get"}, &SmartPtrModeling::handleGet}};
+      {{{"reset"}}, &SmartPtrModeling::handleReset},
+      {{{"release"}}, &SmartPtrModeling::handleRelease},
+      {{{"swap"}, 1}, &SmartPtrModeling::handleSwapMethod},
+      {{{"get"}}, &SmartPtrModeling::handleGet}};
   const CallDescription StdSwapCall{{"std", "swap"}, 2};
   const CallDescription StdMakeUniqueCall{{"std", "make_unique"}};
   const CallDescription StdMakeUniqueForOverwriteCall{
Index: clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
@@ -90,7 +90,7 @@
 REGISTER_MAP_WITH_PROGRAMSTATE(StreamMap, SymbolRef, StreamState)
 
 SimpleStreamChecker::SimpleStreamChecker()
-    : OpenFn("fopen"), CloseFn("fclose", 1) {
+    : OpenFn({"fopen"}), CloseFn({"fclose"}, 1) {
   // Initialize the bug types.
   DoubleCloseBugType.reset(
       new BugType(this, "Double fclose", "Unix Stream API Error"));
Index: clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
@@ -87,7 +87,7 @@
                                               CheckerKind CheckKind) const;
   CallDescriptionMap<FnCheck> PThreadCallbacks = {
       // Init.
-      {{"pthread_mutex_init", 2}, &PthreadLockChecker::InitAnyLock},
+      {{{"pthread_mutex_init"}, 2}, &PthreadLockChecker::InitAnyLock},
       // TODO: pthread_rwlock_init(2 arguments).
       // TODO: lck_mtx_init(3 arguments).
       // TODO: lck_mtx_alloc_init(2 arguments) => returns the mutex.
@@ -95,74 +95,74 @@
       // TODO: lck_rw_alloc_init(2 arguments) => returns the mutex.
 
       // Acquire.
-      {{"pthread_mutex_lock", 1}, &PthreadLockChecker::AcquirePthreadLock},
-      {{"pthread_rwlock_rdlock", 1}, &PthreadLockChecker::AcquirePthreadLock},
-      {{"pthread_rwlock_wrlock", 1}, &PthreadLockChecker::AcquirePthreadLock},
-      {{"lck_mtx_lock", 1}, &PthreadLockChecker::AcquireXNULock},
-      {{"lck_rw_lock_exclusive", 1}, &PthreadLockChecker::AcquireXNULock},
-      {{"lck_rw_lock_shared", 1}, &PthreadLockChecker::AcquireXNULock},
+      {{{"pthread_mutex_lock"}, 1}, &PthreadLockChecker::AcquirePthreadLock},
+      {{{"pthread_rwlock_rdlock"}, 1}, &PthreadLockChecker::AcquirePthreadLock},
+      {{{"pthread_rwlock_wrlock"}, 1}, &PthreadLockChecker::AcquirePthreadLock},
+      {{{"lck_mtx_lock"}, 1}, &PthreadLockChecker::AcquireXNULock},
+      {{{"lck_rw_lock_exclusive"}, 1}, &PthreadLockChecker::AcquireXNULock},
+      {{{"lck_rw_lock_shared"}, 1}, &PthreadLockChecker::AcquireXNULock},
 
       // Try.
-      {{"pthread_mutex_trylock", 1}, &PthreadLockChecker::TryPthreadLock},
-      {{"pthread_rwlock_tryrdlock", 1}, &PthreadLockChecker::TryPthreadLock},
-      {{"pthread_rwlock_trywrlock", 1}, &PthreadLockChecker::TryPthreadLock},
-      {{"lck_mtx_try_lock", 1}, &PthreadLockChecker::TryXNULock},
-      {{"lck_rw_try_lock_exclusive", 1}, &PthreadLockChecker::TryXNULock},
-      {{"lck_rw_try_lock_shared", 1}, &PthreadLockChecker::TryXNULock},
+      {{{"pthread_mutex_trylock"}, 1}, &PthreadLockChecker::TryPthreadLock},
+      {{{"pthread_rwlock_tryrdlock"}, 1}, &PthreadLockChecker::TryPthreadLock},
+      {{{"pthread_rwlock_trywrlock"}, 1}, &PthreadLockChecker::TryPthreadLock},
+      {{{"lck_mtx_try_lock"}, 1}, &PthreadLockChecker::TryXNULock},
+      {{{"lck_rw_try_lock_exclusive"}, 1}, &PthreadLockChecker::TryXNULock},
+      {{{"lck_rw_try_lock_shared"}, 1}, &PthreadLockChecker::TryXNULock},
 
       // Release.
-      {{"pthread_mutex_unlock", 1}, &PthreadLockChecker::ReleaseAnyLock},
-      {{"pthread_rwlock_unlock", 1}, &PthreadLockChecker::ReleaseAnyLock},
-      {{"lck_mtx_unlock", 1}, &PthreadLockChecker::ReleaseAnyLock},
-      {{"lck_rw_unlock_exclusive", 1}, &PthreadLockChecker::ReleaseAnyLock},
-      {{"lck_rw_unlock_shared", 1}, &PthreadLockChecker::ReleaseAnyLock},
-      {{"lck_rw_done", 1}, &PthreadLockChecker::ReleaseAnyLock},
+      {{{"pthread_mutex_unlock"}, 1}, &PthreadLockChecker::ReleaseAnyLock},
+      {{{"pthread_rwlock_unlock"}, 1}, &PthreadLockChecker::ReleaseAnyLock},
+      {{{"lck_mtx_unlock"}, 1}, &PthreadLockChecker::ReleaseAnyLock},
+      {{{"lck_rw_unlock_exclusive"}, 1}, &PthreadLockChecker::ReleaseAnyLock},
+      {{{"lck_rw_unlock_shared"}, 1}, &PthreadLockChecker::ReleaseAnyLock},
+      {{{"lck_rw_done"}, 1}, &PthreadLockChecker::ReleaseAnyLock},
 
       // Destroy.
-      {{"pthread_mutex_destroy", 1}, &PthreadLockChecker::DestroyPthreadLock},
-      {{"lck_mtx_destroy", 2}, &PthreadLockChecker::DestroyXNULock},
+      {{{"pthread_mutex_destroy"}, 1}, &PthreadLockChecker::DestroyPthreadLock},
+      {{{"lck_mtx_destroy"}, 2}, &PthreadLockChecker::DestroyXNULock},
       // TODO: pthread_rwlock_destroy(1 argument).
       // TODO: lck_rw_destroy(2 arguments).
   };
 
   CallDescriptionMap<FnCheck> FuchsiaCallbacks = {
       // Init.
-      {{"spin_lock_init", 1}, &PthreadLockChecker::InitAnyLock},
+      {{{"spin_lock_init"}, 1}, &PthreadLockChecker::InitAnyLock},
 
       // Acquire.
-      {{"spin_lock", 1}, &PthreadLockChecker::AcquirePthreadLock},
-      {{"spin_lock_save", 3}, &PthreadLockChecker::AcquirePthreadLock},
-      {{"sync_mutex_lock", 1}, &PthreadLockChecker::AcquirePthreadLock},
-      {{"sync_mutex_lock_with_waiter", 1},
+      {{{"spin_lock"}, 1}, &PthreadLockChecker::AcquirePthreadLock},
+      {{{"spin_lock_save"}, 3}, &PthreadLockChecker::AcquirePthreadLock},
+      {{{"sync_mutex_lock"}, 1}, &PthreadLockChecker::AcquirePthreadLock},
+      {{{"sync_mutex_lock_with_waiter"}, 1},
        &PthreadLockChecker::AcquirePthreadLock},
 
       // Try.
-      {{"spin_trylock", 1}, &PthreadLockChecker::TryFuchsiaLock},
-      {{"sync_mutex_trylock", 1}, &PthreadLockChecker::TryFuchsiaLock},
-      {{"sync_mutex_timedlock", 2}, &PthreadLockChecker::TryFuchsiaLock},
+      {{{"spin_trylock"}, 1}, &PthreadLockChecker::TryFuchsiaLock},
+      {{{"sync_mutex_trylock"}, 1}, &PthreadLockChecker::TryFuchsiaLock},
+      {{{"sync_mutex_timedlock"}, 2}, &PthreadLockChecker::TryFuchsiaLock},
 
       // Release.
-      {{"spin_unlock", 1}, &PthreadLockChecker::ReleaseAnyLock},
-      {{"spin_unlock_restore", 3}, &PthreadLockChecker::ReleaseAnyLock},
-      {{"sync_mutex_unlock", 1}, &PthreadLockChecker::ReleaseAnyLock},
+      {{{"spin_unlock"}, 1}, &PthreadLockChecker::ReleaseAnyLock},
+      {{{"spin_unlock_restore"}, 3}, &PthreadLockChecker::ReleaseAnyLock},
+      {{{"sync_mutex_unlock"}, 1}, &PthreadLockChecker::ReleaseAnyLock},
   };
 
   CallDescriptionMap<FnCheck> C11Callbacks = {
       // Init.
-      {{"mtx_init", 2}, &PthreadLockChecker::InitAnyLock},
+      {{{"mtx_init"}, 2}, &PthreadLockChecker::InitAnyLock},
 
       // Acquire.
-      {{"mtx_lock", 1}, &PthreadLockChecker::AcquirePthreadLock},
+      {{{"mtx_lock"}, 1}, &PthreadLockChecker::AcquirePthreadLock},
 
       // Try.
-      {{"mtx_trylock", 1}, &PthreadLockChecker::TryC11Lock},
-      {{"mtx_timedlock", 2}, &PthreadLockChecker::TryC11Lock},
+      {{{"mtx_trylock"}, 1}, &PthreadLockChecker::TryC11Lock},
+      {{{"mtx_timedlock"}, 2}, &PthreadLockChecker::TryC11Lock},
 
       // Release.
-      {{"mtx_unlock", 1}, &PthreadLockChecker::ReleaseAnyLock},
+      {{{"mtx_unlock"}, 1}, &PthreadLockChecker::ReleaseAnyLock},
 
       // Destroy
-      {{"mtx_destroy", 1}, &PthreadLockChecker::DestroyPthreadLock},
+      {{{"mtx_destroy"}, 1}, &PthreadLockChecker::DestroyPthreadLock},
   };
 
   ProgramStateRef resolvePossiblyDestroyedMutex(ProgramStateRef state,
Index: clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
@@ -33,7 +33,7 @@
   static int ProtRead;
   mutable std::unique_ptr<BugType> BT;
 public:
-  MmapWriteExecChecker() : MmapFn("mmap", 6), MprotectFn("mprotect", 3) {}
+  MmapWriteExecChecker() : MmapFn({"mmap"}, 6), MprotectFn({"mprotect"}, 3) {}
   void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
   int ProtExecOv;
   int ProtReadOv;
Index: clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -392,10 +392,10 @@
                                      const CallEvent &Call, CheckerContext &C)>;
 
   const CallDescriptionMap<CheckFn> FreeingMemFnMap{
-      {{"free", 1}, &MallocChecker::checkFree},
-      {{"if_freenameindex", 1}, &MallocChecker::checkIfFreeNameIndex},
-      {{"kfree", 1}, &MallocChecker::checkFree},
-      {{"g_free", 1}, &MallocChecker::checkFree},
+      {{{"free"}, 1}, &MallocChecker::checkFree},
+      {{{"if_freenameindex"}, 1}, &MallocChecker::checkIfFreeNameIndex},
+      {{{"kfree"}, 1}, &MallocChecker::checkFree},
+      {{{"g_free"}, 1}, &MallocChecker::checkFree},
   };
 
   bool isFreeingCall(const CallEvent &Call) const;
@@ -404,41 +404,41 @@
   friend class NoOwnershipChangeVisitor;
 
   CallDescriptionMap<CheckFn> AllocatingMemFnMap{
-      {{"alloca", 1}, &MallocChecker::checkAlloca},
-      {{"_alloca", 1}, &MallocChecker::checkAlloca},
-      {{"malloc", 1}, &MallocChecker::checkBasicAlloc},
-      {{"malloc", 3}, &MallocChecker::checkKernelMalloc},
-      {{"calloc", 2}, &MallocChecker::checkCalloc},
-      {{"valloc", 1}, &MallocChecker::checkBasicAlloc},
-      {{CDF_MaybeBuiltin, "strndup", 2}, &MallocChecker::checkStrdup},
-      {{CDF_MaybeBuiltin, "strdup", 1}, &MallocChecker::checkStrdup},
-      {{"_strdup", 1}, &MallocChecker::checkStrdup},
-      {{"kmalloc", 2}, &MallocChecker::checkKernelMalloc},
-      {{"if_nameindex", 1}, &MallocChecker::checkIfNameIndex},
-      {{CDF_MaybeBuiltin, "wcsdup", 1}, &MallocChecker::checkStrdup},
-      {{CDF_MaybeBuiltin, "_wcsdup", 1}, &MallocChecker::checkStrdup},
-      {{"g_malloc", 1}, &MallocChecker::checkBasicAlloc},
-      {{"g_malloc0", 1}, &MallocChecker::checkGMalloc0},
-      {{"g_try_malloc", 1}, &MallocChecker::checkBasicAlloc},
-      {{"g_try_malloc0", 1}, &MallocChecker::checkGMalloc0},
-      {{"g_memdup", 2}, &MallocChecker::checkGMemdup},
-      {{"g_malloc_n", 2}, &MallocChecker::checkGMallocN},
-      {{"g_malloc0_n", 2}, &MallocChecker::checkGMallocN0},
-      {{"g_try_malloc_n", 2}, &MallocChecker::checkGMallocN},
-      {{"g_try_malloc0_n", 2}, &MallocChecker::checkGMallocN0},
+      {{{"alloca"}, 1}, &MallocChecker::checkAlloca},
+      {{{"_alloca"}, 1}, &MallocChecker::checkAlloca},
+      {{{"malloc"}, 1}, &MallocChecker::checkBasicAlloc},
+      {{{"malloc"}, 3}, &MallocChecker::checkKernelMalloc},
+      {{{"calloc"}, 2}, &MallocChecker::checkCalloc},
+      {{{"valloc"}, 1}, &MallocChecker::checkBasicAlloc},
+      {{CDF_MaybeBuiltin, {"strndup"}, 2}, &MallocChecker::checkStrdup},
+      {{CDF_MaybeBuiltin, {"strdup"}, 1}, &MallocChecker::checkStrdup},
+      {{{"_strdup"}, 1}, &MallocChecker::checkStrdup},
+      {{{"kmalloc"}, 2}, &MallocChecker::checkKernelMalloc},
+      {{{"if_nameindex"}, 1}, &MallocChecker::checkIfNameIndex},
+      {{CDF_MaybeBuiltin, {"wcsdup"}, 1}, &MallocChecker::checkStrdup},
+      {{CDF_MaybeBuiltin, {"_wcsdup"}, 1}, &MallocChecker::checkStrdup},
+      {{{"g_malloc"}, 1}, &MallocChecker::checkBasicAlloc},
+      {{{"g_malloc0"}, 1}, &MallocChecker::checkGMalloc0},
+      {{{"g_try_malloc"}, 1}, &MallocChecker::checkBasicAlloc},
+      {{{"g_try_malloc0"}, 1}, &MallocChecker::checkGMalloc0},
+      {{{"g_memdup"}, 2}, &MallocChecker::checkGMemdup},
+      {{{"g_malloc_n"}, 2}, &MallocChecker::checkGMallocN},
+      {{{"g_malloc0_n"}, 2}, &MallocChecker::checkGMallocN0},
+      {{{"g_try_malloc_n"}, 2}, &MallocChecker::checkGMallocN},
+      {{{"g_try_malloc0_n"}, 2}, &MallocChecker::checkGMallocN0},
   };
 
   CallDescriptionMap<CheckFn> ReallocatingMemFnMap{
-      {{"realloc", 2},
+      {{{"realloc"}, 2},
        std::bind(&MallocChecker::checkRealloc, _1, _2, _3, false)},
-      {{"reallocf", 2},
+      {{{"reallocf"}, 2},
        std::bind(&MallocChecker::checkRealloc, _1, _2, _3, true)},
-      {{"g_realloc", 2},
+      {{{"g_realloc"}, 2},
        std::bind(&MallocChecker::checkRealloc, _1, _2, _3, false)},
-      {{"g_try_realloc", 2},
+      {{{"g_try_realloc"}, 2},
        std::bind(&MallocChecker::checkRealloc, _1, _2, _3, false)},
-      {{"g_realloc_n", 3}, &MallocChecker::checkReallocN},
-      {{"g_try_realloc_n", 3}, &MallocChecker::checkReallocN},
+      {{{"g_realloc_n"}, 3}, &MallocChecker::checkReallocN},
+      {{{"g_try_realloc_n"}, 3}, &MallocChecker::checkReallocN},
   };
 
   bool isMemCall(const CallEvent &Call) const;
Index: clang/lib/StaticAnalyzer/Checkers/MIGChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/MIGChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/MIGChecker.cpp
@@ -86,7 +86,7 @@
 #undef CALL
   };
 
-  CallDescription OsRefRetain{"os_ref_retain", 1};
+  CallDescription OsRefRetain{{"os_ref_retain"}, 1};
 
   void checkReturnAux(const ReturnStmt *RS, CheckerContext &C) const;
 
Index: clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -304,7 +304,7 @@
                                  TaintConfiguration &&Config) const;
 
 private:
-  using NamePartsTy = llvm::SmallVector<SmallString<32>, 2>;
+  using NamePartsTy = llvm::SmallVector<StringRef, 2>;
 
   /// Validate part of the configuration, which contains a list of argument
   /// indexes.
@@ -444,10 +444,8 @@
   if (!C.Scope.empty()) {
     // If the Scope argument contains multiple "::" parts, those are considered
     // namespace identifiers.
-    llvm::SmallVector<StringRef, 2> NSParts;
-    StringRef{C.Scope}.split(NSParts, "::", /*MaxSplit*/ -1,
+    StringRef{C.Scope}.split(NameParts, "::", /*MaxSplit*/ -1,
                              /*KeepEmpty*/ false);
-    NameParts.append(NSParts.begin(), NSParts.end());
   }
   NameParts.emplace_back(C.Name);
   return NameParts;
@@ -458,10 +456,7 @@
                                                     GenericTaintRule &&Rule,
                                                     RulesContTy &Rules) {
   NamePartsTy NameParts = parseNameParts(C);
-  llvm::SmallVector<const char *, 2> CallDescParts{NameParts.size()};
-  llvm::transform(NameParts, CallDescParts.begin(),
-                  [](SmallString<32> &S) { return S.c_str(); });
-  Rules.emplace_back(CallDescription(CallDescParts), std::move(Rule));
+  Rules.emplace_back(CallDescription(NameParts), std::move(Rule));
 }
 
 void GenericTaintRuleParser::parseConfig(const std::string &Option,
@@ -531,128 +526,128 @@
 
   RulesConstructionTy GlobalCRules{
       // Sources
-      {{"fdopen"}, TR::Source({{ReturnValueIndex}})},
-      {{"fopen"}, TR::Source({{ReturnValueIndex}})},
-      {{"freopen"}, TR::Source({{ReturnValueIndex}})},
-      {{"getch"}, TR::Source({{ReturnValueIndex}})},
-      {{"getchar"}, TR::Source({{ReturnValueIndex}})},
-      {{"getchar_unlocked"}, TR::Source({{ReturnValueIndex}})},
-      {{"gets"}, TR::Source({{0}, ReturnValueIndex})},
-      {{"gets_s"}, TR::Source({{0}, ReturnValueIndex})},
-      {{"scanf"}, TR::Source({{}, 1})},
-      {{"scanf_s"}, TR::Source({{}, {1}})},
-      {{"wgetch"}, TR::Source({{}, ReturnValueIndex})},
+      {{{"fdopen"}}, TR::Source({{ReturnValueIndex}})},
+      {{{"fopen"}}, TR::Source({{ReturnValueIndex}})},
+      {{{"freopen"}}, TR::Source({{ReturnValueIndex}})},
+      {{{"getch"}}, TR::Source({{ReturnValueIndex}})},
+      {{{"getchar"}}, TR::Source({{ReturnValueIndex}})},
+      {{{"getchar_unlocked"}}, TR::Source({{ReturnValueIndex}})},
+      {{{"gets"}}, TR::Source({{0}, ReturnValueIndex})},
+      {{{"gets_s"}}, TR::Source({{0}, ReturnValueIndex})},
+      {{{"scanf"}}, TR::Source({{}, 1})},
+      {{{"scanf_s"}}, TR::Source({{}, {1}})},
+      {{{"wgetch"}}, TR::Source({{}, ReturnValueIndex})},
       // Sometimes the line between taint sources and propagators is blurry.
       // _IO_getc is choosen to be a source, but could also be a propagator.
       // This way it is simpler, as modeling it as a propagator would require
       // to model the possible sources of _IO_FILE * values, which the _IO_getc
       // function takes as parameters.
-      {{"_IO_getc"}, TR::Source({{ReturnValueIndex}})},
-      {{"getcwd"}, TR::Source({{0, ReturnValueIndex}})},
-      {{"getwd"}, TR::Source({{0, ReturnValueIndex}})},
-      {{"readlink"}, TR::Source({{1, ReturnValueIndex}})},
-      {{"readlinkat"}, TR::Source({{2, ReturnValueIndex}})},
-      {{"get_current_dir_name"}, TR::Source({{ReturnValueIndex}})},
-      {{"gethostname"}, TR::Source({{0}})},
-      {{"getnameinfo"}, TR::Source({{2, 4}})},
-      {{"getseuserbyname"}, TR::Source({{1, 2}})},
-      {{"getgroups"}, TR::Source({{1, ReturnValueIndex}})},
-      {{"getlogin"}, TR::Source({{ReturnValueIndex}})},
-      {{"getlogin_r"}, TR::Source({{0}})},
+      {{{"_IO_getc"}}, TR::Source({{ReturnValueIndex}})},
+      {{{"getcwd"}}, TR::Source({{0, ReturnValueIndex}})},
+      {{{"getwd"}}, TR::Source({{0, ReturnValueIndex}})},
+      {{{"readlink"}}, TR::Source({{1, ReturnValueIndex}})},
+      {{{"readlinkat"}}, TR::Source({{2, ReturnValueIndex}})},
+      {{{"get_current_dir_name"}}, TR::Source({{ReturnValueIndex}})},
+      {{{"gethostname"}}, TR::Source({{0}})},
+      {{{"getnameinfo"}}, TR::Source({{2, 4}})},
+      {{{"getseuserbyname"}}, TR::Source({{1, 2}})},
+      {{{"getgroups"}}, TR::Source({{1, ReturnValueIndex}})},
+      {{{"getlogin"}}, TR::Source({{ReturnValueIndex}})},
+      {{{"getlogin_r"}}, TR::Source({{0}})},
 
       // Props
-      {{"atoi"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"atol"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"atoll"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"fgetc"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"fgetln"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"fgets"}, TR::Prop({{2}}, {{0, ReturnValueIndex}})},
-      {{"fscanf"}, TR::Prop({{0}}, {{}, 2})},
-      {{"fscanf_s"}, TR::Prop({{0}}, {{}, {2}})},
-      {{"sscanf"}, TR::Prop({{0}}, {{}, 2})},
-
-      {{"getc"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"getc_unlocked"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"getdelim"}, TR::Prop({{3}}, {{0}})},
-      {{"getline"}, TR::Prop({{2}}, {{0}})},
-      {{"getw"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"pread"}, TR::Prop({{0, 1, 2, 3}}, {{1, ReturnValueIndex}})},
-      {{"read"}, TR::Prop({{0, 2}}, {{1, ReturnValueIndex}})},
-      {{"strchr"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"strrchr"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"tolower"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"toupper"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"fread"}, TR::Prop({{3}}, {{0, ReturnValueIndex}})},
-      {{"recv"}, TR::Prop({{0}}, {{1, ReturnValueIndex}})},
-      {{"recvfrom"}, TR::Prop({{0}}, {{1, ReturnValueIndex}})},
-
-      {{"ttyname"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"ttyname_r"}, TR::Prop({{0}}, {{1, ReturnValueIndex}})},
-
-      {{"basename"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"dirname"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"fnmatch"}, TR::Prop({{1}}, {{ReturnValueIndex}})},
-      {{"memchr"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"memrchr"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"rawmemchr"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-
-      {{"mbtowc"}, TR::Prop({{1}}, {{0, ReturnValueIndex}})},
-      {{"wctomb"}, TR::Prop({{1}}, {{0, ReturnValueIndex}})},
-      {{"wcwidth"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-
-      {{"memcmp"}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})},
-      {{"memcpy"}, TR::Prop({{1}}, {{0, ReturnValueIndex}})},
-      {{"memmove"}, TR::Prop({{1}}, {{0, ReturnValueIndex}})},
+      {{{"atoi"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"atol"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"atoll"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"fgetc"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"fgetln"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"fgets"}}, TR::Prop({{2}}, {{0, ReturnValueIndex}})},
+      {{{"fscanf"}}, TR::Prop({{0}}, {{}, 2})},
+      {{{"fscanf_s"}}, TR::Prop({{0}}, {{}, {2}})},
+      {{{"sscanf"}}, TR::Prop({{0}}, {{}, 2})},
+
+      {{{"getc"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"getc_unlocked"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"getdelim"}}, TR::Prop({{3}}, {{0}})},
+      {{{"getline"}}, TR::Prop({{2}}, {{0}})},
+      {{{"getw"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"pread"}}, TR::Prop({{0, 1, 2, 3}}, {{1, ReturnValueIndex}})},
+      {{{"read"}}, TR::Prop({{0, 2}}, {{1, ReturnValueIndex}})},
+      {{{"strchr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"strrchr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"tolower"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"toupper"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"fread"}}, TR::Prop({{3}}, {{0, ReturnValueIndex}})},
+      {{{"recv"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})},
+      {{{"recvfrom"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})},
+
+      {{{"ttyname"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"ttyname_r"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})},
+
+      {{{"basename"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"dirname"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"fnmatch"}}, TR::Prop({{1}}, {{ReturnValueIndex}})},
+      {{{"memchr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"memrchr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"rawmemchr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+
+      {{{"mbtowc"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})},
+      {{{"wctomb"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})},
+      {{{"wcwidth"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+
+      {{{"memcmp"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})},
+      {{{"memcpy"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})},
+      {{{"memmove"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})},
       // If memmem was called with a tainted needle and the search was
       // successful, that would mean that the value pointed by the return value
       // has the same content as the needle. If we choose to go by the policy of
       // content equivalence implies taintedness equivalence, that would mean
       // haystack should be considered a propagation source argument.
-      {{"memmem"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"memmem"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
 
       // The comment for memmem above also applies to strstr.
-      {{"strstr"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"strcasestr"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"strstr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"strcasestr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
 
-      {{"strchrnul"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"strchrnul"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
 
-      {{"index"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"rindex"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"index"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"rindex"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
 
       // FIXME: In case of arrays, only the first element of the array gets
       // tainted.
-      {{"qsort"}, TR::Prop({{0}}, {{0}})},
-      {{"qsort_r"}, TR::Prop({{0}}, {{0}})},
-
-      {{"strcmp"}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})},
-      {{"strcasecmp"}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})},
-      {{"strncmp"}, TR::Prop({{0, 1, 2}}, {{ReturnValueIndex}})},
-      {{"strncasecmp"}, TR::Prop({{0, 1, 2}}, {{ReturnValueIndex}})},
-      {{"strspn"}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})},
-      {{"strcspn"}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})},
-      {{"strpbrk"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"strndup"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"strndupa"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"strlen"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"strnlen"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"strtol"}, TR::Prop({{0}}, {{1, ReturnValueIndex}})},
-      {{"strtoll"}, TR::Prop({{0}}, {{1, ReturnValueIndex}})},
-      {{"strtoul"}, TR::Prop({{0}}, {{1, ReturnValueIndex}})},
-      {{"strtoull"}, TR::Prop({{0}}, {{1, ReturnValueIndex}})},
-
-      {{"isalnum"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"isalpha"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"isascii"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"isblank"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"iscntrl"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"isdigit"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"isgraph"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"islower"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"isprint"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"ispunct"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"isspace"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"isupper"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{"isxdigit"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"qsort"}}, TR::Prop({{0}}, {{0}})},
+      {{{"qsort_r"}}, TR::Prop({{0}}, {{0}})},
+
+      {{{"strcmp"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})},
+      {{{"strcasecmp"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})},
+      {{{"strncmp"}}, TR::Prop({{0, 1, 2}}, {{ReturnValueIndex}})},
+      {{{"strncasecmp"}}, TR::Prop({{0, 1, 2}}, {{ReturnValueIndex}})},
+      {{{"strspn"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})},
+      {{{"strcspn"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})},
+      {{{"strpbrk"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"strndup"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"strndupa"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"strlen"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"strnlen"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"strtol"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})},
+      {{{"strtoll"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})},
+      {{{"strtoul"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})},
+      {{{"strtoull"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})},
+
+      {{{"isalnum"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"isalpha"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"isascii"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"isblank"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"iscntrl"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"isdigit"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"isgraph"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"islower"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"isprint"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"ispunct"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"isspace"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"isupper"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"isxdigit"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
 
       {{CDF_MaybeBuiltin, {BI.getName(Builtin::BIstrncat)}},
        TR::Prop({{1, 2}}, {{0, ReturnValueIndex}})},
@@ -660,37 +655,40 @@
        TR::Prop({{1, 2}}, {{0}})},
       {{CDF_MaybeBuiltin, {BI.getName(Builtin::BIstrlcat)}},
        TR::Prop({{1, 2}}, {{0}})},
-      {{CDF_MaybeBuiltin, {"snprintf"}},
+      {{CDF_MaybeBuiltin, {{"snprintf"}}},
        TR::Prop({{1}, 3}, {{0, ReturnValueIndex}})},
-      {{CDF_MaybeBuiltin, {"sprintf"}},
+      {{CDF_MaybeBuiltin, {{"sprintf"}}},
        TR::Prop({{1}, 2}, {{0, ReturnValueIndex}})},
-      {{CDF_MaybeBuiltin, {"strcpy"}},
+      {{CDF_MaybeBuiltin, {{"strcpy"}}},
        TR::Prop({{1}}, {{0, ReturnValueIndex}})},
-      {{CDF_MaybeBuiltin, {"stpcpy"}},
+      {{CDF_MaybeBuiltin, {{"stpcpy"}}},
        TR::Prop({{1}}, {{0, ReturnValueIndex}})},
-      {{CDF_MaybeBuiltin, {"strcat"}},
+      {{CDF_MaybeBuiltin, {{"strcat"}}},
        TR::Prop({{1}}, {{0, ReturnValueIndex}})},
-      {{CDF_MaybeBuiltin, {"strdup"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{CDF_MaybeBuiltin, {"strdupa"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{CDF_MaybeBuiltin, {"wcsdup"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{CDF_MaybeBuiltin, {{"strdup"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{CDF_MaybeBuiltin, {{"strdupa"}}},
+       TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{CDF_MaybeBuiltin, {{"wcsdup"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
 
       // Sinks
-      {{"system"}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
-      {{"popen"}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
-      {{"execl"}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
-      {{"execle"}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
-      {{"execlp"}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
-      {{"execvp"}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
-      {{"execvP"}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
-      {{"execve"}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
-      {{"dlopen"}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
-      {{CDF_MaybeBuiltin, {"malloc"}}, TR::Sink({{0}}, MsgTaintedBufferSize)},
-      {{CDF_MaybeBuiltin, {"calloc"}}, TR::Sink({{0}}, MsgTaintedBufferSize)},
-      {{CDF_MaybeBuiltin, {"alloca"}}, TR::Sink({{0}}, MsgTaintedBufferSize)},
-      {{CDF_MaybeBuiltin, {"memccpy"}}, TR::Sink({{3}}, MsgTaintedBufferSize)},
-      {{CDF_MaybeBuiltin, {"realloc"}}, TR::Sink({{1}}, MsgTaintedBufferSize)},
-      {{{"setproctitle"}}, TR::Sink({{0}, 1}, MsgUncontrolledFormatString)},
-      {{{"setproctitle_fast"}},
+      {{{"system"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
+      {{{"popen"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
+      {{{"execl"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
+      {{{"execle"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
+      {{{"execlp"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
+      {{{"execvp"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
+      {{{"execvP"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
+      {{{"execve"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
+      {{{"dlopen"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
+      {{CDF_MaybeBuiltin, {{"malloc"}}}, TR::Sink({{0}}, MsgTaintedBufferSize)},
+      {{CDF_MaybeBuiltin, {{"calloc"}}}, TR::Sink({{0}}, MsgTaintedBufferSize)},
+      {{CDF_MaybeBuiltin, {{"alloca"}}}, TR::Sink({{0}}, MsgTaintedBufferSize)},
+      {{CDF_MaybeBuiltin, {{"memccpy"}}},
+       TR::Sink({{3}}, MsgTaintedBufferSize)},
+      {{CDF_MaybeBuiltin, {{"realloc"}}},
+       TR::Sink({{1}}, MsgTaintedBufferSize)},
+      {{{{"setproctitle"}}}, TR::Sink({{0}, 1}, MsgUncontrolledFormatString)},
+      {{{{"setproctitle_fast"}}},
        TR::Sink({{0}, 1}, MsgUncontrolledFormatString)},
 
       // SinkProps
@@ -706,7 +704,7 @@
       {{CDF_MaybeBuiltin, {BI.getName(Builtin::BIstrndup)}},
        TR::SinkProp({{1}}, {{0, 1}}, {{ReturnValueIndex}},
                     MsgTaintedBufferSize)},
-      {{CDF_MaybeBuiltin, {"bcopy"}},
+      {{CDF_MaybeBuiltin, {{"bcopy"}}},
        TR::SinkProp({{2}}, {{0, 2}}, {{1}}, MsgTaintedBufferSize)}};
 
   // `getenv` returns taint only in untrusted environments.
@@ -714,7 +712,7 @@
     // void setproctitle_init(int argc, char *argv[], char *envp[])
     GlobalCRules.push_back(
         {{{"setproctitle_init"}}, TR::Sink({{1, 2}}, MsgCustomSink)});
-    GlobalCRules.push_back({{"getenv"}, TR::Source({{ReturnValueIndex}})});
+    GlobalCRules.push_back({{{"getenv"}}, TR::Source({{ReturnValueIndex}})});
   }
 
   StaticTaintRules.emplace(std::make_move_iterator(GlobalCRules.begin()),
Index: clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp
@@ -69,13 +69,13 @@
 
   using EvalFn = std::function<void(CheckerContext &, const CallEvent &)>;
   const CallDescriptionMap<EvalFn> TestCalls{
-      {{"ErrnoTesterChecker_setErrno", 1}, &ErrnoTesterChecker::evalSetErrno},
-      {{"ErrnoTesterChecker_getErrno", 0}, &ErrnoTesterChecker::evalGetErrno},
-      {{"ErrnoTesterChecker_setErrnoIfError", 0},
+      {{{"ErrnoTesterChecker_setErrno"}, 1}, &ErrnoTesterChecker::evalSetErrno},
+      {{{"ErrnoTesterChecker_getErrno"}, 0}, &ErrnoTesterChecker::evalGetErrno},
+      {{{"ErrnoTesterChecker_setErrnoIfError"}, 0},
        &ErrnoTesterChecker::evalSetErrnoIfError},
-      {{"ErrnoTesterChecker_setErrnoIfErrorRange", 0},
+      {{{"ErrnoTesterChecker_setErrnoIfErrorRange"}, 0},
        &ErrnoTesterChecker::evalSetErrnoIfErrorRange},
-      {{"ErrnoTesterChecker_setErrnoCheckState", 0},
+      {{{"ErrnoTesterChecker_setErrnoCheckState"}, 0},
        &ErrnoTesterChecker::evalSetErrnoCheckState}};
 };
 
Index: clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
@@ -57,11 +57,11 @@
 
 private:
   // FIXME: Names from `ErrnoLocationFuncNames` are used to build this set.
-  CallDescriptionSet ErrnoLocationCalls{{"__errno_location", 0, 0},
-                                        {"___errno", 0, 0},
-                                        {"__errno", 0, 0},
-                                        {"_errno", 0, 0},
-                                        {"__error", 0, 0}};
+  CallDescriptionSet ErrnoLocationCalls{{{"__errno_location"}, 0, 0},
+                                        {{"___errno"}, 0, 0},
+                                        {{"__errno"}, 0, 0},
+                                        {{"_errno"}, 0, 0},
+                                        {{"__error"}, 0, 0}};
 };
 
 } // namespace
Index: clang/lib/StaticAnalyzer/Checkers/DebugIteratorModeling.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/DebugIteratorModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/DebugIteratorModeling.cpp
@@ -42,11 +42,11 @@
                                                  CheckerContext &) const;
 
   CallDescriptionMap<FnCheck> Callbacks = {
-      {{"clang_analyzer_iterator_position", 1},
+      {{{"clang_analyzer_iterator_position"}, 1},
        &DebugIteratorModeling::analyzerIteratorPosition},
-      {{"clang_analyzer_iterator_container", 1},
+      {{{"clang_analyzer_iterator_container"}, 1},
        &DebugIteratorModeling::analyzerIteratorContainer},
-      {{"clang_analyzer_iterator_validity", 1},
+      {{{"clang_analyzer_iterator_validity"}, 1},
        &DebugIteratorModeling::analyzerIteratorValidity},
   };
 
Index: clang/lib/StaticAnalyzer/Checkers/DebugContainerModeling.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/DebugContainerModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/DebugContainerModeling.cpp
@@ -41,9 +41,9 @@
                                                  CheckerContext &) const;
 
   CallDescriptionMap<FnCheck> Callbacks = {
-      {{"clang_analyzer_container_begin", 1},
+      {{{"clang_analyzer_container_begin"}, 1},
        &DebugContainerModeling::analyzerContainerBegin},
-      {{"clang_analyzer_container_end", 1},
+      {{{"clang_analyzer_container_end"}, 1},
        &DebugContainerModeling::analyzerContainerEnd},
   };
 
Index: clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
@@ -72,26 +72,26 @@
                                                    SVal) const;
 
   CallDescriptionMap<NoItParamFn> NoIterParamFunctions = {
-      {{"clear", 0}, &ContainerModeling::handleClear},
-      {{"assign", 2}, &ContainerModeling::handleAssign},
-      {{"push_back", 1}, &ContainerModeling::handlePushBack},
-      {{"emplace_back", 1}, &ContainerModeling::handlePushBack},
-      {{"pop_back", 0}, &ContainerModeling::handlePopBack},
-      {{"push_front", 1}, &ContainerModeling::handlePushFront},
-      {{"emplace_front", 1}, &ContainerModeling::handlePushFront},
-      {{"pop_front", 0}, &ContainerModeling::handlePopFront},
+      {{{"clear"}, 0}, &ContainerModeling::handleClear},
+      {{{"assign"}, 2}, &ContainerModeling::handleAssign},
+      {{{"push_back"}, 1}, &ContainerModeling::handlePushBack},
+      {{{"emplace_back"}, 1}, &ContainerModeling::handlePushBack},
+      {{{"pop_back"}, 0}, &ContainerModeling::handlePopBack},
+      {{{"push_front"}, 1}, &ContainerModeling::handlePushFront},
+      {{{"emplace_front"}, 1}, &ContainerModeling::handlePushFront},
+      {{{"pop_front"}, 0}, &ContainerModeling::handlePopFront},
   };
 
   CallDescriptionMap<OneItParamFn> OneIterParamFunctions = {
-      {{"insert", 2}, &ContainerModeling::handleInsert},
-      {{"emplace", 2}, &ContainerModeling::handleInsert},
-      {{"erase", 1}, &ContainerModeling::handleErase},
-      {{"erase_after", 1}, &ContainerModeling::handleEraseAfter},
+      {{{"insert"}, 2}, &ContainerModeling::handleInsert},
+      {{{"emplace"}, 2}, &ContainerModeling::handleInsert},
+      {{{"erase"}, 1}, &ContainerModeling::handleErase},
+      {{{"erase_after"}, 1}, &ContainerModeling::handleEraseAfter},
   };
 
   CallDescriptionMap<TwoItParamFn> TwoIterParamFunctions = {
-      {{"erase", 2}, &ContainerModeling::handleErase},
-      {{"erase_after", 2}, &ContainerModeling::handleEraseAfter},
+      {{{"erase"}, 2}, &ContainerModeling::handleErase},
+      {{{"erase_after"}, 2}, &ContainerModeling::handleEraseAfter},
   };
 };
 
Index: clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
@@ -43,7 +43,7 @@
   // This bug refers to possibly break out of a chroot() jail.
   mutable std::unique_ptr<BuiltinBug> BT_BreakJail;
 
-  const CallDescription Chroot{"chroot", 1}, Chdir{"chdir", 1};
+  const CallDescription Chroot{{"chroot"}, 1}, Chdir{{"chdir"}, 1};
 
 public:
   ChrootChecker() {}
Index: clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -134,45 +134,46 @@
                                      const CallExpr *)>;
 
   CallDescriptionMap<FnCheck> Callbacks = {
-      {{CDF_MaybeBuiltin, "memcpy", 3},
+      {{CDF_MaybeBuiltin, {"memcpy"}, 3},
        std::bind(&CStringChecker::evalMemcpy, _1, _2, _3, CK_Regular)},
-      {{CDF_MaybeBuiltin, "wmemcpy", 3},
+      {{CDF_MaybeBuiltin, {"wmemcpy"}, 3},
        std::bind(&CStringChecker::evalMemcpy, _1, _2, _3, CK_Wide)},
-      {{CDF_MaybeBuiltin, "mempcpy", 3},
+      {{CDF_MaybeBuiltin, {"mempcpy"}, 3},
        std::bind(&CStringChecker::evalMempcpy, _1, _2, _3, CK_Regular)},
-      {{CDF_None, "wmempcpy", 3},
+      {{CDF_None, {"wmempcpy"}, 3},
        std::bind(&CStringChecker::evalMempcpy, _1, _2, _3, CK_Wide)},
-      {{CDF_MaybeBuiltin, "memcmp", 3},
+      {{CDF_MaybeBuiltin, {"memcmp"}, 3},
        std::bind(&CStringChecker::evalMemcmp, _1, _2, _3, CK_Regular)},
-      {{CDF_MaybeBuiltin, "wmemcmp", 3},
+      {{CDF_MaybeBuiltin, {"wmemcmp"}, 3},
        std::bind(&CStringChecker::evalMemcmp, _1, _2, _3, CK_Wide)},
-      {{CDF_MaybeBuiltin, "memmove", 3},
+      {{CDF_MaybeBuiltin, {"memmove"}, 3},
        std::bind(&CStringChecker::evalMemmove, _1, _2, _3, CK_Regular)},
-      {{CDF_MaybeBuiltin, "wmemmove", 3},
+      {{CDF_MaybeBuiltin, {"wmemmove"}, 3},
        std::bind(&CStringChecker::evalMemmove, _1, _2, _3, CK_Wide)},
-      {{CDF_MaybeBuiltin, "memset", 3}, &CStringChecker::evalMemset},
-      {{CDF_MaybeBuiltin, "explicit_memset", 3}, &CStringChecker::evalMemset},
-      {{CDF_MaybeBuiltin, "strcpy", 2}, &CStringChecker::evalStrcpy},
-      {{CDF_MaybeBuiltin, "strncpy", 3}, &CStringChecker::evalStrncpy},
-      {{CDF_MaybeBuiltin, "stpcpy", 2}, &CStringChecker::evalStpcpy},
-      {{CDF_MaybeBuiltin, "strlcpy", 3}, &CStringChecker::evalStrlcpy},
-      {{CDF_MaybeBuiltin, "strcat", 2}, &CStringChecker::evalStrcat},
-      {{CDF_MaybeBuiltin, "strncat", 3}, &CStringChecker::evalStrncat},
-      {{CDF_MaybeBuiltin, "strlcat", 3}, &CStringChecker::evalStrlcat},
-      {{CDF_MaybeBuiltin, "strlen", 1}, &CStringChecker::evalstrLength},
-      {{CDF_MaybeBuiltin, "wcslen", 1}, &CStringChecker::evalstrLength},
-      {{CDF_MaybeBuiltin, "strnlen", 2}, &CStringChecker::evalstrnLength},
-      {{CDF_MaybeBuiltin, "wcsnlen", 2}, &CStringChecker::evalstrnLength},
-      {{CDF_MaybeBuiltin, "strcmp", 2}, &CStringChecker::evalStrcmp},
-      {{CDF_MaybeBuiltin, "strncmp", 3}, &CStringChecker::evalStrncmp},
-      {{CDF_MaybeBuiltin, "strcasecmp", 2}, &CStringChecker::evalStrcasecmp},
-      {{CDF_MaybeBuiltin, "strncasecmp", 3}, &CStringChecker::evalStrncasecmp},
-      {{CDF_MaybeBuiltin, "strsep", 2}, &CStringChecker::evalStrsep},
-      {{CDF_MaybeBuiltin, "bcopy", 3}, &CStringChecker::evalBcopy},
-      {{CDF_MaybeBuiltin, "bcmp", 3},
+      {{CDF_MaybeBuiltin, {"memset"}, 3}, &CStringChecker::evalMemset},
+      {{CDF_MaybeBuiltin, {"explicit_memset"}, 3}, &CStringChecker::evalMemset},
+      {{CDF_MaybeBuiltin, {"strcpy"}, 2}, &CStringChecker::evalStrcpy},
+      {{CDF_MaybeBuiltin, {"strncpy"}, 3}, &CStringChecker::evalStrncpy},
+      {{CDF_MaybeBuiltin, {"stpcpy"}, 2}, &CStringChecker::evalStpcpy},
+      {{CDF_MaybeBuiltin, {"strlcpy"}, 3}, &CStringChecker::evalStrlcpy},
+      {{CDF_MaybeBuiltin, {"strcat"}, 2}, &CStringChecker::evalStrcat},
+      {{CDF_MaybeBuiltin, {"strncat"}, 3}, &CStringChecker::evalStrncat},
+      {{CDF_MaybeBuiltin, {"strlcat"}, 3}, &CStringChecker::evalStrlcat},
+      {{CDF_MaybeBuiltin, {"strlen"}, 1}, &CStringChecker::evalstrLength},
+      {{CDF_MaybeBuiltin, {"wcslen"}, 1}, &CStringChecker::evalstrLength},
+      {{CDF_MaybeBuiltin, {"strnlen"}, 2}, &CStringChecker::evalstrnLength},
+      {{CDF_MaybeBuiltin, {"wcsnlen"}, 2}, &CStringChecker::evalstrnLength},
+      {{CDF_MaybeBuiltin, {"strcmp"}, 2}, &CStringChecker::evalStrcmp},
+      {{CDF_MaybeBuiltin, {"strncmp"}, 3}, &CStringChecker::evalStrncmp},
+      {{CDF_MaybeBuiltin, {"strcasecmp"}, 2}, &CStringChecker::evalStrcasecmp},
+      {{CDF_MaybeBuiltin, {"strncasecmp"}, 3},
+       &CStringChecker::evalStrncasecmp},
+      {{CDF_MaybeBuiltin, {"strsep"}, 2}, &CStringChecker::evalStrsep},
+      {{CDF_MaybeBuiltin, {"bcopy"}, 3}, &CStringChecker::evalBcopy},
+      {{CDF_MaybeBuiltin, {"bcmp"}, 3},
        std::bind(&CStringChecker::evalMemcmp, _1, _2, _3, CK_Regular)},
-      {{CDF_MaybeBuiltin, "bzero", 2}, &CStringChecker::evalBzero},
-      {{CDF_MaybeBuiltin, "explicit_bzero", 2}, &CStringChecker::evalBzero},
+      {{CDF_MaybeBuiltin, {"bzero"}, 2}, &CStringChecker::evalBzero},
+      {{CDF_MaybeBuiltin, {"explicit_bzero"}, 2}, &CStringChecker::evalBzero},
   };
 
   // These require a bit of special handling.
Index: clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
@@ -64,19 +64,15 @@
 REGISTER_TRAIT_WITH_PROGRAMSTATE(MutexCounter, unsigned)
 
 BlockInCriticalSectionChecker::BlockInCriticalSectionChecker()
-    : IILockGuard(nullptr), IIUniqueLock(nullptr),
-      LockFn("lock"), UnlockFn("unlock"), SleepFn("sleep"), GetcFn("getc"),
-      FgetsFn("fgets"), ReadFn("read"), RecvFn("recv"),
-      PthreadLockFn("pthread_mutex_lock"),
-      PthreadTryLockFn("pthread_mutex_trylock"),
-      PthreadUnlockFn("pthread_mutex_unlock"),
-      MtxLock("mtx_lock"),
-      MtxTimedLock("mtx_timedlock"),
-      MtxTryLock("mtx_trylock"),
-      MtxUnlock("mtx_unlock"),
-      ClassLockGuard("lock_guard"),
-      ClassUniqueLock("unique_lock"),
-      IdentifierInfoInitialized(false) {
+    : IILockGuard(nullptr), IIUniqueLock(nullptr), LockFn({"lock"}),
+      UnlockFn({"unlock"}), SleepFn({"sleep"}), GetcFn({"getc"}),
+      FgetsFn({"fgets"}), ReadFn({"read"}), RecvFn({"recv"}),
+      PthreadLockFn({"pthread_mutex_lock"}),
+      PthreadTryLockFn({"pthread_mutex_trylock"}),
+      PthreadUnlockFn({"pthread_mutex_unlock"}), MtxLock({"mtx_lock"}),
+      MtxTimedLock({"mtx_timedlock"}), MtxTryLock({"mtx_trylock"}),
+      MtxUnlock({"mtx_unlock"}), ClassLockGuard("lock_guard"),
+      ClassUniqueLock("unique_lock"), IdentifierInfoInitialized(false) {
   // Initialize the bug type.
   BlockInCritSectionBugType.reset(
       new BugType(this, "Call to blocking function in critical section",
Index: clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -532,10 +532,10 @@
 class CFRetainReleaseChecker : public Checker<check::PreCall> {
   mutable APIMisuse BT{this, "null passed to CF memory management function"};
   const CallDescriptionSet ModelledCalls = {
-      {"CFRetain", 1},
-      {"CFRelease", 1},
-      {"CFMakeCollectable", 1},
-      {"CFAutorelease", 1},
+      {{"CFRetain"}, 1},
+      {{"CFRelease"}, 1},
+      {{"CFMakeCollectable"}, 1},
+      {{"CFAutorelease"}, 1},
   };
 
 public:
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -6947,7 +6947,7 @@
   // Get the decl for the concrete builtin from this, we can tell what the
   // concrete integer type we should convert to is.
   unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex];
-  const char *NewBuiltinName = Context.BuiltinInfo.getName(NewBuiltinID);
+  StringRef NewBuiltinName = Context.BuiltinInfo.getName(NewBuiltinID);
   FunctionDecl *NewBuiltinDecl;
   if (NewBuiltinID == BuiltinID)
     NewBuiltinDecl = FDecl;
@@ -10999,7 +10999,7 @@
                             unsigned AbsKind, QualType ArgType) {
   bool EmitHeaderHint = true;
   const char *HeaderName = nullptr;
-  const char *FunctionName = nullptr;
+  StringRef FunctionName;
   if (S.getLangOpts().CPlusPlus && !ArgType->isAnyComplexType()) {
     FunctionName = "std::abs";
     if (ArgType->isIntegralOrEnumerationType()) {
@@ -11107,7 +11107,7 @@
   // Unsigned types cannot be negative.  Suggest removing the absolute value
   // function call.
   if (ArgType->isUnsignedIntegerType()) {
-    const char *FunctionName =
+    StringRef FunctionName =
         IsStdAbs ? "std::abs" : Context.BuiltinInfo.getName(AbsKind);
     Diag(Call->getExprLoc(), diag::warn_unsigned_abs) << ArgType << ParamType;
     Diag(Call->getExprLoc(), diag::note_remove_abs)
Index: clang/lib/Driver/DriverOptions.cpp
===================================================================
--- clang/lib/Driver/DriverOptions.cpp
+++ clang/lib/Driver/DriverOptions.cpp
@@ -16,7 +16,7 @@
 using namespace clang::driver::options;
 using namespace llvm::opt;
 
-#define PREFIX(NAME, VALUE) static const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) static constexpr llvm::StringLiteral NAME[] = VALUE;
 #include "clang/Driver/Options.inc"
 #undef PREFIX
 
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -134,7 +134,7 @@
                  AIXLongDouble64Builtins.end())
       Name = AIXLongDouble64Builtins[BuiltinID];
     else
-      Name = Context.BuiltinInfo.getName(BuiltinID) + 10;
+      Name = Context.BuiltinInfo.getName(BuiltinID).substr(10);
   }
 
   llvm::FunctionType *Ty =
@@ -5298,7 +5298,7 @@
     LargestVectorWidth = std::max(LargestVectorWidth, VectorWidth);
 
   // See if we have a target specific intrinsic.
-  const char *Name = getContext().BuiltinInfo.getName(BuiltinID);
+  StringRef Name = getContext().BuiltinInfo.getName(BuiltinID);
   Intrinsic::ID IntrinsicID = Intrinsic::not_intrinsic;
   StringRef Prefix =
       llvm::Triple::getArchTypePrefix(getTarget().getTriple().getArch());
Index: clang/lib/Basic/Builtins.cpp
===================================================================
--- clang/lib/Basic/Builtins.cpp
+++ clang/lib/Basic/Builtins.cpp
@@ -18,8 +18,9 @@
 #include "llvm/ADT/StringRef.h"
 using namespace clang;
 
-static const Builtin::Info BuiltinInfo[] = {
-  { "not a builtin function", nullptr, nullptr, nullptr, ALL_LANGUAGES,nullptr},
+static constexpr Builtin::Info BuiltinInfo[] = {
+    {"not a builtin function", nullptr, nullptr, nullptr, ALL_LANGUAGES,
+     nullptr},
 #define BUILTIN(ID, TYPE, ATTRS)                                               \
   { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
 #define LANGBUILTIN(ID, TYPE, ATTRS, LANGS)                                    \
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -9237,8 +9237,8 @@
   case Builtin::BIwmemchr:
     if (Info.getLangOpts().CPlusPlus11)
       Info.CCEDiag(E, diag::note_constexpr_invalid_function)
-        << /*isConstexpr*/0 << /*isConstructor*/0
-        << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'");
+          << /*isConstexpr*/ 0 << /*isConstructor*/ 0
+          << ("'" + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'").str();
     else
       Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr);
     [[fallthrough]];
@@ -9283,7 +9283,7 @@
     // FIXME: We can compare the bytes in the correct order.
     if (IsRawByte && !isOneByteCharacterType(CharTy)) {
       Info.FFDiag(E, diag::note_constexpr_memchr_unsupported)
-          << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'")
+          << ("'" + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'").str()
           << CharTy;
       return false;
     }
@@ -9345,8 +9345,8 @@
   case Builtin::BIwmemmove:
     if (Info.getLangOpts().CPlusPlus11)
       Info.CCEDiag(E, diag::note_constexpr_invalid_function)
-        << /*isConstexpr*/0 << /*isConstructor*/0
-        << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'");
+          << /*isConstexpr*/ 0 << /*isConstructor*/ 0
+          << ("'" + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'").str();
     else
       Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr);
     [[fallthrough]];
@@ -12155,8 +12155,8 @@
     // A call to strlen is not a constant expression.
     if (Info.getLangOpts().CPlusPlus11)
       Info.CCEDiag(E, diag::note_constexpr_invalid_function)
-        << /*isConstexpr*/0 << /*isConstructor*/0
-        << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'");
+          << /*isConstexpr*/ 0 << /*isConstructor*/ 0
+          << ("'" + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'").str();
     else
       Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr);
     [[fallthrough]];
@@ -12180,8 +12180,8 @@
     // A call to strlen is not a constant expression.
     if (Info.getLangOpts().CPlusPlus11)
       Info.CCEDiag(E, diag::note_constexpr_invalid_function)
-        << /*isConstexpr*/0 << /*isConstructor*/0
-        << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'");
+          << /*isConstexpr*/ 0 << /*isConstructor*/ 0
+          << ("'" + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'").str();
     else
       Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr);
     [[fallthrough]];
@@ -12236,7 +12236,7 @@
         !(isOneByteCharacterType(CharTy1) && isOneByteCharacterType(CharTy2))) {
       // FIXME: Consider using our bit_cast implementation to support this.
       Info.FFDiag(E, diag::note_constexpr_memcmp_unsupported)
-          << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'")
+          << ("'" + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'").str()
           << CharTy1 << CharTy2;
       return false;
     }
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h
@@ -63,13 +63,12 @@
   /// @param RequiredArgs The number of arguments that is expected to match a
   /// call. Omit this parameter to match every occurrence of call with a given
   /// name regardless the number of arguments.
-  CallDescription(CallDescriptionFlags Flags,
-                  ArrayRef<const char *> QualifiedName,
+  CallDescription(CallDescriptionFlags Flags, ArrayRef<StringRef> QualifiedName,
                   MaybeCount RequiredArgs = std::nullopt,
                   MaybeCount RequiredParams = std::nullopt);
 
   /// Construct a CallDescription with default flags.
-  CallDescription(ArrayRef<const char *> QualifiedName,
+  CallDescription(ArrayRef<StringRef> QualifiedName,
                   MaybeCount RequiredArgs = std::nullopt,
                   MaybeCount RequiredParams = std::nullopt);
 
Index: clang/include/clang/Basic/Builtins.h
===================================================================
--- clang/include/clang/Basic/Builtins.h
+++ clang/include/clang/Basic/Builtins.h
@@ -57,7 +57,8 @@
 };
 
 struct Info {
-  const char *Name, *Type, *Attributes, *HeaderName;
+  llvm::StringRef Name;
+  const char *Type, *Attributes, *HeaderName;
   LanguageID Langs;
   const char *Features;
 };
@@ -86,9 +87,7 @@
 
   /// Return the identifier name for the specified builtin,
   /// e.g. "__builtin_abs".
-  const char *getName(unsigned ID) const {
-    return getRecord(ID).Name;
-  }
+  llvm::StringRef getName(unsigned ID) const { return getRecord(ID).Name; }
 
   /// Get the type descriptor string for the specified builtin.
   const char *getTypeString(unsigned ID) const {
Index: clang-tools-extra/clangd/CompileCommands.cpp
===================================================================
--- clang-tools-extra/clangd/CompileCommands.cpp
+++ clang-tools-extra/clangd/CompileCommands.cpp
@@ -467,7 +467,7 @@
     };
     // Also grab prefixes for each option, these are not fully exposed.
     const char *const *Prefixes[DriverID::LastOption] = {nullptr};
-#define PREFIX(NAME, VALUE) static const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE) static constexpr llvm::StringLiteral NAME[] = VALUE;
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELP, METAVAR, VALUES)                                          \
   Prefixes[DriverID::OPT_##ID] = PREFIX;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to