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