Index: include/clang/ARCMigrate/ARCMT.h =================================================================== --- include/clang/ARCMigrate/ARCMT.h +++ include/clang/ARCMigrate/ARCMT.h @@ -15,12 +15,13 @@ #include "clang/Frontend/CompilerInvocation.h" namespace clang { - class ASTContext; - class DiagnosticConsumer; - class PCHContainerOperations; +class ASTContext; +class DiagnosticConsumer; +class DiagnosticIDs; +class PCHContainerOperations; namespace arcmt { - class MigrationPass; +class MigrationPass; /// \brief Creates an AST with the provided CompilerInvocation but with these /// changes: @@ -38,29 +39,27 @@ /// the pre-migration ARC diagnostics. /// /// \returns false if no error is produced, true otherwise. -bool -checkForManualIssues(CompilerInvocation &CI, const FrontendInputFile &Input, - std::shared_ptr PCHContainerOps, - DiagnosticConsumer *DiagClient, - bool emitPremigrationARCErrors = false, - StringRef plistOut = StringRef()); +bool checkForManualIssues( + CompilerInvocation &CI, const FrontendInputFile &Input, + std::shared_ptr PCHContainerOps, + DiagnosticsEngine &Diags, bool emitPremigrationARCErrors = false, + StringRef plistOut = StringRef()); /// \brief Works similar to checkForManualIssues but instead of checking, it /// applies automatic modifications to source files to conform to ARC. /// /// \returns false if no error is produced, true otherwise. -bool -applyTransformations(CompilerInvocation &origCI, - const FrontendInputFile &Input, - std::shared_ptr PCHContainerOps, - DiagnosticConsumer *DiagClient); +bool applyTransformations( + CompilerInvocation &origCI, const FrontendInputFile &Input, + std::shared_ptr PCHContainerOps, + DiagnosticsEngine &Diags); /// \brief Applies automatic modifications and produces temporary files /// and metadata into the \p outputDir path. /// /// \param emitPremigrationARCErrors if true all ARC errors will get emitted -/// even if the migrator can fix them, but the function will still return false -/// if all ARC errors can be fixed. +/// even if the migrator can fix them, but the function will still return +/// false if all ARC errors can be fixed. /// /// \param plistOut if non-empty, it is the file path to store the plist with /// the pre-migration ARC diagnostics. @@ -69,25 +68,24 @@ bool migrateWithTemporaryFiles( CompilerInvocation &origCI, const FrontendInputFile &Input, std::shared_ptr PCHContainerOps, - DiagnosticConsumer *DiagClient, StringRef outputDir, + DiagnosticsEngine &Diags, StringRef outputDir, bool emitPremigrationARCErrors, StringRef plistOut); /// \brief Get the set of file remappings from the \p outputDir path that /// migrateWithTemporaryFiles produced. /// /// \returns false if no error is produced, true otherwise. -bool getFileRemappings(std::vector > &remap, - StringRef outputDir, - DiagnosticConsumer *DiagClient); +bool getFileRemappings(std::vector> &remap, + StringRef outputDir, DiagnosticConsumer *DiagClient, + IntrusiveRefCntPtr DiagIDs); /// \brief Get the set of file remappings from a list of files with remapping /// info. /// /// \returns false if no error is produced, true otherwise. bool getFileRemappingsFromFileList( - std::vector > &remap, - ArrayRef remapFiles, - DiagnosticConsumer *DiagClient); + std::vector> &remap, + ArrayRef remapFiles, DiagnosticConsumer *DiagClient); typedef void (*TransformFn)(MigrationPass &pass); @@ -97,7 +95,7 @@ class MigrationProcess { CompilerInvocation OrigCI; std::shared_ptr PCHContainerOps; - DiagnosticConsumer *DiagClient; + DiagnosticsEngine &OriginalDiags; FileRemapper Remapper; public: @@ -105,18 +103,18 @@ MigrationProcess(const CompilerInvocation &CI, std::shared_ptr PCHContainerOps, - DiagnosticConsumer *diagClient, + DiagnosticsEngine &OriginalDiags, StringRef outputDir = StringRef()); class RewriteListener { public: virtual ~RewriteListener(); - virtual void start(ASTContext &Ctx) { } - virtual void finish() { } + virtual void start(ASTContext &Ctx) {} + virtual void finish() {} - virtual void insert(SourceLocation loc, StringRef text) { } - virtual void remove(CharSourceRange range) { } + virtual void insert(SourceLocation loc, StringRef text) {} + virtual void remove(CharSourceRange range) {} }; bool applyTransform(TransformFn trans, RewriteListener *listener = nullptr); Index: include/clang/Basic/DiagnosticIDs.h =================================================================== --- include/clang/Basic/DiagnosticIDs.h +++ include/clang/Basic/DiagnosticIDs.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_BASIC_DIAGNOSTICIDS_H #include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringRef.h" #include @@ -168,12 +169,54 @@ Ignored, Note, Remark, Warning, Error, Fatal }; + // Diagnostic classes. + enum { + CLASS_NOTE = 0x01, + CLASS_REMARK = 0x02, + CLASS_WARNING = 0x03, + CLASS_EXTENSION = 0x04, + CLASS_ERROR = 0x05 + }; + + struct DiagInfoRec { + uint16_t DiagID; + unsigned DefaultSeverity : 3; + unsigned Class : 3; + unsigned SFINAE : 2; + unsigned WarnNoWerror : 1; + unsigned WarnShowInSystemHeader : 1; + unsigned Category : 6; + + uint16_t OptionGroupIndex; + + uint16_t DescriptionLen; + const char *DescriptionStr; + + unsigned getOptionGroupIndex() const { return OptionGroupIndex; } + + StringRef getDescription() const { + return StringRef(DescriptionStr, DescriptionLen); + } + + diag::Flavor getFlavor() const { + return Class == CLASS_REMARK ? diag::Flavor::Remark + : diag::Flavor::WarningOrError; + } + + bool operator<(const DiagInfoRec &RHS) const { return DiagID < RHS.DiagID; } + }; + private: /// \brief Information for uniquing and looking up custom diags. - diag::CustomDiagInfo *CustomDiagInfo; + diag::CustomDiagInfo *CustomDiagInfo = nullptr; + ArrayRef DiagInfo; + std::function GetDiagInfo; public: - DiagnosticIDs(); + DiagnosticIDs(bool); + DiagnosticIDs(ArrayRef DiagInfo, + std::function GetDiagInfo) + : DiagInfo(DiagInfo), GetDiagInfo(GetDiagInfo) {} ~DiagnosticIDs(); /// \brief Return an ID for a diagnostic with the specified format string and @@ -199,18 +242,18 @@ /// /// This only works on builtin diagnostics, not custom ones, and is not /// legal to call on NOTEs. - static bool isBuiltinWarningOrExtension(unsigned DiagID); + bool isBuiltinWarningOrExtension(unsigned DiagID) const; /// \brief Return true if the specified diagnostic is mapped to errors by /// default. - static bool isDefaultMappingAsError(unsigned DiagID); + bool isDefaultMappingAsError(unsigned DiagID) const; /// \brief Determine whether the given built-in diagnostic ID is a Note. - static bool isBuiltinNote(unsigned DiagID); + bool isBuiltinNote(unsigned DiagID) const; /// \brief Determine whether the given built-in diagnostic ID is for an /// extension of some sort. - static bool isBuiltinExtensionDiag(unsigned DiagID) { + bool isBuiltinExtensionDiag(unsigned DiagID) const { bool ignored; return isBuiltinExtensionDiag(DiagID, ignored); } @@ -222,28 +265,27 @@ /// diagnostic is ignored by default (in which case -pedantic enables it) or /// treated as a warning/error by default. /// - static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault); - + bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault) const; /// \brief Return the lowest-level warning option that enables the specified /// diagnostic. /// /// If there is no -Wfoo flag that controls the diagnostic, this returns null. - static StringRef getWarningOptionForDiag(unsigned DiagID); - + StringRef getWarningOptionForDiag(unsigned DiagID) const; + /// \brief Return the category number that a specified \p DiagID belongs to, /// or 0 if no category. - static unsigned getCategoryNumberForDiag(unsigned DiagID); + unsigned getCategoryNumberForDiag(unsigned DiagID) const; /// \brief Return the number of diagnostic categories. - static unsigned getNumberOfCategories(); + unsigned getNumberOfCategories() const; /// \brief Given a category ID, return the name of the category. - static StringRef getCategoryNameFromID(unsigned CategoryID); - + StringRef getCategoryNameFromID(unsigned CategoryID) const; + /// \brief Return true if a given diagnostic falls into an ARC diagnostic /// category. - static bool isARCDiagnostic(unsigned DiagID); + bool isARCDiagnostic(unsigned DiagID) const; /// \brief Enumeration describing how the emission of a diagnostic should /// be treated when it occurs during C++ template argument deduction. @@ -279,14 +321,14 @@ /// deduction fails but no diagnostic is emitted. Certain classes of /// errors, such as those errors that involve C++ access control, /// are not SFINAE errors. - static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID); + SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID) const; /// \brief Get the string of all diagnostic flags. /// /// \returns A list of all diagnostics flags as they would be written in a /// command line invocation including their `no-` variants. For example: /// `{"-Wempty-body", "-Wno-empty-body", ...}` - static std::vector getDiagnosticFlags(); + std::vector getDiagnosticFlags() const; /// \brief Get the set of all diagnostic IDs in the group with the given name. /// @@ -296,12 +338,12 @@ SmallVectorImpl &Diags) const; /// \brief Get the set of all diagnostic IDs. - static void getAllDiagnostics(diag::Flavor Flavor, - SmallVectorImpl &Diags); + void getAllDiagnostics(diag::Flavor Flavor, + SmallVectorImpl &Diags) const; /// \brief Get the diagnostic option with the closest edit distance to the /// given group name. - static StringRef getNearestOption(diag::Flavor Flavor, StringRef Group); + StringRef getNearestOption(diag::Flavor Flavor, StringRef Group) const; private: /// \brief Classify the specified diagnostic ID into a Level, consumable by Index: include/clang/CrossTU/CrossTranslationUnit.h =================================================================== --- include/clang/CrossTU/CrossTranslationUnit.h +++ include/clang/CrossTU/CrossTranslationUnit.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H #include "clang/Basic/LLVM.h" +#include "clang/Frontend/CompilerInstance.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" @@ -27,6 +28,7 @@ class ASTImporter; class ASTUnit; class DeclContext; +class DiagnosticIDs; class FunctionDecl; class NamedDecl; class TranslationUnitDecl; @@ -108,7 +110,8 @@ /// Note that the AST files should also be in the \p CrossTUDir. llvm::Expected getCrossTUDefinition(const FunctionDecl *FD, StringRef CrossTUDir, - StringRef IndexName); + StringRef IndexName, + const IntrusiveRefCntPtr &DiagIDs); /// \brief This function loads a function definition from an external AST /// file. @@ -122,9 +125,10 @@ /// function. /// /// Note that the AST files should also be in the \p CrossTUDir. - llvm::Expected loadExternalAST(StringRef LookupName, - StringRef CrossTUDir, - StringRef IndexName); + llvm::Expected + loadExternalAST(StringRef LookupName, StringRef CrossTUDir, + StringRef IndexName, + const IntrusiveRefCntPtr &DiagIDs); /// \brief This function merges a definition from a separate AST Unit into /// the current one which was created by the compiler instance that @@ -139,6 +143,8 @@ /// \brief Emit diagnostics for the user for potential configuration errors. void emitCrossTUDiagnostics(const IndexError &IE); + CompilerInstance &getCompilerInstance() { return CI; } + private: ASTImporter &getOrCreateASTImporter(ASTContext &From); const FunctionDecl *findFunctionInDeclContext(const DeclContext *DC, Index: include/clang/Frontend/LogDiagnosticPrinter.h =================================================================== --- include/clang/Frontend/LogDiagnosticPrinter.h +++ include/clang/Frontend/LogDiagnosticPrinter.h @@ -52,6 +52,7 @@ raw_ostream &OS; std::unique_ptr StreamOwner; const LangOptions *LangOpts; + IntrusiveRefCntPtr DiagIDs; IntrusiveRefCntPtr DiagOpts; SourceLocation LastWarningLoc; @@ -63,7 +64,9 @@ std::string DwarfDebugFlags; public: - LogDiagnosticPrinter(raw_ostream &OS, DiagnosticOptions *Diags, + LogDiagnosticPrinter(raw_ostream &OS, + IntrusiveRefCntPtr DiagIDs, + DiagnosticOptions *Diags, std::unique_ptr StreamOwner); void setDwarfDebugFlags(StringRef Value) { Index: include/clang/Frontend/SerializedDiagnosticPrinter.h =================================================================== --- include/clang/Frontend/SerializedDiagnosticPrinter.h +++ include/clang/Frontend/SerializedDiagnosticPrinter.h @@ -21,6 +21,7 @@ namespace clang { class DiagnosticConsumer; class DiagnosticsEngine; +class DiagnosticIDs; class DiagnosticOptions; namespace serialized_diags { @@ -33,9 +34,10 @@ /// This allows wrapper tools for Clang to get diagnostics from Clang /// (via libclang) without needing to parse Clang's command line output. /// -std::unique_ptr create(StringRef OutputFile, - DiagnosticOptions *Diags, - bool MergeChildRecords = false); +std::unique_ptr +create(StringRef OutputFile, DiagnosticOptions *Diags, + IntrusiveRefCntPtr DiagIDs, + bool MergeChildRecords = false); } // end serialized_diags namespace } // end clang namespace Index: include/clang/Frontend/TextDiagnosticPrinter.h =================================================================== --- include/clang/Frontend/TextDiagnosticPrinter.h +++ include/clang/Frontend/TextDiagnosticPrinter.h @@ -27,6 +27,7 @@ class TextDiagnosticPrinter : public DiagnosticConsumer { raw_ostream &OS; + IntrusiveRefCntPtr DiagIDs; IntrusiveRefCntPtr DiagOpts; /// \brief Handle to the currently active text diagnostic emitter. @@ -38,7 +39,9 @@ unsigned OwnsOutputStream : 1; public: - TextDiagnosticPrinter(raw_ostream &os, DiagnosticOptions *diags, + TextDiagnosticPrinter(raw_ostream &os, + IntrusiveRefCntPtr DiagIDs, + DiagnosticOptions *diags, bool OwnsOutputStream = false); ~TextDiagnosticPrinter() override; @@ -46,8 +49,10 @@ /// printed at the start of any diagnostics. If empty, no prefix string is /// used. void setPrefix(std::string Value) { Prefix = std::move(Value); } + const IntrusiveRefCntPtr &getDiagIDs() { return DiagIDs; } - void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override; + void BeginSourceFile(const LangOptions &LO, + const Preprocessor *PP = nullptr) override; void EndSourceFile() override; void HandleDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info) override; Index: lib/ARCMigrate/ARCMT.cpp =================================================================== --- lib/ARCMigrate/ARCMT.cpp +++ lib/ARCMigrate/ARCMT.cpp @@ -132,7 +132,7 @@ void HandleDiagnostic(DiagnosticsEngine::Level level, const Diagnostic &Info) override { - if (DiagnosticIDs::isARCDiagnostic(Info.getID()) || + if (Diags.getDiagnosticIDs()->isARCDiagnostic(Info.getID()) || level >= DiagnosticsEngine::Error || level == DiagnosticsEngine::Note) { if (Info.getLocation().isValid()) CapturedDiags.push_back(StoredDiagnostic(level, Info)); @@ -171,7 +171,8 @@ } static CompilerInvocation * -createInvocationForMigration(CompilerInvocation &origCI, +createInvocationForMigration(const IntrusiveRefCntPtr &DiagID, + CompilerInvocation &origCI, const PCHContainerReader &PCHContainerRdr) { std::unique_ptr CInvok; CInvok.reset(new CompilerInvocation(origCI)); @@ -180,10 +181,8 @@ // We can't use a PCH because it was likely built in non-ARC mode and we // want to parse in ARC. Include the original header. FileManager FileMgr(origCI.getFileSystemOpts()); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - IntrusiveRefCntPtr Diags( - new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(), - new IgnoringDiagConsumer())); + IntrusiveRefCntPtr Diags(new DiagnosticsEngine( + DiagID, &origCI.getDiagnosticOpts(), new IgnoringDiagConsumer())); std::string OriginalFile = ASTReader::getOriginalSourceFile( PPOpts.ImplicitPCHInclude, FileMgr, PCHContainerRdr, *Diags); if (!OriginalFile.empty()) @@ -220,11 +219,11 @@ static void emitPremigrationErrors(const CapturedDiagList &arcDiags, DiagnosticOptions *diagOpts, Preprocessor &PP) { - TextDiagnosticPrinter printer(llvm::errs(), diagOpts); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - IntrusiveRefCntPtr Diags( - new DiagnosticsEngine(DiagID, diagOpts, &printer, - /*ShouldOwnClient=*/false)); + TextDiagnosticPrinter printer( + llvm::errs(), PP.getDiagnostics().getDiagnosticIDs(), diagOpts); + IntrusiveRefCntPtr Diags(new DiagnosticsEngine( + PP.getDiagnostics().getDiagnosticIDs(), diagOpts, &printer, + /*ShouldOwnClient=*/false)); Diags->setSourceManager(&PP.getSourceManager()); printer.BeginSourceFile(PP.getLangOpts(), &PP); @@ -239,7 +238,7 @@ bool arcmt::checkForManualIssues( CompilerInvocation &origCI, const FrontendInputFile &Input, std::shared_ptr PCHContainerOps, - DiagnosticConsumer *DiagClient, bool emitPremigrationARCErrors, + DiagnosticsEngine &OriginalDiags, bool emitPremigrationARCErrors, StringRef plistOut) { if (!origCI.getLangOpts()->ObjC1) return false; @@ -253,18 +252,19 @@ assert(!transforms.empty()); std::unique_ptr CInvok; - CInvok.reset( - createInvocationForMigration(origCI, PCHContainerOps->getRawReader())); + CInvok.reset(createInvocationForMigration(OriginalDiags.getDiagnosticIDs(), + origCI, + PCHContainerOps->getRawReader())); CInvok->getFrontendOpts().Inputs.clear(); CInvok->getFrontendOpts().Inputs.push_back(Input); CapturedDiagList capturedDiags; + auto *DiagClient = OriginalDiags.getClient(); assert(DiagClient); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - IntrusiveRefCntPtr Diags( - new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(), - DiagClient, /*ShouldOwnClient=*/false)); + IntrusiveRefCntPtr Diags(new DiagnosticsEngine( + OriginalDiags.getDiagnosticIDs(), &origCI.getDiagnosticOpts(), DiagClient, + /*ShouldOwnClient=*/false)); // Filter of all diagnostics. CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags); @@ -299,8 +299,8 @@ for (CapturedDiagList::iterator I = capturedDiags.begin(), E = capturedDiags.end(); I != E; ++I) arcDiags.push_back(*I); - writeARCDiagsToPlist(plistOut, arcDiags, - Ctx.getSourceManager(), Ctx.getLangOpts()); + writeARCDiagsToPlist(plistOut, arcDiags, Ctx.getSourceManager(), + Ctx.getLangOpts(), *OriginalDiags.getDiagnosticIDs()); } // After parsing of source files ended, we want to reuse the @@ -340,7 +340,7 @@ static bool applyTransforms(CompilerInvocation &origCI, const FrontendInputFile &Input, std::shared_ptr PCHContainerOps, - DiagnosticConsumer *DiagClient, StringRef outputDir, + DiagnosticsEngine &Diags, StringRef outputDir, bool emitPremigrationARCErrors, StringRef plistOut) { if (!origCI.getLangOpts()->ObjC1) return false; @@ -349,16 +349,15 @@ // Make sure checking is successful first. CompilerInvocation CInvokForCheck(origCI); - if (arcmt::checkForManualIssues(CInvokForCheck, Input, PCHContainerOps, - DiagClient, emitPremigrationARCErrors, - plistOut)) + if (arcmt::checkForManualIssues(CInvokForCheck, Input, PCHContainerOps, Diags, + emitPremigrationARCErrors, plistOut)) return true; CompilerInvocation CInvok(origCI); CInvok.getFrontendOpts().Inputs.clear(); CInvok.getFrontendOpts().Inputs.push_back(Input); - MigrationProcess migration(CInvok, PCHContainerOps, DiagClient, outputDir); + MigrationProcess migration(CInvok, PCHContainerOps, Diags, outputDir); bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval; std::vector transforms = arcmt::getAllTransformations(OrigGCMode, @@ -370,46 +369,40 @@ if (err) return true; } - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - IntrusiveRefCntPtr Diags( - new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(), - DiagClient, /*ShouldOwnClient=*/false)); - if (outputDir.empty()) { origCI.getLangOpts()->ObjCAutoRefCount = true; - return migration.getRemapper().overwriteOriginal(*Diags); + return migration.getRemapper().overwriteOriginal(Diags); } else { - return migration.getRemapper().flushToDisk(outputDir, *Diags); + return migration.getRemapper().flushToDisk(outputDir, Diags); } } bool arcmt::applyTransformations( CompilerInvocation &origCI, const FrontendInputFile &Input, std::shared_ptr PCHContainerOps, - DiagnosticConsumer *DiagClient) { - return applyTransforms(origCI, Input, PCHContainerOps, DiagClient, - StringRef(), false, StringRef()); + DiagnosticsEngine &Diags) { + return applyTransforms(origCI, Input, PCHContainerOps, Diags, StringRef(), + false, StringRef()); } bool arcmt::migrateWithTemporaryFiles( CompilerInvocation &origCI, const FrontendInputFile &Input, std::shared_ptr PCHContainerOps, - DiagnosticConsumer *DiagClient, StringRef outputDir, + DiagnosticsEngine &Diags, StringRef outputDir, bool emitPremigrationARCErrors, StringRef plistOut) { assert(!outputDir.empty() && "Expected output directory path"); - return applyTransforms(origCI, Input, PCHContainerOps, DiagClient, outputDir, + return applyTransforms(origCI, Input, PCHContainerOps, Diags, outputDir, emitPremigrationARCErrors, plistOut); } -bool arcmt::getFileRemappings(std::vector > & - remap, - StringRef outputDir, - DiagnosticConsumer *DiagClient) { +bool arcmt::getFileRemappings( + std::vector> &remap, + StringRef outputDir, DiagnosticConsumer *DiagClient, + IntrusiveRefCntPtr DiagIDs) { assert(!outputDir.empty()); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); IntrusiveRefCntPtr Diags( - new DiagnosticsEngine(DiagID, new DiagnosticOptions, + new DiagnosticsEngine(std::move(DiagIDs), new DiagnosticOptions, DiagClient, /*ShouldOwnClient=*/false)); FileRemapper remapper; @@ -509,14 +502,13 @@ MigrationProcess::MigrationProcess( const CompilerInvocation &CI, std::shared_ptr PCHContainerOps, - DiagnosticConsumer *diagClient, StringRef outputDir) + DiagnosticsEngine &OriginalDiags, StringRef outputDir) : OrigCI(CI), PCHContainerOps(std::move(PCHContainerOps)), - DiagClient(diagClient), HadARCErrors(false) { + OriginalDiags(OriginalDiags), HadARCErrors(false) { if (!outputDir.empty()) { - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - IntrusiveRefCntPtr Diags( - new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), - DiagClient, /*ShouldOwnClient=*/false)); + IntrusiveRefCntPtr Diags(new DiagnosticsEngine( + OriginalDiags.getDiagnosticIDs(), &CI.getDiagnosticOpts(), + OriginalDiags.getClient(), /*ShouldOwnClient=*/false)); Remapper.initFromDisk(outputDir, *Diags, /*ignoreIfFilesChanges=*/true); } } @@ -524,8 +516,9 @@ bool MigrationProcess::applyTransform(TransformFn trans, RewriteListener *listener) { std::unique_ptr CInvok; - CInvok.reset( - createInvocationForMigration(OrigCI, PCHContainerOps->getRawReader())); + CInvok.reset(createInvocationForMigration(OriginalDiags.getDiagnosticIDs(), + OrigCI, + PCHContainerOps->getRawReader())); CInvok->getDiagnosticOpts().IgnoreWarnings = true; Remapper.applyMappings(CInvok->getPreprocessorOpts()); @@ -533,11 +526,11 @@ CapturedDiagList capturedDiags; std::vector ARCMTMacroLocs; - assert(DiagClient); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - IntrusiveRefCntPtr Diags( - new DiagnosticsEngine(DiagID, new DiagnosticOptions, - DiagClient, /*ShouldOwnClient=*/false)); + auto *DiagClient = OriginalDiags.getClient(); + assert(OriginalDiags.getClient()); + IntrusiveRefCntPtr Diags(new DiagnosticsEngine( + OriginalDiags.getDiagnosticIDs(), new DiagnosticOptions, DiagClient, + /*ShouldOwnClient=*/false)); // Filter of all diagnostics. CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags); Index: lib/ARCMigrate/ARCMTActions.cpp =================================================================== --- lib/ARCMigrate/ARCMTActions.cpp +++ lib/ARCMigrate/ARCMTActions.cpp @@ -17,7 +17,7 @@ bool CheckAction::BeginInvocation(CompilerInstance &CI) { if (arcmt::checkForManualIssues(CI.getInvocation(), getCurrentInput(), CI.getPCHContainerOperations(), - CI.getDiagnostics().getClient())) + CI.getDiagnostics())) return false; // errors, stop the action. // We only want to see warnings reported from arcmt::checkForManualIssues. @@ -31,7 +31,7 @@ bool ModifyAction::BeginInvocation(CompilerInstance &CI) { return !arcmt::applyTransformations(CI.getInvocation(), getCurrentInput(), CI.getPCHContainerOperations(), - CI.getDiagnostics().getClient()); + CI.getDiagnostics()); } ModifyAction::ModifyAction(std::unique_ptr WrappedAction) @@ -40,8 +40,7 @@ bool MigrateAction::BeginInvocation(CompilerInstance &CI) { if (arcmt::migrateWithTemporaryFiles( CI.getInvocation(), getCurrentInput(), CI.getPCHContainerOperations(), - CI.getDiagnostics().getClient(), MigrateDir, EmitPremigrationARCErros, - PlistOut)) + CI.getDiagnostics(), MigrateDir, EmitPremigrationARCErros, PlistOut)) return false; // errors, stop the action. // We only want to see diagnostics emitted by migrateWithTemporaryFiles. Index: lib/ARCMigrate/Internals.h =================================================================== --- lib/ARCMigrate/Internals.h +++ lib/ARCMigrate/Internals.h @@ -42,8 +42,9 @@ }; void writeARCDiagsToPlist(const std::string &outPath, - ArrayRef diags, - SourceManager &SM, const LangOptions &LangOpts); + ArrayRef diags, SourceManager &SM, + const LangOptions &LangOpts, + const DiagnosticIDs &DiagIDs); class TransformActions { DiagnosticsEngine &Diags; Index: lib/ARCMigrate/ObjCMT.cpp =================================================================== --- lib/ARCMigrate/ObjCMT.cpp +++ lib/ARCMigrate/ObjCMT.cpp @@ -2222,7 +2222,7 @@ FileManager FileMgr(FSOpts); RemapFileParser Parser(FileMgr); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID(new DiagnosticIDs(true)); IntrusiveRefCntPtr Diags( new DiagnosticsEngine(DiagID, new DiagnosticOptions, DiagClient, /*ShouldOwnClient=*/false)); Index: lib/ARCMigrate/PlistReporter.cpp =================================================================== --- lib/ARCMigrate/PlistReporter.cpp +++ lib/ARCMigrate/PlistReporter.cpp @@ -34,9 +34,8 @@ void arcmt::writeARCDiagsToPlist(const std::string &outPath, ArrayRef diags, - SourceManager &SM, - const LangOptions &LangOpts) { - DiagnosticIDs DiagIDs; + SourceManager &SM, const LangOptions &LangOpts, + const DiagnosticIDs &DiagIDs) { // Build up a set of FIDs that we use by scanning the locations and // ranges of the diagnostics. Index: lib/Basic/Diagnostic.cpp =================================================================== --- lib/Basic/Diagnostic.cpp +++ lib/Basic/Diagnostic.cpp @@ -364,7 +364,7 @@ SourceLocation Loc) { // Get all the diagnostics. SmallVector AllDiags; - DiagnosticIDs::getAllDiagnostics(Flavor, AllDiags); + Diags->getAllDiagnostics(Flavor, AllDiags); // Set the mapping. for (diag::kind Diag : AllDiags) Index: lib/Basic/DiagnosticIDs.cpp =================================================================== --- lib/Basic/DiagnosticIDs.cpp +++ lib/Basic/DiagnosticIDs.cpp @@ -25,83 +25,19 @@ // Builtin Diagnostic information //===----------------------------------------------------------------------===// -namespace { - -// Diagnostic classes. -enum { - CLASS_NOTE = 0x01, - CLASS_REMARK = 0x02, - CLASS_WARNING = 0x03, - CLASS_EXTENSION = 0x04, - CLASS_ERROR = 0x05 -}; - -struct StaticDiagInfoRec { - uint16_t DiagID; - unsigned DefaultSeverity : 3; - unsigned Class : 3; - unsigned SFINAE : 2; - unsigned WarnNoWerror : 1; - unsigned WarnShowInSystemHeader : 1; - unsigned Category : 6; - - uint16_t OptionGroupIndex; - - uint16_t DescriptionLen; - const char *DescriptionStr; - - unsigned getOptionGroupIndex() const { - return OptionGroupIndex; - } - - StringRef getDescription() const { - return StringRef(DescriptionStr, DescriptionLen); - } - - diag::Flavor getFlavor() const { - return Class == CLASS_REMARK ? diag::Flavor::Remark - : diag::Flavor::WarningOrError; - } - - bool operator<(const StaticDiagInfoRec &RHS) const { - return DiagID < RHS.DiagID; - } -}; - -#define STRINGIFY_NAME(NAME) #NAME -#define VALIDATE_DIAG_SIZE(NAME) \ - static_assert( \ - static_cast(diag::NUM_BUILTIN_##NAME##_DIAGNOSTICS) < \ - static_cast(diag::DIAG_START_##NAME) + \ - static_cast(diag::DIAG_SIZE_##NAME), \ - STRINGIFY_NAME( \ - DIAG_SIZE_##NAME) " is insufficient to contain all " \ - "diagnostics, it may need to be made larger in " \ - "DiagnosticIDs.h."); -VALIDATE_DIAG_SIZE(COMMON) -VALIDATE_DIAG_SIZE(DRIVER) -VALIDATE_DIAG_SIZE(FRONTEND) -VALIDATE_DIAG_SIZE(SERIALIZATION) -VALIDATE_DIAG_SIZE(LEX) -VALIDATE_DIAG_SIZE(PARSE) -VALIDATE_DIAG_SIZE(AST) -VALIDATE_DIAG_SIZE(COMMENT) -VALIDATE_DIAG_SIZE(SEMA) -VALIDATE_DIAG_SIZE(ANALYSIS) -VALIDATE_DIAG_SIZE(REFACTORING) -#undef VALIDATE_DIAG_SIZE -#undef STRINGIFY_NAME - -} // namespace anonymous - -static const StaticDiagInfoRec StaticDiagInfo[] = { +static const DiagnosticIDs::DiagInfoRec StaticDiagInfo[] = { #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ SHOWINSYSHEADER, CATEGORY) \ - { \ - diag::ENUM, DEFAULT_SEVERITY, CLASS, DiagnosticIDs::SFINAE, NOWERROR, \ - SHOWINSYSHEADER, CATEGORY, GROUP, STR_SIZE(DESC, uint16_t), DESC \ - } \ - , + {diag::ENUM, \ + DEFAULT_SEVERITY, \ + DiagnosticIDs::CLASS, \ + DiagnosticIDs::SFINAE, \ + NOWERROR, \ + SHOWINSYSHEADER, \ + CATEGORY, \ + GROUP, \ + STR_SIZE(DESC, uint16_t), \ + DESC}, #include "clang/Basic/DiagnosticCommonKinds.inc" #include "clang/Basic/DiagnosticDriverKinds.inc" #include "clang/Basic/DiagnosticFrontendKinds.inc" @@ -121,7 +57,7 @@ /// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID, /// or null if the ID is invalid. -static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) { +static const DiagnosticIDs::DiagInfoRec *GetDiagInfo(unsigned DiagID) { // Out of bounds diag. Can't be in the table. using namespace diag; if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON) @@ -161,7 +97,7 @@ assert(ID < StaticDiagInfoSize && Offset < StaticDiagInfoSize); - const StaticDiagInfoRec *Found = &StaticDiagInfo[ID + Offset]; + const auto *Found = &StaticDiagInfo[ID + Offset]; // If the diag id doesn't match we found a different diag, abort. This can // happen when this function is called with an ID that points into a hole in // the diagID space. @@ -174,7 +110,7 @@ DiagnosticMapping Info = DiagnosticMapping::Make( diag::Severity::Fatal, /*IsUser=*/false, /*IsPragma=*/false); - if (const StaticDiagInfoRec *StaticInfo = GetDiagInfo(DiagID)) { + if (const auto *StaticInfo = GetDiagInfo(DiagID)) { Info.setSeverity((diag::Severity)StaticInfo->DefaultSeverity); if (StaticInfo->WarnNoWerror) { @@ -189,8 +125,8 @@ /// getCategoryNumberForDiag - Return the category number that a specified /// DiagID belongs to, or 0 if no category. -unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) { - if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) +unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) const { + if (const auto *Info = ::GetDiagInfo(DiagID)) return Info->Category; return 0; } @@ -231,24 +167,22 @@ }; /// getNumberOfCategories - Return the number of categories -unsigned DiagnosticIDs::getNumberOfCategories() { +unsigned DiagnosticIDs::getNumberOfCategories() const { return llvm::array_lengthof(CategoryNameTable) - 1; } /// getCategoryNameFromID - Given a category ID, return the name of the /// category, an empty string if CategoryID is zero, or null if CategoryID is /// invalid. -StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) { +StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) const { if (CategoryID >= getNumberOfCategories()) return StringRef(); return CategoryNameTable[CategoryID].getName(); } - - DiagnosticIDs::SFINAEResponse -DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) { - if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) +DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) const { + if (const auto *Info = GetDiagInfo(DiagID)) return static_cast(Info->SFINAE); return SFINAE_Report; } @@ -256,7 +190,7 @@ /// getBuiltinDiagClass - Return the class field of the diagnostic. /// static unsigned getBuiltinDiagClass(unsigned DiagID) { - if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) + if (const auto *Info = GetDiagInfo(DiagID)) return Info->Class; return ~0U; } @@ -312,7 +246,8 @@ // Common Diagnostic implementation //===----------------------------------------------------------------------===// -DiagnosticIDs::DiagnosticIDs() { CustomDiagInfo = nullptr; } +DiagnosticIDs::DiagnosticIDs(bool) + : DiagInfo(StaticDiagInfo), GetDiagInfo(&::GetDiagInfo) {} DiagnosticIDs::~DiagnosticIDs() { delete CustomDiagInfo; @@ -335,14 +270,14 @@ /// level of the specified diagnostic ID is a Warning or Extension. /// This only works on builtin diagnostics, not custom ones, and is not legal to /// call on NOTEs. -bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) { +bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) const { return DiagID < diag::DIAG_UPPER_LIMIT && getBuiltinDiagClass(DiagID) != CLASS_ERROR; } /// \brief Determine whether the given built-in diagnostic ID is a /// Note. -bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) { +bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) const { return DiagID < diag::DIAG_UPPER_LIMIT && getBuiltinDiagClass(DiagID) == CLASS_NOTE; } @@ -353,7 +288,7 @@ /// which case -pedantic enables it) or treated as a warning/error by default. /// bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID, - bool &EnabledByDefault) { + bool &EnabledByDefault) const { if (DiagID >= diag::DIAG_UPPER_LIMIT || getBuiltinDiagClass(DiagID) != CLASS_EXTENSION) return false; @@ -363,7 +298,7 @@ return true; } -bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) { +bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) const { if (DiagID >= diag::DIAG_UPPER_LIMIT) return false; @@ -373,7 +308,7 @@ /// getDescription - Given a diagnostic ID, return a description of the /// issue. StringRef DiagnosticIDs::getDescription(unsigned DiagID) const { - if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) + if (const DiagInfoRec *Info = GetDiagInfo(DiagID)) return Info->getDescription(); assert(CustomDiagInfo && "Invalid CustomDiagInfo"); return CustomDiagInfo->getDescription(DiagID); @@ -520,13 +455,13 @@ /// getWarningOptionForDiag - Return the lowest-level warning option that /// enables the specified diagnostic. If there is no -Wfoo flag that controls /// the diagnostic, this returns null. -StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) { - if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) +StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) const { + if (const DiagInfoRec *Info = GetDiagInfo(DiagID)) return OptionTable[Info->getOptionGroupIndex()].getName(); return StringRef(); } -std::vector DiagnosticIDs::getDiagnosticFlags() { +std::vector DiagnosticIDs::getDiagnosticFlags() const { std::vector Res; for (size_t I = 1; DiagGroupNames[I] != '\0';) { std::string Diag(DiagGroupNames + I + 1, DiagGroupNames[I]); @@ -582,15 +517,15 @@ return ::getDiagnosticsInGroup(Flavor, Found, Diags); } -void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor, - SmallVectorImpl &Diags) { +void DiagnosticIDs::getAllDiagnostics( + diag::Flavor Flavor, SmallVectorImpl &Diags) const { for (unsigned i = 0; i != StaticDiagInfoSize; ++i) if (StaticDiagInfo[i].getFlavor() == Flavor) Diags.push_back(StaticDiagInfo[i].DiagID); } StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor, - StringRef Group) { + StringRef Group) const { StringRef Best; unsigned BestDistance = Group.size() + 1; // Sanity threshold. for (const WarningOption &O : OptionTable) { @@ -738,7 +673,7 @@ return true; } -bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) { +bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) const { unsigned cat = getCategoryNumberForDiag(DiagID); return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC "); } Index: lib/Basic/Warnings.cpp =================================================================== --- lib/Basic/Warnings.cpp +++ lib/Basic/Warnings.cpp @@ -35,7 +35,8 @@ static void EmitUnknownDiagWarning(DiagnosticsEngine &Diags, diag::Flavor Flavor, StringRef Prefix, StringRef Opt) { - StringRef Suggestion = DiagnosticIDs::getNearestOption(Flavor, Opt); + StringRef Suggestion = + Diags.getDiagnosticIDs()->getNearestOption(Flavor, Opt); Diags.Report(diag::warn_unknown_diag_option) << (Flavor == diag::Flavor::WarningOrError ? 0 : 1) << (Prefix.str() += Opt) << !Suggestion.empty() << (Prefix.str() += Suggestion); Index: lib/CrossTU/CrossTranslationUnit.cpp =================================================================== --- lib/CrossTU/CrossTranslationUnit.cpp +++ lib/CrossTU/CrossTranslationUnit.cpp @@ -147,16 +147,16 @@ } llvm::Expected -CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD, - StringRef CrossTUDir, - StringRef IndexName) { +CrossTranslationUnitContext::getCrossTUDefinition( + const FunctionDecl *FD, StringRef CrossTUDir, StringRef IndexName, + const IntrusiveRefCntPtr &DiagIDs) { assert(!FD->hasBody() && "FD has a definition in current translation unit!"); const std::string LookupFnName = getLookupName(FD); if (LookupFnName.empty()) return llvm::make_error( index_error_code::failed_to_generate_usr); llvm::Expected ASTUnitOrError = - loadExternalAST(LookupFnName, CrossTUDir, IndexName); + loadExternalAST(LookupFnName, CrossTUDir, IndexName, DiagIDs); if (!ASTUnitOrError) return ASTUnitOrError.takeError(); ASTUnit *Unit = *ASTUnitOrError; @@ -193,7 +193,8 @@ } llvm::Expected CrossTranslationUnitContext::loadExternalAST( - StringRef LookupName, StringRef CrossTUDir, StringRef IndexName) { + StringRef LookupName, StringRef CrossTUDir, StringRef IndexName, + const IntrusiveRefCntPtr &DiagIDs) { // FIXME: The current implementation only supports loading functions with // a lookup name from a single translation unit. If multiple // translation units contains functions with the same lookup name an @@ -223,10 +224,9 @@ if (ASTCacheEntry == FileASTUnitMap.end()) { IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); TextDiagnosticPrinter *DiagClient = - new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + new TextDiagnosticPrinter(llvm::errs(), DiagIDs, &*DiagOpts); IntrusiveRefCntPtr Diags( - new DiagnosticsEngine(DiagID, &*DiagOpts, DiagClient)); + new DiagnosticsEngine(DiagIDs, &*DiagOpts, DiagClient)); std::unique_ptr LoadedUnit(ASTUnit::LoadFromASTFile( ASTFileName, CI.getPCHContainerOperations()->getRawReader(), Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp +++ lib/Driver/Driver.cpp @@ -1148,11 +1148,11 @@ /// PrintDiagnosticCategories - Implement the --print-diagnostic-categories /// option. -static void PrintDiagnosticCategories(raw_ostream &OS) { +static void PrintDiagnosticCategories(const DiagnosticIDs &IDs, + raw_ostream &OS) { // Skip the empty category. - for (unsigned i = 1, max = DiagnosticIDs::getNumberOfCategories(); i != max; - ++i) - OS << i << ',' << DiagnosticIDs::getCategoryNameFromID(i) << '\n'; + for (unsigned i = 1, max = IDs.getNumberOfCategories(); i != max; ++i) + OS << i << ',' << IDs.getCategoryNameFromID(i) << '\n'; } void Driver::handleAutocompletions(StringRef PassedFlags) const { @@ -1180,7 +1180,7 @@ // We have to query the -W flags manually as they're not in the OptTable. // TODO: Find a good way to add them to OptTable instead and them remove // this code. - for (StringRef S : DiagnosticIDs::getDiagnosticFlags()) + for (StringRef S : Diags.getDiagnosticIDs()->getDiagnosticFlags()) if (S.startswith(PassedFlags)) SuggestedCompletions.push_back(S); } else { @@ -1228,7 +1228,7 @@ } if (C.getArgs().hasArg(options::OPT__print_diagnostic_categories)) { - PrintDiagnosticCategories(llvm::outs()); + PrintDiagnosticCategories(*Diags.getDiagnosticIDs(), llvm::outs()); return false; } Index: lib/Frontend/ChainedIncludesSource.cpp =================================================================== --- lib/Frontend/ChainedIncludesSource.cpp +++ lib/Frontend/ChainedIncludesSource.cpp @@ -139,9 +139,9 @@ FrontendInputFile InputFile(includes[i], IK); CInvok->getFrontendOpts().Inputs.push_back(InputFile); - TextDiagnosticPrinter *DiagClient = - new TextDiagnosticPrinter(llvm::errs(), new DiagnosticOptions()); IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter( + llvm::errs(), DiagID, new DiagnosticOptions()); IntrusiveRefCntPtr Diags( new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient)); Index: lib/Frontend/CompilerInstance.cpp =================================================================== --- lib/Frontend/CompilerInstance.cpp +++ lib/Frontend/CompilerInstance.cpp @@ -234,8 +234,8 @@ } // Chain in the diagnostic client which will log the diagnostics. - auto Logger = llvm::make_unique(*OS, DiagOpts, - std::move(StreamOwner)); + auto Logger = llvm::make_unique( + *OS, Diags.getDiagnosticIDs(), DiagOpts, std::move(StreamOwner)); if (CodeGenOpts) Logger->setDwarfDebugFlags(CodeGenOpts->DwarfDebugFlags); assert(Diags.ownsClient()); @@ -246,8 +246,8 @@ static void SetupSerializedDiagnostics(DiagnosticOptions *DiagOpts, DiagnosticsEngine &Diags, StringRef OutputFile) { - auto SerializedConsumer = - clang::serialized_diags::create(OutputFile, DiagOpts); + auto SerializedConsumer = clang::serialized_diags::create( + OutputFile, DiagOpts, Diags.getDiagnosticIDs()); if (Diags.ownsClient()) { Diags.setClient(new ChainedDiagnosticConsumer( @@ -278,7 +278,7 @@ if (Client) { Diags->setClient(Client, ShouldOwnClient); } else - Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts)); + Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), DiagID, Opts)); // Chain in -verify checker, if requested. if (Opts->VerifyDiagnostics) Index: lib/Frontend/LogDiagnosticPrinter.cpp =================================================================== --- lib/Frontend/LogDiagnosticPrinter.cpp +++ lib/Frontend/LogDiagnosticPrinter.cpp @@ -19,10 +19,10 @@ using namespace markup; LogDiagnosticPrinter::LogDiagnosticPrinter( - raw_ostream &os, DiagnosticOptions *diags, - std::unique_ptr StreamOwner) + raw_ostream &os, IntrusiveRefCntPtr DiagIDs, + DiagnosticOptions *diags, std::unique_ptr StreamOwner) : OS(os), StreamOwner(std::move(StreamOwner)), LangOpts(nullptr), - DiagOpts(diags) {} + DiagIDs(std::move(DiagIDs)), DiagOpts(diags) {} static StringRef getLevelName(DiagnosticsEngine::Level Level) { switch (Level) { @@ -130,7 +130,7 @@ DE.DiagnosticID = Info.getID(); DE.DiagnosticLevel = Level; - DE.WarningOption = DiagnosticIDs::getWarningOptionForDiag(DE.DiagnosticID); + DE.WarningOption = DiagIDs->getWarningOptionForDiag(DE.DiagnosticID); // Format the message. SmallString<100> MessageStr; Index: lib/Frontend/SerializedDiagnosticPrinter.cpp =================================================================== --- lib/Frontend/SerializedDiagnosticPrinter.cpp +++ lib/Frontend/SerializedDiagnosticPrinter.cpp @@ -141,10 +141,12 @@ State(std::move(State)) {} public: - SDiagsWriter(StringRef File, DiagnosticOptions *Diags, bool MergeChildRecords) + SDiagsWriter(StringRef File, DiagnosticOptions *Diags, + IntrusiveRefCntPtr DiagIDs, + bool MergeChildRecords) : LangOpts(nullptr), OriginalInstance(true), MergeChildRecords(MergeChildRecords), - State(std::make_shared(File, Diags)) { + State(std::make_shared(File, Diags, std::move(DiagIDs))) { if (MergeChildRecords) RemoveOldDiagnostics(); EmitPreamble(); @@ -240,12 +242,14 @@ /// \brief State that is shared among the various clones of this diagnostic /// consumer. struct SharedState { - SharedState(StringRef File, DiagnosticOptions *Diags) - : DiagOpts(Diags), Stream(Buffer), OutputFile(File.str()), - EmittedAnyDiagBlocks(false) {} + SharedState(StringRef File, DiagnosticOptions *Diags, + IntrusiveRefCntPtr DiagIDs) + : DiagOpts(Diags), DiagIDs(std::move(DiagIDs)), Stream(Buffer), + OutputFile(File.str()), EmittedAnyDiagBlocks(false) {} /// \brief Diagnostic options. IntrusiveRefCntPtr DiagOpts; + IntrusiveRefCntPtr DiagIDs; /// \brief The byte buffer for the serialized content. SmallString<1024> Buffer; @@ -294,8 +298,10 @@ namespace clang { namespace serialized_diags { std::unique_ptr -create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords) { - return llvm::make_unique(OutputFile, Diags, MergeChildRecords); +create(StringRef OutputFile, DiagnosticOptions *Diags, + IntrusiveRefCntPtr DiagIDs, bool MergeChildRecords) { + return llvm::make_unique(OutputFile, Diags, std::move(DiagIDs), + MergeChildRecords); } } // end namespace serialized_diags @@ -525,7 +531,7 @@ // We use a local version of 'Record' so that we can be generating // another record when we lazily generate one for the category entry. - StringRef catName = DiagnosticIDs::getCategoryNameFromID(category); + StringRef catName = State->DiagIDs->getCategoryNameFromID(category); RecordData::value_type Record[] = {RECORD_CATEGORY, category, catName.size()}; State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_CATEGORY), Record, catName); @@ -537,8 +543,8 @@ unsigned DiagID) { if (DiagLevel == DiagnosticsEngine::Note) return 0; // No flag for notes. - - StringRef FlagName = DiagnosticIDs::getWarningOptionForDiag(DiagID); + + StringRef FlagName = State->DiagIDs->getWarningOptionForDiag(DiagID); return getEmitDiagnosticFlag(FlagName); } @@ -639,7 +645,7 @@ if (const Diagnostic *Info = D.dyn_cast()) { // Emit the category string lazily and get the category ID. - unsigned DiagID = DiagnosticIDs::getCategoryNumberForDiag(Info->getID()); + unsigned DiagID = State->DiagIDs->getCategoryNumberForDiag(Info->getID()); Record.push_back(getEmitCategory(DiagID)); // Emit the diagnostic flag string lazily and get the mapped ID. Record.push_back(getEmitDiagnosticFlag(Level, Info->getID())); @@ -741,7 +747,7 @@ if (!State->MetaDiagnostics) { IntrusiveRefCntPtr IDs(new DiagnosticIDs()); auto Client = - new TextDiagnosticPrinter(llvm::errs(), State->DiagOpts.get()); + new TextDiagnosticPrinter(llvm::errs(), IDs, State->DiagOpts.get()); State->MetaDiagnostics = llvm::make_unique( IDs, State->DiagOpts.get(), Client); } Index: lib/Frontend/TextDiagnosticPrinter.cpp =================================================================== --- lib/Frontend/TextDiagnosticPrinter.cpp +++ lib/Frontend/TextDiagnosticPrinter.cpp @@ -22,12 +22,11 @@ #include using namespace clang; -TextDiagnosticPrinter::TextDiagnosticPrinter(raw_ostream &os, - DiagnosticOptions *diags, - bool _OwnsOutputStream) - : OS(os), DiagOpts(diags), - OwnsOutputStream(_OwnsOutputStream) { -} +TextDiagnosticPrinter::TextDiagnosticPrinter( + raw_ostream &os, IntrusiveRefCntPtr DiagIDs, + DiagnosticOptions *diags, bool _OwnsOutputStream) + : OS(os), DiagIDs(std::move(DiagIDs)), DiagOpts(diags), + OwnsOutputStream(_OwnsOutputStream) {} TextDiagnosticPrinter::~TextDiagnosticPrinter() { if (OwnsOutputStream) @@ -52,7 +51,8 @@ static void printDiagnosticOptions(raw_ostream &OS, DiagnosticsEngine::Level Level, const Diagnostic &Info, - const DiagnosticOptions &DiagOpts) { + const DiagnosticOptions &DiagOpts, + const DiagnosticIDs &DiagIDs) { bool Started = false; if (DiagOpts.ShowOptionNames) { // Handle special cases for non-warnings early. @@ -71,13 +71,13 @@ // flag it as such. Note that diagnostics could also have been mapped by a // pragma, but we don't currently have a way to distinguish this. if (Level == DiagnosticsEngine::Error && - DiagnosticIDs::isBuiltinWarningOrExtension(Info.getID()) && - !DiagnosticIDs::isDefaultMappingAsError(Info.getID())) { + DiagIDs.isBuiltinWarningOrExtension(Info.getID()) && + !DiagIDs.isDefaultMappingAsError(Info.getID())) { OS << " [-Werror"; Started = true; } - StringRef Opt = DiagnosticIDs::getWarningOptionForDiag(Info.getID()); + StringRef Opt = DiagIDs.getWarningOptionForDiag(Info.getID()); if (!Opt.empty()) { OS << (Started ? "," : " [") << (Level == DiagnosticsEngine::Remark ? "-R" : "-W") << Opt; @@ -90,8 +90,7 @@ // If the user wants to see category information, include it too. if (DiagOpts.ShowCategories) { - unsigned DiagCategory = - DiagnosticIDs::getCategoryNumberForDiag(Info.getID()); + unsigned DiagCategory = DiagIDs.getCategoryNumberForDiag(Info.getID()); if (DiagCategory) { OS << (Started ? "," : " ["); Started = true; @@ -99,7 +98,7 @@ OS << DiagCategory; else { assert(DiagOpts.ShowCategories == 2 && "Invalid ShowCategories value"); - OS << DiagnosticIDs::getCategoryNameFromID(DiagCategory); + OS << DiagIDs.getCategoryNameFromID(DiagCategory); } } } @@ -118,7 +117,7 @@ Info.FormatDiagnostic(OutStr); llvm::raw_svector_ostream DiagMessageStream(OutStr); - printDiagnosticOptions(DiagMessageStream, Level, Info, *DiagOpts); + printDiagnosticOptions(DiagMessageStream, Level, Info, *DiagOpts, *DiagIDs); // Keeps track of the starting position of the location // information (e.g., "foo.c:10:4:") that precedes the error Index: lib/Sema/Sema.cpp =================================================================== --- lib/Sema/Sema.cpp +++ lib/Sema/Sema.cpp @@ -1191,8 +1191,8 @@ // issue I am not seeing yet), then there should at least be a clarifying // comment somewhere. if (Optional Info = isSFINAEContext()) { - switch (DiagnosticIDs::getDiagnosticSFINAEResponse( - Diags.getCurrentDiagID())) { + switch (Diags.getDiagnosticIDs()->getDiagnosticSFINAEResponse( + Diags.getCurrentDiagID())) { case DiagnosticIDs::SFINAE_Report: // We'll report the diagnostic below. break; @@ -1275,7 +1275,7 @@ // that is different from the last template instantiation where // we emitted an error, print a template instantiation // backtrace. - if (!DiagnosticIDs::isBuiltinNote(DiagID)) + if (!Diags.getDiagnosticIDs()->isBuiltinNote(DiagID)) PrintContextStack(); } Index: lib/Tooling/CompilationDatabase.cpp =================================================================== --- lib/Tooling/CompilationDatabase.cpp +++ lib/Tooling/CompilationDatabase.cpp @@ -221,11 +221,11 @@ std::string &ErrorMsg) { IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); llvm::raw_string_ostream Output(ErrorMsg); - TextDiagnosticPrinter DiagnosticPrinter(Output, &*DiagOpts); + IntrusiveRefCntPtr DiagIDs(new DiagnosticIDs()); + TextDiagnosticPrinter DiagnosticPrinter(Output, DiagIDs, &*DiagOpts); UnusedInputDiagConsumer DiagClient(DiagnosticPrinter); - DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr(new DiagnosticIDs()), - &*DiagOpts, &DiagClient, false); + DiagnosticsEngine Diagnostics(std::move(DiagIDs), &*DiagOpts, &DiagClient, + false); // The clang executable path isn't required since the jobs the driver builds // will not be executed. Index: lib/Tooling/Refactoring.cpp =================================================================== --- lib/Tooling/Refactoring.cpp +++ lib/Tooling/Refactoring.cpp @@ -41,10 +41,10 @@ LangOptions DefaultLangOptions; IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); - TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), &*DiagOpts); - DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr(new DiagnosticIDs()), - &*DiagOpts, &DiagnosticPrinter, false); + IntrusiveRefCntPtr DiagIDs(new DiagnosticIDs()); + TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), DiagIDs, &*DiagOpts); + DiagnosticsEngine Diagnostics(std::move(DiagIDs), &*DiagOpts, + &DiagnosticPrinter, false); SourceManager Sources(Diagnostics, getFiles()); Rewriter Rewrite(Sources, DefaultLangOptions); Index: lib/Tooling/Tooling.cpp =================================================================== --- lib/Tooling/Tooling.cpp +++ lib/Tooling/Tooling.cpp @@ -251,10 +251,10 @@ llvm::opt::InputArgList ParsedArgs = Opts->ParseArgs( ArrayRef(Argv).slice(1), MissingArgIndex, MissingArgCount); ParseDiagnosticArgs(*DiagOpts, ParsedArgs); - TextDiagnosticPrinter DiagnosticPrinter( - llvm::errs(), &*DiagOpts); + IntrusiveRefCntPtr DiagIDs(new DiagnosticIDs()); + TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), DiagIDs, &*DiagOpts); DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr(new DiagnosticIDs()), &*DiagOpts, + std::move(DiagIDs), &*DiagOpts, DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false); const std::unique_ptr Driver( Index: tools/arcmt-test/arcmt-test.cpp =================================================================== --- tools/arcmt-test/arcmt-test.cpp +++ tools/arcmt-test/arcmt-test.cpp @@ -109,9 +109,9 @@ static bool checkForMigration(StringRef resourcesPath, ArrayRef Args) { IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); - DiagnosticConsumer *DiagClient = - new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + DiagnosticConsumer *DiagClient = + new TextDiagnosticPrinter(llvm::errs(), DiagID, &*DiagOpts); IntrusiveRefCntPtr Diags( new DiagnosticsEngine(DiagID, &*DiagOpts, DiagClient)); // Chain in -verify checker, if requested. @@ -135,7 +135,7 @@ arcmt::checkForManualIssues(CI, CI.getFrontendOpts().Inputs[0], std::make_shared(), - Diags->getClient()); + *Diags); return Diags->getClient()->getNumErrors() > 0; } @@ -154,9 +154,9 @@ return true; IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); - DiagnosticConsumer *DiagClient = - new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + DiagnosticConsumer *DiagClient = + new TextDiagnosticPrinter(llvm::errs(), DiagID, &*DiagOpts); IntrusiveRefCntPtr TopDiags( new DiagnosticsEngine(DiagID, &*DiagOpts, &*DiagClient)); @@ -174,7 +174,7 @@ return false; MigrationProcess migration(origCI, std::make_shared(), - DiagClient); + *TopDiags); std::vector transforms = arcmt::getAllTransformations(origCI.getLangOpts()->getGC(), Index: tools/clang-rename/ClangRename.cpp =================================================================== --- tools/clang-rename/ClangRename.cpp +++ tools/clang-rename/ClangRename.cpp @@ -213,10 +213,10 @@ // in the same order we see them. LangOptions DefaultLangOptions; IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); - TextDiagnosticPrinter DiagnosticPrinter(errs(), &*DiagOpts); - DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr(new DiagnosticIDs()), &*DiagOpts, - &DiagnosticPrinter, false); + IntrusiveRefCntPtr DiagIDs(new DiagnosticIDs()); + TextDiagnosticPrinter DiagnosticPrinter(errs(), DiagIDs, &*DiagOpts); + DiagnosticsEngine Diagnostics(std::move(DiagIDs), &*DiagOpts, + &DiagnosticPrinter, false); auto &FileMgr = Tool.getFiles(); SourceManager Sources(Diagnostics, FileMgr); Rewriter Rewrite(Sources, DefaultLangOptions); Index: tools/diagtool/ListWarnings.cpp =================================================================== --- tools/diagtool/ListWarnings.cpp +++ tools/diagtool/ListWarnings.cpp @@ -52,16 +52,18 @@ std::vector Flagged, Unflagged; llvm::StringMap > flagHistogram; + DiagnosticIDs IDs; + for (const DiagnosticRecord &DR : getBuiltinDiagnosticsByName()) { const unsigned diagID = DR.DiagID; - if (DiagnosticIDs::isBuiltinNote(diagID)) + if (IDs.isBuiltinNote(diagID)) continue; - if (!DiagnosticIDs::isBuiltinWarningOrExtension(diagID)) + if (!IDs.isBuiltinWarningOrExtension(diagID)) continue; - Entry entry(DR.getName(), DiagnosticIDs::getWarningOptionForDiag(diagID)); + Entry entry(DR.getName(), IDs.getWarningOptionForDiag(diagID)); if (entry.Flag.empty()) Unflagged.push_back(entry); Index: tools/diagtool/ShowEnabledWarnings.cpp =================================================================== --- tools/diagtool/ShowEnabledWarnings.cpp +++ tools/diagtool/ShowEnabledWarnings.cpp @@ -54,9 +54,8 @@ } static IntrusiveRefCntPtr -createDiagnostics(unsigned int argc, char **argv) { - IntrusiveRefCntPtr DiagIDs(new DiagnosticIDs()); - +createDiagnostics(unsigned int argc, char **argv, + IntrusiveRefCntPtr DiagIDs) { // Buffer diagnostics from argument parsing so that we can output them using a // well formed diagnostic object. TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; @@ -101,8 +100,11 @@ } } + IntrusiveRefCntPtr DiagIDs(new DiagnosticIDs()); + // Create the diagnostic engine. - IntrusiveRefCntPtr Diags = createDiagnostics(argc, argv); + IntrusiveRefCntPtr Diags = + createDiagnostics(argc, argv, DiagIDs); if (!Diags) { printUsage(); return EXIT_FAILURE; @@ -117,10 +119,10 @@ for (const DiagnosticRecord &DR : getBuiltinDiagnosticsByName()) { unsigned DiagID = DR.DiagID; - if (DiagnosticIDs::isBuiltinNote(DiagID)) + if (DiagIDs->isBuiltinNote(DiagID)) continue; - if (!DiagnosticIDs::isBuiltinWarningOrExtension(DiagID)) + if (!DiagIDs->isBuiltinWarningOrExtension(DiagID)) continue; DiagnosticsEngine::Level DiagLevel = @@ -128,7 +130,7 @@ if (DiagLevel == DiagnosticsEngine::Ignored) continue; - StringRef WarningOpt = DiagnosticIDs::getWarningOptionForDiag(DiagID); + StringRef WarningOpt = DiagIDs->getWarningOptionForDiag(DiagID); Active.push_back(PrettyDiag(DR.getName(), WarningOpt, DiagLevel)); } Index: tools/driver/cc1_main.cpp =================================================================== --- tools/driver/cc1_main.cpp +++ tools/driver/cc1_main.cpp @@ -13,7 +13,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Option/Arg.h" +#include "clang/Basic/AllDiagnostics.h" #include "clang/CodeGen/ObjectFilePCHContainerOperations.h" #include "clang/Config/config.h" #include "clang/Driver/DriverDiagnostic.h" @@ -27,6 +27,7 @@ #include "clang/FrontendTool/Utils.h" #include "llvm/ADT/Statistic.h" #include "llvm/LinkAllPasses.h" +#include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/OptTable.h" #include "llvm/Support/Compiler.h" @@ -167,11 +168,104 @@ static void ensureSufficientStack() {} #endif +static const DiagnosticIDs::DiagInfoRec StaticDiagInfo[] = { +#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ + SHOWINSYSHEADER, CATEGORY) \ + {diag::ENUM, \ + DEFAULT_SEVERITY, \ + DiagnosticIDs::CLASS, \ + DiagnosticIDs::SFINAE, \ + NOWERROR, \ + SHOWINSYSHEADER, \ + CATEGORY, \ + GROUP, \ + STR_SIZE(DESC, uint16_t), \ + DESC}, +#include "clang/Basic/DiagnosticCommonKinds.inc" + +#include "clang/Basic/DiagnosticDriverKinds.inc" + +#include "clang/Basic/DiagnosticFrontendKinds.inc" + +#include "clang/Basic/DiagnosticSerializationKinds.inc" + +#include "clang/Basic/DiagnosticLexKinds.inc" + +#include "clang/Basic/DiagnosticParseKinds.inc" + +#include "clang/Basic/DiagnosticASTKinds.inc" + +#include "clang/Basic/DiagnosticCommentKinds.inc" + +#include "clang/Basic/DiagnosticCrossTUKinds.inc" + +#include "clang/Basic/DiagnosticSemaKinds.inc" + +#include "clang/Basic/DiagnosticAnalysisKinds.inc" + +#include "clang/Basic/DiagnosticRefactoringKinds.inc" +#undef DIAG +}; + +/// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID, +/// or null if the ID is invalid. +static const DiagnosticIDs::DiagInfoRec *GetDiagInfo(unsigned DiagID) { + // Out of bounds diag. Can't be in the table. + using namespace diag; + if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON) + return nullptr; + + // Compute the index of the requested diagnostic in the static table. + // 1. Add the number of diagnostics in each category preceding the + // diagnostic and of the category the diagnostic is in. This gives us + // the offset of the category in the table. + // 2. Subtract the number of IDs in each category from our ID. This gives us + // the offset of the diagnostic in the category. + // This is cheaper than a binary search on the table as it doesn't touch + // memory at all. + unsigned Offset = 0; + unsigned ID = DiagID - DIAG_START_COMMON - 1; +#define CATEGORY(NAME, PREV) \ + if (DiagID > DIAG_START_##NAME) { \ + Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \ + ID -= DIAG_START_##NAME - DIAG_START_##PREV; \ + } + CATEGORY(DRIVER, COMMON) + CATEGORY(FRONTEND, DRIVER) + CATEGORY(SERIALIZATION, FRONTEND) + CATEGORY(LEX, SERIALIZATION) + CATEGORY(PARSE, LEX) + CATEGORY(AST, PARSE) + CATEGORY(COMMENT, AST) + CATEGORY(CROSSTU, COMMENT) + CATEGORY(SEMA, CROSSTU) + CATEGORY(ANALYSIS, SEMA) + CATEGORY(REFACTORING, ANALYSIS) +#undef CATEGORY + + auto DiagInfoArr = llvm::makeArrayRef(StaticDiagInfo); + + // Avoid out of bounds reads. + if (ID + Offset >= DiagInfoArr.size()) + return nullptr; + + assert(ID < DiagInfoArr.size() && Offset < DiagInfoArr.size()); + + const auto *Found = &DiagInfoArr[ID + Offset]; + // If the diag id doesn't match we found a different diag, abort. This can + // happen when this function is called with an ID that points into a hole in + // the diagID space. + if (Found->DiagID != DiagID) + return nullptr; + return Found; +} + int cc1_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { ensureSufficientStack(); std::unique_ptr Clang(new CompilerInstance()); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID = + new DiagnosticIDs(StaticDiagInfo, &GetDiagInfo); // Register the support for object-file-wrapped Clang modules. auto PCHOps = Clang->getPCHContainerOperations(); Index: tools/driver/cc1as_main.cpp =================================================================== --- tools/driver/cc1as_main.cpp +++ tools/driver/cc1as_main.cpp @@ -485,10 +485,10 @@ // Construct our diagnostic client. IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); - TextDiagnosticPrinter *DiagClient - = new TextDiagnosticPrinter(errs(), &*DiagOpts); - DiagClient->setPrefix("clang -cc1as"); IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + TextDiagnosticPrinter *DiagClient = + new TextDiagnosticPrinter(errs(), DiagID, &*DiagOpts); + DiagClient->setPrefix("clang -cc1as"); DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient); // Set an error handler, so that any LLVM backend diagnostics go through our Index: tools/driver/driver.cpp =================================================================== --- tools/driver/driver.cpp +++ tools/driver/driver.cpp @@ -435,18 +435,18 @@ IntrusiveRefCntPtr DiagOpts = CreateAndPopulateDiagOpts(argv); - TextDiagnosticPrinter *DiagClient - = new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); - FixupDiagPrefixExeName(DiagClient, Path); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + TextDiagnosticPrinter *DiagClient = + new TextDiagnosticPrinter(llvm::errs(), DiagID, &*DiagOpts); + FixupDiagPrefixExeName(DiagClient, Path); + DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient); if (!DiagOpts->DiagnosticSerializationFile.empty()) { - auto SerializedConsumer = - clang::serialized_diags::create(DiagOpts->DiagnosticSerializationFile, - &*DiagOpts, /*MergeChildRecords=*/true); + auto SerializedConsumer = clang::serialized_diags::create( + DiagOpts->DiagnosticSerializationFile, &*DiagOpts, DiagID, + /*MergeChildRecords=*/true); Diags.setClient(new ChainedDiagnosticConsumer( Diags.takeClient(), std::move(SerializedConsumer))); } Index: tools/libclang/ARCMigrate.cpp =================================================================== --- tools/libclang/ARCMigrate.cpp +++ tools/libclang/ARCMigrate.cpp @@ -56,9 +56,11 @@ } TextDiagnosticBuffer diagBuffer; + IntrusiveRefCntPtr DiagIDs = new DiagnosticIDs(true); std::unique_ptr remap(new Remap()); - bool err = arcmt::getFileRemappings(remap->Vec, migrate_dir_path,&diagBuffer); + bool err = arcmt::getFileRemappings(remap->Vec, migrate_dir_path, &diagBuffer, + DiagIDs); if (err) { if (Logging) { Index: tools/libclang/CIndex.cpp =================================================================== --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -91,8 +91,8 @@ DEnd = AU->stored_diag_end(); D != DEnd; ++D) { if (D->getLevel() >= DiagnosticsEngine::Error && - DiagnosticIDs::getCategoryNumberForDiag(D->getID()) == - diag::DiagCat_AST_Deserialization_Issue) + AU->getDiagnostics().getDiagnosticIDs()->getCategoryNumberForDiag( + D->getID()) == diag::DiagCat_AST_Deserialization_Issue) return true; } return false; Index: tools/libclang/CIndexDiagnostic.cpp =================================================================== --- tools/libclang/CIndexDiagnostic.cpp +++ tools/libclang/CIndexDiagnostic.cpp @@ -402,7 +402,7 @@ CXString clang_getDiagnosticCategoryName(unsigned Category) { // Kept for backward compatibility. - return cxstring::createRef(DiagnosticIDs::getCategoryNameFromID(Category)); + return cxstring::createRef(DiagnosticIDs().getCategoryNameFromID(Category)); } CXString clang_getDiagnosticCategoryText(CXDiagnostic Diag) { Index: tools/libclang/CXStoredDiagnostic.cpp =================================================================== --- tools/libclang/CXStoredDiagnostic.cpp +++ tools/libclang/CXStoredDiagnostic.cpp @@ -52,7 +52,7 @@ CXString CXStoredDiagnostic::getDiagnosticOption(CXString *Disable) const { unsigned ID = Diag.getID(); - StringRef Option = DiagnosticIDs::getWarningOptionForDiag(ID); + StringRef Option = DiagnosticIDs().getWarningOptionForDiag(ID); if (!Option.empty()) { if (Disable) *Disable = cxstring::createDup((Twine("-Wno-") + Option).str()); @@ -69,12 +69,13 @@ } unsigned CXStoredDiagnostic::getCategory() const { - return DiagnosticIDs::getCategoryNumberForDiag(Diag.getID()); + return DiagnosticIDs().getCategoryNumberForDiag(Diag.getID()); } CXString CXStoredDiagnostic::getCategoryText() const { - unsigned catID = DiagnosticIDs::getCategoryNumberForDiag(Diag.getID()); - return cxstring::createRef(DiagnosticIDs::getCategoryNameFromID(catID)); + DiagnosticIDs IDs; + unsigned catID = IDs.getCategoryNumberForDiag(Diag.getID()); + return cxstring::createRef(IDs.getCategoryNameFromID(catID)); } unsigned CXStoredDiagnostic::getNumRanges() const { Index: unittests/CrossTU/CrossTranslationUnitTest.cpp =================================================================== --- unittests/CrossTU/CrossTranslationUnitTest.cpp +++ unittests/CrossTU/CrossTranslationUnitTest.cpp @@ -73,7 +73,9 @@ // Load the definition from the AST file. llvm::Expected NewFDorError = - CTU.getCrossTUDefinition(FD, "", IndexFileName); + CTU.getCrossTUDefinition( + FD, "", IndexFileName, + CTU.getCompilerInstance().getDiagnostics().getDiagnosticIDs()); EXPECT_TRUE((bool)NewFDorError); const FunctionDecl *NewFD = *NewFDorError; Index: unittests/Tooling/RewriterTestContext.h =================================================================== --- unittests/Tooling/RewriterTestContext.h +++ unittests/Tooling/RewriterTestContext.h @@ -38,16 +38,17 @@ : DiagOpts(new DiagnosticOptions()), Diagnostics(IntrusiveRefCntPtr(new DiagnosticIDs), &*DiagOpts), - DiagnosticPrinter(llvm::outs(), &*DiagOpts), + DiagnosticPrinter(llvm::outs(), Diagnostics.getDiagnosticIDs(), + &*DiagOpts), InMemoryFileSystem(new vfs::InMemoryFileSystem), OverlayFileSystem( new vfs::OverlayFileSystem(vfs::getRealFileSystem())), Files(FileSystemOptions(), OverlayFileSystem), Sources(Diagnostics, Files), Rewrite(Sources, Options) { - Diagnostics.setClient(&DiagnosticPrinter, false); - // FIXME: To make these tests truly in-memory, we need to overlay the - // builtin headers. - OverlayFileSystem->pushOverlay(InMemoryFileSystem); + Diagnostics.setClient(&DiagnosticPrinter, false); + // FIXME: To make these tests truly in-memory, we need to overlay the + // builtin headers. + OverlayFileSystem->pushOverlay(InMemoryFileSystem); } ~RewriterTestContext() {}